Tags: ebitengine/oto
Tags
internal/oboe: fix a compile error with NDK 30 Oboe 1.10.0 guards the AAudio types it defines for itself with __NDK_MAJOR__ <= 30, but NDK 30 declares all of them, so AAudio_FallbackMode, AAudio_StretchMode and AAudioPlaybackParameters are redefined. AAudioStream_partialDataCallback is declared there as well and is redefined too, without an error: it is a typedef, and redeclaring one with the same type is allowed. Guard the whole block with < 30. AAudio_DeviceType is now an enum with an explicit underlying type rather than a typedef of int32_t, so ASSERT_INT32 no longer holds. Drop it. The static_asserts next to it cast to int32_t explicitly, and the remaining uses of the type are static_casts, which an enum satisfies. The oboe_* files are generator output, so make the changes in gen.go while copying instead. A replacement that no longer matches is an error, so bumping oboeVersion to a release that carries the upstream fix reports the stale replacement rather than quietly doing nothing. Verified with NDK 30.0.15729638-beta2 and 28.2.13676358, for android/arm64 and android/arm. Closes #287 Co-Authored-By: Claude Opus 5 <[email protected]>
internal/oboe: fix a compile error with NDK 30 Oboe 1.10.0 guards the AAudio types it defines for itself with __NDK_MAJOR__ <= 30, but NDK 30 declares all of them, so AAudio_FallbackMode, AAudio_StretchMode and AAudioPlaybackParameters are redefined. AAudioStream_partialDataCallback is declared there as well and is redefined too, without an error: it is a typedef, and redeclaring one with the same type is allowed. Guard the whole block with < 30. AAudio_DeviceType is now an enum with an explicit underlying type rather than a typedef of int32_t, so ASSERT_INT32 no longer holds. Drop it. The static_asserts next to it cast to int32_t explicitly, and the remaining uses of the type are static_casts, which an enum satisfies. The oboe_* files are generator output, so make the changes in gen.go while copying instead. A replacement that no longer matches is an error, so bumping oboeVersion to a release that carries the upstream fix reports the stale replacement rather than quietly doing nothing. Verified with NDK 30.0.15729638-beta2 and 28.2.13676358, for android/arm64 and android/arm. Closes #287 Co-Authored-By: Claude Opus 5 <[email protected]>
internal/oboe: fall back to OpenSL ES when AAudio fails An Android user reported 'oboe: Play failed: ErrorIllegalArgument', which Ebitengine surfaces as a fatal game error. ErrorIllegalArgument is AAUDIO_ERROR_ILLEGAL_ARGUMENT, a result no OpenSL ES path in Oboe returns, so it became reachable only when AAudio was enabled: the same device played through OpenSL ES before that. The configuration is unremarkable, an output stream that is low latency, shared, float, two channels, the requested sample rate and a data callback, with no buffer capacity requested. google/oboe#1293 reports the same result from openStream for an equally plain configuration on 11 device models, which the vendor could not reproduce and which was closed without a fix. A device that refuses what every other device plays is a platform bug that no argument here avoids, and treating it as a configuration error left the process with no audio at all. Fall back to OpenSL ES when starting fails for a reason that would not pass, and keep it for the rest of the process. It is the API this backend used on every device until AAudio, so it is what is left worth attempting before playing is given up on. The result does not say whether opening or starting failed, so the fallback covers both, and it covers the sharing mode check, which ended playing the same way. Below Android R the API is already OpenSL ES, so nothing changes there. Only a failure of both APIs is reported now. Updates #284 Co-Authored-By: Claude Opus 5 <[email protected]>
oto: bound and back off WASAPI device-recovery retries restart() previously retried transient device errors (device invalidated, resources invalidated, device switched, RPC disconnected) without limit, attempting a full COM device re-acquisition every buffer period. A device that never returned would spin forever, and a longer outage hammered the audio service with back-to-back re-acquisitions. Cap the re-acquisition attempts and back off the interval between them. The mux is still drained at real time on its own cadence, decoupled from the re-acquire interval, so recovery resumes near the current position instead of replaying a backlog. Retrying is paused while suspended and the attempt count resets on resume. Updates #281 Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
oto: run Suspend/Resume off the calling thread on darwin Suspend and Resume held c.cond.L to flip the toPause/toResume flags. On iOS the audio render goroutine can hold c.cond.L for several seconds while resume() retries transient AVAudioSession errors (e.g. AVAudioSessionErrorCodeCannotStartPlaying), which meant the platform UI thread could block in applicationWillResignActive / applicationDidBecome Active for the duration of those retries. Spawn a small goroutine to perform the cond.L acquisition and flag flip so the caller returns immediately. The underlying audio loop, retry policy, and error semantics are unchanged; errors from the asynchronous transition still surface via Err on the next poll. Updates #93
oto: recover from kAudioQueueErr_QueueInvalidated on iOS When mediaserverd resets (e.g. AVAudioSession media services were reset), the AudioQueue is invalidated and AudioQueueStart / AudioQueueEnqueueBuffer / AudioQueuePause start returning kAudioQueueErr_QueueInvalidated (-66671). Plain retry on the same handle never recovers because the queue object itself is dead. Recover by disposing the dead queue and rebuilding a fresh one with new buffers. The render callback now also filters by inAQ to drop any late callbacks delivered for a just-disposed queue. Updates #278
oto: set default PulseAudio latency to 100ms Without an explicit latency, PulseAudio uses its own large default buffer (~2s), which causes a noticeable delay before audio starts playing. Updates hajimehoshi/ebiten#3434 Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
oto: add non-cgo linux pulseaudio driver (#277) Add pulseaudio support on linux via github.com/jfreymuth/pulse that does not require CGO to build. Makes it the default linux audio option, falling back to the ALSA implementation if CGO is enabled. Written entirely with Copilot, plus some manual human testing via the example app. Closes #154
PreviousNext