From 601f44cb7fad4d2ad0d653ef0ddec45817ed9285 Mon Sep 17 00:00:00 2001 From: engineer124 <47598039+engineer124@users.noreply.github.com> Date: Fri, 22 Jul 2022 01:21:02 -0400 Subject: [PATCH] audio_seqplayer.c OK and partial docs (#833) * Import audio_seqplayer progress from main audio branch * cleanup * Better docs * Small fix * More * Cleanup and update * PR Suggestions * PR Suggestions * mute flags --- include/functions.h | 42 +- include/variables.h | 14 +- include/z64audio.h | 71 +- spec | 1 - src/code/audio/audio_data.c | 6 +- src/code/audio/audio_effects.c | 4 +- src/code/audio/audio_heap.c | 84 +- src/code/audio/audio_load.c | 75 +- src/code/audio/audio_playback.c | 26 +- src/code/audio/audio_seqplayer.c | 2311 +++++++++++++++++++++++++++++- tools/disasm/functions.txt | 56 +- tools/disasm/variables.txt | 2 +- tools/sizes/code_functions.csv | 56 +- 13 files changed, 2482 insertions(+), 266 deletions(-) diff --git a/include/functions.h b/include/functions.h index 88a24eda01..cbacf412c7 100644 --- a/include/functions.h +++ b/include/functions.h @@ -3124,8 +3124,8 @@ void AudioLoad_AsyncLoadFont(s32 fontId, s32 arg1, s32 retData, OSMesgQueue* ret u8* AudioLoad_GetFontsForSequence(s32 seqId, u32* outNumFonts); void AudioLoad_DiscardSeqFonts(s32 seqId); void func_8018FA60(u32 tableType, u32 id, s32 arg2, s32 arg3); -s32 AudioLoad_SyncIniPlayer(s32 playerIdx, s32 seqId, s32 arg2); -s32 AudioLoad_SyncInitSetSeqqPlayerSkipTicks(s32 playerIdx, s32 seqId, s32 skipTicks); +s32 AudioLoad_SyncInitSeqPlayer(s32 playerIndex, s32 seqId, s32 arg2); +s32 AudioLoad_SyncInitSeqPlayerSkipTicks(s32 playerIndex, s32 seqId, s32 skipTicks); void AudioLoad_ProcessLoads(s32 resetStatus); void AudioLoad_SetDmaHandler(DmaHandler callback); void AudioLoad_Init(void* heap, u32 heapSize); @@ -3198,43 +3198,17 @@ void AudioEffects_SequencePlayerProcessSound(SequencePlayer* seqPlayer); void AudioEffects_NoteVibratoUpdate(Note* note); void AudioEffects_NoteVibratoInit(Note* note); void AudioEffects_NotePortamentoInit(Note* note); -void AudioEffects_AdsrInit(AdsrState* adsr, AdsrEnvelope* envelope, s16* volOut); +void AudioEffects_AdsrInit(AdsrState* adsr, EnvelopePoint* envelope, s16* volOut); f32 AudioEffects_AdsrUpdate(AdsrState* adsr); -// void func_801974D0(void); -// void func_80197538(void); -// void func_80197714(void); -// void func_80197880(void); -// void func_801979D8(void); -// void func_80197A54(void); void AudioSeq_SequenceChannelDisable(SequenceChannel* channel); -// void func_80197B14(void); -// void func_80197C0C(void); -// void func_80197C8C(void); void AudioSeq_SequencePlayerDisableAsFinished(SequencePlayer* seqPlayer); void AudioSeq_SequencePlayerDisable(SequencePlayer* seqPlayer); void AudioSeq_AudioListPushBack(AudioListItem* list, AudioListItem* item); void* AudioSeq_AudioListPopBack(AudioListItem* list); -// void func_80197E88(void); -// void func_80197F28(void); -// void func_80197F3C(void); -// void func_80197F74(void); -// void func_80197FB4(void); -// void func_801980D0(void); -// void func_8019815C(void); -// void func_8019825C(void); -// void func_80198640(void); -// void func_80198CE0(void); -// void func_801990F4(void); -// void func_80199124(void); -// void func_80199198(void); -// void func_80199244(void); -void func_80199268(s32* param_1); -// void func_8019A0BC(void); -// void func_8019AA3C(void); -// void func_8019AAF0(void); +void AudioSeq_ProcessSequences(s32 arg0); +void AudioSeq_SkipForwardSequence(SequencePlayer* seqPlayer); void AudioSeq_ResetSequencePlayer(SequencePlayer* seqPlayer); -void AudioSeq_InitSequencePlayerChannels(s32 playerIdx); -// void func_8019ACEC(void); +void AudioSeq_InitSequencePlayerChannels(s32 playerIndex); void AudioSeq_InitSequencePlayers(void); void func_8019AE40(s32 param_1, s32 param_2, u32 param_3, s32 param_4); void func_8019AEC0(UNK_PTR param_1, UNK_PTR param_2); @@ -3356,7 +3330,7 @@ void func_801A1DB8(Vec3f* vec, u8 seqId, f32 arg2); // void func_801A1E0C(void); void func_801A1F00(u8 arg0, u16 seqId); void func_801A1F88(void); -void func_801A1FB4(u8 playerIdx, Vec3f* pos, u16 seqId, f32 maxDist); +void func_801A1FB4(u8 playerIndex, Vec3f* pos, u16 seqId, f32 maxDist); // void func_801A2090(void); void func_801A246C(u8 param_1, u8 param_2); // void func_801A2544(void); @@ -3474,7 +3448,7 @@ void Audio_QueueSeqCmd(u32 cmd); // void func_801A89D0(void); s32 func_801A8A50(s32 param1); // void func_801A8ABC(void); -void Audio_SetVolumeScale(u8 playerIdx, u8 scaleIdx, u8 targetVol, u8 volFadeTimer); +void Audio_SetVolumeScale(u8 playerIndex, u8 scaleIndex, u8 targetVol, u8 volFadeTimer); // void func_801A8D5C(void); // void func_801A8E90(void); // void func_801A9768(void); diff --git a/include/variables.h b/include/variables.h index ae65131590..db16664a11 100644 --- a/include/variables.h +++ b/include/variables.h @@ -1554,16 +1554,12 @@ extern s16 gHighPassFilterData[]; extern s16 gBandStopFilterData[]; extern s16 gBandPassFilterData[]; extern s16* gWaveSamples[9]; -extern UNK_PTR D_801D4D98; -extern UNK_PTR D_801D4DB0; extern f32 gBendPitchOneOctaveFrequencies[256]; -// extern UNK_TYPE1 D_801D4FB4; -// extern UNK_TYPE4 gBendPitchTwoSemitonesFrequencies; -// extern UNK_TYPE4 D_801D53B4; -// extern UNK_TYPE1 gPitchFrequencies; -// extern UNK_TYPE1 gDefaultShortNoteVelocityTable; -// extern UNK_TYPE1 gDefaultShortNoteGateTimeTable; -// extern UNK_TYPE1 gDefaultEnvelope; +extern f32 gBendPitchTwoSemitonesFrequencies[]; +extern f32 gPitchFrequencies[]; +extern u8 gDefaultShortNoteVelocityTable[]; +extern u8 gDefaultShortNoteGateTimeTable[]; +extern EnvelopePoint gDefaultEnvelope[]; extern NoteSubEu gZeroNoteSub; extern NoteSubEu gDefaultNoteSub; extern u16 gHeadsetPanQuantization[]; diff --git a/include/z64audio.h b/include/z64audio.h index 5dd78f73ad..af104b6c28 100644 --- a/include/z64audio.h +++ b/include/z64audio.h @@ -8,9 +8,16 @@ #define TATUMS_PER_BEAT 48 #define IS_SEQUENCE_CHANNEL_VALID(ptr) ((uintptr_t)(ptr) != (uintptr_t)&gAudioContext.sequenceChannelNone) +#define SEQ_NUM_CHANNELS 16 #define MAX_CHANNELS_PER_BANK 3 +#define MUTE_FLAGS_3 (1 << 3) // prevent further noteSubEus from playing +#define MUTE_FLAGS_4 (1 << 4) // stop something in seqLayer scripts +#define MUTE_FLAGS_SOFTEN (1 << 5) // lower volume, by default to half +#define MUTE_FLAGS_STOP_NOTES (1 << 6) // prevent further notes from playing +#define MUTE_FLAGS_STOP_SCRIPT (1 << 7) // stop processing sequence/channel scripts + #define AUDIO_LERPIMP(v0, v1, t) (v0 + ((v1 - v0) * t)) #define ADSR_DISABLE 0 @@ -86,12 +93,12 @@ typedef enum { } AudioCacheType; typedef enum { - /* 0 */ LOAD_STATUS_0, - /* 1 */ LOAD_STATUS_1, - /* 2 */ LOAD_STATUS_2, // Samples/Seqplayer - /* 3 */ LOAD_STATUS_3, // Sequences - /* 4 */ LOAD_STATUS_4, // SoundFonts - /* 5 */ LOAD_STATUS_5 // Permanent + /* 0 */ LOAD_STATUS_NOT_LOADED, + /* 1 */ LOAD_STATUS_IN_PROGRESS, + /* 2 */ LOAD_STATUS_COMPLETE, + /* 3 */ LOAD_STATUS_DISCARDABLE, + /* 4 */ LOAD_STATUS_MAYBE_DISCARDABLE, + /* 5 */ LOAD_STATUS_PERMANENT } AudioLoadStatus; typedef s32 (*DmaHandler)(OSPiHandle* handle, OSIoMesg* mb, s32 direction); @@ -139,7 +146,7 @@ typedef struct { typedef struct { /* 0x0 */ s16 delay; /* 0x2 */ s16 arg; -} AdsrEnvelope; // size = 0x4 +} EnvelopePoint; // size = 0x4 typedef struct { /* 0x00 */ u32 start; @@ -231,19 +238,19 @@ typedef struct { /* 0x00 */ u8 loaded; /* 0x01 */ u8 normalRangeLo; /* 0x02 */ u8 normalRangeHi; - /* 0x03 */ u8 releaseRate; - /* 0x04 */ AdsrEnvelope* envelope; + /* 0x03 */ u8 adsrDecayIndex; // index used to obtain adsr decay rate from adsrDecayTable + /* 0x04 */ EnvelopePoint* envelope; /* 0x08 */ SoundFontSound lowNotesSound; /* 0x10 */ SoundFontSound normalNotesSound; /* 0x18 */ SoundFontSound highNotesSound; } Instrument; // size = 0x20 typedef struct { - /* 0x00 */ u8 releaseRate; + /* 0x00 */ u8 adsrDecayIndex; // index used to obtain adsr decay rate from adsrDecayTable /* 0x01 */ u8 pan; /* 0x02 */ u8 loaded; /* 0x04 */ SoundFontSound sound; - /* 0x14 */ AdsrEnvelope* envelope; + /* 0x14 */ EnvelopePoint* envelope; } Drum; // size = 0x18 typedef struct { @@ -277,11 +284,11 @@ typedef struct { /* 0x000 */ u8 applyBend : 1; /* 0x001 */ u8 state; /* 0x002 */ u8 noteAllocPolicy; - /* 0x003 */ u8 muteBehavior; + /* 0x003 */ u8 muteFlags; /* 0x004 */ u8 seqId; /* 0x005 */ u8 defaultFont; /* 0x006 */ u8 unk_06[1]; - /* 0x007 */ s8 playerIdx; + /* 0x007 */ s8 playerIndex; /* 0x008 */ u16 tempo; // tatums per minute /* 0x00A */ u16 tempoAcc; /* 0x00C */ s16 unk_0C; @@ -289,7 +296,7 @@ typedef struct { /* 0x010 */ u16 delay; /* 0x012 */ u16 fadeTimer; /* 0x014 */ u16 fadeTimerUnkEu; - /* 0x016 */ u16 unk_16; // New to MM + /* 0x016 */ u16 unk_16; union { /* 0x018 */ u8* seqData; /* 0x018 */ u16* seqData16; @@ -313,9 +320,9 @@ typedef struct { } SequencePlayer; // size = 0x160 typedef struct { - /* 0x0 */ u8 releaseRate; + /* 0x0 */ u8 decayIndex; // index used to obtain adsr decay rate from adsrDecayTable /* 0x1 */ u8 sustain; - /* 0x4 */ AdsrEnvelope* envelope; + /* 0x4 */ EnvelopePoint* envelope; } AdsrSettings; // size = 0x8 typedef struct { @@ -337,7 +344,7 @@ typedef struct { /* 0x10 */ f32 current; /* 0x14 */ f32 target; /* 0x18 */ char unk_18[4]; - /* 0x1C */ AdsrEnvelope* envelope; + /* 0x1C */ EnvelopePoint* envelope; } AdsrState; // size = 0x20 typedef struct { @@ -356,7 +363,7 @@ typedef union { typedef struct { /* 0x00 */ u8 reverb; - /* 0x01 */ u8 unk_1; + /* 0x01 */ u8 gain; // Increases volume by a multiplicative scaling factor. Represented as a UQ4.4 number /* 0x02 */ u8 pan; /* 0x03 */ u8 unk_3; // Possibly part of stereo? /* 0x04 */ Stereo stereo; @@ -397,7 +404,7 @@ typedef struct SequenceChannel { /* 0x01 */ u8 asByte; } changes; /* 0x02 */ u8 noteAllocPolicy; - /* 0x03 */ u8 muteBehavior; + /* 0x03 */ u8 muteFlags; /* 0x04 */ u8 reverb; // or dry/wet mix /* 0x05 */ u8 notePriority; // 0-3 /* 0x06 */ u8 someOtherPriority; @@ -406,12 +413,12 @@ typedef struct SequenceChannel { /* 0x09 */ u8 bookOffset; /* 0x0A */ u8 newPan; /* 0x0B */ u8 panChannelWeight; // proportion of pan that comes from the channel (0..128) - /* 0x0C */ u8 unk_0C; + /* 0x0C */ u8 gain; // Increases volume by a multiplicative scaling factor. Represented as a UQ4.4 number /* 0x0D */ u8 velocityRandomVariance; /* 0x0E */ u8 gateTimeRandomVariance; /* 0x0F */ u8 unk_0F; - /* 0x10 */ u8 unk_10; // New to MM - /* 0x11 */ u8 unk_11; // New to MM + /* 0x10 */ u8 unk_10; + /* 0x11 */ u8 unk_11; /* 0x12 */ VibratoSubStruct vibrato; /* 0x20 */ u16 delay; /* 0x22 */ u16 unk_20; @@ -434,11 +441,11 @@ typedef struct SequenceChannel { /* 0x80 */ AdsrSettings adsr; /* 0x88 */ NotePool notePool; /* 0xC8 */ s8 soundScriptIO[8]; // bridge between sound script and audio lib, "io ports" - /* 0xD0 */ u8* unk_D0; // New to MM + /* 0xD0 */ u8* sfxState; /* 0xD4 */ s16* filter; /* 0xD8 */ Stereo stereo; - /* 0xDC */ s32 unk_DC; // New to MM - /* 0xE0 */ s32 unk_E0; // New to MM + /* 0xDC */ s32 unk_DC; + /* 0xE0 */ s32 unk_E0; } SequenceChannel; // size = 0xE4 // Might also be known as a Track, according to sm64 debug strings (?). @@ -531,7 +538,7 @@ typedef struct { /* 0x04 */ u8 reverbVol; /* 0x05 */ u8 numParts; /* 0x06 */ u16 samplePosFrac; - /* 0x08 */ u16 unk_08; // New to MM + /* 0x08 */ u16 unk_08; /* 0x0C */ s32 samplePosInt; /* 0x10 */ NoteSynthesisBuffers* synthesisBuffers; /* 0x14 */ s16 curVolLeft; @@ -596,7 +603,7 @@ typedef struct { /* 0x01 */ u8 hasTwoParts : 1; /* 0x01 */ u8 usesHeadsetPanEffects2 : 1; } bitField1; - /* 0x02 */ u8 unk_2; + /* 0x02 */ u8 gain; // Increases volume by a multiplicative scaling factor. Represented as a UQ4.4 number /* 0x03 */ u8 headsetPanRight; /* 0x04 */ u8 headsetPanLeft; /* 0x05 */ u8 reverbVol; @@ -611,8 +618,8 @@ typedef struct { /* 0x10 */ s16* samples; // used for synthetic waves } sound; /* 0x14 */ s16* filter; - /* 0x18 */ u8 unk_18; // New to MM - /* 0x19 */ u8 unk_19; // New to MM + /* 0x18 */ u8 unk_18; + /* 0x19 */ u8 unk_19; /* 0x1A */ UNK_TYPE1 pad_1A[0x6]; } NoteSubEu; // size = 0x20 @@ -965,7 +972,7 @@ typedef struct { /* 0x4448 */ volatile u8 resetStatus; /* 0x4449 */ u8 audioResetSpecIdToLoad; /* 0x444C */ s32 audioResetFadeOutFramesLeft; - /* 0x4450 */ f32* unk_3520; // fadeOutVelocities for ADSR + /* 0x4450 */ f32* adsrDecayTable; // A table on the audio heap that stores decay rates used for ADSR /* 0x4454 */ u8* audioHeap; /* 0x4458 */ size_t audioHeapSize; /* 0x445C */ Note* notes; @@ -994,7 +1001,7 @@ typedef struct { typedef struct { /* 0x00 */ u8 reverbVol; - /* 0x01 */ u8 unk_1; + /* 0x01 */ u8 gain; // Increases volume by a multiplicative scaling factor. Represented as a UQ4.4 number /* 0x02 */ u8 pan; /* 0x03 */ u8 unk_3; /* 0x04 */ Stereo stereo; @@ -1050,7 +1057,7 @@ typedef struct { /* 0x218 */ u8 unk_4C; /* 0x219 */ u8 unk_4D; /* 0x21A */ u8 unk_4E; - /* 0x21B */ u8 unk_21B; // New to MM + /* 0x21B */ u8 unk_21B; } unk_D_8016E750; // size = 0x21C typedef struct { diff --git a/spec b/spec index a4769effcd..209727c3d7 100644 --- a/spec +++ b/spec @@ -620,7 +620,6 @@ beginseg include "build/src/code/audio/audio_playback.o" include "build/src/code/audio/audio_effects.o" include "build/src/code/audio/audio_seqplayer.o" - include "build/data/code/audio_seqplayer.data.o" include "build/data/code/audio_dramStack.data.o" include "build/asm/code/code_8019AE40.text.o" // handwritten pad_text diff --git a/src/code/audio/audio_data.c b/src/code/audio/audio_data.c index c430189223..7238a4bfa6 100644 --- a/src/code/audio/audio_data.c +++ b/src/code/audio/audio_data.c @@ -850,11 +850,11 @@ u8 gDefaultShortNoteGateTimeTable[] = { 229, 203, 177, 151, 139, 126, 113, 100, 87, 74, 61, 48, 36, 23, 10, 0, }; -AdsrEnvelope gDefaultEnvelope[] = { +EnvelopePoint gDefaultEnvelope[] = { { 1, 32000 }, { 1000, 32000 }, - { -1, 0 }, - { 0, 0 }, + { ADSR_HANG, 0 }, + { ADSR_DISABLE, 0 }, }; NoteSubEu gZeroNoteSub = { 0 }; diff --git a/src/code/audio/audio_effects.c b/src/code/audio/audio_effects.c index 2dcef2237a..ab9228bbf6 100644 --- a/src/code/audio/audio_effects.c +++ b/src/code/audio/audio_effects.c @@ -7,7 +7,7 @@ void AudioEffects_SequenceChannelProcessSound(SequenceChannel* channel, s32 reca if (channel->changes.s.volume || recalculateVolume) { channelVolume = channel->volume * channel->volumeScale * channel->seqPlayer->appliedFadeVolume; - if (channel->seqPlayer->muted && (channel->muteBehavior & 0x20)) { + if (channel->seqPlayer->muted && (channel->muteFlags & MUTE_FLAGS_SOFTEN)) { channelVolume = channel->seqPlayer->muteVolumeScale * channelVolume; } channel->appliedVolume = channelVolume * channelVolume; @@ -218,7 +218,7 @@ void AudioEffects_NotePortamentoInit(Note* note) { note->playbackState.portamento = note->playbackState.parentLayer->portamento; } -void AudioEffects_AdsrInit(AdsrState* adsr, AdsrEnvelope* envelope, s16* volOut) { +void AudioEffects_AdsrInit(AdsrState* adsr, EnvelopePoint* envelope, s16* volOut) { adsr->action.asByte = 0; adsr->delay = 0; adsr->envelope = envelope; diff --git a/src/code/audio/audio_heap.c b/src/code/audio/audio_heap.c index b06f6a5776..7d3ea8ba66 100644 --- a/src/code/audio/audio_heap.c +++ b/src/code/audio/audio_heap.c @@ -21,45 +21,45 @@ f32 func_8018B0F0(f32 arg0) { void func_8018B10C(void) { s32 i; - gAudioContext.unk_3520[255] = func_8018B0F0(0.25f); - gAudioContext.unk_3520[254] = func_8018B0F0(0.33f); - gAudioContext.unk_3520[253] = func_8018B0F0(0.5f); - gAudioContext.unk_3520[252] = func_8018B0F0(0.66f); - gAudioContext.unk_3520[251] = func_8018B0F0(0.75f); + gAudioContext.adsrDecayTable[255] = func_8018B0F0(0.25f); + gAudioContext.adsrDecayTable[254] = func_8018B0F0(0.33f); + gAudioContext.adsrDecayTable[253] = func_8018B0F0(0.5f); + gAudioContext.adsrDecayTable[252] = func_8018B0F0(0.66f); + gAudioContext.adsrDecayTable[251] = func_8018B0F0(0.75f); for (i = 128; i < 251; i++) { - gAudioContext.unk_3520[i] = func_8018B0F0(251 - i); + gAudioContext.adsrDecayTable[i] = func_8018B0F0(251 - i); } for (i = 16; i < 128; i++) { - gAudioContext.unk_3520[i] = func_8018B0F0(4 * (143 - i)); + gAudioContext.adsrDecayTable[i] = func_8018B0F0(4 * (143 - i)); } for (i = 1; i < 16; i++) { - gAudioContext.unk_3520[i] = func_8018B0F0(60 * (23 - i)); + gAudioContext.adsrDecayTable[i] = func_8018B0F0(60 * (23 - i)); } - gAudioContext.unk_3520[0] = 0.0f; + gAudioContext.adsrDecayTable[0] = 0.0f; } void AudioHeap_ResetLoadStatus(void) { s32 i; for (i = 0; i < ARRAY_COUNT(gAudioContext.fontLoadStatus); i++) { - if (gAudioContext.fontLoadStatus[i] != LOAD_STATUS_5) { - gAudioContext.fontLoadStatus[i] = LOAD_STATUS_0; + if (gAudioContext.fontLoadStatus[i] != LOAD_STATUS_PERMANENT) { + gAudioContext.fontLoadStatus[i] = LOAD_STATUS_NOT_LOADED; } } for (i = 0; i < ARRAY_COUNT(gAudioContext.sampleFontLoadStatus); i++) { - if (gAudioContext.sampleFontLoadStatus[i] != LOAD_STATUS_5) { - gAudioContext.sampleFontLoadStatus[i] = LOAD_STATUS_0; + if (gAudioContext.sampleFontLoadStatus[i] != LOAD_STATUS_PERMANENT) { + gAudioContext.sampleFontLoadStatus[i] = LOAD_STATUS_NOT_LOADED; } } for (i = 0; i < ARRAY_COUNT(gAudioContext.seqLoadStatus); i++) { - if (gAudioContext.seqLoadStatus[i] != LOAD_STATUS_5) { - gAudioContext.seqLoadStatus[i] = LOAD_STATUS_0; + if (gAudioContext.seqLoadStatus[i] != LOAD_STATUS_PERMANENT) { + gAudioContext.seqLoadStatus[i] = LOAD_STATUS_NOT_LOADED; } } } @@ -302,7 +302,7 @@ void AudioHeap_PopCache(s32 tableType) { AudioHeap_DiscardFont(persistent->entries[persistent->numEntries - 1].id); } - loadStatus[persistent->entries[persistent->numEntries - 1].id] = LOAD_STATUS_0; + loadStatus[persistent->entries[persistent->numEntries - 1].id] = LOAD_STATUS_NOT_LOADED; persistent->numEntries--; } @@ -409,12 +409,12 @@ void* AudioHeap_AllocCached(s32 tableType, size_t size, s32 cache, s32 id) { } loadStatusEntry0 = - (temporaryCache->entries[0].id == -1) ? LOAD_STATUS_0 : loadStatus[temporaryCache->entries[0].id]; + (temporaryCache->entries[0].id == -1) ? LOAD_STATUS_NOT_LOADED : loadStatus[temporaryCache->entries[0].id]; loadStatusEntry1 = - (temporaryCache->entries[1].id == -1) ? LOAD_STATUS_0 : loadStatus[temporaryCache->entries[1].id]; + (temporaryCache->entries[1].id == -1) ? LOAD_STATUS_NOT_LOADED : loadStatus[temporaryCache->entries[1].id]; if (tableType == FONT_TABLE) { - if (loadStatusEntry0 == LOAD_STATUS_4) { + 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) { @@ -423,12 +423,12 @@ void* AudioHeap_AllocCached(s32 tableType, size_t size, s32 cache, s32 id) { } if (i == gAudioContext.numNotes) { - AudioLoad_SetFontLoadStatus(temporaryCache->entries[0].id, LOAD_STATUS_3); - loadStatusEntry0 = LOAD_STATUS_3; + AudioLoad_SetFontLoadStatus(temporaryCache->entries[0].id, LOAD_STATUS_DISCARDABLE); + loadStatusEntry0 = LOAD_STATUS_DISCARDABLE; } } - if (loadStatusEntry1 == LOAD_STATUS_4) { + 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) { @@ -437,26 +437,26 @@ void* AudioHeap_AllocCached(s32 tableType, size_t size, s32 cache, s32 id) { } if (i == gAudioContext.numNotes) { - AudioLoad_SetFontLoadStatus(temporaryCache->entries[1].id, LOAD_STATUS_3); - loadStatusEntry1 = LOAD_STATUS_3; + AudioLoad_SetFontLoadStatus(temporaryCache->entries[1].id, LOAD_STATUS_DISCARDABLE); + loadStatusEntry1 = LOAD_STATUS_DISCARDABLE; } } } - if (loadStatusEntry0 == LOAD_STATUS_0) { + if (loadStatusEntry0 == LOAD_STATUS_NOT_LOADED) { temporaryCache->nextSide = 0; - } else if (loadStatusEntry1 == LOAD_STATUS_0) { + } else if (loadStatusEntry1 == LOAD_STATUS_NOT_LOADED) { temporaryCache->nextSide = 1; - } else if ((loadStatusEntry0 == LOAD_STATUS_3) && (loadStatusEntry1 == LOAD_STATUS_3)) { + } else if ((loadStatusEntry0 == LOAD_STATUS_DISCARDABLE) && (loadStatusEntry1 == LOAD_STATUS_DISCARDABLE)) { // Use the opposite side from last time. - } else if (loadStatusEntry0 == LOAD_STATUS_3) { + } else if (loadStatusEntry0 == LOAD_STATUS_DISCARDABLE) { temporaryCache->nextSide = 0; - } else if (loadStatusEntry1 == LOAD_STATUS_3) { + } else if (loadStatusEntry1 == LOAD_STATUS_DISCARDABLE) { temporaryCache->nextSide = 1; } else { // Check if there is a side which isn't in active use, if so, evict that one. if (tableType == SEQUENCE_TABLE) { - if (loadStatusEntry0 == LOAD_STATUS_2) { + if (loadStatusEntry0 == LOAD_STATUS_COMPLETE) { for (i = 0; i < gAudioContext.audioBufferParameters.numSequencePlayers; i++) { if (gAudioContext.seqPlayers[i].enabled && gAudioContext.seqPlayers[i].seqId == temporaryCache->entries[0].id) { @@ -470,7 +470,7 @@ void* AudioHeap_AllocCached(s32 tableType, size_t size, s32 cache, s32 id) { } } - if (loadStatusEntry1 == LOAD_STATUS_2) { + if (loadStatusEntry1 == LOAD_STATUS_COMPLETE) { for (i = 0; i < gAudioContext.audioBufferParameters.numSequencePlayers; i++) { if (gAudioContext.seqPlayers[i].enabled && gAudioContext.seqPlayers[i].seqId == temporaryCache->entries[1].id) { @@ -484,7 +484,7 @@ void* AudioHeap_AllocCached(s32 tableType, size_t size, s32 cache, s32 id) { } } } else if (tableType == FONT_TABLE) { - if (loadStatusEntry0 == LOAD_STATUS_2) { + 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) { @@ -497,7 +497,7 @@ void* AudioHeap_AllocCached(s32 tableType, size_t size, s32 cache, s32 id) { } } - if (loadStatusEntry1 == LOAD_STATUS_2) { + 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) { @@ -514,15 +514,15 @@ void* AudioHeap_AllocCached(s32 tableType, size_t size, s32 cache, s32 id) { // No such luck. Evict the side that wasn't chosen last time, except // if it is being loaded into. if (temporaryCache->nextSide == 0) { - if (loadStatusEntry0 == LOAD_STATUS_1) { - if (loadStatusEntry1 == LOAD_STATUS_1) { + if (loadStatusEntry0 == LOAD_STATUS_IN_PROGRESS) { + if (loadStatusEntry1 == LOAD_STATUS_IN_PROGRESS) { goto fail; } temporaryCache->nextSide = 1; } } else { - if (loadStatusEntry1 == LOAD_STATUS_1) { - if (loadStatusEntry0 == LOAD_STATUS_1) { + if (loadStatusEntry1 == LOAD_STATUS_IN_PROGRESS) { + if (loadStatusEntry0 == LOAD_STATUS_IN_PROGRESS) { goto fail; } temporaryCache->nextSide = 0; @@ -544,7 +544,7 @@ void* AudioHeap_AllocCached(s32 tableType, size_t size, s32 cache, s32 id) { AudioHeap_DiscardSampleBank(temporaryCache->entries[side].id); } - loadStatus[temporaryCache->entries[side].id] = LOAD_STATUS_0; + loadStatus[temporaryCache->entries[side].id] = LOAD_STATUS_NOT_LOADED; if (tableType == FONT_TABLE) { AudioHeap_DiscardFont(temporaryCache->entries[side].id); @@ -564,7 +564,7 @@ void* AudioHeap_AllocCached(s32 tableType, size_t size, s32 cache, s32 id) { AudioHeap_DiscardSampleBank(temporaryCache->entries[1].id); } - loadStatus[temporaryCache->entries[1].id] = LOAD_STATUS_0; + loadStatus[temporaryCache->entries[1].id] = LOAD_STATUS_NOT_LOADED; switch (tableType) { case SEQUENCE_TABLE: @@ -594,7 +594,7 @@ void* AudioHeap_AllocCached(s32 tableType, size_t size, s32 cache, s32 id) { AudioHeap_DiscardSampleBank(temporaryCache->entries[0].id); } - loadStatus[temporaryCache->entries[0].id] = LOAD_STATUS_0; + loadStatus[temporaryCache->entries[0].id] = LOAD_STATUS_NOT_LOADED; switch (tableType) { case SEQUENCE_TABLE: @@ -1042,8 +1042,8 @@ void AudioHeap_Init(void) { AudioHeap_AllocDmaMemoryZeroed(&gAudioContext.miscPool, gAudioContext.maxAudioCmds * sizeof(u64)); } - // Initialize unk_3520 (fadeOutVelocities for ADSR) - gAudioContext.unk_3520 = AudioHeap_Alloc(&gAudioContext.miscPool, 0x100 * sizeof(f32)); + // Initialize adsrDecayTable (fadeOutVelocities for ADSR) + gAudioContext.adsrDecayTable = AudioHeap_Alloc(&gAudioContext.miscPool, 0x100 * sizeof(f32)); func_8018B10C(); // Initialize reverbs diff --git a/src/code/audio/audio_load.c b/src/code/audio/audio_load.c index 8b70eadd71..b4997a94e4 100644 --- a/src/code/audio/audio_load.c +++ b/src/code/audio/audio_load.c @@ -29,7 +29,7 @@ typedef struct { } AudioRelocInfo; // size = 0x18 void AudioLoad_DiscardFont(s32 fontId); -s32 AudioLoad_SyncInitSeqPlayerInternal(s32 playerIdx, s32 seqId, s32 arg2); +s32 AudioLoad_SyncInitSeqPlayerInternal(s32 playerIndex, s32 seqId, s32 arg2); u8* AudioLoad_SyncLoadSeq(s32 seqId); u32 AudioLoad_TrySyncLoadSampleBank(u32 sampleBankId, u32* outMedium, s32 noLoad); SoundFontData* AudioLoad_SyncLoadFont(u32 fontId); @@ -301,9 +301,9 @@ void AudioLoad_InitSampleDmaBuffers(s32 numNotes) { s32 AudioLoad_IsFontLoadComplete(s32 fontId) { if (fontId == 0xFF) { return true; - } else if (gAudioContext.fontLoadStatus[fontId] >= LOAD_STATUS_2) { + } else if (gAudioContext.fontLoadStatus[fontId] >= LOAD_STATUS_COMPLETE) { return true; - } else if (gAudioContext.fontLoadStatus[AudioLoad_GetRealTableIndex(FONT_TABLE, fontId)] >= LOAD_STATUS_2) { + } else if (gAudioContext.fontLoadStatus[AudioLoad_GetRealTableIndex(FONT_TABLE, fontId)] >= LOAD_STATUS_COMPLETE) { return true; } else { return false; @@ -313,9 +313,10 @@ s32 AudioLoad_IsFontLoadComplete(s32 fontId) { s32 AudioLoad_IsSeqLoadComplete(s32 seqId) { if (seqId == 0xFF) { return true; - } else if (gAudioContext.seqLoadStatus[seqId] >= LOAD_STATUS_2) { + } else if (gAudioContext.seqLoadStatus[seqId] >= LOAD_STATUS_COMPLETE) { return true; - } else if (gAudioContext.seqLoadStatus[AudioLoad_GetRealTableIndex(SEQUENCE_TABLE, seqId)] >= LOAD_STATUS_2) { + } else if (gAudioContext.seqLoadStatus[AudioLoad_GetRealTableIndex(SEQUENCE_TABLE, seqId)] >= + LOAD_STATUS_COMPLETE) { return true; } else { return false; @@ -325,10 +326,10 @@ s32 AudioLoad_IsSeqLoadComplete(s32 seqId) { s32 AudioLoad_IsSampleLoadComplete(s32 sampleBankId) { if (sampleBankId == 0xFF) { return true; - } else if (gAudioContext.sampleFontLoadStatus[sampleBankId] >= LOAD_STATUS_2) { + } else if (gAudioContext.sampleFontLoadStatus[sampleBankId] >= LOAD_STATUS_COMPLETE) { return true; } else if (gAudioContext.sampleFontLoadStatus[AudioLoad_GetRealTableIndex(SAMPLE_TABLE, sampleBankId)] >= - LOAD_STATUS_2) { + LOAD_STATUS_COMPLETE) { return true; } else { return false; @@ -336,32 +337,32 @@ s32 AudioLoad_IsSampleLoadComplete(s32 sampleBankId) { } void AudioLoad_SetFontLoadStatus(s32 fontId, s32 loadStatus) { - if ((fontId != 0xFF) && (gAudioContext.fontLoadStatus[fontId] != LOAD_STATUS_5)) { + if ((fontId != 0xFF) && (gAudioContext.fontLoadStatus[fontId] != LOAD_STATUS_PERMANENT)) { gAudioContext.fontLoadStatus[fontId] = loadStatus; } } void AudioLoad_SetSeqLoadStatus(s32 seqId, s32 loadStatus) { - if ((seqId != 0xFF) && (gAudioContext.seqLoadStatus[seqId] != LOAD_STATUS_5)) { + if ((seqId != 0xFF) && (gAudioContext.seqLoadStatus[seqId] != LOAD_STATUS_PERMANENT)) { gAudioContext.seqLoadStatus[seqId] = loadStatus; } } void AudioLoad_SetSampleFontLoadStatusAndApplyCaches(s32 sampleBankId, s32 loadStatus) { if (sampleBankId != 0xFF) { - if (gAudioContext.sampleFontLoadStatus[sampleBankId] != LOAD_STATUS_5) { + if (gAudioContext.sampleFontLoadStatus[sampleBankId] != LOAD_STATUS_PERMANENT) { gAudioContext.sampleFontLoadStatus[sampleBankId] = loadStatus; } - if ((gAudioContext.sampleFontLoadStatus[sampleBankId] == LOAD_STATUS_5) || - (gAudioContext.sampleFontLoadStatus[sampleBankId] == LOAD_STATUS_2)) { + if ((gAudioContext.sampleFontLoadStatus[sampleBankId] == LOAD_STATUS_PERMANENT) || + (gAudioContext.sampleFontLoadStatus[sampleBankId] == LOAD_STATUS_COMPLETE)) { AudioHeap_ApplySampleBankCache(sampleBankId); } } } void AudioLoad_SetSampleFontLoadStatus(s32 sampleBankId, s32 loadStatus) { - if ((sampleBankId != 0xFF) && (gAudioContext.sampleFontLoadStatus[sampleBankId] != LOAD_STATUS_5)) { + if ((sampleBankId != 0xFF) && (gAudioContext.sampleFontLoadStatus[sampleBankId] != LOAD_STATUS_PERMANENT)) { gAudioContext.sampleFontLoadStatus[sampleBankId] = loadStatus; } } @@ -510,7 +511,7 @@ void AudioLoad_DiscardSeqFonts(s32 seqId) { fontId = AudioLoad_GetRealTableIndex(FONT_TABLE, gAudioContext.sequenceFontTable[index++]); if (AudioHeap_SearchPermanentCache(FONT_TABLE, fontId) == NULL) { AudioLoad_DiscardFont(fontId); - AudioLoad_SetFontLoadStatus(fontId, LOAD_STATUS_0); + AudioLoad_SetFontLoadStatus(fontId, LOAD_STATUS_NOT_LOADED); } } } @@ -553,31 +554,31 @@ void func_8018FA60(u32 tableType, u32 id, s32 type, s32 data) { } } -s32 AudioLoad_SyncInitSeqPlayer(s32 playerIdx, s32 seqId, s32 arg2) { +s32 AudioLoad_SyncInitSeqPlayer(s32 playerIndex, s32 seqId, s32 arg2) { if (gAudioContext.resetTimer != 0) { return 0; } - gAudioContext.seqPlayers[playerIdx].skipTicks = 0; - AudioLoad_SyncInitSeqPlayerInternal(playerIdx, seqId, arg2); + gAudioContext.seqPlayers[playerIndex].skipTicks = 0; + AudioLoad_SyncInitSeqPlayerInternal(playerIndex, seqId, arg2); // Intentionally missing return. Returning the result of the above function // call matches but is UB because it too is missing a return, and using the // result of a non-void function that has failed to return a value is UB. // The callers of this function do not use the return value, so it's fine. } -s32 AudioLoad_SyncInitSeqPlayerSkipTicks(s32 playerIdx, s32 seqId, s32 skipTicks) { +s32 AudioLoad_SyncInitSeqPlayerSkipTicks(s32 playerIndex, s32 seqId, s32 skipTicks) { if (gAudioContext.resetTimer != 0) { return 0; } - gAudioContext.seqPlayers[playerIdx].skipTicks = skipTicks; - AudioLoad_SyncInitSeqPlayerInternal(playerIdx, seqId, 0); + gAudioContext.seqPlayers[playerIndex].skipTicks = skipTicks; + AudioLoad_SyncInitSeqPlayerInternal(playerIndex, seqId, 0); // Missing return, see above. } -s32 AudioLoad_SyncInitSeqPlayerInternal(s32 playerIdx, s32 seqId, s32 arg2) { - SequencePlayer* seqPlayer = &gAudioContext.seqPlayers[playerIdx]; +s32 AudioLoad_SyncInitSeqPlayerInternal(s32 playerIndex, s32 seqId, s32 arg2) { + SequencePlayer* seqPlayer = &gAudioContext.seqPlayers[playerIndex]; u8* seqData; s32 index; s32 numFonts; @@ -620,7 +621,7 @@ s32 AudioLoad_SyncInitSeqPlayerInternal(s32 playerIdx, s32 seqId, s32 arg2) { seqPlayer->scriptState.depth = 0; seqPlayer->delay = 0; seqPlayer->finished = false; - seqPlayer->playerIdx = playerIdx; + seqPlayer->playerIndex = playerIndex; //! @bug missing return (but the return value is not used so it's not UB) } @@ -628,7 +629,7 @@ u8* AudioLoad_SyncLoadSeq(s32 seqId) { s32 pad; s32 didAllocate; - if (gAudioContext.seqLoadStatus[AudioLoad_GetRealTableIndex(SEQUENCE_TABLE, seqId)] == LOAD_STATUS_1) { + if (gAudioContext.seqLoadStatus[AudioLoad_GetRealTableIndex(SEQUENCE_TABLE, seqId)] == LOAD_STATUS_IN_PROGRESS) { return NULL; } @@ -649,8 +650,8 @@ u32 AudioLoad_TrySyncLoadSampleBank(u32 sampleBankId, u32* outMedium, s32 noLoad addr = AudioLoad_SearchCaches(SAMPLE_TABLE, realTableId); if (addr != NULL) { - if (gAudioContext.sampleFontLoadStatus[realTableId] != LOAD_STATUS_1) { - AudioLoad_SetSampleFontLoadStatus(realTableId, LOAD_STATUS_2); + if (gAudioContext.sampleFontLoadStatus[realTableId] != LOAD_STATUS_IN_PROGRESS) { + AudioLoad_SetSampleFontLoadStatus(realTableId, LOAD_STATUS_COMPLETE); } *outMedium = MEDIUM_RAM; @@ -682,7 +683,7 @@ SoundFontData* AudioLoad_SyncLoadFont(u32 fontId) { AudioRelocInfo relocInfo; s32 realFontId = AudioLoad_GetRealTableIndex(FONT_TABLE, fontId); - if (gAudioContext.fontLoadStatus[realFontId] == LOAD_STATUS_1) { + if (gAudioContext.fontLoadStatus[realFontId] == LOAD_STATUS_IN_PROGRESS) { return NULL; } @@ -730,7 +731,7 @@ void* AudioLoad_SyncLoad(s32 tableType, u32 id, s32* didAllocate) { ramAddr = AudioLoad_SearchCaches(tableType, realId); if (ramAddr != NULL) { *didAllocate = false; - loadStatus = LOAD_STATUS_2; + loadStatus = LOAD_STATUS_COMPLETE; } else { table = AudioLoad_GetLoadTable(tableType); size = table->entries[realId].size; @@ -793,7 +794,7 @@ void* AudioLoad_SyncLoad(s32 tableType, u32 id, s32* didAllocate) { AudioLoad_SyncDma(romAddr, ramAddr, size, medium); } - loadStatus = (cachePolicy == CACHE_LOAD_PERMANENT) ? LOAD_STATUS_5 : LOAD_STATUS_2; + loadStatus = (cachePolicy == CACHE_LOAD_PERMANENT) ? LOAD_STATUS_PERMANENT : LOAD_STATUS_COMPLETE; } switch (tableType) { @@ -1032,19 +1033,19 @@ void* AudioLoad_AsyncLoadInner(s32 tableType, s32 id, s32 nChunks, s32 retData, switch (tableType) { case SEQUENCE_TABLE: - if (gAudioContext.seqLoadStatus[realId] == LOAD_STATUS_1) { + if (gAudioContext.seqLoadStatus[realId] == LOAD_STATUS_IN_PROGRESS) { return NULL; } break; case FONT_TABLE: - if (gAudioContext.fontLoadStatus[realId] == LOAD_STATUS_1) { + if (gAudioContext.fontLoadStatus[realId] == LOAD_STATUS_IN_PROGRESS) { return NULL; } break; case SAMPLE_TABLE: - if (gAudioContext.sampleFontLoadStatus[realId] == LOAD_STATUS_1) { + if (gAudioContext.sampleFontLoadStatus[realId] == LOAD_STATUS_IN_PROGRESS) { return NULL; } break; @@ -1052,8 +1053,8 @@ void* AudioLoad_AsyncLoadInner(s32 tableType, s32 id, s32 nChunks, s32 retData, ramAddr = AudioLoad_SearchCaches(tableType, realId); if (ramAddr != NULL) { - loadStatus = LOAD_STATUS_2; - osSendMesg(retQueue, MK_ASYNC_MSG(retData, 0, 0, LOAD_STATUS_0), OS_MESG_NOBLOCK); + loadStatus = LOAD_STATUS_COMPLETE; + osSendMesg(retQueue, MK_ASYNC_MSG(retData, 0, 0, LOAD_STATUS_NOT_LOADED), OS_MESG_NOBLOCK); } else { table = AudioLoad_GetLoadTable(tableType); size = table->entries[realId].size; @@ -1061,7 +1062,7 @@ void* AudioLoad_AsyncLoadInner(s32 tableType, s32 id, s32 nChunks, s32 retData, medium = table->entries[id].medium; cachePolicy = table->entries[id].cachePolicy; romAddr = table->entries[realId].romAddr; - loadStatus = LOAD_STATUS_2; + loadStatus = LOAD_STATUS_COMPLETE; switch (cachePolicy) { case CACHE_LOAD_PERMANENT: @@ -1069,7 +1070,7 @@ void* AudioLoad_AsyncLoadInner(s32 tableType, s32 id, s32 nChunks, s32 retData, if (ramAddr == NULL) { return ramAddr; } - loadStatus = LOAD_STATUS_5; + loadStatus = LOAD_STATUS_PERMANENT; break; case CACHE_LOAD_PERSISTENT: @@ -1119,7 +1120,7 @@ void* AudioLoad_AsyncLoadInner(s32 tableType, s32 id, s32 nChunks, s32 retData, MK_ASYNC_MSG(retData, tableType, realId, loadStatus)); } - loadStatus = LOAD_STATUS_1; + loadStatus = LOAD_STATUS_IN_PROGRESS; } switch (tableType) { diff --git a/src/code/audio/audio_playback.c b/src/code/audio/audio_playback.c index 6ae5696f10..c7789bd367 100644 --- a/src/code/audio/audio_playback.c +++ b/src/code/audio/audio_playback.c @@ -98,7 +98,7 @@ void AudioPlayback_InitNoteSub(Note* note, NoteSubEu* sub, NoteSubAttributes* at sub->targetVolLeft = (s32)((vel * volLeft) * (0x1000 - 0.001f)); sub->targetVolRight = (s32)((vel * volRight) * (0x1000 - 0.001f)); - sub->unk_2 = attrs->unk_1; + sub->gain = attrs->gain; sub->filter = attrs->filter; sub->unk_07 = attrs->unk_14; sub->unk_0E = attrs->unk_16; @@ -125,7 +125,7 @@ void AudioPlayback_NoteSetResamplingRate(NoteSubEu* noteSubEu, f32 resamplingRat } void AudioPlayback_NoteInit(Note* note) { - if (note->playbackState.parentLayer->adsr.releaseRate == 0) { + if (note->playbackState.parentLayer->adsr.decayIndex == 0) { AudioEffects_AdsrInit(¬e->playbackState.adsr, note->playbackState.parentLayer->channel->adsr.envelope, ¬e->playbackState.adsrVolScaleUnused); } else { @@ -189,7 +189,7 @@ void AudioPlayback_ProcessNotes(void) { playbackState->unk_04 = 1; continue; } else if (playbackState->parentLayer->channel->seqPlayer->muted && - (playbackState->parentLayer->channel->muteBehavior & 0x40)) { + (playbackState->parentLayer->channel->muteFlags & MUTE_FLAGS_STOP_NOTES)) { // do nothing } else { goto out; @@ -257,7 +257,7 @@ void AudioPlayback_ProcessNotes(void) { subAttrs.pan = attrs->pan; subAttrs.reverbVol = attrs->reverb; subAttrs.stereo = attrs->stereo; - subAttrs.unk_1 = attrs->unk_1; + subAttrs.gain = attrs->gain; subAttrs.filter = attrs->filter; subAttrs.unk_14 = attrs->unk_4; subAttrs.unk_16 = attrs->unk_6; @@ -290,9 +290,9 @@ void AudioPlayback_ProcessNotes(void) { } if (layer->unk_0A.s.bit_9 == 1) { - subAttrs.unk_1 = channel->unk_0C; + subAttrs.gain = channel->gain; } else { - subAttrs.unk_1 = 0; + subAttrs.gain = 0; if (1) {} } @@ -301,7 +301,7 @@ void AudioPlayback_ProcessNotes(void) { subAttrs.unk_16 = channel->unk_20; bookOffset = channel->bookOffset & 0x7; - if (channel->seqPlayer->muted && (channel->muteBehavior & 8)) { + if (channel->seqPlayer->muted && (channel->muteFlags & MUTE_FLAGS_3)) { subAttrs.frequency = 0.0f; subAttrs.velocity = 0.0f; } @@ -506,9 +506,9 @@ void AudioPlayback_SeqLayerDecayRelease(SequenceLayer* layer, s32 target) { } if (layer->unk_0A.s.bit_9 == 1) { - attrs->unk_1 = chan->unk_0C; + attrs->gain = chan->gain; } else { - attrs->unk_1 = 0; + attrs->gain = 0; } attrs->filter = chan->filter; @@ -522,7 +522,7 @@ void AudioPlayback_SeqLayerDecayRelease(SequenceLayer* layer, s32 target) { attrs->unk_6 = chan->unk_20; attrs->unk_4 = chan->unk_0F; - if (chan->seqPlayer->muted && (chan->muteBehavior & 8)) { + if (chan->seqPlayer->muted && (chan->muteFlags & MUTE_FLAGS_3)) { note->noteSubEu.bitField0.finished = true; } @@ -546,10 +546,10 @@ void AudioPlayback_SeqLayerDecayRelease(SequenceLayer* layer, s32 target) { } else { note->playbackState.unk_04 = 1; note->playbackState.adsr.action.s.decay = true; - if (layer->adsr.releaseRate == 0) { - note->playbackState.adsr.fadeOutVel = gAudioContext.unk_3520[layer->channel->adsr.releaseRate]; + if (layer->adsr.decayIndex == 0) { + note->playbackState.adsr.fadeOutVel = gAudioContext.adsrDecayTable[layer->channel->adsr.decayIndex]; } else { - note->playbackState.adsr.fadeOutVel = gAudioContext.unk_3520[layer->adsr.releaseRate]; + note->playbackState.adsr.fadeOutVel = gAudioContext.adsrDecayTable[layer->adsr.decayIndex]; } note->playbackState.adsr.sustain = ((f32)(s32)(layer->channel->adsr.sustain) * note->playbackState.adsr.current) / 256.0f; diff --git a/src/code/audio/audio_seqplayer.c b/src/code/audio/audio_seqplayer.c index e57ad19b5a..d504f9f3a9 100644 --- a/src/code/audio/audio_seqplayer.c +++ b/src/code/audio/audio_seqplayer.c @@ -1,73 +1,2312 @@ +/** + * @file audio_seqplayer.c + * + * Manages audio sequence players, interprets and executes sequence instructions used to write .seq files + * + * Sequence Instructions: + * - A customized assembly language based on MIDI + * - All sequences are written using these instructions + * - There are 3 different sets of instructions + * 1) Sequence Instructions + * 2) Channel Instructions + * 3) Layer Instruction + * - All three sets share a common pool of control flow instructions (>= 0xF2). + * Otherwise, each set of instructions has its own command interpreter + */ #include "global.h" -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_seqplayer/func_801974D0.s") +#define PORTAMENTO_IS_SPECIAL(x) ((x).mode & 0x80) +#define PORTAMENTO_MODE(x) ((x).mode & ~0x80) -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_seqplayer/func_80197538.s") +#define PROCESS_SCRIPT_END -1 -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_seqplayer/func_80197714.s") +typedef enum { + /* 0 */ PORTAMENTO_MODE_OFF, + /* 1 */ PORTAMENTO_MODE_1, + /* 2 */ PORTAMENTO_MODE_2, + /* 3 */ PORTAMENTO_MODE_3, + /* 4 */ PORTAMENTO_MODE_4, + /* 5 */ PORTAMENTO_MODE_5 +} PortamentoMode; -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_seqplayer/func_80197880.s") +u8 AudioSeq_ScriptReadU8(SeqScriptState* state); +s16 AudioSeq_ScriptReadS16(SeqScriptState* state); +u16 AudioSeq_ScriptReadCompressedU16(SeqScriptState* state); +void AudioSeq_SeqLayerProcessScriptStep1(SequenceLayer* layer); +s32 AudioSeq_SeqLayerProcessScriptStep5(SequenceLayer* layer, s32 sameSound); +s32 AudioSeq_SeqLayerProcessScriptStep2(SequenceLayer* layer); +s32 AudioSeq_SeqLayerProcessScriptStep4(SequenceLayer* layer, s32 cmd); +s32 AudioSeq_SeqLayerProcessScriptStep3(SequenceLayer* layer, s32 cmd); +u8 AudioSeq_GetInstrument(SequenceChannel* channel, u8 instId, Instrument** instOut, AdsrSettings* adsr); -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_seqplayer/func_801979D8.s") +/** + * sSeqInstructionArgsTable is a table for each sequence instruction + * that contains both how many arguments an instruction takes, as well + * as the type of each argument + * + * sSeqInstructionArgsTable is bitpacked as follows: + * abcUUUnn + * + * n - number of arguments that the sequence instruction takes + * + * a - bitFlag for the type of arg0 if it exists + * b - bitFlag for the type of arg1 if it exists + * c - bitFlag for the type of arg2 if it exists + * + * bitFlag on - argument is s16 + * bitFlag off - argument is u8 + * + * U - Unused + */ -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_seqplayer/func_80197A54.s") +// CMD_ARGS_(NUMBER_OF_ARGS) +#define CMD_ARGS_0() 0 +#define CMD_ARGS_1(arg0Type) (((sizeof(arg0Type) - 1) << 7) | 1) +#define CMD_ARGS_2(arg0Type, arg1Type) (((sizeof(arg0Type) - 1) << 7) | ((sizeof(arg1Type) - 1) << 6) | 2) +#define CMD_ARGS_3(arg0Type, arg1Type, arg2Type) \ + (((sizeof(arg0Type) - 1) << 7) | ((sizeof(arg1Type) - 1) << 6) | ((sizeof(arg2Type) - 1) << 5) | 3) -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_seqplayer/AudioSeq_SequenceChannelDisable.s") +u8 sSeqInstructionArgsTable[] = { + CMD_ARGS_1(s16), // 0xA0 (channel:) + CMD_ARGS_0(), // 0xA1 (channel:) + CMD_ARGS_1(s16), // 0xA2 (channel:) + CMD_ARGS_0(), // 0xA3 (channel:) + CMD_ARGS_1(u8), // 0xA4 (channel:) + CMD_ARGS_0(), // 0xA5 (channel:) + CMD_ARGS_2(u8, s16), // 0xA6 (channel:) + CMD_ARGS_1(u8), // 0xA7 (channel:) + CMD_ARGS_2(s16, s16), // 0xA8 (channel: random range large) + CMD_ARGS_0(), // 0xA9 () + CMD_ARGS_0(), // 0xAA () + CMD_ARGS_0(), // 0xAB () + CMD_ARGS_0(), // 0xAC () + CMD_ARGS_0(), // 0xAD () + CMD_ARGS_0(), // 0xAE () + CMD_ARGS_0(), // 0xAF () + CMD_ARGS_1(s16), // 0xB0 (channel: set filter) + CMD_ARGS_0(), // 0xB1 (channel: clear filter) + CMD_ARGS_1(s16), // 0xB2 (channel: dynread sequence large) + CMD_ARGS_1(u8), // 0xB3 (channel: load filter) + CMD_ARGS_0(), // 0xB4 (channel: set dyntable large) + CMD_ARGS_0(), // 0xB5 (channel: read dyntable large) + CMD_ARGS_0(), // 0xB6 (channel: read dyntable) + CMD_ARGS_1(s16), // 0xB7 (channel: random large) + CMD_ARGS_1(u8), // 0xB8 (channel: random) + CMD_ARGS_1(u8), // 0xB9 (channel: set velocity random variance) + CMD_ARGS_1(u8), // 0xBA (channel: set gatetime random variance) + CMD_ARGS_2(u8, s16), // 0xBB (channel:) + CMD_ARGS_1(s16), // 0xBC (channel: add large) + CMD_ARGS_1(s16), // 0xBD (channel:) + CMD_ARGS_1(u8), // 0xBE (channel:) + CMD_ARGS_0(), // 0xBF () + CMD_ARGS_0(), // 0xC0 () + CMD_ARGS_1(u8), // 0xC1 (channel: set instrument) + CMD_ARGS_1(s16), // 0xC2 (channel: set dyntable) + CMD_ARGS_0(), // 0xC3 (channel: large notes off) + CMD_ARGS_0(), // 0xC4 (channel: large notes on) + CMD_ARGS_0(), // 0xC5 (channel: dyn set dyntable) + CMD_ARGS_1(u8), // 0xC6 (channel: set soundFont) + CMD_ARGS_2(u8, s16), // 0xC7 (channel: write into sequence script) + CMD_ARGS_1(u8), // 0xC8 (channel: subtract -> set value) + CMD_ARGS_1(u8), // 0xC9 (channel: `bit and` -> set value) + CMD_ARGS_1(u8), // 0xCA (channel: set mute behavior) + CMD_ARGS_1(s16), // 0xCB (channel: read sequence -> set value) + CMD_ARGS_1(u8), // 0xCC (channel: set value) + CMD_ARGS_1(u8), // 0xCD (channel: disable channel) + CMD_ARGS_1(s16), // 0xCE (channel:) + CMD_ARGS_1(s16), // 0xCF (channel: write large into sequence script) + CMD_ARGS_1(u8), // 0xD0 (channel: stereo headset effects) + CMD_ARGS_1(u8), // 0xD1 (channel: set note allocation policy) + CMD_ARGS_1(u8), // 0xD2 (channel: set sustain) + CMD_ARGS_1(u8), // 0xD3 (channel: large bend pitch) + CMD_ARGS_1(u8), // 0xD4 (channel: set reverb) + CMD_ARGS_1(u8), // 0xD5 () + CMD_ARGS_1(u8), // 0xD6 () + CMD_ARGS_1(u8), // 0xD7 (channel: set vibrato rate) + CMD_ARGS_1(u8), // 0xD8 (channel: set vibrato extent) + CMD_ARGS_1(u8), // 0xD9 (channel: set decay index) + CMD_ARGS_1(s16), // 0xDA (channel: set envelope) + CMD_ARGS_1(u8), // 0xDB (channel: transpose) + CMD_ARGS_1(u8), // 0xDC (channel: set pan mix) + CMD_ARGS_1(u8), // 0xDD (channel: set pan) + CMD_ARGS_1(s16), // 0xDE (channel: set freqscale) + CMD_ARGS_1(u8), // 0xDF (channel: set volume) + CMD_ARGS_1(u8), // 0xE0 (channel: set volume scale) + CMD_ARGS_3(u8, u8, u8), // 0xE1 (channel: set vibratorate linear) + CMD_ARGS_3(u8, u8, u8), // 0xE2 (channel: set vibrato extent linear) + CMD_ARGS_1(u8), // 0xE3 (channel: set vibrato delay) + CMD_ARGS_0(), // 0xE4 (channel: dyncall) + CMD_ARGS_1(u8), // 0xE5 (channel: set reverb index) + CMD_ARGS_1(u8), // 0xE6 (channel: set book offset) + CMD_ARGS_1(s16), // 0xE7 (channel:) + CMD_ARGS_3(u8, u8, u8), // 0xE8 (channel:) + CMD_ARGS_1(u8), // 0xE9 (channel: set note priority) + CMD_ARGS_0(), // 0xEA (channel: stop script) + CMD_ARGS_2(u8, u8), // 0xEB (channel: set soundFont and instrument) + CMD_ARGS_0(), // 0xEC (channel: reset vibrato) + CMD_ARGS_1(u8), // 0xED (channel: set hilo gain) + CMD_ARGS_1(u8), // 0xEE (channel: small bend pitch) + CMD_ARGS_2(s16, u8), // 0xEF () + CMD_ARGS_0(), // 0xF0 (channel: unreserve notes) + CMD_ARGS_1(u8), // 0xF1 (channel: reserve notes) + // Control flow instructions (>= 0xF2) can only have 0 or 1 args + CMD_ARGS_1(u8), // 0xF2 (branch relative if less than zero) + CMD_ARGS_1(u8), // 0xF3 (branch relative if equal to zero) + CMD_ARGS_1(u8), // 0xF4 (jump relative) + CMD_ARGS_1(s16), // 0xF5 (branch if greater than or equal to zero) + CMD_ARGS_0(), // 0xF6 (break) + CMD_ARGS_0(), // 0xF7 (loop end) + CMD_ARGS_1(u8), // 0xF8 (loop) + CMD_ARGS_1(s16), // 0xF9 (branch if less than zero) + CMD_ARGS_1(s16), // 0xFA (branch if equal to zero) + CMD_ARGS_1(s16), // 0xFB (jump) + CMD_ARGS_1(s16), // 0xFC (call and jump to a function) + CMD_ARGS_0(), // 0xFD (delay n frames) + CMD_ARGS_0(), // 0xFE (delay 1 frame) + CMD_ARGS_0(), // 0xFF (end script) +}; -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_seqplayer/func_80197B14.s") +/** + * Read and return the argument from the sequence script for a control flow instruction. + * Control flow instructions (>= 0xF2) can only have 0 or 1 args. + * + * @return the argument value for a control flow instruction, or 0 if there is no argument + */ +u16 AudioSeq_GetScriptControlFlowArgument(SeqScriptState* state, u8 cmd) { + u8 highBits = sSeqInstructionArgsTable[cmd - 0xA0]; + u8 lowBits = highBits & 3; + u16 cmdArg = 0; -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_seqplayer/func_80197C0C.s") + // only 1 argument + if (lowBits == 1) { + if (!(highBits & 0x80)) { + cmdArg = AudioSeq_ScriptReadU8(state); + } else { + cmdArg = AudioSeq_ScriptReadS16(state); + } + } -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_seqplayer/func_80197C8C.s") + return cmdArg; +} -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_seqplayer/AudioSeq_SequencePlayerDisableAsFinished.s") +/** + * Read and execute the control flow sequence instructions + * + * @return number of frames until next instruction. -1 signals termination + */ +s32 AudioSeq_HandleScriptFlowControl(SequencePlayer* seqPlayer, SeqScriptState* state, s32 cmd, s32 cmdArg) { + u32 depth; -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_seqplayer/AudioSeq_SequencePlayerDisable.s") + switch (cmd) { + case 0xFF: // end script + if (state->depth == 0) { + return PROCESS_SCRIPT_END; + } + state->pc = state->stack[--state->depth]; + break; -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_seqplayer/AudioSeq_AudioListPushBack.s") + case 0xFD: // delay n frames + return AudioSeq_ScriptReadCompressedU16(state); -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_seqplayer/AudioSeq_AudioListPopBack.s") + case 0xFE: // delay 1 frame + return 1; -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_seqplayer/func_80197E88.s") + case 0xFC: // call and jump to a function + state->stack[depth = state->depth++] = state->pc; + state->pc = seqPlayer->seqData + (u16)cmdArg; + break; -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_seqplayer/func_80197F28.s") + case 0xF8: // loop + state->remLoopIters[depth = state->depth] = cmdArg; + state->stack[state->depth++] = state->pc; + break; -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_seqplayer/func_80197F3C.s") + case 0xF7: // loop end + state->remLoopIters[state->depth - 1]--; + if (state->remLoopIters[state->depth - 1] != 0) { + state->pc = state->stack[state->depth - 1]; + } else { + state->depth--; + } + break; -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_seqplayer/func_80197F74.s") + case 0xF6: // break + state->depth--; + break; -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_seqplayer/func_80197FB4.s") + case 0xF5: // branch if greater than or equal to zero + case 0xF9: // branch if less than zero + case 0xFA: // branch if equal to zero + case 0xFB: // jump + if ((cmd == 0xFA) && (state->value != 0)) { + break; + } + if ((cmd == 0xF9) && (state->value >= 0)) { + break; + } + if ((cmd == 0xF5) && (state->value < 0)) { + break; + } + state->pc = seqPlayer->seqData + (u16)cmdArg; + break; -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_seqplayer/func_801980D0.s") + case 0xF2: // branch relative if less than zero + case 0xF3: // branch relative if equal to zero + case 0xF4: // jump relative + if ((cmd == 0xF3) && (state->value != 0)) { + break; + } + if ((cmd == 0xF2) && (state->value >= 0)) { + break; + } + state->pc += (s8)(cmdArg & 0xFF); + break; + } -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_seqplayer/func_8019815C.s") + return 0; +} -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_seqplayer/func_8019825C.s") +void AudioSeq_InitSequenceChannel(SequenceChannel* channel) { + s32 i; -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_seqplayer/func_80198640.s") + if (channel == &gAudioContext.sequenceChannelNone) { + return; + } -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_seqplayer/func_80198CE0.s") + channel->enabled = false; + channel->finished = false; + channel->stopScript = false; + channel->stopSomething2 = false; + channel->hasInstrument = false; + channel->stereoHeadsetEffects = false; + channel->transposition = 0; + channel->largeNotes = false; + channel->bookOffset = 0; + channel->stereo.asByte = 0; + channel->changes.asByte = 0xFF; + channel->scriptState.depth = 0; + channel->newPan = 0x40; + channel->panChannelWeight = 0x80; + channel->unk_10 = 0xFF; + channel->velocityRandomVariance = 0; + channel->gateTimeRandomVariance = 0; + channel->noteUnused = NULL; + channel->reverbIndex = 0; + channel->reverb = 0; + channel->gain = 0; + channel->notePriority = 3; + channel->someOtherPriority = 1; + channel->delay = 0; + channel->adsr.envelope = gDefaultEnvelope; + channel->adsr.decayIndex = 0xF0; + channel->adsr.sustain = 0; + channel->vibrato.vibratoRateTarget = 0x800; + channel->vibrato.vibratoRateStart = 0x800; + channel->vibrato.vibratoExtentTarget = 0; + channel->vibrato.vibratoExtentStart = 0; + channel->vibrato.vibratoRateChangeDelay = 0; + channel->vibrato.vibratoExtentChangeDelay = 0; + channel->vibrato.vibratoDelay = 0; + channel->filter = NULL; + channel->unk_20 = 0; + channel->unk_0F = 0; + channel->volume = 1.0f; + channel->volumeScale = 1.0f; + channel->freqScale = 1.0f; -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_seqplayer/func_801990F4.s") + for (i = 0; i < ARRAY_COUNT(channel->soundScriptIO); i++) { + channel->soundScriptIO[i] = -1; + } -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_seqplayer/func_80199124.s") + channel->unused = false; + AudioPlayback_InitNoteLists(&channel->notePool); + channel->unk_DC = 0; + channel->unk_E0 = 0; + channel->sfxState = NULL; +} -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_seqplayer/func_80199198.s") +s32 AudioSeq_SeqChannelSetLayer(SequenceChannel* channel, s32 layerIndex) { + SequenceLayer* layer; + s32 pad; -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_seqplayer/func_80199244.s") + if (channel->layers[layerIndex] == NULL) { + layer = AudioSeq_AudioListPopBack(&gAudioContext.layerFreeList); + channel->layers[layerIndex] = layer; + if (layer == NULL) { + channel->layers[layerIndex] = NULL; + return -1; + } + } else { + AudioPlayback_SeqLayerNoteDecay(channel->layers[layerIndex]); + } -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_seqplayer/func_80199268.s") + layer = channel->layers[layerIndex]; -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_seqplayer/func_8019A0BC.s") + layer->channel = channel; + layer->adsr = channel->adsr; + layer->adsr.decayIndex = 0; + layer->unk_09 = channel->reverb; + layer->enabled = true; + layer->finished = false; + layer->stopSomething = false; + layer->continuousNotes = false; + layer->bit3 = false; + layer->ignoreDrumPan = false; + layer->bit1 = false; + layer->notePropertiesNeedInit = false; + layer->gateTime = 0x80; + layer->unk_08 = 0x80; + layer->stereo.asByte = 0; + layer->portamento.mode = PORTAMENTO_MODE_OFF; + layer->scriptState.depth = 0; + layer->pan = 0x40; + layer->transposition = 0; + layer->delay = 0; + layer->gateDelay = 0; + layer->delay2 = 0; + layer->note = NULL; + layer->instrument = NULL; + layer->instOrWave = 0xFF; + layer->unk_0A.asByte = 0xFFFF; + layer->vibrato.vibratoRateTarget = 0x800; + layer->vibrato.vibratoRateStart = 0x800; + layer->vibrato.vibratoExtentTarget = 0; + layer->vibrato.vibratoExtentStart = 0; + layer->vibrato.vibratoRateChangeDelay = 0; + layer->vibrato.vibratoExtentChangeDelay = 0; + layer->vibrato.vibratoDelay = 0; + layer->freqScale = 1.0f; + layer->bend = 1.0f; + layer->velocitySquare2 = 0.0f; -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_seqplayer/func_8019AA3C.s") + return 0; +} -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_seqplayer/func_8019AAF0.s") +void AudioSeq_SeqLayerDisable(SequenceLayer* layer) { + if (layer != NULL) { + if ((layer->channel != &gAudioContext.sequenceChannelNone) && (layer->channel->seqPlayer->finished == true)) { + AudioPlayback_SeqLayerNoteRelease(layer); + } else { + AudioPlayback_SeqLayerNoteDecay(layer); + } + layer->enabled = false; + layer->finished = true; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_seqplayer/AudioSeq_ResetSequencePlayer.s") +void AudioSeq_SeqLayerFree(SequenceChannel* channel, s32 layerIndex) { + SequenceLayer* layer = channel->layers[layerIndex]; -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_seqplayer/AudioSeq_InitSequencePlayerChannels.s") + if (layer != NULL) { + AudioSeq_AudioListPushBack(&gAudioContext.layerFreeList, &layer->listItem); + AudioSeq_SeqLayerDisable(layer); + channel->layers[layerIndex] = NULL; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_seqplayer/func_8019ACEC.s") +void AudioSeq_SequenceChannelDisable(SequenceChannel* channel) { + s32 i; -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_seqplayer/AudioSeq_InitSequencePlayers.s") + channel->finished = true; + + for (i = 0; i < 4; i++) { + AudioSeq_SeqLayerFree(channel, i); + } + + AudioPlayback_NotePoolClear(&channel->notePool); + channel->enabled = false; +} + +void AudioSeq_SequencePlayerSetupChannels(SequencePlayer* seqPlayer, u16 channelBits) { + SequenceChannel* channel; + s32 i; + + for (i = 0; i < SEQ_NUM_CHANNELS; i++) { + if (channelBits & 1) { + channel = seqPlayer->channels[i]; + channel->fontId = seqPlayer->defaultFont; + channel->muteFlags = seqPlayer->muteFlags; + channel->noteAllocPolicy = seqPlayer->noteAllocPolicy; + } + channelBits = channelBits >> 1; + } +} + +void AudioSeq_SequencePlayerDisableChannels(SequencePlayer* seqPlayer, u16 channelBitsUnused) { + SequenceChannel* channel; + s32 i; + + for (i = 0; i < SEQ_NUM_CHANNELS; i++) { + channel = seqPlayer->channels[i]; + if (IS_SEQUENCE_CHANNEL_VALID(channel) == 1) { + AudioSeq_SequenceChannelDisable(channel); + } + } +} + +void AudioSeq_SequenceChannelEnable(SequencePlayer* seqPlayer, u8 channelIndex, void* script) { + SequenceChannel* channel = seqPlayer->channels[channelIndex]; + s32 i; + + channel->enabled = true; + channel->finished = false; + channel->scriptState.depth = 0; + channel->scriptState.pc = script; + channel->delay = 0; + + for (i = 0; i < ARRAY_COUNT(channel->layers); i++) { + if (channel->layers[i] != NULL) { + AudioSeq_SeqLayerFree(channel, i); + } + } +} + +void AudioSeq_SequencePlayerDisableAsFinished(SequencePlayer* seqPlayer) { + seqPlayer->finished = true; + AudioSeq_SequencePlayerDisable(seqPlayer); +} + +void AudioSeq_SequencePlayerDisable(SequencePlayer* seqPlayer) { + AudioSeq_SequencePlayerDisableChannels(seqPlayer, 0xFFFF); + AudioPlayback_NotePoolClear(&seqPlayer->notePool); + if (!seqPlayer->enabled) { + return; + } + + seqPlayer->enabled = false; + seqPlayer->finished = true; + + if (AudioLoad_IsSeqLoadComplete(seqPlayer->seqId)) { + AudioLoad_SetSeqLoadStatus(seqPlayer->seqId, LOAD_STATUS_DISCARDABLE); + } + + if (AudioLoad_IsFontLoadComplete(seqPlayer->defaultFont)) { + AudioLoad_SetFontLoadStatus(seqPlayer->defaultFont, LOAD_STATUS_MAYBE_DISCARDABLE); + } + + if (seqPlayer->defaultFont == gAudioContext.fontCache.temporary.entries[0].id) { + gAudioContext.fontCache.temporary.nextSide = 1; + } else if (seqPlayer->defaultFont == gAudioContext.fontCache.temporary.entries[1].id) { + gAudioContext.fontCache.temporary.nextSide = 0; + } +} + +void AudioSeq_AudioListPushBack(AudioListItem* list, AudioListItem* item) { + if (item->prev == NULL) { + list->prev->next = item; + item->prev = list->prev; + item->next = list; + list->prev = item; + list->u.count++; + item->pool = list->pool; + } +} + +void* AudioSeq_AudioListPopBack(AudioListItem* list) { + AudioListItem* item = list->prev; + + if (item == list) { + return NULL; + } + + item->prev->next = list; + list->prev = item->prev; + item->prev = NULL; + list->u.count--; + + return item->u.value; +} + +void AudioSeq_InitLayerFreelist(void) { + s32 i; + + gAudioContext.layerFreeList.prev = &gAudioContext.layerFreeList; + gAudioContext.layerFreeList.next = &gAudioContext.layerFreeList; + gAudioContext.layerFreeList.u.count = 0; + gAudioContext.layerFreeList.pool = NULL; + + for (i = 0; i < ARRAY_COUNT(gAudioContext.sequenceLayers); i++) { + gAudioContext.sequenceLayers[i].listItem.u.value = &gAudioContext.sequenceLayers[i]; + gAudioContext.sequenceLayers[i].listItem.prev = NULL; + AudioSeq_AudioListPushBack(&gAudioContext.layerFreeList, &gAudioContext.sequenceLayers[i].listItem); + } +} + +u8 AudioSeq_ScriptReadU8(SeqScriptState* state) { + return *(state->pc++); +} + +s16 AudioSeq_ScriptReadS16(SeqScriptState* state) { + s16 ret = *(state->pc++) << 8; + + ret = *(state->pc++) | ret; + return ret; +} + +u16 AudioSeq_ScriptReadCompressedU16(SeqScriptState* state) { + u16 ret = *(state->pc++); + + if (ret & 0x80) { + ret = (ret << 8) & 0x7F00; + ret = *(state->pc++) | ret; + } + return ret; +} + +void AudioSeq_SeqLayerProcessScript(SequenceLayer* layer) { + s32 cmd; + + if (!layer->enabled) { + return; + } + + if (layer->delay > 1) { + layer->delay--; + if (!layer->stopSomething && (layer->delay <= layer->gateDelay)) { + AudioPlayback_SeqLayerNoteDecay(layer); + layer->stopSomething = true; + } + return; + } + + AudioSeq_SeqLayerProcessScriptStep1(layer); + + do { + cmd = AudioSeq_SeqLayerProcessScriptStep2(layer); + if (cmd == PROCESS_SCRIPT_END) { + return; + } + + cmd = AudioSeq_SeqLayerProcessScriptStep3(layer, cmd); + + } while ((cmd == -1) && (layer->delay == 0)); + + if (cmd != PROCESS_SCRIPT_END) { + // returns `sameSound` instead of a command + cmd = AudioSeq_SeqLayerProcessScriptStep4(layer, cmd); + } + + if (cmd != PROCESS_SCRIPT_END) { + AudioSeq_SeqLayerProcessScriptStep5(layer, cmd); + } + + if (layer->stopSomething == true) { + if ((layer->note != NULL) || layer->continuousNotes) { + AudioPlayback_SeqLayerNoteDecay(layer); + } + } +} + +void AudioSeq_SeqLayerProcessScriptStep1(SequenceLayer* layer) { + if (!layer->continuousNotes) { + AudioPlayback_SeqLayerNoteDecay(layer); + } else if ((layer->note != NULL) && (layer->note->playbackState.wantedParentLayer == layer)) { + AudioPlayback_SeqLayerNoteDecay(layer); + } + + if ((PORTAMENTO_MODE(layer->portamento) == PORTAMENTO_MODE_1) || + (PORTAMENTO_MODE(layer->portamento) == PORTAMENTO_MODE_2)) { + layer->portamento.mode = PORTAMENTO_MODE_OFF; + } + layer->notePropertiesNeedInit = true; +} + +s32 AudioSeq_SeqLayerProcessScriptStep5(SequenceLayer* layer, s32 sameSound) { + Note* note; + + if ((layer->continuousNotes == true) && (layer->bit1 == true)) { + return 0; + } + + if ((layer->continuousNotes == true) && (layer->note != NULL) && layer->bit3 && (sameSound == true) && + (layer->note->playbackState.parentLayer == layer)) { + if (layer->sound == NULL) { + AudioPlayback_InitSyntheticWave(layer->note, layer); + } + } else { + if (!sameSound) { + AudioPlayback_SeqLayerNoteDecay(layer); + } + + layer->note = AudioPlayback_AllocNote(layer); + + if (layer->note != NULL) { + note = layer->note; + + if (note->playbackState.parentLayer == layer) { + AudioEffects_NoteVibratoInit(note); + } + } + } + + if ((layer->note != NULL) && (layer->note->playbackState.parentLayer == layer)) { + note = layer->note; + + AudioEffects_NotePortamentoInit(note); + } + + return 0; +} + +s32 AudioSeq_SeqLayerProcessScriptStep2(SequenceLayer* layer) { + SequenceChannel* channel = layer->channel; + SeqScriptState* state = &layer->scriptState; + SequencePlayer* seqPlayer = channel->seqPlayer; + u8 cmd; + u8 cmdArg8; + u16 cmdArg16; + u16 velocity; + + while (true) { + cmd = AudioSeq_ScriptReadU8(state); + + // Note Commands + // To be processed in AudioSeq_SeqLayerProcessScriptStep3 + if (cmd <= 0xC0) { + return cmd; + } + + // Control Flow Commands + if (cmd >= 0xF2) { + cmdArg16 = AudioSeq_GetScriptControlFlowArgument(state, cmd); + + if (AudioSeq_HandleScriptFlowControl(seqPlayer, state, cmd, cmdArg16) == 0) { + continue; + } + AudioSeq_SeqLayerDisable(layer); + return PROCESS_SCRIPT_END; + } + + switch (cmd) { + case 0xC1: // layer: set short note velocity + case 0xCA: // layer: set pan + cmdArg8 = *(state->pc++); + if (cmd == 0xC1) { + layer->velocitySquare = SQ(cmdArg8) / SQ(127.0f); + } else { + layer->pan = cmdArg8; + } + break; + + case 0xC9: // layer: set short note gatetime + case 0xC2: // layer: set transposition in semitones + cmdArg8 = *(state->pc++); + if (cmd == 0xC9) { + layer->gateTime = cmdArg8; + } else { + layer->transposition = cmdArg8; + } + break; + + case 0xC4: // layer: continuous notes on + case 0xC5: // layer: continuous notes off + if (cmd == 0xC4) { + layer->continuousNotes = true; + } else { + layer->continuousNotes = false; + } + layer->bit1 = false; + AudioPlayback_SeqLayerNoteDecay(layer); + break; + + case 0xC3: // layer: set short note default delay + cmdArg16 = AudioSeq_ScriptReadCompressedU16(state); + layer->shortNoteDefaultDelay = cmdArg16; + break; + + case 0xC6: // layer: set instrument + cmd = AudioSeq_ScriptReadU8(state); + if (cmd >= 0x7E) { + if (cmd == 0x7E) { + // Sfxs + layer->instOrWave = 1; + } else if (cmd == 0x7F) { + // Drums + layer->instOrWave = 0; + } else { + // Synthetic Wave + layer->instOrWave = cmd; + layer->instrument = NULL; + } + + if (cmd == 0xFF) { + layer->adsr.decayIndex = 0; + } + } else { + // Instrument + if ((layer->instOrWave = AudioSeq_GetInstrument(channel, cmd, &layer->instrument, &layer->adsr)) == + 0) { + layer->instOrWave = 0xFF; + } + } + break; + + case 0xC7: // layer: enable portamento + layer->portamento.mode = AudioSeq_ScriptReadU8(state); + + cmd = AudioSeq_ScriptReadU8(state); + cmd += channel->transposition; + cmd += layer->transposition; + cmd += seqPlayer->transposition; + + if (cmd >= 0x80) { + cmd = 0; + } + + layer->portamentoTargetNote = cmd; + + // If special, the next param is u8 instead of var + if (PORTAMENTO_IS_SPECIAL(layer->portamento)) { + layer->portamentoTime = *(state->pc++); + break; + } + + cmdArg16 = AudioSeq_ScriptReadCompressedU16(state); + layer->portamentoTime = cmdArg16; + break; + + case 0xC8: // layer: disable portamento + layer->portamento.mode = PORTAMENTO_MODE_OFF; + break; + + case 0xCB: // layer: set envelope and decay index + cmdArg16 = AudioSeq_ScriptReadS16(state); + layer->adsr.envelope = (EnvelopePoint*)(seqPlayer->seqData + cmdArg16); + // fallthrough + case 0xCF: // layer: set decay index + layer->adsr.decayIndex = AudioSeq_ScriptReadU8(state); + break; + + case 0xCC: // layer: ignore drum pan + layer->ignoreDrumPan = true; + break; + + case 0xCD: // layer: stereo effects + layer->stereo.asByte = AudioSeq_ScriptReadU8(state); + break; + + case 0xCE: // layer: bend pitch + cmdArg8 = AudioSeq_ScriptReadU8(state); + layer->bend = gBendPitchTwoSemitonesFrequencies[(u8)(cmdArg8 + 0x80)]; + break; + + case 0xF0: // layer: + cmdArg16 = AudioSeq_ScriptReadS16(state); + layer->unk_0A.asByte &= (cmdArg16 ^ 0xFFFF); + break; + + case 0xF1: // layer: + layer->unk_08 = AudioSeq_ScriptReadU8(state); + break; + + default: + switch (cmd & 0xF0) { + case 0xD0: // layer: set short note velocity from table + velocity = seqPlayer->shortNoteVelocityTable[cmd & 0xF]; + layer->velocitySquare = SQ(velocity) / SQ(127.0f); + break; + + case 0xE0: // layer: set short note gatetime from table + layer->gateTime = seqPlayer->shortNoteGateTimeTable[cmd & 0xF]; + break; + } + } + } +} + +s32 AudioSeq_SeqLayerProcessScriptStep4(SequenceLayer* layer, s32 cmd) { + s32 sameSound = true; + s32 instOrWave; + s32 speed; + f32 temp_f14; + f32 temp_f2; + Portamento* portamento; + f32 freqScale; + f32 freqScale2; + SoundFontSound* sound; + Instrument* instrument; + Drum* drum; + s32 pad; + SequenceChannel* channel; + SequencePlayer* seqPlayer; + u8 semitone = cmd; + u16 sfxId; + s32 semitone2; + s32 vel; + f32 time; + f32 tuning; + s32 speed2; + + instOrWave = layer->instOrWave; + channel = layer->channel; + seqPlayer = channel->seqPlayer; + + if (instOrWave == 0xFF) { + if (!channel->hasInstrument) { + return PROCESS_SCRIPT_END; + } + instOrWave = channel->instOrWave; + } + + switch (instOrWave) { + case 0: + // Drums + semitone += channel->transposition + layer->transposition; + layer->semitone = semitone; + + drum = AudioPlayback_GetDrum(channel->fontId, semitone); + if (drum == NULL) { + layer->stopSomething = true; + layer->delay2 = layer->delay; + return PROCESS_SCRIPT_END; + } + + sound = &drum->sound; + layer->adsr.envelope = drum->envelope; + layer->adsr.decayIndex = drum->adsrDecayIndex; + if (!layer->ignoreDrumPan) { + layer->pan = drum->pan; + } + + layer->sound = sound; + layer->freqScale = sound->tuning; + break; + + case 1: + // Sfxs + layer->semitone = semitone; + sfxId = (layer->transposition << 6) + semitone; + + sound = AudioPlayback_GetSfx(channel->fontId, sfxId); + if (sound == NULL) { + layer->stopSomething = true; + layer->delay2 = layer->delay + 1; + return PROCESS_SCRIPT_END; + } + + layer->sound = sound; + layer->freqScale = sound->tuning; + break; + + default: + semitone += seqPlayer->transposition + channel->transposition + layer->transposition; + semitone2 = semitone; + + layer->semitone = semitone; + if (semitone >= 0x80) { + layer->stopSomething = true; + return PROCESS_SCRIPT_END; + } + + if (layer->instOrWave == 0xFF) { + instrument = channel->instrument; + } else { + instrument = layer->instrument; + } + + if (layer->portamento.mode != PORTAMENTO_MODE_OFF) { + portamento = &layer->portamento; + vel = (semitone > layer->portamentoTargetNote) ? semitone : layer->portamentoTargetNote; + + if (instrument != NULL) { + sound = AudioPlayback_InstrumentGetSound(instrument, vel); + sameSound = (layer->sound == sound); + layer->sound = sound; + tuning = sound->tuning; + } else { + layer->sound = NULL; + tuning = 1.0f; + if (instOrWave >= 0xC0) { + layer->sound = &gAudioContext.synthesisReverbs[instOrWave - 0xC0].sound; + } + } + + temp_f2 = gPitchFrequencies[semitone2] * tuning; + temp_f14 = gPitchFrequencies[layer->portamentoTargetNote] * tuning; + + switch (PORTAMENTO_MODE(*portamento)) { + case PORTAMENTO_MODE_1: + case PORTAMENTO_MODE_3: + case PORTAMENTO_MODE_5: + freqScale2 = temp_f2; + freqScale = temp_f14; + break; + + case PORTAMENTO_MODE_2: + case PORTAMENTO_MODE_4: + freqScale = temp_f2; + freqScale2 = temp_f14; + break; + + default: + freqScale = temp_f2; + freqScale2 = temp_f2; + break; + } + + portamento->extent = (freqScale2 / freqScale) - 1.0f; + + if (PORTAMENTO_IS_SPECIAL(*portamento)) { + speed = seqPlayer->tempo * 0x8000 / gAudioContext.tempoInternalToExternal; + if (layer->delay != 0) { + speed = speed * 0x100 / (layer->delay * layer->portamentoTime); + } + } else { + speed = 0x20000 / (layer->portamentoTime * gAudioContext.audioBufferParameters.updatesPerFrame); + } + + if (speed >= 0x7FFF) { + speed = 0x7FFF; + } else if (speed < 1) { + speed = 1; + } + + portamento->speed = speed; + portamento->cur = 0; + layer->freqScale = freqScale; + if (PORTAMENTO_MODE(*portamento) == PORTAMENTO_MODE_5) { + layer->portamentoTargetNote = semitone; + } + break; + } + + if (instrument != NULL) { + sound = AudioPlayback_InstrumentGetSound(instrument, semitone); + sameSound = (sound == layer->sound); + layer->sound = sound; + layer->freqScale = gPitchFrequencies[semitone2] * sound->tuning; + } else { + layer->sound = NULL; + layer->freqScale = gPitchFrequencies[semitone2]; + if (instOrWave >= 0xC0) { + layer->sound = &gAudioContext.synthesisReverbs[instOrWave - 0xC0].sound; + } + } + break; + } + + layer->delay2 = layer->delay; + layer->freqScale *= layer->bend; + + if (layer->delay == 0) { + if (layer->sound != NULL) { + time = layer->sound->sample->loop->end; + } else { + time = 0.0f; + } + time *= seqPlayer->tempo; + time *= gAudioContext.unk_2870; + time /= layer->freqScale; + if (1) {} + if (time > 0x7FFE) { + time = 0x7FFE; + } + + layer->gateDelay = 0; + layer->delay = (u16)(s32)time + 1; + + if (layer->portamento.mode != PORTAMENTO_MODE_OFF) { + // (It's a bit unclear if 'portamento' has actually always been + // set when this is reached...) + if (PORTAMENTO_IS_SPECIAL(*portamento)) { + speed2 = seqPlayer->tempo * 0x8000 / gAudioContext.tempoInternalToExternal; + speed2 = speed2 * 0x100 / (layer->delay * layer->portamentoTime); + if (speed2 >= 0x7FFF) { + speed2 = 0x7FFF; + } else if (speed2 < 1) { + speed2 = 1; + } + portamento->speed = speed2; + } + } + } + return sameSound; +} + +s32 AudioSeq_SeqLayerProcessScriptStep3(SequenceLayer* layer, s32 cmd) { + SeqScriptState* state = &layer->scriptState; + u16 delay; + s32 velocity; + SequenceChannel* channel = layer->channel; + SequencePlayer* seqPlayer = channel->seqPlayer; + s32 intDelta; + f32 floatDelta; + + if (cmd == 0xC0) { // layer: delay + layer->delay = AudioSeq_ScriptReadCompressedU16(state); + layer->stopSomething = true; + layer->bit1 = false; + return PROCESS_SCRIPT_END; + } + + layer->stopSomething = false; + + if (channel->largeNotes == true) { + switch (cmd & 0xC0) { + case 0x00: // layer: large note 0 + delay = AudioSeq_ScriptReadCompressedU16(state); + velocity = *(state->pc++); + layer->gateTime = *(state->pc++); + layer->lastDelay = delay; + break; + + case 0x40: // layer: large note 1 + delay = AudioSeq_ScriptReadCompressedU16(state); + velocity = *(state->pc++); + layer->gateTime = 0; + layer->lastDelay = delay; + break; + + case 0x80: // layer: large note 2 + delay = layer->lastDelay; + velocity = *(state->pc++); + layer->gateTime = *(state->pc++); + break; + } + + if ((velocity > 0x7F) || (velocity < 0)) { + velocity = 0x7F; + } + layer->velocitySquare = SQ((f32)velocity) / SQ(127.0f); + cmd -= (cmd & 0xC0); + } else { + switch (cmd & 0xC0) { + case 0x00: // layer: small note 0 + delay = AudioSeq_ScriptReadCompressedU16(state); + layer->lastDelay = delay; + break; + + case 0x40: // layer: small note 1 + delay = layer->shortNoteDefaultDelay; + break; + + case 0x80: // layer: small note 2 + delay = layer->lastDelay; + break; + } + cmd -= (cmd & 0xC0); + } + + if (channel->velocityRandomVariance != 0) { + floatDelta = layer->velocitySquare * (gAudioContext.audioRandom % channel->velocityRandomVariance) / 100.0f; + if ((gAudioContext.audioRandom & 0x8000) != 0) { + floatDelta = -floatDelta; + } + + layer->velocitySquare2 = layer->velocitySquare + floatDelta; + + if (layer->velocitySquare2 < 0.0f) { + layer->velocitySquare2 = 0.0f; + } else if (layer->velocitySquare2 > 1.0f) { + layer->velocitySquare2 = 1.0f; + } + } else { + layer->velocitySquare2 = layer->velocitySquare; + } + + layer->delay = delay; + layer->gateDelay = (layer->gateTime * delay) >> 8; + + if (channel->gateTimeRandomVariance != 0) { + //! @bug should probably be gateTimeRandomVariance + intDelta = (layer->gateDelay * (gAudioContext.audioRandom % channel->velocityRandomVariance)) / 100; + if ((gAudioContext.audioRandom & 0x4000) != 0) { + intDelta = -intDelta; + } + + layer->gateDelay += intDelta; + if (layer->gateDelay < 0) { + layer->gateDelay = 0; + } else if (layer->gateDelay > layer->delay) { + layer->gateDelay = layer->delay; + } + } + + if ((seqPlayer->muted && (channel->muteFlags & (MUTE_FLAGS_STOP_NOTES | MUTE_FLAGS_4))) || + channel->stopSomething2) { + layer->stopSomething = true; + return PROCESS_SCRIPT_END; + } + + if (seqPlayer->skipTicks != 0) { + layer->stopSomething = true; + return PROCESS_SCRIPT_END; + } + + return cmd; +} + +void AudioSeq_SetChannelPriorities(SequenceChannel* channel, u8 priority) { + if ((priority & 0xF) != 0) { + channel->notePriority = priority & 0xF; + } + + priority = priority >> 4; + if (priority != 0) { + channel->someOtherPriority = priority; + } +} + +u8 AudioSeq_GetInstrument(SequenceChannel* channel, u8 instId, Instrument** instOut, AdsrSettings* adsr) { + Instrument* inst = AudioPlayback_GetInstrumentInner(channel->fontId, instId); + + if (inst == NULL) { + *instOut = NULL; + return 0; + } + + adsr->envelope = inst->envelope; + adsr->decayIndex = inst->adsrDecayIndex; + + *instOut = inst; + + // temporarily offset instrument id by 2 so that instId 0, 1 + // can be reserved by drums and sfxs respectively. + instId += 2; + + return instId; +} + +void AudioSeq_SetInstrument(SequenceChannel* channel, u8 instId) { + if (instId >= 0x80) { + // Synthetic Waves + channel->instOrWave = instId; + channel->instrument = NULL; + } else if (instId == 0x7F) { + // Drums + channel->instOrWave = 0; + channel->instrument = (Instrument*)1; // invalid pointer, never dereferenced + } else if (instId == 0x7E) { + // Sfxs + channel->instOrWave = 1; + channel->instrument = (Instrument*)2; // invalid pointer, never dereferenced + } else { + // Instruments + if ((channel->instOrWave = AudioSeq_GetInstrument(channel, instId, &channel->instrument, &channel->adsr)) == + 0) { + channel->hasInstrument = false; + return; + } + } + + channel->hasInstrument = true; +} + +void AudioSeq_SequenceChannelSetVolume(SequenceChannel* channel, u8 volume) { + channel->volume = (s32)volume / 127.0f; +} + +void AudioSeq_SequenceChannelProcessScript(SequenceChannel* channel) { + s32 i; + u8* data; + u32 rand; + SequencePlayer* seqPlayer; + + if (channel->stopScript) { + goto exit_loop; + } + + seqPlayer = channel->seqPlayer; + if (seqPlayer->muted && (channel->muteFlags & MUTE_FLAGS_STOP_SCRIPT)) { + return; + } + + if (channel->delay >= 2) { + channel->delay--; + goto exit_loop; + } + + while (true) { + SeqScriptState* scriptState = &channel->scriptState; + s32 param; + s16 temp1; + u16 cmdArgU16; + u32 cmdArgs[3]; + s8 cmdArgS8; + u8 cmd = AudioSeq_ScriptReadU8(scriptState); + u8 lowBits; + u8 highBits; + s32 delay; + s32 temp2; + u8 phi_v0_3; + u8 new_var; + u8 depth; + u8* seqData = seqPlayer->seqData; + u32 new_var2; + + // Commands 0xA0 - 0xFF + if (cmd >= 0xA0) { + highBits = sSeqInstructionArgsTable[cmd - 0xA0]; + lowBits = highBits & 3; + + // read in arguments for the instruction + for (i = 0; i < lowBits; i++, highBits <<= 1) { + if (!(highBits & 0x80)) { + cmdArgs[i] = AudioSeq_ScriptReadU8(scriptState); + } else { + cmdArgs[i] = AudioSeq_ScriptReadS16(scriptState); + } + } + + // Control Flow Commands + if (cmd >= 0xF2) { + delay = AudioSeq_HandleScriptFlowControl(seqPlayer, scriptState, cmd, cmdArgs[0]); + + if (delay != 0) { + if (delay == PROCESS_SCRIPT_END) { + AudioSeq_SequenceChannelDisable(channel); + } else { + channel->delay = delay; + } + break; + } + continue; + } + + switch (cmd) { + case 0xEA: // channel: stop script + channel->stopScript = true; + goto exit_loop; + + case 0xF1: // channel: reserve notes + AudioPlayback_NotePoolClear(&channel->notePool); + cmd = (u8)cmdArgs[0]; + AudioPlayback_NotePoolFill(&channel->notePool, cmd); + break; + + case 0xF0: // channel: unreserve notes + AudioPlayback_NotePoolClear(&channel->notePool); + break; + + case 0xC2: // channel: set dyntable + cmdArgU16 = (u16)cmdArgs[0]; + channel->dynTable = (void*)&seqPlayer->seqData[cmdArgU16]; + break; + + case 0xC5: // channel: dyn set dyntable + if (scriptState->value != -1) { + data = (*channel->dynTable)[scriptState->value]; + cmdArgU16 = (u16)((data[0] << 8) + data[1]); + scriptState->pc = (void*)&seqPlayer->seqData[cmdArgU16]; + } + break; + + case 0xEB: // channel: set soundFont and instrument + cmd = (u8)cmdArgs[0]; + + if (seqPlayer->defaultFont != 0xFF) { + cmdArgU16 = ((u16*)gAudioContext.sequenceFontTable)[seqPlayer->seqId]; + lowBits = gAudioContext.sequenceFontTable[cmdArgU16]; + cmd = gAudioContext.sequenceFontTable[cmdArgU16 + lowBits - cmd]; + } + + if (AudioHeap_SearchCaches(FONT_TABLE, CACHE_EITHER, cmd)) { + channel->fontId = cmd; + } + + cmdArgs[0] = cmdArgs[1]; + // fallthrough + case 0xC1: // channel: set instrument + cmd = (u8)cmdArgs[0]; + AudioSeq_SetInstrument(channel, cmd); + break; + + case 0xC3: // channel: large notes off + channel->largeNotes = false; + break; + + case 0xC4: // channel: large notes on + channel->largeNotes = true; + break; + + case 0xDF: // channel: set volume + cmd = (u8)cmdArgs[0]; + AudioSeq_SequenceChannelSetVolume(channel, cmd); + channel->changes.s.volume = true; + break; + + case 0xE0: // channel: set volume scale + cmd = (u8)cmdArgs[0]; + channel->volumeScale = (f32)(s32)cmd / 128.0f; + channel->changes.s.volume = true; + break; + + case 0xDE: // channel: set freqscale + cmdArgU16 = (u16)cmdArgs[0]; + channel->freqScale = (f32)(s32)cmdArgU16 / 0x8000; + channel->changes.s.freqScale = true; + break; + + case 0xD3: // channel: large bend pitch + cmd = (u8)cmdArgs[0]; + cmd += 0x80; + channel->freqScale = gBendPitchOneOctaveFrequencies[cmd]; + channel->changes.s.freqScale = true; + break; + + case 0xEE: // channel: small bend pitch + cmd = (u8)cmdArgs[0]; + cmd += 0x80; + channel->freqScale = gBendPitchTwoSemitonesFrequencies[cmd]; + channel->changes.s.freqScale = true; + break; + + case 0xDD: // channel: set pan + cmd = (u8)cmdArgs[0]; + channel->newPan = cmd; + channel->changes.s.pan = true; + break; + + case 0xDC: // channel: set pan mix + cmd = (u8)cmdArgs[0]; + channel->panChannelWeight = cmd; + channel->changes.s.pan = true; + break; + + case 0xDB: // channel: transpose + cmdArgS8 = (s8)cmdArgs[0]; + channel->transposition = cmdArgS8; + break; + + case 0xDA: // channel: set envelope + cmdArgU16 = (u16)cmdArgs[0]; + channel->adsr.envelope = (EnvelopePoint*)&seqPlayer->seqData[cmdArgU16]; + break; + + case 0xD9: // channel: set decay index + cmd = (u8)cmdArgs[0]; + channel->adsr.decayIndex = cmd; + break; + + case 0xD8: // channel: set vibrato extent + cmd = (u8)cmdArgs[0]; + channel->vibrato.vibratoExtentTarget = cmd * 8; + channel->vibrato.vibratoExtentStart = 0; + channel->vibrato.vibratoExtentChangeDelay = 0; + break; + + case 0xD7: // channel: set vibrato rate + cmd = (u8)cmdArgs[0]; + channel->vibrato.vibratoRateChangeDelay = 0; + channel->vibrato.vibratoRateTarget = cmd * 32; + channel->vibrato.vibratoRateStart = cmd * 32; + break; + + case 0xE2: // channel: set vibrato extent linear + cmd = (u8)cmdArgs[0]; + channel->vibrato.vibratoExtentStart = cmd * 8; + cmd = (u8)cmdArgs[1]; + channel->vibrato.vibratoExtentTarget = cmd * 8; + cmd = (u8)cmdArgs[2]; + channel->vibrato.vibratoExtentChangeDelay = cmd * 16; + break; + + case 0xE1: // channel: set vibratorate linear + cmd = (u8)cmdArgs[0]; + channel->vibrato.vibratoRateStart = cmd * 32; + cmd = (u8)cmdArgs[1]; + channel->vibrato.vibratoRateTarget = cmd * 32; + cmd = (u8)cmdArgs[2]; + channel->vibrato.vibratoRateChangeDelay = cmd * 16; + break; + + case 0xE3: // channel: set vibrato delay + cmd = (u8)cmdArgs[0]; + channel->vibrato.vibratoDelay = cmd * 16; + break; + + case 0xD4: // channel: set reverb + cmd = (u8)cmdArgs[0]; + channel->reverb = cmd; + break; + + case 0xC6: // channel: set soundFont + cmd = (u8)cmdArgs[0]; + + if (seqPlayer->defaultFont != 0xFF) { + cmdArgU16 = ((u16*)gAudioContext.sequenceFontTable)[seqPlayer->seqId]; + lowBits = gAudioContext.sequenceFontTable[cmdArgU16]; + cmd = gAudioContext.sequenceFontTable[cmdArgU16 + lowBits - cmd]; + } + + if (AudioHeap_SearchCaches(FONT_TABLE, CACHE_EITHER, cmd)) { + channel->fontId = cmd; + } + break; + + case 0xC7: // channel: write into sequence script + cmd = (u8)cmdArgs[0]; + cmdArgU16 = (u16)cmdArgs[1]; + seqData = &seqPlayer->seqData[cmdArgU16]; + seqData[0] = (u8)scriptState->value + cmd; + break; + + case 0xC8: // channel: subtract -> set value + case 0xCC: // channel: set value + case 0xC9: // channel: `bit and` -> set value + cmdArgS8 = (s8)cmdArgs[0]; + + if (cmd == 0xC8) { + scriptState->value -= cmdArgS8; + } else if (cmd == 0xCC) { + scriptState->value = cmdArgS8; + } else { + scriptState->value &= cmdArgS8; + } + break; + + case 0xCD: // channel: disable channel + cmd = (u8)cmdArgs[0]; + AudioSeq_SequenceChannelDisable(seqPlayer->channels[cmd]); + break; + + case 0xCA: // channel: set mute behavior + cmd = (u8)cmdArgs[0]; + channel->muteFlags = cmd; + channel->changes.s.volume = true; + break; + + case 0xCB: // channel: read sequence -> set value + cmdArgU16 = (u16)cmdArgs[0]; + scriptState->value = *(seqPlayer->seqData + (u32)(cmdArgU16 + scriptState->value)); + break; + + case 0xCE: // channel: + cmdArgU16 = (u16)cmdArgs[0]; + channel->unk_22 = cmdArgU16; + break; + + case 0xCF: // channel: write large into sequence script + cmdArgU16 = (u16)cmdArgs[0]; + seqData = &seqPlayer->seqData[cmdArgU16]; + seqData[0] = (channel->unk_22 >> 8) & 0xFF; + seqData[1] = channel->unk_22 & 0xFF; + break; + + case 0xD0: // channel: stereo headset effects + cmd = (u8)cmdArgs[0]; + if (cmd & 0x80) { + channel->stereoHeadsetEffects = true; + } else { + channel->stereoHeadsetEffects = false; + } + channel->stereo.asByte = cmd & 0x7F; + break; + + case 0xD1: // channel: set note allocation policy + cmd = (u8)cmdArgs[0]; + channel->noteAllocPolicy = cmd; + break; + + case 0xD2: // channel: set sustain + cmd = (u8)cmdArgs[0]; + channel->adsr.sustain = cmd; + break; + + case 0xE5: // channel: set reverb index + cmd = (u8)cmdArgs[0]; + channel->reverbIndex = cmd; + break; + + case 0xE4: // channel: dyncall + if (scriptState->value != -1) { + data = (*channel->dynTable)[scriptState->value]; + depth = scriptState->depth; + //! @bug: Missing a stack depth check here + scriptState->stack[depth] = scriptState->pc; + scriptState->depth++; + cmdArgU16 = (u16)((data[0] << 8) + data[1]); + scriptState->pc = seqPlayer->seqData + cmdArgU16; + } + break; + + case 0xE6: // channel: set book offset + cmd = (u8)cmdArgs[0]; + channel->bookOffset = cmd; + break; + + case 0xE7: // channel: + cmdArgU16 = (u16)cmdArgs[0]; + data = &seqPlayer->seqData[cmdArgU16]; + channel->muteFlags = data[0]; + data += 3; + channel->noteAllocPolicy = data[-2]; + AudioSeq_SetChannelPriorities(channel, data[-1]); + channel->transposition = (s8)data[0]; + data += 4; + channel->newPan = data[-3]; + channel->panChannelWeight = data[-2]; + channel->reverb = data[-1]; + channel->reverbIndex = data[0]; + //! @bug: Not marking reverb state as changed + channel->changes.s.pan = true; + break; + + case 0xE8: // channel: + channel->muteFlags = cmdArgs[0]; + channel->noteAllocPolicy = cmdArgs[1]; + cmd = (u8)cmdArgs[2]; + AudioSeq_SetChannelPriorities(channel, cmd); + channel->transposition = (s8)AudioSeq_ScriptReadU8(scriptState); + channel->newPan = AudioSeq_ScriptReadU8(scriptState); + channel->panChannelWeight = AudioSeq_ScriptReadU8(scriptState); + channel->reverb = AudioSeq_ScriptReadU8(scriptState); + channel->reverbIndex = AudioSeq_ScriptReadU8(scriptState); + //! @bug: Not marking reverb state as changed + channel->changes.s.pan = true; + break; + + case 0xEC: // channel: reset vibrato + channel->vibrato.vibratoExtentTarget = 0; + channel->vibrato.vibratoExtentStart = 0; + channel->vibrato.vibratoExtentChangeDelay = 0; + channel->vibrato.vibratoRateTarget = 0; + channel->vibrato.vibratoRateStart = 0; + channel->vibrato.vibratoRateChangeDelay = 0; + channel->filter = NULL; + channel->gain = 0; + channel->adsr.sustain = 0; + channel->velocityRandomVariance = 0; + channel->gateTimeRandomVariance = 0; + channel->unk_0F = 0; + channel->unk_20 = 0; + channel->bookOffset = 0; + channel->unk_DC = 0; + channel->unk_E0 = 0; + channel->freqScale = 1.0f; + break; + + case 0xE9: // channel: set note priority + AudioSeq_SetChannelPriorities(channel, (u8)cmdArgs[0]); + break; + + case 0xED: // channel: set hilo gain + cmd = (u8)cmdArgs[0]; + channel->gain = cmd; + break; + + case 0xB0: // channel: set filter + cmdArgU16 = (u16)cmdArgs[0]; + data = seqPlayer->seqData + cmdArgU16; + channel->filter = (s16*)data; + break; + + case 0xB1: // channel: clear filter + channel->filter = NULL; + break; + + case 0xB3: // channel: load filter + cmd = cmdArgs[0]; + + if (channel->filter != NULL) { + lowBits = (cmd >> 4) & 0xF; // LowPassCutoff + cmd &= 0xF; // HighPassCutoff + AudioHeap_LoadFilter(channel->filter, lowBits, cmd); + } + break; + + case 0xB2: // channel: dynread sequence large + cmdArgU16 = (u16)cmdArgs[0]; + channel->unk_22 = *(u16*)(seqPlayer->seqData + (u32)(cmdArgU16 + scriptState->value * 2)); + break; + + case 0xB4: // channel: set dyntable large + channel->dynTable = (void*)&seqPlayer->seqData[channel->unk_22]; + break; + + case 0xB5: // channel: read dyntable large + channel->unk_22 = ((u16*)(channel->dynTable))[scriptState->value]; + break; + + case 0xB6: // channel: read dyntable + scriptState->value = (*channel->dynTable)[0][scriptState->value]; + break; + + case 0xB7: // channel: random large + channel->unk_22 = (cmdArgs[0] == 0) ? (gAudioContext.audioRandom & 0xFFFF) + : (gAudioContext.audioRandom % cmdArgs[0]); + break; + + case 0xB8: // channel: random value + scriptState->value = (cmdArgs[0] == 0) ? (gAudioContext.audioRandom & 0xFFFF) + : (gAudioContext.audioRandom % cmdArgs[0]); + break; + + case 0xA8: // channel: random range large (only cmd that differs from OoT) + rand = Audio_NextRandom(); + channel->unk_22 = (cmdArgs[0] == 0) ? (rand & 0xFFFF) : (rand % cmdArgs[0]); + channel->unk_22 += cmdArgs[1]; + temp2 = (channel->unk_22 / 0x100) + 0x80; + param = channel->unk_22 % 0x100; + channel->unk_22 = (temp2 << 8) | param; + break; + + case 0xB9: // channel: set velocity random variance + channel->velocityRandomVariance = cmdArgs[0]; + break; + + case 0xBA: // channel: set gatetime random variance + channel->gateTimeRandomVariance = cmdArgs[0]; + break; + + case 0xBB: // channel: + channel->unk_0F = cmdArgs[0]; + channel->unk_20 = cmdArgs[1]; + break; + + case 0xBC: // channel: add large + channel->unk_22 += cmdArgs[0]; + break; + + case 0xBD: // channel: + channel->unk_DC = cmdArgs[0]; + break; + + case 0xBE: // 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); + } + } + break; + + case 0xA0: // channel: + case 0xA1: // channel: + case 0xA2: // channel: + case 0xA3: // channel: + if ((cmd == 0xA0) || (cmd == 0xA2)) { + cmdArgU16 = (u16)cmdArgs[0]; + } else { + cmdArgU16 = channel->unk_22; + } + + if (channel->sfxState != NULL) { + if ((cmd == 0xA0) || (cmd == 0xA1)) { + scriptState->value = channel->sfxState[cmdArgU16]; + } else { + channel->sfxState[cmdArgU16] = scriptState->value; + } + } + break; + + case 0xA4: // channel: + channel->unk_10 = cmdArgs[0]; + break; + + case 0xA5: // channel: + scriptState->value += channel->unk_11; + break; + + case 0xA6: // channel: + cmd = (u8)cmdArgs[0]; + cmdArgU16 = (u16)cmdArgs[1]; + seqData = seqPlayer->seqData + (u32)(cmdArgU16 + channel->unk_11); + seqData[0] = (u8)scriptState->value + cmd; + break; + + case 0xA7: // channel: + new_var2 = (cmdArgs[0] & 0x80); + new_var = (scriptState->value & 0x80); + + if (!new_var2) { + phi_v0_3 = scriptState->value << (cmdArgs[0] & 0xF); + } else { + phi_v0_3 = scriptState->value >> (cmdArgs[0] & 0xF); + } + + if (cmdArgs[0] & 0x40) { + phi_v0_3 &= (u8)~0x80; + phi_v0_3 |= new_var; + } + + scriptState->value = phi_v0_3; + break; + } + continue; + } + + // Commands 0x70 - 0x9F + if (cmd >= 0x70) { + lowBits = cmd & 0x7; + + if (((cmd & 0xF8) != 0x70) && (lowBits >= 4)) { + lowBits = 0; + } + + switch (cmd & 0xF8) { + case 0x80: // channel: test layer is finished + if (channel->layers[lowBits] != NULL) { + scriptState->value = channel->layers[lowBits]->finished; + } else { + scriptState->value = -1; + } + break; + + case 0x88: // channel: set layer + cmdArgU16 = AudioSeq_ScriptReadS16(scriptState); + if (!AudioSeq_SeqChannelSetLayer(channel, lowBits)) { + channel->layers[lowBits]->scriptState.pc = &seqPlayer->seqData[cmdArgU16]; + } + break; + + case 0x90: // channel: free layer + AudioSeq_SeqLayerFree(channel, lowBits); + break; + + case 0x98: // channel: dynset layer + if ((scriptState->value != -1) && (AudioSeq_SeqChannelSetLayer(channel, lowBits) != -1)) { + data = (*channel->dynTable)[scriptState->value]; + cmdArgU16 = (data[0] << 8) + data[1]; + channel->layers[lowBits]->scriptState.pc = &seqPlayer->seqData[cmdArgU16]; + } + break; + + case 0x70: // channel: io write value + channel->soundScriptIO[lowBits] = scriptState->value; + break; + + case 0x78: // channel: set layer relative + temp1 = AudioSeq_ScriptReadS16(scriptState); + if (!AudioSeq_SeqChannelSetLayer(channel, lowBits)) { + channel->layers[lowBits]->scriptState.pc = &scriptState->pc[temp1]; + } + break; + } + continue; + } + + // Commands 0x00 - 0x6F + lowBits = cmd & 0xF; + + switch (cmd & 0xF0) { + case 0x00: // channel: delay short + channel->delay = lowBits; + if (lowBits == 0) { + break; + } + goto exit_loop; + + case 0x10: // channel: load sample + if (lowBits < 8) { + channel->soundScriptIO[lowBits] = -1; + if (AudioLoad_SlowLoadSample(channel->fontId, scriptState->value, + &channel->soundScriptIO[lowBits]) == -1) {} + } else { + lowBits -= 8; + channel->soundScriptIO[lowBits] = -1; + if (AudioLoad_SlowLoadSample(channel->fontId, channel->unk_22 + 0x100, + &channel->soundScriptIO[lowBits]) == -1) {} + } + break; + + case 0x60: // channel: io read value + scriptState->value = channel->soundScriptIO[lowBits]; + if (lowBits < 2) { + channel->soundScriptIO[lowBits] = -1; + } + break; + + case 0x50: // channel: io read value subtract + scriptState->value -= channel->soundScriptIO[lowBits]; + break; + + case 0x20: // channel: start channel + cmdArgU16 = AudioSeq_ScriptReadS16(scriptState); + AudioSeq_SequenceChannelEnable(seqPlayer, lowBits, &seqPlayer->seqData[cmdArgU16]); + break; + + case 0x30: // channel: io write value 2 + cmd = AudioSeq_ScriptReadU8(scriptState); + seqPlayer->channels[lowBits]->soundScriptIO[cmd] = scriptState->value; + break; + + case 0x40: // channel: io read value 2 + cmd = AudioSeq_ScriptReadU8(scriptState); + scriptState->value = seqPlayer->channels[lowBits]->soundScriptIO[cmd]; + break; + } + } +exit_loop: + + for (i = 0; i < ARRAY_COUNT(channel->layers); i++) { + if (channel->layers[i] != NULL) { + AudioSeq_SeqLayerProcessScript(channel->layers[i]); + } + } +} + +void AudioSeq_SequencePlayerProcessSequence(SequencePlayer* seqPlayer) { + u8 cmd; + u8 cmdLowBits; + SeqScriptState* seqScript = &seqPlayer->scriptState; + s16 tempS; + u16 temp; + s32 i; + s32 value; + u8* data1; + u8* data2; + u8* data3; + u8* data4; + s32 tempoChange; + s32 j; + SequenceChannel* channel; + u16* new_var; + s32 delay; + + if (!seqPlayer->enabled) { + return; + } + + if (!AudioLoad_IsSeqLoadComplete(seqPlayer->seqId) || !AudioLoad_IsFontLoadComplete(seqPlayer->defaultFont)) { + // These function calls serve no purpose + if (AudioLoad_IsSeqLoadComplete(seqPlayer->seqId)) {} + if (AudioLoad_IsSeqLoadComplete(seqPlayer->defaultFont)) {} + + AudioSeq_SequencePlayerDisable(seqPlayer); + return; + } + + AudioLoad_SetSeqLoadStatus(seqPlayer->seqId, LOAD_STATUS_COMPLETE); + AudioLoad_SetFontLoadStatus(seqPlayer->defaultFont, LOAD_STATUS_COMPLETE); + + if (seqPlayer->muted && (seqPlayer->muteFlags & MUTE_FLAGS_STOP_SCRIPT)) { + return; + } + + seqPlayer->scriptCounter++; + + tempoChange = seqPlayer->tempo + seqPlayer->unk_0C; + if (tempoChange > gAudioContext.tempoInternalToExternal) { + tempoChange = gAudioContext.tempoInternalToExternal; + } + + seqPlayer->tempoAcc += tempoChange; + + if (seqPlayer->tempoAcc < gAudioContext.tempoInternalToExternal) { + return; + } + + seqPlayer->tempoAcc -= (u16)gAudioContext.tempoInternalToExternal; + seqPlayer->unk_16++; + + if (seqPlayer->stopScript == true) { + return; + } + + if (seqPlayer->delay > 1) { + seqPlayer->delay--; + } else { + seqPlayer->recalculateVolume = true; + + while (true) { + cmd = AudioSeq_ScriptReadU8(seqScript); + + // 0xF2 and above are "flow control" commands, including termination. + if (cmd >= 0xF2) { + delay = AudioSeq_HandleScriptFlowControl( + seqPlayer, seqScript, cmd, AudioSeq_GetScriptControlFlowArgument(&seqPlayer->scriptState, cmd)); + + if (delay != 0) { + if (delay == -1) { + AudioSeq_SequencePlayerDisable(seqPlayer); + } else { + seqPlayer->delay = delay; + } + break; + } + continue; + } + + // Commands 0xC0 - 0xF1 + if (cmd >= 0xC0) { + switch (cmd) { + case 0xF1: // seqPlayer: reserve notes + AudioPlayback_NotePoolClear(&seqPlayer->notePool); + cmd = AudioSeq_ScriptReadU8(seqScript); + AudioPlayback_NotePoolFill(&seqPlayer->notePool, cmd); + break; + + case 0xF0: // seqPlayer: unreserve notes + AudioPlayback_NotePoolClear(&seqPlayer->notePool); + break; + + case 0xDF: // seqPlayer: transpose + seqPlayer->transposition = 0; + // fallthrough + case 0xDE: // seqPlayer: transpose relative + seqPlayer->transposition += (s8)AudioSeq_ScriptReadU8(seqScript); + break; + + case 0xDD: // seqPlayer: set tempo + seqPlayer->tempo = AudioSeq_ScriptReadU8(seqScript) * TATUMS_PER_BEAT; + if (seqPlayer->tempo > gAudioContext.tempoInternalToExternal) { + seqPlayer->tempo = gAudioContext.tempoInternalToExternal; + } + + if ((s16)seqPlayer->tempo <= 0) { + seqPlayer->tempo = 1; + } + break; + + case 0xDC: // seqPlayer: add tempo + seqPlayer->unk_0C = (s8)AudioSeq_ScriptReadU8(seqScript) * TATUMS_PER_BEAT; + break; + + case 0xDA: // seqPlayer: change volume + cmd = AudioSeq_ScriptReadU8(seqScript); + temp = AudioSeq_ScriptReadS16(seqScript); + switch (cmd) { + case 0: + case 1: + if (seqPlayer->state != 2) { + seqPlayer->fadeTimerUnkEu = temp; + seqPlayer->state = cmd; + } + break; + + case 2: + seqPlayer->fadeTimer = temp; + seqPlayer->state = cmd; + seqPlayer->fadeVelocity = (0.0f - seqPlayer->fadeVolume) / (s32)seqPlayer->fadeTimer; + break; + } + break; + + case 0xDB: // seqPlayer: set volume + value = AudioSeq_ScriptReadU8(seqScript); + switch (seqPlayer->state) { + case 1: + seqPlayer->state = 0; + seqPlayer->fadeVolume = 0.0f; + // fallthrough + case 0: + seqPlayer->fadeTimer = seqPlayer->fadeTimerUnkEu; + if (seqPlayer->fadeTimerUnkEu != 0) { + seqPlayer->fadeVelocity = + ((value / 127.0f) - seqPlayer->fadeVolume) / (s32)seqPlayer->fadeTimer; + } else { + seqPlayer->fadeVolume = value / 127.0f; + } + break; + + case 2: + break; + } + break; + + case 0xD9: // seqPlayer: set volume scale + seqPlayer->fadeVolumeScale = (s8)AudioSeq_ScriptReadU8(seqScript) / 127.0f; + break; + + case 0xD7: // seqPlayer: initialize channels + temp = AudioSeq_ScriptReadS16(seqScript); + AudioSeq_SequencePlayerSetupChannels(seqPlayer, temp); + break; + + case 0xD6: // seqPlayer: disable channels + AudioSeq_ScriptReadS16(seqScript); + break; + + case 0xD5: // seqPlayer: set mute scale + seqPlayer->muteVolumeScale = (s8)AudioSeq_ScriptReadU8(seqScript) / 127.0f; + break; + + case 0xD4: // seqPlayer: mute + seqPlayer->muted = true; + break; + + case 0xD3: // seqPlayer: set mute behavior + seqPlayer->muteFlags = AudioSeq_ScriptReadU8(seqScript); + break; + + case 0xD1: // seqPlayer: set short note gatetime table + case 0xD2: // seqPlayer: set short note velocity table + temp = AudioSeq_ScriptReadS16(seqScript); + data3 = &seqPlayer->seqData[temp]; + if (cmd == 0xD2) { + seqPlayer->shortNoteVelocityTable = data3; + } else { + seqPlayer->shortNoteGateTimeTable = data3; + } + break; + + case 0xD0: // seqPlayer: set note allocation policy + seqPlayer->noteAllocPolicy = AudioSeq_ScriptReadU8(seqScript); + break; + + case 0xCE: // seqPlayer: random value + cmd = AudioSeq_ScriptReadU8(seqScript); + if (cmd == 0) { + seqScript->value = (gAudioContext.audioRandom >> 2) & 0xFF; + } else { + seqScript->value = (gAudioContext.audioRandom >> 2) % cmd; + } + break; + + case 0xCD: // seqPlayer: dyncall + temp = AudioSeq_ScriptReadS16(seqScript); + if ((seqScript->value != -1) && (seqScript->depth != 3)) { + data1 = seqPlayer->seqData + (u32)(temp + (seqScript->value << 1)); + seqScript->stack[seqScript->depth] = seqScript->pc; + seqScript->depth++; + temp = (data1[0] << 8) + data1[1]; + seqScript->pc = &seqPlayer->seqData[temp]; + } + break; + + case 0xCC: // seqPlayer: set value + seqScript->value = AudioSeq_ScriptReadU8(seqScript); + break; + + case 0xC9: // seqPlayer: `bit and` -> set value + seqScript->value &= AudioSeq_ScriptReadU8(seqScript); + break; + + case 0xC8: // seqPlayer: subtract -> set value + seqScript->value -= AudioSeq_ScriptReadU8(seqScript); + break; + + case 0xC7: // seqPlayer: write into sequence script + cmd = AudioSeq_ScriptReadU8(seqScript); + temp = AudioSeq_ScriptReadS16(seqScript); + data2 = &seqPlayer->seqData[temp]; + *data2 = (u8)seqScript->value + cmd; + break; + + case 0xC2: // seqPlayer: + temp = AudioSeq_ScriptReadS16(seqScript); + if (seqScript->value != -1) { + data4 = seqPlayer->seqData + (u32)(temp + (seqScript->value << 1)); + + temp = (data4[0] << 8) + data4[1]; + seqScript->pc = &seqPlayer->seqData[temp]; + } + break; + + case 0xC6: // seqPlayer: stop script + seqPlayer->stopScript = true; + return; + + case 0xC5: // seqPlayer: + seqPlayer->unk_16 = AudioSeq_ScriptReadS16(seqScript); + break; + + case 0xEF: // seqPlayer: + AudioSeq_ScriptReadS16(seqScript); + AudioSeq_ScriptReadU8(seqScript); + break; + + case 0xC4: // seqPlayer: start sequence + cmd = AudioSeq_ScriptReadU8(seqScript); + if (cmd == 0xFF) { + cmd = seqPlayer->playerIndex; + if (seqPlayer->state == 2) { + break; + } + } + + cmdLowBits = AudioSeq_ScriptReadU8(seqScript); + AudioLoad_SyncInitSeqPlayer(cmd, cmdLowBits, 0); + if (cmd == (u8)seqPlayer->playerIndex) { + return; + } + break; + + case 0xC3: // seqPlayer: + temp = AudioSeq_ScriptReadS16(seqScript); + if (seqScript->value != -1) { + new_var = (u16*)(seqPlayer->seqData + (u32)(temp + seqScript->value * 2)); + temp = *new_var; + + for (i = 0; i < ARRAY_COUNT(seqPlayer->channels); i++) { + seqPlayer->channels[i]->stopSomething2 = temp & 1; + temp = temp >> 1; + } + } + break; + } + continue; + } + + // Commands 0x00 - 0xBF + cmdLowBits = cmd & 0x0F; + + switch (cmd & 0xF0) { + case 0x00: // seqPlayer: test channel disabled + seqScript->value = seqPlayer->channels[cmdLowBits]->enabled ^ 1; + break; + + case 0x50: // seqPlayer: io read value subtract + seqScript->value -= seqPlayer->soundScriptIO[cmdLowBits]; + break; + + case 0x70: // seqPlayer: io write value + seqPlayer->soundScriptIO[cmdLowBits] = seqScript->value; + break; + + case 0x80: // seqPlayer: io read value + seqScript->value = seqPlayer->soundScriptIO[cmdLowBits]; + if (cmdLowBits < 2) { + seqPlayer->soundScriptIO[cmdLowBits] = -1; + } + break; + + case 0x40: // seqPlayer: disable channel + AudioSeq_SequenceChannelDisable(seqPlayer->channels[cmdLowBits]); + break; + + case 0x90: // seqPlayer: start channel + temp = AudioSeq_ScriptReadS16(seqScript); + AudioSeq_SequenceChannelEnable(seqPlayer, cmdLowBits, (void*)&seqPlayer->seqData[temp]); + break; + + case 0xA0: // seqPlayer: start channel relative + tempS = AudioSeq_ScriptReadS16(seqScript); + AudioSeq_SequenceChannelEnable(seqPlayer, cmdLowBits, (void*)&seqScript->pc[tempS]); + break; + + case 0xB0: // seqPlayer: load sequence + cmd = AudioSeq_ScriptReadU8(seqScript); + temp = AudioSeq_ScriptReadS16(seqScript); + data2 = &seqPlayer->seqData[temp]; + AudioLoad_SlowLoadSeq(cmd, data2, &seqPlayer->soundScriptIO[cmdLowBits]); + break; + + case 0x60: // seqPlayer: async load + cmd = AudioSeq_ScriptReadU8(seqScript); + value = cmd; + temp = AudioSeq_ScriptReadU8(seqScript); + AudioLoad_ScriptLoad(value, temp, &seqPlayer->soundScriptIO[cmdLowBits]); + break; + } + } + } + + for (j = 0; j < SEQ_NUM_CHANNELS; j++) { + channel = seqPlayer->channels[j]; + if (channel->enabled) { + AudioSeq_SequenceChannelProcessScript(channel); + } + } +} + +void AudioSeq_ProcessSequences(s32 arg0) { + SequencePlayer* seqPlayer; + u32 i; + + gAudioContext.noteSubEuOffset = + (gAudioContext.audioBufferParameters.updatesPerFrame - arg0 - 1) * gAudioContext.numNotes; + + for (i = 0; i < (u32)gAudioContext.audioBufferParameters.numSequencePlayers; i++) { + seqPlayer = &gAudioContext.seqPlayers[i]; + if (seqPlayer->enabled == true) { + AudioSeq_SequencePlayerProcessSequence(seqPlayer); + AudioEffects_SequencePlayerProcessSound(seqPlayer); + } + } + + AudioPlayback_ProcessNotes(); +} + +void AudioSeq_SkipForwardSequence(SequencePlayer* seqPlayer) { + while (seqPlayer->skipTicks > 0) { + AudioSeq_SequencePlayerProcessSequence(seqPlayer); + AudioEffects_SequencePlayerProcessSound(seqPlayer); + seqPlayer->skipTicks--; + } +} + +void AudioSeq_ResetSequencePlayer(SequencePlayer* seqPlayer) { + s32 i; + + AudioSeq_SequencePlayerDisable(seqPlayer); + seqPlayer->stopScript = false; + seqPlayer->delay = 0; + seqPlayer->state = 1; + seqPlayer->fadeTimer = 0; + seqPlayer->fadeTimerUnkEu = 0; + seqPlayer->tempoAcc = 0; + seqPlayer->tempo = 120 * TATUMS_PER_BEAT; // 120 BPM + seqPlayer->unk_0C = 0; + seqPlayer->transposition = 0; + seqPlayer->noteAllocPolicy = 0; + seqPlayer->shortNoteVelocityTable = gDefaultShortNoteVelocityTable; + seqPlayer->shortNoteGateTimeTable = gDefaultShortNoteGateTimeTable; + seqPlayer->scriptCounter = 0; + seqPlayer->unk_16 = 0; + seqPlayer->fadeVolume = 1.0f; + seqPlayer->fadeVelocity = 0.0f; + seqPlayer->volume = 0.0f; + seqPlayer->muteVolumeScale = 0.5f; + + for (i = 0; i < SEQ_NUM_CHANNELS; i++) { + AudioSeq_InitSequenceChannel(seqPlayer->channels[i]); + } +} + +void AudioSeq_InitSequencePlayerChannels(s32 playerIndex) { + SequenceChannel* channel; + SequencePlayer* seqPlayer = &gAudioContext.seqPlayers[playerIndex]; + s32 i; + s32 j; + + for (i = 0; i < SEQ_NUM_CHANNELS; i++) { + seqPlayer->channels[i] = AudioHeap_AllocZeroed(&gAudioContext.miscPool, sizeof(SequenceChannel)); + if (seqPlayer->channels[i] == NULL) { + seqPlayer->channels[i] = &gAudioContext.sequenceChannelNone; + } else { + channel = seqPlayer->channels[i]; + channel->seqPlayer = seqPlayer; + channel->enabled = false; + channel->unk_11 = i; + for (j = 0; j < ARRAY_COUNT(channel->layers); j++) { + channel->layers[j] = NULL; + } + } + + AudioSeq_InitSequenceChannel(seqPlayer->channels[i]); + } +} + +void AudioSeq_InitSequencePlayer(SequencePlayer* seqPlayer) { + s32 i; + s32 j; + + for (i = 0; i < SEQ_NUM_CHANNELS; i++) { + seqPlayer->channels[i] = &gAudioContext.sequenceChannelNone; + } + + seqPlayer->enabled = false; + seqPlayer->muted = false; + seqPlayer->fontDmaInProgress = false; + seqPlayer->seqDmaInProgress = false; + seqPlayer->applyBend = false; + + for (j = 0; j < ARRAY_COUNT(seqPlayer->soundScriptIO); j++) { + seqPlayer->soundScriptIO[j] = -1; + } + + seqPlayer->muteFlags = MUTE_FLAGS_SOFTEN | MUTE_FLAGS_STOP_NOTES; + seqPlayer->fadeVolumeScale = 1.0f; + seqPlayer->bend = 1.0f; + + AudioPlayback_InitNoteLists(&seqPlayer->notePool); + AudioSeq_ResetSequencePlayer(seqPlayer); +} + +void AudioSeq_InitSequencePlayers(void) { + s32 i; + + AudioSeq_InitLayerFreelist(); + + for (i = 0; i < ARRAY_COUNT(gAudioContext.sequenceLayers); i++) { + gAudioContext.sequenceLayers[i].channel = NULL; + gAudioContext.sequenceLayers[i].enabled = false; + } + + for (i = 0; i < ARRAY_COUNT(gAudioContext.seqPlayers); i++) { + AudioSeq_InitSequencePlayer(&gAudioContext.seqPlayers[i]); + } +} diff --git a/tools/disasm/functions.txt b/tools/disasm/functions.txt index 46c36a6284..8fbbbf0c95 100644 --- a/tools/disasm/functions.txt +++ b/tools/disasm/functions.txt @@ -3767,41 +3767,41 @@ 0x80197138:("AudioEffects_NotePortamentoInit",), 0x80197164:("AudioEffects_AdsrInit",), 0x80197188:("AudioEffects_AdsrUpdate",), - 0x801974D0:("func_801974D0",), - 0x80197538:("func_80197538",), - 0x80197714:("func_80197714",), - 0x80197880:("func_80197880",), - 0x801979D8:("func_801979D8",), - 0x80197A54:("func_80197A54",), + 0x801974D0:("AudioSeq_GetScriptControlFlowArgument",), + 0x80197538:("AudioSeq_HandleScriptFlowControl",), + 0x80197714:("AudioSeq_InitSequenceChannel",), + 0x80197880:("AudioSeq_SeqChannelSetLayer",), + 0x801979D8:("AudioSeq_SeqLayerDisable",), + 0x80197A54:("AudioSeq_SeqLayerFree",), 0x80197AA4:("AudioSeq_SequenceChannelDisable",), - 0x80197B14:("func_80197B14",), - 0x80197C0C:("func_80197C0C",), - 0x80197C8C:("func_80197C8C",), + 0x80197B14:("AudioSeq_SequencePlayerSetupChannels",), + 0x80197C0C:("AudioSeq_SequencePlayerDisableChannels",), + 0x80197C8C:("AudioSeq_SequenceChannelEnable",), 0x80197D24:("AudioSeq_SequencePlayerDisableAsFinished",), 0x80197D4C:("AudioSeq_SequencePlayerDisable",), 0x80197E08:("AudioSeq_AudioListPushBack",), 0x80197E48:("AudioSeq_AudioListPopBack",), - 0x80197E88:("func_80197E88",), - 0x80197F28:("func_80197F28",), - 0x80197F3C:("func_80197F3C",), - 0x80197F74:("func_80197F74",), - 0x80197FB4:("func_80197FB4",), - 0x801980D0:("func_801980D0",), - 0x8019815C:("func_8019815C",), - 0x8019825C:("func_8019825C",), - 0x80198640:("func_80198640",), - 0x80198CE0:("func_80198CE0",), - 0x801990F4:("func_801990F4",), - 0x80199124:("func_80199124",), - 0x80199198:("func_80199198",), - 0x80199244:("func_80199244",), - 0x80199268:("func_80199268",), - 0x8019A0BC:("func_8019A0BC",), - 0x8019AA3C:("func_8019AA3C",), - 0x8019AAF0:("func_8019AAF0",), + 0x80197E88:("AudioSeq_InitLayerFreelist",), + 0x80197F28:("AudioSeq_ScriptReadU8",), + 0x80197F3C:("AudioSeq_ScriptReadS16",), + 0x80197F74:("AudioSeq_ScriptReadCompressedU16",), + 0x80197FB4:("AudioSeq_SeqLayerProcessScript",), + 0x801980D0:("AudioSeq_SeqLayerProcessScriptStep1",), + 0x8019815C:("AudioSeq_SeqLayerProcessScriptStep5",), + 0x8019825C:("AudioSeq_SeqLayerProcessScriptStep2",), + 0x80198640:("AudioSeq_SeqLayerProcessScriptStep4",), + 0x80198CE0:("AudioSeq_SeqLayerProcessScriptStep3",), + 0x801990F4:("AudioSeq_SetChannelPriorities",), + 0x80199124:("AudioSeq_GetInstrument",), + 0x80199198:("AudioSeq_SetInstrument",), + 0x80199244:("AudioSeq_SequenceChannelSetVolume",), + 0x80199268:("AudioSeq_SequenceChannelProcessScript",), + 0x8019A0BC:("AudioSeq_SequencePlayerProcessSequence",), + 0x8019AA3C:("AudioSeq_ProcessSequences",), + 0x8019AAF0:("AudioSeq_SkipForwardSequence",), 0x8019AB40:("AudioSeq_ResetSequencePlayer",), 0x8019AC10:("AudioSeq_InitSequencePlayerChannels",), - 0x8019ACEC:("func_8019ACEC",), + 0x8019ACEC:("AudioSeq_InitSequencePlayer",), 0x8019ADBC:("AudioSeq_InitSequencePlayers",), 0x8019AE40:("func_8019AE40",), 0x8019AEC0:("func_8019AEC0",), diff --git a/tools/disasm/variables.txt b/tools/disasm/variables.txt index e6f3e21390..d9ce9cf704 100644 --- a/tools/disasm/variables.txt +++ b/tools/disasm/variables.txt @@ -2252,7 +2252,7 @@ 0x801D618C:("D_801D618C","UNK_PTR","",0x4), 0x801D6190:("D_801D6190","f32","",0x4), 0x801D6194:("D_801D6194","UNK_TYPE4","",0x4), - 0x801D61A0:("D_801D61A0","u8","[96]",0x60), + 0x801D61A0:("sSeqInstructionArgsTable","u8","[96]",0x60), 0x801D6200:("D_801D6200","UNK_TYPE1","",0x1), 0x801D6600:("D_801D6600","UNK_TYPE1","",0x1), 0x801D6608:("D_801D6608","UNK_TYPE1","",0x1), diff --git a/tools/sizes/code_functions.csv b/tools/sizes/code_functions.csv index e8acc77447..41da82d05a 100644 --- a/tools/sizes/code_functions.csv +++ b/tools/sizes/code_functions.csv @@ -3283,41 +3283,41 @@ asm/non_matchings/code/audio_effects/AudioEffects_NoteVibratoInit.s,AudioEffects asm/non_matchings/code/audio_effects/AudioEffects_NotePortamentoInit.s,AudioEffects_NotePortamentoInit,0x80197138,0xB asm/non_matchings/code/audio_effects/AudioEffects_AdsrInit.s,AudioEffects_AdsrInit,0x80197164,0x9 asm/non_matchings/code/audio_effects/AudioEffects_AdsrUpdate.s,AudioEffects_AdsrUpdate,0x80197188,0xD2 -asm/non_matchings/code/audio_seqplayer/func_801974D0.s,func_801974D0,0x801974D0,0x1A -asm/non_matchings/code/audio_seqplayer/func_80197538.s,func_80197538,0x80197538,0x77 -asm/non_matchings/code/audio_seqplayer/func_80197714.s,func_80197714,0x80197714,0x5B -asm/non_matchings/code/audio_seqplayer/func_80197880.s,func_80197880,0x80197880,0x56 -asm/non_matchings/code/audio_seqplayer/func_801979D8.s,func_801979D8,0x801979D8,0x1F -asm/non_matchings/code/audio_seqplayer/func_80197A54.s,func_80197A54,0x80197A54,0x14 +asm/non_matchings/code/audio_seqplayer/AudioSeq_GetScriptControlFlowArgument.s,AudioSeq_GetScriptControlFlowArgument,0x801974D0,0x1A +asm/non_matchings/code/audio_seqplayer/AudioSeq_HandleScriptFlowControl.s,AudioSeq_HandleScriptFlowControl,0x80197538,0x77 +asm/non_matchings/code/audio_seqplayer/AudioSeq_InitSequenceChannel.s,AudioSeq_InitSequenceChannel,0x80197714,0x5B +asm/non_matchings/code/audio_seqplayer/AudioSeq_SeqChannelSetLayer.s,AudioSeq_SeqChannelSetLayer,0x80197880,0x56 +asm/non_matchings/code/audio_seqplayer/AudioSeq_SeqLayerDisable.s,AudioSeq_SeqLayerDisable,0x801979D8,0x1F +asm/non_matchings/code/audio_seqplayer/AudioSeq_SeqLayerFree.s,AudioSeq_SeqLayerFree,0x80197A54,0x14 asm/non_matchings/code/audio_seqplayer/AudioSeq_SequenceChannelDisable.s,AudioSeq_SequenceChannelDisable,0x80197AA4,0x1C -asm/non_matchings/code/audio_seqplayer/func_80197B14.s,func_80197B14,0x80197B14,0x3E -asm/non_matchings/code/audio_seqplayer/func_80197C0C.s,func_80197C0C,0x80197C0C,0x20 -asm/non_matchings/code/audio_seqplayer/func_80197C8C.s,func_80197C8C,0x80197C8C,0x26 +asm/non_matchings/code/audio_seqplayer/AudioSeq_SequencePlayerSetupChannels.s,AudioSeq_SequencePlayerSetupChannels,0x80197B14,0x3E +asm/non_matchings/code/audio_seqplayer/AudioSeq_SequencePlayerDisableChannels.s,AudioSeq_SequencePlayerDisableChannels,0x80197C0C,0x20 +asm/non_matchings/code/audio_seqplayer/AudioSeq_SequenceChannelEnable.s,AudioSeq_SequenceChannelEnable,0x80197C8C,0x26 asm/non_matchings/code/audio_seqplayer/AudioSeq_SequencePlayerDisableAsFinished.s,AudioSeq_SequencePlayerDisableAsFinished,0x80197D24,0xA asm/non_matchings/code/audio_seqplayer/AudioSeq_SequencePlayerDisable.s,AudioSeq_SequencePlayerDisable,0x80197D4C,0x2F asm/non_matchings/code/audio_seqplayer/AudioSeq_AudioListPushBack.s,AudioSeq_AudioListPushBack,0x80197E08,0x10 asm/non_matchings/code/audio_seqplayer/AudioSeq_AudioListPopBack.s,AudioSeq_AudioListPopBack,0x80197E48,0x10 -asm/non_matchings/code/audio_seqplayer/func_80197E88.s,func_80197E88,0x80197E88,0x28 -asm/non_matchings/code/audio_seqplayer/func_80197F28.s,func_80197F28,0x80197F28,0x5 -asm/non_matchings/code/audio_seqplayer/func_80197F3C.s,func_80197F3C,0x80197F3C,0xE -asm/non_matchings/code/audio_seqplayer/func_80197F74.s,func_80197F74,0x80197F74,0x10 -asm/non_matchings/code/audio_seqplayer/func_80197FB4.s,func_80197FB4,0x80197FB4,0x47 -asm/non_matchings/code/audio_seqplayer/func_801980D0.s,func_801980D0,0x801980D0,0x23 -asm/non_matchings/code/audio_seqplayer/func_8019815C.s,func_8019815C,0x8019815C,0x40 -asm/non_matchings/code/audio_seqplayer/func_8019825C.s,func_8019825C,0x8019825C,0xF9 -asm/non_matchings/code/audio_seqplayer/func_80198640.s,func_80198640,0x80198640,0x1A8 -asm/non_matchings/code/audio_seqplayer/func_80198CE0.s,func_80198CE0,0x80198CE0,0x105 -asm/non_matchings/code/audio_seqplayer/func_801990F4.s,func_801990F4,0x801990F4,0xC -asm/non_matchings/code/audio_seqplayer/func_80199124.s,func_80199124,0x80199124,0x1D -asm/non_matchings/code/audio_seqplayer/func_80199198.s,func_80199198,0x80199198,0x2B -asm/non_matchings/code/audio_seqplayer/func_80199244.s,func_80199244,0x80199244,0x9 -asm/non_matchings/code/audio_seqplayer/func_80199268.s,func_80199268,0x80199268,0x395 -asm/non_matchings/code/audio_seqplayer/func_8019A0BC.s,func_8019A0BC,0x8019A0BC,0x260 -asm/non_matchings/code/audio_seqplayer/func_8019AA3C.s,func_8019AA3C,0x8019AA3C,0x2D -asm/non_matchings/code/audio_seqplayer/func_8019AAF0.s,func_8019AAF0,0x8019AAF0,0x14 +asm/non_matchings/code/audio_seqplayer/AudioSeq_InitLayerFreelist.s,AudioSeq_InitLayerFreelist,0x80197E88,0x28 +asm/non_matchings/code/audio_seqplayer/AudioSeq_ScriptReadU8.s,AudioSeq_ScriptReadU8,0x80197F28,0x5 +asm/non_matchings/code/audio_seqplayer/AudioSeq_ScriptReadS16.s,AudioSeq_ScriptReadS16,0x80197F3C,0xE +asm/non_matchings/code/audio_seqplayer/AudioSeq_ScriptReadCompressedU16.s,AudioSeq_ScriptReadCompressedU16,0x80197F74,0x10 +asm/non_matchings/code/audio_seqplayer/AudioSeq_SeqLayerProcessScript.s,AudioSeq_SeqLayerProcessScript,0x80197FB4,0x47 +asm/non_matchings/code/audio_seqplayer/AudioSeq_SeqLayerProcessScriptStep1.s,AudioSeq_SeqLayerProcessScriptStep1,0x801980D0,0x23 +asm/non_matchings/code/audio_seqplayer/AudioSeq_SeqLayerProcessScriptStep5.s,AudioSeq_SeqLayerProcessScriptStep5,0x8019815C,0x40 +asm/non_matchings/code/audio_seqplayer/AudioSeq_SeqLayerProcessScriptStep2.s,AudioSeq_SeqLayerProcessScriptStep2,0x8019825C,0xF9 +asm/non_matchings/code/audio_seqplayer/AudioSeq_SeqLayerProcessScriptStep4.s,AudioSeq_SeqLayerProcessScriptStep4,0x80198640,0x1A8 +asm/non_matchings/code/audio_seqplayer/AudioSeq_SeqLayerProcessScriptStep3.s,AudioSeq_SeqLayerProcessScriptStep3,0x80198CE0,0x105 +asm/non_matchings/code/audio_seqplayer/AudioSeq_SetChannelPriorities.s,AudioSeq_SetChannelPriorities,0x801990F4,0xC +asm/non_matchings/code/audio_seqplayer/AudioSeq_GetInstrument.s,AudioSeq_GetInstrument,0x80199124,0x1D +asm/non_matchings/code/audio_seqplayer/AudioSeq_SetInstrument.s,AudioSeq_SetInstrument,0x80199198,0x2B +asm/non_matchings/code/audio_seqplayer/AudioSeq_SequenceChannelSetVolume.s,AudioSeq_SequenceChannelSetVolume,0x80199244,0x9 +asm/non_matchings/code/audio_seqplayer/AudioSeq_SequenceChannelProcessScript.s,AudioSeq_SequenceChannelProcessScript,0x80199268,0x395 +asm/non_matchings/code/audio_seqplayer/AudioSeq_SequencePlayerProcessSequence.s,AudioSeq_SequencePlayerProcessSequence,0x8019A0BC,0x260 +asm/non_matchings/code/audio_seqplayer/AudioSeq_ProcessSequences.s,AudioSeq_ProcessSequences,0x8019AA3C,0x2D +asm/non_matchings/code/audio_seqplayer/AudioSeq_SkipForwardSequence.s,AudioSeq_SkipForwardSequence,0x8019AAF0,0x14 asm/non_matchings/code/audio_seqplayer/AudioSeq_ResetSequencePlayer.s,AudioSeq_ResetSequencePlayer,0x8019AB40,0x34 asm/non_matchings/code/audio_seqplayer/AudioSeq_InitSequencePlayerChannels.s,AudioSeq_InitSequencePlayerChannels,0x8019AC10,0x37 -asm/non_matchings/code/audio_seqplayer/func_8019ACEC.s,func_8019ACEC,0x8019ACEC,0x34 +asm/non_matchings/code/audio_seqplayer/AudioSeq_InitSequencePlayer.s,AudioSeq_InitSequencePlayer,0x8019ACEC,0x34 asm/non_matchings/code/audio_seqplayer/AudioSeq_InitSequencePlayers.s,AudioSeq_InitSequencePlayers,0x8019ADBC,0x21 asm/non_matchings/code/code_8019AE40/func_8019AE40.s,func_8019AE40,0x8019AE40,0x1C asm/non_matchings/code/code_8019AEC0/func_8019AEC0.s,func_8019AEC0,0x8019AEC0,0x10