IOP, DMA: Silence VAG audio on first chunk upload (#4048)

Fixes https://github.com/open-goal/jak-project/issues/2635 by zeroing
out the volume of the VAG command on the first chunk upload. This isn't
a "true" fix because I'm only addressing the symptom instead of the
actual problem.

But this did allow me to complete Mountain Temple without a single chirp
of static from the `mtn-step-plat-rocks` explosion sounds. They were
completely silent until I hit their buttons. All other sounds in the
game, to my untrained ears, sounded unaffected.

As an additional concern, I clear the IOP threads' `waitType` whenever
their `state` is set to Ready. This didn't seem to affect the sound bug,
but it seemed to be "the right thing to do." Will happily remove this
from the PR if it's deemed unnecessary, extraneous, or ought to be
addressed separately.
This commit is contained in:
massimilianodelliubaldini
2025-12-29 20:35:44 -05:00
committed by GitHub
parent 60cf8f7b46
commit 40b088a02f
2 changed files with 14 additions and 1 deletions
+11 -1
View File
@@ -97,7 +97,7 @@ int SpuDmaIntr(int, void*) {
// if we just finished the first upload, start playing! I'm not entirely sure if this is playing
// sound yet, or if we're just looping and waiting for the second upload to actually start.
// (we don't set the appropriate volumes here, so this is probably not the real playback)
// (this is probably not the real playback)
if (DmaVagCmd->num_processed_chunks == 1) {
int pitch = CalculateVAGPitch(DmaVagCmd->pitch1, DmaVagCmd->unk_256_pitch2);
if (!DmaStereoVagCmd) {
@@ -107,6 +107,10 @@ int SpuDmaIntr(int, void*) {
sceSdSetParam(SD_VP_ADSR2 | DmaVagCmd->voice, 0x1fc0);
sceSdSetParam(SD_VP_PITCH | DmaVagCmd->voice, pitch);
// setting volume to 0 on first chunk to avoid unpleasant initial chirps of audio.
sceSdSetParam(SD_VP_VOLL | DmaVagCmd->voice, 0x0);
sceSdSetParam(SD_VP_VOLR | DmaVagCmd->voice, 0x0);
sceSdSetSwitch(SD_S_KON | (DmaVagCmd->voice & 1), VOICE_BIT(DmaVagCmd->voice));
} else {
// same for stereo, but we start both voices.
@@ -123,6 +127,12 @@ int SpuDmaIntr(int, void*) {
sceSdSetParam(SD_VP_PITCH | DmaVagCmd->voice, pitch);
sceSdSetParam(SD_VP_PITCH | DmaStereoVagCmd->voice, pitch);
// setting volume to 0 on first chunk to avoid unpleasant initial chirps of audio.
sceSdSetParam(SD_VP_VOLL | DmaVagCmd->voice, 0x0);
sceSdSetParam(SD_VP_VOLL | DmaStereoVagCmd->voice, 0x0);
sceSdSetParam(SD_VP_VOLR | DmaVagCmd->voice, 0x0);
sceSdSetParam(SD_VP_VOLR | DmaStereoVagCmd->voice, 0x0);
sceSdSetSwitch(SD_S_KON | (DmaVagCmd->voice & 1),
VOICE_BIT(DmaVagCmd->voice) | VOICE_BIT(DmaStereoVagCmd->voice));
}
+3
View File
@@ -72,6 +72,7 @@ s32 IOP_Kernel::CreateThread(std::string name, void (*func)(), u32 priority) {
* Start a thread. Marking it to run on each dispatch of the IOP kernel.
*/
void IOP_Kernel::StartThread(s32 id) {
threads.at(id).waitType = IopThread::Wait::None;
threads.at(id).state = IopThread::State::Ready;
}
@@ -114,6 +115,7 @@ void IOP_Kernel::SleepThread() {
void IOP_Kernel::YieldThread() {
ASSERT(_currentThread);
_currentThread->waitType = IopThread::Wait::None;
_currentThread->state = IopThread::State::Ready;
leaveThread();
}
@@ -130,6 +132,7 @@ void IOP_Kernel::WakeupThread(s32 id) {
return;
}
threads.at(id).waitType = IopThread::Wait::None;
threads.at(id).state = IopThread::State::Ready;
}