mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-01 14:58:14 +00:00
I deduced that this was the case, and attempted implementing this path long ago, but I could never quite get it to work in all games. Set Claude on a quest to research and implement it, and lo and behold, it works. A bit sobering. Fixes #12888 and likely more. Additionally, audio latency is likely slightly improved overall, and memory usage is down by 4.6MB. Claude says: The blocking output calls are not a queue that callers line up behind. Each mixer channel holds exactly one buffer and at most one parked thread; a second thread arriving while the first is waiting is told the channel is busy and is expected to skip its turn. The Output2/SRC channel holds two DMA descriptors and refuses a third caller outright, without waiting at all. We blocked everyone instead, so a game running a movie thread and a sound-effect thread over one output made the two alternate - a frame of movie audio, a frame of effects silence - and the movie played at half rate. That is #12888, seen in F1 2009 and Colin McRae: DiRT 2. With this, the movie thread keeps the channel for the whole cutscene and the effects thread is refused, which is what the hardware trace shows. The driver also never copies a buffer on the way in: it stores the pointer and its mixer walks it forward 64 samples at a time out of the game's own memory. Modelling that fixes #20095 as a side effect, and drops the 4.6MB of per-channel sample rings we were carrying. The mix event is re-phased to the moment a DMA starts, since the mixer thread outranks its caller and gets a block in before the output call returns. Along the way: the two rest-length calls differ after a null-pointer output, sceAudioChRelease reports not-reserved rather than not-init, sceAudioChangeChannelConfig validates the format, sceAudioChangeChannelVolume validates nothing, and sceAudioOutput2ChangeLength takes a range of 17..4111. Details in docs/sceAudio.md. Savestates: AudioChannel goes to version 4. Older ones stored mixed samples that can't become a pointer and a position again, so they load with the pending audio dropped and any parked threads released. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>