audio docs from the decomp

This commit is contained in:
Sonic Dreamcaster 2024-11-11 03:53:15 -03:00
parent 144db0e445
commit c238f8a493
5 changed files with 318 additions and 293 deletions

View File

@ -1029,8 +1029,8 @@ typedef struct {
#define SEQ_BYTE2(seqId) (((seqId) & (0xFF << 16)) >> 13 & 0xFFFF) #define SEQ_BYTE2(seqId) (((seqId) & (0xFF << 16)) >> 13 & 0xFFFF)
// audio_synthesis // audio_synthesis
void func_80008780(f32*, s32, f32*); void AudioSynth_HartleyTransform(f32*, s32, f32*);
Acmd* func_80009B64(Acmd* aList, s32* cmdCount, s16* aiBufStart, s32 aiBufLen); Acmd* AudioSynth_Update(Acmd* aList, s32* cmdCount, s16* aiBufStart, s32 aiBufLen);
// audio_effects // audio_effects
void Audio_SequencePlayerProcessSound(SequencePlayer* seqplayer); void Audio_SequencePlayerProcessSound(SequencePlayer* seqplayer);

View File

@ -222,26 +222,26 @@ sAudioResetMsg = 0x8015661C;
// functions // functions
func_800080C0 = 0x800080C0; AudioSynth_InitNextRingBuf = 0x800080C0;
func_80008364 = 0x80008364; AudioSynth_InverseDiscreteCosineTransform = 0x80008364;
func_80008780 = 0x80008780; AudioSynth_HartleyTransform = 0x80008780;
func_80009124 = 0x80009124; func_80009124 = 0x80009124;
func_80009504 = 0x80009504; func_80009504 = 0x80009504;
func_8000967C = 0x8000967C; func_8000967C = 0x8000967C;
func_800097A8 = 0x800097A8; func_800097A8 = 0x800097A8;
func_800098DC = 0x800098DC; AudioSynth_LoadRingBufferPart = 0x800098DC;
func_80009984 = 0x80009984; AudioSynth_SaveRingBufferPart = 0x80009984;
func_80009A2C = 0x80009A2C; AudioSynth_DisableSampleStates = 0x80009A2C;
func_80009AAC = 0x80009AAC; AudioSynth_SyncSampleStates = 0x80009AAC;
func_80009B64 = 0x80009B64; AudioSynth_Update = 0x80009B64;
func_80009D78 = 0x80009D78; AudioSynth_LoadReverbSamples = 0x80009D78;
func_8000A128 = 0x8000A128; AudioSynth_SaveReverbSamples = 0x8000A128;
func_8000A25C = 0x8000A25C; AudioSynth_DoOneAudioUpdate = 0x8000A25C;
func_8000A700 = 0x8000A700; AudioSynth_ProcessNote = 0x8000A700;
func_8000B3F0 = 0x8000B3F0; AudioSynth_LoadWaveSamples = 0x8000B3F0;
func_8000B480 = 0x8000B480; AudioSynth_FinalResample = 0x8000B480;
func_8000B51C = 0x8000B51C; AudioSynth_ProcessEnvelope = 0x8000B51C;
func_8000B98C = 0x8000B98C; AudioSynth_ApplyHaasEffect = 0x8000B98C;

View File

@ -2268,7 +2268,7 @@ void Audio_AnalyzeFrequencies(f32* buffer0, f32* buffer1, s32 length, f32* buffe
buff1half1 = buffer1; buff1half1 = buffer1;
// FFT buffer 1 using buffer 2 // FFT buffer 1 using buffer 2
func_80008780(buffer1, length, buffer2); AudioSynth_HartleyTransform(buffer1, length, buffer2);
// handle i = 0 case // handle i = 0 case
buff0fromStart[0] = buff1half1[0]; buff0fromStart[0] = buff1half1[0];

View File

@ -3,6 +3,22 @@
#include "audio/mixer.h" #include "audio/mixer.h"
#include "endianness.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 s32 D_80145D40; // unused
// all of these are part of the DFT-related function // 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 devstr8[] = "W->S\n";
static const char devstr9[] = "S-Resample Pitch %x (old %d -> delay %d)\n"; static const char devstr9[] = "S-Resample Pitch %x (old %d -> delay %d)\n";
void func_80009A2C(s32 updateIndex, s32 noteIndex); void AudioSynth_DisableSampleStates(s32 updateIndex, s32 noteIndex);
void func_80009AAC(s32 updateIndex); void AudioSynth_SyncSampleStates(s32 updateIndex);
Acmd* func_8000A700(s32 noteIndex, NoteSubEu* noteSub, NoteSynthesisState* synthState, s16* aiBuf, s32 aiBufLen, Acmd* AudioSynth_ProcessNote(s32 noteIndex, NoteSubEu* noteSub, NoteSynthesisState* synthState, s16* aiBuf, s32 aiBufLen,
Acmd* aList, s32 updateIndex); Acmd* aList, s32 updateIndex);
Acmd* func_8000A25C(s16* aiBuf, s32 aiBufLen, Acmd* aList, s32 updateIndex); Acmd* AudioSynth_DoOneAudioUpdate(s16* aiBuf, s32 aiBufLen, Acmd* aList, s32 updateIndex);
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);
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);
Acmd* func_80009D78(Acmd* aList, s32 aiBufLen, s16 reverbIndex, s16 updateIndex); Acmd* AudioSynth_LoadReverbSamples(Acmd* aList, s32 aiBufLen, s16 reverbIndex, s16 updateIndex);
Acmd* func_8000A128(Acmd* aList, s16 reverbIndex, s16 updateIndex); Acmd* AudioSynth_SaveReverbSamples(Acmd* aList, s16 reverbIndex, s16 updateIndex);
Acmd* func_8000B3F0(Acmd* aList, NoteSubEu* noteSub, NoteSynthesisState* synthState, s32 numSamplesToLoad); Acmd* AudioSynth_LoadWaveSamples(Acmd* aList, NoteSubEu* noteSub, NoteSynthesisState* synthState, s32 numSamplesToLoad);
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);
Acmd* func_8000B51C(Acmd* aList, NoteSubEu* noteSub, NoteSynthesisState* synthState, s32 aiBufLen, u16 dmemSrc, Acmd* AudioSynth_ProcessEnvelope(Acmd* aList, NoteSubEu* noteSub, NoteSynthesisState* synthState, s32 aiBufLen, u16 dmemSrc,
s32 delaySide, s32 flags); 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); s32 delaySide);
void func_800080C0(s32 sampleCount, s32 itemIndex, s32 reverbIndex) { void AudioSynth_InitNextRingBuf(s32 sampleCount, s32 itemIndex, s32 reverbIndex) {
ReverbRingBufferItem* ringItem; ReverbRingBufferItem* ringItem;
SynthesisReverb* reverb = &gSynthReverbs[reverbIndex]; SynthesisReverb* reverb = &gSynthReverbs[reverbIndex];
s32 temp_lo; s32 numSamples;
s32 temp_v1_3; s32 extraSamples;
s32 i; s32 i;
s32 j; s32 j;
s32 pad1; s32 pad1;
@ -69,26 +85,27 @@ void func_800080C0(s32 sampleCount, s32 itemIndex, s32 reverbIndex) {
reverb->rightRingBuf[i] = ringItem->toDownsampleRight[j]; 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 = &reverb->items[reverb->curFrame][itemIndex];
ringItem->lengthA = temp_lo * 2; numSamples = sampleCount / reverb->downsampleRate;
extraSamples = reverb->nextRingBufPos + numSamples - reverb->bufSizePerChan;
if (extraSamples < 0) {
ringItem->lengthA = numSamples * SAMPLE_SIZE;
ringItem->lengthB = 0; ringItem->lengthB = 0;
ringItem->startPos = reverb->nextRingBufPos; ringItem->startPos = reverb->nextRingBufPos;
reverb->nextRingBufPos += temp_lo; reverb->nextRingBufPos += numSamples;
} else { } else {
ringItem->lengthA = (temp_lo - temp_v1_3) * 2; ringItem->lengthA = (numSamples - extraSamples) * 2;
ringItem->lengthB = temp_v1_3 * 2; ringItem->lengthB = extraSamples * SAMPLE_SIZE;
ringItem->startPos = reverb->nextRingBufPos; ringItem->startPos = reverb->nextRingBufPos;
reverb->nextRingBufPos = temp_v1_3; reverb->nextRingBufPos = extraSamples;
} }
ringItem->numSamplesAfterDownsampling = temp_lo; ringItem->numSamplesAfterDownsampling = numSamples;
ringItem->chunkLen = sampleCount; 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 temp_ft0;
f32 var_fs0; f32 var_fs0;
f32* buff0fromStart; f32* buff0fromStart;
@ -146,7 +163,7 @@ void func_80008364(f32* buffer0, f32* buffer1, s32 length, f32* buffer2) {
} }
// FFT buffer 1 using buffer 2 // FFT buffer 1 using buffer 2
func_80008780(buffer1, length, buffer2); AudioSynth_HartleyTransform(buffer1, length, buffer2);
buff0fromStart = buffer0; buff0fromStart = buffer0;
buff0FromEnd = &buffer0[size - 1]; buff0FromEnd = &buffer0[size - 1];
@ -165,7 +182,7 @@ void func_80008364(f32* buffer0, f32* buffer1, s32 length, f32* buffer2) {
// https://decomp.me/scratch/8eyVg // https://decomp.me/scratch/8eyVg
#ifdef NON_MATCHING #ifdef NON_MATCHING
void func_80008780(f32* arg0, s32 arg1, f32* arg2) { void AudioSynth_HartleyTransform(f32* arg0, s32 arg1, f32* arg2) {
s32 length; s32 length;
s32 spD0; s32 spD0;
s32 spCC; s32 spCC;
@ -366,7 +383,7 @@ void func_80008780(f32* arg0, s32 arg1, f32* arg2) {
} }
} }
#else #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 #endif
// https://decomp.me/scratch/mYlns // https://decomp.me/scratch/mYlns
@ -376,6 +393,7 @@ void func_80009124(s16** arg0) {
s32 temp_a0; s32 temp_a0;
u8 temp_s0; u8 temp_s0;
u8 temp_s1; u8 temp_s1;
u8 temp_u1;
s32 temp_t5_4; s32 temp_t5_4;
s32 temp_v0; s32 temp_v0;
u8 temp_v1; u8 temp_v1;
@ -386,35 +404,38 @@ void func_80009124(s16** arg0) {
u32 var_t3; u32 var_t3;
s32 i; s32 i;
s32 j; s32 j;
s16 new_var2;
var_a1 = *arg0; var_a1 = *arg0;
for (i = 255; i >= 0; i--) { for (i = 255; i >= 0; i--) {
D_80145D48[i] = 0.0f; D_80145D48[i] = 0.0f;
} }
var_t3 = *var_a1++ << 0x10; temp_v0 = *var_a1++;
var_t3 |= *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; temp_s0 = var_t3 >> 0x18;
var_v1 = var_t2;
var_t3 <<= 8; var_t3 <<= 8;
temp_v0 = ((temp_s0 >> 4) & 0xF); temp_v1 = ((temp_s0 >> 4) & 0xF);
temp_a0 = temp_s0 & 0xF; temp_a0 = temp_s0 & 0xF;
if (((temp_s0 >> 4) & 0xF) == 0) { if (temp_v1 == 0) {
continue; continue;
} }
switch (temp_v0) { switch (temp_v1) {
case 1: case 1:
while (true) { while (true) {
var_s0 = *var_a1++; var_s0 = *var_a1++;
for (var_s1 = 0; var_s1 < 4; var_s1++) { for (var_s1 = 0; var_s1 < 4; var_s1++) {
temp_s1 = (var_s0 >> 0xC) & 0xF; temp_u1 = (var_s0 >> 0xC) & 0xF;
var_s0 <<= 4; var_s0 <<= 4;
D_80145D48[var_v1++] = ((temp_s1 & 7) - 4) << temp_a0; D_80145D48[var_v1++] = ((temp_u1 & 7) - 4) << temp_a0;
if (temp_u1 >= 8) {
if (temp_s1 >= 8) {
goto case_1_break; goto case_1_break;
} }
} }
@ -422,49 +443,47 @@ void func_80009124(s16** arg0) {
case_1_break: case_1_break:
break; break;
case 2: case 2:
var_s1 = -1; for (var_s1 = 0; var_s1 < 16; var_s1++) {
while (++var_s1 < 16) {
var_s0 = *var_a1++; var_s0 = *var_a1++;
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
temp_s1 = (var_s0 >> 0xC) & 0xF; temp_u1 = (var_s0 >> 0xC) & 0xF;
var_s0 <<= 4; var_s0 <<= 4;
D_80145D48[var_v1++] = (temp_s1 - 8) << temp_a0; D_80145D48[var_v1++] = (temp_u1 - 8) << temp_a0;
} }
} }
break; break;
case 6: case 6:
while (true) { while (true) {
var_s0 = *var_a1++; var_s0 = *var_a1++;
temp_s1 = (var_s0 >> 8) & 0xFF; temp_u1 = (var_s0 >> 8) & 0xFF;
temp_t5_4 = temp_u1 >> 6;
D_80145D48[var_v1] = ((temp_s1 & 0x3F) - 0x20) << temp_a0; D_80145D48[var_v1] = ((temp_u1 & 0x3F) - 0x20) << temp_a0;
if (temp_s1 >> 6 == 0) { if (temp_t5_4 == 0) {
break; break;
} }
var_v1 += temp_s1 >> 6; var_v1 += temp_t5_4;
temp_s1 = var_s0 & 0xFF; temp_u1 = var_s0 & 0xFF;
D_80145D48[var_v1] = ((temp_s1 & 0x3F) - 0x20) << temp_a0; temp_t5_4 = temp_u1 >> 6;
if (temp_s1 >> 6 == 0) { D_80145D48[var_v1] = ((temp_u1 & 0x3F) - 0x20) << temp_a0;
if (temp_t5_4 == 0) {
break; break;
} }
var_v1 += temp_s1 >> 6; var_v1 += temp_t5_4;
} }
break; break;
case 3: case 3:
while (true) { while (true) {
var_s0 = *var_a1++; 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_u1 >= 0x80) {
if (temp_s1 >= 0x80) {
break; break;
} }
temp_s1 = var_s0 & 0xFF; temp_u1 = var_s0 & 0xFF;
D_80145D48[var_v1++] = ((temp_s1 & 0x7F) - 0x40) << temp_a0; D_80145D48[var_v1++] = ((temp_u1 & 0x7F) - 0x40) << temp_a0;
if (temp_s1 >= 0x80) { if (temp_u1 >= 0x80) {
break; break;
} }
} }
@ -483,8 +502,9 @@ void func_80009124(s16** arg0) {
case 5: case 5:
while (true) { while (true) {
var_s0 = *var_a1++; var_s0 = *var_a1++;
temp_t5_4 = var_s0 >> 0xF;
D_80145D48[var_v1] = ((var_s0 & 0x7FFF) - 0x4000) << temp_a0; D_80145D48[var_v1] = ((var_s0 & 0x7FFF) - 0x4000) << temp_a0;
if ((var_s0 >> 0xF) == 1) { if (temp_t5_4 == 1) {
break; break;
} }
var_v1++; var_v1++;
@ -513,7 +533,7 @@ void func_80009504(s16* arg0, UnkStruct_800097A8* arg1) {
arg1->unk18 -= 0x1000; 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++) { for (i = 0; i < 256; i++) {
if (D_80145D48[i] > 32767.0f) { 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* pad2;
SampleDma* sp1C; SampleDma* sp1C;
if (flags == 1) { if (flags == A_INIT) {
arg3->unk_0 = (s16*) sample->sampleAddr; arg3->unk_0 = (s16*) sample->sampleAddr;
arg3->unk_4 = 0; arg3->unk_4 = 0;
arg3->unk_8 = 0; arg3->unk_8 = 0;
@ -580,6 +600,7 @@ u8* func_800097A8(Sample* sample, s32 length, u32 flags, UnkStruct_800097A8* arg
if (1) {} //! FAKE if (1) {} //! FAKE
sp1C->ttl = 2; sp1C->ttl = 2;
// @port: (uintptr_t)
sp1C->devAddr = (uintptr_t) sample->sampleAddr; sp1C->devAddr = (uintptr_t) sample->sampleAddr;
sp1C->sizeUnused = length * 2; sp1C->sizeUnused = length * 2;
pad2 = arg3->unk_14; pad2 = arg3->unk_14;
@ -588,19 +609,21 @@ u8* func_800097A8(Sample* sample, s32 length, u32 flags, UnkStruct_800097A8* arg
return sp1C->ramAddr; 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].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; 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, 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; return aList;
} }
void func_80009A2C(s32 updateIndex, s32 noteIndex) { void AudioSynth_DisableSampleStates(s32 updateIndex, s32 noteIndex) {
NoteSubEu* noteSubEu; NoteSubEu* noteSubEu;
s32 i; s32 i;
@ -613,24 +636,27 @@ void func_80009A2C(s32 updateIndex, s32 noteIndex) {
} }
} }
void func_80009AAC(s32 updateIndex) { /**
NoteSubEu* subEu; * Sync the sample states between the notes and the list
NoteSubEu* subEu2; */
void AudioSynth_SyncSampleStates(s32 updateIndex) {
NoteSubEu* noteSampleState;
NoteSubEu* sampleState;
s32 i; s32 i;
for (i = 0; i < gNumNotes; i++) { for (i = 0; i < gNumNotes; i++) {
subEu = &gNotes[i].noteSubEu; noteSampleState = &gNotes[i].noteSubEu;
subEu2 = &gNoteSubsEu[gNumNotes * updateIndex + i]; sampleState = &gNoteSubsEu[gNumNotes * updateIndex + i];
if (subEu->bitField0.enabled) { if (noteSampleState->bitField0.enabled) {
*subEu2 = *subEu; *sampleState = *noteSampleState;
subEu->bitField0.needsInit = false; noteSampleState->bitField0.needsInit = false;
} else { } 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; Acmd* aCmdPtr;
s32* aiBufPtr; s32* aiBufPtr;
s32 chunkLen; s32 chunkLen;
@ -640,10 +666,12 @@ Acmd* func_80009B64(Acmd* aList, s32* cmdCount, s16* aiBufStart, s32 aiBufLen) {
aCmdPtr = aList; aCmdPtr = aList;
for (i = gAudioBufferParams.ticksPerUpdate; i > 0; i--) { for (i = gAudioBufferParams.ticksPerUpdate; i > 0; i--) {
AudioSeq_ProcessSequences(i - 1); AudioSeq_ProcessSequences(i - 1);
func_80009AAC(gAudioBufferParams.ticksPerUpdate - i); AudioSynth_SyncSampleStates(gAudioBufferParams.ticksPerUpdate - i);
} }
aiBufPtr = (s32*) aiBufStart; 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--) { for (i = gAudioBufferParams.ticksPerUpdate - 1; i > 0; i--) {
if (i == 1) { if (i == 1) {
chunkLen = aiBufLen; chunkLen = aiBufLen;
@ -657,11 +685,12 @@ Acmd* func_80009B64(Acmd* aList, s32* cmdCount, s16* aiBufStart, s32 aiBufLen) {
for (j = 0; j < gNumSynthReverbs; j++) { for (j = 0; j < gNumSynthReverbs; j++) {
if (gSynthReverbs[j].useReverb) { 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; aiBufLen -= chunkLen;
aiBufPtr += chunkLen; aiBufPtr += chunkLen;
} }
@ -678,59 +707,61 @@ Acmd* func_80009B64(Acmd* aList, s32* cmdCount, s16* aiBufStart, s32 aiBufLen) {
return aCmdPtr; 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]; ReverbRingBufferItem* sp64 = &gSynthReverbs[reverbIndex].items[gSynthReverbs[reverbIndex].curFrame][updateIndex];
s16 sp62; s16 sp62;
s16 sp60; s16 sp60;
aClearBuffer(aList++, 0xC90, 0x300); aClearBuffer(aList++, DMEM_WET_LEFT_CH, DMEM_2CH_SIZE);
if (gSynthReverbs[reverbIndex].downsampleRate == 1) { 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) { 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); aAddMixer(aList++, 0x300, DMEM_WET_LEFT_CH, DMEM_LEFT_CH);
aMix(aList++, 0x30, gSynthReverbs[reverbIndex].decayRatio + 0x8000, 0xC90, 0xC90); aMix(aList++, 0x30, gSynthReverbs[reverbIndex].decayRatio + 0x8000, DMEM_WET_LEFT_CH, DMEM_WET_LEFT_CH);
} else { } else {
sp62 = (sp64->startPos & 7) * 2; sp62 = (sp64->startPos & 7) * 2;
sp60 = ALIGN16(sp62 + sp64->lengthA); 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) { 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, aResample(aList++, gSynthReverbs[reverbIndex].resampleFlags, gSynthReverbs[reverbIndex].unk_0A,
OS_K0_TO_PHYSICAL(gSynthReverbs[reverbIndex].unk_30)); 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, aResample(aList++, gSynthReverbs[reverbIndex].resampleFlags, gSynthReverbs[reverbIndex].unk_0A,
OS_K0_TO_PHYSICAL(gSynthReverbs[reverbIndex].unk_34)); OS_K0_TO_PHYSICAL(gSynthReverbs[reverbIndex].unk_34));
aAddMixer(aList++, 0x300, 0xC90, 0x990); aAddMixer(aList++, 0x300, DMEM_WET_LEFT_CH, DMEM_LEFT_CH);
aMix(aList++, 0x30, gSynthReverbs[reverbIndex].decayRatio + 0x8000, 0xC90, 0xC90); aMix(aList++, 0x30, gSynthReverbs[reverbIndex].decayRatio + 0x8000, DMEM_WET_LEFT_CH, DMEM_WET_LEFT_CH);
} }
if ((gSynthReverbs[reverbIndex].leakRtL != 0) || (gSynthReverbs[reverbIndex].leakLtR != 0)) { if ((gSynthReverbs[reverbIndex].leakRtL != 0) || (gSynthReverbs[reverbIndex].leakLtR != 0)) {
aDMEMMove(aList++, 0xC90, 0x470, 0x180); aDMEMMove(aList++, DMEM_WET_LEFT_CH, 0x470, DMEM_1CH_SIZE);
aMix(aList++, 0x18, gSynthReverbs[reverbIndex].leakRtL, 0xE10, 0xC90); aMix(aList++, DMEM_1CH_SIZE >> 4, gSynthReverbs[reverbIndex].leakRtL, DMEM_WET_RIGHT_CH, DMEM_WET_LEFT_CH);
aMix(aList++, 0x18, gSynthReverbs[reverbIndex].leakLtR, 0x470, 0xE10); aMix(aList++, DMEM_1CH_SIZE >> 4, gSynthReverbs[reverbIndex].leakLtR, 0x470, DMEM_WET_RIGHT_CH);
} }
return aList; return aList;
} }
Acmd* func_8000A128(Acmd* aList, s16 reverbIndex, s16 updateIndex) { Acmd* AudioSynth_SaveReverbSamples(Acmd* aList, s16 reverbIndex, s16 updateIndex) {
ReverbRingBufferItem* sp24; ReverbRingBufferItem* sp24;
sp24 = &gSynthReverbs[reverbIndex].items[gSynthReverbs[reverbIndex].curFrame][updateIndex]; sp24 = &gSynthReverbs[reverbIndex].items[gSynthReverbs[reverbIndex].curFrame][updateIndex];
switch (gSynthReverbs[reverbIndex].downsampleRate) { switch (gSynthReverbs[reverbIndex].downsampleRate) {
case 1: 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) { 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; break;
default: default:
aSaveBuffer(aList++, 0xC90, aSaveBuffer(aList++, DMEM_WET_LEFT_CH,
OS_K0_TO_PHYSICAL(gSynthReverbs[reverbIndex] OS_K0_TO_PHYSICAL(gSynthReverbs[reverbIndex]
.items[gSynthReverbs[reverbIndex].curFrame][updateIndex] .items[gSynthReverbs[reverbIndex].curFrame][updateIndex]
.toDownsampleLeft), .toDownsampleLeft),
@ -742,19 +773,19 @@ Acmd* func_8000A128(Acmd* aList, s16 reverbIndex, s16 updateIndex) {
return aList; 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]; u8 sp84[0x3C];
NoteSubEu* temp_v0; NoteSubEu* temp_v0;
s16 var_s2; s16 count;
s16 i = 0; s16 i;
s32 j = 0; s32 j;
var_s2 = 0; count = 0;
if (gNumSynthReverbs == 0) { if (gNumSynthReverbs == 0) {
if (gSynthReverbs[i].useReverb) {} // fake? if (gSynthReverbs[i].useReverb) {} // fake?
for (j = 0; j < gNumNotes; j++) { for (j = 0; j < gNumNotes; j++) {
if (gNoteSubsEu[gNumNotes * updateIndex + j].bitField0.enabled) { if (gNoteSubsEu[gNumNotes * updateIndex + j].bitField0.enabled) {
sp84[var_s2++] = j; sp84[count++] = j;
} }
} }
} else { } else {
@ -762,64 +793,57 @@ Acmd* func_8000A25C(s16* aiBuf, s32 aiBufLen, Acmd* aList, s32 updateIndex) {
for (j = 0; j < gNumNotes; j++) { for (j = 0; j < gNumNotes; j++) {
temp_v0 = &gNoteSubsEu[gNumNotes * updateIndex + j]; temp_v0 = &gNoteSubsEu[gNumNotes * updateIndex + j];
if (temp_v0->bitField0.enabled && (temp_v0->bitField1.reverbIndex == i)) { if (temp_v0->bitField0.enabled && (temp_v0->bitField1.reverbIndex == i)) {
sp84[var_s2++] = j; sp84[count++] = j;
} }
} }
} }
for (j = 0; j < gNumNotes; j++) { for (j = 0; j < gNumNotes; j++) {
temp_v0 = &gNoteSubsEu[gNumNotes * updateIndex + j]; temp_v0 = &gNoteSubsEu[gNumNotes * updateIndex + j];
if (temp_v0->bitField0.enabled && (temp_v0->bitField1.reverbIndex >= gNumSynthReverbs)) { 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; j = 0;
for (i = 0; i < gNumSynthReverbs; i++) { for (i = 0; i < gNumSynthReverbs; i++) {
D_8014C1B2 = gSynthReverbs[i].useReverb; D_8014C1B2 = gSynthReverbs[i].useReverb;
if (D_8014C1B2) { 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) { if (i != gNoteSubsEu[updateIndex * gNumNotes + sp84[j]].bitField1.reverbIndex) {
break; break;
} }
aList = func_8000A700(sp84[j], &gNoteSubsEu[updateIndex * gNumNotes + sp84[j]], aList = AudioSynth_ProcessNote(sp84[j], &gNoteSubsEu[updateIndex * gNumNotes + sp84[j]],
&gNotes[sp84[j]].synthesisState, aiBuf, aiBufLen, aList, updateIndex); &gNotes[sp84[j]].synthesisState, aiBuf, aiBufLen, aList, updateIndex);
j++; j++;
} }
if (gSynthReverbs[i].useReverb) { if (gSynthReverbs[i].useReverb) {
aList = func_8000A128(aList, i, updateIndex); aList = AudioSynth_SaveReverbSamples(aList, i, updateIndex);
} }
} }
while (j < var_s2) { while (j < count) {
aList = func_8000A700(sp84[j], &gNoteSubsEu[updateIndex * gNumNotes + sp84[j]], &gNotes[sp84[j]].synthesisState, aList = AudioSynth_ProcessNote(sp84[j], &gNoteSubsEu[updateIndex * gNumNotes + sp84[j]],
aiBuf, aiBufLen, aList, updateIndex); &gNotes[sp84[j]].synthesisState, aiBuf, aiBufLen, aList, updateIndex);
j++; j++;
} }
j = aiBufLen * 2; j = aiBufLen * 2;
aSetBuffer(aList++, 0, 0, 0x450, j); aSetBuffer(aList++, 0, 0, DMEM_TEMP, j);
aInterleave(aList++, 0, 0x990, 0xB10, 0); aInterleave(aList++, 0, DMEM_LEFT_CH, DMEM_RIGHT_CH, 0);
aSaveBuffer(aList++, 0x450, OS_K0_TO_PHYSICAL(aiBuf), j * 2); aSaveBuffer(aList++, DMEM_TEMP, OS_K0_TO_PHYSICAL(aiBuf), j * 2);
return aList; return aList;
} }
// https://decomp.me/scratch/RgX4r // https://decomp.me/scratch/RgX4r
#ifdef NON_MATCHING #ifdef NON_MATCHING
Acmd* func_8000A700( Acmd* AudioSynth_ProcessNote(s32 noteIndex, NoteSubEu* noteSub, NoteSynthesisState* synthState, s16* aiBuf, s32 aiBufLen,
s32 noteIndex, Acmd* aList, s32 updateIndex) {
NoteSubEu* noteSub,
NoteSynthesisState* synthState,
s16* aiBuf,
s32 aiBufLen,
Acmd* aList,
s32 updateIndex
) {
s32 pad11C; s32 pad11C;
s32 pad118; s32 pad118;
s32 pad114; s32 pad114;
@ -921,7 +945,7 @@ Acmd* func_8000A700(
} }
synthState->numParts = numParts; synthState->numParts = numParts;
if (noteSub->bitField1.isSyntheticWave) { if (noteSub->bitField1.isSyntheticWave) {
aList = func_8000B3F0(aList, noteSub, synthState, numSamplesToLoad); aList = AudioSynth_LoadWaveSamples(aList, noteSub, synthState, numSamplesToLoad);
noteSamplesDmemAddrBeforeResampling = (synthState->samplePosInt * ((char) 2)) + 0x5F0; noteSamplesDmemAddrBeforeResampling = (synthState->samplePosInt * ((char) 2)) + 0x5F0;
synthState->samplePosInt += numSamplesToLoad; synthState->samplePosInt += numSamplesToLoad;
} else { } else {
@ -1006,11 +1030,9 @@ Acmd* func_8000A700(
break; break;
case 2: case 2:
temp = func_800097A8( temp = func_800097A8(bookSample, numSamplesToLoadAdj, flags,
bookSample, numSamplesToLoadAdj, flags, &synthState->synthesisBuffers->unk_40 &synthState->synthesisBuffers->unk_40);
); if (0) {}
if (0) {
}
aLoadBuffer(aList++, OS_K0_TO_PHYSICAL(temp), 0x5F0, (numSamplesToLoadAdj + 0x10) * 2); aLoadBuffer(aList++, OS_K0_TO_PHYSICAL(temp), 0x5F0, (numSamplesToLoadAdj + 0x10) * 2);
flags = 0; flags = 0;
skipBytes = 0; skipBytes = 0;
@ -1022,8 +1044,7 @@ Acmd* func_8000A700(
aligned = ALIGN16((nFramesToDecode * frameSize) + 0x10); aligned = ALIGN16((nFramesToDecode * frameSize) + 0x10);
addr = 0x990 - aligned; addr = 0x990 - aligned;
if (nFramesToDecode != 0) { if (nFramesToDecode != 0) {
if (1) { if (1) {}
}
frameIndex = (synthState->samplePosInt + skipInitialSamples - nFirstFrameSamplesToIgnore) / 16; frameIndex = (synthState->samplePosInt + skipInitialSamples - nFirstFrameSamplesToIgnore) / 16;
sampleDataOffset = frameIndex * frameSize; sampleDataOffset = frameIndex * frameSize;
if (bookSample->medium == 0) { if (bookSample->medium == 0) {
@ -1068,24 +1089,20 @@ Acmd* func_8000A700(
align2 = ALIGN16(dmemUncompressedAddrOffset1 + 0x10); align2 = ALIGN16(dmemUncompressedAddrOffset1 + 0x10);
switch (bookSample->codec) { switch (bookSample->codec) {
case 0: case 0:
aSetBuffer( aSetBuffer(aList++, 0, addr + sampleDataChunkAlignPad, align2 + 0x5F0,
aList++, 0, addr + sampleDataChunkAlignPad, align2 + 0x5F0, numSamplesToDecode * 2 numSamplesToDecode * 2);
);
aADPCMdec(aList++, flags, OS_K0_TO_PHYSICAL(synthState->synthesisBuffers)); aADPCMdec(aList++, flags, OS_K0_TO_PHYSICAL(synthState->synthesisBuffers));
break; break;
case 1: case 1:
aSetBuffer( aSetBuffer(aList++, 0, addr + sampleDataChunkAlignPad, align2 + 0x5F0,
aList++, 0, addr + sampleDataChunkAlignPad, align2 + 0x5F0, numSamplesToDecode * 2 numSamplesToDecode * 2);
);
aS8Dec(aList++, flags, OS_K0_TO_PHYSICAL(synthState->synthesisBuffers)); aS8Dec(aList++, flags, OS_K0_TO_PHYSICAL(synthState->synthesisBuffers));
break; break;
} }
aDMEMMove( aDMEMMove(aList++, 0x5F0 + align2 + (nFirstFrameSamplesToIgnore * 2),
aList++, 0x5F0 + align2 + (nFirstFrameSamplesToIgnore * 2), 0x5F0 + dmemUncompressedAddrOffset1, 0x5F0 + dmemUncompressedAddrOffset1, numSamplesInThisIteration * 2);
numSamplesInThisIteration * 2
);
} }
numSamplesProcessed += numSamplesInThisIteration; numSamplesProcessed += numSamplesInThisIteration;
@ -1113,12 +1130,11 @@ Acmd* func_8000A700(
flags = 0; flags = 0;
if (sampleFinished) { if (sampleFinished) {
aClearBuffer( aClearBuffer(aList++, dmemUncompressedAddrOffset1 + 0x5F0,
aList++, dmemUncompressedAddrOffset1 + 0x5F0, (numSamplesToLoadAdj - numSamplesProcessed) * 2 (numSamplesToLoadAdj - numSamplesProcessed) * 2);
);
noteSub->bitField0.finished = 1; noteSub->bitField0.finished = 1;
note->noteSubEu.bitField0.finished = 1; note->noteSubEu.bitField0.finished = 1;
func_80009A2C(updateIndex, noteIndex); AudioSynth_DisableSampleStates(updateIndex, noteIndex);
break; break;
} }
if (loopToPoint != 0) { if (loopToPoint != 0) {
@ -1141,17 +1157,14 @@ Acmd* func_8000A700(
resampledTempLen = numSamplesToLoadAdj; resampledTempLen = numSamplesToLoadAdj;
noteSamplesDmemAddrBeforeResampling = 0x470; noteSamplesDmemAddrBeforeResampling = 0x470;
if (noteSub->bitField0.finished) { if (noteSub->bitField0.finished) {
aClearBuffer( aClearBuffer(aList++, resampledTempLen + noteSamplesDmemAddrBeforeResampling,
aList++, resampledTempLen + noteSamplesDmemAddrBeforeResampling, numSamplesToLoadAdj + 0x10);
numSamplesToLoadAdj + 0x10
);
} }
break; break;
case 1: case 1:
aInterl( aInterl(aList++, skipBytes + 0x5F0, resampledTempLen + 0x470,
aList++, skipBytes + 0x5F0, resampledTempLen + 0x470, ALIGN8(numSamplesToLoadAdj / 2) ALIGN8(numSamplesToLoadAdj / 2));
);
break; break;
} }
@ -1169,9 +1182,8 @@ Acmd* func_8000A700(
noteSub->bitField0.needsInit = 0; noteSub->bitField0.needsInit = 0;
} }
flags = sp56 | flags; flags = sp56 | flags;
aList = func_8000B480( aList = AudioSynth_FinalResample(aList, synthState, aiBufLen * 2, resampleRateFixedPoint, noteSamplesDmemAddrBeforeResampling,
aList, synthState, aiBufLen * 2, resampleRateFixedPoint, noteSamplesDmemAddrBeforeResampling, flags flags);
);
if (flags & 1) { if (flags & 1) {
flags = 1; flags = 1;
} }
@ -1192,171 +1204,193 @@ Acmd* func_8000A700(
} else { } else {
delaySide = 0; 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 (noteSub->bitField0.usesHeadsetPanEffects) {
if (!(flags & 1)) { if (!(flags & 1)) {
flags = 0; flags = 0;
} }
aList = func_8000B98C(aList, noteSub, synthState, aiBufLen * 2, flags, delaySide); aList = AudioSynth_ApplyHaasEffect(aList, noteSub, synthState, aiBufLen * 2, flags, delaySide);
} }
return aList; return aList;
} }
#else #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 #endif
Acmd* func_8000B3F0(Acmd* aList, NoteSubEu* noteSub, NoteSynthesisState* synthState, s32 numSamplesToLoad) { Acmd* AudioSynth_LoadWaveSamples(Acmd* aList, NoteSubEu* noteSub, NoteSynthesisState* synthState,
s32 temp_v1; s32 numSamplesToLoad) {
s32 numSamplesAvail;
s32 numDuplicates;
aLoadBuffer(aList++, OS_K0_TO_PHYSICAL(noteSub->waveSampleAddr), 0x5F0, 0x80); aLoadBuffer(aList++, OS_K0_TO_PHYSICAL(noteSub->waveSampleAddr), DMEM_UNCOMPRESSED_NOTE,
synthState->samplePosInt &= 0x3F; WAVE_SAMPLE_COUNT * SAMPLE_SIZE);
temp_v1 = 0x40 - synthState->samplePosInt;
if (temp_v1 < numSamplesToLoad) { // Offset in the WAVE_SAMPLE_COUNT samples of gWaveSamples to start processing the wave for continuity
if ((((numSamplesToLoad - temp_v1) + 0x3F) / 64) != 0) { synthState->samplePosInt = (u32) synthState->samplePosInt % WAVE_SAMPLE_COUNT;
aDuplicate(aList++, ((numSamplesToLoad - temp_v1) + 0x3F) / 64, 0x5F0, 0x670); // 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; 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) { if (pitch == 0) {
aClearBuffer(aList++, 0x450, size); aClearBuffer(aList++, DMEM_TEMP, size);
} else { } 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)); aResample(aList++, resampleFlags, pitch, OS_K0_TO_PHYSICAL(synthState->synthesisBuffers->finalResampleState));
} }
return aList; return aList;
} }
Acmd* func_8000B51C(Acmd* aList, NoteSubEu* noteSub, NoteSynthesisState* synthState, s32 aiBufLen, u16 dmemSrc, Acmd* AudioSynth_ProcessEnvelope(Acmd* aList, NoteSubEu* noteSub, NoteSynthesisState* synthState, s32 aiBufLen,
s32 delaySide, s32 flags) { u16 dmemSrc, s32 delaySide, s32 flags) {
s16 var_a2; s16 rampReverb;
s16 var_a3; s16 rampRight;
s16 var_t0; s16 rampLeft;
u16 temp_t7; u16 panVolLeft;
u16 temp_t9; u16 panVolRight;
u16 temp_t1; u16 curVolLeft;
u16 temp_t2; u16 curVolRight;
s32 temp_a1; s32 sourceReverbVol;
s32 temp = 0; s32 temp = 0;
temp_t1 = synthState->curVolLeft; curVolLeft = synthState->curVolLeft;
temp_t2 = synthState->curVolRight; curVolRight = synthState->curVolRight;
temp_t7 = noteSub->panVolLeft; panVolLeft = noteSub->panVolLeft;
temp_t9 = noteSub->panVolRight; panVolRight = noteSub->panVolRight;
temp_t7 <<= 4; panVolLeft <<= 4;
temp_t9 <<= 4; panVolRight <<= 4;
if (temp_t7 != temp_t1) { if (panVolLeft != curVolLeft) {
var_t0 = (temp_t7 - temp_t1) / (aiBufLen >> 3); rampLeft = (panVolLeft - curVolLeft) / (aiBufLen >> 3);
} else { } else {
var_t0 = 0; rampLeft = 0;
} }
if (temp_t9 != temp_t2) { if (panVolRight != curVolRight) {
var_a3 = (temp_t9 - temp_t2) / (aiBufLen >> 3); rampRight = (panVolRight - curVolRight) / (aiBufLen >> 3);
} else { } else {
var_a3 = 0; rampRight = 0;
} }
temp_a1 = synthState->reverbVol; sourceReverbVol = synthState->reverbVol;
if (noteSub->reverb != temp_a1) { if (noteSub->reverb != sourceReverbVol) {
temp = (((noteSub->reverb & 0x7F) - (temp_a1 & 0x7F)) << 8); temp = (((noteSub->reverb & 0x7F) - (sourceReverbVol & 0x7F)) << 8);
var_a2 = temp / (aiBufLen >> 3); rampReverb = temp / (aiBufLen >> 3);
synthState->reverbVol = noteSub->reverb; synthState->reverbVol = noteSub->reverb;
} else { } else {
var_a2 = 0; rampReverb = 0;
} }
synthState->curVolLeft = temp_t1 + (var_t0 * (aiBufLen >> 3)); synthState->curVolLeft = curVolLeft + (rampLeft * (aiBufLen >> 3));
synthState->curVolRight = temp_t2 + (var_a3 * (aiBufLen >> 3)); synthState->curVolRight = curVolRight + (rampRight * (aiBufLen >> 3));
if (noteSub->bitField0.usesHeadsetPanEffects) { if (noteSub->bitField0.usesHeadsetPanEffects) {
aClearBuffer(aList++, 0x650, 0x180); aClearBuffer(aList++, DMEM_HAAS_TEMP, DMEM_1CH_SIZE);
aEnvSetup1(aList++, (temp_a1 & 0x7F), var_a2, var_t0, var_a3); aEnvSetup1(aList++, (sourceReverbVol & 0x7F), rampReverb, rampLeft, rampRight);
aEnvSetup2(aList++, temp_t1, temp_t2); aEnvSetup2(aList++, curVolLeft, curVolRight);
switch (delaySide) { switch (delaySide) {
case 1: case HAAS_EFFECT_DELAY_LEFT:
aEnvMixer(aList++, dmemSrc, aiBufLen, 0, 0, ((temp_a1 & 0x80) >> 7), aEnvMixer(aList++, dmemSrc, aiBufLen, 0, 0, ((sourceReverbVol & 0x80) >> 7),
noteSub->bitField0.stereoStrongRight, noteSub->bitField0.stereoStrongLeft, 0x65B1C9E1, 0); noteSub->bitField0.stereoStrongRight, noteSub->bitField0.stereoStrongLeft, 0x65B1C9E1, 0);
break; 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); noteSub->bitField0.stereoStrongRight, noteSub->bitField0.stereoStrongLeft, 0x9965C9E1, 0);
break; 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); noteSub->bitField0.stereoStrongRight, noteSub->bitField0.stereoStrongLeft, 0x99B1C9E1, 0);
break; break;
} }
} else { } else {
aEnvSetup1(aList++, (temp_a1 & 0x7F), var_a2, var_t0, var_a3); aEnvSetup1(aList++, (sourceReverbVol & 0x7F), rampReverb, rampLeft, rampRight);
aEnvSetup2(aList++, temp_t1, temp_t2); aEnvSetup2(aList++, curVolLeft, curVolRight);
aEnvMixer(aList++, dmemSrc, aiBufLen, 0, 0, ((temp_a1 & 0x80) >> 7), noteSub->bitField0.stereoStrongRight, aEnvMixer(aList++, dmemSrc, aiBufLen, 0, 0, ((sourceReverbVol & 0x80) >> 7),
noteSub->bitField0.stereoStrongLeft, 0x99B1C9E1, 0); noteSub->bitField0.stereoStrongRight, noteSub->bitField0.stereoStrongLeft, 0x99B1C9E1, 0);
} }
return aList; return aList;
} }
Acmd* func_8000B98C(Acmd* aList, NoteSubEu* noteSub, NoteSynthesisState* synthState, s32 size, s32 flags, /**
* 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) { s32 delaySide) {
u16 var_t0; u16 dmemDest;
u8 var_a1; u8 haasEffectDelaySize;
u8 var_v1; u8 prevHaasEffectDelaySize;
u16 temp; u16 pitch;
switch (delaySide) { switch (delaySide) {
case 1: case HAAS_EFFECT_DELAY_LEFT:
var_t0 = 0x990; dmemDest = DMEM_LEFT_CH;
var_a1 = noteSub->leftDelaySize; haasEffectDelaySize = noteSub->leftDelaySize;
prevHaasEffectDelaySize = synthState->prevHaasEffectLeftDelaySize;
synthState->prevHaasEffectRightDelaySize = 0; synthState->prevHaasEffectRightDelaySize = 0;
var_v1 = synthState->prevHaasEffectLeftDelaySize; synthState->prevHaasEffectLeftDelaySize = haasEffectDelaySize;
synthState->prevHaasEffectLeftDelaySize = var_a1;
break; break;
case 2: case HAAS_EFFECT_DELAY_RIGHT:
var_t0 = 0xB10; dmemDest = DMEM_RIGHT_CH;
var_a1 = noteSub->rightDelaySize; haasEffectDelaySize = noteSub->rightDelaySize;
prevHaasEffectDelaySize = synthState->prevHaasEffectRightDelaySize;
synthState->prevHaasEffectRightDelaySize = haasEffectDelaySize;
synthState->prevHaasEffectLeftDelaySize = 0; synthState->prevHaasEffectLeftDelaySize = 0;
var_v1 = synthState->prevHaasEffectRightDelaySize;
synthState->prevHaasEffectRightDelaySize = var_a1;
break; break;
default: default: // HAAS_EFFECT_DELAY_NONE
return aList; return aList;
} }
if (flags != 1) { if (flags != A_INIT) {
if (var_a1 != var_v1) { if (haasEffectDelaySize != prevHaasEffectDelaySize) {
temp = (((size << 0xF) / 2) - 1) / ((size + var_a1 - var_v1 - 2) / 2); pitch = (((size << 0xF) / 2) - 1) / ((size + haasEffectDelaySize - prevHaasEffectDelaySize - 2) / 2);
aSetBuffer(aList++, 0, 0x650, 0x450, size + var_a1 - var_v1); aSetBuffer(aList++, 0, DMEM_HAAS_TEMP, DMEM_TEMP, size + haasEffectDelaySize - prevHaasEffectDelaySize);
aResampleZoh(aList++, temp, 0); aResampleZoh(aList++, pitch, 0);
} else { } else {
aDMEMMove(aList++, 0x650, 0x450, size); aDMEMMove(aList++, DMEM_HAAS_TEMP, DMEM_TEMP, size);
} }
if (var_v1 != 0) { if (prevHaasEffectDelaySize != 0) {
aLoadBuffer(aList++, OS_K0_TO_PHYSICAL(synthState->synthesisBuffers->panSamplesBuffer), 0x650, aLoadBuffer(aList++, OS_K0_TO_PHYSICAL(synthState->synthesisBuffers->panSamplesBuffer), DMEM_HAAS_TEMP,
ALIGN16(var_v1)); ALIGN16(prevHaasEffectDelaySize));
aDMEMMove(aList++, 0x450, var_v1 + 0x650, size + var_a1 - var_v1); aDMEMMove(aList++, DMEM_TEMP, prevHaasEffectDelaySize + DMEM_HAAS_TEMP,
size + haasEffectDelaySize - prevHaasEffectDelaySize);
} else { } else {
aDMEMMove(aList++, 0x450, 0x650, size + var_a1); aDMEMMove(aList++, DMEM_TEMP, DMEM_HAAS_TEMP, size + haasEffectDelaySize);
} }
} else { } else {
aDMEMMove(aList++, 0x650, 0x450, size); aDMEMMove(aList++, DMEM_HAAS_TEMP, DMEM_TEMP, size);
aClearBuffer(aList++, 0x650, var_a1); aClearBuffer(aList++, DMEM_HAAS_TEMP, haasEffectDelaySize);
aDMEMMove(aList++, 0x450, var_a1 + 0x650, size); aDMEMMove(aList++, DMEM_TEMP, haasEffectDelaySize + DMEM_HAAS_TEMP, size);
}
if (var_a1) {
aSaveBuffer(aList++, size + 0x650, OS_K0_TO_PHYSICAL(synthState->synthesisBuffers->panSamplesBuffer),
ALIGN16(var_a1));
} }
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; return aList;
} }

View File

@ -79,7 +79,7 @@ void AudioThread_CreateNextAudioBuffer(s16 *samples, u32 num_samples) {
AudioThread_ProcessCmds(msg.data32); 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); memcpy(gAiBuffers[gCurAiBuffIndex], samples, num_samples);
gAudioRandom = osGetCount() * (gAudioRandom + gAudioTaskCountQ); gAudioRandom = osGetCount() * (gAudioRandom + gAudioTaskCountQ);
@ -163,7 +163,7 @@ SPTask* AudioThread_CreateTask() {
while (MQ_GET_MESG(gThreadCmdProcQueue, &msg)) { while (MQ_GET_MESG(gThreadCmdProcQueue, &msg)) {
AudioThread_ProcessCmds(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 = osGetCount() * (gAudioRandom + gAudioTaskCountQ);
gAudioRandom = gAiBuffers[aiBuffIndex][gAudioTaskCountQ & 0xFF] + gAudioRandom; gAudioRandom = gAiBuffers[aiBuffIndex][gAudioTaskCountQ & 0xFF] + gAudioRandom;
@ -317,26 +317,17 @@ void AudioThread_QueueCmd(AudioCmd cmd) {
} }
void AudioThread_QueueCmdF32(u32 opArgs, f32 val) { void AudioThread_QueueCmdF32(u32 opArgs, f32 val) {
AudioCmd cmd = { AudioCmd cmd = { .opArgs = opArgs, .asFloat = val };
.opArgs = opArgs,
.asFloat = val
};
AudioThread_QueueCmd(cmd); AudioThread_QueueCmd(cmd);
} }
void AudioThread_QueueCmdS32(u32 opArgs, u32 val) { void AudioThread_QueueCmdS32(u32 opArgs, u32 val) {
AudioCmd cmd = { AudioCmd cmd = { .opArgs = opArgs, .asInt = val };
.opArgs = opArgs,
.asInt = val
};
AudioThread_QueueCmd(cmd); AudioThread_QueueCmd(cmd);
} }
void AudioThread_QueueCmdS8(u32 opArgs, s8 val) { void AudioThread_QueueCmdS8(u32 opArgs, s8 val) {
AudioCmd cmd = { AudioCmd cmd = { .opArgs = opArgs, .asSbyte = val };
.opArgs = opArgs,
.asSbyte = val
};
AudioThread_QueueCmd(cmd); AudioThread_QueueCmd(cmd);
} }