Skip to content

Tags: ebitengine/oto

Tags

v3.5.0-alpha.10

Toggle v3.5.0-alpha.10's commit message
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]>

v3.4.1

Toggle v3.4.1's commit message
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]>

v3.5.0-alpha.9

Toggle v3.5.0-alpha.9's commit message
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]>

v3.5.0-alpha.8

Toggle v3.5.0-alpha.8's commit message
all: update PureGo

v3.5.0-alpha.7

Toggle v3.5.0-alpha.7's commit message
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]>

v3.5.0-alpha.6

Toggle v3.5.0-alpha.6's commit message
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

v3.5.0-alpha.5

Toggle v3.5.0-alpha.5's commit message
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

v3.5.0-alpha.4

Toggle v3.5.0-alpha.4's commit message
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]>

v3.5.0-alpha.3

Toggle v3.5.0-alpha.3's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
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

v3.5.0-alpha.2

Toggle v3.5.0-alpha.2's commit message
all: update dependencies