From c238f8a493aebaf2c42b7af98819e41c04f7e8df Mon Sep 17 00:00:00 2001 From: Sonic Dreamcaster Date: Mon, 11 Nov 2024 03:53:15 -0300 Subject: [PATCH] audio docs from the decomp --- include/sf64audio_provisional.h | 4 +- linker_scripts/us/rev1/symbol_addrs_audio.txt | 32 +- src/audio/audio_general.c | 2 +- src/audio/audio_synthesis.c | 552 ++++++++++-------- src/audio/audio_thread.c | 21 +- 5 files changed, 318 insertions(+), 293 deletions(-) diff --git a/include/sf64audio_provisional.h b/include/sf64audio_provisional.h index 9154f6f7..9f766f8b 100644 --- a/include/sf64audio_provisional.h +++ b/include/sf64audio_provisional.h @@ -1029,8 +1029,8 @@ typedef struct { #define SEQ_BYTE2(seqId) (((seqId) & (0xFF << 16)) >> 13 & 0xFFFF) // audio_synthesis -void func_80008780(f32*, s32, f32*); -Acmd* func_80009B64(Acmd* aList, s32* cmdCount, s16* aiBufStart, s32 aiBufLen); +void AudioSynth_HartleyTransform(f32*, s32, f32*); +Acmd* AudioSynth_Update(Acmd* aList, s32* cmdCount, s16* aiBufStart, s32 aiBufLen); // audio_effects void Audio_SequencePlayerProcessSound(SequencePlayer* seqplayer); diff --git a/linker_scripts/us/rev1/symbol_addrs_audio.txt b/linker_scripts/us/rev1/symbol_addrs_audio.txt index aa782727..6867f783 100644 --- a/linker_scripts/us/rev1/symbol_addrs_audio.txt +++ b/linker_scripts/us/rev1/symbol_addrs_audio.txt @@ -222,26 +222,26 @@ sAudioResetMsg = 0x8015661C; // functions -func_800080C0 = 0x800080C0; -func_80008364 = 0x80008364; -func_80008780 = 0x80008780; +AudioSynth_InitNextRingBuf = 0x800080C0; +AudioSynth_InverseDiscreteCosineTransform = 0x80008364; +AudioSynth_HartleyTransform = 0x80008780; func_80009124 = 0x80009124; func_80009504 = 0x80009504; func_8000967C = 0x8000967C; func_800097A8 = 0x800097A8; -func_800098DC = 0x800098DC; -func_80009984 = 0x80009984; -func_80009A2C = 0x80009A2C; -func_80009AAC = 0x80009AAC; -func_80009B64 = 0x80009B64; -func_80009D78 = 0x80009D78; -func_8000A128 = 0x8000A128; -func_8000A25C = 0x8000A25C; -func_8000A700 = 0x8000A700; -func_8000B3F0 = 0x8000B3F0; -func_8000B480 = 0x8000B480; -func_8000B51C = 0x8000B51C; -func_8000B98C = 0x8000B98C; +AudioSynth_LoadRingBufferPart = 0x800098DC; +AudioSynth_SaveRingBufferPart = 0x80009984; +AudioSynth_DisableSampleStates = 0x80009A2C; +AudioSynth_SyncSampleStates = 0x80009AAC; +AudioSynth_Update = 0x80009B64; +AudioSynth_LoadReverbSamples = 0x80009D78; +AudioSynth_SaveReverbSamples = 0x8000A128; +AudioSynth_DoOneAudioUpdate = 0x8000A25C; +AudioSynth_ProcessNote = 0x8000A700; +AudioSynth_LoadWaveSamples = 0x8000B3F0; +AudioSynth_FinalResample = 0x8000B480; +AudioSynth_ProcessEnvelope = 0x8000B51C; +AudioSynth_ApplyHaasEffect = 0x8000B98C; diff --git a/src/audio/audio_general.c b/src/audio/audio_general.c index 3f91fa5e..43bd0958 100644 --- a/src/audio/audio_general.c +++ b/src/audio/audio_general.c @@ -2268,7 +2268,7 @@ void Audio_AnalyzeFrequencies(f32* buffer0, f32* buffer1, s32 length, f32* buffe buff1half1 = buffer1; // FFT buffer 1 using buffer 2 - func_80008780(buffer1, length, buffer2); + AudioSynth_HartleyTransform(buffer1, length, buffer2); // handle i = 0 case buff0fromStart[0] = buff1half1[0]; diff --git a/src/audio/audio_synthesis.c b/src/audio/audio_synthesis.c index dad2c9e4..85b82639 100644 --- a/src/audio/audio_synthesis.c +++ b/src/audio/audio_synthesis.c @@ -3,6 +3,22 @@ #include "audio/mixer.h" #include "endianness.h" +#define DMEM_COMPRESSED_ADPCM_DATA 0x990 +#define DMEM_LEFT_CH 0x990 +#define DMEM_RIGHT_CH 0xB10 +#define DMEM_HAAS_TEMP 0x650 +#define DMEM_TEMP 0x450 +#define DMEM_UNCOMPRESSED_NOTE 0x5F0 +#define DMEM_WET_LEFT_CH 0xC90 +#define DMEM_WET_RIGHT_CH 0xE10 // = DMEM_WET_LEFT_CH + DMEM_1CH_SIZE +#define SAMPLE_SIZE sizeof(s16) + +typedef enum { + /* 0 */ HAAS_EFFECT_DELAY_NONE, + /* 1 */ HAAS_EFFECT_DELAY_LEFT, // Delay left channel so that right channel is heard first + /* 2 */ HAAS_EFFECT_DELAY_RIGHT // Delay right channel so that left channel is heard first +} HaasEffectDelaySide; + s32 D_80145D40; // unused // all of these are part of the DFT-related function @@ -29,27 +45,27 @@ static const char devstr7[] = "S->W\n"; static const char devstr8[] = "W->S\n"; static const char devstr9[] = "S-Resample Pitch %x (old %d -> delay %d)\n"; -void func_80009A2C(s32 updateIndex, s32 noteIndex); -void func_80009AAC(s32 updateIndex); -Acmd* func_8000A700(s32 noteIndex, NoteSubEu* noteSub, NoteSynthesisState* synthState, s16* aiBuf, s32 aiBufLen, +void AudioSynth_DisableSampleStates(s32 updateIndex, s32 noteIndex); +void AudioSynth_SyncSampleStates(s32 updateIndex); +Acmd* AudioSynth_ProcessNote(s32 noteIndex, NoteSubEu* noteSub, NoteSynthesisState* synthState, s16* aiBuf, s32 aiBufLen, Acmd* aList, s32 updateIndex); -Acmd* func_8000A25C(s16* aiBuf, s32 aiBufLen, Acmd* aList, s32 updateIndex); -Acmd* func_800098DC(Acmd* aList, u16 dmem, u16 startPos, s32 size, s32 reverbIndex); -Acmd* func_80009984(Acmd* aList, u16 dmem, u16 startPos, s32 size, s32 reverbIndex); -Acmd* func_80009D78(Acmd* aList, s32 aiBufLen, s16 reverbIndex, s16 updateIndex); -Acmd* func_8000A128(Acmd* aList, s16 reverbIndex, s16 updateIndex); -Acmd* func_8000B3F0(Acmd* aList, NoteSubEu* noteSub, NoteSynthesisState* synthState, s32 numSamplesToLoad); -Acmd* func_8000B480(Acmd* aList, NoteSynthesisState* synthState, s32 size, u16 pitch, u16 inpDmem, u32 resampleFlags); -Acmd* func_8000B51C(Acmd* aList, NoteSubEu* noteSub, NoteSynthesisState* synthState, s32 aiBufLen, u16 dmemSrc, +Acmd* AudioSynth_DoOneAudioUpdate(s16* aiBuf, s32 aiBufLen, Acmd* aList, s32 updateIndex); +Acmd* AudioSynth_LoadRingBufferPart(Acmd* aList, u16 dmem, u16 startPos, s32 size, s32 reverbIndex); +Acmd* AudioSynth_SaveRingBufferPart(Acmd* aList, u16 dmem, u16 startPos, s32 size, s32 reverbIndex); +Acmd* AudioSynth_LoadReverbSamples(Acmd* aList, s32 aiBufLen, s16 reverbIndex, s16 updateIndex); +Acmd* AudioSynth_SaveReverbSamples(Acmd* aList, s16 reverbIndex, s16 updateIndex); +Acmd* AudioSynth_LoadWaveSamples(Acmd* aList, NoteSubEu* noteSub, NoteSynthesisState* synthState, s32 numSamplesToLoad); +Acmd* AudioSynth_FinalResample(Acmd* aList, NoteSynthesisState* synthState, s32 size, u16 pitch, u16 inpDmem, u32 resampleFlags); +Acmd* AudioSynth_ProcessEnvelope(Acmd* aList, NoteSubEu* noteSub, NoteSynthesisState* synthState, s32 aiBufLen, u16 dmemSrc, s32 delaySide, s32 flags); -Acmd* func_8000B98C(Acmd* aList, NoteSubEu* noteSub, NoteSynthesisState* synthState, s32 size, s32 flags, +Acmd* AudioSynth_ApplyHaasEffect(Acmd* aList, NoteSubEu* noteSub, NoteSynthesisState* synthState, s32 size, s32 flags, s32 delaySide); -void func_800080C0(s32 sampleCount, s32 itemIndex, s32 reverbIndex) { +void AudioSynth_InitNextRingBuf(s32 sampleCount, s32 itemIndex, s32 reverbIndex) { ReverbRingBufferItem* ringItem; SynthesisReverb* reverb = &gSynthReverbs[reverbIndex]; - s32 temp_lo; - s32 temp_v1_3; + s32 numSamples; + s32 extraSamples; s32 i; s32 j; s32 pad1; @@ -69,26 +85,27 @@ void func_800080C0(s32 sampleCount, s32 itemIndex, s32 reverbIndex) { reverb->rightRingBuf[i] = ringItem->toDownsampleRight[j]; } } - ringItem = &reverb->items[reverb->curFrame][itemIndex]; - temp_lo = sampleCount / reverb->downsampleRate; - temp_v1_3 = reverb->nextRingBufPos + temp_lo - reverb->bufSizePerChan; - if (temp_v1_3 < 0) { - ringItem->lengthA = temp_lo * 2; + ringItem = &reverb->items[reverb->curFrame][itemIndex]; + numSamples = sampleCount / reverb->downsampleRate; + extraSamples = reverb->nextRingBufPos + numSamples - reverb->bufSizePerChan; + + if (extraSamples < 0) { + ringItem->lengthA = numSamples * SAMPLE_SIZE; ringItem->lengthB = 0; ringItem->startPos = reverb->nextRingBufPos; - reverb->nextRingBufPos += temp_lo; + reverb->nextRingBufPos += numSamples; } else { - ringItem->lengthA = (temp_lo - temp_v1_3) * 2; - ringItem->lengthB = temp_v1_3 * 2; + ringItem->lengthA = (numSamples - extraSamples) * 2; + ringItem->lengthB = extraSamples * SAMPLE_SIZE; ringItem->startPos = reverb->nextRingBufPos; - reverb->nextRingBufPos = temp_v1_3; + reverb->nextRingBufPos = extraSamples; } - ringItem->numSamplesAfterDownsampling = temp_lo; + ringItem->numSamplesAfterDownsampling = numSamples; ringItem->chunkLen = sampleCount; } -void func_80008364(f32* buffer0, f32* buffer1, s32 length, f32* buffer2) { +void AudioSynth_InverseDiscreteCosineTransform(f32* buffer0, f32* buffer1, s32 length, f32* buffer2) { f32 temp_ft0; f32 var_fs0; f32* buff0fromStart; @@ -146,7 +163,7 @@ void func_80008364(f32* buffer0, f32* buffer1, s32 length, f32* buffer2) { } // FFT buffer 1 using buffer 2 - func_80008780(buffer1, length, buffer2); + AudioSynth_HartleyTransform(buffer1, length, buffer2); buff0fromStart = buffer0; buff0FromEnd = &buffer0[size - 1]; @@ -165,7 +182,7 @@ void func_80008364(f32* buffer0, f32* buffer1, s32 length, f32* buffer2) { // https://decomp.me/scratch/8eyVg #ifdef NON_MATCHING -void func_80008780(f32* arg0, s32 arg1, f32* arg2) { +void AudioSynth_HartleyTransform(f32* arg0, s32 arg1, f32* arg2) { s32 length; s32 spD0; s32 spCC; @@ -366,7 +383,7 @@ void func_80008780(f32* arg0, s32 arg1, f32* arg2) { } } #else -#pragma GLOBAL_ASM("asm/us/rev1/nonmatchings/audio/audio_synthesis/func_80008780.s") +#pragma GLOBAL_ASM("asm/us/rev1/nonmatchings/audio/audio_synthesis/AudioSynth_HartleyTransform.s") #endif // https://decomp.me/scratch/mYlns @@ -376,6 +393,7 @@ void func_80009124(s16** arg0) { s32 temp_a0; u8 temp_s0; u8 temp_s1; + u8 temp_u1; s32 temp_t5_4; s32 temp_v0; u8 temp_v1; @@ -386,35 +404,38 @@ void func_80009124(s16** arg0) { u32 var_t3; s32 i; s32 j; + s16 new_var2; var_a1 = *arg0; for (i = 255; i >= 0; i--) { D_80145D48[i] = 0.0f; } - var_t3 = *var_a1++ << 0x10; - var_t3 |= *var_a1++; + temp_v0 = *var_a1++; + var_t3 = temp_v0 << 0x10; + temp_v0 = *var_a1++; + var_t3 |= temp_v0; - for (var_t2 = 0; var_t2 != 0x100; var_t2 += 0x40) { + for (var_t2 = 0; var_t2 < 4; var_t2++) { + var_v1 = var_t2 * 0x40; temp_s0 = var_t3 >> 0x18; - var_v1 = var_t2; + var_t3 <<= 8; - temp_v0 = ((temp_s0 >> 4) & 0xF); + temp_v1 = ((temp_s0 >> 4) & 0xF); temp_a0 = temp_s0 & 0xF; - if (((temp_s0 >> 4) & 0xF) == 0) { + if (temp_v1 == 0) { continue; } - switch (temp_v0) { + switch (temp_v1) { case 1: while (true) { var_s0 = *var_a1++; for (var_s1 = 0; var_s1 < 4; var_s1++) { - temp_s1 = (var_s0 >> 0xC) & 0xF; + temp_u1 = (var_s0 >> 0xC) & 0xF; var_s0 <<= 4; - D_80145D48[var_v1++] = ((temp_s1 & 7) - 4) << temp_a0; - - if (temp_s1 >= 8) { + D_80145D48[var_v1++] = ((temp_u1 & 7) - 4) << temp_a0; + if (temp_u1 >= 8) { goto case_1_break; } } @@ -422,49 +443,47 @@ void func_80009124(s16** arg0) { case_1_break: break; case 2: - var_s1 = -1; - while (++var_s1 < 16) { + for (var_s1 = 0; var_s1 < 16; var_s1++) { var_s0 = *var_a1++; for (i = 0; i < 4; i++) { - temp_s1 = (var_s0 >> 0xC) & 0xF; + temp_u1 = (var_s0 >> 0xC) & 0xF; var_s0 <<= 4; - D_80145D48[var_v1++] = (temp_s1 - 8) << temp_a0; + D_80145D48[var_v1++] = (temp_u1 - 8) << temp_a0; } } break; case 6: while (true) { var_s0 = *var_a1++; - temp_s1 = (var_s0 >> 8) & 0xFF; - - D_80145D48[var_v1] = ((temp_s1 & 0x3F) - 0x20) << temp_a0; - if (temp_s1 >> 6 == 0) { - + temp_u1 = (var_s0 >> 8) & 0xFF; + temp_t5_4 = temp_u1 >> 6; + D_80145D48[var_v1] = ((temp_u1 & 0x3F) - 0x20) << temp_a0; + if (temp_t5_4 == 0) { break; } - var_v1 += temp_s1 >> 6; - temp_s1 = var_s0 & 0xFF; - D_80145D48[var_v1] = ((temp_s1 & 0x3F) - 0x20) << temp_a0; - if (temp_s1 >> 6 == 0) { - + var_v1 += temp_t5_4; + temp_u1 = var_s0 & 0xFF; + temp_t5_4 = temp_u1 >> 6; + D_80145D48[var_v1] = ((temp_u1 & 0x3F) - 0x20) << temp_a0; + if (temp_t5_4 == 0) { break; } - var_v1 += temp_s1 >> 6; + var_v1 += temp_t5_4; } break; case 3: while (true) { var_s0 = *var_a1++; + temp_u1 = (var_s0 >> 8) & 0xFF; - temp_s1 = (var_s0 >> 8) & 0xFF; + D_80145D48[var_v1++] = ((temp_u1 & 0x7F) - 0x40) << temp_a0; - D_80145D48[var_v1++] = ((temp_s1 & 0x7F) - 0x40) << temp_a0; - if (temp_s1 >= 0x80) { + if (temp_u1 >= 0x80) { break; } - temp_s1 = var_s0 & 0xFF; - D_80145D48[var_v1++] = ((temp_s1 & 0x7F) - 0x40) << temp_a0; - if (temp_s1 >= 0x80) { + temp_u1 = var_s0 & 0xFF; + D_80145D48[var_v1++] = ((temp_u1 & 0x7F) - 0x40) << temp_a0; + if (temp_u1 >= 0x80) { break; } } @@ -483,8 +502,9 @@ void func_80009124(s16** arg0) { case 5: while (true) { var_s0 = *var_a1++; + temp_t5_4 = var_s0 >> 0xF; D_80145D48[var_v1] = ((var_s0 & 0x7FFF) - 0x4000) << temp_a0; - if ((var_s0 >> 0xF) == 1) { + if (temp_t5_4 == 1) { break; } var_v1++; @@ -513,7 +533,7 @@ void func_80009504(s16* arg0, UnkStruct_800097A8* arg1) { arg1->unk18 -= 0x1000; } - func_80008364(D_80145D48, D_80146148, 8, D_80146548); + AudioSynth_InverseDiscreteCosineTransform(D_80145D48, D_80146148, 8, D_80146548); for (i = 0; i < 256; i++) { if (D_80145D48[i] > 32767.0f) { @@ -560,7 +580,7 @@ u8* func_800097A8(Sample* sample, s32 length, u32 flags, UnkStruct_800097A8* arg SampleDma* pad2; SampleDma* sp1C; - if (flags == 1) { + if (flags == A_INIT) { arg3->unk_0 = (s16*) sample->sampleAddr; arg3->unk_4 = 0; arg3->unk_8 = 0; @@ -580,6 +600,7 @@ u8* func_800097A8(Sample* sample, s32 length, u32 flags, UnkStruct_800097A8* arg if (1) {} //! FAKE sp1C->ttl = 2; + // @port: (uintptr_t) sp1C->devAddr = (uintptr_t) sample->sampleAddr; sp1C->sizeUnused = length * 2; pad2 = arg3->unk_14; @@ -588,19 +609,21 @@ u8* func_800097A8(Sample* sample, s32 length, u32 flags, UnkStruct_800097A8* arg return sp1C->ramAddr; } -Acmd* func_800098DC(Acmd* aList, u16 dmem, u16 startPos, s32 size, s32 reverbIndex) { +Acmd* AudioSynth_LoadRingBufferPart(Acmd* aList, u16 dmem, u16 startPos, s32 size, s32 reverbIndex) { aLoadBuffer(aList++, OS_K0_TO_PHYSICAL(&gSynthReverbs[reverbIndex].leftRingBuf[startPos]), dmem, size); - aLoadBuffer(aList++, OS_K0_TO_PHYSICAL(&gSynthReverbs[reverbIndex].rightRingBuf[startPos]), dmem + 0x180, size); + aLoadBuffer(aList++, OS_K0_TO_PHYSICAL(&gSynthReverbs[reverbIndex].rightRingBuf[startPos]), dmem + DMEM_1CH_SIZE, + size); return aList; } -Acmd* func_80009984(Acmd* aList, u16 dmem, u16 startPos, s32 size, s32 reverbIndex) { +Acmd* AudioSynth_SaveRingBufferPart(Acmd* aList, u16 dmem, u16 startPos, s32 size, s32 reverbIndex) { aSaveBuffer(aList++, dmem, OS_K0_TO_PHYSICAL(&gSynthReverbs[reverbIndex].leftRingBuf[startPos]), size); - aSaveBuffer(aList++, dmem + 0x180, OS_K0_TO_PHYSICAL(&gSynthReverbs[reverbIndex].rightRingBuf[startPos]), size); + aSaveBuffer(aList++, dmem + DMEM_1CH_SIZE, OS_K0_TO_PHYSICAL(&gSynthReverbs[reverbIndex].rightRingBuf[startPos]), + size); return aList; } -void func_80009A2C(s32 updateIndex, s32 noteIndex) { +void AudioSynth_DisableSampleStates(s32 updateIndex, s32 noteIndex) { NoteSubEu* noteSubEu; s32 i; @@ -613,24 +636,27 @@ void func_80009A2C(s32 updateIndex, s32 noteIndex) { } } -void func_80009AAC(s32 updateIndex) { - NoteSubEu* subEu; - NoteSubEu* subEu2; +/** + * Sync the sample states between the notes and the list + */ +void AudioSynth_SyncSampleStates(s32 updateIndex) { + NoteSubEu* noteSampleState; + NoteSubEu* sampleState; s32 i; for (i = 0; i < gNumNotes; i++) { - subEu = &gNotes[i].noteSubEu; - subEu2 = &gNoteSubsEu[gNumNotes * updateIndex + i]; - if (subEu->bitField0.enabled) { - *subEu2 = *subEu; - subEu->bitField0.needsInit = false; + noteSampleState = &gNotes[i].noteSubEu; + sampleState = &gNoteSubsEu[gNumNotes * updateIndex + i]; + if (noteSampleState->bitField0.enabled) { + *sampleState = *noteSampleState; + noteSampleState->bitField0.needsInit = false; } else { - subEu2->bitField0.enabled = false; + sampleState->bitField0.enabled = false; } } } -Acmd* func_80009B64(Acmd* aList, s32* cmdCount, s16* aiBufStart, s32 aiBufLen) { +Acmd* AudioSynth_Update(Acmd* aList, s32* cmdCount, s16* aiBufStart, s32 aiBufLen) { Acmd* aCmdPtr; s32* aiBufPtr; s32 chunkLen; @@ -640,10 +666,12 @@ Acmd* func_80009B64(Acmd* aList, s32* cmdCount, s16* aiBufStart, s32 aiBufLen) { aCmdPtr = aList; for (i = gAudioBufferParams.ticksPerUpdate; i > 0; i--) { AudioSeq_ProcessSequences(i - 1); - func_80009AAC(gAudioBufferParams.ticksPerUpdate - i); + AudioSynth_SyncSampleStates(gAudioBufferParams.ticksPerUpdate - i); } aiBufPtr = (s32*) aiBufStart; + // @port: i = gAudioBufferParams.ticksPerUpdate - 1 // this change is necessary to avoid a crash, sounds like a + // problem for (i = gAudioBufferParams.ticksPerUpdate - 1; i > 0; i--) { if (i == 1) { chunkLen = aiBufLen; @@ -657,11 +685,12 @@ Acmd* func_80009B64(Acmd* aList, s32* cmdCount, s16* aiBufStart, s32 aiBufLen) { for (j = 0; j < gNumSynthReverbs; j++) { if (gSynthReverbs[j].useReverb) { - func_800080C0(chunkLen, gAudioBufferParams.ticksPerUpdate - i, j); + AudioSynth_InitNextRingBuf(chunkLen, gAudioBufferParams.ticksPerUpdate - i, j); } } - aCmdPtr = func_8000A25C((s16*) aiBufPtr, chunkLen, aCmdPtr, gAudioBufferParams.ticksPerUpdate - i); + aCmdPtr = + AudioSynth_DoOneAudioUpdate((s16*) aiBufPtr, chunkLen, aCmdPtr, gAudioBufferParams.ticksPerUpdate - i); aiBufLen -= chunkLen; aiBufPtr += chunkLen; } @@ -678,59 +707,61 @@ Acmd* func_80009B64(Acmd* aList, s32* cmdCount, s16* aiBufStart, s32 aiBufLen) { return aCmdPtr; } -Acmd* func_80009D78(Acmd* aList, s32 aiBufLen, s16 reverbIndex, s16 updateIndex) { +Acmd* AudioSynth_LoadReverbSamples(Acmd* aList, s32 aiBufLen, s16 reverbIndex, s16 updateIndex) { ReverbRingBufferItem* sp64 = &gSynthReverbs[reverbIndex].items[gSynthReverbs[reverbIndex].curFrame][updateIndex]; s16 sp62; s16 sp60; - aClearBuffer(aList++, 0xC90, 0x300); + aClearBuffer(aList++, DMEM_WET_LEFT_CH, DMEM_2CH_SIZE); if (gSynthReverbs[reverbIndex].downsampleRate == 1) { - aList = func_800098DC(aList, 0xC90, sp64->startPos, sp64->lengthA, reverbIndex); + aList = AudioSynth_LoadRingBufferPart(aList, DMEM_WET_LEFT_CH, sp64->startPos, sp64->lengthA, reverbIndex); if (sp64->lengthB != 0) { - aList = func_800098DC(aList, sp64->lengthA + 0xC90, 0, sp64->lengthB, reverbIndex); + aList = + AudioSynth_LoadRingBufferPart(aList, sp64->lengthA + DMEM_WET_LEFT_CH, 0, sp64->lengthB, reverbIndex); } - aAddMixer(aList++, 0x300, 0xC90, 0x990); - aMix(aList++, 0x30, gSynthReverbs[reverbIndex].decayRatio + 0x8000, 0xC90, 0xC90); + aAddMixer(aList++, 0x300, DMEM_WET_LEFT_CH, DMEM_LEFT_CH); + aMix(aList++, 0x30, gSynthReverbs[reverbIndex].decayRatio + 0x8000, DMEM_WET_LEFT_CH, DMEM_WET_LEFT_CH); } else { sp62 = (sp64->startPos & 7) * 2; sp60 = ALIGN16(sp62 + sp64->lengthA); - aList = func_800098DC(aList, 0x470, sp64->startPos - (sp62 / 2), 0x180, reverbIndex); + aList = AudioSynth_LoadRingBufferPart(aList, 0x470, sp64->startPos - (sp62 / 2), DMEM_1CH_SIZE, reverbIndex); if (sp64->lengthB != 0) { - aList = func_800098DC(aList, sp60 + 0x470, 0, 0x180 - sp60, reverbIndex); + aList = AudioSynth_LoadRingBufferPart(aList, sp60 + 0x470, 0, DMEM_1CH_SIZE - sp60, reverbIndex); } - aSetBuffer(aList++, 0, sp62 + 0x470, 0xC90, aiBufLen * 2); + aSetBuffer(aList++, 0, sp62 + 0x470, DMEM_WET_LEFT_CH, aiBufLen * 2); aResample(aList++, gSynthReverbs[reverbIndex].resampleFlags, gSynthReverbs[reverbIndex].unk_0A, OS_K0_TO_PHYSICAL(gSynthReverbs[reverbIndex].unk_30)); - aSetBuffer(aList++, 0, sp62 + 0x5F0, 0xE10, aiBufLen * 2); + aSetBuffer(aList++, 0, sp62 + DMEM_UNCOMPRESSED_NOTE, DMEM_WET_RIGHT_CH, aiBufLen * 2); aResample(aList++, gSynthReverbs[reverbIndex].resampleFlags, gSynthReverbs[reverbIndex].unk_0A, OS_K0_TO_PHYSICAL(gSynthReverbs[reverbIndex].unk_34)); - aAddMixer(aList++, 0x300, 0xC90, 0x990); - aMix(aList++, 0x30, gSynthReverbs[reverbIndex].decayRatio + 0x8000, 0xC90, 0xC90); + aAddMixer(aList++, 0x300, DMEM_WET_LEFT_CH, DMEM_LEFT_CH); + aMix(aList++, 0x30, gSynthReverbs[reverbIndex].decayRatio + 0x8000, DMEM_WET_LEFT_CH, DMEM_WET_LEFT_CH); } if ((gSynthReverbs[reverbIndex].leakRtL != 0) || (gSynthReverbs[reverbIndex].leakLtR != 0)) { - aDMEMMove(aList++, 0xC90, 0x470, 0x180); - aMix(aList++, 0x18, gSynthReverbs[reverbIndex].leakRtL, 0xE10, 0xC90); - aMix(aList++, 0x18, gSynthReverbs[reverbIndex].leakLtR, 0x470, 0xE10); + aDMEMMove(aList++, DMEM_WET_LEFT_CH, 0x470, DMEM_1CH_SIZE); + aMix(aList++, DMEM_1CH_SIZE >> 4, gSynthReverbs[reverbIndex].leakRtL, DMEM_WET_RIGHT_CH, DMEM_WET_LEFT_CH); + aMix(aList++, DMEM_1CH_SIZE >> 4, gSynthReverbs[reverbIndex].leakLtR, 0x470, DMEM_WET_RIGHT_CH); } return aList; } -Acmd* func_8000A128(Acmd* aList, s16 reverbIndex, s16 updateIndex) { +Acmd* AudioSynth_SaveReverbSamples(Acmd* aList, s16 reverbIndex, s16 updateIndex) { ReverbRingBufferItem* sp24; sp24 = &gSynthReverbs[reverbIndex].items[gSynthReverbs[reverbIndex].curFrame][updateIndex]; switch (gSynthReverbs[reverbIndex].downsampleRate) { case 1: - aList = func_80009984(aList, 0xC90, sp24->startPos, sp24->lengthA, reverbIndex); + aList = AudioSynth_SaveRingBufferPart(aList, DMEM_WET_LEFT_CH, sp24->startPos, sp24->lengthA, reverbIndex); if (sp24->lengthB != 0) { - aList = func_80009984(aList, sp24->lengthA + 0xC90, 0, sp24->lengthB, reverbIndex); + aList = AudioSynth_SaveRingBufferPart(aList, sp24->lengthA + DMEM_WET_LEFT_CH, 0, sp24->lengthB, + reverbIndex); } break; default: - aSaveBuffer(aList++, 0xC90, + aSaveBuffer(aList++, DMEM_WET_LEFT_CH, OS_K0_TO_PHYSICAL(gSynthReverbs[reverbIndex] .items[gSynthReverbs[reverbIndex].curFrame][updateIndex] .toDownsampleLeft), @@ -742,19 +773,19 @@ Acmd* func_8000A128(Acmd* aList, s16 reverbIndex, s16 updateIndex) { return aList; } -Acmd* func_8000A25C(s16* aiBuf, s32 aiBufLen, Acmd* aList, s32 updateIndex) { +Acmd* AudioSynth_DoOneAudioUpdate(s16* aiBuf, s32 aiBufLen, Acmd* aList, s32 updateIndex) { u8 sp84[0x3C]; NoteSubEu* temp_v0; - s16 var_s2; - s16 i = 0; - s32 j = 0; + s16 count; + s16 i; + s32 j; - var_s2 = 0; + count = 0; if (gNumSynthReverbs == 0) { if (gSynthReverbs[i].useReverb) {} // fake? for (j = 0; j < gNumNotes; j++) { if (gNoteSubsEu[gNumNotes * updateIndex + j].bitField0.enabled) { - sp84[var_s2++] = j; + sp84[count++] = j; } } } else { @@ -762,64 +793,57 @@ Acmd* func_8000A25C(s16* aiBuf, s32 aiBufLen, Acmd* aList, s32 updateIndex) { for (j = 0; j < gNumNotes; j++) { temp_v0 = &gNoteSubsEu[gNumNotes * updateIndex + j]; if (temp_v0->bitField0.enabled && (temp_v0->bitField1.reverbIndex == i)) { - sp84[var_s2++] = j; + sp84[count++] = j; } } } for (j = 0; j < gNumNotes; j++) { temp_v0 = &gNoteSubsEu[gNumNotes * updateIndex + j]; if (temp_v0->bitField0.enabled && (temp_v0->bitField1.reverbIndex >= gNumSynthReverbs)) { - sp84[var_s2++] = j; + sp84[count++] = j; } } } - aClearBuffer(aList++, 0x990, 0x300); + aClearBuffer(aList++, DMEM_LEFT_CH, DMEM_2CH_SIZE); j = 0; for (i = 0; i < gNumSynthReverbs; i++) { D_8014C1B2 = gSynthReverbs[i].useReverb; if (D_8014C1B2) { - aList = func_80009D78(aList, aiBufLen, i, updateIndex); + aList = AudioSynth_LoadReverbSamples(aList, aiBufLen, i, updateIndex); } - while (j < var_s2) { + while (j < count) { if (i != gNoteSubsEu[updateIndex * gNumNotes + sp84[j]].bitField1.reverbIndex) { break; } - aList = func_8000A700(sp84[j], &gNoteSubsEu[updateIndex * gNumNotes + sp84[j]], - &gNotes[sp84[j]].synthesisState, aiBuf, aiBufLen, aList, updateIndex); + aList = AudioSynth_ProcessNote(sp84[j], &gNoteSubsEu[updateIndex * gNumNotes + sp84[j]], + &gNotes[sp84[j]].synthesisState, aiBuf, aiBufLen, aList, updateIndex); j++; } if (gSynthReverbs[i].useReverb) { - aList = func_8000A128(aList, i, updateIndex); + aList = AudioSynth_SaveReverbSamples(aList, i, updateIndex); } } - while (j < var_s2) { - aList = func_8000A700(sp84[j], &gNoteSubsEu[updateIndex * gNumNotes + sp84[j]], &gNotes[sp84[j]].synthesisState, - aiBuf, aiBufLen, aList, updateIndex); + while (j < count) { + aList = AudioSynth_ProcessNote(sp84[j], &gNoteSubsEu[updateIndex * gNumNotes + sp84[j]], + &gNotes[sp84[j]].synthesisState, aiBuf, aiBufLen, aList, updateIndex); j++; } j = aiBufLen * 2; - aSetBuffer(aList++, 0, 0, 0x450, j); - aInterleave(aList++, 0, 0x990, 0xB10, 0); - aSaveBuffer(aList++, 0x450, OS_K0_TO_PHYSICAL(aiBuf), j * 2); + aSetBuffer(aList++, 0, 0, DMEM_TEMP, j); + aInterleave(aList++, 0, DMEM_LEFT_CH, DMEM_RIGHT_CH, 0); + aSaveBuffer(aList++, DMEM_TEMP, OS_K0_TO_PHYSICAL(aiBuf), j * 2); return aList; } // https://decomp.me/scratch/RgX4r #ifdef NON_MATCHING -Acmd* func_8000A700( - s32 noteIndex, - NoteSubEu* noteSub, - NoteSynthesisState* synthState, - s16* aiBuf, - s32 aiBufLen, - Acmd* aList, - s32 updateIndex -) { +Acmd* AudioSynth_ProcessNote(s32 noteIndex, NoteSubEu* noteSub, NoteSynthesisState* synthState, s16* aiBuf, s32 aiBufLen, + Acmd* aList, s32 updateIndex) { s32 pad11C; s32 pad118; s32 pad114; @@ -921,11 +945,11 @@ Acmd* func_8000A700( } synthState->numParts = numParts; if (noteSub->bitField1.isSyntheticWave) { - aList = func_8000B3F0(aList, noteSub, synthState, numSamplesToLoad); - noteSamplesDmemAddrBeforeResampling = (synthState->samplePosInt * ((char)2)) + 0x5F0; + aList = AudioSynth_LoadWaveSamples(aList, noteSub, synthState, numSamplesToLoad); + noteSamplesDmemAddrBeforeResampling = (synthState->samplePosInt * ((char) 2)) + 0x5F0; synthState->samplePosInt += numSamplesToLoad; } else { - bookSample = *((Sample**)noteSub->waveSampleAddr); + bookSample = *((Sample**) noteSub->waveSampleAddr); loopInfo = bookSample->loop; endPos = loopInfo->end; @@ -1006,11 +1030,9 @@ Acmd* func_8000A700( break; case 2: - temp = func_800097A8( - bookSample, numSamplesToLoadAdj, flags, &synthState->synthesisBuffers->unk_40 - ); - if (0) { - } + temp = func_800097A8(bookSample, numSamplesToLoadAdj, flags, + &synthState->synthesisBuffers->unk_40); + if (0) {} aLoadBuffer(aList++, OS_K0_TO_PHYSICAL(temp), 0x5F0, (numSamplesToLoadAdj + 0x10) * 2); flags = 0; skipBytes = 0; @@ -1022,16 +1044,15 @@ Acmd* func_8000A700( aligned = ALIGN16((nFramesToDecode * frameSize) + 0x10); addr = 0x990 - aligned; if (nFramesToDecode != 0) { - if (1) { - } + if (1) {} frameIndex = (synthState->samplePosInt + skipInitialSamples - nFirstFrameSamplesToIgnore) / 16; sampleDataOffset = frameIndex * frameSize; if (bookSample->medium == 0) { - samplesToLoadAddr = (u8*)(sampleDmaStart + sampleDataOffset + sampleAddr); + samplesToLoadAddr = (u8*) (sampleDmaStart + sampleDataOffset + sampleAddr); } else { - samplesToLoadAddr = (u8*)(sampleDmaStart + sampleDataOffset + sampleAddr); + samplesToLoadAddr = (u8*) (sampleDmaStart + sampleDataOffset + sampleAddr); } - sampleDataChunkAlignPad = ((uintptr_t)samplesToLoadAddr) % 16; + sampleDataChunkAlignPad = ((uintptr_t) samplesToLoadAddr) % 16; aLoadBuffer(aList++, OS_K0_TO_PHYSICAL(samplesToLoadAddr - sampleDataChunkAlignPad), addr, aligned); } else { @@ -1068,24 +1089,20 @@ Acmd* func_8000A700( align2 = ALIGN16(dmemUncompressedAddrOffset1 + 0x10); switch (bookSample->codec) { case 0: - aSetBuffer( - aList++, 0, addr + sampleDataChunkAlignPad, align2 + 0x5F0, numSamplesToDecode * 2 - ); + aSetBuffer(aList++, 0, addr + sampleDataChunkAlignPad, align2 + 0x5F0, + numSamplesToDecode * 2); aADPCMdec(aList++, flags, OS_K0_TO_PHYSICAL(synthState->synthesisBuffers)); break; case 1: - aSetBuffer( - aList++, 0, addr + sampleDataChunkAlignPad, align2 + 0x5F0, numSamplesToDecode * 2 - ); + aSetBuffer(aList++, 0, addr + sampleDataChunkAlignPad, align2 + 0x5F0, + numSamplesToDecode * 2); aS8Dec(aList++, flags, OS_K0_TO_PHYSICAL(synthState->synthesisBuffers)); break; } - aDMEMMove( - aList++, 0x5F0 + align2 + (nFirstFrameSamplesToIgnore * 2), 0x5F0 + dmemUncompressedAddrOffset1, - numSamplesInThisIteration * 2 - ); + aDMEMMove(aList++, 0x5F0 + align2 + (nFirstFrameSamplesToIgnore * 2), + 0x5F0 + dmemUncompressedAddrOffset1, numSamplesInThisIteration * 2); } numSamplesProcessed += numSamplesInThisIteration; @@ -1113,12 +1130,11 @@ Acmd* func_8000A700( flags = 0; if (sampleFinished) { - aClearBuffer( - aList++, dmemUncompressedAddrOffset1 + 0x5F0, (numSamplesToLoadAdj - numSamplesProcessed) * 2 - ); + aClearBuffer(aList++, dmemUncompressedAddrOffset1 + 0x5F0, + (numSamplesToLoadAdj - numSamplesProcessed) * 2); noteSub->bitField0.finished = 1; note->noteSubEu.bitField0.finished = 1; - func_80009A2C(updateIndex, noteIndex); + AudioSynth_DisableSampleStates(updateIndex, noteIndex); break; } if (loopToPoint != 0) { @@ -1141,17 +1157,14 @@ Acmd* func_8000A700( resampledTempLen = numSamplesToLoadAdj; noteSamplesDmemAddrBeforeResampling = 0x470; if (noteSub->bitField0.finished) { - aClearBuffer( - aList++, resampledTempLen + noteSamplesDmemAddrBeforeResampling, - numSamplesToLoadAdj + 0x10 - ); + aClearBuffer(aList++, resampledTempLen + noteSamplesDmemAddrBeforeResampling, + numSamplesToLoadAdj + 0x10); } break; case 1: - aInterl( - aList++, skipBytes + 0x5F0, resampledTempLen + 0x470, ALIGN8(numSamplesToLoadAdj / 2) - ); + aInterl(aList++, skipBytes + 0x5F0, resampledTempLen + 0x470, + ALIGN8(numSamplesToLoadAdj / 2)); break; } @@ -1169,9 +1182,8 @@ Acmd* func_8000A700( noteSub->bitField0.needsInit = 0; } flags = sp56 | flags; - aList = func_8000B480( - aList, synthState, aiBufLen * 2, resampleRateFixedPoint, noteSamplesDmemAddrBeforeResampling, flags - ); + aList = AudioSynth_FinalResample(aList, synthState, aiBufLen * 2, resampleRateFixedPoint, noteSamplesDmemAddrBeforeResampling, + flags); if (flags & 1) { flags = 1; } @@ -1192,171 +1204,193 @@ Acmd* func_8000A700( } else { delaySide = 0; } - aList = func_8000B51C(aList, noteSub, synthState, aiBufLen, 0x450, delaySide, flags); + aList = AudioSynth_ProcessEnvelope(aList, noteSub, synthState, aiBufLen, 0x450, delaySide, flags); if (noteSub->bitField0.usesHeadsetPanEffects) { if (!(flags & 1)) { flags = 0; } - aList = func_8000B98C(aList, noteSub, synthState, aiBufLen * 2, flags, delaySide); + aList = AudioSynth_ApplyHaasEffect(aList, noteSub, synthState, aiBufLen * 2, flags, delaySide); } return aList; } #else -#pragma GLOBAL_ASM("asm/us/rev1/nonmatchings/audio/audio_synthesis/func_8000A700.s") +#pragma GLOBAL_ASM("asm/us/rev1/nonmatchings/audio/audio_synthesis/AudioSynth_ProcessNote.s") #endif -Acmd* func_8000B3F0(Acmd* aList, NoteSubEu* noteSub, NoteSynthesisState* synthState, s32 numSamplesToLoad) { - s32 temp_v1; +Acmd* AudioSynth_LoadWaveSamples(Acmd* aList, NoteSubEu* noteSub, NoteSynthesisState* synthState, + s32 numSamplesToLoad) { + s32 numSamplesAvail; + s32 numDuplicates; - aLoadBuffer(aList++, OS_K0_TO_PHYSICAL(noteSub->waveSampleAddr), 0x5F0, 0x80); - synthState->samplePosInt &= 0x3F; - temp_v1 = 0x40 - synthState->samplePosInt; - if (temp_v1 < numSamplesToLoad) { - if ((((numSamplesToLoad - temp_v1) + 0x3F) / 64) != 0) { - aDuplicate(aList++, ((numSamplesToLoad - temp_v1) + 0x3F) / 64, 0x5F0, 0x670); + aLoadBuffer(aList++, OS_K0_TO_PHYSICAL(noteSub->waveSampleAddr), DMEM_UNCOMPRESSED_NOTE, + WAVE_SAMPLE_COUNT * SAMPLE_SIZE); + + // Offset in the WAVE_SAMPLE_COUNT samples of gWaveSamples to start processing the wave for continuity + synthState->samplePosInt = (u32) synthState->samplePosInt % WAVE_SAMPLE_COUNT; + // Number of samples in the initial WAVE_SAMPLE_COUNT samples available to be used to process + numSamplesAvail = WAVE_SAMPLE_COUNT - synthState->samplePosInt; + + if (numSamplesToLoad > numSamplesAvail) { + // Duplicate (copy) the WAVE_SAMPLE_COUNT samples as many times as needed to reach numSamplesToLoad. + // (numSamplesToLoad - numSamplesAvail) is the number of samples missing. + // Divide by WAVE_SAMPLE_COUNT, rounding up, to get the amount of duplicates + numDuplicates = ((numSamplesToLoad - numSamplesAvail + WAVE_SAMPLE_COUNT - 1) / WAVE_SAMPLE_COUNT); + if (numDuplicates != 0) { + aDuplicate(aList++, numDuplicates, DMEM_UNCOMPRESSED_NOTE, + DMEM_UNCOMPRESSED_NOTE + (WAVE_SAMPLE_COUNT * SAMPLE_SIZE)); } } return aList; } -Acmd* func_8000B480(Acmd* aList, NoteSynthesisState* synthState, s32 size, u16 pitch, u16 inpDmem, u32 resampleFlags) { +Acmd* AudioSynth_FinalResample(Acmd* aList, NoteSynthesisState* synthState, s32 size, u16 pitch, u16 inpDmem, + u32 resampleFlags) { if (pitch == 0) { - aClearBuffer(aList++, 0x450, size); + aClearBuffer(aList++, DMEM_TEMP, size); } else { - aSetBuffer(aList++, 0, inpDmem, 0x450, size); + aSetBuffer(aList++, 0, inpDmem, DMEM_TEMP, size); aResample(aList++, resampleFlags, pitch, OS_K0_TO_PHYSICAL(synthState->synthesisBuffers->finalResampleState)); } return aList; } -Acmd* func_8000B51C(Acmd* aList, NoteSubEu* noteSub, NoteSynthesisState* synthState, s32 aiBufLen, u16 dmemSrc, - s32 delaySide, s32 flags) { - s16 var_a2; - s16 var_a3; - s16 var_t0; - u16 temp_t7; - u16 temp_t9; - u16 temp_t1; - u16 temp_t2; - s32 temp_a1; +Acmd* AudioSynth_ProcessEnvelope(Acmd* aList, NoteSubEu* noteSub, NoteSynthesisState* synthState, s32 aiBufLen, + u16 dmemSrc, s32 delaySide, s32 flags) { + s16 rampReverb; + s16 rampRight; + s16 rampLeft; + u16 panVolLeft; + u16 panVolRight; + u16 curVolLeft; + u16 curVolRight; + s32 sourceReverbVol; s32 temp = 0; - temp_t1 = synthState->curVolLeft; - temp_t2 = synthState->curVolRight; + curVolLeft = synthState->curVolLeft; + curVolRight = synthState->curVolRight; - temp_t7 = noteSub->panVolLeft; - temp_t9 = noteSub->panVolRight; + panVolLeft = noteSub->panVolLeft; + panVolRight = noteSub->panVolRight; - temp_t7 <<= 4; - temp_t9 <<= 4; + panVolLeft <<= 4; + panVolRight <<= 4; - if (temp_t7 != temp_t1) { - var_t0 = (temp_t7 - temp_t1) / (aiBufLen >> 3); + if (panVolLeft != curVolLeft) { + rampLeft = (panVolLeft - curVolLeft) / (aiBufLen >> 3); } else { - var_t0 = 0; + rampLeft = 0; } - if (temp_t9 != temp_t2) { - var_a3 = (temp_t9 - temp_t2) / (aiBufLen >> 3); + if (panVolRight != curVolRight) { + rampRight = (panVolRight - curVolRight) / (aiBufLen >> 3); } else { - var_a3 = 0; + rampRight = 0; } - temp_a1 = synthState->reverbVol; + sourceReverbVol = synthState->reverbVol; - if (noteSub->reverb != temp_a1) { - temp = (((noteSub->reverb & 0x7F) - (temp_a1 & 0x7F)) << 8); - var_a2 = temp / (aiBufLen >> 3); + if (noteSub->reverb != sourceReverbVol) { + temp = (((noteSub->reverb & 0x7F) - (sourceReverbVol & 0x7F)) << 8); + rampReverb = temp / (aiBufLen >> 3); synthState->reverbVol = noteSub->reverb; } else { - var_a2 = 0; + rampReverb = 0; } - synthState->curVolLeft = temp_t1 + (var_t0 * (aiBufLen >> 3)); - synthState->curVolRight = temp_t2 + (var_a3 * (aiBufLen >> 3)); + synthState->curVolLeft = curVolLeft + (rampLeft * (aiBufLen >> 3)); + synthState->curVolRight = curVolRight + (rampRight * (aiBufLen >> 3)); if (noteSub->bitField0.usesHeadsetPanEffects) { - aClearBuffer(aList++, 0x650, 0x180); - aEnvSetup1(aList++, (temp_a1 & 0x7F), var_a2, var_t0, var_a3); - aEnvSetup2(aList++, temp_t1, temp_t2); + aClearBuffer(aList++, DMEM_HAAS_TEMP, DMEM_1CH_SIZE); + aEnvSetup1(aList++, (sourceReverbVol & 0x7F), rampReverb, rampLeft, rampRight); + aEnvSetup2(aList++, curVolLeft, curVolRight); switch (delaySide) { - case 1: - aEnvMixer(aList++, dmemSrc, aiBufLen, 0, 0, ((temp_a1 & 0x80) >> 7), + case HAAS_EFFECT_DELAY_LEFT: + aEnvMixer(aList++, dmemSrc, aiBufLen, 0, 0, ((sourceReverbVol & 0x80) >> 7), noteSub->bitField0.stereoStrongRight, noteSub->bitField0.stereoStrongLeft, 0x65B1C9E1, 0); break; - case 2: - aEnvMixer(aList++, dmemSrc, aiBufLen, 0, 0, ((temp_a1 & 0x80) >> 7), + + case HAAS_EFFECT_DELAY_RIGHT: + aEnvMixer(aList++, dmemSrc, aiBufLen, 0, 0, ((sourceReverbVol & 0x80) >> 7), noteSub->bitField0.stereoStrongRight, noteSub->bitField0.stereoStrongLeft, 0x9965C9E1, 0); break; - default: - aEnvMixer(aList++, dmemSrc, aiBufLen, 0, 0, ((temp_a1 & 0x80) >> 7), + + default: // HAAS_EFFECT_DELAY_NONE + aEnvMixer(aList++, dmemSrc, aiBufLen, 0, 0, ((sourceReverbVol & 0x80) >> 7), noteSub->bitField0.stereoStrongRight, noteSub->bitField0.stereoStrongLeft, 0x99B1C9E1, 0); break; } } else { - aEnvSetup1(aList++, (temp_a1 & 0x7F), var_a2, var_t0, var_a3); - aEnvSetup2(aList++, temp_t1, temp_t2); - aEnvMixer(aList++, dmemSrc, aiBufLen, 0, 0, ((temp_a1 & 0x80) >> 7), noteSub->bitField0.stereoStrongRight, - noteSub->bitField0.stereoStrongLeft, 0x99B1C9E1, 0); + aEnvSetup1(aList++, (sourceReverbVol & 0x7F), rampReverb, rampLeft, rampRight); + aEnvSetup2(aList++, curVolLeft, curVolRight); + aEnvMixer(aList++, dmemSrc, aiBufLen, 0, 0, ((sourceReverbVol & 0x80) >> 7), + noteSub->bitField0.stereoStrongRight, noteSub->bitField0.stereoStrongLeft, 0x99B1C9E1, 0); } return aList; } -Acmd* func_8000B98C(Acmd* aList, NoteSubEu* noteSub, NoteSynthesisState* synthState, s32 size, s32 flags, - s32 delaySide) { - u16 var_t0; - u8 var_a1; - u8 var_v1; - u16 temp; +/** + * The Haas Effect gives directionality to sound by applying a small (< 35ms) delay to either the left or right channel. + * The delay is small enough that the sound is still perceived as one sound, but the channel that is not delayed will + * reach our ear first and give a sense of directionality. The sound is directed towards the opposite side of the delay. + */ +Acmd* AudioSynth_ApplyHaasEffect(Acmd* aList, NoteSubEu* noteSub, NoteSynthesisState* synthState, s32 size, s32 flags, + s32 delaySide) { + u16 dmemDest; + u8 haasEffectDelaySize; + u8 prevHaasEffectDelaySize; + u16 pitch; switch (delaySide) { - case 1: - var_t0 = 0x990; - var_a1 = noteSub->leftDelaySize; + case HAAS_EFFECT_DELAY_LEFT: + dmemDest = DMEM_LEFT_CH; + haasEffectDelaySize = noteSub->leftDelaySize; + prevHaasEffectDelaySize = synthState->prevHaasEffectLeftDelaySize; synthState->prevHaasEffectRightDelaySize = 0; - var_v1 = synthState->prevHaasEffectLeftDelaySize; - synthState->prevHaasEffectLeftDelaySize = var_a1; + synthState->prevHaasEffectLeftDelaySize = haasEffectDelaySize; break; - case 2: - var_t0 = 0xB10; - var_a1 = noteSub->rightDelaySize; + case HAAS_EFFECT_DELAY_RIGHT: + dmemDest = DMEM_RIGHT_CH; + haasEffectDelaySize = noteSub->rightDelaySize; + prevHaasEffectDelaySize = synthState->prevHaasEffectRightDelaySize; + synthState->prevHaasEffectRightDelaySize = haasEffectDelaySize; synthState->prevHaasEffectLeftDelaySize = 0; - var_v1 = synthState->prevHaasEffectRightDelaySize; - synthState->prevHaasEffectRightDelaySize = var_a1; break; - default: + default: // HAAS_EFFECT_DELAY_NONE return aList; } - if (flags != 1) { - if (var_a1 != var_v1) { - temp = (((size << 0xF) / 2) - 1) / ((size + var_a1 - var_v1 - 2) / 2); - aSetBuffer(aList++, 0, 0x650, 0x450, size + var_a1 - var_v1); - aResampleZoh(aList++, temp, 0); + if (flags != A_INIT) { + if (haasEffectDelaySize != prevHaasEffectDelaySize) { + pitch = (((size << 0xF) / 2) - 1) / ((size + haasEffectDelaySize - prevHaasEffectDelaySize - 2) / 2); + aSetBuffer(aList++, 0, DMEM_HAAS_TEMP, DMEM_TEMP, size + haasEffectDelaySize - prevHaasEffectDelaySize); + aResampleZoh(aList++, pitch, 0); } else { - aDMEMMove(aList++, 0x650, 0x450, size); + aDMEMMove(aList++, DMEM_HAAS_TEMP, DMEM_TEMP, size); } - if (var_v1 != 0) { - aLoadBuffer(aList++, OS_K0_TO_PHYSICAL(synthState->synthesisBuffers->panSamplesBuffer), 0x650, - ALIGN16(var_v1)); - aDMEMMove(aList++, 0x450, var_v1 + 0x650, size + var_a1 - var_v1); + if (prevHaasEffectDelaySize != 0) { + aLoadBuffer(aList++, OS_K0_TO_PHYSICAL(synthState->synthesisBuffers->panSamplesBuffer), DMEM_HAAS_TEMP, + ALIGN16(prevHaasEffectDelaySize)); + aDMEMMove(aList++, DMEM_TEMP, prevHaasEffectDelaySize + DMEM_HAAS_TEMP, + size + haasEffectDelaySize - prevHaasEffectDelaySize); } else { - aDMEMMove(aList++, 0x450, 0x650, size + var_a1); + aDMEMMove(aList++, DMEM_TEMP, DMEM_HAAS_TEMP, size + haasEffectDelaySize); } } else { - aDMEMMove(aList++, 0x650, 0x450, size); - aClearBuffer(aList++, 0x650, var_a1); - aDMEMMove(aList++, 0x450, var_a1 + 0x650, size); - } - if (var_a1) { - aSaveBuffer(aList++, size + 0x650, OS_K0_TO_PHYSICAL(synthState->synthesisBuffers->panSamplesBuffer), - ALIGN16(var_a1)); + aDMEMMove(aList++, DMEM_HAAS_TEMP, DMEM_TEMP, size); + aClearBuffer(aList++, DMEM_HAAS_TEMP, haasEffectDelaySize); + aDMEMMove(aList++, DMEM_TEMP, haasEffectDelaySize + DMEM_HAAS_TEMP, size); } - aAddMixer(aList++, ALIGN64(size), 0x650, var_t0); + if (haasEffectDelaySize) { + aSaveBuffer(aList++, size + DMEM_HAAS_TEMP, OS_K0_TO_PHYSICAL(synthState->synthesisBuffers->panSamplesBuffer), + ALIGN16(haasEffectDelaySize)); + } + + aAddMixer(aList++, ALIGN64(size), DMEM_HAAS_TEMP, dmemDest); return aList; } diff --git a/src/audio/audio_thread.c b/src/audio/audio_thread.c index e7549306..ec7a79b9 100644 --- a/src/audio/audio_thread.c +++ b/src/audio/audio_thread.c @@ -39,7 +39,7 @@ static const char devstr12[] = "Undefined Port Command %d\n"; static const char devstr13[] = "specchg conjunction error (Msg:%d Cur:%d)\n"; static const char devstr14[] = "Error : Queue is not empty ( %x ) \n"; -void AudioThread_CreateNextAudioBuffer(s16 *samples, u32 num_samples) { +void AudioThread_CreateNextAudioBuffer(s16* samples, u32 num_samples) { static s32 gMaxAbiCmdCnt = 128; static SPTask* gWaitingAudioTask = NULL; s32 abiCmdCount; @@ -79,7 +79,7 @@ void AudioThread_CreateNextAudioBuffer(s16 *samples, u32 num_samples) { AudioThread_ProcessCmds(msg.data32); } - gCurAbiCmdBuffer = func_80009B64(gCurAbiCmdBuffer, &abiCmdCount, samples, num_samples); + AudioSynth_Update(gCurAbiCmdBuffer, &abiCmdCount, samples, num_samples); memcpy(gAiBuffers[gCurAiBuffIndex], samples, num_samples); gAudioRandom = osGetCount() * (gAudioRandom + gAudioTaskCountQ); @@ -163,7 +163,7 @@ SPTask* AudioThread_CreateTask() { while (MQ_GET_MESG(gThreadCmdProcQueue, &msg)) { AudioThread_ProcessCmds(msg); } - gCurAbiCmdBuffer = func_80009B64(gCurAbiCmdBuffer, &abiCmdCount, aiBuffer, gAiBuffLengths[aiBuffIndex]); + gCurAbiCmdBuffer = AudioSynth_Update(gCurAbiCmdBuffer, &abiCmdCount, aiBuffer, gAiBuffLengths[aiBuffIndex]); gAudioRandom = osGetCount() * (gAudioRandom + gAudioTaskCountQ); gAudioRandom = gAiBuffers[aiBuffIndex][gAudioTaskCountQ & 0xFF] + gAudioRandom; @@ -317,26 +317,17 @@ void AudioThread_QueueCmd(AudioCmd cmd) { } void AudioThread_QueueCmdF32(u32 opArgs, f32 val) { - AudioCmd cmd = { - .opArgs = opArgs, - .asFloat = val - }; + AudioCmd cmd = { .opArgs = opArgs, .asFloat = val }; AudioThread_QueueCmd(cmd); } void AudioThread_QueueCmdS32(u32 opArgs, u32 val) { - AudioCmd cmd = { - .opArgs = opArgs, - .asInt = val - }; + AudioCmd cmd = { .opArgs = opArgs, .asInt = val }; AudioThread_QueueCmd(cmd); } void AudioThread_QueueCmdS8(u32 opArgs, s8 val) { - AudioCmd cmd = { - .opArgs = opArgs, - .asSbyte = val - }; + AudioCmd cmd = { .opArgs = opArgs, .asSbyte = val }; AudioThread_QueueCmd(cmd); }