Cache PSP volume/pan computation, mix channel + master volume into mixer playback, wire boa.mp3 as looping BGM
- PSP output thread now caches the last computed leftVolume/rightVolume and only recomputes them when stream->volume/directionality actually changed since the previous chunk, instead of recomputing every ~23ms chunk unconditionally. - Mixer channels and the mixer itself now carry their own volume (audioMixerSetChannelVolume()/audioMixerSetMasterVolume()), multiplied with each sound's own volume every audioMixerUpdateEarly() and applied via audioStreamSetVolume() - so changing a channel's or the master volume affects whatever's already playing, not just future sounds. Also fixed audioMixerUpdateEarly() to tolerate a PLAY command queued outside the normal per-frame cycle (no loadingAsset yet from a preceding audioMixerUpdateLate(), e.g. during engine startup) by leaving it queued for the following frame instead of asserting. - engine.c now plays boa.mp3 on AUDIO_MIXER_CHANNEL_BGM_0 on loop through the mixer instead of driving a raw audiostream_t directly, exercising the new mixer pipeline end to end. Built and verified on Linux, PSP (Docker) and GameCube (Docker). Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
@@ -73,6 +73,7 @@ errorret_t audioStreamPSPInit(audiostream_t *stream) {
|
||||
stream->platform.channel = channel;
|
||||
stream->platform.finished = false;
|
||||
stream->platform.playRequested = false;
|
||||
stream->platform.hasLastVolume = false;
|
||||
|
||||
const size_t ringSize =
|
||||
AUDIO_PSP_RING_FRAMES * stream->channels * sizeof(int16_t);
|
||||
@@ -381,17 +382,33 @@ void audioStreamPSPThreadFeed(thread_t *thread) {
|
||||
}
|
||||
}
|
||||
|
||||
// Re-read every chunk (~23ms at 44100Hz) so SetVolume/SetDirectionality
|
||||
// take effect mid-playback, unlike the platform's other one-shot calls.
|
||||
float_t leftFactor, rightFactor;
|
||||
audioStreamGetPanFactors(stream, &leftFactor, &rightFactor);
|
||||
// Checked every chunk (~23ms at 44100Hz) so SetVolume/SetDirectionality
|
||||
// take effect mid-playback, unlike the platform's other one-shot
|
||||
// calls - but only actually recomputed when one of them has changed
|
||||
// since the last chunk (see lastVolume's own comment); otherwise the
|
||||
// previous chunk's already-computed leftVolume/rightVolume are reused
|
||||
// as-is.
|
||||
if(
|
||||
!stream->platform.hasLastVolume ||
|
||||
stream->platform.lastVolume != stream->volume ||
|
||||
stream->platform.lastDirectionality != stream->directionality
|
||||
) {
|
||||
float_t leftFactor, rightFactor;
|
||||
audioStreamGetPanFactors(stream, &leftFactor, &rightFactor);
|
||||
|
||||
const int baseVolume = (int) (stream->volume * PSP_AUDIO_VOLUME_MAX);
|
||||
const int leftVolume = (int) (baseVolume * leftFactor);
|
||||
const int rightVolume = (int) (baseVolume * rightFactor);
|
||||
const int baseVolume = (int) (stream->volume * PSP_AUDIO_VOLUME_MAX);
|
||||
stream->platform.lastLeftVolume = (int) (baseVolume * leftFactor);
|
||||
stream->platform.lastRightVolume = (int) (baseVolume * rightFactor);
|
||||
stream->platform.lastVolume = stream->volume;
|
||||
stream->platform.lastDirectionality = stream->directionality;
|
||||
stream->platform.hasLastVolume = true;
|
||||
}
|
||||
|
||||
sceAudioOutputPannedBlocking(
|
||||
stream->platform.channel, leftVolume, rightVolume, chunk
|
||||
stream->platform.channel,
|
||||
stream->platform.lastLeftVolume,
|
||||
stream->platform.lastRightVolume,
|
||||
chunk
|
||||
);
|
||||
|
||||
stream->platform.framesOutput += framesThisChunk;
|
||||
|
||||
Reference in New Issue
Block a user