summaryrefslogtreecommitdiff
path: root/src/code
diff options
context:
space:
mode:
authorengineer124 <engineer124engineer124@gmail.com>2022-10-02 19:56:28 -0400
committerengineer124 <engineer124engineer124@gmail.com>2022-10-02 19:56:28 -0400
commitddbc03fed34c178c01215eef4bafc386063f2087 (patch)
tree5c0833f78d0791d0e2b0d001f9d08a4fe067ee52 /src/code
parentcd05be704983a8d0452d19624ca1244b10dbcb43 (diff)
parent3e32379c2bbce332dae9675954e28387480128f0 (diff)
merge master
Diffstat (limited to 'src/code')
-rw-r--r--src/code/audio/audio_data.c95
-rw-r--r--src/code/audio/audio_heap.c268
-rw-r--r--src/code/audio/audio_init_params.c182
-rw-r--r--src/code/audio/audio_load.c6
-rw-r--r--src/code/audio/audio_playback.c202
-rw-r--r--src/code/audio/audio_seqplayer.c49
-rw-r--r--src/code/audio/audio_synthesis.c1807
-rw-r--r--src/code/audio/code_8019AF00.c2
-rw-r--r--src/code/speed_meter.c1
-rw-r--r--src/code/z_camera.c2
-rw-r--r--src/code/z_demo.c9
-rw-r--r--src/code/z_effect_soft_sprite_old_init.c10
-rw-r--r--src/code/z_eventmgr.c1
-rw-r--r--src/code/z_game_over.c3
-rw-r--r--src/code/z_kaleido_scope_call.c3
-rw-r--r--src/code/z_kaleido_setup.c6
-rw-r--r--src/code/z_message.c4
-rw-r--r--src/code/z_parameter.c10
-rw-r--r--src/code/z_play.c2
-rw-r--r--src/code/z_quake.c9
-rw-r--r--src/code/z_shrink_window.c93
-rw-r--r--src/code/z_view.c243
22 files changed, 2450 insertions, 557 deletions
diff --git a/src/code/audio/audio_data.c b/src/code/audio/audio_data.c
index 7238a4bfa..eb931262b 100644
--- a/src/code/audio/audio_data.c
+++ b/src/code/audio/audio_data.c
@@ -857,22 +857,99 @@ EnvelopePoint gDefaultEnvelope[] = {
{ ADSR_DISABLE, 0 },
};
-NoteSubEu gZeroNoteSub = { 0 };
-
-NoteSubEu gDefaultNoteSub = {
- { 1, 1, 0, 0, 0, 0, 0, 0 }, { 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+NoteSampleState gZeroedSampleState = { 0 };
+
+NoteSampleState gDefaultSampleState = {
+ { true, true, false, false, false, false, false, false },
+ { 0 },
+ 0, // gain
+ 0, // haasEffectLeftDelaySize
+ 0, // haasEffectRightDelaySize
+ 0, // targetReverbVol
+ 0, // harmonicIndexCurAndPrev
+ 0, // combFilterSize
+ 0, // targetVolLeft
+ 0, // targetVolRight
+ 0, // frequencyFixedPoint
+ 0, // combFilterGain
+ NULL, // tunedSample
+ NULL, // filter
+ 0, // unk_18
+ 0, // surroundEffectIndex
+ 0, // unk_1A
};
-u16 gHeadsetPanQuantization[64] = {
- 60, 58, 56, 54, 52, 50, 48, 46, 44, 42, 40, 38, 36, 34, 32, 30, 28, 26, 24, 22, 20, 18,
- 16, 14, 12, 10, 8, 6, 4, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+u16 gHaasEffectDelaySize[64] = {
+ 30 * SAMPLE_SIZE,
+ 29 * SAMPLE_SIZE,
+ 28 * SAMPLE_SIZE,
+ 27 * SAMPLE_SIZE,
+ 26 * SAMPLE_SIZE,
+ 25 * SAMPLE_SIZE,
+ 24 * SAMPLE_SIZE,
+ 23 * SAMPLE_SIZE,
+ 22 * SAMPLE_SIZE,
+ 21 * SAMPLE_SIZE,
+ 20 * SAMPLE_SIZE,
+ 19 * SAMPLE_SIZE,
+ 18 * SAMPLE_SIZE,
+ 17 * SAMPLE_SIZE,
+ 16 * SAMPLE_SIZE,
+ 15 * SAMPLE_SIZE,
+ 14 * SAMPLE_SIZE,
+ 13 * SAMPLE_SIZE,
+ 12 * SAMPLE_SIZE,
+ 11 * SAMPLE_SIZE,
+ 10 * SAMPLE_SIZE,
+ 9 * SAMPLE_SIZE,
+ 8 * SAMPLE_SIZE,
+ 7 * SAMPLE_SIZE,
+ 6 * SAMPLE_SIZE,
+ 5 * SAMPLE_SIZE,
+ 4 * SAMPLE_SIZE,
+ 3 * SAMPLE_SIZE,
+ 2 * SAMPLE_SIZE,
+ 1 * SAMPLE_SIZE,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
};
s32 D_801D58A4 = 0;
// clang-format off
-s16 D_801D58A8[] = {
+s16 gInvalidAdpcmCodeBook[] = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
diff --git a/src/code/audio/audio_heap.c b/src/code/audio/audio_heap.c
index 667cd1c40..8412220a3 100644
--- a/src/code/audio/audio_heap.c
+++ b/src/code/audio/audio_heap.c
@@ -10,7 +10,7 @@ void AudioHeap_DiscardSampleCaches(void);
void AudioHeap_DiscardSampleBank(s32 sampleBankId);
void AudioHeap_ApplySampleBankCacheInternal(s32 apply, s32 sampleBankId);
void AudioHeap_DiscardSampleBanks(void);
-void AudioHeap_InitReverb(s32 reverbIndex, ReverbSettings* settings, s32 flags);
+void AudioHeap_InitReverb(s32 reverbIndex, ReverbSettings* settings, s32 isFirstInit);
#define gTatumsPerBeat (gAudioTatumInit[1])
@@ -421,7 +421,7 @@ void* AudioHeap_AllocCached(s32 tableType, size_t size, s32 cache, s32 id) {
if (loadStatusEntry0 == LOAD_STATUS_MAYBE_DISCARDABLE) {
for (i = 0; i < gAudioContext.numNotes; i++) {
if ((gAudioContext.notes[i].playbackState.fontId == temporaryCache->entries[0].id) &&
- gAudioContext.notes[i].noteSubEu.bitField0.enabled) {
+ gAudioContext.notes[i].sampleState.bitField0.enabled) {
break;
}
}
@@ -435,7 +435,7 @@ void* AudioHeap_AllocCached(s32 tableType, size_t size, s32 cache, s32 id) {
if (loadStatusEntry1 == LOAD_STATUS_MAYBE_DISCARDABLE) {
for (i = 0; i < gAudioContext.numNotes; i++) {
if ((gAudioContext.notes[i].playbackState.fontId == temporaryCache->entries[1].id) &&
- gAudioContext.notes[i].noteSubEu.bitField0.enabled) {
+ gAudioContext.notes[i].sampleState.bitField0.enabled) {
break;
}
}
@@ -491,7 +491,7 @@ void* AudioHeap_AllocCached(s32 tableType, size_t size, s32 cache, s32 id) {
if (loadStatusEntry0 == LOAD_STATUS_COMPLETE) {
for (i = 0; i < gAudioContext.numNotes; i++) {
if ((gAudioContext.notes[i].playbackState.fontId == temporaryCache->entries[0].id) &&
- gAudioContext.notes[i].noteSubEu.bitField0.enabled) {
+ gAudioContext.notes[i].sampleState.bitField0.enabled) {
break;
}
}
@@ -504,7 +504,7 @@ void* AudioHeap_AllocCached(s32 tableType, size_t size, s32 cache, s32 id) {
if (loadStatusEntry1 == LOAD_STATUS_COMPLETE) {
for (i = 0; i < gAudioContext.numNotes; i++) {
if ((gAudioContext.notes[i].playbackState.fontId == temporaryCache->entries[1].id) &&
- gAudioContext.notes[i].noteSubEu.bitField0.enabled) {
+ gAudioContext.notes[i].sampleState.bitField0.enabled) {
break;
}
}
@@ -814,7 +814,7 @@ void AudioHeap_UpdateReverb(SynthesisReverb* reverb) {
void AudioHeap_UpdateReverbs(void) {
s32 count;
- s32 i;
+ s32 reverbIndex;
s32 j;
if (gAudioContext.audioBufferParameters.specUnk4 == 2) {
@@ -823,9 +823,9 @@ void AudioHeap_UpdateReverbs(void) {
count = 1;
}
- for (i = 0; i < gAudioContext.numSynthesisReverbs; i++) {
+ for (reverbIndex = 0; reverbIndex < gAudioContext.numSynthesisReverbs; reverbIndex++) {
for (j = 0; j < count; j++) {
- AudioHeap_UpdateReverb(&gAudioContext.synthesisReverbs[i]);
+ AudioHeap_UpdateReverb(&gAudioContext.synthesisReverbs[reverbIndex]);
}
}
}
@@ -837,7 +837,7 @@ void AudioHeap_ClearAiBuffers(void) {
s32 curAiBufferIndex = gAudioContext.curAiBufferIndex;
s32 i;
- gAudioContext.aiBufNumSamples[curAiBufferIndex] = gAudioContext.audioBufferParameters.minAiBufNumSamples;
+ gAudioContext.aiBufNumSamples[curAiBufferIndex] = gAudioContext.audioBufferParameters.numSamplesPerFrameMin;
for (i = 0; i < AIBUF_LEN; i++) {
gAudioContext.aiBuffers[curAiBufferIndex][i] = 0;
@@ -870,7 +870,7 @@ s32 AudioHeap_ResetStep(void) {
AudioHeap_UpdateReverbs();
} else {
for (i = 0; i < gAudioContext.numNotes; i++) {
- if (gAudioContext.notes[i].noteSubEu.bitField0.enabled &&
+ if (gAudioContext.notes[i].sampleState.bitField0.enabled &&
gAudioContext.notes[i].playbackState.adsr.action.s.state != ADSR_STATE_DISABLED) {
gAudioContext.notes[i].playbackState.adsr.fadeOutVel =
gAudioContext.audioBufferParameters.updatesPerFrameInv;
@@ -907,7 +907,7 @@ s32 AudioHeap_ResetStep(void) {
AudioHeap_Init();
gAudioContext.resetStatus = 0;
for (i = 0; i < ARRAY_COUNT(gAudioContext.aiBufNumSamples); i++) {
- gAudioContext.aiBufNumSamples[i] = gAudioContext.audioBufferParameters.maxAiBufNumSamples;
+ gAudioContext.aiBufNumSamples[i] = gAudioContext.audioBufferParameters.numSamplesPerFrameMax;
for (j = 0; j < AIBUF_LEN; j++) {
gAudioContext.aiBuffers[i][j] = 0;
}
@@ -930,8 +930,8 @@ void AudioHeap_Init(void) {
size_t cachePoolSize;
size_t miscPoolSize;
u32 intMask;
+ s32 reverbIndex;
s32 i;
- s32 j;
s32 pad2;
AudioSpec* spec = &gAudioSpecs[gAudioContext.audioResetSpecIdToLoad]; // Audio Specifications
@@ -942,19 +942,22 @@ void AudioHeap_Init(void) {
gAudioContext.audioBufferParameters.aiSamplingFreq =
osAiSetFrequency(gAudioContext.audioBufferParameters.samplingFreq);
- gAudioContext.audioBufferParameters.samplesPerFrameTarget =
+ gAudioContext.audioBufferParameters.numSamplesPerFrameTarget =
ALIGN16(gAudioContext.audioBufferParameters.samplingFreq / gAudioContext.refreshRate);
- gAudioContext.audioBufferParameters.minAiBufNumSamples =
- gAudioContext.audioBufferParameters.samplesPerFrameTarget - 0x10;
- gAudioContext.audioBufferParameters.maxAiBufNumSamples =
- gAudioContext.audioBufferParameters.samplesPerFrameTarget + 0x10;
+ gAudioContext.audioBufferParameters.numSamplesPerFrameMin =
+ gAudioContext.audioBufferParameters.numSamplesPerFrameTarget - 0x10;
+ gAudioContext.audioBufferParameters.numSamplesPerFrameMax =
+ gAudioContext.audioBufferParameters.numSamplesPerFrameTarget + 0x10;
gAudioContext.audioBufferParameters.updatesPerFrame =
- ((gAudioContext.audioBufferParameters.samplesPerFrameTarget + 0x10) / 0xD0) + 1;
- gAudioContext.audioBufferParameters.samplesPerUpdate = (gAudioContext.audioBufferParameters.samplesPerFrameTarget /
- gAudioContext.audioBufferParameters.updatesPerFrame) &
- ~7;
- gAudioContext.audioBufferParameters.samplesPerUpdateMax = gAudioContext.audioBufferParameters.samplesPerUpdate + 8;
- gAudioContext.audioBufferParameters.samplesPerUpdateMin = gAudioContext.audioBufferParameters.samplesPerUpdate - 8;
+ ((gAudioContext.audioBufferParameters.numSamplesPerFrameTarget + 0x10) / 0xD0) + 1;
+ gAudioContext.audioBufferParameters.numSamplesPerUpdate =
+ (gAudioContext.audioBufferParameters.numSamplesPerFrameTarget /
+ gAudioContext.audioBufferParameters.updatesPerFrame) &
+ ~7;
+ gAudioContext.audioBufferParameters.numSamplesPerUpdateMax =
+ gAudioContext.audioBufferParameters.numSamplesPerUpdate + 8;
+ gAudioContext.audioBufferParameters.numSamplesPerUpdateMin =
+ gAudioContext.audioBufferParameters.numSamplesPerUpdate - 8;
gAudioContext.audioBufferParameters.resampleRate = 32000.0f / (s32)gAudioContext.audioBufferParameters.samplingFreq;
gAudioContext.audioBufferParameters.updatesPerFrameInvScaled =
(1.0f / 256.0f) / gAudioContext.audioBufferParameters.updatesPerFrame;
@@ -984,13 +987,13 @@ void AudioHeap_Init(void) {
gAudioContext.unk_2870 /= gAudioContext.tempoInternalToExternal;
gAudioContext.audioBufferParameters.specUnk4 = spec->unk_04;
- gAudioContext.audioBufferParameters.samplesPerFrameTarget *= gAudioContext.audioBufferParameters.specUnk4;
- gAudioContext.audioBufferParameters.maxAiBufNumSamples *= gAudioContext.audioBufferParameters.specUnk4;
- gAudioContext.audioBufferParameters.minAiBufNumSamples *= gAudioContext.audioBufferParameters.specUnk4;
+ gAudioContext.audioBufferParameters.numSamplesPerFrameTarget *= gAudioContext.audioBufferParameters.specUnk4;
+ gAudioContext.audioBufferParameters.numSamplesPerFrameMax *= gAudioContext.audioBufferParameters.specUnk4;
+ gAudioContext.audioBufferParameters.numSamplesPerFrameMin *= gAudioContext.audioBufferParameters.specUnk4;
gAudioContext.audioBufferParameters.updatesPerFrame *= gAudioContext.audioBufferParameters.specUnk4;
if (gAudioContext.audioBufferParameters.specUnk4 >= 2) {
- gAudioContext.audioBufferParameters.maxAiBufNumSamples -= 0x10;
+ gAudioContext.audioBufferParameters.numSamplesPerFrameMax -= 0x10;
}
// Determine the maximum allowable number of audio command list entries for the rsp microcode
@@ -1037,13 +1040,13 @@ void AudioHeap_Init(void) {
gAudioContext.notes = AudioHeap_AllocZeroed(&gAudioContext.miscPool, gAudioContext.numNotes * sizeof(Note));
AudioPlayback_NoteInitAll();
AudioPlayback_InitNoteFreeList();
- gAudioContext.noteSubsEu =
+ gAudioContext.sampleStateList =
AudioHeap_AllocZeroed(&gAudioContext.miscPool, gAudioContext.audioBufferParameters.updatesPerFrame *
- gAudioContext.numNotes * sizeof(NoteSubEu));
+ gAudioContext.numNotes * sizeof(NoteSampleState));
// Initialize audio binary interface command list buffer
- for (j = 0; j < ARRAY_COUNT(gAudioContext.abiCmdBufs); j++) {
- gAudioContext.abiCmdBufs[j] =
+ for (i = 0; i < ARRAY_COUNT(gAudioContext.abiCmdBufs); i++) {
+ gAudioContext.abiCmdBufs[i] =
AudioHeap_AllocDmaMemoryZeroed(&gAudioContext.miscPool, gAudioContext.maxAudioCmds * sizeof(Acmd));
}
@@ -1052,20 +1055,20 @@ void AudioHeap_Init(void) {
AudioHeap_InitAdsrDecayTable();
// Initialize reverbs
- for (i = 0; i < ARRAY_COUNT(gAudioContext.synthesisReverbs); i++) {
- gAudioContext.synthesisReverbs[i].useReverb = 0;
+ for (reverbIndex = 0; reverbIndex < ARRAY_COUNT(gAudioContext.synthesisReverbs); reverbIndex++) {
+ gAudioContext.synthesisReverbs[reverbIndex].useReverb = 0;
}
gAudioContext.numSynthesisReverbs = spec->numReverbs;
- for (i = 0; i < gAudioContext.numSynthesisReverbs; i++) {
- AudioHeap_InitReverb(i, &spec->reverbSettings[i], 1);
+ for (reverbIndex = 0; reverbIndex < gAudioContext.numSynthesisReverbs; reverbIndex++) {
+ AudioHeap_InitReverb(reverbIndex, &spec->reverbSettings[reverbIndex], true);
}
// Initialize sequence players
AudioSeq_InitSequencePlayers();
- for (j = 0; j < gAudioContext.audioBufferParameters.numSequencePlayers; j++) {
- AudioSeq_InitSequencePlayerChannels(j);
- AudioSeq_ResetSequencePlayer(&gAudioContext.seqPlayers[j]);
+ for (i = 0; i < gAudioContext.audioBufferParameters.numSequencePlayers; i++) {
+ AudioSeq_InitSequencePlayerChannels(i);
+ AudioSeq_ResetSequencePlayer(&gAudioContext.seqPlayers[i]);
}
// Initialize two additional caches on the audio heap to store individual audio samples
@@ -1529,149 +1532,165 @@ void AudioHeap_DiscardSampleBanks(void) {
}
}
-void AudioHeap_SetReverbData(s32 reverbIndex, u32 dataType, s32 data, s32 flags) {
- s32 windowSize;
+void AudioHeap_SetReverbData(s32 reverbIndex, u32 dataType, s32 data, s32 isFirstInit) {
+ s32 delayNumSamples;
SynthesisReverb* reverb = &gAudioContext.synthesisReverbs[reverbIndex];
switch (dataType) {
- case 0:
- AudioHeap_InitReverb(reverbIndex, (ReverbSettings*)data, 0);
+ case REVERB_DATA_TYPE_SETTINGS:
+ AudioHeap_InitReverb(reverbIndex, (ReverbSettings*)data, false);
break;
- case 1:
+
+ case REVERB_DATA_TYPE_DELAY:
if (data < 4) {
data = 4;
}
- windowSize = data * 64;
- if (windowSize < 0x100) {
- windowSize = 0x100;
+ delayNumSamples = data * 64;
+ if (delayNumSamples < (16 * SAMPLES_PER_FRAME)) {
+ delayNumSamples = 16 * SAMPLES_PER_FRAME;
}
- windowSize /= reverb->downsampleRate;
+ delayNumSamples /= reverb->downsampleRate;
- if (flags == 0) {
- if (reverb->unk_1E >= (data / reverb->downsampleRate)) {
- if ((reverb->nextRingBufPos >= windowSize) || (reverb->unk_24 >= windowSize)) {
- reverb->nextRingBufPos = 0;
- reverb->unk_24 = 0;
- }
- } else {
+ if (!isFirstInit) {
+ if (reverb->delayNumSamplesAfterDownsampling < (data / reverb->downsampleRate)) {
break;
}
+ if ((reverb->nextReverbBufPos >= delayNumSamples) || (reverb->delayNumSamplesUnk >= delayNumSamples)) {
+ reverb->nextReverbBufPos = 0;
+ reverb->delayNumSamplesUnk = 0;
+ }
}
- reverb->windowSize = windowSize;
-
- if ((reverb->downsampleRate != 1) || reverb->unk_18) {
- reverb->unk_0E = 0x8000 / reverb->downsampleRate;
- if (reverb->unk_30 == NULL) {
- reverb->unk_30 = AudioHeap_AllocZeroed(&gAudioContext.miscPool, 0x20);
- reverb->unk_34 = AudioHeap_AllocZeroed(&gAudioContext.miscPool, 0x20);
- reverb->unk_38 = AudioHeap_AllocZeroed(&gAudioContext.miscPool, 0x20);
- reverb->unk_3C = AudioHeap_AllocZeroed(&gAudioContext.miscPool, 0x20);
- if (reverb->unk_3C == NULL) {
+ reverb->delayNumSamples = delayNumSamples;
+
+ if ((reverb->downsampleRate != 1) || reverb->resampleEffectOn) {
+ reverb->downsamplePitch = 0x8000 / reverb->downsampleRate;
+ if (reverb->leftLoadResampleBuf == NULL) {
+ reverb->leftLoadResampleBuf =
+ AudioHeap_AllocZeroed(&gAudioContext.miscPool, sizeof(RESAMPLE_STATE));
+ reverb->rightLoadResampleBuf =
+ AudioHeap_AllocZeroed(&gAudioContext.miscPool, sizeof(RESAMPLE_STATE));
+ reverb->leftSaveResampleBuf =
+ AudioHeap_AllocZeroed(&gAudioContext.miscPool, sizeof(RESAMPLE_STATE));
+ reverb->rightSaveResampleBuf =
+ AudioHeap_AllocZeroed(&gAudioContext.miscPool, sizeof(RESAMPLE_STATE));
+ if (reverb->rightSaveResampleBuf == NULL) {
reverb->downsampleRate = 1;
}
}
}
break;
- case 2:
- gAudioContext.synthesisReverbs[reverbIndex].unk_0C = data;
+
+ case REVERB_DATA_TYPE_DECAY:
+ gAudioContext.synthesisReverbs[reverbIndex].decayRatio = data;
break;
- case 3:
- gAudioContext.synthesisReverbs[reverbIndex].unk_16 = data;
+
+ case REVERB_DATA_TYPE_SUB_VOLUME:
+ gAudioContext.synthesisReverbs[reverbIndex].subVolume = data;
break;
- case 4:
- gAudioContext.synthesisReverbs[reverbIndex].unk_0A = data;
+
+ case REVERB_DATA_TYPE_VOLUME:
+ gAudioContext.synthesisReverbs[reverbIndex].volume = data;
break;
- case 5:
+
+ case REVERB_DATA_TYPE_LEAK_RIGHT:
gAudioContext.synthesisReverbs[reverbIndex].leakRtl = data;
break;
- case 6:
+
+ case REVERB_DATA_TYPE_LEAK_LEFT:
gAudioContext.synthesisReverbs[reverbIndex].leakLtr = data;
break;
- case 7:
+
+ case REVERB_DATA_TYPE_FILTER_LEFT:
if (data != 0) {
- if ((flags != 0) || (reverb->unk_278 == 0)) {
- reverb->filterLeftState = AudioHeap_AllocDmaMemoryZeroed(&gAudioContext.miscPool, 0x40);
- reverb->unk_278 = AudioHeap_AllocDmaMemory(&gAudioContext.miscPool, 0x10);
+ if (isFirstInit || (reverb->filterLeftInit == NULL)) {
+ reverb->filterLeftState = AudioHeap_AllocDmaMemoryZeroed(&gAudioContext.miscPool,
+ 2 * (FILTER_BUF_PART1 + FILTER_BUF_PART2));
+ reverb->filterLeftInit = AudioHeap_AllocDmaMemory(&gAudioContext.miscPool, FILTER_SIZE);
}
- reverb->filterLeft = reverb->unk_278;
- if (reverb->filterLeft != 0) {
+ reverb->filterLeft = reverb->filterLeftInit;
+ if (reverb->filterLeft != NULL) {
AudioHeap_LoadLowPassFilter(reverb->filterLeft, data);
}
} else {
- reverb->filterLeft = 0;
+ reverb->filterLeft = NULL;
- if (flags != 0) {
- reverb->unk_278 = 0;
+ if (isFirstInit) {
+ reverb->filterLeftInit = NULL;
}
}
-
break;
- case 8:
+
+ case REVERB_DATA_TYPE_FILTER_RIGHT:
if (data != 0) {
- if ((flags != 0) || (reverb->unk_27C == 0)) {
- reverb->filterRightState = AudioHeap_AllocDmaMemoryZeroed(&gAudioContext.miscPool, 0x40);
- reverb->unk_27C = AudioHeap_AllocDmaMemory(&gAudioContext.miscPool, 0x10);
+ if (isFirstInit || (reverb->filterRightInit == NULL)) {
+ reverb->filterRightState = AudioHeap_AllocDmaMemoryZeroed(
+ &gAudioContext.miscPool, 2 * (FILTER_BUF_PART1 + FILTER_BUF_PART2));
+ reverb->filterRightInit = AudioHeap_AllocDmaMemory(&gAudioContext.miscPool, FILTER_SIZE);
}
- reverb->filterRight = reverb->unk_27C;
- if (reverb->unk_27C != 0) {
- AudioHeap_LoadLowPassFilter(reverb->unk_27C, data);
+ reverb->filterRight = reverb->filterRightInit;
+ if (reverb->filterRight != NULL) {
+ AudioHeap_LoadLowPassFilter(reverb->filterRight, data);
}
} else {
- reverb->filterRight = 0;
- if (flags != 0) {
- reverb->unk_27C = 0;
+ reverb->filterRight = NULL;
+ if (isFirstInit) {
+ reverb->filterRightInit = NULL;
}
}
break;
- case 9:
- reverb->unk_19 = data;
+
+ case REVERB_DATA_TYPE_9:
+ reverb->resampleEffectExtraSamples = data;
if (data == 0) {
- reverb->unk_18 = false;
+ reverb->resampleEffectOn = false;
} else {
- reverb->unk_18 = true;
+ reverb->resampleEffectOn = true;
}
break;
+
default:
break;
}
}
-void AudioHeap_InitReverb(s32 reverbIndex, ReverbSettings* settings, s32 flags) {
+void AudioHeap_InitReverb(s32 reverbIndex, ReverbSettings* settings, s32 isFirstInit) {
SynthesisReverb* reverb = &gAudioContext.synthesisReverbs[reverbIndex];
- if (flags != 0) {
- reverb->unk_1E = settings->windowSize / settings->downsampleRate;
- reverb->unk_30 = 0;
- } else if (reverb->unk_1E < (settings->windowSize / settings->downsampleRate)) {
+ if (isFirstInit) {
+ reverb->delayNumSamplesAfterDownsampling = settings->delayNumSamples / settings->downsampleRate;
+ reverb->leftLoadResampleBuf = NULL;
+ } else if (reverb->delayNumSamplesAfterDownsampling < (settings->delayNumSamples / settings->downsampleRate)) {
return;
}
reverb->downsampleRate = settings->downsampleRate;
- reverb->unk_18 = false;
- reverb->unk_19 = 0;
- reverb->unk_1A = 0;
- reverb->unk_1C = 0;
- AudioHeap_SetReverbData(reverbIndex, 1, settings->windowSize, flags);
- reverb->unk_0C = settings->unk_4;
- reverb->unk_0A = settings->unk_A;
- reverb->unk_14 = settings->unk_6 << 6;
- reverb->unk_16 = settings->unk_8;
+ reverb->resampleEffectOn = false;
+ reverb->resampleEffectExtraSamples = 0;
+ reverb->resampleEffectLoadUnk = 0;
+ reverb->resampleEffectSaveUnk = 0;
+ AudioHeap_SetReverbData(reverbIndex, REVERB_DATA_TYPE_DELAY, settings->delayNumSamples, isFirstInit);
+ reverb->decayRatio = settings->decayRatio;
+ reverb->volume = settings->volume;
+ reverb->subDelay = settings->subDelay * 64;
+ reverb->subVolume = settings->subVolume;
reverb->leakRtl = settings->leakRtl;
reverb->leakLtr = settings->leakLtr;
- reverb->unk_05 = settings->unk_10;
- reverb->unk_08 = settings->unk_12;
- reverb->useReverb = 8;
-
- if (flags != 0) {
- reverb->leftRingBuf = AudioHeap_AllocZeroedAttemptExternal(&gAudioContext.miscPool, reverb->windowSize * 2);
- reverb->rightRingBuf = AudioHeap_AllocZeroedAttemptExternal(&gAudioContext.miscPool, reverb->windowSize * 2);
+ reverb->mixReverbIndex = settings->mixReverbIndex;
+ reverb->mixReverbStrength = settings->mixReverbStrength;
+ reverb->useReverb = 8; // used as a boolean
+
+ if (isFirstInit) {
+ reverb->leftReverbBuf =
+ AudioHeap_AllocZeroedAttemptExternal(&gAudioContext.miscPool, reverb->delayNumSamples * 2);
+ reverb->rightReverbBuf =
+ AudioHeap_AllocZeroedAttemptExternal(&gAudioContext.miscPool, reverb->delayNumSamples * 2);
reverb->resampleFlags = 1;
- reverb->nextRingBufPos = 0;
- reverb->unk_24 = 0;
+ reverb->nextReverbBufPos = 0;
+ reverb->delayNumSamplesUnk = 0;
reverb->curFrame = 0;
reverb->framesToIgnore = 2;
}
@@ -1681,12 +1700,13 @@ void AudioHeap_InitReverb(s32 reverbIndex, ReverbSettings* settings, s32 flags)
reverb->tunedSample.tuning = 1.0f;
reverb->sample.codec = CODEC_REVERB;
reverb->sample.medium = MEDIUM_RAM;
- reverb->sample.size = reverb->windowSize * 2;
- reverb->sample.sampleAddr = (u8*)reverb->leftRingBuf;
+ reverb->sample.size = reverb->delayNumSamples * SAMPLE_SIZE;
+ reverb->sample.sampleAddr = (u8*)reverb->leftReverbBuf;
reverb->loop.start = 0;
reverb->loop.count = 1;
- reverb->loop.end = reverb->windowSize;
+ reverb->loop.loopEnd = reverb->delayNumSamples;
- AudioHeap_SetReverbData(reverbIndex, 7, settings->lowPassFilterCutoffLeft, flags);
- AudioHeap_SetReverbData(reverbIndex, 8, settings->lowPassFilterCutoffRight, flags);
+ AudioHeap_SetReverbData(reverbIndex, REVERB_DATA_TYPE_FILTER_LEFT, settings->lowPassFilterCutoffLeft, isFirstInit);
+ AudioHeap_SetReverbData(reverbIndex, REVERB_DATA_TYPE_FILTER_RIGHT, settings->lowPassFilterCutoffRight,
+ isFirstInit);
}
diff --git a/src/code/audio/audio_init_params.c b/src/code/audio/audio_init_params.c
index 81c49b30c..59c6658ac 100644
--- a/src/code/audio/audio_init_params.c
+++ b/src/code/audio/audio_init_params.c
@@ -1,12 +1,184 @@
#include "global.h"
const s16 gAudioTatumInit[] = {
- 0x1C00, // unused
- 0x30, // gTatumsPerBeat
+ 0x1C00, // unused
+ TATUMS_PER_BEAT, // gTatumsPerBeat
};
+// TODO: Extract from table?
+#define NUM_SOUNDFONTS 41
+#define SFX_SEQ_SIZE 0xC6A0
+#define AMBIENCE_SEQ_SIZE 0xFC0
+#define SOUNDFONT_0_SIZE 0x81C0
+#define SOUNDFONT_1_SIZE 0x36D0
+#define SOUNDFONT_2_SIZE 0xCE0
+
+// Sizes of everything on the init pool
+#define AI_BUFFERS_SIZE (AIBUF_SIZE * ARRAY_COUNT(gAudioContext.aiBuffers))
+#define SOUNDFONT_LIST_SIZE (NUM_SOUNDFONTS * sizeof(SoundFont))
+
+// 0x19BD0
+#define PERMANENT_POOL_SIZE \
+ (SFX_SEQ_SIZE + AMBIENCE_SEQ_SIZE + SOUNDFONT_0_SIZE + SOUNDFONT_1_SIZE + SOUNDFONT_2_SIZE + 0x430)
+
const AudioHeapInitSizes gAudioHeapInitSizes = {
- 0x137F00, // heapSize
- 0x1C480, // initPoolSize
- 0x1A000, // permanentPoolSize
+ ALIGN16(sizeof(gAudioHeap) - 0x100), // audio heap size
+ ALIGN16(PERMANENT_POOL_SIZE + AI_BUFFERS_SIZE + SOUNDFONT_LIST_SIZE + 0x40), // init pool size
+ ALIGN16(PERMANENT_POOL_SIZE), // permanent pool size
+};
+
+#define REVERB_INDEX_0_SETTINGS \
+ { 1, 0x30, 0x3000, 0, 0, 0x7FFF, 0x0000, 0x0000, REVERB_INDEX_NONE, 0x3000, 0, 0 }
+
+ReverbSettings reverbSettings0[3] = {
+ REVERB_INDEX_0_SETTINGS,
+ { 1, 0x20, 0x0800, 0, 0, 0x7FFF, 0x0000, 0x0000, REVERB_INDEX_NONE, 0x0000, 0, 0 },
+};
+
+ReverbSettings reverbSettings1[3] = {
+ REVERB_INDEX_0_SETTINGS,
+ { 1, 0x30, 0x1800, 0, 0, 0x7FFF, 0x0000, 0x0000, REVERB_INDEX_NONE, 0x0000, 11, 11 },
+};
+
+ReverbSettings reverbSettings2[3] = {
+ REVERB_INDEX_0_SETTINGS,
+ { 1, 0x38, 0x2800, 0, 0, 0x7FFF, 0x0000, 0x0000, REVERB_INDEX_NONE, 0x0000, 7, 7 },
+};
+
+ReverbSettings reverbSettings3[3] = {
+ REVERB_INDEX_0_SETTINGS,
+ { 1, 0x30, 0x6800, 0, 0, 0x7FFF, 0x1400, 0x1400, REVERB_INDEX_NONE, 0x3000, 6, 6 },
+ { 2, 0x50, 0x6000, 0, 0, 0x7FFF, 0xD000, 0x3000, REVERB_INDEX_NONE, 0x3000, 0, 0 },
+};
+
+ReverbSettings reverbSettings4[3] = {
+ REVERB_INDEX_0_SETTINGS,
+ { 1, 0x40, 0x5000, 0, 0, 0x7FFF, 0x1800, 0x1800, REVERB_INDEX_NONE, 0x3000, 7, 7 },
+};
+
+ReverbSettings reverbSettings5[3] = {
+ REVERB_INDEX_0_SETTINGS,
+ { 1, 0x40, 0x5C00, 0, 0, 0x7FFF, 0x2000, 0x2000, REVERB_INDEX_NONE, 0x3000, 4, 4 },
+};
+
+ReverbSettings reverbSettings6[3] = {
+ REVERB_INDEX_0_SETTINGS,
+ { 1, 0x30, 0x6000, 0, 0, 0x7FFF, 0x1000, 0x1000, REVERB_INDEX_NONE, 0x3000, 10, 10 },
+};
+
+ReverbSettings reverbSettings7[3] = {
+ REVERB_INDEX_0_SETTINGS,
+ { 1, 0x30, 0x6800, 0, 0, 0x7FFF, 0x1400, 0x1400, REVERB_INDEX_NONE, 0x3000, 6, 6 },
+};
+
+ReverbSettings reverbSettings8[2] = {
+ REVERB_INDEX_0_SETTINGS,
+ { 1, 0x50, 0x5000, 0, 0, 0x7FFF, 0xD000, 0x3000, REVERB_INDEX_NONE, 0x3000, 0, 0 },
+};
+
+ReverbSettings reverbSettings9[3] = {
+ REVERB_INDEX_0_SETTINGS,
+ { 1, 0x20, 0x0000, 0, 0, 0x7FFF, 0x0000, 0x0000, REVERB_INDEX_NONE, 0x0000, 0, 0 },
+};
+
+ReverbSettings reverbSettingsA[3] = {
+ REVERB_INDEX_0_SETTINGS,
+ { 1, 0x30, 0x1800, 0, 0, 0x7FFF, 0x0000, 0x0000, REVERB_INDEX_NONE, 0x0000, 11, 11 },
+};
+
+ReverbSettings reverbSettingsB[3] = {
+ REVERB_INDEX_0_SETTINGS,
+};
+
+ReverbSettings reverbSettingsC[3] = {
+ REVERB_INDEX_0_SETTINGS,
+ { 1, 0x40, 0x5000, 0, 0, 0x7FFF, 0x0000, 0x0000, REVERB_INDEX_NONE, 0x3000, 0, 0 },
+};
+
+ReverbSettings reverbSettingsD[3] = {
+ REVERB_INDEX_0_SETTINGS,
+ { 1, 0x30, 0x6800, 0, 0, 0x7FFF, 0x1400, 0x1400, REVERB_INDEX_NONE, 0x3000, 6, 6 },
+ { 2, 0x50, 0x6000, 0, 0, 0x7FFF, 0xD000, 0x3000, REVERB_INDEX_NONE, 0x3000, 0, 0 },
+};
+
+ReverbSettings reverbSettingsE[3] = {
+ REVERB_INDEX_0_SETTINGS,
+ { 1, 0x30, 0x1800, 0, 0, 0x7FFF, 0x0000, 0x0000, REVERB_INDEX_NONE, 0x0000, 11, 11 },
+ { 1, 0x40, 0x5000, 0, 0, 0x7FFF, 0x1800, 0x1800, REVERB_INDEX_NONE, 0x3000, 7, 7 },
+};
+
+ReverbSettings reverbSettingsF[2] = {
+ REVERB_INDEX_0_SETTINGS,
+ { 1, 0x50, 0x1800, 0, 0, 0x7FFF, 0x0000, 0x0000, REVERB_INDEX_NONE, 0x0000, 11, 11 },
+};
+
+ReverbSettings* gReverbSettingsTable[] = {
+ reverbSettings0, reverbSettings1, reverbSettings2, reverbSettings4, reverbSettings5,
+ reverbSettings6, reverbSettings7, reverbSettings8, reverbSettings9, reverbSettings3,
+};
+
+AudioSpec gAudioSpecs[21] = {
+ /* 0x0 */
+ { 32000, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
+ 0xDC800 },
+ /* 0x1 */
+ { 32000, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
+ 0xDC800 },
+ /* 0x2 */
+ { 32000, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
+ 0xDC800 },
+ /* 0x3 */
+ { 32000, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
+ 0xDC800 },
+ /* 0x4 */
+ { 32000, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
+ 0xDC800 },
+ /* 0x5 */
+ { 32000, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
+ 0xDC800 },
+ /* 0x6 */
+ { 32000, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
+ 0xDC800 },
+ /* 0x7 */
+ { 32000, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
+ 0xDC800 },
+ /* 0x8 */
+ { 32000, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
+ 0xDC800 },
+ /* 0x9 */
+ { 32000, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
+ 0xDC800 },
+ /* 0xA */
+ { 32000, 1, 28, 3, 0, 0, 2, reverbSettingsA, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x2800, 0x2D00, 0, 0,
+ 0xDC800 },
+ /* 0xB */
+ { 32000, 1, 28, 3, 0, 0, 2, reverbSettingsA, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
+ 0xDC800 },
+ /* 0xC */
+ { 32000, 1, 28, 5, 0, 0, 2, reverbSettingsA, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
+ 0xCC800 },
+ /* 0xD */
+ { 32000, 1, 24, 5, 0, 0, 3, reverbSettingsD, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
+ 0xDC800 },
+ /* 0xE */
+ { 32000, 1, 24, 5, 0, 0, 3, reverbSettingsE, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
+ 0xDC800 },
+ /* 0xF */
+ { 32000, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4000, 0x2D00, 0, 0,
+ 0xDC800 },
+ /* 0x10 */
+ { 32000, 1, 22, 5, 0, 0, 2, reverbSettings0, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
+ 0xDC800 },
+ /* 0x11 */
+ { 32000, 1, 22, 5, 0, 0, 2, reverbSettings8, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
+ 0xDC800 },
+ /* 0x12 */
+ { 32000, 1, 16, 5, 0, 0, 2, reverbSettings0, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
+ 0xDC800 },
+ /* 0x13 */
+ { 22050, 1, 24, 5, 0, 0, 2, reverbSettings0, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
+ 0xDC800 },
+ /* 0x14 */
+ { 32000, 1, 24, 5, 0, 0, 2, reverbSettings2, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x3600, 0x2600, 0, 0,
+ 0xDC800 },
};
diff --git a/src/code/audio/audio_load.c b/src/code/audio/audio_load.c
index c8e5ac5d1..ccdc7488d 100644
--- a/src/code/audio/audio_load.c
+++ b/src/code/audio/audio_load.c
@@ -1218,9 +1218,9 @@ void AudioLoad_Init(void* heap, size_t heapSize) {
s32 i;
s32 j;
- D_80208E68 = NULL;
- D_80208E70 = NULL;
- D_80208E74 = NULL;
+ gCustomAudioUpdateFunction = NULL;
+ gCustomAudioReverbFunction = NULL;
+ gCustomAudioSynthFunction = NULL;
for (i = 0; i < ARRAY_COUNT(gAudioContext.unk_29A8); i++) {
gAudioContext.unk_29A8[i] = NULL;
diff --git a/src/code/audio/audio_playback.c b/src/code/audio/audio_playback.c
index e1a42b1ed..a7cc9a588 100644
--- a/src/code/audio/audio_playback.c
+++ b/src/code/audio/audio_playback.c
@@ -1,10 +1,10 @@
#include "global.h"
-void AudioPlayback_NoteSetResamplingRate(NoteSubEu* noteSubEu, f32 resamplingRateInput);
+void AudioPlayback_NoteSetResamplingRate(NoteSampleState* sampleState, f32 resamplingRateInput);
void AudioPlayback_AudioListPushFront(AudioListItem* list, AudioListItem* item);
void AudioPlayback_NoteInitForLayer(Note* note, SequenceLayer* layer);
-void AudioPlayback_InitNoteSub(Note* note, NoteSubEu* noteSubEu, NoteSubAttributes* subAttrs) {
+void AudioPlayback_InitSampleState(Note* note, NoteSampleState* sampleState, NoteSubAttributes* subAttrs) {
f32 volLeft;
f32 volRight;
s32 halfPanIndex;
@@ -13,45 +13,45 @@ void AudioPlayback_InitNoteSub(Note* note, NoteSubEu* noteSubEu, NoteSubAttribut
u8 strongRight;
f32 vel;
u8 pan;
- u8 reverbVol;
+ u8 targetReverbVol;
StereoData stereoData;
s32 stereoHeadsetEffects = note->playbackState.stereoHeadsetEffects;
vel = subAttrs->velocity;
pan = subAttrs->pan;
- reverbVol = subAttrs->reverbVol;
- stereoData = subAttrs->stereo.s;
+ targetReverbVol = subAttrs->targetReverbVol;
+ stereoData = subAttrs->stereoData;
- noteSubEu->bitField0 = note->noteSubEu.bitField0;
- noteSubEu->bitField1 = note->noteSubEu.bitField1;
- noteSubEu->waveSampleAddr = note->noteSubEu.waveSampleAddr;
- noteSubEu->harmonicIndexCurAndPrev = note->noteSubEu.harmonicIndexCurAndPrev;
+ sampleState->bitField0 = note->sampleState.bitField0;
+ sampleState->bitField1 = note->sampleState.bitField1;
+ sampleState->waveSampleAddr = note->sampleState.waveSampleAddr;
+ sampleState->harmonicIndexCurAndPrev = note->sampleState.harmonicIndexCurAndPrev;
- AudioPlayback_NoteSetResamplingRate(noteSubEu, subAttrs->frequency);
+ AudioPlayback_NoteSetResamplingRate(sampleState, subAttrs->frequency);
pan &= 0x7F;
- noteSubEu->bitField0.stereoStrongRight = false;
- noteSubEu->bitField0.stereoStrongLeft = false;
- noteSubEu->bitField0.stereoHeadsetEffects = stereoData.stereoHeadsetEffects;
- noteSubEu->bitField0.usesHeadsetPanEffects = stereoData.usesHeadsetPanEffects;
+ sampleState->bitField0.strongRight = false;
+ sampleState->bitField0.strongLeft = false;
+ sampleState->bitField0.strongReverbRight = stereoData.strongReverbRight;
+ sampleState->bitField0.strongReverbLeft = stereoData.strongReverbLeft;
if (stereoHeadsetEffects && (gAudioContext.soundMode == SOUNDMODE_HEADSET)) {
halfPanIndex = pan >> 1;
if (halfPanIndex > 0x3F) {
halfPanIndex = 0x3F;
}
- noteSubEu->headsetPanLeft = gHeadsetPanQuantization[halfPanIndex];
- noteSubEu->headsetPanRight = gHeadsetPanQuantization[0x3F - halfPanIndex];
- noteSubEu->bitField1.usesHeadsetPanEffects2 = true;
+ sampleState->haasEffectRightDelaySize = gHaasEffectDelaySize[halfPanIndex];
+ sampleState->haasEffectLeftDelaySize = gHaasEffectDelaySize[0x3F - halfPanIndex];
+ sampleState->bitField1.useHaasEffect = true;
volLeft = gHeadsetPanVolume[pan];
volRight = gHeadsetPanVolume[0x7F - pan];
} else if (stereoHeadsetEffects && (gAudioContext.soundMode == SOUNDMODE_STEREO)) {
strongLeft = strongRight = false;
- noteSubEu->headsetPanRight = 0;
- noteSubEu->headsetPanLeft = 0;
- noteSubEu->bitField1.usesHeadsetPanEffects2 = false;
+ sampleState->haasEffectLeftDelaySize = 0;
+ sampleState->haasEffectRightDelaySize = 0;
+ sampleState->bitField1.useHaasEffect = false;
volLeft = gStereoPanVolume[pan];
volRight = gStereoPanVolume[0x7F - pan];
@@ -62,37 +62,37 @@ void AudioPlayback_InitNoteSub(Note* note, NoteSubEu* noteSubEu, NoteSubAttribut
}
// case 0:
- noteSubEu->bitField0.stereoStrongRight = strongRight;
- noteSubEu->bitField0.stereoStrongLeft = strongLeft;
+ sampleState->bitField0.strongRight = strongRight;
+ sampleState->bitField0.strongLeft = strongLeft;
- switch (stereoData.bit2) {
+ switch (stereoData.type) {
case 0:
break;
case 1:
- noteSubEu->bitField0.stereoStrongRight = stereoData.strongRight;
- noteSubEu->bitField0.stereoStrongLeft = stereoData.strongLeft;
+ sampleState->bitField0.strongRight = stereoData.strongRight;
+ sampleState->bitField0.strongLeft = stereoData.strongLeft;
break;
case 2:
- noteSubEu->bitField0.stereoStrongRight = stereoData.strongRight | strongRight;
- noteSubEu->bitField0.stereoStrongLeft = stereoData.strongLeft | strongLeft;
+ sampleState->bitField0.strongRight = stereoData.strongRight | strongRight;
+ sampleState->bitField0.strongLeft = stereoData.strongLeft | strongLeft;
break;
case 3:
- noteSubEu->bitField0.stereoStrongRight = stereoData.strongRight ^ strongRight;
- noteSubEu->bitField0.stereoStrongLeft = stereoData.strongLeft ^ strongLeft;
+ sampleState->bitField0.strongRight = stereoData.strongRight ^ strongRight;
+ sampleState->bitField0.strongLeft = stereoData.strongLeft ^ strongLeft;
break;
}
} else if (gAudioContext.soundMode == SOUNDMODE_MONO) {
- noteSubEu->bitField0.stereoHeadsetEffects = false;
- noteSubEu->bitField0.usesHeadsetPanEffects = false;
+ sampleState->bitField0.strongReverbRight = false;
+ sampleState->bitField0.strongReverbLeft = false;
volLeft = 0.707f; // approx 1/sqrt(2)
volRight = 0.707f;
} else {
- noteSubEu->bitField0.stereoStrongRight = stereoData.strongRight;
- noteSubEu->bitField0.stereoStrongLeft = stereoData.strongLeft;
+ sampleState->bitField0.strongRight = stereoData.strongRight;
+ sampleState->bitField0.strongLeft = stereoData.strongLeft;
volLeft = gDefaultPanVolume[pan];
volRight = gDefaultPanVolume[0x7F - pan];
}
@@ -100,33 +100,33 @@ void AudioPlayback_InitNoteSub(Note* note, NoteSubEu* noteSubEu, NoteSubAttribut
vel = 0.0f > vel ? 0.0f : vel;
vel = 1.0f < vel ? 1.0f : vel;
- noteSubEu->targetVolLeft = (s32)((vel * volLeft) * (0x1000 - 0.001f));
- noteSubEu->targetVolRight = (s32)((vel * volRight) * (0x1000 - 0.001f));
+ sampleState->targetVolLeft = (s32)((vel * volLeft) * (0x1000 - 0.001f));
+ sampleState->targetVolRight = (s32)((vel * volRight) * (0x1000 - 0.001f));
- noteSubEu->gain = subAttrs->gain;
- noteSubEu->filter = subAttrs->filter;
- noteSubEu->unk_07 = subAttrs->unk_14;
- noteSubEu->unk_0E = subAttrs->unk_16;
- noteSubEu->reverbVol = reverbVol;
- noteSubEu->unk_19 = subAttrs->unk_3;
+ sampleState->gain = subAttrs->gain;
+ sampleState->filter = subAttrs->filter;
+ sampleState->combFilterSize = subAttrs->combFilterSize;
+ sampleState->combFilterGain = subAttrs->combFilterGain;
+ sampleState->targetReverbVol = targetReverbVol;
+ sampleState->surroundEffectIndex = subAttrs->surroundEffectIndex;
}
-void AudioPlayback_NoteSetResamplingRate(NoteSubEu* noteSubEu, f32 resamplingRateInput) {
+void AudioPlayback_NoteSetResamplingRate(NoteSampleState* sampleState, f32 resamplingRateInput) {
f32 resamplingRate = 0.0f;
if (resamplingRateInput < 2.0f) {
- noteSubEu->bitField1.hasTwoParts = false;
+ sampleState->bitField1.hasTwoParts = false;
resamplingRate = CLAMP_MAX(resamplingRateInput, 1.99998f);
} else {
- noteSubEu->bitField1.hasTwoParts = true;
+ sampleState->bitField1.hasTwoParts = true;
if (resamplingRateInput > 3.99996f) {
resamplingRate = 1.99998f;
} else {
resamplingRate = resamplingRateInput * 0.5f;
}
}
- noteSubEu->resamplingRateFixedPoint = (s32)(resamplingRate * 32768.0f);
+ sampleState->frequencyFixedPoint = (s32)(resamplingRate * 32768.0f);
}
void AudioPlayback_NoteInit(Note* note) {
@@ -140,17 +140,17 @@ void AudioPlayback_NoteInit(Note* note) {
note->playbackState.status = PLAYBACK_STATUS_0;
note->playbackState.adsr.action.s.state = ADSR_STATE_INITIAL;
- note->noteSubEu = gDefaultNoteSub;
+ note->sampleState = gDefaultSampleState;
}
void AudioPlayback_NoteDisable(Note* note) {
- if (note->noteSubEu.bitField0.needsInit == true) {
- note->noteSubEu.bitField0.needsInit = false;
+ if (note->sampleState.bitField0.needsInit == true) {
+ note->sampleState.bitField0.needsInit = false;
}
note->playbackState.priority = 0;
- note->noteSubEu.bitField0.enabled = false;
+ note->sampleState.bitField0.enabled = false;
note->playbackState.status = PLAYBACK_STATUS_0;
- note->noteSubEu.bitField0.finished = false;
+ note->sampleState.bitField0.finished = false;
note->playbackState.parentLayer = NO_LAYER;
note->playbackState.prevParentLayer = NO_LAYER;
note->playbackState.adsr.action.s.state = ADSR_STATE_DISABLED;
@@ -161,8 +161,8 @@ void AudioPlayback_ProcessNotes(void) {
s32 pad;
s32 playbackStatus;
NoteAttributes* attrs;
- NoteSubEu* noteSubEu2;
- NoteSubEu* noteSubEu;
+ NoteSampleState* sampleState;
+ NoteSampleState* noteSampleState;
Note* note;
NotePlaybackState* playbackState;
NoteSubAttributes subAttrs;
@@ -172,7 +172,7 @@ void AudioPlayback_ProcessNotes(void) {
for (i = 0; i < gAudioContext.numNotes; i++) {
note = &gAudioContext.notes[i];
- noteSubEu2 = &gAudioContext.noteSubsEu[gAudioContext.noteSubEuOffset + i];
+ sampleState = &gAudioContext.sampleStateList[gAudioContext.sampleStateOffset + i];
playbackState = &note->playbackState;
if (playbackState->parentLayer != NO_LAYER) {
if ((u32)playbackState->parentLayer < 0x7FFFFFFF) {
@@ -211,10 +211,12 @@ void AudioPlayback_ProcessNotes(void) {
out:
if (playbackState->priority != 0) {
+ //! FAKE:
if (1) {}
- noteSubEu = &note->noteSubEu;
- if ((playbackState->status >= 1) || noteSubEu->bitField0.finished) {
- if ((playbackState->adsr.action.s.state == ADSR_STATE_DISABLED) || noteSubEu->bitField0.finished) {
+ noteSampleState = &note->sampleState;
+ if ((playbackState->status >= 1) || noteSampleState->bitField0.finished) {
+ if ((playbackState->adsr.action.s.state == ADSR_STATE_DISABLED) ||
+ noteSampleState->bitField0.finished) {
if (playbackState->wantedParentLayer != NO_LAYER) {
AudioPlayback_NoteDisable(note);
if (playbackState->wantedParentLayer->channel != NULL) {
@@ -260,14 +262,14 @@ void AudioPlayback_ProcessNotes(void) {
subAttrs.frequency = attrs->freqScale;
subAttrs.velocity = attrs->velocity;
subAttrs.pan = attrs->pan;
- subAttrs.reverbVol = attrs->reverb;
- subAttrs.stereo = attrs->stereo;
+ subAttrs.targetReverbVol = attrs->targetReverbVol;
+ subAttrs.stereoData = attrs->stereoData;
subAttrs.gain = attrs->gain;
subAttrs.filter = attrs->filter;
- subAttrs.unk_14 = attrs->unk_4;
- subAttrs.unk_16 = attrs->unk_6;
- subAttrs.unk_3 = attrs->unk_3;
- bookOffset = noteSubEu->bitField1.bookOffset;
+ subAttrs.combFilterSize = attrs->combFilterSize;
+ subAttrs.combFilterGain = attrs->combFilterGain;
+ subAttrs.surroundEffectIndex = attrs->surroundEffectIndex;
+ bookOffset = noteSampleState->bitField1.bookOffset;
} else {
SequenceLayer* layer = playbackState->parentLayer;
SequenceChannel* channel = playbackState->parentLayer->channel;
@@ -276,34 +278,35 @@ void AudioPlayback_ProcessNotes(void) {
subAttrs.velocity = layer->noteVelocity;
subAttrs.pan = layer->notePan;
- if (layer->unk_08 == 0x80) {
- subAttrs.unk_3 = channel->unk_10;
+ if (layer->surroundEffectIndex == 0x80) {
+ subAttrs.surroundEffectIndex = channel->surroundEffectIndex;
} else {
- subAttrs.unk_3 = layer->unk_08;
+ subAttrs.surroundEffectIndex = layer->surroundEffectIndex;
}
- if (layer->stereo.s.bit2 == 0) {
- subAttrs.stereo = channel->stereo;
+ if (layer->stereoData.type == 0) {
+ subAttrs.stereoData = channel->stereoData;
} else {
- subAttrs.stereo = layer->stereo;
+ subAttrs.stereoData = layer->stereoData;
}
if (layer->unk_0A.s.bit_2 == 1) {
- subAttrs.reverbVol = channel->reverb;
+ subAttrs.targetReverbVol = channel->targetReverbVol;
} else {
- subAttrs.reverbVol = layer->unk_09;
+ subAttrs.targetReverbVol = layer->targetReverbVol;
}
if (layer->unk_0A.s.bit_9 == 1) {
subAttrs.gain = channel->gain;
} else {
subAttrs.gain = 0;
+ //! FAKE:
if (1) {}
}
subAttrs.filter = channel->filter;
- subAttrs.unk_14 = channel->unk_0F;
- subAttrs.unk_16 = channel->unk_20;
+ subAttrs.combFilterSize = channel->combFilterSize;
+ subAttrs.combFilterGain = channel->combFilterGain;
bookOffset = channel->bookOffset & 0x7;
if (channel->seqPlayer->muted && (channel->muteFlags & MUTE_FLAGS_3)) {
@@ -315,8 +318,8 @@ void AudioPlayback_ProcessNotes(void) {
subAttrs.frequency *= playbackState->vibratoFreqScale * playbackState->portamentoFreqScale;
subAttrs.frequency *= gAudioContext.audioBufferParameters.resampleRate;
subAttrs.velocity *= scale;
- AudioPlayback_InitNoteSub(note, noteSubEu2, &subAttrs);
- noteSubEu->bitField1.bookOffset = bookOffset;
+ AudioPlayback_InitSampleState(note, sampleState, &subAttrs);
+ noteSampleState->bitField1.bookOffset = bookOffset;
skip:;
}
}
@@ -500,15 +503,15 @@ void AudioPlayback_SeqLayerDecayRelease(SequenceLayer* layer, s32 target) {
channel = layer->channel;
if (layer->unk_0A.s.bit_2 == 1) {
- attrs->reverb = channel->reverb;
+ attrs->targetReverbVol = channel->targetReverbVol;
} else {
- attrs->reverb = layer->unk_09;
+ attrs->targetReverbVol = layer->targetReverbVol;
}
- if (layer->unk_08 == 0x80) {
- attrs->unk_3 = channel->unk_10;
+ if (layer->surroundEffectIndex == 0x80) {
+ attrs->surroundEffectIndex = channel->surroundEffectIndex;
} else {
- attrs->unk_3 = layer->unk_08;
+ attrs->surroundEffectIndex = layer->surroundEffectIndex;
}
if (layer->unk_0A.s.bit_9 == 1) {
@@ -526,20 +529,20 @@ void AudioPlayback_SeqLayerDecayRelease(SequenceLayer* layer, s32 target) {
attrs->filter = attrs->filterBuf;
}
- attrs->unk_6 = channel->unk_20;
- attrs->unk_4 = channel->unk_0F;
+ attrs->combFilterGain = channel->combFilterGain;
+ attrs->combFilterSize = channel->combFilterSize;
if (channel->seqPlayer->muted && (channel->muteFlags & MUTE_FLAGS_3)) {
- note->noteSubEu.bitField0.finished = true;
+ note->sampleState.bitField0.finished = true;
}
- if (layer->stereo.asByte == 0) {
- attrs->stereo = channel->stereo;
+ if (layer->stereoData.asByte == 0) {
+ attrs->stereoData = channel->stereoData;
} else {
- attrs->stereo = layer->stereo;
+ attrs->stereoData = layer->stereoData;
}
note->playbackState.priority = channel->someOtherPriority;
} else {
- attrs->stereo = layer->stereo;
+ attrs->stereoData = layer->stereoData;
note->playbackState.priority = 1;
}
@@ -620,7 +623,7 @@ s32 AudioPlayback_BuildSyntheticWave(Note* note, SequenceLayer* layer, s32 waveI
// Save the pointer to the synthethic wave
// waveId index starts at 128, there are WAVE_SAMPLE_COUNT samples to read from
- note->noteSubEu.waveSampleAddr = &gWaveSamples[waveId - 128][harmonicIndex * WAVE_SAMPLE_COUNT];
+ note->sampleState.waveSampleAddr = &gWaveSamples[waveId - 128][harmonicIndex * WAVE_SAMPLE_COUNT];
return harmonicIndex;
}
@@ -638,7 +641,7 @@ void AudioPlayback_InitSyntheticWave(Note* note, SequenceLayer* layer) {
curHarmonicIndex = AudioPlayback_BuildSyntheticWave(note, layer, waveId);
if (curHarmonicIndex != prevHarmonicIndex) {
- note->noteSubEu.harmonicIndexCurAndPrev = (curHarmonicIndex << 2) + prevHarmonicIndex;
+ note->sampleState.harmonicIndexCurAndPrev = (curHarmonicIndex << 2) + prevHarmonicIndex;
}
}
@@ -808,7 +811,7 @@ void AudioPlayback_NoteInitForLayer(Note* note, SequenceLayer* layer) {
s16 instId;
SequenceChannel* channel = layer->channel;
NotePlaybackState* playbackState = &note->playbackState;
- NoteSubEu* noteSubEu = &note->noteSubEu;
+ NoteSampleState* noteSampleState = &note->sampleState;
playbackState->prevParentLayer = NO_LAYER;
playbackState->parentLayer = layer;
@@ -825,28 +828,28 @@ void AudioPlayback_NoteInitForLayer(Note* note, SequenceLayer* layer) {
if (instId == 0xFF) {
instId = channel->instOrWave;
}
- noteSubEu->tunedSample = layer->tunedSample;
+ noteSampleState->tunedSample = layer->tunedSample;
if (instId >= 0x80 && instId < 0xC0) {
- noteSubEu->bitField1.isSyntheticWave = true;
+ noteSampleState->bitField1.isSyntheticWave = true;
} else {
- noteSubEu->bitField1.isSyntheticWave = false;
+ noteSampleState->bitField1.isSyntheticWave = false;
}
- if (noteSubEu->bitField1.isSyntheticWave) {
+ if (noteSampleState->bitField1.isSyntheticWave) {
AudioPlayback_BuildSyntheticWave(note, layer, instId);
} else if (channel->startSamplePos == 1) {
- playbackState->startSamplePos = noteSubEu->tunedSample->sample->loop->start;
+ playbackState->startSamplePos = noteSampleState->tunedSample->sample->loop->start;
} else {
playbackState->startSamplePos = channel->startSamplePos;
- if (playbackState->startSamplePos >= noteSubEu->tunedSample->sample->loop->end) {
+ if (playbackState->startSamplePos >= noteSampleState->tunedSample->sample->loop->loopEnd) {
playbackState->startSamplePos = 0;
}
}
playbackState->fontId = channel->fontId;
playbackState->stereoHeadsetEffects = channel->stereoHeadsetEffects;
- noteSubEu->bitField1.reverbIndex = channel->reverbIndex & 3;
+ noteSampleState->bitField1.reverbIndex = channel->reverbIndex & 3;
}
void func_801963E8(Note* note, SequenceLayer* layer) {
@@ -987,7 +990,7 @@ void AudioPlayback_NoteInitAll(void) {
for (i = 0; i < gAudioContext.numNotes; i++) {
note = &gAudioContext.notes[i];
- note->noteSubEu = gZeroNoteSub;
+ note->sampleState = gZeroedSampleState;
note->playbackState.priority = 0;
note->playbackState.status = PLAYBACK_STATUS_0;
note->playbackState.parentLayer = NO_LAYER;
@@ -1002,7 +1005,8 @@ void AudioPlayback_NoteInitAll(void) {
note->playbackState.portamento.speed = 0;
note->playbackState.stereoHeadsetEffects = false;
note->playbackState.startSamplePos = 0;
- note->synthesisState.synthesisBuffers = AudioHeap_AllocDmaMemory(&gAudioContext.miscPool, 0x2E0);
- note->playbackState.attributes.filterBuf = AudioHeap_AllocDmaMemory(&gAudioContext.miscPool, 0x10);
+ note->synthesisState.synthesisBuffers =
+ AudioHeap_AllocDmaMemory(&gAudioContext.miscPool, sizeof(NoteSynthesisBuffers));
+ note->playbackState.attributes.filterBuf = AudioHeap_AllocDmaMemory(&gAudioContext.miscPool, FILTER_SIZE);
}
}
diff --git a/src/code/audio/audio_seqplayer.c b/src/code/audio/audio_seqplayer.c
index a8573e33d..bc5115f8f 100644
--- a/src/code/audio/audio_seqplayer.c
+++ b/src/code/audio/audio_seqplayer.c
@@ -282,17 +282,17 @@ void AudioSeq_InitSequenceChannel(SequenceChannel* channel) {
channel->transposition = 0;
channel->largeNotes = false;
channel->bookOffset = 0;
- channel->stereo.asByte = 0;
+ channel->stereoData.asByte = 0;
channel->changes.asByte = 0xFF;
channel->scriptState.depth = 0;
channel->newPan = 0x40;
channel->panChannelWeight = 0x80;
- channel->unk_10 = 0xFF;
+ channel->surroundEffectIndex = 0xFF;
channel->velocityRandomVariance = 0;
channel->gateTimeRandomVariance = 0;
channel->noteUnused = NULL;
channel->reverbIndex = 0;
- channel->reverb = 0;
+ channel->targetReverbVol = 0;
channel->gain = 0;
channel->notePriority = 3;
channel->someOtherPriority = 1;
@@ -308,8 +308,8 @@ void AudioSeq_InitSequenceChannel(SequenceChannel* channel) {
channel->vibrato.vibratoExtentChangeDelay = 0;
channel->vibrato.vibratoDelay = 0;
channel->filter = NULL;
- channel->unk_20 = 0;
- channel->unk_0F = 0;
+ channel->combFilterGain = 0;
+ channel->combFilterSize = 0;
channel->volume = 1.0f;
channel->volumeScale = 1.0f;
channel->freqScale = 1.0f;
@@ -345,7 +345,7 @@ s32 AudioSeq_SeqChannelSetLayer(SequenceChannel* channel, s32 layerIndex) {
layer->channel = channel;
layer->adsr = channel->adsr;
layer->adsr.decayIndex = 0;
- layer->unk_09 = channel->reverb;
+ layer->targetReverbVol = channel->targetReverbVol;
layer->enabled = true;
layer->finished = false;
layer->stopSomething = false;
@@ -355,8 +355,8 @@ s32 AudioSeq_SeqChannelSetLayer(SequenceChannel* channel, s32 layerIndex) {
layer->bit1 = false;
layer->notePropertiesNeedInit = false;
layer->gateTime = 0x80;
- layer->unk_08 = 0x80;
- layer->stereo.asByte = 0;
+ layer->surroundEffectIndex = 0x80;
+ layer->stereoData.asByte = 0;
layer->portamento.mode = PORTAMENTO_MODE_OFF;
layer->scriptState.depth = 0;
layer->pan = 0x40;
@@ -782,7 +782,7 @@ s32 AudioSeq_SeqLayerProcessScriptStep2(SequenceLayer* layer) {
break;
case 0xCD: // layer: stereo effects
- layer->stereo.asByte = AudioSeq_ScriptReadU8(state);
+ layer->stereoData.asByte = AudioSeq_ScriptReadU8(state);
break;
case 0xCE: // layer: bend pitch
@@ -796,7 +796,7 @@ s32 AudioSeq_SeqLayerProcessScriptStep2(SequenceLayer* layer) {
break;
case 0xF1: // layer:
- layer->unk_08 = AudioSeq_ScriptReadU8(state);
+ layer->surroundEffectIndex = AudioSeq_ScriptReadU8(state);
break;
default:
@@ -991,13 +991,14 @@ s32 AudioSeq_SeqLayerProcessScriptStep4(SequenceLayer* layer, s32 cmd) {
if (layer->delay == 0) {
if (layer->tunedSample != NULL) {
- time = layer->tunedSample->sample->loop->end;
+ time = layer->tunedSample->sample->loop->loopEnd;
} else {
time = 0.0f;
}
time *= seqPlayer->tempo;
time *= gAudioContext.unk_2870;
time /= layer->freqScale;
+ //! FAKE:
if (1) {}
if (time > 0x7FFE) {
time = 0x7FFE;
@@ -1416,9 +1417,9 @@ void AudioSeq_SequenceChannelProcessScript(SequenceChannel* channel) {
channel->vibrato.vibratoDelay = cmd * 16;
break;
- case 0xD4: // channel: set reverb
+ case 0xD4: // channel: set reverb volume
cmd = (u8)cmdArgs[0];
- channel->reverb = cmd;
+ channel->targetReverbVol = cmd;
break;
case 0xC6: // channel: set soundFont
@@ -1491,7 +1492,7 @@ void AudioSeq_SequenceChannelProcessScript(SequenceChannel* channel) {
} else {
channel->stereoHeadsetEffects = false;
}
- channel->stereo.asByte = cmd & 0x7F;
+ channel->stereoData.asByte = cmd & 0x7F;
break;
case 0xD1: // channel: set note allocation policy
@@ -1537,7 +1538,7 @@ void AudioSeq_SequenceChannelProcessScript(SequenceChannel* channel) {
data += 4;
channel->newPan = data[-3];
channel->panChannelWeight = data[-2];
- channel->reverb = data[-1];
+ channel->targetReverbVol = data[-1];
channel->reverbIndex = data[0];
//! @bug: Not marking reverb state as changed
channel->changes.s.pan = true;
@@ -1551,7 +1552,7 @@ void AudioSeq_SequenceChannelProcessScript(SequenceChannel* channel) {
channel->transposition = (s8)AudioSeq_ScriptReadU8(scriptState);
channel->newPan = AudioSeq_ScriptReadU8(scriptState);
channel->panChannelWeight = AudioSeq_ScriptReadU8(scriptState);
- channel->reverb = AudioSeq_ScriptReadU8(scriptState);
+ channel->targetReverbVol = AudioSeq_ScriptReadU8(scriptState);
channel->reverbIndex = AudioSeq_ScriptReadU8(scriptState);
//! @bug: Not marking reverb state as changed
channel->changes.s.pan = true;
@@ -1569,8 +1570,8 @@ void AudioSeq_SequenceChannelProcessScript(SequenceChannel* channel) {
channel->adsr.sustain = 0;
channel->velocityRandomVariance = 0;
channel->gateTimeRandomVariance = 0;
- channel->unk_0F = 0;
- channel->unk_20 = 0;
+ channel->combFilterSize = 0;
+ channel->combFilterGain = 0;
channel->bookOffset = 0;
channel->startSamplePos = 0;
channel->unk_E0 = 0;
@@ -1651,8 +1652,8 @@ void AudioSeq_SequenceChannelProcessScript(SequenceChannel* channel) {
break;
case 0xBB: // channel:
- channel->unk_0F = cmdArgs[0];
- channel->unk_20 = cmdArgs[1];
+ channel->combFilterSize = cmdArgs[0];
+ channel->combFilterGain = cmdArgs[1];
break;
case 0xBC: // channel: add large
@@ -1667,8 +1668,8 @@ void AudioSeq_SequenceChannelProcessScript(SequenceChannel* channel) {
if (cmdArgs[0] < 5) {
if (1) {}
if (gAudioContext.unk_29A8[cmdArgs[0]] != NULL) {
- D_80208E6C = gAudioContext.unk_29A8[cmdArgs[0]];
- scriptState->value = D_80208E6C(scriptState->value, channel);
+ gCustomAudioSeqFunction = gAudioContext.unk_29A8[cmdArgs[0]];
+ scriptState->value = gCustomAudioSeqFunction(scriptState->value, channel);
}
}
break;
@@ -1693,7 +1694,7 @@ void AudioSeq_SequenceChannelProcessScript(SequenceChannel* channel) {
break;
case 0xA4: // channel:
- channel->unk_10 = cmdArgs[0];
+ channel->surroundEffectIndex = cmdArgs[0];
break;
case 0xA5: // channel:
@@ -2197,7 +2198,7 @@ void AudioSeq_ProcessSequences(s32 arg0) {
SequencePlayer* seqPlayer;
u32 i;
- gAudioContext.noteSubEuOffset =
+ gAudioContext.sampleStateOffset =
(gAudioContext.audioBufferParameters.updatesPerFrame - arg0 - 1) * gAudioContext.numNotes;
for (i = 0; i < (u32)gAudioContext.audioBufferParameters.numSequencePlayers; i++) {
diff --git a/src/code/audio/audio_synthesis.c b/src/code/audio/audio_synthesis.c
index 51842a33f..17b3ff4be 100644
--- a/src/code/audio/audio_synthesis.c
+++ b/src/code/audio/audio_synthesis.c
@@ -1,137 +1,1698 @@
#include "global.h"
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_801877D0.s")
+// DMEM Addresses for the RSP
+#define DMEM_TEMP 0x3B0
+#define DMEM_TEMP2 0x3C0
+#define DMEM_SURROUND_TEMP 0x4B0
+#define DMEM_UNCOMPRESSED_NOTE 0x570
+#define DMEM_HAAS_TEMP 0x5B0
+#define DMEM_COMB_TEMP 0x750 // = DMEM_TEMP + DMEM_2CH_SIZE + a bit more
+#define DMEM_COMPRESSED_ADPCM_DATA 0x930 // = DMEM_LEFT_CH
+#define DMEM_LEFT_CH 0x930
+#define DMEM_RIGHT_CH 0xAD0
+#define DMEM_WET_TEMP 0x3D0
+#define DMEM_WET_SCRATCH 0x710 // = DMEM_WET_TEMP + DMEM_2CH_SIZE
+#define DMEM_WET_LEFT_CH 0xC70
+#define DMEM_WET_RIGHT_CH 0xE10 // = DMEM_WET_LEFT_CH + DMEM_1CH_SIZE
+
+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;
+
+Acmd* AudioSynth_SaveResampledReverbSamplesImpl(Acmd* cmd, u16 dmem, u16 arg2, uintptr_t arg3);
+Acmd* AudioSynth_LoadReverbSamplesImpl(Acmd* cmd, u16 dmem, u16 startPos, s32 size, SynthesisReverb* reverb);
+Acmd* AudioSynth_SaveReverbSamplesImpl(Acmd* cmd, u16 dmem, u16 startPos, s32 size, SynthesisReverb* reverb);
+Acmd* AudioSynth_ProcessSamples(s16* aiBuf, s32 numSamplesPerUpdate, Acmd* cmd, s32 updateIndex);
+Acmd* AudioSynth_ProcessSample(s32 noteIndex, NoteSampleState* sampleState, NoteSynthesisState* synthState, s16* aiBuf,
+ s32 numSamplesPerUpdate, Acmd* cmd, s32 updateIndex);
+Acmd* AudioSynth_ApplySurroundEffect(Acmd* cmd, NoteSampleState* sampleState, NoteSynthesisState* synthState, s32 size,
+ s32 dmem, s32 flags);
+Acmd* AudioSynth_FinalResample(Acmd* cmd, NoteSynthesisState* synthState, s32 size, u16 pitch, u16 inpDmem,
+ s32 resampleFlags);
+Acmd* AudioSynth_ProcessEnvelope(Acmd* cmd, NoteSampleState* sampleState, NoteSynthesisState* synthState,
+ s32 numSamplesPerUpdate, u16 dmemSrc, s32 haasEffectDelaySide, s32 flags);
+Acmd* AudioSynth_LoadWaveSamples(Acmd* cmd, NoteSampleState* sampleState, NoteSynthesisState* synthState,
+ s32 numSamplesToLoad);
+Acmd* AudioSynth_ApplyHaasEffect(Acmd* cmd, NoteSampleState* sampleState, NoteSynthesisState* synthState, s32 size,
+ s32 flags, s32 haasEffectDelaySide);
+
+s32 D_801D5FB0 = 0;
+
+u32 sEnvMixerOp = _SHIFTL(A_ENVMIXER, 24, 8);
+
+// Store the left dry channel in a temp space to be delayed to produce the haas effect
+u32 sEnvMixerLeftHaasDmemDests =
+ AUDIO_MK_CMD(DMEM_HAAS_TEMP >> 4, DMEM_RIGHT_CH >> 4, DMEM_WET_LEFT_CH >> 4, DMEM_WET_RIGHT_CH >> 4);
+
+// Store the right dry channel in a temp space to be delayed to produce the haas effect
+u32 sEnvMixerRightHaasDmemDests =
+ AUDIO_MK_CMD(DMEM_LEFT_CH >> 4, DMEM_HAAS_TEMP >> 4, DMEM_WET_LEFT_CH >> 4, DMEM_WET_RIGHT_CH >> 4);
+
+u32 sEnvMixerDefaultDmemDests =
+ AUDIO_MK_CMD(DMEM_LEFT_CH >> 4, DMEM_RIGHT_CH >> 4, DMEM_WET_LEFT_CH >> 4, DMEM_WET_RIGHT_CH >> 4);
+
+// Unused Data
+u16 D_801D5FC4[] = {
+ 0x7FFF, 0xD001, 0x3FFF, 0xF001, 0x5FFF, 0x9001, 0x7FFF, 0x8001,
+};
+
+u8 sNumSamplesPerWavePeriod[] = {
+ WAVE_SAMPLE_COUNT / 1, // 1st harmonic
+ WAVE_SAMPLE_COUNT / 2, // 2nd harmonic
+ WAVE_SAMPLE_COUNT / 4, // 4th harmonic
+ WAVE_SAMPLE_COUNT / 8, // 8th harmonic
+};
+
+/**
+ * Add a collection of s16-samples as a single entry to the reverb buffer
+ */
+void AudioSynth_AddReverbBufferEntry(s32 numSamples, s32 updateIndex, s32 reverbIndex) {
+ SynthesisReverb* reverb;
+ ReverbBufferEntry* entry;
+ s32 extraSamples;
+ s32 numSamplesAfterDownsampling;
+ s32 reverbBufPos;
+ s32 temp_t2;
+ s32 temp_t4;
+ s32 count1;
+ s32 count2;
+ s32 nextReverbSubBufPos;
+
+ reverb = &gAudioContext.synthesisReverbs[reverbIndex];
+ entry = &reverb->bufEntry[reverb->curFrame][updateIndex];
+
+ numSamplesAfterDownsampling = numSamples / gAudioContext.synthesisReverbs[reverbIndex].downsampleRate;
+
+ // Apply resampling effect
+ if (gAudioContext.synthesisReverbs[reverbIndex].resampleEffectOn) {
+ if (reverb->downsampleRate == 1) {
+ count1 = 0;
+ count2 = 0;
+
+ numSamplesAfterDownsampling += reverb->resampleEffectExtraSamples;
+
+ entry->saveResampleNumSamples = numSamplesAfterDownsampling;
+ entry->loadResamplePitch = ((u16)numSamplesAfterDownsampling << 0xF) / numSamples;
+ entry->saveResamplePitch = (numSamples << 0xF) / (u16)numSamplesAfterDownsampling;
+
+ while (true) {
+ temp_t2 = (entry->loadResamplePitch * numSamples * 2) + reverb->resampleEffectLoadUnk;
+ temp_t4 = temp_t2 >> 0x10;
+
+ if ((temp_t4 != numSamplesAfterDownsampling) && (count1 == 0)) {
+ entry->loadResamplePitch =
+ ((numSamplesAfterDownsampling << 0x10) - reverb->resampleEffectLoadUnk) / (numSamples * 2);
+ count1++;
+ } else {
+ count1++;
+ if (temp_t4 > numSamplesAfterDownsampling) {
+ entry->loadResamplePitch--;
+ } else if (temp_t4 < numSamplesAfterDownsampling) {
+ entry->loadResamplePitch++;
+ } else {
+ break;
+ }
+ }
+ }
+
+ reverb->resampleEffectLoadUnk = temp_t2 & 0xFFFF;
+
+ while (true) {
+ temp_t2 = (entry->saveResamplePitch * numSamplesAfterDownsampling * 2) + reverb->resampleEffectSaveUnk;
+ temp_t4 = temp_t2 >> 0x10;
+
+ if ((temp_t4 != numSamples) && (count2 == 0)) {
+ entry->saveResamplePitch =
+ ((numSamples << 0x10) - reverb->resampleEffectSaveUnk) / (numSamplesAfterDownsampling * 2);
+ count2++;
+ } else {
+ count2++;
+ if (temp_t4 > numSamples) {
+ entry->saveResamplePitch--;
+ } else if (temp_t4 < numSamples) {
+ entry->saveResamplePitch++;
+ } else {
+ break;
+ }
+ }
+ }
+
+ reverb->resampleEffectSaveUnk = temp_t2 & 0xFFFF;
+ }
+ }
+
+ extraSamples = (reverb->nextReverbBufPos + numSamplesAfterDownsampling) - reverb->delayNumSamples;
+ reverbBufPos = reverb->nextReverbBufPos;
+
+ // Add a reverb entry
+ if (extraSamples < 0) {
+ entry->size = numSamplesAfterDownsampling * SAMPLE_SIZE;
+ entry->wrappedSize = 0;
+ entry->startPos = reverb->nextReverbBufPos;
+ reverb->nextReverbBufPos += numSamplesAfterDownsampling;
+ } else {
+ // End of the buffer is reached. Loop back around
+ entry->size = (numSamplesAfterDownsampling - extraSamples) * SAMPLE_SIZE;
+ entry->wrappedSize = extraSamples * SAMPLE_SIZE;
+ entry->startPos = reverb->nextReverbBufPos;
+ reverb->nextReverbBufPos = extraSamples;
+ }
+
+ entry->numSamplesAfterDownsampling = numSamplesAfterDownsampling;
+ entry->numSamples = numSamples;
+
+ // Add a sub-reverb entry
+ if (reverb->subDelay != 0) {
+ nextReverbSubBufPos = reverb->subDelay + reverbBufPos;
+ if (nextReverbSubBufPos >= reverb->delayNumSamples) {
+ nextReverbSubBufPos -= reverb->delayNumSamples;
+ }
+
+ entry = &reverb->subBufEntry[reverb->curFrame][updateIndex];
+ numSamplesAfterDownsampling = numSamples / reverb->downsampleRate;
+ extraSamples = (nextReverbSubBufPos + numSamplesAfterDownsampling) - reverb->delayNumSamples;
+
+ if (extraSamples < 0) {
+ entry->size = numSamplesAfterDownsampling * SAMPLE_SIZE;
+ entry->wrappedSize = 0;
+ entry->startPos = nextReverbSubBufPos;
+ } else {
+ // End of the buffer is reached. Loop back around
+ entry->size = (numSamplesAfterDownsampling - extraSamples) * SAMPLE_SIZE;
+ entry->wrappedSize = extraSamples * SAMPLE_SIZE;
+ entry->startPos = nextReverbSubBufPos;
+ }
+
+ entry->numSamplesAfterDownsampling = numSamplesAfterDownsampling;
+ entry->numSamples = numSamples;
+ }
+}
+
+/**
+ * Sync the sample states between the notes and the list
+ */
+void AudioSynth_SyncSampleStates(s32 updateIndex) {
+ NoteSampleState* noteSampleState;
+ NoteSampleState* sampleState;
+ s32 sampleStateBaseIndex;
+ s32 i;
+
+ sampleStateBaseIndex = gAudioContext.numNotes * updateIndex;
+ for (i = 0; i < gAudioContext.numNotes; i++) {
+ noteSampleState = &gAudioContext.notes[i].sampleState;
+ sampleState = &gAudioContext.sampleStateList[sampleStateBaseIndex + i];
+ if (noteSampleState->bitField0.enabled) {
+ noteSampleState->bitField0.needsInit = false;
+ } else {
+ sampleState->bitField0.enabled = false;
+ }
+
+ noteSampleState->harmonicIndexCurAndPrev = 0;
+ }
+}
+
+Acmd* AudioSynth_Update(Acmd* abiCmdStart, s32* numAbiCmds, s16* aiBufStart, s32 numSamplesPerFrame) {
+ s32 numSamplesPerUpdate;
+ s16* curAiBufPos;
+ Acmd* curCmd = abiCmdStart;
+ s32 reverseUpdateIndex;
+ s32 reverbIndex;
+ SynthesisReverb* reverb;
+
+ for (reverseUpdateIndex = gAudioContext.audioBufferParameters.updatesPerFrame; reverseUpdateIndex > 0;
+ reverseUpdateIndex--) {
+ AudioSeq_ProcessSequences(reverseUpdateIndex - 1);
+ AudioSynth_SyncSampleStates(gAudioContext.audioBufferParameters.updatesPerFrame - reverseUpdateIndex);
+ }
+
+ curAiBufPos = aiBufStart;
+ gAudioContext.adpcmCodeBook = NULL;
+
+ // Process/Update all samples multiple times in a single frame
+ for (reverseUpdateIndex = gAudioContext.audioBufferParameters.updatesPerFrame; reverseUpdateIndex > 0;
+ reverseUpdateIndex--) {
+ if (reverseUpdateIndex == 1) {
+ // Final Update
+ numSamplesPerUpdate = numSamplesPerFrame;
+ } else if ((numSamplesPerFrame / reverseUpdateIndex) >=
+ gAudioContext.audioBufferParameters.numSamplesPerUpdateMax) {
+ numSamplesPerUpdate = gAudioContext.audioBufferParameters.numSamplesPerUpdateMax;
+ } else if ((numSamplesPerFrame / reverseUpdateIndex) <=
+ gAudioContext.audioBufferParameters.numSamplesPerUpdateMin) {
+ numSamplesPerUpdate = gAudioContext.audioBufferParameters.numSamplesPerUpdateMin;
+ } else {
+ numSamplesPerUpdate = gAudioContext.audioBufferParameters.numSamplesPerUpdate;
+ }
+
+ for (reverbIndex = 0; reverbIndex < gAudioContext.numSynthesisReverbs; reverbIndex++) {
+ if (gAudioContext.synthesisReverbs[reverbIndex].useReverb) {
+ AudioSynth_AddReverbBufferEntry(
+ numSamplesPerUpdate, gAudioContext.audioBufferParameters.updatesPerFrame - reverseUpdateIndex,
+ reverbIndex);
+ }
+ }
+
+ curCmd = AudioSynth_ProcessSamples(curAiBufPos, numSamplesPerUpdate, curCmd,
+ gAudioContext.audioBufferParameters.updatesPerFrame - reverseUpdateIndex);
+ numSamplesPerFrame -= numSamplesPerUpdate;
+ curAiBufPos += numSamplesPerUpdate * SAMPLE_SIZE;
+ }
+
+ // Update reverb frame info
+ for (reverbIndex = 0; reverbIndex < gAudioContext.numSynthesisReverbs; reverbIndex++) {
+ if (gAudioContext.synthesisReverbs[reverbIndex].framesToIgnore != 0) {
+ gAudioContext.synthesisReverbs[reverbIndex].framesToIgnore--;
+ }
+ gAudioContext.synthesisReverbs[reverbIndex].curFrame ^= 1;
+ }
+
+ *numAbiCmds = curCmd - abiCmdStart;
+ return curCmd;
+}
+
+void AudioSynth_DisableSampleStates(s32 updateIndex, s32 noteIndex) {
+ NoteSampleState* sampleState;
+ s32 i;
+
+ for (i = updateIndex + 1; i < gAudioContext.audioBufferParameters.updatesPerFrame; i++) {
+ sampleState = &gAudioContext.sampleStateList[(gAudioContext.numNotes * i) + noteIndex];
+ if (sampleState->bitField0.needsInit) {
+ break;
+ }
+ sampleState->bitField0.enabled = false;
+ }
+}
+
+/**
+ * Load reverb samples from a different reverb index
+ */
+Acmd* AudioSynth_LoadMixedReverbSamples(Acmd* cmd, SynthesisReverb* reverb, s16 updateIndex) {
+ ReverbBufferEntry* entry = &reverb->bufEntry[reverb->curFrame][updateIndex];
+
+ cmd = AudioSynth_LoadReverbSamplesImpl(cmd, DMEM_WET_TEMP, entry->startPos, entry->size, reverb);
+ if (entry->wrappedSize != 0) {
+ // Ring buffer wrapped
+ cmd = AudioSynth_LoadReverbSamplesImpl(cmd, DMEM_WET_TEMP + entry->size, 0, entry->wrappedSize, reverb);
+ }
+ return cmd;
+}
+
+/**
+ * Save reverb samples from a different reverb index
+ */
+Acmd* AudioSynth_SaveMixedReverbSamples(Acmd* cmd, SynthesisReverb* reverb, s16 updateIndex) {
+ ReverbBufferEntry* entry = &reverb->bufEntry[reverb->curFrame][updateIndex];
+
+ cmd = AudioSynth_SaveReverbSamplesImpl(cmd, DMEM_WET_TEMP, entry->startPos, entry->size, reverb);
+ if (entry->wrappedSize != 0) {
+ // Ring buffer wrapped
+ cmd = AudioSynth_SaveReverbSamplesImpl(cmd, DMEM_WET_TEMP + entry->size, 0, entry->wrappedSize, reverb);
+ }
+ return cmd;
+}
+
+void AudioSynth_Noop1(void) {
+}
+
+void AudioSynth_ClearBuffer(Acmd* cmd, s32 dmem, s32 size) {
+ aClearBuffer(cmd, dmem, size);
+}
+
+void AudioSynth_Noop2(void) {
+}
+
+void AudioSynth_Noop3(void) {
+}
+
+void AudioSynth_Noop4(void) {
+}
+
+void AudioSynth_Mix(Acmd* cmd, size_t size, s32 gain, s32 dmemIn, s32 dmemOut) {
+ aMix(cmd, size, gain, dmemIn, dmemOut);
+}
+
+void AudioSynth_Noop5(void) {
+}
+
+void AudioSynth_Noop6(void) {
+}
+
+void AudioSynth_Noop7(void) {
+}
+
+void AudioSynth_SetBuffer(Acmd* cmd, s32 flags, s32 dmemIn, s32 dmemOut, size_t size) {
+ aSetBuffer(cmd, flags, dmemIn, dmemOut, size);
+}
+
+void AudioSynth_Noop8(void) {
+}
+
+void AudioSynth_Noop9(void) {
+}
+
+void AudioSynth_DMemMove(Acmd* cmd, s32 dmemIn, s32 dmemOut, size_t size) {
+ // aDMEMMove(cmd, dmemIn, dmemOut, size);
+ cmd->words.w0 = _SHIFTL(A_DMEMMOVE, 24, 8) | _SHIFTL(dmemIn, 0, 24);
+ cmd->words.w1 = _SHIFTL(dmemOut, 16, 16) | _SHIFTL(size, 0, 16);
+}
+
+void AudioSynth_Noop10(void) {
+}
+
+void AudioSynth_Noop11(void) {
+}
+
+void AudioSynth_Noop12(void) {
+}
+
+void AudioSynth_Noop13(void) {
+}
+
+void AudioSynth_InterL(Acmd* cmd, s32 dmemIn, s32 dmemOut, s32 numSamples) {
+ // aInterl(cmd, dmemIn, dmemOut, numSamples);
+ cmd->words.w0 = _SHIFTL(A_INTERL, 24, 8) | _SHIFTL(numSamples, 0, 16);
+ cmd->words.w1 = _SHIFTL(dmemIn, 16, 16) | _SHIFTL(dmemOut, 0, 16);
+}
+
+void AudioSynth_EnvSetup1(Acmd* cmd, s32 reverbVol, s32 rampReverb, s32 rampLeft, s32 rampRight) {
+ aEnvSetup1(cmd, reverbVol, rampReverb, rampLeft, rampRight);
+}
+
+void AudioSynth_Noop14(void) {
+}
+
+void AudioSynth_LoadBuffer(Acmd* cmd, s32 dmemDest, s32 size, void* addrSrc) {
+ aLoadBuffer(cmd, addrSrc, dmemDest, size);
+}
+
+void AudioSynth_SaveBuffer(Acmd* cmd, s32 dmemSrc, s32 size, void* addrDest) {
+ aSaveBuffer(cmd, dmemSrc, addrDest, size);
+}
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80187B64.s")
+void AudioSynth_EnvSetup2(Acmd* cmd, s32 volLeft, s32 volRight) {
+ // aEnvSetup2(cmd, volLeft, volRight);
+ cmd->words.w0 = _SHIFTL(A_ENVSETUP2, 24, 8);
+ cmd->words.w1 = _SHIFTL(volLeft, 16, 16) | _SHIFTL(volRight, 0, 16);
+}
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80187BEC.s")
+void AudioSynth_Noop15(void) {
+}
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80187DE8.s")
+void AudioSynth_Noop16(void) {
+}
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80187E58.s")
+void AudioSynth_Noop17(void) {
+}
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80187F00.s")
+void AudioSynth_S8Dec(Acmd* cmd, s32 flags, s16* state) {
+ aS8Dec(cmd, flags, state);
+}
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80187FA8.s")
+void AudioSynth_HiLoGain(Acmd* cmd, s32 gain, s32 dmemIn, s32 dmemOut, s32 size) {
+ // aHiLoGain(cmd, gain, size, dmemIn, dmemOut);
+ cmd->words.w0 = _SHIFTL(A_HILOGAIN, 24, 8) | _SHIFTL(gain, 16, 8) | _SHIFTL(size, 0, 16);
+ cmd->words.w1 = _SHIFTL(dmemIn, 16, 16) | _SHIFTL(dmemOut, 0, 16);
+}
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80187FB0.s")
+// Remnant of OoT
+void AudioSynth_UnkCmd19(Acmd* cmd, s32 dmem1, s32 dmem2, s32 size, s32 arg4) {
+ cmd->words.w0 = _SHIFTL(A_SPNOOP, 24, 8) | _SHIFTL(arg4, 16, 8) | _SHIFTL(size, 0, 16);
+ cmd->words.w1 = _SHIFTL(dmem1, 16, 16) | _SHIFTL(dmem2, 0, 16);
+}
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80187FD0.s")
+void AudioSynth_Noop18(void) {
+}
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80187FD8.s")
+void AudioSynth_Noop19(void) {
+}
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80187FE0.s")
+void AudioSynth_Noop20(void) {
+}
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80187FE8.s")
+void AudioSynth_Noop21(void) {
+}
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_8018801C.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188024.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_8018802C.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188034.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188068.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188070.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188078.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_801880A4.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_801880AC.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_801880B4.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_801880BC.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_801880C4.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_801880E8.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_8018811C.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188124.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_8018814C.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188174.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188190.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188198.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_801881A0.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_801881A8.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_801881C4.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_801881F8.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188224.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_8018822C.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188234.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_8018823C.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188244.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_8018824C.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188254.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_8018825C.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188264.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188288.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_801882A0.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188304.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_801884A0.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188698.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_8018883C.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_801888E4.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_801889A4.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188A50.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188AFC.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188C48.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188CB4.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188D20.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188D28.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188D68.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188DDC.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188FBC.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80189064.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80189620.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_8018A4B4.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_8018A768.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_8018A808.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_8018ACC4.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_8018AE34.s")
+void AudioSynth_Noop22(void) {
+}
+
+void AudioSynth_Noop23(void) {
+}
+
+void AudioSynth_Noop24(void) {
+}
+
+void AudioSynth_Noop25(void) {
+}
+
+void AudioSynth_LoadFilterBuffer(Acmd* cmd, s32 flags, s32 buf, s16* addr) {
+ aFilter(cmd, flags, buf, addr);
+}
+
+void AudioSynth_LoadFilterSize(Acmd* cmd, size_t size, s16* addr) {
+ aFilter(cmd, 2, size, addr);
+}
+
+/**
+ * Leak some audio from the left reverb channel into the right reverb channel and vice versa (pan)
+ */
+Acmd* AudioSynth_LeakReverb(Acmd* cmd, SynthesisReverb* reverb) {
+ aDMEMMove(cmd++, DMEM_WET_LEFT_CH, DMEM_WET_SCRATCH, DMEM_1CH_SIZE);
+ aMix(cmd++, DMEM_1CH_SIZE >> 4, reverb->leakRtl, DMEM_WET_RIGHT_CH, DMEM_WET_LEFT_CH);
+ aMix(cmd++, DMEM_1CH_SIZE >> 4, reverb->leakLtr, DMEM_WET_SCRATCH, DMEM_WET_RIGHT_CH);
+
+ return cmd;
+}
+
+Acmd* AudioSynth_LoadDownsampledReverbSamples(Acmd* cmd, s32 numSamplesPerUpdate, SynthesisReverb* reverb,
+ s16 updateIndex) {
+ ReverbBufferEntry* entry = &reverb->bufEntry[reverb->curFrame][updateIndex];
+ s16 offsetSize = (entry->startPos & 7) * SAMPLE_SIZE;
+ s16 wrappedOffsetSize = ALIGN16(offsetSize + entry->size);
+
+ cmd = AudioSynth_LoadReverbSamplesImpl(cmd, DMEM_WET_TEMP, entry->startPos - (offsetSize / (s32)SAMPLE_SIZE),
+ DMEM_1CH_SIZE, reverb);
+
+ if (entry->wrappedSize != 0) {
+ // Ring buffer wrapped
+ cmd = AudioSynth_LoadReverbSamplesImpl(cmd, DMEM_WET_TEMP + wrappedOffsetSize, 0,
+ DMEM_1CH_SIZE - wrappedOffsetSize, reverb);
+ }
+
+ aSetBuffer(cmd++, 0, DMEM_WET_TEMP + offsetSize, DMEM_WET_LEFT_CH, numSamplesPerUpdate * SAMPLE_SIZE);
+ aResample(cmd++, reverb->resampleFlags, reverb->downsamplePitch, reverb->leftLoadResampleBuf);
+ aSetBuffer(cmd++, 0, DMEM_WET_TEMP + DMEM_1CH_SIZE + offsetSize, DMEM_WET_RIGHT_CH,
+ numSamplesPerUpdate * SAMPLE_SIZE);
+ aResample(cmd++, reverb->resampleFlags, reverb->downsamplePitch, reverb->rightLoadResampleBuf);
+
+ return cmd;
+}
+
+Acmd* AudioSynth_SaveResampledReverbSamples(Acmd* cmd, SynthesisReverb* reverb, s16 updateIndex) {
+ ReverbBufferEntry* entry = &reverb->bufEntry[reverb->curFrame][updateIndex];
+ s16 numSamples = entry->numSamples;
+ u32 size = numSamples * SAMPLE_SIZE;
+
+ // Left Resample
+ aDMEMMove(cmd++, DMEM_WET_LEFT_CH, DMEM_WET_TEMP, size);
+ aSetBuffer(cmd++, 0, DMEM_WET_TEMP, DMEM_WET_SCRATCH, entry->saveResampleNumSamples * SAMPLE_SIZE);
+ aResample(cmd++, reverb->resampleFlags, entry->saveResamplePitch, reverb->leftSaveResampleBuf);
+
+ cmd = AudioSynth_SaveResampledReverbSamplesImpl(cmd, DMEM_WET_SCRATCH, entry->size,
+ &reverb->leftReverbBuf[entry->startPos]);
+
+ if (entry->wrappedSize != 0) {
+ // Ring buffer wrapped
+ cmd = AudioSynth_SaveResampledReverbSamplesImpl(cmd, entry->size + DMEM_WET_SCRATCH, entry->wrappedSize,
+ reverb->leftReverbBuf);
+ }
+
+ // Right Resample
+ aDMEMMove(cmd++, DMEM_WET_RIGHT_CH, DMEM_WET_TEMP, size);
+ aSetBuffer(cmd++, 0, DMEM_WET_TEMP, DMEM_WET_SCRATCH, entry->saveResampleNumSamples * SAMPLE_SIZE);
+ aResample(cmd++, reverb->resampleFlags, entry->saveResamplePitch, reverb->rightSaveResampleBuf);
+
+ cmd = AudioSynth_SaveResampledReverbSamplesImpl(cmd, DMEM_WET_SCRATCH, entry->size,
+ &reverb->rightReverbBuf[entry->startPos]);
+
+ if (entry->wrappedSize != 0) {
+ // Ring buffer wrapped
+ cmd = AudioSynth_SaveResampledReverbSamplesImpl(cmd, entry->size + DMEM_WET_SCRATCH, entry->wrappedSize,
+ reverb->rightReverbBuf);
+ }
+
+ return cmd;
+}
+
+Acmd* AudioSynth_LoadResampledReverbSamples(Acmd* cmd, s32 numSamplesPerUpdate, SynthesisReverb* reverb,
+ s16 updateIndex) {
+ ReverbBufferEntry* entry = &reverb->bufEntry[reverb->curFrame][updateIndex];
+ s16 offsetSize = (entry->startPos & 7) * SAMPLE_SIZE;
+ s16 wrappedOffsetSize = ALIGN16(offsetSize + entry->size);
+
+ cmd = AudioSynth_LoadReverbSamplesImpl(cmd, DMEM_WET_TEMP, entry->startPos - (offsetSize / (s32)SAMPLE_SIZE),
+ DMEM_1CH_SIZE, reverb);
+
+ if (entry->wrappedSize != 0) {
+ // Ring buffer wrapped
+ cmd = AudioSynth_LoadReverbSamplesImpl(cmd, wrappedOffsetSize + DMEM_WET_TEMP, 0,
+ DMEM_1CH_SIZE - wrappedOffsetSize, reverb);
+ }
+
+ aSetBuffer(cmd++, 0, DMEM_WET_TEMP + offsetSize, DMEM_WET_LEFT_CH, numSamplesPerUpdate * SAMPLE_SIZE);
+ aResample(cmd++, reverb->resampleFlags, entry->loadResamplePitch, reverb->leftLoadResampleBuf);
+ aSetBuffer(cmd++, 0, DMEM_WET_TEMP + DMEM_1CH_SIZE + offsetSize, DMEM_WET_RIGHT_CH,
+ numSamplesPerUpdate * SAMPLE_SIZE);
+ aResample(cmd++, reverb->resampleFlags, entry->loadResamplePitch, reverb->rightLoadResampleBuf);
+
+ return cmd;
+}
+
+/**
+ * Apply a filter (convolution) to each reverb channel.
+ */
+Acmd* AudioSynth_FilterReverb(Acmd* cmd, s32 size, SynthesisReverb* reverb) {
+ if (reverb->filterLeft != NULL) {
+ aFilter(cmd++, 2, size, reverb->filterLeft);
+ aFilter(cmd++, reverb->resampleFlags, DMEM_WET_LEFT_CH, reverb->filterLeftState);
+ }
+
+ if (reverb->filterRight != NULL) {
+ aFilter(cmd++, 2, size, reverb->filterRight);
+ aFilter(cmd++, reverb->resampleFlags, DMEM_WET_RIGHT_CH, reverb->filterRightState);
+ }
+
+ return cmd;
+}
+
+/**
+ * Mix in reverb from a different reverb index
+ */
+Acmd* AudioSynth_MixOtherReverbIndex(Acmd* cmd, SynthesisReverb* reverb, s32 updateIndex) {
+ SynthesisReverb* mixReverb;
+
+ if (reverb->mixReverbIndex >= gAudioContext.numSynthesisReverbs) {
+ return cmd;
+ }
+
+ mixReverb = &gAudioContext.synthesisReverbs[reverb->mixReverbIndex];
+ if (mixReverb->downsampleRate == 1) {
+ cmd = AudioSynth_LoadMixedReverbSamples(cmd, mixReverb, updateIndex);
+ aMix(cmd++, DMEM_2CH_SIZE >> 4, reverb->mixReverbStrength, DMEM_WET_LEFT_CH, DMEM_WET_TEMP);
+ cmd = AudioSynth_SaveMixedReverbSamples(cmd, mixReverb, updateIndex);
+ }
+
+ return cmd;
+}
+
+Acmd* AudioSynth_LoadDefaultReverbSamples(Acmd* cmd, s32 numSamplesPerUpdate, SynthesisReverb* reverb,
+ s16 updateIndex) {
+ ReverbBufferEntry* entry = &reverb->bufEntry[reverb->curFrame][updateIndex];
+
+ cmd = AudioSynth_LoadReverbSamplesImpl(cmd, DMEM_WET_LEFT_CH, entry->startPos, entry->size, reverb);
+ if (entry->wrappedSize != 0) {
+ // Ring buffer wrapped
+ cmd = AudioSynth_LoadReverbSamplesImpl(cmd, DMEM_WET_LEFT_CH + entry->size, 0, entry->wrappedSize, reverb);
+ }
+
+ return cmd;
+}
+
+Acmd* AudioSynth_LoadSubReverbSamples(Acmd* cmd, s32 numSamplesPerUpdate, SynthesisReverb* reverb, s16 updateIndex) {
+ ReverbBufferEntry* subEntry = &reverb->subBufEntry[reverb->curFrame][updateIndex];
+
+ cmd = AudioSynth_LoadReverbSamplesImpl(cmd, DMEM_WET_LEFT_CH, subEntry->startPos, subEntry->size, reverb);
+ if (subEntry->wrappedSize != 0) {
+ // Ring buffer wrapped
+ cmd =
+ AudioSynth_LoadReverbSamplesImpl(cmd, DMEM_WET_LEFT_CH + subEntry->size, 0, subEntry->wrappedSize, reverb);
+ }
+
+ return cmd;
+}
+
+Acmd* AudioSynth_SaveResampledReverbSamplesImpl(Acmd* cmd, u16 dmem, u16 size, uintptr_t startAddr) {
+ s32 startAddrAlignDropped;
+ u32 endAddr;
+ s32 endAddrAlignDropped;
+
+ endAddr = startAddr + size;
+
+ endAddrAlignDropped = endAddr & 0xF;
+ if (endAddrAlignDropped != 0) {
+ aLoadBuffer(cmd++, (endAddr - endAddrAlignDropped), DMEM_TEMP, 0x10);
+ aDMEMMove(cmd++, dmem, DMEM_TEMP2, size);
+ aDMEMMove(cmd++, DMEM_TEMP + endAddrAlignDropped, size + DMEM_TEMP2, 0x10 - endAddrAlignDropped);
+
+ size += (0x10 - endAddrAlignDropped);
+ dmem = DMEM_TEMP2;
+ }
+
+ startAddrAlignDropped = startAddr & 0xF;
+ if (startAddrAlignDropped != 0) {
+ aLoadBuffer(cmd++, startAddr - startAddrAlignDropped, DMEM_TEMP, 0x10);
+ aDMEMMove(cmd++, dmem, startAddrAlignDropped + DMEM_TEMP, size);
+
+ size += startAddrAlignDropped;
+ dmem = DMEM_TEMP;
+ }
+
+ aSaveBuffer(cmd++, dmem, startAddr - startAddrAlignDropped, size);
+
+ return cmd;
+}
+
+Acmd* AudioSynth_LoadReverbSamplesImpl(Acmd* cmd, u16 dmem, u16 startPos, s32 size, SynthesisReverb* reverb) {
+ aLoadBuffer(cmd++, &reverb->leftReverbBuf[startPos], dmem, size);
+ aLoadBuffer(cmd++, &reverb->rightReverbBuf[startPos], dmem + DMEM_1CH_SIZE, size);
+
+ return cmd;
+}
+
+Acmd* AudioSynth_SaveReverbSamplesImpl(Acmd* cmd, u16 dmem, u16 startPos, s32 size, SynthesisReverb* reverb) {
+ aSaveBuffer(cmd++, dmem, &reverb->leftReverbBuf[startPos], size);
+ aSaveBuffer(cmd++, dmem + DMEM_1CH_SIZE, &reverb->rightReverbBuf[startPos], size);
+
+ return cmd;
+}
+
+void AudioSynth_Noop26(void) {
+}
+
+Acmd* AudioSynth_LoadSubReverbSamplesWithoutDownsample(Acmd* cmd, s32 numSamplesPerUpdate, SynthesisReverb* reverb,
+ s16 updateIndex) {
+ if (reverb->downsampleRate == 1) {
+ cmd = AudioSynth_LoadSubReverbSamples(cmd, numSamplesPerUpdate, reverb, updateIndex);
+ }
+
+ return cmd;
+}
+
+Acmd* AudioSynth_LoadReverbSamples(Acmd* cmd, s32 numSamplesPerUpdate, SynthesisReverb* reverb, s16 updateIndex) {
+ if (reverb->downsampleRate == 1) {
+ if (reverb->resampleEffectOn) {
+ cmd = AudioSynth_LoadResampledReverbSamples(cmd, numSamplesPerUpdate, reverb, updateIndex);
+ } else {
+ cmd = AudioSynth_LoadDefaultReverbSamples(cmd, numSamplesPerUpdate, reverb, updateIndex);
+ }
+ } else {
+ cmd = AudioSynth_LoadDownsampledReverbSamples(cmd, numSamplesPerUpdate, reverb, updateIndex);
+ }
+
+ return cmd;
+}
+
+Acmd* AudioSynth_SaveReverbSamples(Acmd* cmd, SynthesisReverb* reverb, s16 updateIndex) {
+ ReverbBufferEntry* entry = &reverb->bufEntry[reverb->curFrame][updateIndex];
+ s32 downsampleRate;
+ s32 numSamples;
+
+ if (reverb->downsampleRate == 1) {
+ if (reverb->resampleEffectOn) {
+ cmd = AudioSynth_SaveResampledReverbSamples(cmd, reverb, updateIndex);
+ } else {
+ // Put the oldest samples in the ring buffer into the wet channels
+ cmd = AudioSynth_SaveReverbSamplesImpl(cmd, DMEM_WET_LEFT_CH, entry->startPos, entry->size, reverb);
+ if (entry->wrappedSize != 0) {
+ // Ring buffer wrapped
+ cmd = AudioSynth_SaveReverbSamplesImpl(cmd, DMEM_WET_LEFT_CH + entry->size, 0, entry->wrappedSize,
+ reverb);
+ }
+ }
+ } else {
+ //! FAKE:
+ if (1) {}
+
+ downsampleRate = reverb->downsampleRate;
+ numSamples = 13 * SAMPLES_PER_FRAME;
+
+ while (downsampleRate >= 2) {
+ aInterl(cmd++, DMEM_WET_LEFT_CH, DMEM_WET_LEFT_CH, numSamples);
+ aInterl(cmd++, DMEM_WET_RIGHT_CH, DMEM_WET_RIGHT_CH, numSamples);
+ downsampleRate >>= 1;
+ numSamples >>= 1;
+ }
+
+ if (entry->size != 0) {
+ cmd = AudioSynth_SaveResampledReverbSamplesImpl(cmd, DMEM_WET_LEFT_CH, entry->size,
+ &reverb->leftReverbBuf[entry->startPos]);
+ cmd = AudioSynth_SaveResampledReverbSamplesImpl(cmd, DMEM_WET_RIGHT_CH, entry->size,
+ &reverb->rightReverbBuf[entry->startPos]);
+ }
+
+ if (entry->wrappedSize != 0) {
+ cmd = AudioSynth_SaveResampledReverbSamplesImpl(cmd, entry->size + DMEM_WET_LEFT_CH, entry->wrappedSize,
+ reverb->leftReverbBuf);
+ cmd = AudioSynth_SaveResampledReverbSamplesImpl(cmd, entry->size + DMEM_WET_RIGHT_CH, entry->wrappedSize,
+ reverb->rightReverbBuf);
+ }
+ }
+
+ reverb->resampleFlags = 0;
+
+ return cmd;
+}
+
+Acmd* AudioSynth_SaveSubReverbSamples(Acmd* cmd, SynthesisReverb* reverb, s16 updateIndex) {
+ ReverbBufferEntry* subEntry = &reverb->subBufEntry[reverb->curFrame][updateIndex];
+
+ cmd = AudioSynth_SaveReverbSamplesImpl(cmd, DMEM_WET_LEFT_CH, subEntry->startPos, subEntry->size, reverb);
+ if (subEntry->wrappedSize != 0) {
+ // Ring buffer wrapped
+ cmd =
+ AudioSynth_SaveReverbSamplesImpl(cmd, DMEM_WET_LEFT_CH + subEntry->size, 0, subEntry->wrappedSize, reverb);
+ }
+
+ return cmd;
+}
+
+/**
+ * Process all samples embedded in a note. Every sample has numSamplesPerUpdate processed,
+ * and each of those are mixed together into both DMEM_LEFT_CH and DMEM_RIGHT_CH
+ */
+Acmd* AudioSynth_ProcessSamples(s16* aiBuf, s32 numSamplesPerUpdate, Acmd* cmd, s32 updateIndex) {
+ s32 size;
+ u8 noteIndices[0x58];
+ s16 noteCount = 0;
+ s16 reverbIndex;
+ SynthesisReverb* reverb;
+ s32 useReverb;
+ s32 sampleStateOffset = gAudioContext.numNotes * updateIndex;
+ s32 i;
+
+ if (gAudioContext.numSynthesisReverbs == 0) {
+ for (i = 0; i < gAudioContext.numNotes; i++) {
+ if (gAudioContext.sampleStateList[sampleStateOffset + i].bitField0.enabled) {
+ noteIndices[noteCount++] = i;
+ }
+ }
+ } else {
+ NoteSampleState* sampleState;
+
+ for (reverbIndex = 0; reverbIndex < gAudioContext.numSynthesisReverbs; reverbIndex++) {
+ for (i = 0; i < gAudioContext.numNotes; i++) {
+ sampleState = &gAudioContext.sampleStateList[sampleStateOffset + i];
+ if (sampleState->bitField0.enabled && (sampleState->bitField1.reverbIndex == reverbIndex)) {
+ noteIndices[noteCount++] = i;
+ }
+ }
+ }
+
+ for (i = 0; i < gAudioContext.numNotes; i++) {
+ sampleState = &gAudioContext.sampleStateList[sampleStateOffset + i];
+ if (sampleState->bitField0.enabled &&
+ (sampleState->bitField1.reverbIndex >= gAudioContext.numSynthesisReverbs)) {
+ noteIndices[noteCount++] = i;
+ }
+ }
+ }
+
+ aClearBuffer(cmd++, DMEM_LEFT_CH, DMEM_2CH_SIZE);
+
+ i = 0;
+ for (reverbIndex = 0; reverbIndex < gAudioContext.numSynthesisReverbs; reverbIndex++) {
+ s32 subDelay;
+ NoteSampleState* sampleState;
+
+ reverb = &gAudioContext.synthesisReverbs[reverbIndex];
+ useReverb = reverb->useReverb;
+ if (useReverb) {
+
+ // Loads reverb samples from DRAM (ringBuffer) into DMEM (DMEM_WET_LEFT_CH)
+ cmd = AudioSynth_LoadReverbSamples(cmd, numSamplesPerUpdate, reverb, updateIndex);
+
+ // Mixes reverb sample into the main dry channel
+ // reverb->volume is always set to 0x7FFF (audio spec), and DMEM_LEFT_CH is cleared before reverbs.
+ // So this is essentially a DMEMmove from DMEM_WET_LEFT_CH to DMEM_LEFT_CH
+ aMix(cmd++, DMEM_2CH_SIZE >> 4, reverb->volume, DMEM_WET_LEFT_CH, DMEM_LEFT_CH);
+
+ subDelay = reverb->subDelay;
+ if (subDelay != 0) {
+ aDMEMMove(cmd++, DMEM_WET_LEFT_CH, DMEM_WET_TEMP, DMEM_2CH_SIZE);
+ }
+
+ // Decays reverb over time. The (+ 0x8000) here is -100%
+ aMix(cmd++, DMEM_2CH_SIZE >> 4, reverb->decayRatio + 0x8000, DMEM_WET_LEFT_CH, DMEM_WET_LEFT_CH);
+
+ if (((reverb->leakRtl != 0) || (reverb->leakLtr != 0)) && (gAudioContext.soundMode != SOUNDMODE_MONO)) {
+ cmd = AudioSynth_LeakReverb(cmd, reverb);
+ }
+
+ if (subDelay != 0) {
+ if (reverb->mixReverbIndex != REVERB_INDEX_NONE) {
+ cmd = AudioSynth_MixOtherReverbIndex(cmd, reverb, updateIndex);
+ }
+ cmd = AudioSynth_SaveReverbSamples(cmd, reverb, updateIndex);
+ cmd = AudioSynth_LoadSubReverbSamplesWithoutDownsample(cmd, numSamplesPerUpdate, reverb, updateIndex);
+ aMix(cmd++, DMEM_2CH_SIZE >> 4, reverb->subVolume, DMEM_WET_TEMP, DMEM_WET_LEFT_CH);
+ }
+ }
+
+ while (i < noteCount) {
+ sampleState = &gAudioContext.sampleStateList[sampleStateOffset + noteIndices[i]];
+ if (sampleState->bitField1.reverbIndex != reverbIndex) {
+ break;
+ }
+ cmd = AudioSynth_ProcessSample(noteIndices[i], sampleState,
+ &gAudioContext.notes[noteIndices[i]].synthesisState, aiBuf,
+ numSamplesPerUpdate, cmd, updateIndex);
+ i++;
+ }
+
+ if (useReverb) {
+ if ((reverb->filterLeft != NULL) || (reverb->filterRight != NULL)) {
+ cmd = AudioSynth_FilterReverb(cmd, numSamplesPerUpdate * SAMPLE_SIZE, reverb);
+ }
+
+ // Saves the wet channel sample from DMEM (DMEM_WET_LEFT_CH) into (ringBuffer) DRAM for future use
+ if (subDelay != 0) {
+ cmd = AudioSynth_SaveSubReverbSamples(cmd, reverb, updateIndex);
+ } else {
+ if (reverb->mixReverbIndex != REVERB_INDEX_NONE) {
+ cmd = AudioSynth_MixOtherReverbIndex(cmd, reverb, updateIndex);
+ }
+ cmd = AudioSynth_SaveReverbSamples(cmd, reverb, updateIndex);
+ }
+ }
+ }
+
+ while (i < noteCount) {
+ cmd = AudioSynth_ProcessSample(
+ noteIndices[i], &gAudioContext.sampleStateList[sampleStateOffset + noteIndices[i]],
+ &gAudioContext.notes[noteIndices[i]].synthesisState, aiBuf, numSamplesPerUpdate, cmd, updateIndex);
+ i++;
+ }
+
+ size = numSamplesPerUpdate * SAMPLE_SIZE;
+ aInterleave(cmd++, DMEM_TEMP, DMEM_LEFT_CH, DMEM_RIGHT_CH, size);
+
+ if (gCustomAudioSynthFunction != NULL) {
+ cmd = gCustomAudioSynthFunction(cmd, 2 * size, updateIndex);
+ }
+ aSaveBuffer(cmd++, DMEM_TEMP, aiBuf, 2 * size);
+
+ return cmd;
+}
+
+Acmd* AudioSynth_ProcessSample(s32 noteIndex, NoteSampleState* sampleState, NoteSynthesisState* synthState, s16* aiBuf,
+ s32 numSamplesPerUpdate, Acmd* cmd, s32 updateIndex) {
+ s32 pad1[2];
+ void* reverbAddrSrc;
+ Sample* sample;
+ AdpcmLoop* loopInfo;
+ s32 numSamplesUntilEnd;
+ s32 numSamplesInThisIteration;
+ s32 sampleFinished;
+ s32 loopToPoint;
+ s32 flags;
+ u16 frequencyFixedPoint;
+ s32 gain;
+ s32 frameIndex;
+ s32 skipBytes;
+ void* combFilterState;
+ s32 numSamplesToDecode;
+ s32 numFirstFrameSamplesToIgnore;
+ u8* sampleAddr;
+ u32 numSamplesToLoadFixedPoint;
+ s32 numSamplesToLoadAdj;
+ s32 numSamplesProcessed;
+ s32 sampleEndPos;
+ s32 numSamplesToProcess;
+ s32 dmemUncompressedAddrOffset2;
+ s32 pad2[3];
+ s32 numSamplesInFirstFrame;
+ s32 numTrailingSamplesToIgnore;
+ s32 pad3[3];
+ s32 frameSize;
+ s32 numFramesToDecode;
+ s32 skipInitialSamples;
+ s32 zeroOffset;
+ u8* samplesToLoadAddr;
+ s32 numParts;
+ s32 curPart;
+ s32 sampleDataChunkAlignPad;
+ s32 haasEffectDelaySide;
+ s32 numSamplesToLoadFirstPart;
+ u16 sampleDmemBeforeResampling;
+ s32 sampleAddrOffset;
+ s32 combFilterDmem;
+ s32 dmemUncompressedAddrOffset1;
+ Note* note;
+ u32 numSamplesToLoad;
+ u16 combFilterSize;
+ u16 combFilterGain;
+ s16* filter;
+ s32 bookOffset = sampleState->bitField1.bookOffset;
+ s32 finished = sampleState->bitField0.finished;
+ s32 sampleDataChunkSize;
+ s16 sampleDataDmemAddr;
+
+ note = &gAudioContext.notes[noteIndex];
+ flags = A_CONTINUE;
+
+ // Initialize the synthesis state
+ if (sampleState->bitField0.needsInit == true) {
+ flags = A_INIT;
+ synthState->atLoopPoint = false;
+ synthState->stopLoop = false;
+ synthState->samplePosInt = note->playbackState.startSamplePos;
+ synthState->samplePosFrac = 0;
+ synthState->curVolLeft = 0;
+ synthState->curVolRight = 0;
+ synthState->prevHaasEffectLeftDelaySize = 0;
+ synthState->prevHaasEffectRightDelaySize = 0;
+ synthState->curReverbVol = sampleState->targetReverbVol;
+ synthState->numParts = 0;
+ synthState->combFilterNeedsInit = true;
+ note->sampleState.bitField0.finished = false;
+ synthState->unk_1F = note->playbackState.unk_80; // Never set, never used
+ finished = false;
+ }
+
+ // Process the sample in either one or two parts
+ numParts = sampleState->bitField1.hasTwoParts + 1;
+
+ // Determine number of samples to load based on numSamplesPerUpdate and relative frequency
+ frequencyFixedPoint = sampleState->frequencyFixedPoint;
+ numSamplesToLoadFixedPoint = (frequencyFixedPoint * numSamplesPerUpdate * 2) + synthState->samplePosFrac;
+ numSamplesToLoad = numSamplesToLoadFixedPoint >> 16;
+
+ if (numSamplesToLoad == 0) {
+ skipBytes = false;
+ }
+
+ synthState->samplePosFrac = numSamplesToLoadFixedPoint & 0xFFFF;
+
+ // Partially-optimized out no-op ifs required for matching. SM64 decomp
+ // makes it clear that this is how it should look.
+ if ((synthState->numParts == 1) && (numParts == 2)) {
+ } else if ((synthState->numParts == 2) && (numParts == 1)) {
+ } else {
+ }
+
+ synthState->numParts = numParts;
+
+ if (sampleState->bitField1.isSyntheticWave) {
+ cmd = AudioSynth_LoadWaveSamples(cmd, sampleState, synthState, numSamplesToLoad);
+ sampleDmemBeforeResampling = DMEM_UNCOMPRESSED_NOTE + (synthState->samplePosInt * 2);
+ synthState->samplePosInt += numSamplesToLoad;
+ } else {
+ sample = sampleState->tunedSample->sample;
+ loopInfo = sample->loop;
+
+ if (note->playbackState.status != PLAYBACK_STATUS_0) {
+ synthState->stopLoop = true;
+ }
+
+ if ((loopInfo->count == 2) && synthState->stopLoop) {
+ sampleEndPos = loopInfo->sampleEnd;
+ } else {
+ sampleEndPos = loopInfo->loopEnd;
+ }
+
+ sampleAddr = sample->sampleAddr;
+ numSamplesToLoadFirstPart = 0;
+
+ // If the frequency requested is more than double that of the raw sample,
+ // then the sample processing is split into two parts.
+ for (curPart = 0; curPart < numParts; curPart++) {
+ numSamplesProcessed = 0;
+ dmemUncompressedAddrOffset1 = 0;
+
+ // Adjust the number of samples to load only if there are two parts and an odd number of samples
+ if (numParts == 1) {
+ numSamplesToLoadAdj = numSamplesToLoad;
+ } else if (numSamplesToLoad & 1) {
+ // round down for the first part
+ // round up for the second part
+ numSamplesToLoadAdj = (numSamplesToLoad & ~1) + (curPart * 2);
+ } else {
+ numSamplesToLoadAdj = numSamplesToLoad;
+ }
+
+ // Load the ADPCM codeBook
+ if ((sample->codec == CODEC_ADPCM) || (sample->codec == CODEC_SMALL_ADPCM)) {
+ if (gAudioContext.adpcmCodeBook != sample->book->codeBook) {
+ u32 numEntries;
+
+ switch (bookOffset) {
+ case 1:
+ gAudioContext.adpcmCodeBook = &gInvalidAdpcmCodeBook[1];
+ break;
+
+ case 2:
+ case 3:
+ default:
+ gAudioContext.adpcmCodeBook = sample->book->codeBook;
+ break;
+ }
+
+ numEntries = SAMPLES_PER_FRAME * sample->book->order * sample->book->numPredictors;
+ aLoadADPCM(cmd++, numEntries, gAudioContext.adpcmCodeBook);
+ }
+ }
+
+ // Continue processing samples until the number of samples needed to load is reached
+ while (numSamplesProcessed != numSamplesToLoadAdj) {
+ sampleFinished = false;
+ loopToPoint = false;
+ dmemUncompressedAddrOffset2 = 0;
+
+ numFirstFrameSamplesToIgnore = synthState->samplePosInt & 0xF;
+ numSamplesUntilEnd = sampleEndPos - synthState->samplePosInt;
+
+ // Calculate number of samples to process this loop
+ numSamplesToProcess = numSamplesToLoadAdj - numSamplesProcessed;
+
+ if ((numFirstFrameSamplesToIgnore == 0) && !synthState->atLoopPoint) {
+ numFirstFrameSamplesToIgnore = SAMPLES_PER_FRAME;
+ }
+ numSamplesInFirstFrame = SAMPLES_PER_FRAME - numFirstFrameSamplesToIgnore;
+
+ // Determine the number of samples to decode based on whether the end will be reached or not.
+ if (numSamplesToProcess < numSamplesUntilEnd) {
+ // The end will not be reached.
+ numFramesToDecode =
+ (s32)(numSamplesToProcess - numSamplesInFirstFrame + SAMPLES_PER_FRAME - 1) / SAMPLES_PER_FRAME;
+ numSamplesToDecode = numFramesToDecode * SAMPLES_PER_FRAME;
+ numTrailingSamplesToIgnore = numSamplesInFirstFrame + numSamplesToDecode - numSamplesToProcess;
+ } else {
+ // The end will be reached.
+ numSamplesToDecode = numSamplesUntilEnd - numSamplesInFirstFrame;
+ numTrailingSamplesToIgnore = 0;
+ if (numSamplesToDecode <= 0) {
+ numSamplesToDecode = 0;
+ numSamplesInFirstFrame = numSamplesUntilEnd;
+ }
+ numFramesToDecode = (numSamplesToDecode + SAMPLES_PER_FRAME - 1) / SAMPLES_PER_FRAME;
+ if (loopInfo->count != 0) {
+ if ((loopInfo->count == 2) && synthState->stopLoop) {
+ sampleFinished = true;
+ } else {
+ // Loop around and restart
+ loopToPoint = true;
+ }
+ } else {
+ sampleFinished = true;
+ }
+ }
+
+ // Set parameters based on compression type
+ switch (sample->codec) {
+ case CODEC_ADPCM:
+ // 16 2-byte samples (32 bytes) compressed into 4-bit samples (8 bytes) + 1 header byte
+ frameSize = 9;
+ skipInitialSamples = SAMPLES_PER_FRAME;
+ zeroOffset = 0;
+ break;
+
+ case CODEC_SMALL_ADPCM:
+ // 16 2-byte samples (32 bytes) compressed into 2-bit samples (4 bytes) + 1 header byte
+ frameSize = 5;
+ skipInitialSamples = SAMPLES_PER_FRAME;
+ zeroOffset = 0;
+ break;
+
+ case CODEC_UNK7:
+ // 2 2-byte samples (4 bytes) processed without decompression
+ frameSize = 4;
+ skipInitialSamples = SAMPLES_PER_FRAME;
+ zeroOffset = 0;
+ break;
+
+ case CODEC_S8:
+ // 16 2-byte samples (32 bytes) compressed into 8-bit samples (16 bytes)
+ frameSize = 16;
+ skipInitialSamples = SAMPLES_PER_FRAME;
+ zeroOffset = 0;
+ break;
+
+ case CODEC_REVERB:
+ reverbAddrSrc = (void*)0xFFFFFFFF;
+ if (gCustomAudioReverbFunction != NULL) {
+ reverbAddrSrc = gCustomAudioReverbFunction(sample, numSamplesToLoadAdj, flags, noteIndex);
+ }
+
+ if (reverbAddrSrc == (void*)0xFFFFFFFF) {
+ sampleFinished = true;
+ } else if (reverbAddrSrc == NULL) {
+ return cmd;
+ } else {
+ AudioSynth_LoadBuffer(cmd++, DMEM_UNCOMPRESSED_NOTE,
+ (numSamplesToLoadAdj + SAMPLES_PER_FRAME) * SAMPLE_SIZE,
+ reverbAddrSrc);
+ flags = A_CONTINUE;
+ skipBytes = 0;
+ numSamplesProcessed = numSamplesToLoadAdj;
+ dmemUncompressedAddrOffset1 = numSamplesToLoadAdj;
+ }
+ goto skip;
+
+ case CODEC_S16_INMEMORY:
+ case CODEC_UNK6:
+ AudioSynth_ClearBuffer(cmd++, DMEM_UNCOMPRESSED_NOTE,
+ (numSamplesToLoadAdj + SAMPLES_PER_FRAME) * SAMPLE_SIZE);
+ flags = A_CONTINUE;
+ skipBytes = 0;
+ numSamplesProcessed = numSamplesToLoadAdj;
+ dmemUncompressedAddrOffset1 = numSamplesToLoadAdj;
+ goto skip;
+
+ case CODEC_S16:
+ AudioSynth_ClearBuffer(cmd++, DMEM_UNCOMPRESSED_NOTE,
+ (numSamplesToLoadAdj + SAMPLES_PER_FRAME) * SAMPLE_SIZE);
+ flags = A_CONTINUE;
+ skipBytes = 0;
+ numSamplesProcessed = numSamplesToLoadAdj;
+ dmemUncompressedAddrOffset1 = numSamplesToLoadAdj;
+ goto skip;
+
+ default:
+ break;
+ }
+
+ // Move the compressed raw sample data from ram into the rsp (DMEM)
+ if (numFramesToDecode != 0) {
+ // Get the offset from the start of the sample to where the sample is currently playing from
+ frameIndex = (synthState->samplePosInt + skipInitialSamples - numFirstFrameSamplesToIgnore) /
+ SAMPLES_PER_FRAME;
+ sampleAddrOffset = frameIndex * frameSize;
+
+ // Get the ram address of the requested sample chunk
+ if (sample->medium == MEDIUM_RAM) {
+ // Sample is already loaded into ram
+ samplesToLoadAddr = sampleAddr + (zeroOffset + sampleAddrOffset);
+ } else if (gAudioContext.unk_29B8) { // always false
+ return cmd;
+ } else if (sample->medium == MEDIUM_UNK) {
+ // This medium is unsupported so terminate processing this note
+ return cmd;
+ } else {
+ // This medium is not in ram, so dma the requested sample into ram
+ samplesToLoadAddr =
+ AudioLoad_DmaSampleData(sampleAddr + (zeroOffset + sampleAddrOffset),
+ ALIGN16((numFramesToDecode * frameSize) + SAMPLES_PER_FRAME), flags,
+ &synthState->sampleDmaIndex, sample->medium);
+ }
+
+ if (samplesToLoadAddr == NULL) {
+ // The ram address was unsuccessfully allocated
+ return cmd;
+ }
+
+ // Move the raw sample chunk from ram to the rsp
+ // DMEM at the addresses before DMEM_COMPRESSED_ADPCM_DATA
+ sampleDataChunkAlignPad = (u32)samplesToLoadAddr & 0xF;
+ sampleDataChunkSize = ALIGN16((numFramesToDecode * frameSize) + SAMPLES_PER_FRAME);
+ sampleDataDmemAddr = DMEM_COMPRESSED_ADPCM_DATA - sampleDataChunkSize;
+ aLoadBuffer(cmd++, samplesToLoadAddr - sampleDataChunkAlignPad, sampleDataDmemAddr,
+ sampleDataChunkSize);
+ } else {
+ numSamplesToDecode = 0;
+ sampleDataChunkAlignPad = 0;
+ }
+
+ if (synthState->atLoopPoint) {
+ aSetLoop(cmd++, sample->loop->predictorState);
+ flags = A_LOOP;
+ synthState->atLoopPoint = false;
+ }
+
+ numSamplesInThisIteration = numSamplesToDecode + numSamplesInFirstFrame - numTrailingSamplesToIgnore;
+
+ if (numSamplesProcessed == 0) {
+ //! FAKE:
+ if (1) {}
+ skipBytes = numFirstFrameSamplesToIgnore * SAMPLE_SIZE;
+ } else {
+ dmemUncompressedAddrOffset2 = ALIGN16(dmemUncompressedAddrOffset1 + 8 * SAMPLE_SIZE);
+ }
+
+ // Decompress the raw sample chunks in the rsp
+ // Goes from adpcm (compressed) sample data to pcm (uncompressed) sample data
+ switch (sample->codec) {
+ case CODEC_ADPCM:
+ sampleDataChunkSize = ALIGN16((numFramesToDecode * frameSize) + SAMPLES_PER_FRAME);
+ sampleDataDmemAddr = DMEM_COMPRESSED_ADPCM_DATA - sampleDataChunkSize;
+ aSetBuffer(cmd++, 0, sampleDataDmemAddr + sampleDataChunkAlignPad,
+ DMEM_UNCOMPRESSED_NOTE + dmemUncompressedAddrOffset2,
+ numSamplesToDecode * SAMPLE_SIZE);
+ aADPCMdec(cmd++, flags, synthState->synthesisBuffers->adpcmState);
+ break;
+
+ case CODEC_SMALL_ADPCM:
+ sampleDataChunkSize = ALIGN16((numFramesToDecode * frameSize) + SAMPLES_PER_FRAME);
+ sampleDataDmemAddr = DMEM_COMPRESSED_ADPCM_DATA - sampleDataChunkSize;
+ aSetBuffer(cmd++, 0, sampleDataDmemAddr + sampleDataChunkAlignPad,
+ DMEM_UNCOMPRESSED_NOTE + dmemUncompressedAddrOffset2,
+ numSamplesToDecode * SAMPLE_SIZE);
+ aADPCMdec(cmd++, flags | A_ADPCM_SHORT, synthState->synthesisBuffers->adpcmState);
+ break;
+
+ case CODEC_S8:
+ sampleDataChunkSize = ALIGN16((numFramesToDecode * frameSize) + SAMPLES_PER_FRAME);
+ sampleDataDmemAddr = DMEM_COMPRESSED_ADPCM_DATA - sampleDataChunkSize;
+ AudioSynth_SetBuffer(cmd++, 0, sampleDataDmemAddr + sampleDataChunkAlignPad,
+ DMEM_UNCOMPRESSED_NOTE + dmemUncompressedAddrOffset2,
+ numSamplesToDecode * SAMPLE_SIZE);
+ AudioSynth_S8Dec(cmd++, flags, synthState->synthesisBuffers->adpcmState);
+ break;
+
+ case CODEC_UNK7:
+ default:
+ // No decompression
+ break;
+ }
+
+ if (numSamplesProcessed != 0) {
+ aDMEMMove(cmd++,
+ DMEM_UNCOMPRESSED_NOTE + dmemUncompressedAddrOffset2 +
+ (numFirstFrameSamplesToIgnore * SAMPLE_SIZE),
+ DMEM_UNCOMPRESSED_NOTE + dmemUncompressedAddrOffset1,
+ numSamplesInThisIteration * SAMPLE_SIZE);
+ }
+
+ numSamplesProcessed += numSamplesInThisIteration;
+
+ switch (flags) {
+ case A_INIT:
+ skipBytes = SAMPLES_PER_FRAME * SAMPLE_SIZE;
+ dmemUncompressedAddrOffset1 = (numSamplesToDecode + SAMPLES_PER_FRAME) * SAMPLE_SIZE;
+ break;
+
+ case A_LOOP:
+ dmemUncompressedAddrOffset1 =
+ numSamplesInThisIteration * SAMPLE_SIZE + dmemUncompressedAddrOffset1;
+ break;
+
+ default:
+ if (dmemUncompressedAddrOffset1 != 0) {
+ dmemUncompressedAddrOffset1 =
+ numSamplesInThisIteration * SAMPLE_SIZE + dmemUncompressedAddrOffset1;
+ } else {
+ dmemUncompressedAddrOffset1 =
+ (numFirstFrameSamplesToIgnore + numSamplesInThisIteration) * SAMPLE_SIZE;
+ }
+ break;
+ }
+
+ flags = A_CONTINUE;
+
+ skip:
+
+ // Update what to do with the samples next
+ if (sampleFinished) {
+ if ((numSamplesToLoadAdj - numSamplesProcessed) != 0) {
+ AudioSynth_ClearBuffer(cmd++, DMEM_UNCOMPRESSED_NOTE + dmemUncompressedAddrOffset1,
+ (numSamplesToLoadAdj - numSamplesProcessed) * SAMPLE_SIZE);
+ }
+ finished = true;
+ note->sampleState.bitField0.finished = true;
+ AudioSynth_DisableSampleStates(updateIndex, noteIndex);
+ break; // break out of the for-loop
+ } else if (loopToPoint) {
+ synthState->atLoopPoint = true;
+ synthState->samplePosInt = loopInfo->start;
+ } else {
+ synthState->samplePosInt += numSamplesToProcess;
+ }
+ }
+
+ switch (numParts) {
+ case 1:
+ sampleDmemBeforeResampling = DMEM_UNCOMPRESSED_NOTE + skipBytes;
+ break;
+
+ case 2:
+ switch (curPart) {
+ case 0:
+ AudioSynth_InterL(cmd++, DMEM_UNCOMPRESSED_NOTE + skipBytes,
+ DMEM_TEMP + (SAMPLES_PER_FRAME * SAMPLE_SIZE),
+ ALIGN8(numSamplesToLoadAdj / 2));
+ numSamplesToLoadFirstPart = numSamplesToLoadAdj;
+ sampleDmemBeforeResampling = DMEM_TEMP + (SAMPLES_PER_FRAME * SAMPLE_SIZE);
+ if (finished) {
+ AudioSynth_ClearBuffer(cmd++, sampleDmemBeforeResampling + numSamplesToLoadFirstPart,
+ numSamplesToLoadAdj + SAMPLES_PER_FRAME);
+ }
+ break;
+
+ case 1:
+ AudioSynth_InterL(cmd++, DMEM_UNCOMPRESSED_NOTE + skipBytes,
+ DMEM_TEMP + (SAMPLES_PER_FRAME * SAMPLE_SIZE) + numSamplesToLoadFirstPart,
+ ALIGN8(numSamplesToLoadAdj / 2));
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+ if (finished) {
+ break;
+ }
+ }
+ }
+
+ // Update the flags for the signal processing below
+ flags = A_CONTINUE;
+ if (sampleState->bitField0.needsInit == true) {
+ sampleState->bitField0.needsInit = false;
+ flags = A_INIT;
+ }
+
+ // Resample the decompressed mono-signal to the correct pitch
+ cmd = AudioSynth_FinalResample(cmd, synthState, numSamplesPerUpdate * SAMPLE_SIZE, frequencyFixedPoint,
+ sampleDmemBeforeResampling, flags);
+
+ // UnkCmd19 was removed from the audio microcode
+ // This block performs no operation
+ if (bookOffset == 3) {
+ AudioSynth_UnkCmd19(cmd++, DMEM_TEMP, DMEM_TEMP, numSamplesPerUpdate * (s32)SAMPLE_SIZE, 0);
+ }
+
+ // Apply the gain to the mono-signal to adjust the volume
+ gain = sampleState->gain;
+ if (gain != 0) {
+ // A gain of 0x10 (a UQ4.4 number) is equivalent to 1.0 and represents no volume change
+ if (gain < 0x10) {
+ gain = 0x10;
+ }
+ AudioSynth_HiLoGain(cmd++, gain, DMEM_TEMP, 0, (numSamplesPerUpdate + SAMPLES_PER_FRAME) * SAMPLE_SIZE);
+ }
+
+ // Apply the filter to the mono-signal
+ filter = sampleState->filter;
+ if (filter != 0) {
+ AudioSynth_LoadFilterSize(cmd++, numSamplesPerUpdate * SAMPLE_SIZE, filter);
+ AudioSynth_LoadFilterBuffer(cmd++, flags, DMEM_TEMP, synthState->synthesisBuffers->filterState);
+ }
+
+ // Apply the comb filter to the mono-signal by taking the signal with a small temporal offset,
+ // and adding it back to itself
+ combFilterSize = sampleState->combFilterSize;
+ combFilterGain = sampleState->combFilterGain;
+ combFilterState = synthState->synthesisBuffers->combFilterState;
+ if ((combFilterSize != 0) && (sampleState->combFilterGain != 0)) {
+ AudioSynth_DMemMove(cmd++, DMEM_TEMP, DMEM_COMB_TEMP, numSamplesPerUpdate * SAMPLE_SIZE);
+ combFilterDmem = DMEM_COMB_TEMP - combFilterSize;
+ if (synthState->combFilterNeedsInit) {
+ AudioSynth_ClearBuffer(cmd++, combFilterDmem, combFilterSize);
+ synthState->combFilterNeedsInit = false;
+ } else {
+ AudioSynth_LoadBuffer(cmd++, combFilterDmem, combFilterSize, combFilterState);
+ }
+ AudioSynth_SaveBuffer(cmd++, DMEM_TEMP + (numSamplesPerUpdate * SAMPLE_SIZE) - combFilterSize, combFilterSize,
+ combFilterState);
+ AudioSynth_Mix(cmd++, (numSamplesPerUpdate * (s32)SAMPLE_SIZE) >> 4, combFilterGain, DMEM_COMB_TEMP,
+ combFilterDmem);
+ AudioSynth_DMemMove(cmd++, combFilterDmem, DMEM_TEMP, numSamplesPerUpdate * SAMPLE_SIZE);
+ } else {
+ synthState->combFilterNeedsInit = true;
+ }
+
+ // Determine the behavior of the audio processing that leads to the haas effect
+ if ((sampleState->haasEffectLeftDelaySize != 0) || (synthState->prevHaasEffectLeftDelaySize != 0)) {
+ haasEffectDelaySide = HAAS_EFFECT_DELAY_LEFT;
+ } else if ((sampleState->haasEffectRightDelaySize != 0) || (synthState->prevHaasEffectRightDelaySize != 0)) {
+ haasEffectDelaySide = HAAS_EFFECT_DELAY_RIGHT;
+ } else {
+ haasEffectDelaySide = HAAS_EFFECT_DELAY_NONE;
+ }
+
+ // Apply an unknown effect based on the surround sound-mode
+ if (gAudioContext.soundMode == SOUNDMODE_SURROUND) {
+ sampleState->targetVolLeft = sampleState->targetVolLeft >> 1;
+ sampleState->targetVolRight = sampleState->targetVolRight >> 1;
+ if (sampleState->surroundEffectIndex != 0xFF) {
+ cmd = AudioSynth_ApplySurroundEffect(cmd, sampleState, synthState, numSamplesPerUpdate, DMEM_TEMP, flags);
+ }
+ }
+
+ // Split the mono-signal into left and right channels:
+ // Both for dry signal (to go to the speakers now)
+ // and for wet signal (to go to a reverb buffer to be stored, and brought back later to produce an echo)
+ cmd = AudioSynth_ProcessEnvelope(cmd, sampleState, synthState, numSamplesPerUpdate, DMEM_TEMP, haasEffectDelaySide,
+ flags);
+
+ // Apply the haas effect by delaying either the left or the right channel by a small amount
+ if (sampleState->bitField1.useHaasEffect) {
+ if (!(flags & A_INIT)) {
+ flags = A_CONTINUE;
+ }
+ cmd = AudioSynth_ApplyHaasEffect(cmd, sampleState, synthState, numSamplesPerUpdate * (s32)SAMPLE_SIZE, flags,
+ haasEffectDelaySide);
+ }
+
+ return cmd;
+}
+
+Acmd* AudioSynth_ApplySurroundEffect(Acmd* cmd, NoteSampleState* sampleState, NoteSynthesisState* synthState,
+ s32 numSamplesPerUpdate, s32 haasDmem, s32 flags) {
+ s32 wetGain;
+ u16 dryGain;
+ s64 dmem = DMEM_SURROUND_TEMP;
+ f32 decayGain;
+
+ AudioSynth_DMemMove(cmd++, haasDmem, DMEM_HAAS_TEMP, numSamplesPerUpdate * SAMPLE_SIZE);
+ dryGain = synthState->surroundEffectGain;
+
+ if (flags == A_INIT) {
+ aClearBuffer(cmd++, dmem, sizeof(synthState->synthesisBuffers->surroundEffectState));
+ synthState->surroundEffectGain = 0;
+ } else {
+ aLoadBuffer(cmd++, synthState->synthesisBuffers->surroundEffectState, dmem,
+ sizeof(synthState->synthesisBuffers->surroundEffectState));
+ aMix(cmd++, (numSamplesPerUpdate * (s32)SAMPLE_SIZE) >> 4, dryGain, dmem, DMEM_LEFT_CH);
+ aMix(cmd++, (numSamplesPerUpdate * (s32)SAMPLE_SIZE) >> 4, (dryGain ^ 0xFFFF), dmem, DMEM_RIGHT_CH);
+
+ wetGain = (dryGain * synthState->curReverbVol) >> 7;
+
+ aMix(cmd++, (numSamplesPerUpdate * (s32)SAMPLE_SIZE) >> 4, wetGain, dmem, DMEM_WET_LEFT_CH);
+ aMix(cmd++, (numSamplesPerUpdate * (s32)SAMPLE_SIZE) >> 4, (wetGain ^ 0xFFFF), dmem, DMEM_WET_RIGHT_CH);
+ }
+
+ aSaveBuffer(cmd++, DMEM_SURROUND_TEMP + (numSamplesPerUpdate * SAMPLE_SIZE),
+ synthState->synthesisBuffers->surroundEffectState,
+ sizeof(synthState->synthesisBuffers->surroundEffectState));
+
+ decayGain = (sampleState->targetVolLeft + sampleState->targetVolRight) * (1.0f / 0x2000);
+
+ if (decayGain > 1.0f) {
+ decayGain = 1.0f;
+ }
+
+ decayGain = decayGain * gDefaultPanVolume[127 - sampleState->surroundEffectIndex];
+ synthState->surroundEffectGain = ((decayGain * 0x7FFF) + synthState->surroundEffectGain) / 2;
+
+ AudioSynth_DMemMove(cmd++, DMEM_HAAS_TEMP, haasDmem, numSamplesPerUpdate * SAMPLE_SIZE);
+
+ return cmd;
+}
+
+Acmd* AudioSynth_FinalResample(Acmd* cmd, NoteSynthesisState* synthState, s32 size, u16 pitch, u16 inpDmem,
+ s32 resampleFlags) {
+ if (pitch == 0) {
+ AudioSynth_ClearBuffer(cmd++, DMEM_TEMP, size);
+ } else {
+ aSetBuffer(cmd++, 0, inpDmem, DMEM_TEMP, size);
+ aResample(cmd++, resampleFlags, pitch, synthState->synthesisBuffers->finalResampleState);
+ }
+
+ return cmd;
+}
+
+Acmd* AudioSynth_ProcessEnvelope(Acmd* cmd, NoteSampleState* sampleState, NoteSynthesisState* synthState,
+ s32 numSamplesPerUpdate, u16 dmemSrc, s32 haasEffectDelaySide, s32 flags) {
+ u32 dmemDests;
+ u16 curVolLeft;
+ u16 targetVolLeft;
+ s32 curReverbVol;
+ u16 curVolRight;
+ s16 targetReverbVol;
+ s16 rampLeft;
+ s16 rampRight;
+ s16 rampReverb;
+ s16 curReverbVolAndFlags;
+ u16 targetVolRight;
+ f32 defaultPanVolume;
+ s32 pad;
+
+ targetReverbVol = sampleState->targetReverbVol;
+
+ curVolLeft = synthState->curVolLeft;
+ curVolRight = synthState->curVolRight;
+
+ targetVolLeft = sampleState->targetVolLeft;
+ targetVolLeft <<= 4;
+ targetVolRight = sampleState->targetVolRight;
+ targetVolRight <<= 4;
+
+ if ((gAudioContext.soundMode == SOUNDMODE_SURROUND) && (sampleState->surroundEffectIndex != 0xFF)) {
+ defaultPanVolume = gDefaultPanVolume[sampleState->surroundEffectIndex];
+ targetVolLeft *= defaultPanVolume;
+ targetVolRight *= defaultPanVolume;
+ }
+
+ if (targetVolLeft != curVolLeft) {
+ rampLeft = (targetVolLeft - curVolLeft) / (numSamplesPerUpdate >> 3);
+ } else {
+ rampLeft = 0;
+ }
+
+ if (targetVolRight != curVolRight) {
+ rampRight = (targetVolRight - curVolRight) / (numSamplesPerUpdate >> 3);
+ } else {
+ rampRight = 0;
+ }
+
+ curReverbVolAndFlags = synthState->curReverbVol;
+ curReverbVol = curReverbVolAndFlags & 0x7F;
+
+ if (curReverbVolAndFlags != targetReverbVol) {
+ rampReverb = (((targetReverbVol & 0x7F) - curReverbVol) << 9) / (numSamplesPerUpdate >> 3);
+ synthState->curReverbVol = targetReverbVol;
+ } else {
+ rampReverb = 0;
+ }
+
+ synthState->curVolLeft = curVolLeft + (rampLeft * (numSamplesPerUpdate >> 3));
+ synthState->curVolRight = curVolRight + (rampRight * (numSamplesPerUpdate >> 3));
+
+ if (sampleState->bitField1.useHaasEffect) {
+ AudioSynth_ClearBuffer(cmd++, DMEM_HAAS_TEMP, DMEM_1CH_SIZE);
+ AudioSynth_EnvSetup1(cmd++, curReverbVol * 2, rampReverb, rampLeft, rampRight);
+ AudioSynth_EnvSetup2(cmd++, curVolLeft, curVolRight);
+
+ switch (haasEffectDelaySide) {
+ case HAAS_EFFECT_DELAY_LEFT:
+ // Store the left dry channel in a temp space to be delayed to produce the haas effect
+ dmemDests = sEnvMixerLeftHaasDmemDests;
+ break;
+
+ case HAAS_EFFECT_DELAY_RIGHT:
+ // Store the right dry channel in a temp space to be delayed to produce the haas effect
+ dmemDests = sEnvMixerRightHaasDmemDests;
+ break;
+
+ default: // HAAS_EFFECT_DELAY_NONE
+ dmemDests = sEnvMixerDefaultDmemDests;
+ break;
+ }
+ } else {
+ aEnvSetup1(cmd++, curReverbVol * 2, rampReverb, rampLeft, rampRight);
+ aEnvSetup2(cmd++, curVolLeft, curVolRight);
+ dmemDests = sEnvMixerDefaultDmemDests;
+ }
+
+ aEnvMixer(cmd++, dmemSrc, numSamplesPerUpdate, (curReverbVolAndFlags & 0x80) >> 7,
+ sampleState->bitField0.strongReverbRight, sampleState->bitField0.strongReverbLeft,
+ sampleState->bitField0.strongRight, sampleState->bitField0.strongLeft, dmemDests, sEnvMixerOp);
+
+ return cmd;
+}
+
+Acmd* AudioSynth_LoadWaveSamples(Acmd* cmd, NoteSampleState* sampleState, NoteSynthesisState* synthState,
+ s32 numSamplesToLoad) {
+ s32 numSamplesAvailable;
+ s32 harmonicIndexCurAndPrev = sampleState->harmonicIndexCurAndPrev;
+ s32 samplePosInt = synthState->samplePosInt;
+ s32 numDuplicates;
+
+ if (sampleState->bitField1.bookOffset != 0) {
+ // Move the noise wave (that reads compiled assembly as samples) from ram to dmem
+ AudioSynth_LoadBuffer(cmd++, DMEM_UNCOMPRESSED_NOTE, ALIGN16(numSamplesToLoad * SAMPLE_SIZE), gWaveSamples[8]);
+ // Offset the address for the samples read by gWaveSamples[8] to the next set of samples
+ gWaveSamples[8] += numSamplesToLoad * SAMPLE_SIZE;
+
+ return cmd;
+ } else {
+ // Move the synthetic wave from ram to dmem
+ aLoadBuffer(cmd++, sampleState->waveSampleAddr, DMEM_UNCOMPRESSED_NOTE, WAVE_SAMPLE_COUNT * SAMPLE_SIZE);
+
+ // If the harmonic changes, map the offset in the wave from one harmonic to another for continuity
+ if (harmonicIndexCurAndPrev != 0) {
+ samplePosInt = (samplePosInt * sNumSamplesPerWavePeriod[harmonicIndexCurAndPrev >> 2]) /
+ sNumSamplesPerWavePeriod[harmonicIndexCurAndPrev & 3];
+ }
+
+ // Offset in the WAVE_SAMPLE_COUNT samples of gWaveSamples to start processing the wave for continuity
+ samplePosInt = (u32)samplePosInt % WAVE_SAMPLE_COUNT;
+ // Number of samples in the initial WAVE_SAMPLE_COUNT samples available to be used to process
+ numSamplesAvailable = WAVE_SAMPLE_COUNT - samplePosInt;
+
+ // Require duplicates if there are more samples to load than available
+ if (numSamplesToLoad > numSamplesAvailable) {
+ // Duplicate (copy) the WAVE_SAMPLE_COUNT samples as many times as needed to reach numSamplesToLoad.
+ // (numSamplesToLoad - numSamplesAvailable) is the number of samples missing.
+ // Divide by WAVE_SAMPLE_COUNT, rounding up, to get the amount of duplicates
+ numDuplicates = ((numSamplesToLoad - numSamplesAvailable + WAVE_SAMPLE_COUNT - 1) / WAVE_SAMPLE_COUNT);
+ if (numDuplicates != 0) {
+ aDuplicate(cmd++, numDuplicates, DMEM_UNCOMPRESSED_NOTE,
+ DMEM_UNCOMPRESSED_NOTE + (WAVE_SAMPLE_COUNT * SAMPLE_SIZE));
+ }
+ }
+ synthState->samplePosInt = samplePosInt;
+ }
+
+ return cmd;
+}
+
+/**
+ * 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* cmd, NoteSampleState* sampleState, NoteSynthesisState* synthState, s32 size,
+ s32 flags, s32 haasEffectDelaySide) {
+ u16 dmemDest;
+ u16 pitch;
+ u8 prevHaasEffectDelaySize;
+ u8 haasEffectDelaySize;
+
+ switch (haasEffectDelaySide) {
+ case HAAS_EFFECT_DELAY_LEFT:
+ // Delay the sample on the left channel
+ // This allows the right channel to be heard first
+ dmemDest = DMEM_LEFT_CH;
+ haasEffectDelaySize = sampleState->haasEffectLeftDelaySize;
+ prevHaasEffectDelaySize = synthState->prevHaasEffectLeftDelaySize;
+ synthState->prevHaasEffectRightDelaySize = 0;
+ synthState->prevHaasEffectLeftDelaySize = haasEffectDelaySize;
+ break;
+
+ case HAAS_EFFECT_DELAY_RIGHT:
+ // Delay the sample on the right channel
+ // This allows the left channel to be heard first
+ dmemDest = DMEM_RIGHT_CH;
+ haasEffectDelaySize = sampleState->haasEffectRightDelaySize;
+ prevHaasEffectDelaySize = synthState->prevHaasEffectRightDelaySize;
+ synthState->prevHaasEffectRightDelaySize = haasEffectDelaySize;
+ synthState->prevHaasEffectLeftDelaySize = 0;
+ break;
+
+ default: // HAAS_EFFECT_DELAY_NONE
+ return cmd;
+ }
+
+ if (flags != A_INIT) {
+ // Slightly adjust the sample rate in order to fit a change in sample delay
+ if (haasEffectDelaySize != prevHaasEffectDelaySize) {
+ pitch = (((size << 0xF) / 2) - 1) / ((size + haasEffectDelaySize - prevHaasEffectDelaySize - 2) / 2);
+ aSetBuffer(cmd++, 0, DMEM_HAAS_TEMP, DMEM_TEMP, size + haasEffectDelaySize - prevHaasEffectDelaySize);
+ aResampleZoh(cmd++, pitch, 0);
+ } else {
+ aDMEMMove(cmd++, DMEM_HAAS_TEMP, DMEM_TEMP, size);
+ }
+
+ if (prevHaasEffectDelaySize != 0) {
+ aLoadBuffer(cmd++, synthState->synthesisBuffers->haasEffectDelayState, DMEM_HAAS_TEMP,
+ ALIGN16(prevHaasEffectDelaySize));
+ aDMEMMove(cmd++, DMEM_TEMP, DMEM_HAAS_TEMP + prevHaasEffectDelaySize,
+ size + haasEffectDelaySize - prevHaasEffectDelaySize);
+ } else {
+ aDMEMMove(cmd++, DMEM_TEMP, DMEM_HAAS_TEMP, size + haasEffectDelaySize);
+ }
+ } else {
+ // Just apply a delay directly
+ aDMEMMove(cmd++, DMEM_HAAS_TEMP, DMEM_TEMP, size);
+ if (haasEffectDelaySize) { // != 0
+ aClearBuffer(cmd++, DMEM_HAAS_TEMP, haasEffectDelaySize);
+ }
+ aDMEMMove(cmd++, DMEM_TEMP, DMEM_HAAS_TEMP + haasEffectDelaySize, size);
+ }
+
+ if (haasEffectDelaySize) { // != 0
+ // Save excessive samples for next iteration
+ aSaveBuffer(cmd++, DMEM_HAAS_TEMP + size, synthState->synthesisBuffers->haasEffectDelayState,
+ ALIGN16(haasEffectDelaySize));
+ }
+
+ aAddMixer(cmd++, ALIGN64(size), DMEM_HAAS_TEMP, dmemDest, 0x7FFF);
+
+ return cmd;
+}
diff --git a/src/code/audio/code_8019AF00.c b/src/code/audio/code_8019AF00.c
index 007d7ca85..98be41397 100644
--- a/src/code/audio/code_8019AF00.c
+++ b/src/code/audio/code_8019AF00.c
@@ -4078,7 +4078,7 @@ void AudioSfx_SetProperties(u8 bankId, u8 entryIndex, u8 channelIndex) {
}
u32 AudioSfx_SetFreqAndStereoBits(u8 seqScriptValIn, SequenceChannel* channel) {
- channel->stereo.asByte = sSfxChannelState[seqScriptValIn].stereoBits;
+ channel->stereoData.asByte = sSfxChannelState[seqScriptValIn].stereoBits;
channel->freqScale = sSfxChannelState[seqScriptValIn].freqScale;
channel->changes.s.freqScale = true;
diff --git a/src/code/speed_meter.c b/src/code/speed_meter.c
index 9f04de110..5ad1cdbe0 100644
--- a/src/code/speed_meter.c
+++ b/src/code/speed_meter.c
@@ -1,4 +1,5 @@
#include "global.h"
+#include "z64view.h"
#include "system_malloc.h"
#pragma GLOBAL_ASM("asm/non_matchings/code/speed_meter/func_80177390.s")
diff --git a/src/code/z_camera.c b/src/code/z_camera.c
index c26947b21..da8a5f35a 100644
--- a/src/code/z_camera.c
+++ b/src/code/z_camera.c
@@ -1,5 +1,7 @@
#include "global.h"
#include "z64quake.h"
+#include "z64shrink_window.h"
+#include "z64view.h"
/**
* Returns the absolute value for floats
diff --git a/src/code/z_demo.c b/src/code/z_demo.c
index ea4a9828a..79d6d05ff 100644
--- a/src/code/z_demo.c
+++ b/src/code/z_demo.c
@@ -1,6 +1,7 @@
#include "global.h"
#include "z64quake.h"
#include "z64rumble.h"
+#include "z64shrink_window.h"
#include "overlays/gamestates/ovl_daytelop/z_daytelop.h"
void Cutscene_DoNothing(PlayState* play, CutsceneContext* csCtx);
@@ -107,7 +108,7 @@ s32 func_800EA220(PlayState* play, CutsceneContext* csCtx, f32 target) {
void func_800EA258(PlayState* play, CutsceneContext* csCtx) {
Interface_SetHudVisibility(HUD_VISIBILITY_NONE);
- ShrinkWindow_SetLetterboxTarget(32);
+ ShrinkWindow_Letterbox_SetSizeTarget(32);
if (func_800EA220(play, csCtx, 1.0f)) {
Audio_SetCutsceneFlag(true);
csCtx->state++;
@@ -117,7 +118,7 @@ void func_800EA258(PlayState* play, CutsceneContext* csCtx) {
void func_800EA2B8(PlayState* play, CutsceneContext* csCtx) {
func_800ED980(play, csCtx);
Interface_SetHudVisibility(HUD_VISIBILITY_NONE);
- ShrinkWindow_SetLetterboxTarget(32);
+ ShrinkWindow_Letterbox_SetSizeTarget(32);
if (func_800EA220(play, csCtx, 1.0f)) {
Audio_SetCutsceneFlag(true);
csCtx->state++;
@@ -1449,8 +1450,8 @@ void func_800EDA84(PlayState* play, CutsceneContext* csCtx) {
if (gSaveContext.cutsceneTrigger == 0) {
Interface_SetHudVisibility(HUD_VISIBILITY_NONE);
- ShrinkWindow_SetLetterboxTarget(32);
- ShrinkWindow_SetLetterboxMagnitude(0x20);
+ ShrinkWindow_Letterbox_SetSizeTarget(32);
+ ShrinkWindow_Letterbox_SetSize(32);
csCtx->state++;
}
diff --git a/src/code/z_effect_soft_sprite_old_init.c b/src/code/z_effect_soft_sprite_old_init.c
index 5fc51b0c3..bbdd528a4 100644
--- a/src/code/z_effect_soft_sprite_old_init.c
+++ b/src/code/z_effect_soft_sprite_old_init.c
@@ -702,16 +702,16 @@ void EffectSsKFire_Spawn(PlayState* play, Vec3f* pos, Vec3f* velocity, Vec3f* ac
// EffectSsSolderSrchBall Spawn Functions
-void EffectSsSolderSrchBall_Spawn(PlayState* play, Vec3f* pos, Vec3f* velocity, Vec3f* accel, s16 unused,
- s16* linkDetected, s16 drawFlag) {
+void EffectSsSolderSrchBall_Spawn(PlayState* play, Vec3f* pos, Vec3f* velocity, Vec3f* accel, s16 scale,
+ s16* playerDetected, s16 flags) {
EffectSsSolderSrchBallInitParams initParams;
Math_Vec3f_Copy(&initParams.pos, pos);
Math_Vec3f_Copy(&initParams.velocity, velocity);
Math_Vec3f_Copy(&initParams.accel, accel);
- initParams.unused = unused;
- initParams.linkDetected = linkDetected;
- initParams.drawFlag = drawFlag;
+ initParams.scale = scale;
+ initParams.playerDetected = playerDetected;
+ initParams.flags = flags;
EffectSs_Spawn(play, EFFECT_SS_SOLDER_SRCH_BALL, 128, &initParams);
}
diff --git a/src/code/z_eventmgr.c b/src/code/z_eventmgr.c
index 7128368ac..5b8b8dce3 100644
--- a/src/code/z_eventmgr.c
+++ b/src/code/z_eventmgr.c
@@ -1,4 +1,5 @@
#include "global.h"
+#include "z64shrink_window.h"
#pragma GLOBAL_ASM("asm/non_matchings/code/z_eventmgr/func_800F1460.s")
diff --git a/src/code/z_game_over.c b/src/code/z_game_over.c
index 776dc75d7..857250eec 100644
--- a/src/code/z_game_over.c
+++ b/src/code/z_game_over.c
@@ -1,5 +1,6 @@
#include "global.h"
#include "z64rumble.h"
+#include "z64shrink_window.h"
void GameOver_Init(PlayState* play) {
play->gameOverCtx.state = GAMEOVER_INACTIVE;
@@ -86,7 +87,7 @@ void GameOver_Update(PlayState* play) {
gameOverCtx->state++;
sGameOverTimer = 0;
Kankyo_InitGameOverLights(play);
- ShrinkWindow_SetLetterboxTarget(32);
+ ShrinkWindow_Letterbox_SetSizeTarget(32);
break;
case GAMEOVER_REVIVE_RUMBLE:
sGameOverTimer = 50;
diff --git a/src/code/z_kaleido_scope_call.c b/src/code/z_kaleido_scope_call.c
index d7905e4dd..9cea42691 100644
--- a/src/code/z_kaleido_scope_call.c
+++ b/src/code/z_kaleido_scope_call.c
@@ -1,5 +1,6 @@
#include "prevent_bss_reordering.h"
#include "global.h"
+#include "z64shrink_window.h"
#include "overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope.h"
void (*sKaleidoScopeUpdateFunc)(PlayState* play);
@@ -36,7 +37,7 @@ void KaleidoScopeCall_Update(PlayState* play) {
if ((play->pauseCtx.state != 0) || (play->pauseCtx.debugEditor != DEBUG_EDITOR_NONE)) {
if (pauseCtx->state == 1 || pauseCtx->state == 19) {
- if (ShrinkWindow_GetLetterboxMagnitude() == 0) {
+ if (ShrinkWindow_Letterbox_GetSize() == 0) {
R_PAUSE_MENU_MODE = 1;
pauseCtx->unk_200 = 0;
pauseCtx->unk_208 = 0;
diff --git a/src/code/z_kaleido_setup.c b/src/code/z_kaleido_setup.c
index ad24321c7..ec9ae8824 100644
--- a/src/code/z_kaleido_setup.c
+++ b/src/code/z_kaleido_setup.c
@@ -1,5 +1,7 @@
#include "global.h"
#include "z64rumble.h"
+#include "z64shrink_window.h"
+#include "z64view.h"
#include "overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope.h"
s16 D_801BDB00[] = { PAUSE_MAP, PAUSE_QUEST, PAUSE_MASK, PAUSE_ITEM };
@@ -91,8 +93,8 @@ void KaleidoSetup_Update(PlayState* play) {
if (pauseCtx->state == 1) {
Game_SetFramerateDivisor(&play->state, 2);
- if (ShrinkWindow_GetLetterboxTarget() != 0) {
- ShrinkWindow_SetLetterboxTarget(0);
+ if (ShrinkWindow_Letterbox_GetSizeTarget() != 0) {
+ ShrinkWindow_Letterbox_SetSizeTarget(0);
}
func_801A3AEC(1);
}
diff --git a/src/code/z_message.c b/src/code/z_message.c
index df9d160a2..94b0e4b91 100644
--- a/src/code/z_message.c
+++ b/src/code/z_message.c
@@ -1,4 +1,6 @@
#include "global.h"
+#include "z64shrink_window.h"
+#include "z64view.h"
#include "message_data_static.h"
#include "overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope.h"
@@ -488,7 +490,7 @@ u8 Message_GetState(MessageContext* msgCtx) {
void func_80152C64(View* view) {
SET_FULLSCREEN_VIEWPORT(view);
- func_8013FBC8(view);
+ View_ApplyOrthoToOverlay(view);
}
#pragma GLOBAL_ASM("asm/non_matchings/code/z_message/func_80152CAC.s")
diff --git a/src/code/z_parameter.c b/src/code/z_parameter.c
index cf7716c9f..5bcd47e15 100644
--- a/src/code/z_parameter.c
+++ b/src/code/z_parameter.c
@@ -1,6 +1,6 @@
#include "global.h"
#include "z64snap.h"
-
+#include "z64view.h"
#include "interface/parameter_static/parameter_static.h"
#include "interface/do_action_static/do_action_static.h"
#include "misc/story_static/story_static.h"
@@ -3825,7 +3825,7 @@ void Interface_SetView1(PlayState* play, s32 topY, s32 bottomY, s32 leftX, s32 r
up.x = up.z = 0.0f;
up.y = 1.0f;
- View_SetViewOrientation(&interfaceCtx->view, &eye, &lookAt, &up);
+ View_LookAt(&interfaceCtx->view, &eye, &lookAt, &up);
interfaceCtx->viewport.topY = topY;
interfaceCtx->viewport.bottomY = bottomY;
@@ -3833,13 +3833,13 @@ void Interface_SetView1(PlayState* play, s32 topY, s32 bottomY, s32 leftX, s32 r
interfaceCtx->viewport.rightX = rightX;
View_SetViewport(&interfaceCtx->view, &interfaceCtx->viewport);
- func_8013F0D0(&interfaceCtx->view, 60.0f, 10.0f, 60.0f);
- func_8013FD74(&interfaceCtx->view);
+ View_SetPerspective(&interfaceCtx->view, 60.0f, 10.0f, 60.0f);
+ View_ApplyPerspectiveToOverlay(&interfaceCtx->view);
}
void Interface_SetView2(InterfaceContext* interfaceCtx) {
SET_FULLSCREEN_VIEWPORT(&interfaceCtx->view);
- func_8013FBC8(&interfaceCtx->view);
+ View_ApplyOrthoToOverlay(&interfaceCtx->view);
}
void Interface_DrawItemButtons(PlayState* play) {
diff --git a/src/code/z_play.c b/src/code/z_play.c
index 06ec9c21e..47bb97a60 100644
--- a/src/code/z_play.c
+++ b/src/code/z_play.c
@@ -1,5 +1,7 @@
#include "global.h"
#include "z64quake.h"
+#include "z64shrink_window.h"
+#include "z64view.h"
#pragma GLOBAL_ASM("asm/non_matchings/code/z_play/func_80165460.s")
diff --git a/src/code/z_quake.c b/src/code/z_quake.c
index 2b66a39f8..964935ea1 100644
--- a/src/code/z_quake.c
+++ b/src/code/z_quake.c
@@ -1,5 +1,6 @@
#include "global.h"
#include "z64quake.h"
+#include "z64view.h"
typedef struct {
/* 0x00 */ s16 randIndex;
@@ -823,10 +824,10 @@ void Distortion_Update(void) {
depthPhase += CAM_DEG_TO_BINANG(depthPhaseStep);
screenPlanePhase += CAM_DEG_TO_BINANG(screenPlanePhaseStep);
- View_SetDistortionDirRot(&sDistortionRequest.play->view,
- Math_CosS(depthPhase) * (DEGF_TO_RADF(rotX) * xyScaleFactor),
- Math_SinS(depthPhase) * (DEGF_TO_RADF(rotY) * xyScaleFactor),
- Math_SinS(screenPlanePhase) * (DEGF_TO_RADF(rotZ) * zScaleFactor));
+ View_SetDistortionOrientation(&sDistortionRequest.play->view,
+ Math_CosS(depthPhase) * (DEGF_TO_RADF(rotX) * xyScaleFactor),
+ Math_SinS(depthPhase) * (DEGF_TO_RADF(rotY) * xyScaleFactor),
+ Math_SinS(screenPlanePhase) * (DEGF_TO_RADF(rotZ) * zScaleFactor));
View_SetDistortionScale(&sDistortionRequest.play->view,
(Math_SinS(screenPlanePhase) * (xScale * xyScaleFactor)) + 1.0f,
(Math_CosS(screenPlanePhase) * (yScale * xyScaleFactor)) + 1.0f,
diff --git a/src/code/z_shrink_window.c b/src/code/z_shrink_window.c
index 5bfca86d9..acbdb5c5b 100644
--- a/src/code/z_shrink_window.c
+++ b/src/code/z_shrink_window.c
@@ -4,70 +4,78 @@
*/
#include "prevent_bss_reordering.h"
#include "global.h"
+#include "z64shrink_window.h"
-ShrinkWindowContext gShrinkWindowContext;
-ShrinkWindowContext* gShrinkWindowContextPtr;
+typedef struct {
+ /* 0x0 */ s8 letterboxTarget;
+ /* 0x1 */ s8 letterboxSize;
+ /* 0x2 */ s8 pillarboxTarget;
+ /* 0x3 */ s8 pillarboxSize;
+} ShrinkWindow; // size = 0x4
-void ShrinkWindow_SetLetterboxTarget(s32 target) {
- gShrinkWindowContextPtr->letterboxTarget = target;
+ShrinkWindow sShrinkWindow;
+ShrinkWindow* sShrinkWindowPtr;
+
+void ShrinkWindow_Letterbox_SetSizeTarget(s32 target) {
+ sShrinkWindowPtr->letterboxTarget = target;
}
-s32 ShrinkWindow_GetLetterboxTarget(void) {
- return gShrinkWindowContextPtr->letterboxTarget;
+s32 ShrinkWindow_Letterbox_GetSizeTarget(void) {
+ return sShrinkWindowPtr->letterboxTarget;
}
-void ShrinkWindow_SetLetterboxMagnitude(s32 magnitude) {
- gShrinkWindowContextPtr->letterboxMagnitude = magnitude;
+void ShrinkWindow_Letterbox_SetSize(s32 size) {
+ sShrinkWindowPtr->letterboxSize = size;
}
-s32 ShrinkWindow_GetLetterboxMagnitude(void) {
- return gShrinkWindowContextPtr->letterboxMagnitude;
+s32 ShrinkWindow_Letterbox_GetSize(void) {
+ return sShrinkWindowPtr->letterboxSize;
}
-void ShrinkWindow_SetPillarboxTarget(s32 target) {
- gShrinkWindowContextPtr->pillarboxTarget = target;
+void ShrinkWindow_Pillarbox_SetSizeTarget(s32 target) {
+ sShrinkWindowPtr->pillarboxTarget = target;
}
-s32 ShrinkWindow_GetPillarboxTarget(void) {
- return gShrinkWindowContextPtr->pillarboxTarget;
+s32 ShrinkWindow_Pillarbox_GetSizeTarget(void) {
+ return sShrinkWindowPtr->pillarboxTarget;
}
-void ShrinkWindow_SetPillarboxMagnitude(s32 magnitude) {
- gShrinkWindowContextPtr->pillarboxMagnitude = magnitude;
+void ShrinkWindow_Pillarbox_SetSize(s32 size) {
+ sShrinkWindowPtr->pillarboxSize = size;
}
-s32 ShrinkWindow_GetPillarboxMagnitude(void) {
- return gShrinkWindowContextPtr->pillarboxMagnitude;
+s32 ShrinkWindow_Pillarbox_GetSize(void) {
+ return sShrinkWindowPtr->pillarboxSize;
}
void ShrinkWindow_Init(void) {
- gShrinkWindowContextPtr = &gShrinkWindowContext;
- bzero(gShrinkWindowContextPtr, sizeof(gShrinkWindowContext));
+ sShrinkWindowPtr = &sShrinkWindow;
+ bzero(sShrinkWindowPtr, sizeof(sShrinkWindow));
}
void ShrinkWindow_Destroy(void) {
- gShrinkWindowContextPtr = NULL;
+ sShrinkWindowPtr = NULL;
}
void ShrinkWindow_Update(s32 framerateDivisor) {
- s32 step = ((framerateDivisor == 3) ? 10 : 30 / framerateDivisor);
- s32 nextMagnitude;
+ s32 step = (framerateDivisor == 3) ? 10 : (30 / framerateDivisor);
+ s32 nextSize;
- nextMagnitude = gShrinkWindowContextPtr->letterboxMagnitude;
- Math_StepToIGet(&nextMagnitude, gShrinkWindowContextPtr->letterboxTarget, step);
- gShrinkWindowContextPtr->letterboxMagnitude = nextMagnitude;
+ nextSize = sShrinkWindowPtr->letterboxSize;
+ Math_StepToIGet(&nextSize, sShrinkWindowPtr->letterboxTarget, step);
+ sShrinkWindowPtr->letterboxSize = nextSize;
- nextMagnitude = gShrinkWindowContextPtr->pillarboxMagnitude;
- Math_StepToIGet(&nextMagnitude, gShrinkWindowContextPtr->pillarboxTarget, step);
- gShrinkWindowContextPtr->pillarboxMagnitude = nextMagnitude;
+ nextSize = sShrinkWindowPtr->pillarboxSize;
+ Math_StepToIGet(&nextSize, sShrinkWindowPtr->pillarboxTarget, step);
+ sShrinkWindowPtr->pillarboxSize = nextSize;
}
void ShrinkWindow_Draw(GraphicsContext* gfxCtx) {
Gfx* gfx;
- s8 letterboxMagnitude = gShrinkWindowContextPtr->letterboxMagnitude;
- s8 pillarboxMagnitude = gShrinkWindowContextPtr->pillarboxMagnitude;
+ s8 letterboxSize = sShrinkWindowPtr->letterboxSize;
+ s8 pillarboxSize = sShrinkWindowPtr->pillarboxSize;
- if (letterboxMagnitude > 0) {
+ if (letterboxSize > 0) {
OPEN_DISPS(gfxCtx);
gfx = OVERLAY_DISP;
@@ -76,23 +84,23 @@ void ShrinkWindow_Draw(GraphicsContext* gfxCtx) {
gDPSetCycleType(gfx++, G_CYC_FILL);
gDPSetRenderMode(gfx++, G_RM_NOOP, G_RM_NOOP2);
gDPSetFillColor(gfx++, (GPACK_RGBA5551(0, 0, 0, 1) << 16) | GPACK_RGBA5551(0, 0, 0, 1));
- gDPFillRectangle(gfx++, 0, 0, gScreenWidth - 1, letterboxMagnitude - 1);
- gDPFillRectangle(gfx++, 0, gScreenHeight - letterboxMagnitude, gScreenWidth - 1, gScreenHeight - 1);
+ gDPFillRectangle(gfx++, 0, 0, gScreenWidth - 1, letterboxSize - 1);
+ gDPFillRectangle(gfx++, 0, gScreenHeight - letterboxSize, gScreenWidth - 1, gScreenHeight - 1);
gDPPipeSync(gfx++);
gDPSetCycleType(gfx++, G_CYC_1CYCLE);
gDPSetRenderMode(gfx++, G_RM_XLU_SURF, G_RM_XLU_SURF2);
gDPSetPrimColor(gfx++, 0, 0, 0, 0, 0, 0);
- gDPFillRectangle(gfx++, 0, letterboxMagnitude, gScreenWidth, letterboxMagnitude + 1);
- gDPFillRectangle(gfx++, 0, gScreenHeight - letterboxMagnitude - 1, gScreenWidth,
- gScreenHeight - letterboxMagnitude);
+ gDPFillRectangle(gfx++, 0, letterboxSize, gScreenWidth, letterboxSize + 1);
+ gDPFillRectangle(gfx++, 0, gScreenHeight - letterboxSize - 1, gScreenWidth, gScreenHeight - letterboxSize);
gDPPipeSync(gfx++);
OVERLAY_DISP = gfx++;
CLOSE_DISPS(gfxCtx);
}
- if (pillarboxMagnitude > 0) {
+
+ if (pillarboxSize > 0) {
OPEN_DISPS(gfxCtx);
gfx = OVERLAY_DISP;
@@ -102,17 +110,16 @@ void ShrinkWindow_Draw(GraphicsContext* gfxCtx) {
gDPSetRenderMode(gfx++, G_RM_NOOP, G_RM_NOOP2);
gDPSetFillColor(gfx++, (GPACK_RGBA5551(0, 0, 0, 1) << 16) | GPACK_RGBA5551(0, 0, 0, 1));
- gDPFillRectangle(gfx++, 0, 0, pillarboxMagnitude - 1, gScreenHeight - 1);
- gDPFillRectangle(gfx++, gScreenWidth - pillarboxMagnitude, 0, gScreenWidth - 1, gScreenHeight - 1);
+ gDPFillRectangle(gfx++, 0, 0, pillarboxSize - 1, gScreenHeight - 1);
+ gDPFillRectangle(gfx++, gScreenWidth - pillarboxSize, 0, gScreenWidth - 1, gScreenHeight - 1);
gDPPipeSync(gfx++);
gDPSetCycleType(gfx++, G_CYC_1CYCLE);
gDPSetRenderMode(gfx++, G_RM_XLU_SURF, G_RM_XLU_SURF2);
gDPSetPrimColor(gfx++, 0, 0, 0, 0, 0, 0);
- gDPFillRectangle(gfx++, pillarboxMagnitude, 0, pillarboxMagnitude + 2, gScreenHeight);
- gDPFillRectangle(gfx++, gScreenWidth - pillarboxMagnitude - 2, 0, gScreenWidth - pillarboxMagnitude,
- gScreenHeight);
+ gDPFillRectangle(gfx++, pillarboxSize, 0, pillarboxSize + 2, gScreenHeight);
+ gDPFillRectangle(gfx++, gScreenWidth - pillarboxSize - 2, 0, gScreenWidth - pillarboxSize, gScreenHeight);
gDPPipeSync(gfx++);
OVERLAY_DISP = gfx++;
diff --git a/src/code/z_view.c b/src/code/z_view.c
index 915c196b7..105e6643a 100644
--- a/src/code/z_view.c
+++ b/src/code/z_view.c
@@ -1,4 +1,9 @@
#include "global.h"
+#include "z64shrink_window.h"
+#include "z64view.h"
+
+s32 View_ApplyPerspective(View* view);
+s32 View_ApplyOrtho(View* view);
void View_ViewportToVp(Vp* dest, Viewport* src) {
s32 width = src->rightX - src->leftX;
@@ -13,41 +18,45 @@ void View_ViewportToVp(Vp* dest, Viewport* src) {
dest->vp.vtrans[2] = 0x01FF;
dest->vp.vtrans[3] = 0;
- if (src->leftX == 0 && src->rightX == 576 && src->topY == 0 && src->bottomY) {}
+ if ((src->leftX == 0) && (src->rightX == SCREEN_WIDTH_HIGH_RES) && (src->topY == 0) &&
+ (src->bottomY == SCREEN_HEIGHT_HIGH_RES)) {}
}
void View_Init(View* view, GraphicsContext* gfxCtx) {
view->gfxCtx = gfxCtx;
+
view->viewport.topY = 0;
- view->viewport.bottomY = 240;
+ view->viewport.bottomY = SCREEN_HEIGHT;
view->viewport.leftX = 0;
- view->viewport.rightX = 320;
- view->magic = 0x56494557; // "VIEW"
+ view->viewport.rightX = SCREEN_WIDTH;
- view->unk164 = 0;
- view->flags = 1 | 2 | 4;
+ view->magic = 0x56494557; // "VIEW"
- if (1) {
- ;
- }
+ if (1) {}
view->scale = 1.0f;
- view->up.y = 1.0f;
view->fovy = 60.0f;
+ view->zNear = 10.0f;
+ view->zFar = 12800.0f;
+
view->eye.x = 0.0f;
view->eye.y = 0.0f;
+ view->eye.z = -1.0f;
+
view->at.x = 0.0f;
+
view->up.x = 0.0f;
+ view->up.y = 1.0f;
view->up.z = 0.0f;
- view->zNear = 10.0f;
- view->zFar = 12800.0f;
- view->eye.z = -1.0f;
+
+ view->unk164 = 0;
+ view->flags = VIEW_VIEWING | VIEW_VIEWPORT | VIEW_PROJECTION_PERSPECTIVE;
View_InitDistortion(view);
}
-void View_SetViewOrientation(View* view, Vec3f* eye, Vec3f* at, Vec3f* up) {
- if (eye->x == at->x && eye->z == at->z) {
+void View_LookAt(View* view, Vec3f* eye, Vec3f* at, Vec3f* up) {
+ if ((eye->x == at->x) && (eye->z == at->z)) {
eye->z += 0.1f;
up->z = 0.0f;
up->x = 0.0f;
@@ -57,17 +66,21 @@ void View_SetViewOrientation(View* view, Vec3f* eye, Vec3f* at, Vec3f* up) {
view->eye = *eye;
view->at = *at;
view->up = *up;
- view->flags |= 1;
+ view->flags |= VIEW_VIEWING;
}
-void func_8013F050(View* view, Vec3f* eye, Vec3f* at, Vec3f* up) {
+/*
+ * Unused. View_LookAt is always used instead. This version is similar but
+ * is missing the input sanitization and the update to the flags.
+ */
+void View_LookAtUnsafe(View* view, Vec3f* eye, Vec3f* at, Vec3f* up) {
view->eye = *eye;
view->at = *at;
view->up = *up;
}
void View_SetScale(View* view, f32 scale) {
- view->flags |= 4;
+ view->flags |= VIEW_PROJECTION_PERSPECTIVE;
view->scale = scale;
}
@@ -75,28 +88,32 @@ void View_GetScale(View* view, f32* scale) {
*scale = view->scale;
}
-void func_8013F0D0(View* view, f32 fovy, f32 zNear, f32 zFar) {
+void View_SetPerspective(View* view, f32 fovy, f32 zNear, f32 zFar) {
view->fovy = fovy;
view->zNear = zNear;
view->zFar = zFar;
- view->flags |= 4;
+ view->flags |= VIEW_PROJECTION_PERSPECTIVE;
}
-void func_8013F100(View* view, f32* fovy, f32* zNear, f32* zFar) {
+void View_GetPerspective(View* view, f32* fovy, f32* zNear, f32* zFar) {
*fovy = view->fovy;
*zNear = view->zNear;
*zFar = view->zFar;
}
-void func_8013F120(View* view, f32 fovy, f32 zNear, f32 zFar) {
+void View_SetOrtho(View* view, f32 fovy, f32 zNear, f32 zFar) {
view->fovy = fovy;
view->zNear = zNear;
view->zFar = zFar;
- view->flags |= 8;
+ view->flags |= VIEW_PROJECTION_ORTHO;
view->scale = 1.0f;
}
-void func_8013F15C(View* view, f32* fovy, f32* zNear, f32* zFar) {
+/*
+ * Identical to View_GetPerspective, and never called.
+ * Named as it seems to fit the "set, get" pattern.
+ */
+void View_GetOrtho(View* view, f32* fovy, f32* zNear, f32* zFar) {
*fovy = view->fovy;
*zNear = view->zNear;
*zFar = view->zFar;
@@ -104,14 +121,14 @@ void func_8013F15C(View* view, f32* fovy, f32* zNear, f32* zFar) {
void View_SetViewport(View* view, Viewport* viewport) {
view->viewport = *viewport;
- view->flags |= 2;
+ view->flags |= VIEW_VIEWPORT;
}
void View_GetViewport(View* view, Viewport* viewport) {
*viewport = view->viewport;
}
-void View_WriteScissor(Gfx** gfx, s32 ulx, s32 uly, s32 lrx, s32 lry) {
+void View_SetScissor(Gfx** gfx, s32 ulx, s32 uly, s32 lrx, s32 lry) {
Gfx* gfxp = *gfx;
gDPSetScissor(gfxp++, G_SC_NON_INTERLACE, ulx, uly, lrx, lry);
@@ -119,7 +136,7 @@ void View_WriteScissor(Gfx** gfx, s32 ulx, s32 uly, s32 lrx, s32 lry) {
*gfx = gfxp;
}
-void View_SyncAndWriteScissor(View* view, Gfx** gfx) {
+void View_ClearScissor(View* view, Gfx** gfx) {
Gfx* gfxp = *gfx;
s32 ulx = view->viewport.leftX;
s32 uly = view->viewport.topY;
@@ -127,12 +144,12 @@ void View_SyncAndWriteScissor(View* view, Gfx** gfx) {
s32 lry = view->viewport.bottomY;
gDPPipeSync(gfxp++);
- View_WriteScissor(&gfxp, ulx, uly, lrx, lry);
+ View_SetScissor(&gfxp, ulx, uly, lrx, lry);
*gfx = gfxp;
}
-void View_SetScissorForLetterbox(View* view) {
+void View_ApplyLetterbox(View* view) {
s32 letterboxY;
s32 letterboxX;
s32 pad1;
@@ -143,20 +160,21 @@ void View_SetScissorForLetterbox(View* view) {
OPEN_DISPS(view->gfxCtx);
- letterboxY = ShrinkWindow_GetLetterboxMagnitude();
+ letterboxY = ShrinkWindow_Letterbox_GetSize();
+
letterboxX = -1; // The following is optimized to varX = 0 but affects codegen
if (letterboxX < 0) {
letterboxX = 0;
}
- if (letterboxX > 160) {
- letterboxX = 160;
+ if (letterboxX > (SCREEN_WIDTH / 2)) {
+ letterboxX = SCREEN_WIDTH / 2;
}
if (letterboxY < 0) {
letterboxY = 0;
- } else if (letterboxY > 120) {
- letterboxY = 120;
+ } else if (letterboxY > (SCREEN_HEIGHT / 2)) {
+ letterboxY = SCREEN_HEIGHT / 2;
}
ulx = view->viewport.leftX + letterboxX;
@@ -166,31 +184,31 @@ void View_SetScissorForLetterbox(View* view) {
gDPPipeSync(POLY_OPA_DISP++);
{
- s32 pad3;
+ s32 pad2;
Gfx* polyOpa;
polyOpa = POLY_OPA_DISP;
- View_WriteScissor(&polyOpa, ulx, uly, lrx, lry);
+ View_SetScissor(&polyOpa, ulx, uly, lrx, lry);
POLY_OPA_DISP = polyOpa;
}
gDPPipeSync(POLY_XLU_DISP++);
{
Gfx* polyXlu;
- s32 pad4;
+ s32 pad3;
polyXlu = POLY_XLU_DISP;
- View_WriteScissor(&polyXlu, ulx, uly, lrx, lry);
+ View_SetScissor(&polyXlu, ulx, uly, lrx, lry);
POLY_XLU_DISP = polyXlu;
}
CLOSE_DISPS(view->gfxCtx);
}
-s32 View_SetDistortionDirRot(View* view, f32 dirRotX, f32 dirRotY, f32 dirRotZ) {
- view->distortionDirRot.x = dirRotX;
- view->distortionDirRot.y = dirRotY;
- view->distortionDirRot.z = dirRotZ;
+s32 View_SetDistortionOrientation(View* view, f32 rotX, f32 rotY, f32 rotZ) {
+ view->distortionOrientation.x = rotX;
+ view->distortionOrientation.y = rotY;
+ view->distortionOrientation.z = rotZ;
return 1;
}
@@ -207,22 +225,22 @@ s32 View_SetDistortionSpeed(View* view, f32 speed) {
}
s32 View_InitDistortion(View* view) {
- view->distortionDirRot.x = 0.0f;
- view->distortionDirRot.y = 0.0f;
- view->distortionDirRot.z = 0.0f;
+ view->distortionOrientation.x = 0.0f;
+ view->distortionOrientation.y = 0.0f;
+ view->distortionOrientation.z = 0.0f;
view->distortionScale.x = 1.0f;
view->distortionScale.y = 1.0f;
view->distortionScale.z = 1.0f;
- view->curDistortionDirRot = view->distortionDirRot;
+ view->curDistortionOrientation = view->distortionOrientation;
view->curDistortionScale = view->distortionScale;
view->distortionSpeed = 0.0f;
return 1;
}
s32 View_ClearDistortion(View* view) {
- view->distortionDirRot.x = 0.0f;
- view->distortionDirRot.y = 0.0f;
- view->distortionDirRot.z = 0.0f;
+ view->distortionOrientation.x = 0.0f;
+ view->distortionOrientation.y = 0.0f;
+ view->distortionOrientation.z = 0.0f;
view->distortionScale.x = 1.0f;
view->distortionScale.y = 1.0f;
view->distortionScale.z = 1.0f;
@@ -230,8 +248,8 @@ s32 View_ClearDistortion(View* view) {
return 1;
}
-s32 View_SetDistortion(View* view, Vec3f dirRot, Vec3f scale, f32 speed) {
- view->distortionDirRot = dirRot;
+s32 View_SetDistortion(View* view, Vec3f orientation, Vec3f scale, f32 speed) {
+ view->distortionOrientation = orientation;
view->distortionScale = scale;
view->distortionSpeed = speed;
return 1;
@@ -242,17 +260,19 @@ s32 View_StepDistortion(View* view, Mtx* projectionMtx) {
if (view->distortionSpeed == 0.0f) {
return false;
- } else if (view->distortionSpeed == 1.0f) {
- view->curDistortionDirRot = view->distortionDirRot;
+ }
+
+ if (view->distortionSpeed == 1.0f) {
+ view->curDistortionOrientation = view->distortionOrientation;
view->curDistortionScale = view->distortionScale;
view->distortionSpeed = 0.0f;
} else {
- view->curDistortionDirRot.x =
- F32_LERPIMP(view->curDistortionDirRot.x, view->distortionDirRot.x, view->distortionSpeed);
- view->curDistortionDirRot.y =
- F32_LERPIMP(view->curDistortionDirRot.y, view->distortionDirRot.y, view->distortionSpeed);
- view->curDistortionDirRot.z =
- F32_LERPIMP(view->curDistortionDirRot.z, view->distortionDirRot.z, view->distortionSpeed);
+ view->curDistortionOrientation.x =
+ F32_LERPIMP(view->curDistortionOrientation.x, view->distortionOrientation.x, view->distortionSpeed);
+ view->curDistortionOrientation.y =
+ F32_LERPIMP(view->curDistortionOrientation.y, view->distortionOrientation.y, view->distortionSpeed);
+ view->curDistortionOrientation.z =
+ F32_LERPIMP(view->curDistortionOrientation.z, view->distortionOrientation.z, view->distortionSpeed);
view->curDistortionScale.x =
F32_LERPIMP(view->curDistortionScale.x, view->distortionScale.x, view->distortionSpeed);
@@ -264,29 +284,32 @@ s32 View_StepDistortion(View* view, Mtx* projectionMtx) {
Matrix_MtxToMtxF(projectionMtx, &projectionMtxF);
Matrix_Put(&projectionMtxF);
- Matrix_RotateXFApply(view->curDistortionDirRot.x);
- Matrix_RotateYF(view->curDistortionDirRot.y, MTXMODE_APPLY);
- Matrix_RotateZF(view->curDistortionDirRot.z, MTXMODE_APPLY);
+ Matrix_RotateXFApply(view->curDistortionOrientation.x);
+ Matrix_RotateYF(view->curDistortionOrientation.y, MTXMODE_APPLY);
+ Matrix_RotateZF(view->curDistortionOrientation.z, MTXMODE_APPLY);
Matrix_Scale(view->curDistortionScale.x, view->curDistortionScale.y, view->curDistortionScale.z, MTXMODE_APPLY);
- Matrix_RotateZF(-view->curDistortionDirRot.z, MTXMODE_APPLY);
- Matrix_RotateYF(-view->curDistortionDirRot.y, MTXMODE_APPLY);
- Matrix_RotateXFApply(-view->curDistortionDirRot.x);
+ Matrix_RotateZF(-view->curDistortionOrientation.z, MTXMODE_APPLY);
+ Matrix_RotateYF(-view->curDistortionOrientation.y, MTXMODE_APPLY);
+ Matrix_RotateXFApply(-view->curDistortionOrientation.x);
Matrix_ToMtx(projectionMtx);
return true;
}
-void View_RenderView(View* view, s32 uParm2) {
- uParm2 = (view->flags & uParm2) | uParm2 >> 4;
+/**
+ * Apply view to POLY_OPA_DISP, POLY_XLU_DISP (and OVERLAY_DISP if ortho)
+ */
+void View_Apply(View* view, s32 mask) {
+ mask = (view->flags & mask) | (mask >> 4);
- if (uParm2 & 8) {
- View_RenderToOrthographicMatrix(view);
+ if (mask & VIEW_PROJECTION_ORTHO) {
+ View_ApplyOrtho(view);
} else {
- View_RenderToPerspectiveMatrix(view);
+ View_ApplyPerspective(view);
}
}
-s32 View_RenderToPerspectiveMatrix(View* view) {
+s32 View_ApplyPerspective(View* view) {
f32 aspect;
s32 width;
s32 height;
@@ -297,36 +320,39 @@ s32 View_RenderToPerspectiveMatrix(View* view) {
OPEN_DISPS(gfxCtx);
- vp = GRAPH_ALLOC(gfxCtx, sizeof(*vp));
+ // Viewport
+ vp = GRAPH_ALLOC(gfxCtx, sizeof(Vp));
View_ViewportToVp(vp, &view->viewport);
view->vp = *vp;
- View_SetScissorForLetterbox(view);
+ View_ApplyLetterbox(view);
gSPViewport(POLY_OPA_DISP++, vp);
gSPViewport(POLY_XLU_DISP++, vp);
- projection = GRAPH_ALLOC(gfxCtx, sizeof(*projection));
+ // Perspective projection
+ projection = GRAPH_ALLOC(gfxCtx, sizeof(Mtx));
view->projectionPtr = projection;
width = view->viewport.rightX - view->viewport.leftX;
height = view->viewport.bottomY - view->viewport.topY;
aspect = (f32)width / (f32)height;
- guPerspective(projection, &view->normal, view->fovy, aspect, view->zNear, view->zFar, view->scale);
+ guPerspective(projection, &view->perspNorm, view->fovy, aspect, view->zNear, view->zFar, view->scale);
view->projection = *projection;
View_StepDistortion(view, projection);
- gSPPerspNormalize(POLY_OPA_DISP++, view->normal);
+ gSPPerspNormalize(POLY_OPA_DISP++, view->perspNorm);
gSPMatrix(POLY_OPA_DISP++, projection, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION);
- gSPPerspNormalize(POLY_XLU_DISP++, view->normal);
+ gSPPerspNormalize(POLY_XLU_DISP++, view->perspNorm);
gSPMatrix(POLY_XLU_DISP++, projection, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION);
- viewing = GRAPH_ALLOC(gfxCtx, sizeof(*viewing));
+ // View matrix (look-at)
+ viewing = GRAPH_ALLOC(gfxCtx, sizeof(Mtx));
view->viewingPtr = viewing;
- if (view->eye.x == view->at.x && view->eye.y == view->at.y && view->eye.z == view->at.z) {
+ if ((view->eye.x == view->at.x) && (view->eye.y == view->at.y) && (view->eye.z == view->at.z)) {
view->eye.z += 2.0f;
}
@@ -343,24 +369,24 @@ s32 View_RenderToPerspectiveMatrix(View* view) {
return 1;
}
-s32 View_RenderToOrthographicMatrix(View* view) {
+s32 View_ApplyOrtho(View* view) {
Vp* vp;
Mtx* projection;
GraphicsContext* gfxCtx = view->gfxCtx;
OPEN_DISPS(gfxCtx);
- vp = GRAPH_ALLOC(gfxCtx, sizeof(*vp));
+ vp = GRAPH_ALLOC(gfxCtx, sizeof(Vp));
View_ViewportToVp(vp, &view->viewport);
view->vp = *vp;
- View_SetScissorForLetterbox(view);
+ View_ApplyLetterbox(view);
gSPViewport(POLY_OPA_DISP++, vp);
gSPViewport(POLY_XLU_DISP++, vp);
gSPViewport(OVERLAY_DISP++, vp);
- projection = GRAPH_ALLOC(gfxCtx, sizeof(*projection));
+ projection = GRAPH_ALLOC(gfxCtx, sizeof(Mtx));
view->projectionPtr = projection;
guOrtho(projection, gScreenWidth * -0.5f, gScreenWidth * 0.5f, gScreenHeight * -0.5f, gScreenHeight * 0.5f,
@@ -376,7 +402,10 @@ s32 View_RenderToOrthographicMatrix(View* view) {
return 1;
}
-s32 func_8013FBC8(View* view) {
+/**
+ * Apply scissor, viewport and projection (ortho) to OVERLAY_DISP.
+ */
+s32 View_ApplyOrthoToOverlay(View* view) {
Vp* vp;
Mtx* projection;
GraphicsContext* gfxCtx;
@@ -385,7 +414,7 @@ s32 func_8013FBC8(View* view) {
OPEN_DISPS(gfxCtx);
- vp = GRAPH_ALLOC(gfxCtx, sizeof(*vp));
+ vp = GRAPH_ALLOC(gfxCtx, sizeof(Vp));
View_ViewportToVp(vp, &view->viewport);
view->vp = *vp;
@@ -395,26 +424,29 @@ s32 func_8013FBC8(View* view) {
s32 pad;
overlay = OVERLAY_DISP;
- View_WriteScissor(&overlay, view->viewport.leftX, view->viewport.topY, view->viewport.rightX,
- view->viewport.bottomY);
+ View_SetScissor(&overlay, view->viewport.leftX, view->viewport.topY, view->viewport.rightX,
+ view->viewport.bottomY);
OVERLAY_DISP = overlay;
}
gSPViewport(OVERLAY_DISP++, vp);
- projection = GRAPH_ALLOC(gfxCtx, sizeof(*projection));
+ projection = GRAPH_ALLOC(gfxCtx, sizeof(Mtx));
view->projectionPtr = projection;
guOrtho(projection, gScreenWidth * -0.5f, gScreenWidth * 0.5f, gScreenHeight * -0.5f, gScreenHeight * 0.5f,
view->zNear, view->zFar, view->scale);
view->projection = *projection;
- gSPMatrix(OVERLAY_DISP++, projection, G_MTX_LOAD | G_MTX_PROJECTION);
+ gSPMatrix(OVERLAY_DISP++, projection, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION);
CLOSE_DISPS(gfxCtx);
return 1;
}
-s32 func_8013FD74(View* view) {
+/**
+ * Apply scissor, viewport, view and projection (perspective) to OVERLAY_DISP.
+ */
+s32 View_ApplyPerspectiveToOverlay(View* view) {
f32 aspect;
s32 width;
s32 height;
@@ -428,7 +460,7 @@ s32 func_8013FD74(View* view) {
OPEN_DISPS(gfxCtx);
- vp = GRAPH_ALLOC(gfxCtx, sizeof(*vp));
+ vp = GRAPH_ALLOC(gfxCtx, sizeof(Vp));
View_ViewportToVp(vp, &view->viewport);
view->vp = *vp;
@@ -438,28 +470,30 @@ s32 func_8013FD74(View* view) {
Gfx* overlay;
overlay = OVERLAY_DISP;
- View_WriteScissor(&overlay, view->viewport.leftX, view->viewport.topY, view->viewport.rightX,
- view->viewport.bottomY);
+ View_SetScissor(&overlay, view->viewport.leftX, view->viewport.topY, view->viewport.rightX,
+ view->viewport.bottomY);
OVERLAY_DISP = overlay;
}
gSPViewport(OVERLAY_DISP++, vp);
- projection = GRAPH_ALLOC(gfxCtx, sizeof(*projection));
+ projection = GRAPH_ALLOC(gfxCtx, sizeof(Mtx));
view->projectionPtr = projection;
width = view->viewport.rightX - view->viewport.leftX;
height = view->viewport.bottomY - view->viewport.topY;
aspect = (f32)width / (f32)height;
- guPerspective(projection, &view->normal, view->fovy, aspect, view->zNear, view->zFar, view->scale);
+ guPerspective(projection, &view->perspNorm, view->fovy, aspect, view->zNear, view->zFar, view->scale);
+
view->projection = *projection;
- gSPPerspNormalize(OVERLAY_DISP++, view->normal);
+ gSPPerspNormalize(OVERLAY_DISP++, view->perspNorm);
gSPMatrix(OVERLAY_DISP++, projection, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION);
- viewing = GRAPH_ALLOC(gfxCtx, sizeof(*viewing));
+ viewing = GRAPH_ALLOC(gfxCtx, sizeof(Mtx));
view->viewingPtr = viewing;
+ // This check avoids a divide-by-zero in guLookAt if eye == at
if (view->eye.x == view->at.x && view->eye.y == view->at.y && view->eye.z == view->at.z) {
view->eye.z += 2.0f;
}
@@ -476,7 +510,10 @@ s32 func_8013FD74(View* view) {
return 1;
}
-s32 func_80140024(View* view) {
+/**
+ * Just updates view's view matrix from its eye/at/up vectors.
+ */
+s32 View_UpdateViewingMatrix(View* view) {
guLookAt(view->viewingPtr, view->eye.x, view->eye.y, view->eye.z, view->at.x, view->at.y, view->at.z, view->up.x,
view->up.y, view->up.z);
@@ -486,22 +523,22 @@ s32 func_80140024(View* view) {
return 1;
}
-s32 func_801400CC(View* view, Gfx** gfxp) {
+s32 View_ApplyTo(View* view, Gfx** gfxp) {
Gfx* gfx = *gfxp;
GraphicsContext* gfxCtx = view->gfxCtx;
Viewport* viewport = &view->viewport;
Mtx* projection;
Vp* vp;
- vp = GRAPH_ALLOC(gfxCtx, sizeof(*vp));
+ vp = GRAPH_ALLOC(gfxCtx, sizeof(Vp));
View_ViewportToVp(vp, viewport);
view->vp = *vp;
- View_SyncAndWriteScissor(view, &gfx);
+ View_ClearScissor(view, &gfx);
gSPViewport(gfx++, vp);
- projection = GRAPH_ALLOC(gfxCtx, sizeof(*projection));
+ projection = GRAPH_ALLOC(gfxCtx, sizeof(Mtx));
view->projectionPtr = projection;
guOrtho(projection, gScreenWidth * -0.5f, gScreenWidth * 0.5f, gScreenHeight * -0.5f, gScreenHeight * 0.5f,
@@ -509,7 +546,7 @@ s32 func_801400CC(View* view, Gfx** gfxp) {
view->projection = *projection;
- gSPMatrix(gfx++, projection, G_MTX_LOAD | G_MTX_PROJECTION);
+ gSPMatrix(gfx++, projection, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION);
*gfxp = gfx;
return 1;