Replaces the ansnd-based backend (a third-party library with a custom
DSP ucode Dolphin's HLE audio emulation doesn't recognize, requiring
-a LLE as a workaround) with libogc's own asndlib - the standard,
HLE-supported audio API most GC/Wii homebrew already uses.
Also fixes three real bugs found while getting a large (41MB) WAV
asset actually playing on Dolphin:
- audiostreamdolphin.c previously buffered a stream's entire loop
segment into one allocation up front (inherited from the ansnd
design) - fine for a short test tone, but an out-of-memory crash for
a real multi-minute track on GameCube's 24MB (or even Wii's 88MB)
total RAM. Rewritten to stream bounded windows via ASND's real
double-buffer primitives (ASND_SetVoice + ASND_AddVoice, polled from
the main thread - never from an interrupt callback), matching how
Linux/PSP already work.
- ASND_TestVoiceBufferReady() returns SND_OK (0) when ready and
SND_BUSY (1) when not, in the actual toolchain fork
(extremscorner/libogc2) this project builds against - opposite of a
plain boolean. Treating the raw result as one meant a genuinely
ready voice's SND_OK read as false, silently skipping every
ASND_AddVoice() call forever after a stream's first buffered window.
- audioStreamPcmRead()'s 16-bit fast path read WAV's little-endian
sample bytes straight into the output buffer with no byte-swap -
correct by coincidence on every little-endian platform this engine
targets (Linux, PSP), but reversed every sample's bytes on
Dolphin/GameCube/Wii's big-endian PowerPC.
libmad is GPL-licensed (see audiostreammp3decodersw.h's own note from
the prior MP3 change); libogc's asndlib is under a permissive
BSD-style license, so this doesn't add another such dependency.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
minimp3's sliding-window frame confirmation could spuriously discard real
frames near the tail of a not-yet-full window, losing ~5.5% of a real
VBR file's content even at a tuned 256KB window (~0.3% residual) -
audible as the whole track finishing early with stutters at each drop.
libmad's mad_stream/mad_frame/mad_synth API reports "need more data"
(MAD_ERROR_BUFLEN) and "genuinely bad data" separately rather than
overloading one return value, which was the actual ambiguity minimp3
couldn't resolve. Verified against the same real file with a 32KB window
(vs minimp3's 256KB): frame count and duration match the Xing header
exactly. Confirmed building for Linux, GameCube, and Wii (the latter two
via the project's real devkitPPC/libogc Docker toolchain) - libmad ships
inside libogc itself on Dolphin, no separate fetch needed there.
libmad is GPL-licensed, unlike the rest of this MIT project - a
deliberate tradeoff, noted at each site that pulls it in.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Allocates an ansnd voice per stream and configures/starts it in
single-buffer mode (no continuous re-feed needed yet, matching the
PSP/Linux single-shot approach). Real linear panning from
directionality via left/right voice volume. ansnd has no polling API
for voice state, so finish detection uses a voice_callback (fired
from ansnd's own audio DMA interrupt, not the main thread) that sets
a flag audioStreamDolphinIsFinished() reads.
Links libansnd (new for this project) and wires duskdolphin/audio
into the CMake build for the first time.
Verified via the dusk-dolphin toolchain: both GameCube and Wii
targets compile and link cleanly. Runtime verification in headless
Dolphin was inconclusive - confirmed via an A/B test against a
pre-audio baseline build that a pre-existing MMIO flood (unrelated
to this change, reproduces identically with zero audio code present)
keeps the harness from reaching the game's own steady state before
timing out.