From e989cb7ace48435ef1de1ea10f8e81c61a8a46e2 Mon Sep 17 00:00:00 2001 From: engineer124 <47598039+engineer124@users.noreply.github.com> Date: Sat, 4 Jun 2022 05:59:02 +1000 Subject: [PATCH] Audio Misc Docs and Cleanup (#1221) * Audio Cleanup * more * missed one * Audio docs imported from MM * Suggestions from Discord * Small fix * Fix sizes in z64audio.h * numSamples * Cleanup comments * Revert overlap with soundFont PR * revert Audio_AdsrUpdate cleanup (move to different PR) * PR Suggestion * Mainly typos * PR suggestion, vol -> volume * Better description * Name sampling frequency * A good number of PR suggestions * Missed a suggestion * More PR Suggestions Co-authored-by: fig02 --- include/functions.h | 10 +- include/variables.h | 4 +- include/z64audio.h | 210 ++++++----- src/code/audio_data.c | 4 +- src/code/audio_effects.c | 37 +- src/code/audio_heap.c | 743 ++++++++++++++++++++----------------- src/code/audio_load.c | 504 +++++++++++++------------ src/code/audio_playback.c | 115 +++--- src/code/audio_seqplayer.c | 67 +++- src/code/audio_synthesis.c | 183 +++++---- src/code/code_800E4FE0.c | 195 ++++++---- src/code/code_800EC960.c | 12 +- 12 files changed, 1177 insertions(+), 907 deletions(-) diff --git a/include/functions.h b/include/functions.h index 8a19801ff7..4a95aeec22 100644 --- a/include/functions.h +++ b/include/functions.h @@ -1806,8 +1806,8 @@ void* AudioLoad_DmaSampleData(u32 devAddr, u32 size, s32 arg2, u8* dmaIndexRef, void AudioLoad_InitSampleDmaBuffers(s32 arg0); s32 AudioLoad_IsFontLoadComplete(s32 fontId); s32 AudioLoad_IsSeqLoadComplete(s32 seqId); -void AudioLoad_SetFontLoadStatus(s32 fontId, s32 status); -void AudioLoad_SetSeqLoadStatus(s32 seqId, s32 status); +void AudioLoad_SetFontLoadStatus(s32 fontId, s32 loadStatus); +void AudioLoad_SetSeqLoadStatus(s32 seqId, s32 loadStatus); void AudioLoad_SyncLoadSeqParts(s32 seqId, s32 arg1); s32 AudioLoad_SyncLoadInstrument(s32 fontId, s32 instId, s32 drumId); void AudioLoad_AsyncLoadSeq(s32 seqId, s32 arg1, s32 retData, OSMesgQueue* retQueue); @@ -1821,11 +1821,11 @@ void AudioLoad_ProcessLoads(s32 resetStatus); void AudioLoad_SetDmaHandler(DmaHandler callback); void AudioLoad_Init(void* heap, u32 heapSize); void AudioLoad_InitSlowLoads(void); -s32 AudioLoad_SlowLoadSample(s32 fontId, s32 instId, s8* isDone); -s32 AudioLoad_SlowLoadSeq(s32 seqId, u8* ramAddr, s8* isDone); +s32 AudioLoad_SlowLoadSample(s32 fontId, s32 instId, s8* status); +s32 AudioLoad_SlowLoadSeq(s32 seqId, u8* ramAddr, s8* status); void AudioLoad_InitAsyncLoads(void); void AudioLoad_LoadPermanentSamples(void); -void AudioLoad_ScriptLoad(s32 tableType, s32 id, s8* isDone); +void AudioLoad_ScriptLoad(s32 tableType, s32 id, s8* status); void AudioLoad_ProcessScriptLoads(void); void AudioLoad_InitScriptLoads(void); AudioTask* func_800E4FE0(void); diff --git a/include/variables.h b/include/variables.h index bcd4a309ca..083426294b 100644 --- a/include/variables.h +++ b/include/variables.h @@ -126,8 +126,8 @@ extern s16 D_8012FBA8[]; extern f32 gHeadsetPanVolume[128]; extern f32 gStereoPanVolume[128]; extern f32 gDefaultPanVolume[128]; -extern s16 sLowPassFilterData[16*8]; -extern s16 sHighPassFilterData[15*8]; +extern s16 gLowPassFilterData[16 * 8]; +extern s16 gHighPassFilterData[15 * 8]; extern s32 gAudioContextInitalized; extern u8 gIsLargeSoundBank[7]; extern u8 gChannelsPerBank[4][7]; diff --git a/include/z64audio.h b/include/z64audio.h index 4a25b9f72d..023fece0a6 100644 --- a/include/z64audio.h +++ b/include/z64audio.h @@ -59,6 +59,15 @@ typedef enum { /* 3 */ CACHE_PERMANENT } AudioCacheType; +typedef enum { + /* 0 */ LOAD_STATUS_NOT_LOADED, // the entry data is not loaded + /* 1 */ LOAD_STATUS_IN_PROGRESS, // the entry data is being loaded asynchronously + /* 2 */ LOAD_STATUS_COMPLETE, // the entry data is loaded, it may be discarded if not stored persistently, and either no longer in use, or the memory is needed for something else + /* 3 */ LOAD_STATUS_DISCARDABLE, // the entry data is loaded, and can be discarded + /* 4 */ LOAD_STATUS_MAYBE_DISCARDABLE, // only for font table entries, like COMPLETE but prefer discarding it over a COMPLETE entry + /* 5 */ LOAD_STATUS_PERMANENTLY_LOADED // the entry data is loaded in the permanent pool, it won't be discarded +} AudioLoadStatus; + typedef s32 (*DmaHandler)(OSPiHandle* handle, OSIoMesg* mb, s32 direction); struct Note; @@ -88,7 +97,7 @@ typedef struct NotePool { /* 0x10 */ AudioListItem decaying; /* 0x20 */ AudioListItem releasing; /* 0x30 */ AudioListItem active; -} NotePool; +} NotePool; // size = 0x40 // Pitch sliding by up to one octave in the positive direction. Negative // direction is "supported" by setting extent to be negative. The code @@ -158,8 +167,8 @@ typedef struct { /* 0x005 */ s8 unk_05; /* 0x006 */ u16 windowSize; /* 0x008 */ s16 unk_08; - /* 0x00A */ s16 unk_0A; - /* 0x00C */ u16 unk_0C; + /* 0x00A */ s16 volume; + /* 0x00C */ u16 decayRatio; // determines how much reverb persists /* 0x00E */ u16 unk_0E; /* 0x010 */ s16 leakRtl; /* 0x012 */ s16 leakLtr; @@ -205,8 +214,8 @@ typedef struct { /* 0x01 */ u8 pan; /* 0x02 */ u8 loaded; /* 0x04 */ SoundFontSound sound; - /* 0x14 */ AdsrEnvelope* envelope; -} Drum; // size = 0x14 + /* 0x0C */ AdsrEnvelope* envelope; +} Drum; // size = 0x10 typedef struct { /* 0x00 */ u8 numInstruments; @@ -220,9 +229,9 @@ typedef struct { } SoundFont; // size = 0x14 typedef struct { - /* 0x00 */ u8* pc; + /* 0x00 */ u8* pc; // program counter /* 0x04 */ u8* stack[4]; - /* 0x14 */ u8 remLoopIters[4]; + /* 0x14 */ u8 remLoopIters[4]; // remaining loop iterations /* 0x18 */ u8 depth; /* 0x19 */ s8 value; } SeqScriptState; // size = 0x1C @@ -236,7 +245,7 @@ typedef struct { /* 0x000 */ u8 fontDmaInProgress : 1; /* 0x000 */ u8 recalculateVolume : 1; /* 0x000 */ u8 stopScript : 1; - /* 0x000 */ u8 unk_0b1 : 1; + /* 0x000 */ u8 applyBend : 1; /* 0x001 */ u8 state; /* 0x002 */ u8 noteAllocPolicy; /* 0x003 */ u8 muteBehavior; @@ -258,7 +267,7 @@ typedef struct { /* 0x028 */ f32 muteVolumeScale; /* 0x02C */ f32 fadeVolumeScale; /* 0x030 */ f32 appliedFadeVolume; - /* 0x034 */ f32 unk_34; + /* 0x034 */ f32 bend; /* 0x038 */ struct SequenceChannel* channels[16]; /* 0x078 */ SeqScriptState scriptState; /* 0x094 */ u8* shortNoteVelocityTable; @@ -296,7 +305,7 @@ typedef struct { /* 0x14 */ f32 target; /* 0x18 */ char unk_18[4]; /* 0x1C */ AdsrEnvelope* envelope; -} AdsrState; +} AdsrState; // size = 0x20 typedef struct { /* 0x00 */ u8 unused : 2; @@ -305,16 +314,16 @@ typedef struct { /* 0x00 */ u8 strongLeft : 1; /* 0x00 */ u8 stereoHeadsetEffects : 1; /* 0x00 */ u8 usesHeadsetPanEffects : 1; -} StereoData; +} StereoData; // size = 0x1 typedef union { /* 0x00 */ StereoData s; /* 0x00 */ u8 asByte; -} Stereo; +} Stereo; // size = 0x1 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 */ Stereo stereo; /* 0x04 */ u8 unk_4; @@ -353,7 +362,7 @@ 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; @@ -419,7 +428,7 @@ typedef struct SequenceLayer { /* 0x20 */ Portamento portamento; /* 0x2C */ struct Note* note; /* 0x30 */ f32 freqScale; - /* 0x34 */ f32 unk_34; + /* 0x34 */ f32 bend; /* 0x38 */ f32 velocitySquare2; /* 0x3C */ f32 velocitySquare; // not sure which one of those corresponds to the sm64 original /* 0x40 */ f32 noteVelocity; @@ -487,8 +496,8 @@ typedef struct { /* 0x18 */ SequenceLayer* wantedParentLayer; /* 0x1C */ NoteAttributes attributes; /* 0x40 */ AdsrState adsr; - // may contain portamento, vibratoState, if those are not part of Note itself -} NotePlaybackState; + // Majora's Mask suggests this struct contains portamento, vibratoState +} NotePlaybackState; // size = 0x60 typedef struct { struct { @@ -508,7 +517,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; @@ -540,10 +549,10 @@ typedef struct Note { typedef struct { /* 0x00 */ u8 downsampleRate; /* 0x02 */ u16 windowSize; - /* 0x04 */ u16 unk_4; + /* 0x04 */ u16 decayRatio; // determines how much reverb persists /* 0x06 */ u16 unk_6; /* 0x08 */ u16 unk_8; - /* 0x0A */ u16 unk_A; + /* 0x0A */ u16 volume; /* 0x0C */ u16 leakRtl; /* 0x0E */ u16 leakLtr; /* 0x10 */ s8 unk_10; @@ -552,8 +561,12 @@ typedef struct { /* 0x16 */ s16 lowPassFilterCutoffRight; } ReverbSettings; // size = 0x18 +/** + * The high-level audio specifications requested when initializing or resetting the audio heap. + * The audio heap can be reset on various occasions, including on most scene transitions. + */ typedef struct { - /* 0x00 */ u32 frequency; + /* 0x00 */ u32 samplingFrequency; // Target sampling rate in Hz /* 0x04 */ u8 unk_04; /* 0x05 */ u8 numNotes; /* 0x06 */ u8 numSequencePlayers; @@ -561,23 +574,28 @@ typedef struct { /* 0x08 */ u8 unk_08; // unused, set to zero /* 0x09 */ u8 numReverbs; /* 0x0C */ ReverbSettings* reverbSettings; - /* 0x10 */ u16 sampleDmaBufSize1; - /* 0x12 */ u16 sampleDmaBufSize2; + /* 0x10 */ u16 sampleDmaBufSize1; // size of buffers in the audio misc pool to store small snippets of individual samples. Stored short-lived. + /* 0x12 */ u16 sampleDmaBufSize2; // size of buffers in the audio misc pool to store small snippets of individual samples. Stored long-lived. /* 0x14 */ u16 unk_14; - /* 0x18 */ u32 persistentSeqMem; - /* 0x1C */ u32 persistentFontMem; - /* 0x20 */ u32 persistentSampleMem; - /* 0x24 */ u32 temporarySeqMem; - /* 0x28 */ u32 temporaryFontMem; - /* 0x2C */ u32 temporarySampleMem; - /* 0x30 */ s32 persistentSampleCacheMem; - /* 0x34 */ s32 temporarySampleCacheMem; + /* 0x18 */ u32 persistentSeqCacheSize; // size of cache on audio pool to store sequences persistently + /* 0x1C */ u32 persistentFontCacheSize; // size of cache on audio pool to store soundFonts persistently + /* 0x20 */ u32 persistentSampleBankCacheSize; // size of cache on audio pool to store entire sample banks persistently + /* 0x24 */ u32 temporarySeqCacheSize; // size of cache on audio pool to store sequences temporarily + /* 0x28 */ u32 temporaryFontCacheSize; // size of cache on audio pool to store soundFonts temporarily + /* 0x2C */ u32 temporarySampleBankCacheSize; // size of cache on audio pool to store entire sample banks temporarily + /* 0x30 */ s32 persistentSampleCacheSize; // size of cache in the audio misc pool to store individual samples persistently + /* 0x34 */ s32 temporarySampleCacheSize; // size of cache in the audio misc pool to store individual samples temporarily } AudioSpec; // size = 0x38 +/** + * The audio buffer stores the fully processed digital audio before it is sent to the audio interface (AI), then to the + * digital-analog converter (DAC), then to play on the speakers. The audio buffer is written to by the rsp after + * processing audio commands. This struct parameterizes that buffer. + */ typedef struct { /* 0x00 */ s16 specUnk4; - /* 0x02 */ u16 frequency; - /* 0x04 */ u16 aiFrequency; + /* 0x02 */ u16 samplingFrequency; // Target sampling rate in Hz + /* 0x04 */ u16 aiSamplingFrequency; // True sampling rate of the audio interface (AI), see `osAiSetFrequency` /* 0x06 */ s16 samplesPerFrameTarget; /* 0x08 */ s16 maxAiBufferLength; /* 0x0A */ s16 minAiBufferLength; @@ -592,20 +610,29 @@ typedef struct { /* 0x24 */ f32 updatesPerFrameScaled; // updatesPerFrame scaled down by a factor of 4 } AudioBufferParameters; // size = 0x28 +/** + * Meta-data associated with a pool (contained within the Audio Heap) + */ typedef struct { - /* 0x0 */ u8* start; - /* 0x4 */ u8* cur; - /* 0x8 */ s32 size; - /* 0xC */ s32 count; + /* 0x0 */ u8* startRamAddr; // start addr of the pool + /* 0x4 */ u8* curRamAddr; // address of the next available memory for allocation + /* 0x8 */ s32 size; // size of the pool + /* 0xC */ s32 numEntries; // number of entries allocated to the pool } AudioAllocPool; // size = 0x10 +/** + * Audio cache entry data to store a single entry containing either a sequence, soundfont, or entire sample banks + */ typedef struct { - /* 0x0 */ u8* ptr; + /* 0x0 */ u8* ramAddr; /* 0x4 */ u32 size; /* 0x8 */ s16 tableType; /* 0xA */ s16 id; } AudioCacheEntry; // size = 0xC +/** + * Audio cache entry data to store a single entry containing an individual sample + */ typedef struct { /* 0x00 */ s8 inUse; /* 0x01 */ s8 origMedium; @@ -616,10 +643,13 @@ typedef struct { /* 0x10 */ u32 size; } SampleCacheEntry; // size = 0x14 +/** + * Audio cache entry data to store individual samples + */ typedef struct { /* 0x000 */ AudioAllocPool pool; /* 0x010 */ SampleCacheEntry entries[32]; - /* 0x290 */ s32 size; + /* 0x290 */ s32 numEntries; } AudioSampleCache; // size = 0x294 typedef struct { @@ -641,22 +671,21 @@ typedef struct { } AudioCache; // size = 0x110 typedef struct { - u32 wantPersistent; - u32 wantTemporary; -} AudioPoolSplit2; // size = 0x8 + /* 0x0 */ u32 persistentCommonPoolSize; + /* 0x4 */ u32 temporaryCommonPoolSize; +} AudioCachePoolSplit; // size = 0x8 typedef struct { - u32 wantSeq; - u32 wantFont; - u32 wantSample; -} AudioPoolSplit3; // size = 0xC + /* 0x0 */ u32 seqCacheSize; + /* 0x4 */ u32 fontCacheSize; + /* 0x8 */ u32 sampleBankCacheSize; +} AudioCommonPoolSplit; // size = 0xC typedef struct { - u32 wantSeq; - u32 wantFont; - u32 wantSample; - u32 wantCustom; -} AudioPoolSplit4; // size = 0x10 + /* 0x0 */ u32 miscPoolSize; + /* 0x4 */ u32 unkSizes[2]; + /* 0xC */ u32 cachePoolSize; +} AudioSessionPoolSplit; // size = 0x10 typedef struct { /* 0x00 */ u32 endAndMediumKey; @@ -666,8 +695,11 @@ typedef struct { /* 0x10 */ s32 isFree; } AudioPreloadReq; // size = 0x14 +/** + * Audio commands used to transfer audio requests from the graph thread to the audio thread + */ typedef struct { - union{ + /* 0x0 */ union{ u32 opArgs; struct { u8 op; @@ -676,7 +708,7 @@ typedef struct { u8 arg2; }; }; - union { + /* 0x4 */ union { void* data; f32 asFloat; s32 asInt; @@ -685,7 +717,7 @@ typedef struct { u8 asUbyte; u32 asUInt; }; -} AudioCmd; +} AudioCmd; // size = 0x8 typedef struct { /* 0x00 */ s8 status; @@ -712,9 +744,9 @@ typedef struct { /* 0x08 */ s32 curDevAddr; /* 0x0C */ u8* curRamAddr; /* 0x10 */ u8* ramAddr; - /* 0x14 */ s32 status; + /* 0x14 */ s32 state; /* 0x18 */ s32 bytesRemaining; - /* 0x1C */ s8* isDone; + /* 0x1C */ s8* status; // write-only /* 0x20 */ SoundFontSample sample; /* 0x30 */ OSMesgQueue msgQueue; /* 0x48 */ OSMesg msg; @@ -759,7 +791,7 @@ typedef struct { typedef struct { /* 0x0000 */ char unk_0000; /* 0x0001 */ s8 numSynthesisReverbs; - /* 0x0002 */ u16 unk_2; + /* 0x0002 */ u16 unk_2; // reads from audio spec unk_14, never used, always set to 0x7FFF /* 0x0004 */ u16 unk_4; /* 0x0006 */ char unk_0006[0x0A]; /* 0x0010 */ s16* curLoadedBook; @@ -794,10 +826,10 @@ typedef struct { /* 0x2628 */ s32 unused2628; /* 0x262C */ u8 sampleDmaReuseQueue1[0x100]; // read pos <= write pos, wrapping mod 256 /* 0x272C */ u8 sampleDmaReuseQueue2[0x100]; - /* 0x282C */ u8 sampleDmaReuseQueue1RdPos; - /* 0x282D */ u8 sampleDmaReuseQueue2RdPos; - /* 0x282E */ u8 sampleDmaReuseQueue1WrPos; - /* 0x282F */ u8 sampleDmaReuseQueue2WrPos; + /* 0x282C */ u8 sampleDmaReuseQueue1RdPos; // Read position for short-lived sampleDma + /* 0x282D */ u8 sampleDmaReuseQueue2RdPos; // Read position for long-lived sampleDma + /* 0x282E */ u8 sampleDmaReuseQueue1WrPos; // Write position for short-lived sampleDma + /* 0x282F */ u8 sampleDmaReuseQueue2WrPos; // Write position for long-lived sampleDma /* 0x2830 */ AudioTable* sequenceTable; /* 0x2834 */ AudioTable* soundFontTable; /* 0x2838 */ AudioTable* sampleBankTable; @@ -814,13 +846,13 @@ typedef struct { /* 0x2894 */ s32 numNotes; /* 0x2898 */ s16 tempoInternalToExternal; /* 0x289A */ s8 soundMode; - /* 0x289C */ s32 totalTaskCount; + /* 0x289C */ s32 totalTaskCount; // The total number of times the top-level function on the audio thread has run since audio was initialized /* 0x28A0 */ s32 curAudioFrameDmaCount; - /* 0x28A4 */ s32 rspTaskIdx; - /* 0x28A8 */ s32 curAIBufIdx; - /* 0x28AC */ Acmd* abiCmdBufs[2]; - /* 0x28B4 */ Acmd* curAbiCmdBuf; - /* 0x28B8 */ AudioTask* currTask; + /* 0x28A4 */ s32 rspTaskIndex; + /* 0x28A8 */ s32 curAiBufIndex; + /* 0x28AC */ Acmd* abiCmdBufs[2]; // Pointer to audio heap where the audio binary interface command lists (for the rsp) are stored. Two lists that alternate every frame + /* 0x28B4 */ Acmd* curAbiCmdBuf; // Pointer to the currently active abiCmdBufs + /* 0x28B8 */ AudioTask* curTask; /* 0x28BC */ char unk_28BC[0x4]; /* 0x28C0 */ AudioTask rspTask[2]; /* 0x2960 */ f32 unk_2960; @@ -831,25 +863,25 @@ typedef struct { /* 0x2980 */ s32 audioErrorFlags; /* 0x2984 */ volatile u32 resetTimer; /* 0x2988 */ char unk_2988[0x8]; - /* 0x2990 */ AudioAllocPool audioSessionPool; - /* 0x29A0 */ AudioAllocPool externalPool; - /* 0x29B0 */ AudioAllocPool audioInitPool; - /* 0x29C0 */ AudioAllocPool notesAndBuffersPool; + /* 0x2990 */ AudioAllocPool audioSessionPool; // A sub-pool to main pool, contains all sub-pools and data that changes every audio reset + /* 0x29A0 */ AudioAllocPool externalPool; // pool allocated externally to the audio heap. Never used in game + /* 0x29B0 */ AudioAllocPool audioInitPool;// A sub-pool to the main pool, contains all sub-pools and data that persists every audio reset + /* 0x29C0 */ AudioAllocPool miscPool; // A sub-pool to the session pool. /* 0x29D0 */ char unk_29D0[0x20]; // probably two unused pools - /* 0x29F0 */ AudioAllocPool cachePool; - /* 0x2A00 */ AudioAllocPool persistentCommonPool; - /* 0x2A10 */ AudioAllocPool temporaryCommonPool; - /* 0x2A20 */ AudioCache seqCache; - /* 0x2B30 */ AudioCache fontCache; - /* 0x2C40 */ AudioCache sampleBankCache; - /* 0x2D50 */ AudioAllocPool permanentPool; - /* 0x2D60 */ AudioCacheEntry permanentCache[32]; - /* 0x2EE0 */ AudioSampleCache persistentSampleCache; - /* 0x3174 */ AudioSampleCache temporarySampleCache; - /* 0x3408 */ AudioPoolSplit4 sessionPoolSplit; - /* 0x3418 */ AudioPoolSplit2 cachePoolSplit; - /* 0x3420 */ AudioPoolSplit3 persistentCommonPoolSplit; - /* 0x342C */ AudioPoolSplit3 temporaryCommonPoolSplit; + /* 0x29F0 */ AudioAllocPool cachePool; // The common pool for cache entries + /* 0x2A00 */ AudioAllocPool persistentCommonPool; // A sub-pool to the cache pool, contains caches for data stored persistently + /* 0x2A10 */ AudioAllocPool temporaryCommonPool; // A sub-pool to the cache pool, contains caches for data stored temporarily + /* 0x2A20 */ AudioCache seqCache; // Cache to store sequences + /* 0x2B30 */ AudioCache fontCache; // Cache to store soundFonts + /* 0x2C40 */ AudioCache sampleBankCache; // Cache for loading entire sample banks + /* 0x2D50 */ AudioAllocPool permanentPool; // Pool to store audio data that is always loaded. Used for sfxs + /* 0x2D60 */ AudioCacheEntry permanentCache[32]; // individual entries to the permanent pool + /* 0x2EE0 */ AudioSampleCache persistentSampleCache; // Stores individual samples persistently + /* 0x3174 */ AudioSampleCache temporarySampleCache; // Stores individual samples temporarily + /* 0x3408 */ AudioSessionPoolSplit sessionPoolSplit; // splits session pool into the cache pool and misc pool + /* 0x3418 */ AudioCachePoolSplit cachePoolSplit; // splits cache pool into the persistent & temporary common pools + /* 0x3420 */ AudioCommonPoolSplit persistentCommonPoolSplit;// splits persistent common pool into caches for sequences, soundFonts, sample banks + /* 0x342C */ AudioCommonPoolSplit temporaryCommonPoolSplit; // splits temporary common pool into caches for sequences, soundFonts, sample banks /* 0x3438 */ u8 sampleFontLoadStatus[0x30]; /* 0x3468 */ u8 fontLoadStatus[0x30]; /* 0x3498 */ u8 seqLoadStatus[0x80]; @@ -879,12 +911,12 @@ typedef struct { /* 0x5C38 */ OSMesg taskStartMsgBuf[1]; /* 0x5C3C */ OSMesg audioResetMsgBuf[1]; /* 0x5C40 */ OSMesg cmdProcMsgBuf[4]; - /* 0x5C50 */ AudioCmd cmdBuf[0x100]; + /* 0x5C50 */ AudioCmd cmdBuf[0x100]; // Audio commands used to transfer audio requests from the graph thread to the audio thread } AudioContext; // size = 0x6450 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 */ Stereo stereo; /* 0x04 */ f32 frequency; @@ -896,8 +928,8 @@ typedef struct { } NoteSubAttributes; // size = 0x18 typedef struct { - /* 0x00 */ u32 heapSize; - /* 0x04 */ u32 initPoolSize; + /* 0x00 */ u32 heapSize; // total number of bytes allocated to the audio heap. Must be <= the size of `gAudioHeap` (ideally about the same size) + /* 0x04 */ u32 initPoolSize; // The entire audio heap is split into two pools. /* 0x08 */ u32 permanentPoolSize; } AudioContextInitSizes; // size = 0xC diff --git a/src/code/audio_data.c b/src/code/audio_data.c index 4798ea47c8..ed0ecb6995 100644 --- a/src/code/audio_data.c +++ b/src/code/audio_data.c @@ -625,7 +625,7 @@ f32 gDefaultPanVolume[] = { 0.086471f, 0.074143f, 0.061803f, 0.049454f, 0.037097f, 0.024734f, 0.012368f, 0.0f, }; -s16 sLowPassFilterData[16 * 8] = { +s16 gLowPassFilterData[16 * 8] = { /* 0x0 */ 0, 0, 0, 32767, 0, 0, 0, 0, // Identity filter (delta function) /* 0x1 */ 3854, 4188, 4398, 4469, 4398, 4188, 3854, 3416, /* 0x2 */ 3415, 4314, 4915, 5126, 4915, 4314, 3415, 2351, @@ -644,7 +644,7 @@ s16 sLowPassFilterData[16 * 8] = { /* 0xF */ 841, -853, 863, 26829, 863, -853, 841, -820, }; -s16 sHighPassFilterData[15 * 8] = { +s16 gHighPassFilterData[15 * 8] = { /* 0x0 */ -289, -291, -289, 30736, -289, -291, -289, -290, /* 0x1 */ -464, -467, -467, 29506, -467, -467, -464, -463, /* 0x2 */ -662, -670, -672, 28101, -672, -670, -662, -656, diff --git a/src/code/audio_effects.c b/src/code/audio_effects.c index d1e860df8b..84fde3a305 100644 --- a/src/code/audio_effects.c +++ b/src/code/audio_effects.c @@ -1,7 +1,7 @@ #include "ultra64.h" #include "global.h" -void Audio_SequenceChannelProcessSound(SequenceChannel* channel, s32 recalculateVolume, s32 b) { +void Audio_SequenceChannelProcessSound(SequenceChannel* channel, s32 recalculateVolume, s32 applyBend) { f32 channelVolume; f32 chanFreqScale; s32 i; @@ -19,13 +19,14 @@ void Audio_SequenceChannelProcessSound(SequenceChannel* channel, s32 recalculate } chanFreqScale = channel->freqScale; - if (b != 0) { - chanFreqScale *= channel->seqPlayer->unk_34; + if (applyBend) { + chanFreqScale *= channel->seqPlayer->bend; channel->changes.s.freqScale = true; } for (i = 0; i < 4; i++) { SequenceLayer* layer = channel->layers[i]; + if (layer != NULL && layer->enabled && layer->note != NULL) { if (layer->notePropertiesNeedInit) { layer->noteFreqScale = layer->freqScale * chanFreqScale; @@ -58,11 +59,12 @@ void Audio_SequencePlayerProcessSound(SequencePlayer* seqPlayer) { if (seqPlayer->fadeVolume > 1.0f) { seqPlayer->fadeVolume = 1.0f; } - if (seqPlayer->fadeVolume < 0) { - seqPlayer->fadeVolume = 0; + if (seqPlayer->fadeVolume < 0.0f) { + seqPlayer->fadeVolume = 0.0f; } - if (--seqPlayer->fadeTimer == 0 && seqPlayer->state == 2) { + seqPlayer->fadeTimer--; + if (seqPlayer->fadeTimer == 0 && seqPlayer->state == 2) { AudioSeq_SequencePlayerDisable(seqPlayer); return; } @@ -74,31 +76,34 @@ void Audio_SequencePlayerProcessSound(SequencePlayer* seqPlayer) { for (i = 0; i < 16; i++) { if (seqPlayer->channels[i]->enabled == 1) { - Audio_SequenceChannelProcessSound(seqPlayer->channels[i], seqPlayer->recalculateVolume, seqPlayer->unk_0b1); + Audio_SequenceChannelProcessSound(seqPlayer->channels[i], seqPlayer->recalculateVolume, + seqPlayer->applyBend); } } seqPlayer->recalculateVolume = false; } -f32 Audio_GetPortamentoFreqScale(Portamento* p) { +f32 Audio_GetPortamentoFreqScale(Portamento* portamento) { u32 loResCur; - f32 result; + f32 portamentoFreq; - p->cur += p->speed; - loResCur = (p->cur >> 8) & 0xFF; + portamento->cur += portamento->speed; + loResCur = (portamento->cur >> 8) & 0xFF; if (loResCur >= 127) { loResCur = 127; - p->mode = 0; + portamento->mode = 0; } - result = 1.0f + p->extent * (gBendPitchOneOctaveFrequencies[loResCur + 128] - 1.0f); - return result; + portamentoFreq = 1.0f + portamento->extent * (gBendPitchOneOctaveFrequencies[loResCur + 128] - 1.0f); + + return portamentoFreq; } s16 Audio_GetVibratoPitchChange(VibratoState* vib) { s32 index; + vib->time += (s32)vib->rate; index = (vib->time >> 10) & 0x3F; return vib->curve[index]; @@ -116,7 +121,7 @@ f32 Audio_GetVibratoFreqScale(VibratoState* vib) { if (vib->delay != 0) { vib->delay--; - return 1; + return 1.0f; } //! @bug this probably meant to compare with gAudioContext.sequenceChannelNone. @@ -151,7 +156,7 @@ f32 Audio_GetVibratoFreqScale(VibratoState* vib) { } } - if (vib->extent == 0) { + if (vib->extent == 0.0f) { return 1.0f; } diff --git a/src/code/audio_heap.c b/src/code/audio_heap.c index 82d1a2e951..b498227117 100644 --- a/src/code/audio_heap.c +++ b/src/code/audio_heap.c @@ -50,20 +50,20 @@ void AudioHeap_ResetLoadStatus(void) { s32 i; for (i = 0; i < 0x30; i++) { - if (gAudioContext.fontLoadStatus[i] != 5) { - gAudioContext.fontLoadStatus[i] = 0; + if (gAudioContext.fontLoadStatus[i] != LOAD_STATUS_PERMANENTLY_LOADED) { + gAudioContext.fontLoadStatus[i] = LOAD_STATUS_NOT_LOADED; } } for (i = 0; i < 0x30; i++) { - if (gAudioContext.sampleFontLoadStatus[i] != 5) { - gAudioContext.sampleFontLoadStatus[i] = 0; + if (gAudioContext.sampleFontLoadStatus[i] != LOAD_STATUS_PERMANENTLY_LOADED) { + gAudioContext.sampleFontLoadStatus[i] = LOAD_STATUS_NOT_LOADED; } } for (i = 0; i < 0x80; i++) { - if (gAudioContext.seqLoadStatus[i] != 5) { - gAudioContext.seqLoadStatus[i] = 0; + if (gAudioContext.seqLoadStatus[i] != LOAD_STATUS_PERMANENTLY_LOADED) { + gAudioContext.seqLoadStatus[i] = LOAD_STATUS_NOT_LOADED; } } } @@ -113,139 +113,155 @@ void AudioHeap_DiscardSequence(s32 seqId) { } } -void AudioHeap_WritebackDCache(void* mem, u32 size) { - Audio_WritebackDCache(mem, size); +/** + * Perform a writeback from the data cache to the ram. + */ +void AudioHeap_WritebackDCache(void* ramAddr, u32 size) { + Audio_WritebackDCache(ramAddr, size); } +/** + * Attempt to allocate space externally to the audio heap. If no external pool is available, + * then allocate space on the pool provided in the argument. + * The newly allocated space is zero'ed + */ void* AudioHeap_AllocZeroedAttemptExternal(AudioAllocPool* pool, u32 size) { - void* ret = NULL; + void* ramAddr = NULL; - if (gAudioContext.externalPool.start != 0) { - ret = AudioHeap_AllocZeroed(&gAudioContext.externalPool, size); + if (gAudioContext.externalPool.startRamAddr != NULL) { + ramAddr = AudioHeap_AllocZeroed(&gAudioContext.externalPool, size); } - if (ret == NULL) { - ret = AudioHeap_AllocZeroed(pool, size); + if (ramAddr == NULL) { + ramAddr = AudioHeap_AllocZeroed(pool, size); } - return ret; + return ramAddr; } void* AudioHeap_AllocAttemptExternal(AudioAllocPool* pool, u32 size) { - void* ret = NULL; + void* ramAddr = NULL; - if (gAudioContext.externalPool.start != NULL) { - ret = AudioHeap_Alloc(&gAudioContext.externalPool, size); + if (gAudioContext.externalPool.startRamAddr != NULL) { + ramAddr = AudioHeap_Alloc(&gAudioContext.externalPool, size); } - if (ret == NULL) { - ret = AudioHeap_Alloc(pool, size); + if (ramAddr == NULL) { + ramAddr = AudioHeap_Alloc(pool, size); } - return ret; + return ramAddr; } void* AudioHeap_AllocDmaMemory(AudioAllocPool* pool, u32 size) { - void* ret; + void* ramAddr = AudioHeap_Alloc(pool, size); - ret = AudioHeap_Alloc(pool, size); - if (ret != NULL) { - AudioHeap_WritebackDCache(ret, size); + if (ramAddr != NULL) { + AudioHeap_WritebackDCache(ramAddr, size); } - return ret; + return ramAddr; } void* AudioHeap_AllocDmaMemoryZeroed(AudioAllocPool* pool, u32 size) { - void* ret; + void* ramAddr; - ret = AudioHeap_AllocZeroed(pool, size); - if (ret != NULL) { - AudioHeap_WritebackDCache(ret, size); + ramAddr = AudioHeap_AllocZeroed(pool, size); + if (ramAddr != NULL) { + AudioHeap_WritebackDCache(ramAddr, size); } - return ret; + return ramAddr; } +/** + * Allocates space on a pool contained within the heap and sets all the allocated space to 0 + */ void* AudioHeap_AllocZeroed(AudioAllocPool* pool, u32 size) { - u8* ret = AudioHeap_Alloc(pool, size); + u8* ramAddr = AudioHeap_Alloc(pool, size); u8* ptr; - if (ret != NULL) { - for (ptr = ret; ptr < pool->cur; ptr++) { + if (ramAddr != NULL) { + for (ptr = ramAddr; ptr < pool->curRamAddr; ptr++) { *ptr = 0; } } - return ret; + return ramAddr; } void* AudioHeap_Alloc(AudioAllocPool* pool, u32 size) { u32 aligned = ALIGN16(size); - u8* ret = pool->cur; + u8* ramAddr = pool->curRamAddr; - if (pool->start + pool->size >= pool->cur + aligned) { - pool->cur += aligned; + if (pool->startRamAddr + pool->size >= pool->curRamAddr + aligned) { + pool->curRamAddr += aligned; } else { return NULL; } - pool->count++; - return ret; + pool->numEntries++; + return ramAddr; } -void AudioHeap_AllocPoolInit(AudioAllocPool* pool, void* mem, u32 size) { - pool->cur = pool->start = (u8*)ALIGN16((u32)mem); - pool->size = size - ((u32)mem & 0xF); - pool->count = 0; +/** + * Initialize a pool to allocate memory from the specified address, up to the specified size. + * Store the metadata of this pool in AudioAllocPool* pool + */ +void AudioHeap_AllocPoolInit(AudioAllocPool* pool, void* ramAddr, u32 size) { + pool->curRamAddr = pool->startRamAddr = (u8*)ALIGN16((u32)ramAddr); + pool->size = size - ((u32)ramAddr & 0xF); + pool->numEntries = 0; } void AudioHeap_PersistentCacheClear(AudioPersistentCache* persistent) { - persistent->pool.count = 0; + persistent->pool.numEntries = 0; persistent->numEntries = 0; - persistent->pool.cur = persistent->pool.start; + persistent->pool.curRamAddr = persistent->pool.startRamAddr; } void AudioHeap_TemporaryCacheClear(AudioTemporaryCache* temporary) { - temporary->pool.count = 0; - temporary->pool.cur = temporary->pool.start; + temporary->pool.numEntries = 0; + temporary->pool.curRamAddr = temporary->pool.startRamAddr; temporary->nextSide = 0; - temporary->entries[0].ptr = temporary->pool.start; - temporary->entries[1].ptr = temporary->pool.start + temporary->pool.size; + temporary->entries[0].ramAddr = temporary->pool.startRamAddr; + temporary->entries[1].ramAddr = temporary->pool.startRamAddr + temporary->pool.size; temporary->entries[0].id = -1; temporary->entries[1].id = -1; } void AudioHeap_ResetPool(AudioAllocPool* pool) { - pool->count = 0; - pool->cur = pool->start; + pool->numEntries = 0; + pool->curRamAddr = pool->startRamAddr; } void AudioHeap_PopCache(s32 tableType) { - AudioCache* loadedPool; + AudioCache* loadedCache; AudioAllocPool* persistentPool; AudioPersistentCache* persistent; - void* entryPtr; - u8* table; + void* entryRamAddr; + u8* loadStatus; switch (tableType) { case SEQUENCE_TABLE: - loadedPool = &gAudioContext.seqCache; - table = gAudioContext.seqLoadStatus; + loadedCache = &gAudioContext.seqCache; + loadStatus = gAudioContext.seqLoadStatus; break; + case FONT_TABLE: - loadedPool = &gAudioContext.fontCache; - table = gAudioContext.fontLoadStatus; + loadedCache = &gAudioContext.fontCache; + loadStatus = gAudioContext.fontLoadStatus; break; + case SAMPLE_TABLE: - loadedPool = &gAudioContext.sampleBankCache; - table = gAudioContext.sampleFontLoadStatus; + loadedCache = &gAudioContext.sampleBankCache; + loadStatus = gAudioContext.sampleFontLoadStatus; break; } - persistent = &loadedPool->persistent; + persistent = &loadedCache->persistent; persistentPool = &persistent->pool; if (persistent->numEntries == 0) { return; } - entryPtr = persistent->entries[persistent->numEntries - 1].ptr; - persistentPool->cur = entryPtr; - persistentPool->count--; + entryRamAddr = persistent->entries[persistent->numEntries - 1].ramAddr; + persistentPool->curRamAddr = entryRamAddr; + persistentPool->numEntries--; if (tableType == SAMPLE_TABLE) { AudioHeap_DiscardSampleBank(persistent->entries[persistent->numEntries - 1].id); @@ -253,7 +269,8 @@ void AudioHeap_PopCache(s32 tableType) { if (tableType == FONT_TABLE) { AudioHeap_DiscardFont(persistent->entries[persistent->numEntries - 1].id); } - table[persistent->entries[persistent->numEntries - 1].id] = 0; + + loadStatus[persistent->entries[persistent->numEntries - 1].id] = LOAD_STATUS_NOT_LOADED; persistent->numEntries--; } @@ -261,182 +278,195 @@ void AudioHeap_InitMainPools(s32 initPoolSize) { AudioHeap_AllocPoolInit(&gAudioContext.audioInitPool, gAudioContext.audioHeap, initPoolSize); AudioHeap_AllocPoolInit(&gAudioContext.audioSessionPool, gAudioContext.audioHeap + initPoolSize, gAudioContext.audioHeapSize - initPoolSize); - gAudioContext.externalPool.start = NULL; + gAudioContext.externalPool.startRamAddr = NULL; } -void AudioHeap_SessionPoolsInit(AudioPoolSplit4* split) { - gAudioContext.audioSessionPool.cur = gAudioContext.audioSessionPool.start; - AudioHeap_AllocPoolInit(&gAudioContext.notesAndBuffersPool, - AudioHeap_Alloc(&gAudioContext.audioSessionPool, split->wantSeq), split->wantSeq); +void AudioHeap_SessionPoolsInit(AudioSessionPoolSplit* split) { + gAudioContext.audioSessionPool.curRamAddr = gAudioContext.audioSessionPool.startRamAddr; + AudioHeap_AllocPoolInit(&gAudioContext.miscPool, + AudioHeap_Alloc(&gAudioContext.audioSessionPool, split->miscPoolSize), split->miscPoolSize); AudioHeap_AllocPoolInit(&gAudioContext.cachePool, - AudioHeap_Alloc(&gAudioContext.audioSessionPool, split->wantCustom), split->wantCustom); + AudioHeap_Alloc(&gAudioContext.audioSessionPool, split->cachePoolSize), + split->cachePoolSize); } -void AudioHeap_CachePoolInit(AudioPoolSplit2* split) { - gAudioContext.cachePool.cur = gAudioContext.cachePool.start; +void AudioHeap_CachePoolInit(AudioCachePoolSplit* split) { + gAudioContext.cachePool.curRamAddr = gAudioContext.cachePool.startRamAddr; AudioHeap_AllocPoolInit(&gAudioContext.persistentCommonPool, - AudioHeap_Alloc(&gAudioContext.cachePool, split->wantPersistent), split->wantPersistent); + AudioHeap_Alloc(&gAudioContext.cachePool, split->persistentCommonPoolSize), + split->persistentCommonPoolSize); AudioHeap_AllocPoolInit(&gAudioContext.temporaryCommonPool, - AudioHeap_Alloc(&gAudioContext.cachePool, split->wantTemporary), split->wantTemporary); + AudioHeap_Alloc(&gAudioContext.cachePool, split->temporaryCommonPoolSize), + split->temporaryCommonPoolSize); } -void AudioHeap_PersistentCachesInit(AudioPoolSplit3* split) { - gAudioContext.persistentCommonPool.cur = gAudioContext.persistentCommonPool.start; +void AudioHeap_PersistentCachesInit(AudioCommonPoolSplit* split) { + gAudioContext.persistentCommonPool.curRamAddr = gAudioContext.persistentCommonPool.startRamAddr; AudioHeap_AllocPoolInit(&gAudioContext.seqCache.persistent.pool, - AudioHeap_Alloc(&gAudioContext.persistentCommonPool, split->wantSeq), split->wantSeq); + AudioHeap_Alloc(&gAudioContext.persistentCommonPool, split->seqCacheSize), + split->seqCacheSize); AudioHeap_AllocPoolInit(&gAudioContext.fontCache.persistent.pool, - AudioHeap_Alloc(&gAudioContext.persistentCommonPool, split->wantFont), split->wantFont); + AudioHeap_Alloc(&gAudioContext.persistentCommonPool, split->fontCacheSize), + split->fontCacheSize); AudioHeap_AllocPoolInit(&gAudioContext.sampleBankCache.persistent.pool, - AudioHeap_Alloc(&gAudioContext.persistentCommonPool, split->wantSample), split->wantSample); + AudioHeap_Alloc(&gAudioContext.persistentCommonPool, split->sampleBankCacheSize), + split->sampleBankCacheSize); AudioHeap_PersistentCacheClear(&gAudioContext.seqCache.persistent); AudioHeap_PersistentCacheClear(&gAudioContext.fontCache.persistent); AudioHeap_PersistentCacheClear(&gAudioContext.sampleBankCache.persistent); } -void AudioHeap_TemporaryCachesInit(AudioPoolSplit3* split) { - gAudioContext.temporaryCommonPool.cur = gAudioContext.temporaryCommonPool.start; +void AudioHeap_TemporaryCachesInit(AudioCommonPoolSplit* split) { + gAudioContext.temporaryCommonPool.curRamAddr = gAudioContext.temporaryCommonPool.startRamAddr; AudioHeap_AllocPoolInit(&gAudioContext.seqCache.temporary.pool, - AudioHeap_Alloc(&gAudioContext.temporaryCommonPool, split->wantSeq), split->wantSeq); + AudioHeap_Alloc(&gAudioContext.temporaryCommonPool, split->seqCacheSize), + split->seqCacheSize); AudioHeap_AllocPoolInit(&gAudioContext.fontCache.temporary.pool, - AudioHeap_Alloc(&gAudioContext.temporaryCommonPool, split->wantFont), split->wantFont); + AudioHeap_Alloc(&gAudioContext.temporaryCommonPool, split->fontCacheSize), + split->fontCacheSize); AudioHeap_AllocPoolInit(&gAudioContext.sampleBankCache.temporary.pool, - AudioHeap_Alloc(&gAudioContext.temporaryCommonPool, split->wantSample), split->wantSample); + AudioHeap_Alloc(&gAudioContext.temporaryCommonPool, split->sampleBankCacheSize), + split->sampleBankCacheSize); AudioHeap_TemporaryCacheClear(&gAudioContext.seqCache.temporary); AudioHeap_TemporaryCacheClear(&gAudioContext.fontCache.temporary); AudioHeap_TemporaryCacheClear(&gAudioContext.sampleBankCache.temporary); } void* AudioHeap_AllocCached(s32 tableType, s32 size, s32 cache, s32 id) { - AudioCache* loadedPool; - AudioTemporaryCache* tp; - AudioAllocPool* pool; - void* mem; - void* ret; - u8 firstVal; - u8 secondVal; + AudioCache* loadedCache; + AudioTemporaryCache* temporaryCache; + AudioAllocPool* temporaryPool; + void* persistentRamAddr; + void* temporaryRamAddr; + u8 loadStatusEntry0; + u8 loadStatusEntry1; s32 i; - u8* table; + u8* loadStatus; s32 side; switch (tableType) { case SEQUENCE_TABLE: - loadedPool = &gAudioContext.seqCache; - table = gAudioContext.seqLoadStatus; + loadedCache = &gAudioContext.seqCache; + loadStatus = gAudioContext.seqLoadStatus; break; + case FONT_TABLE: - loadedPool = &gAudioContext.fontCache; - table = gAudioContext.fontLoadStatus; + loadedCache = &gAudioContext.fontCache; + loadStatus = gAudioContext.fontLoadStatus; break; + case SAMPLE_TABLE: - loadedPool = &gAudioContext.sampleBankCache; - table = gAudioContext.sampleFontLoadStatus; + loadedCache = &gAudioContext.sampleBankCache; + loadStatus = gAudioContext.sampleFontLoadStatus; break; } if (cache == CACHE_TEMPORARY) { - tp = &loadedPool->temporary; - pool = &tp->pool; + temporaryCache = &loadedCache->temporary; + temporaryPool = &temporaryCache->pool; - if (pool->size < size) { + if (temporaryPool->size < size) { return NULL; } - firstVal = (tp->entries[0].id == -1) ? 0 : table[tp->entries[0].id]; - secondVal = (tp->entries[1].id == -1) ? 0 : table[tp->entries[1].id]; + loadStatusEntry0 = + (temporaryCache->entries[0].id == -1) ? LOAD_STATUS_NOT_LOADED : loadStatus[temporaryCache->entries[0].id]; + loadStatusEntry1 = + (temporaryCache->entries[1].id == -1) ? LOAD_STATUS_NOT_LOADED : loadStatus[temporaryCache->entries[1].id]; if (tableType == FONT_TABLE) { - if (firstVal == 4) { + if (loadStatusEntry0 == LOAD_STATUS_MAYBE_DISCARDABLE) { for (i = 0; i < gAudioContext.numNotes; i++) { - if (gAudioContext.notes[i].playbackState.fontId == tp->entries[0].id && - gAudioContext.notes[i].noteSubEu.bitField0.enabled != 0) { + if (gAudioContext.notes[i].playbackState.fontId == temporaryCache->entries[0].id && + gAudioContext.notes[i].noteSubEu.bitField0.enabled) { break; } } if (i == gAudioContext.numNotes) { - AudioLoad_SetFontLoadStatus(tp->entries[0].id, 3); - firstVal = 3; + AudioLoad_SetFontLoadStatus(temporaryCache->entries[0].id, LOAD_STATUS_DISCARDABLE); + loadStatusEntry0 = LOAD_STATUS_DISCARDABLE; } } - if (secondVal == 4) { + if (loadStatusEntry1 == LOAD_STATUS_MAYBE_DISCARDABLE) { for (i = 0; i < gAudioContext.numNotes; i++) { - if (gAudioContext.notes[i].playbackState.fontId == tp->entries[1].id && - gAudioContext.notes[i].noteSubEu.bitField0.enabled != 0) { + if (gAudioContext.notes[i].playbackState.fontId == temporaryCache->entries[1].id && + gAudioContext.notes[i].noteSubEu.bitField0.enabled) { break; } } if (i == gAudioContext.numNotes) { - AudioLoad_SetFontLoadStatus(tp->entries[1].id, 3); - secondVal = 3; + AudioLoad_SetFontLoadStatus(temporaryCache->entries[1].id, LOAD_STATUS_DISCARDABLE); + loadStatusEntry1 = LOAD_STATUS_DISCARDABLE; } } } - if (firstVal == 0) { - tp->nextSide = 0; - } else if (secondVal == 0) { - tp->nextSide = 1; - } else if (firstVal == 3 && secondVal == 3) { + if (loadStatusEntry0 == LOAD_STATUS_NOT_LOADED) { + temporaryCache->nextSide = 0; + } else if (loadStatusEntry1 == LOAD_STATUS_NOT_LOADED) { + temporaryCache->nextSide = 1; + } else if (loadStatusEntry0 == LOAD_STATUS_DISCARDABLE && loadStatusEntry1 == LOAD_STATUS_DISCARDABLE) { // Use the opposite side from last time. - } else if (firstVal == 3) { - tp->nextSide = 0; - } else if (secondVal == 3) { - tp->nextSide = 1; + } else if (loadStatusEntry0 == LOAD_STATUS_DISCARDABLE) { + temporaryCache->nextSide = 0; + } 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 (firstVal == 2) { + if (loadStatusEntry0 == LOAD_STATUS_COMPLETE) { for (i = 0; i < gAudioContext.audioBufferParameters.numSequencePlayers; i++) { - if (gAudioContext.seqPlayers[i].enabled != 0 && - gAudioContext.seqPlayers[i].seqId == tp->entries[0].id) { + if (gAudioContext.seqPlayers[i].enabled && + gAudioContext.seqPlayers[i].seqId == temporaryCache->entries[0].id) { break; } } if (i == gAudioContext.audioBufferParameters.numSequencePlayers) { - tp->nextSide = 0; + temporaryCache->nextSide = 0; goto done; } } - if (secondVal == 2) { + if (loadStatusEntry1 == LOAD_STATUS_COMPLETE) { for (i = 0; i < gAudioContext.audioBufferParameters.numSequencePlayers; i++) { - if (gAudioContext.seqPlayers[i].enabled != 0 && - gAudioContext.seqPlayers[i].seqId == tp->entries[1].id) { + if (gAudioContext.seqPlayers[i].enabled && + gAudioContext.seqPlayers[i].seqId == temporaryCache->entries[1].id) { break; } } if (i == gAudioContext.audioBufferParameters.numSequencePlayers) { - tp->nextSide = 1; + temporaryCache->nextSide = 1; goto done; } } } else if (tableType == FONT_TABLE) { - if (firstVal == 2) { + if (loadStatusEntry0 == LOAD_STATUS_COMPLETE) { for (i = 0; i < gAudioContext.numNotes; i++) { - if (gAudioContext.notes[i].playbackState.fontId == tp->entries[0].id && - gAudioContext.notes[i].noteSubEu.bitField0.enabled != 0) { + if (gAudioContext.notes[i].playbackState.fontId == temporaryCache->entries[0].id && + gAudioContext.notes[i].noteSubEu.bitField0.enabled) { break; } } if (i == gAudioContext.numNotes) { - tp->nextSide = 0; + temporaryCache->nextSide = 0; goto done; } } - if (secondVal == 2) { + if (loadStatusEntry1 == LOAD_STATUS_COMPLETE) { for (i = 0; i < gAudioContext.numNotes; i++) { - if (gAudioContext.notes[i].playbackState.fontId == tp->entries[1].id && - gAudioContext.notes[i].noteSubEu.bitField0.enabled != 0) { + if (gAudioContext.notes[i].playbackState.fontId == temporaryCache->entries[1].id && + gAudioContext.notes[i].noteSubEu.bitField0.enabled) { break; } } if (i == gAudioContext.numNotes) { - tp->nextSide = 1; + temporaryCache->nextSide = 1; goto done; } } @@ -444,19 +474,19 @@ void* AudioHeap_AllocCached(s32 tableType, s32 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 (tp->nextSide == 0) { - if (firstVal == 1) { - if (secondVal == 1) { + if (temporaryCache->nextSide == 0) { + if (loadStatusEntry0 == LOAD_STATUS_IN_PROGRESS) { + if (loadStatusEntry1 == LOAD_STATUS_IN_PROGRESS) { goto fail; } - tp->nextSide = 1; + temporaryCache->nextSide = 1; } } else { - if (secondVal == 1) { - if (firstVal == 1) { + if (loadStatusEntry1 == LOAD_STATUS_IN_PROGRESS) { + if (loadStatusEntry0 == LOAD_STATUS_IN_PROGRESS) { goto fail; } - tp->nextSide = 0; + temporaryCache->nextSide = 0; } } @@ -468,84 +498,92 @@ void* AudioHeap_AllocCached(s32 tableType, s32 size, s32 cache, s32 id) { } done: - side = tp->nextSide; + side = temporaryCache->nextSide; - if (tp->entries[side].id != -1) { + if (temporaryCache->entries[side].id != -1) { if (tableType == SAMPLE_TABLE) { - AudioHeap_DiscardSampleBank(tp->entries[side].id); + AudioHeap_DiscardSampleBank(temporaryCache->entries[side].id); } - table[tp->entries[side].id] = 0; + + loadStatus[temporaryCache->entries[side].id] = LOAD_STATUS_NOT_LOADED; + if (tableType == FONT_TABLE) { - AudioHeap_DiscardFont(tp->entries[side].id); + AudioHeap_DiscardFont(temporaryCache->entries[side].id); } } switch (side) { case 0: - tp->entries[0].ptr = pool->start; - tp->entries[0].id = id; - tp->entries[0].size = size; - pool->cur = pool->start + size; + temporaryCache->entries[0].ramAddr = temporaryPool->startRamAddr; + temporaryCache->entries[0].id = id; + temporaryCache->entries[0].size = size; + temporaryPool->curRamAddr = temporaryPool->startRamAddr + size; - if (tp->entries[1].id != -1 && tp->entries[1].ptr < pool->cur) { + if (temporaryCache->entries[1].id != -1 && + temporaryCache->entries[1].ramAddr < temporaryPool->curRamAddr) { if (tableType == SAMPLE_TABLE) { - AudioHeap_DiscardSampleBank(tp->entries[1].id); + AudioHeap_DiscardSampleBank(temporaryCache->entries[1].id); } - table[tp->entries[1].id] = 0; + loadStatus[temporaryCache->entries[1].id] = LOAD_STATUS_NOT_LOADED; + switch (tableType) { case SEQUENCE_TABLE: - AudioHeap_DiscardSequence((s32)tp->entries[1].id); + AudioHeap_DiscardSequence((s32)temporaryCache->entries[1].id); break; + case FONT_TABLE: - AudioHeap_DiscardFont((s32)tp->entries[1].id); + AudioHeap_DiscardFont((s32)temporaryCache->entries[1].id); break; } - tp->entries[1].id = -1; - tp->entries[1].ptr = pool->start + pool->size; + temporaryCache->entries[1].id = -1; + temporaryCache->entries[1].ramAddr = temporaryPool->startRamAddr + temporaryPool->size; } - ret = tp->entries[0].ptr; + temporaryRamAddr = temporaryCache->entries[0].ramAddr; break; case 1: - tp->entries[1].ptr = (u8*)((u32)(pool->start + pool->size - size) & ~0xF); - tp->entries[1].id = id; - tp->entries[1].size = size; - if (tp->entries[0].id != -1 && tp->entries[1].ptr < pool->cur) { + temporaryCache->entries[1].ramAddr = + (u8*)((u32)(temporaryPool->startRamAddr + temporaryPool->size - size) & ~0xF); + temporaryCache->entries[1].id = id; + temporaryCache->entries[1].size = size; + if (temporaryCache->entries[0].id != -1 && + temporaryCache->entries[1].ramAddr < temporaryPool->curRamAddr) { if (tableType == SAMPLE_TABLE) { - AudioHeap_DiscardSampleBank(tp->entries[0].id); + AudioHeap_DiscardSampleBank(temporaryCache->entries[0].id); } - table[tp->entries[0].id] = 0; + loadStatus[temporaryCache->entries[0].id] = LOAD_STATUS_NOT_LOADED; switch (tableType) { case SEQUENCE_TABLE: - AudioHeap_DiscardSequence(tp->entries[0].id); + AudioHeap_DiscardSequence(temporaryCache->entries[0].id); break; + case FONT_TABLE: - AudioHeap_DiscardFont(tp->entries[0].id); + AudioHeap_DiscardFont(temporaryCache->entries[0].id); break; } - tp->entries[0].id = -1; - pool->cur = pool->start; + temporaryCache->entries[0].id = -1; + temporaryPool->curRamAddr = temporaryPool->startRamAddr; } - ret = tp->entries[1].ptr; + temporaryRamAddr = temporaryCache->entries[1].ramAddr; break; default: return NULL; } - tp->nextSide ^= 1; - return ret; + temporaryCache->nextSide ^= 1; + return temporaryRamAddr; } - mem = AudioHeap_Alloc(&loadedPool->persistent.pool, size); - loadedPool->persistent.entries[loadedPool->persistent.numEntries].ptr = mem; + persistentRamAddr = AudioHeap_Alloc(&loadedCache->persistent.pool, size); + loadedCache->persistent.entries[loadedCache->persistent.numEntries].ramAddr = persistentRamAddr; - if (mem == NULL) { + if (persistentRamAddr == NULL) { switch (cache) { case CACHE_EITHER: return AudioHeap_AllocCached(tableType, size, CACHE_TEMPORARY, id); @@ -556,18 +594,19 @@ void* AudioHeap_AllocCached(s32 tableType, s32 size, s32 cache, s32 id) { } } - loadedPool->persistent.entries[loadedPool->persistent.numEntries].id = id; - loadedPool->persistent.entries[loadedPool->persistent.numEntries].size = size; - return loadedPool->persistent.entries[loadedPool->persistent.numEntries++].ptr; + loadedCache->persistent.entries[loadedCache->persistent.numEntries].id = id; + loadedCache->persistent.entries[loadedCache->persistent.numEntries].size = size; + + return loadedCache->persistent.entries[loadedCache->persistent.numEntries++].ramAddr; } void* AudioHeap_SearchCaches(s32 tableType, s32 cache, s32 id) { - void* ret; + void* ramAddr; // Always search the permanent cache in addition to the regular ones. - ret = AudioHeap_SearchPermanentCache(tableType, id); - if (ret != NULL) { - return ret; + ramAddr = AudioHeap_SearchPermanentCache(tableType, id); + if (ramAddr != NULL) { + return ramAddr; } if (cache == CACHE_PERMANENT) { return NULL; @@ -577,39 +616,41 @@ void* AudioHeap_SearchCaches(s32 tableType, s32 cache, s32 id) { void* AudioHeap_SearchRegularCaches(s32 tableType, s32 cache, s32 id) { u32 i; - AudioCache* loadedPool; + AudioCache* loadedCache; AudioTemporaryCache* temporary; AudioPersistentCache* persistent; switch (tableType) { case SEQUENCE_TABLE: - loadedPool = &gAudioContext.seqCache; + loadedCache = &gAudioContext.seqCache; break; + case FONT_TABLE: - loadedPool = &gAudioContext.fontCache; + loadedCache = &gAudioContext.fontCache; break; + case SAMPLE_TABLE: - loadedPool = &gAudioContext.sampleBankCache; + loadedCache = &gAudioContext.sampleBankCache; break; } - temporary = &loadedPool->temporary; + temporary = &loadedCache->temporary; if (cache == CACHE_TEMPORARY) { if (temporary->entries[0].id == id) { temporary->nextSide = 1; - return temporary->entries[0].ptr; + return temporary->entries[0].ramAddr; } else if (temporary->entries[1].id == id) { temporary->nextSide = 0; - return temporary->entries[1].ptr; + return temporary->entries[1].ramAddr; } else { return NULL; } } - persistent = &loadedPool->persistent; + persistent = &loadedCache->persistent; for (i = 0; i < persistent->numEntries; i++) { if (persistent->entries[i].id == id) { - return persistent->entries[i].ptr; + return persistent->entries[i].ramAddr; } } @@ -657,7 +698,7 @@ void AudioHeap_ClearFilter(s16* filter) { void AudioHeap_LoadLowPassFilter(s16* filter, s32 cutoff) { s32 i; - s16* ptr = &sLowPassFilterData[8 * cutoff]; + s16* ptr = &gLowPassFilterData[8 * cutoff]; for (i = 0; i < 8; i++) { filter[i] = ptr[i]; @@ -666,7 +707,7 @@ void AudioHeap_LoadLowPassFilter(s16* filter, s32 cutoff) { void AudioHeap_LoadHighPassFilter(s16* filter, s32 cutoff) { s32 i; - s16* ptr = &sHighPassFilterData[8 * (cutoff - 1)]; + s16* ptr = &gHighPassFilterData[8 * (cutoff - 1)]; for (i = 0; i < 8; i++) { filter[i] = ptr[i]; @@ -684,8 +725,9 @@ void AudioHeap_LoadFilter(s16* filter, s32 lowPassCutoff, s32 highPassCutoff) { } else if (lowPassCutoff == 0) { AudioHeap_LoadHighPassFilter(filter, highPassCutoff); } else { - s16* ptr1 = &sLowPassFilterData[8 * lowPassCutoff]; - s16* ptr2 = &sHighPassFilterData[8 * (highPassCutoff - 1)]; + s16* ptr1 = &gLowPassFilterData[8 * lowPassCutoff]; + s16* ptr2 = &gHighPassFilterData[8 * (highPassCutoff - 1)]; + for (i = 0; i < 8; i++) { filter[i] = (ptr1[i] + ptr2[i]) / 2; } @@ -713,15 +755,17 @@ void AudioHeap_UpdateReverbs(void) { } } -void AudioHeap_ClearAiBuffers(void) { - s32 ind; +/** + * Clear the current Audio Interface Buffer + */ +void AudioHeap_ClearCurrentAiBuffer(void) { + s32 curAiBufferIndex = gAudioContext.curAiBufIndex; s32 i; - ind = gAudioContext.curAIBufIdx; - gAudioContext.aiBufLengths[ind] = gAudioContext.audioBufferParameters.minAiBufferLength; + gAudioContext.aiBufLengths[curAiBufferIndex] = gAudioContext.audioBufferParameters.minAiBufferLength; for (i = 0; i < AIBUF_LEN; i++) { - gAudioContext.aiBuffers[ind][i] = 0; + gAudioContext.aiBuffers[curAiBufferIndex][i] = 0; } } @@ -774,7 +818,7 @@ s32 AudioHeap_ResetStep(void) { break; case 2: - AudioHeap_ClearAiBuffers(); + AudioHeap_ClearCurrentAiBuffer(); if (gAudioContext.audioResetFadeOutFramesLeft != 0) { gAudioContext.audioResetFadeOutFramesLeft--; } else { @@ -797,31 +841,33 @@ s32 AudioHeap_ResetStep(void) { } if (gAudioContext.resetStatus < 3) { - return 0; + return false; } - return 1; + return true; } void AudioHeap_Init(void) { s32 pad1[4]; - s16* mem; - s32 persistentMem; - s32 temporaryMem; - s32 totalMem; - s32 wantMisc; + s16* ramAddr; + s32 persistentSize; + s32 temporarySize; + s32 cachePoolSize; + s32 miscPoolSize; OSIntMask intMask; s32 i; s32 j; s32 pad2; - AudioSpec* spec; + AudioSpec* spec = &gAudioSpecs[gAudioContext.audioResetSpecIdToLoad]; // Audio Specifications - spec = &gAudioSpecs[gAudioContext.audioResetSpecIdToLoad]; gAudioContext.sampleDmaCount = 0; - gAudioContext.audioBufferParameters.frequency = spec->frequency; - gAudioContext.audioBufferParameters.aiFrequency = osAiSetFrequency(gAudioContext.audioBufferParameters.frequency); + + // audio buffer parameters + gAudioContext.audioBufferParameters.samplingFrequency = spec->samplingFrequency; + gAudioContext.audioBufferParameters.aiSamplingFrequency = + osAiSetFrequency(gAudioContext.audioBufferParameters.samplingFrequency); gAudioContext.audioBufferParameters.samplesPerFrameTarget = - ((gAudioContext.audioBufferParameters.frequency / gAudioContext.refreshRate) + 0xF) & 0xFFF0; + ALIGN16(gAudioContext.audioBufferParameters.samplingFrequency / gAudioContext.refreshRate); gAudioContext.audioBufferParameters.minAiBufferLength = gAudioContext.audioBufferParameters.samplesPerFrameTarget - 0x10; gAudioContext.audioBufferParameters.maxAiBufferLength = @@ -833,12 +879,15 @@ void AudioHeap_Init(void) { ~7; gAudioContext.audioBufferParameters.samplesPerUpdateMax = gAudioContext.audioBufferParameters.samplesPerUpdate + 8; gAudioContext.audioBufferParameters.samplesPerUpdateMin = gAudioContext.audioBufferParameters.samplesPerUpdate - 8; - gAudioContext.audioBufferParameters.resampleRate = 32000.0f / (s32)gAudioContext.audioBufferParameters.frequency; + gAudioContext.audioBufferParameters.resampleRate = + 32000.0f / (s32)gAudioContext.audioBufferParameters.samplingFrequency; gAudioContext.audioBufferParameters.updatesPerFrameInvScaled = (1.0f / 256.0f) / gAudioContext.audioBufferParameters.updatesPerFrame; gAudioContext.audioBufferParameters.updatesPerFrameScaled = gAudioContext.audioBufferParameters.updatesPerFrame / 4.0f; gAudioContext.audioBufferParameters.updatesPerFrameInv = 1.0f / gAudioContext.audioBufferParameters.updatesPerFrame; + + // SampleDma buffer size gAudioContext.sampleDmaBufSize1 = spec->sampleDmaBufSize1; gAudioContext.sampleDmaBufSize2 = spec->sampleDmaBufSize2; @@ -853,7 +902,7 @@ void AudioHeap_Init(void) { gAudioContext.unk_2870 = gAudioContext.refreshRate; gAudioContext.unk_2870 *= gAudioContext.audioBufferParameters.updatesPerFrame; - gAudioContext.unk_2870 /= gAudioContext.audioBufferParameters.aiFrequency; + gAudioContext.unk_2870 /= gAudioContext.audioBufferParameters.aiSamplingFrequency; gAudioContext.unk_2870 /= gAudioContext.tempoInternalToExternal; gAudioContext.audioBufferParameters.specUnk4 = spec->unk_04; @@ -866,51 +915,64 @@ void AudioHeap_Init(void) { gAudioContext.audioBufferParameters.maxAiBufferLength -= 0x10; } + // Determine the length of the buffer for storing the audio command list passed to the rsp audio microcode gAudioContext.maxAudioCmds = gAudioContext.numNotes * 0x10 * gAudioContext.audioBufferParameters.updatesPerFrame + spec->numReverbs * 0x18 + 0x140; - persistentMem = spec->persistentSeqMem + spec->persistentFontMem + spec->persistentSampleMem + 0x10; - temporaryMem = spec->temporarySeqMem + spec->temporaryFontMem + spec->temporarySampleMem + 0x10; - totalMem = persistentMem + temporaryMem; - wantMisc = gAudioContext.audioSessionPool.size - totalMem - 0x100; + // Calculate sizes for various caches on the audio heap + persistentSize = + spec->persistentSeqCacheSize + spec->persistentFontCacheSize + spec->persistentSampleBankCacheSize + 0x10; + temporarySize = + spec->temporarySeqCacheSize + spec->temporaryFontCacheSize + spec->temporarySampleBankCacheSize + 0x10; + cachePoolSize = persistentSize + temporarySize; + miscPoolSize = gAudioContext.audioSessionPool.size - cachePoolSize - 0x100; - if (gAudioContext.externalPool.start != NULL) { - gAudioContext.externalPool.cur = gAudioContext.externalPool.start; + if (gAudioContext.externalPool.startRamAddr != NULL) { + gAudioContext.externalPool.curRamAddr = gAudioContext.externalPool.startRamAddr; } - gAudioContext.sessionPoolSplit.wantSeq = wantMisc; - gAudioContext.sessionPoolSplit.wantCustom = totalMem; + // Session Pool Split (split into Cache and Misc pools) + gAudioContext.sessionPoolSplit.miscPoolSize = miscPoolSize; + gAudioContext.sessionPoolSplit.cachePoolSize = cachePoolSize; AudioHeap_SessionPoolsInit(&gAudioContext.sessionPoolSplit); - gAudioContext.cachePoolSplit.wantPersistent = persistentMem; - gAudioContext.cachePoolSplit.wantTemporary = temporaryMem; + + // Cache Pool Split (split into Persistent and Temporary pools) + gAudioContext.cachePoolSplit.persistentCommonPoolSize = persistentSize; + gAudioContext.cachePoolSplit.temporaryCommonPoolSize = temporarySize; AudioHeap_CachePoolInit(&gAudioContext.cachePoolSplit); - gAudioContext.persistentCommonPoolSplit.wantSeq = spec->persistentSeqMem; - gAudioContext.persistentCommonPoolSplit.wantFont = spec->persistentFontMem; - gAudioContext.persistentCommonPoolSplit.wantSample = spec->persistentSampleMem; + + // Persistent Pool Split (split into Sequences, SoundFonts, Samples pools) + gAudioContext.persistentCommonPoolSplit.seqCacheSize = spec->persistentSeqCacheSize; + gAudioContext.persistentCommonPoolSplit.fontCacheSize = spec->persistentFontCacheSize; + gAudioContext.persistentCommonPoolSplit.sampleBankCacheSize = spec->persistentSampleBankCacheSize; AudioHeap_PersistentCachesInit(&gAudioContext.persistentCommonPoolSplit); - gAudioContext.temporaryCommonPoolSplit.wantSeq = spec->temporarySeqMem; - gAudioContext.temporaryCommonPoolSplit.wantFont = spec->temporaryFontMem; - gAudioContext.temporaryCommonPoolSplit.wantSample = spec->temporarySampleMem; + + // Temporary Pool Split (split into Sequences, SoundFonts, Samples pools) + gAudioContext.temporaryCommonPoolSplit.seqCacheSize = spec->temporarySeqCacheSize; + gAudioContext.temporaryCommonPoolSplit.fontCacheSize = spec->temporaryFontCacheSize; + gAudioContext.temporaryCommonPoolSplit.sampleBankCacheSize = spec->temporarySampleBankCacheSize; AudioHeap_TemporaryCachesInit(&gAudioContext.temporaryCommonPoolSplit); AudioHeap_ResetLoadStatus(); - gAudioContext.notes = - AudioHeap_AllocZeroed(&gAudioContext.notesAndBuffersPool, gAudioContext.numNotes * sizeof(Note)); + + // Initialize notes + gAudioContext.notes = AudioHeap_AllocZeroed(&gAudioContext.miscPool, gAudioContext.numNotes * sizeof(Note)); Audio_NoteInitAll(); Audio_InitNoteFreeList(); gAudioContext.noteSubsEu = - AudioHeap_AllocZeroed(&gAudioContext.notesAndBuffersPool, gAudioContext.audioBufferParameters.updatesPerFrame * - gAudioContext.numNotes * sizeof(NoteSubEu)); - + AudioHeap_AllocZeroed(&gAudioContext.miscPool, gAudioContext.audioBufferParameters.updatesPerFrame * + gAudioContext.numNotes * sizeof(NoteSubEu)); + // Initialize audio binary interface command list buffers for (i = 0; i != 2; i++) { - gAudioContext.abiCmdBufs[i] = AudioHeap_AllocDmaMemoryZeroed(&gAudioContext.notesAndBuffersPool, - gAudioContext.maxAudioCmds * sizeof(u64)); + gAudioContext.abiCmdBufs[i] = + AudioHeap_AllocDmaMemoryZeroed(&gAudioContext.miscPool, gAudioContext.maxAudioCmds * sizeof(u64)); } // Initialize the decay rate table for adsr - gAudioContext.adsrDecayTable = AudioHeap_Alloc(&gAudioContext.notesAndBuffersPool, 256 * sizeof(f32)); + gAudioContext.adsrDecayTable = AudioHeap_Alloc(&gAudioContext.miscPool, 256 * sizeof(f32)); AudioHeap_InitAdsrDecayTable(); + // Initialize reverbs for (i = 0; i < 4; i++) { gAudioContext.synthesisReverbs[i].useReverb = 0; } @@ -919,11 +981,12 @@ void AudioHeap_Init(void) { for (i = 0; i < gAudioContext.numSynthesisReverbs; i++) { ReverbSettings* settings = &spec->reverbSettings[i]; SynthesisReverb* reverb = &gAudioContext.synthesisReverbs[i]; + reverb->downsampleRate = settings->downsampleRate; reverb->windowSize = settings->windowSize * 64; reverb->windowSize /= reverb->downsampleRate; - reverb->unk_0C = settings->unk_4; - reverb->unk_0A = settings->unk_A; + reverb->decayRatio = settings->decayRatio; + reverb->volume = settings->volume; reverb->unk_14 = settings->unk_6 * 64; reverb->unk_16 = settings->unk_8; reverb->unk_18 = 0; @@ -933,9 +996,9 @@ void AudioHeap_Init(void) { reverb->unk_08 = settings->unk_12; reverb->useReverb = 8; reverb->leftRingBuf = - AudioHeap_AllocZeroedAttemptExternal(&gAudioContext.notesAndBuffersPool, reverb->windowSize * sizeof(s16)); + AudioHeap_AllocZeroedAttemptExternal(&gAudioContext.miscPool, reverb->windowSize * sizeof(s16)); reverb->rightRingBuf = - AudioHeap_AllocZeroedAttemptExternal(&gAudioContext.notesAndBuffersPool, reverb->windowSize * sizeof(s16)); + AudioHeap_AllocZeroedAttemptExternal(&gAudioContext.miscPool, reverb->windowSize * sizeof(s16)); reverb->nextRingBufPos = 0; reverb->unk_20 = 0; reverb->curFrame = 0; @@ -955,51 +1018,57 @@ void AudioHeap_Init(void) { if (reverb->downsampleRate != 1) { reverb->unk_0E = 0x8000 / reverb->downsampleRate; - reverb->unk_30 = AudioHeap_AllocZeroed(&gAudioContext.notesAndBuffersPool, 0x20); - reverb->unk_34 = AudioHeap_AllocZeroed(&gAudioContext.notesAndBuffersPool, 0x20); - reverb->unk_38 = AudioHeap_AllocZeroed(&gAudioContext.notesAndBuffersPool, 0x20); - reverb->unk_3C = AudioHeap_AllocZeroed(&gAudioContext.notesAndBuffersPool, 0x20); + reverb->unk_30 = AudioHeap_AllocZeroed(&gAudioContext.miscPool, 0x20); + reverb->unk_34 = AudioHeap_AllocZeroed(&gAudioContext.miscPool, 0x20); + reverb->unk_38 = AudioHeap_AllocZeroed(&gAudioContext.miscPool, 0x20); + reverb->unk_3C = AudioHeap_AllocZeroed(&gAudioContext.miscPool, 0x20); for (j = 0; j < gAudioContext.audioBufferParameters.updatesPerFrame; j++) { - mem = AudioHeap_AllocZeroedAttemptExternal(&gAudioContext.notesAndBuffersPool, 0x340); - reverb->items[0][j].toDownsampleLeft = mem; - reverb->items[0][j].toDownsampleRight = mem + 0x1A0 / sizeof(s16); - mem = AudioHeap_AllocZeroedAttemptExternal(&gAudioContext.notesAndBuffersPool, 0x340); - reverb->items[1][j].toDownsampleLeft = mem; - reverb->items[1][j].toDownsampleRight = mem + 0x1A0 / sizeof(s16); + ramAddr = AudioHeap_AllocZeroedAttemptExternal(&gAudioContext.miscPool, 0x340); + reverb->items[0][j].toDownsampleLeft = ramAddr; + reverb->items[0][j].toDownsampleRight = ramAddr + 0x1A0 / sizeof(s16); + + ramAddr = AudioHeap_AllocZeroedAttemptExternal(&gAudioContext.miscPool, 0x340); + reverb->items[1][j].toDownsampleLeft = ramAddr; + reverb->items[1][j].toDownsampleRight = ramAddr + 0x1A0 / sizeof(s16); } } if (settings->lowPassFilterCutoffLeft != 0) { - reverb->filterLeftState = AudioHeap_AllocDmaMemoryZeroed(&gAudioContext.notesAndBuffersPool, 0x40); - reverb->filterLeft = AudioHeap_AllocDmaMemory(&gAudioContext.notesAndBuffersPool, 8 * sizeof(s16)); + reverb->filterLeftState = AudioHeap_AllocDmaMemoryZeroed(&gAudioContext.miscPool, 0x40); + reverb->filterLeft = AudioHeap_AllocDmaMemory(&gAudioContext.miscPool, 8 * sizeof(s16)); AudioHeap_LoadLowPassFilter(reverb->filterLeft, settings->lowPassFilterCutoffLeft); } else { reverb->filterLeft = NULL; } if (settings->lowPassFilterCutoffRight != 0) { - reverb->filterRightState = AudioHeap_AllocDmaMemoryZeroed(&gAudioContext.notesAndBuffersPool, 0x40); - reverb->filterRight = AudioHeap_AllocDmaMemory(&gAudioContext.notesAndBuffersPool, 8 * sizeof(s16)); + reverb->filterRightState = AudioHeap_AllocDmaMemoryZeroed(&gAudioContext.miscPool, 0x40); + reverb->filterRight = AudioHeap_AllocDmaMemory(&gAudioContext.miscPool, 8 * sizeof(s16)); AudioHeap_LoadLowPassFilter(reverb->filterRight, settings->lowPassFilterCutoffRight); } else { reverb->filterRight = NULL; } } + // Initialize sequence players AudioSeq_InitSequencePlayers(); for (j = 0; j < gAudioContext.audioBufferParameters.numSequencePlayers; j++) { AudioSeq_InitSequencePlayerChannels(j); AudioSeq_ResetSequencePlayer(&gAudioContext.seqPlayers[j]); } - AudioHeap_InitSampleCaches(spec->persistentSampleCacheMem, spec->temporarySampleCacheMem); + // Initialize two additional sample caches for individual samples + AudioHeap_InitSampleCaches(spec->persistentSampleCacheSize, spec->temporarySampleCacheSize); AudioLoad_InitSampleDmaBuffers(gAudioContext.numNotes); + + // Initalize Loads gAudioContext.preloadSampleStackTop = 0; AudioLoad_InitSlowLoads(); AudioLoad_InitScriptLoads(); AudioLoad_InitAsyncLoads(); gAudioContext.unk_4 = 0x1000; AudioLoad_LoadPermanentSamples(); + intMask = osSetIntMask(OS_IM_NONE); osWritebackDCacheAll(); osSetIntMask(intMask); @@ -1008,33 +1077,31 @@ void AudioHeap_Init(void) { void* AudioHeap_SearchPermanentCache(s32 tableType, s32 id) { s32 i; - for (i = 0; i < gAudioContext.permanentPool.count; i++) { + for (i = 0; i < gAudioContext.permanentPool.numEntries; i++) { if (gAudioContext.permanentCache[i].tableType == tableType && gAudioContext.permanentCache[i].id == id) { - return gAudioContext.permanentCache[i].ptr; + return gAudioContext.permanentCache[i].ramAddr; } } return NULL; } void* AudioHeap_AllocPermanent(s32 tableType, s32 id, u32 size) { - void* ret; - s32 index; + void* ramAddr; + s32 index = gAudioContext.permanentPool.numEntries; - index = gAudioContext.permanentPool.count; - - ret = AudioHeap_Alloc(&gAudioContext.permanentPool, size); - gAudioContext.permanentCache[index].ptr = ret; - if (ret == NULL) { + ramAddr = AudioHeap_Alloc(&gAudioContext.permanentPool, size); + gAudioContext.permanentCache[index].ramAddr = ramAddr; + if (ramAddr == NULL) { return NULL; } gAudioContext.permanentCache[index].tableType = tableType; gAudioContext.permanentCache[index].id = id; gAudioContext.permanentCache[index].size = size; - //! @bug UB: missing return. "ret" is in v0 at this point, but doing an + //! @bug UB: missing return. "ramAddr" is in v0 at this point, but doing an //! explicit return uses an additional register. #ifdef AVOID_UB - return ret; + return ramAddr; #endif } @@ -1056,67 +1123,72 @@ void* AudioHeap_AllocSampleCache(u32 size, s32 fontId, void* sampleAddr, s8 medi return NULL; } -void AudioHeap_InitSampleCaches(u32 persistentSize, u32 temporarySize) { - void* mem; +/** + * Initializes the persistent and temporary caches used for individual samples. Will attempt to use heap space available + * on the external pool. If no external pool is provided, then default to using space on the misc pool. + */ +void AudioHeap_InitSampleCaches(u32 persistentSampleCacheSize, u32 temporarySampleCacheSize) { + void* ramAddr; - mem = AudioHeap_AllocAttemptExternal(&gAudioContext.notesAndBuffersPool, persistentSize); - if (mem == NULL) { + ramAddr = AudioHeap_AllocAttemptExternal(&gAudioContext.miscPool, persistentSampleCacheSize); + if (ramAddr == NULL) { gAudioContext.persistentSampleCache.pool.size = 0; } else { - AudioHeap_AllocPoolInit(&gAudioContext.persistentSampleCache.pool, mem, persistentSize); + AudioHeap_AllocPoolInit(&gAudioContext.persistentSampleCache.pool, ramAddr, persistentSampleCacheSize); } - mem = AudioHeap_AllocAttemptExternal(&gAudioContext.notesAndBuffersPool, temporarySize); - if (mem == NULL) { + ramAddr = AudioHeap_AllocAttemptExternal(&gAudioContext.miscPool, temporarySampleCacheSize); + if (ramAddr == NULL) { gAudioContext.temporarySampleCache.pool.size = 0; } else { - AudioHeap_AllocPoolInit(&gAudioContext.temporarySampleCache.pool, mem, temporarySize); + AudioHeap_AllocPoolInit(&gAudioContext.temporarySampleCache.pool, ramAddr, temporarySampleCacheSize); } - gAudioContext.persistentSampleCache.size = 0; - gAudioContext.temporarySampleCache.size = 0; + gAudioContext.persistentSampleCache.numEntries = 0; + gAudioContext.temporarySampleCache.numEntries = 0; } SampleCacheEntry* AudioHeap_AllocTemporarySampleCacheEntry(u32 size) { u8* allocAfter; u8* allocBefore; - void* mem; + void* ramAddr; s32 index; s32 i; - SampleCacheEntry* ret; + SampleCacheEntry* entry; AudioPreloadReq* preload; - AudioSampleCache* pool; - u8* start; - u8* end; + AudioSampleCache* cache; + u8* startRamAddr; + u8* endRamAddr; - pool = &gAudioContext.temporarySampleCache; - allocBefore = pool->pool.cur; - mem = AudioHeap_Alloc(&pool->pool, size); - if (mem == NULL) { + cache = &gAudioContext.temporarySampleCache; + allocBefore = cache->pool.curRamAddr; + ramAddr = AudioHeap_Alloc(&cache->pool, size); + if (ramAddr == NULL) { // Reset the pool and try again. We still keep pointers to within the // pool, so we have to be careful to discard existing overlapping // allocations further down. - u8* old = pool->pool.cur; - pool->pool.cur = pool->pool.start; - mem = AudioHeap_Alloc(&pool->pool, size); - if (mem == NULL) { - pool->pool.cur = old; + u8* old = cache->pool.curRamAddr; + + cache->pool.curRamAddr = cache->pool.startRamAddr; + ramAddr = AudioHeap_Alloc(&cache->pool, size); + if (ramAddr == NULL) { + cache->pool.curRamAddr = old; return NULL; } - allocBefore = pool->pool.start; + allocBefore = cache->pool.startRamAddr; } - allocAfter = pool->pool.cur; + allocAfter = cache->pool.curRamAddr; index = -1; for (i = 0; i < gAudioContext.preloadSampleStackTop; i++) { preload = &gAudioContext.preloadSampleStack[i]; if (preload->isFree == false) { - start = preload->ramAddr; - end = preload->ramAddr + preload->sample->size - 1; + startRamAddr = preload->ramAddr; + endRamAddr = preload->ramAddr + preload->sample->size - 1; - if (end < allocBefore && start < allocBefore) { + if (endRamAddr < allocBefore && startRamAddr < allocBefore) { continue; } - if (end >= allocAfter && start >= allocAfter) { + if (endRamAddr >= allocAfter && startRamAddr >= allocAfter) { continue; } @@ -1125,37 +1197,38 @@ SampleCacheEntry* AudioHeap_AllocTemporarySampleCacheEntry(u32 size) { } } - for (i = 0; i < pool->size; i++) { - if (pool->entries[i].inUse == false) { + for (i = 0; i < cache->numEntries; i++) { + if (!cache->entries[i].inUse) { continue; } - start = pool->entries[i].allocatedAddr; - end = start + pool->entries[i].size - 1; + startRamAddr = cache->entries[i].allocatedAddr; + endRamAddr = startRamAddr + cache->entries[i].size - 1; - if (end < allocBefore && start < allocBefore) { + if (endRamAddr < allocBefore && startRamAddr < allocBefore) { continue; } - if (end >= allocAfter && start >= allocAfter) { + if (endRamAddr >= allocAfter && startRamAddr >= allocAfter) { continue; } // Overlap, discard existing entry. - AudioHeap_DiscardSampleCacheEntry(&pool->entries[i]); + AudioHeap_DiscardSampleCacheEntry(&cache->entries[i]); if (index == -1) { index = i; } } if (index == -1) { - index = pool->size++; + index = cache->numEntries++; } - ret = &pool->entries[index]; - ret->inUse = true; - ret->allocatedAddr = mem; - ret->size = size; - return ret; + entry = &cache->entries[index]; + entry->inUse = true; + entry->allocatedAddr = ramAddr; + entry->size = size; + + return entry; } void AudioHeap_UnapplySampleCacheForFont(SampleCacheEntry* entry, s32 fontId) { @@ -1225,20 +1298,21 @@ void AudioHeap_UnapplySampleCache(SampleCacheEntry* entry, SoundFontSample* samp } SampleCacheEntry* AudioHeap_AllocPersistentSampleCacheEntry(u32 size) { - AudioSampleCache* pool; + AudioSampleCache* cache; SampleCacheEntry* entry; - void* mem; + void* ramAddr; - pool = &gAudioContext.persistentSampleCache; - mem = AudioHeap_Alloc(&pool->pool, size); - if (mem == NULL) { + cache = &gAudioContext.persistentSampleCache; + ramAddr = AudioHeap_Alloc(&cache->pool, size); + if (ramAddr == NULL) { return NULL; } - entry = &pool->entries[pool->size]; + entry = &cache->entries[cache->numEntries]; entry->inUse = true; - entry->allocatedAddr = mem; + entry->allocatedAddr = ramAddr; entry->size = size; - pool->size++; + cache->numEntries++; + return entry; } @@ -1268,11 +1342,11 @@ void AudioHeap_DiscardSampleCaches(void) { continue; } - for (j = 0; j < gAudioContext.persistentSampleCache.size; j++) { + for (j = 0; j < gAudioContext.persistentSampleCache.numEntries; j++) { AudioHeap_DiscardSampleCacheForFont(&gAudioContext.persistentSampleCache.entries[j], sampleBankId1, sampleBankId2, fontId); } - for (j = 0; j < gAudioContext.temporarySampleCache.size; j++) { + for (j = 0; j < gAudioContext.temporarySampleCache.numEntries; j++) { AudioHeap_DiscardSampleCacheForFont(&gAudioContext.temporarySampleCache.entries[j], sampleBankId1, sampleBankId2, fontId); } @@ -1288,11 +1362,11 @@ typedef struct { void AudioHeap_ChangeStorage(StorageChange* change, SoundFontSample* sample) { if (sample != NULL) { - u32 start = change->oldAddr; - u32 end = change->oldAddr + change->size; + u32 startAddr = change->oldAddr; + u32 endAddr = change->oldAddr + change->size; - if (start <= (u32)sample->sampleAddr && (u32)sample->sampleAddr < end) { - sample->sampleAddr = sample->sampleAddr - start + change->newAddr; + if (startAddr <= (u32)sample->sampleAddr && (u32)sample->sampleAddr < endAddr) { + sample->sampleAddr = sample->sampleAddr - startAddr + change->newAddr; sample->medium = change->newMedium; } } @@ -1345,6 +1419,7 @@ void AudioHeap_ApplySampleBankCacheInternal(s32 apply, s32 sampleBankId) { fakematch = &change.oldAddr; if ((apply != false) && (apply == true)) { u32 temp = change.newAddr; + change.newAddr = *fakematch; // = change.oldAddr change.oldAddr = temp; change.newMedium = MEDIUM_RAM; @@ -1396,13 +1471,13 @@ void AudioHeap_ApplySampleBankCacheInternal(s32 apply, s32 sampleBankId) { } void AudioHeap_DiscardSampleBanks(void) { - AudioCache* pool; + AudioCache* cache; AudioPersistentCache* persistent; AudioTemporaryCache* temporary; u32 i; - pool = &gAudioContext.sampleBankCache; - temporary = &pool->temporary; + cache = &gAudioContext.sampleBankCache; + temporary = &cache->temporary; if (temporary->entries[0].id != -1) { AudioHeap_DiscardSampleBank(temporary->entries[0].id); @@ -1412,7 +1487,7 @@ void AudioHeap_DiscardSampleBanks(void) { AudioHeap_DiscardSampleBank(temporary->entries[1].id); } - persistent = &pool->persistent; + persistent = &cache->persistent; for (i = 0; i < persistent->numEntries; i++) { AudioHeap_DiscardSampleBank(persistent->entries[i].id); } diff --git a/src/code/audio_load.c b/src/code/audio_load.c index 27a1ae1f0c..dde5abbc2d 100644 --- a/src/code/audio_load.c +++ b/src/code/audio_load.c @@ -1,17 +1,18 @@ #include "ultra64.h" #include "global.h" -#define MK_ASYNC_MSG(retData, tableType, id, status) (((retData) << 24) | ((tableType) << 16) | ((id) << 8) | (status)) +#define MK_ASYNC_MSG(retData, tableType, id, loadStatus) \ + (((retData) << 24) | ((tableType) << 16) | ((id) << 8) | (loadStatus)) #define ASYNC_TBLTYPE(v) ((u8)(v >> 16)) #define ASYNC_ID(v) ((u8)(v >> 8)) -#define ASYNC_STATUS(v) ((u8)(v >> 0)) +#define ASYNC_LOAD_STATUS(v) ((u8)(v >> 0)) typedef enum { - /* 0 */ LOAD_STATUS_WAITING, - /* 1 */ LOAD_STATUS_START, - /* 2 */ LOAD_STATUS_LOADING, - /* 3 */ LOAD_STATUS_DONE -} SlowLoadStatus; + /* 0 */ SLOW_LOAD_STATE_WAITING, + /* 1 */ SLOW_LOAD_STATE_START, + /* 2 */ SLOW_LOAD_STATE_LOADING, + /* 3 */ SLOW_LOAD_STATE_DONE +} SlowLoadState; typedef struct { /* 0x00 */ s32 sampleBankId1; @@ -200,7 +201,7 @@ void* AudioLoad_DmaSampleData(u32 devAddr, u32 size, s32 arg2, u8* dmaIndexRef, return (devAddr - dmaDevAddr) + dma->ramAddr; } -void AudioLoad_InitSampleDmaBuffers(s32 arg0) { +void AudioLoad_InitSampleDmaBuffers(s32 numNotes) { SampleDma* dma; s32 i; s32 t2; @@ -208,13 +209,12 @@ void AudioLoad_InitSampleDmaBuffers(s32 arg0) { gAudioContext.sampleDmaBufSize = gAudioContext.sampleDmaBufSize1; gAudioContext.sampleDmas = - AudioHeap_Alloc(&gAudioContext.notesAndBuffersPool, + AudioHeap_Alloc(&gAudioContext.miscPool, 4 * gAudioContext.numNotes * sizeof(SampleDma) * gAudioContext.audioBufferParameters.specUnk4); t2 = 3 * gAudioContext.numNotes * gAudioContext.audioBufferParameters.specUnk4; for (i = 0; i < t2; i++) { dma = &gAudioContext.sampleDmas[gAudioContext.sampleDmaCount]; - dma->ramAddr = - AudioHeap_AllocAttemptExternal(&gAudioContext.notesAndBuffersPool, gAudioContext.sampleDmaBufSize); + dma->ramAddr = AudioHeap_AllocAttemptExternal(&gAudioContext.miscPool, gAudioContext.sampleDmaBufSize); if (dma->ramAddr == NULL) { break; } else { @@ -244,8 +244,7 @@ void AudioLoad_InitSampleDmaBuffers(s32 arg0) { for (j = 0; j < gAudioContext.numNotes; j++) { dma = &gAudioContext.sampleDmas[gAudioContext.sampleDmaCount]; - dma->ramAddr = - AudioHeap_AllocAttemptExternal(&gAudioContext.notesAndBuffersPool, gAudioContext.sampleDmaBufSize); + dma->ramAddr = AudioHeap_AllocAttemptExternal(&gAudioContext.miscPool, gAudioContext.sampleDmaBufSize); if (dma->ramAddr == NULL) { break; } else { @@ -275,9 +274,9 @@ void AudioLoad_InitSampleDmaBuffers(s32 arg0) { s32 AudioLoad_IsFontLoadComplete(s32 fontId) { if (fontId == 0xFF) { return true; - } else if (gAudioContext.fontLoadStatus[fontId] >= 2) { + } else if (gAudioContext.fontLoadStatus[fontId] >= LOAD_STATUS_COMPLETE) { return true; - } else if (gAudioContext.fontLoadStatus[AudioLoad_GetRealTableIndex(FONT_TABLE, fontId)] >= 2) { + } else if (gAudioContext.fontLoadStatus[AudioLoad_GetRealTableIndex(FONT_TABLE, fontId)] >= LOAD_STATUS_COMPLETE) { return true; } else { return false; @@ -287,9 +286,10 @@ s32 AudioLoad_IsFontLoadComplete(s32 fontId) { s32 AudioLoad_IsSeqLoadComplete(s32 seqId) { if (seqId == 0xFF) { return true; - } else if (gAudioContext.seqLoadStatus[seqId] >= 2) { + } else if (gAudioContext.seqLoadStatus[seqId] >= LOAD_STATUS_COMPLETE) { return true; - } else if (gAudioContext.seqLoadStatus[AudioLoad_GetRealTableIndex(SEQUENCE_TABLE, seqId)] >= 2) { + } else if (gAudioContext.seqLoadStatus[AudioLoad_GetRealTableIndex(SEQUENCE_TABLE, seqId)] >= + LOAD_STATUS_COMPLETE) { return true; } else { return false; @@ -299,43 +299,45 @@ s32 AudioLoad_IsSeqLoadComplete(s32 seqId) { s32 AudioLoad_IsSampleLoadComplete(s32 sampleBankId) { if (sampleBankId == 0xFF) { return true; - } else if (gAudioContext.sampleFontLoadStatus[sampleBankId] >= 2) { + } else if (gAudioContext.sampleFontLoadStatus[sampleBankId] >= LOAD_STATUS_COMPLETE) { return true; - } else if (gAudioContext.sampleFontLoadStatus[AudioLoad_GetRealTableIndex(SAMPLE_TABLE, sampleBankId)] >= 2) { + } else if (gAudioContext.sampleFontLoadStatus[AudioLoad_GetRealTableIndex(SAMPLE_TABLE, sampleBankId)] >= + LOAD_STATUS_COMPLETE) { return true; } else { return false; } } -void AudioLoad_SetFontLoadStatus(s32 fontId, s32 status) { - if ((fontId != 0xFF) && (gAudioContext.fontLoadStatus[fontId] != 5)) { - gAudioContext.fontLoadStatus[fontId] = status; +void AudioLoad_SetFontLoadStatus(s32 fontId, s32 loadStatus) { + if ((fontId != 0xFF) && (gAudioContext.fontLoadStatus[fontId] != LOAD_STATUS_PERMANENTLY_LOADED)) { + gAudioContext.fontLoadStatus[fontId] = loadStatus; } } -void AudioLoad_SetSeqLoadStatus(s32 seqId, s32 status) { - if ((seqId != 0xFF) && (gAudioContext.seqLoadStatus[seqId] != 5)) { - gAudioContext.seqLoadStatus[seqId] = status; +void AudioLoad_SetSeqLoadStatus(s32 seqId, s32 loadStatus) { + if ((seqId != 0xFF) && (gAudioContext.seqLoadStatus[seqId] != LOAD_STATUS_PERMANENTLY_LOADED)) { + gAudioContext.seqLoadStatus[seqId] = loadStatus; } } -void AudioLoad_SetSampleFontLoadStatusAndApplyCaches(s32 sampleBankId, s32 status) { +void AudioLoad_SetSampleFontLoadStatusAndApplyCaches(s32 sampleBankId, s32 loadStatus) { if (sampleBankId != 0xFF) { - if (gAudioContext.sampleFontLoadStatus[sampleBankId] != 5) { - gAudioContext.sampleFontLoadStatus[sampleBankId] = status; + if (gAudioContext.sampleFontLoadStatus[sampleBankId] != LOAD_STATUS_PERMANENTLY_LOADED) { + gAudioContext.sampleFontLoadStatus[sampleBankId] = loadStatus; } - if ((gAudioContext.sampleFontLoadStatus[sampleBankId] == 5) || - (gAudioContext.sampleFontLoadStatus[sampleBankId] == 2)) { + if ((gAudioContext.sampleFontLoadStatus[sampleBankId] == LOAD_STATUS_PERMANENTLY_LOADED) || + (gAudioContext.sampleFontLoadStatus[sampleBankId] == LOAD_STATUS_COMPLETE)) { AudioHeap_ApplySampleBankCache(sampleBankId); } } } -void AudioLoad_SetSampleFontLoadStatus(s32 sampleBankId, s32 status) { - if ((sampleBankId != 0xFF) && (gAudioContext.sampleFontLoadStatus[sampleBankId] != 5)) { - gAudioContext.sampleFontLoadStatus[sampleBankId] = status; +void AudioLoad_SetSampleFontLoadStatus(s32 sampleBankId, s32 loadStatus) { + if ((sampleBankId != 0xFF) && + (gAudioContext.sampleFontLoadStatus[sampleBankId] != LOAD_STATUS_PERMANENTLY_LOADED)) { + gAudioContext.sampleFontLoadStatus[sampleBankId] = loadStatus; } } @@ -353,9 +355,9 @@ void AudioLoad_InitTable(AudioTable* table, u32 romAddr, u16 unkMediumParam) { } SoundFontData* AudioLoad_SyncLoadSeqFonts(s32 seqId, u32* outDefaultFontId) { - char pad[0x8]; + s32 pad[2]; s32 index; - SoundFontData* font; + SoundFontData* fontData; s32 numFonts; s32 fontId; s32 i; @@ -370,12 +372,12 @@ SoundFontData* AudioLoad_SyncLoadSeqFonts(s32 seqId, u32* outDefaultFontId) { while (numFonts > 0) { fontId = gAudioContext.sequenceFontTable[index++]; - font = AudioLoad_SyncLoadFont(fontId); + fontData = AudioLoad_SyncLoadFont(fontId); numFonts--; } *outDefaultFontId = fontId; - return font; + return fontData; } void AudioLoad_SyncLoadSeqParts(s32 seqId, s32 arg1) { @@ -459,9 +461,7 @@ void AudioLoad_AsyncLoadFont(s32 fontId, s32 arg1, s32 retData, OSMesgQueue* ret } u8* AudioLoad_GetFontsForSequence(s32 seqId, u32* outNumFonts) { - s32 index; - - index = ((u16*)gAudioContext.sequenceFontTable)[seqId]; + s32 index = ((u16*)gAudioContext.sequenceFontTable)[seqId]; *outNumFonts = gAudioContext.sequenceFontTable[index++]; if (*outNumFonts == 0) { @@ -472,18 +472,15 @@ u8* AudioLoad_GetFontsForSequence(s32 seqId, u32* outNumFonts) { void AudioLoad_DiscardSeqFonts(s32 seqId) { s32 fontId; - s32 index; - s32 numFonts; - - index = ((u16*)gAudioContext.sequenceFontTable)[seqId]; - numFonts = gAudioContext.sequenceFontTable[index++]; + s32 index = ((u16*)gAudioContext.sequenceFontTable)[seqId]; + s32 numFonts = gAudioContext.sequenceFontTable[index++]; while (numFonts > 0) { numFonts--; fontId = AudioLoad_GetRealTableIndex(FONT_TABLE, gAudioContext.sequenceFontTable[index++]); if (AudioHeap_SearchPermanentCache(FONT_TABLE, fontId) == NULL) { AudioLoad_DiscardFont(fontId); - AudioLoad_SetFontLoadStatus(fontId, 0); + AudioLoad_SetFontLoadStatus(fontId, LOAD_STATUS_NOT_LOADED); } } } @@ -564,11 +561,11 @@ s32 AudioLoad_SyncInitSeqPlayerInternal(s32 playerIdx, s32 seqId, s32 arg2) { seqPlayer->seqId = seqId; seqPlayer->defaultFont = AudioLoad_GetRealTableIndex(FONT_TABLE, fontId); seqPlayer->seqData = seqData; - seqPlayer->enabled = 1; + seqPlayer->enabled = true; seqPlayer->scriptState.pc = seqData; seqPlayer->scriptState.depth = 0; seqPlayer->delay = 0; - seqPlayer->finished = 0; + seqPlayer->finished = false; seqPlayer->playerIdx = playerIdx; AudioSeq_SkipForwardSequence(seqPlayer); //! @bug missing return (but the return value is not used so it's not UB) @@ -578,7 +575,7 @@ u8* AudioLoad_SyncLoadSeq(s32 seqId) { s32 pad; s32 didAllocate; - if (gAudioContext.seqLoadStatus[AudioLoad_GetRealTableIndex(SEQUENCE_TABLE, seqId)] == 1) { + if (gAudioContext.seqLoadStatus[AudioLoad_GetRealTableIndex(SEQUENCE_TABLE, seqId)] == LOAD_STATUS_IN_PROGRESS) { return NULL; } @@ -590,19 +587,19 @@ u32 AudioLoad_GetSampleBank(u32 sampleBankId, u32* outMedium) { } u32 AudioLoad_TrySyncLoadSampleBank(u32 sampleBankId, u32* outMedium, s32 noLoad) { - void* ret; + void* ramAddr; AudioTable* sampleBankTable; u32 realTableId = AudioLoad_GetRealTableIndex(SAMPLE_TABLE, sampleBankId); s8 cachePolicy; sampleBankTable = AudioLoad_GetLoadTable(SAMPLE_TABLE); - ret = AudioLoad_SearchCaches(SAMPLE_TABLE, realTableId); - if (ret != NULL) { - if (gAudioContext.sampleFontLoadStatus[realTableId] != 1) { - AudioLoad_SetSampleFontLoadStatus(realTableId, 2); + ramAddr = AudioLoad_SearchCaches(SAMPLE_TABLE, realTableId); + if (ramAddr != NULL) { + if (gAudioContext.sampleFontLoadStatus[realTableId] != LOAD_STATUS_IN_PROGRESS) { + AudioLoad_SetSampleFontLoadStatus(realTableId, LOAD_STATUS_COMPLETE); } *outMedium = MEDIUM_RAM; - return ret; + return ramAddr; } cachePolicy = sampleBankTable->entries[sampleBankId].cachePolicy; @@ -611,10 +608,10 @@ u32 AudioLoad_TrySyncLoadSampleBank(u32 sampleBankId, u32* outMedium, s32 noLoad return sampleBankTable->entries[realTableId].romAddr; } - ret = AudioLoad_SyncLoad(SAMPLE_TABLE, sampleBankId, &noLoad); - if (ret != NULL) { + ramAddr = AudioLoad_SyncLoad(SAMPLE_TABLE, sampleBankId, &noLoad); + if (ramAddr != NULL) { *outMedium = MEDIUM_RAM; - return ret; + return ramAddr; } *outMedium = sampleBankTable->entries[sampleBankId].medium; @@ -622,14 +619,14 @@ u32 AudioLoad_TrySyncLoadSampleBank(u32 sampleBankId, u32* outMedium, s32 noLoad } SoundFontData* AudioLoad_SyncLoadFont(u32 fontId) { - SoundFontData* ret; + SoundFontData* fontData; s32 sampleBankId1; s32 sampleBankId2; s32 didAllocate; RelocInfo relocInfo; s32 realFontId = AudioLoad_GetRealTableIndex(FONT_TABLE, fontId); - if (gAudioContext.fontLoadStatus[realFontId] == 1) { + if (gAudioContext.fontLoadStatus[realFontId] == LOAD_STATUS_IN_PROGRESS) { return NULL; } sampleBankId1 = gAudioContext.soundFonts[realFontId].sampleBankId1; @@ -649,15 +646,15 @@ SoundFontData* AudioLoad_SyncLoadFont(u32 fontId) { relocInfo.baseAddr2 = 0; } - ret = AudioLoad_SyncLoad(FONT_TABLE, fontId, &didAllocate); - if (ret == NULL) { + fontData = AudioLoad_SyncLoad(FONT_TABLE, fontId, &didAllocate); + if (fontData == NULL) { return NULL; } if (didAllocate == true) { - AudioLoad_RelocateFontAndPreloadSamples(realFontId, ret, &relocInfo, false); + AudioLoad_RelocateFontAndPreloadSamples(realFontId, fontData, &relocInfo, false); } - return ret; + return fontData; } void* AudioLoad_SyncLoad(u32 tableType, u32 id, s32* didAllocate) { @@ -665,17 +662,17 @@ void* AudioLoad_SyncLoad(u32 tableType, u32 id, s32* didAllocate) { AudioTable* table; s32 pad; u32 medium; - s32 status; + s32 loadStatus; u32 romAddr; s32 cachePolicy; - void* ret; + void* ramAddr; u32 realId; realId = AudioLoad_GetRealTableIndex(tableType, id); - ret = AudioLoad_SearchCaches(tableType, realId); - if (ret != NULL) { + ramAddr = AudioLoad_SearchCaches(tableType, realId); + if (ramAddr != NULL) { *didAllocate = false; - status = 2; + loadStatus = LOAD_STATUS_COMPLETE; } else { table = AudioLoad_GetLoadTable(tableType); size = table->entries[realId].size; @@ -685,57 +682,63 @@ void* AudioLoad_SyncLoad(u32 tableType, u32 id, s32* didAllocate) { romAddr = table->entries[realId].romAddr; switch (cachePolicy) { case 0: - ret = AudioHeap_AllocPermanent(tableType, realId, size); - if (ret == NULL) { - return ret; + ramAddr = AudioHeap_AllocPermanent(tableType, realId, size); + if (ramAddr == NULL) { + return ramAddr; } break; + case 1: - ret = AudioHeap_AllocCached(tableType, size, CACHE_PERSISTENT, realId); - if (ret == NULL) { - return ret; + ramAddr = AudioHeap_AllocCached(tableType, size, CACHE_PERSISTENT, realId); + if (ramAddr == NULL) { + return ramAddr; } break; + case 2: - ret = AudioHeap_AllocCached(tableType, size, CACHE_TEMPORARY, realId); - if (ret == NULL) { - return ret; + ramAddr = AudioHeap_AllocCached(tableType, size, CACHE_TEMPORARY, realId); + if (ramAddr == NULL) { + return ramAddr; } break; + case 3: case 4: - ret = AudioHeap_AllocCached(tableType, size, CACHE_EITHER, realId); - if (ret == NULL) { - return ret; + ramAddr = AudioHeap_AllocCached(tableType, size, CACHE_EITHER, realId); + if (ramAddr == NULL) { + return ramAddr; } break; } *didAllocate = true; if (medium == MEDIUM_UNK) { - AudioLoad_SyncDmaUnkMedium(romAddr, ret, size, (s16)table->unkMediumParam); + AudioLoad_SyncDmaUnkMedium(romAddr, ramAddr, size, (s16)table->unkMediumParam); } else { - AudioLoad_SyncDma(romAddr, ret, size, medium); + AudioLoad_SyncDma(romAddr, ramAddr, size, medium); } - status = cachePolicy == 0 ? 5 : 2; + loadStatus = (cachePolicy == 0) ? LOAD_STATUS_PERMANENTLY_LOADED : LOAD_STATUS_COMPLETE; } switch (tableType) { case SEQUENCE_TABLE: - AudioLoad_SetSeqLoadStatus(realId, status); + AudioLoad_SetSeqLoadStatus(realId, loadStatus); break; + case FONT_TABLE: - AudioLoad_SetFontLoadStatus(realId, status); + AudioLoad_SetFontLoadStatus(realId, loadStatus); break; + case SAMPLE_TABLE: - AudioLoad_SetSampleFontLoadStatusAndApplyCaches(realId, status); + AudioLoad_SetSampleFontLoadStatusAndApplyCaches(realId, loadStatus); break; + default: break; } - return ret; + return ramAddr; } u32 AudioLoad_GetRealTableIndex(s32 tableType, u32 id) { @@ -749,39 +752,42 @@ u32 AudioLoad_GetRealTableIndex(s32 tableType, u32 id) { } void* AudioLoad_SearchCaches(s32 tableType, s32 id) { - void* ret; + void* ramAddr; - ret = AudioHeap_SearchPermanentCache(tableType, id); - if (ret != NULL) { - return ret; + ramAddr = AudioHeap_SearchPermanentCache(tableType, id); + if (ramAddr != NULL) { + return ramAddr; } - ret = AudioHeap_SearchCaches(tableType, CACHE_EITHER, id); - if (ret != NULL) { - return ret; + ramAddr = AudioHeap_SearchCaches(tableType, CACHE_EITHER, id); + if (ramAddr != NULL) { + return ramAddr; } return NULL; } AudioTable* AudioLoad_GetLoadTable(s32 tableType) { - AudioTable* ret; + AudioTable* table; switch (tableType) { case SEQUENCE_TABLE: - ret = gAudioContext.sequenceTable; + table = gAudioContext.sequenceTable; break; + case FONT_TABLE: - ret = gAudioContext.soundFontTable; + table = gAudioContext.soundFontTable; break; + default: - ret = NULL; + table = NULL; break; + case SAMPLE_TABLE: - ret = gAudioContext.sampleBankTable; + table = gAudioContext.sampleBankTable; break; } - return ret; + return table; } void AudioLoad_RelocateFont(s32 fontId, SoundFontData* mem, RelocInfo* relocInfo) { @@ -851,7 +857,7 @@ void AudioLoad_RelocateFont(s32 fontId, SoundFontData* mem, RelocInfo* relocInfo reloc = inst->envelope; inst->envelope = BASE_OFFSET(reloc); - inst->loaded = 1; + inst->loaded = true; } } } @@ -863,26 +869,26 @@ void AudioLoad_RelocateFont(s32 fontId, SoundFontData* mem, RelocInfo* relocInfo gAudioContext.soundFonts[fontId].instruments = (Instrument**)(ptrs + 2); } -void AudioLoad_SyncDma(u32 devAddr, u8* addr, u32 size, s32 medium) { +void AudioLoad_SyncDma(u32 devAddr, u8* ramAddr, u32 size, s32 medium) { OSMesgQueue* msgQueue = &gAudioContext.syncDmaQueue; OSIoMesg* ioMesg = &gAudioContext.syncDmaIoMesg; size = ALIGN16(size); - Audio_InvalDCache(addr, size); + Audio_InvalDCache(ramAddr, size); while (true) { if (size < 0x400) { break; } - AudioLoad_Dma(ioMesg, OS_MESG_PRI_HIGH, OS_READ, devAddr, addr, 0x400, msgQueue, medium, "FastCopy"); + AudioLoad_Dma(ioMesg, OS_MESG_PRI_HIGH, OS_READ, devAddr, ramAddr, 0x400, msgQueue, medium, "FastCopy"); osRecvMesg(msgQueue, NULL, OS_MESG_BLOCK); size -= 0x400; devAddr += 0x400; - addr += 0x400; + ramAddr += 0x400; } if (size != 0) { - AudioLoad_Dma(ioMesg, OS_MESG_PRI_HIGH, OS_READ, devAddr, addr, size, msgQueue, medium, "FastCopy"); + AudioLoad_Dma(ioMesg, OS_MESG_PRI_HIGH, OS_READ, devAddr, ramAddr, size, msgQueue, medium, "FastCopy"); osRecvMesg(msgQueue, NULL, OS_MESG_BLOCK); } } @@ -894,7 +900,7 @@ s32 AudioLoad_Dma(OSIoMesg* mesg, u32 priority, s32 direction, u32 devAddr, void OSMesgQueue* reqQueue, s32 medium, const char* dmaFuncType) { OSPiHandle* handle; - if (gAudioContext.resetTimer > 0x10) { + if (gAudioContext.resetTimer > 16) { return -1; } @@ -902,11 +908,13 @@ s32 AudioLoad_Dma(OSIoMesg* mesg, u32 priority, s32 direction, u32 devAddr, void case MEDIUM_CART: handle = gAudioContext.cartHandle; break; + case MEDIUM_DISK_DRIVE: // driveHandle is uninitialized and corresponds to stubbed-out disk drive support. // SM64 Shindou called osDriveRomInit here. handle = gAudioContext.driveHandle; break; + default: return 0; } @@ -936,100 +944,108 @@ void AudioLoad_SyncLoadSimple(u32 tableType, u32 fontId) { void* AudioLoad_AsyncLoadInner(s32 tableType, s32 id, s32 nChunks, s32 retData, OSMesgQueue* retQueue) { u32 size; - AudioTable* sp50; - void* ret; + AudioTable* table; + void* ramAddr; s32 medium; s8 cachePolicy; u32 devAddr; - s32 status; - u32 temp_v0; - u32 realId; + s32 loadStatus; + s32 pad; + u32 realId = AudioLoad_GetRealTableIndex(tableType, id); - realId = AudioLoad_GetRealTableIndex(tableType, id); switch (tableType) { case SEQUENCE_TABLE: - if (gAudioContext.seqLoadStatus[realId] == 1) { + if (gAudioContext.seqLoadStatus[realId] == LOAD_STATUS_IN_PROGRESS) { return NULL; } break; + case FONT_TABLE: - if (gAudioContext.fontLoadStatus[realId] == 1) { + if (gAudioContext.fontLoadStatus[realId] == LOAD_STATUS_IN_PROGRESS) { return NULL; } break; + case SAMPLE_TABLE: - if (gAudioContext.sampleFontLoadStatus[realId] == 1) { + if (gAudioContext.sampleFontLoadStatus[realId] == LOAD_STATUS_IN_PROGRESS) { return NULL; } break; } - ret = AudioLoad_SearchCaches(tableType, realId); - if (ret != NULL) { - status = 2; - osSendMesg(retQueue, (OSMesg)MK_ASYNC_MSG(retData, 0, 0, 0), OS_MESG_NOBLOCK); + ramAddr = AudioLoad_SearchCaches(tableType, realId); + if (ramAddr != NULL) { + loadStatus = LOAD_STATUS_COMPLETE; + osSendMesg(retQueue, (OSMesg)MK_ASYNC_MSG(retData, 0, 0, LOAD_STATUS_NOT_LOADED), OS_MESG_NOBLOCK); } else { - sp50 = AudioLoad_GetLoadTable(tableType); - size = sp50->entries[realId].size; + table = AudioLoad_GetLoadTable(tableType); + size = table->entries[realId].size; size = ALIGN16(size); - medium = sp50->entries[id].medium; - cachePolicy = sp50->entries[id].cachePolicy; - devAddr = sp50->entries[realId].romAddr; - status = 2; + medium = table->entries[id].medium; + cachePolicy = table->entries[id].cachePolicy; + devAddr = table->entries[realId].romAddr; + loadStatus = LOAD_STATUS_COMPLETE; + switch (cachePolicy) { case 0: - ret = AudioHeap_AllocPermanent(tableType, realId, size); - if (ret == NULL) { - return ret; + ramAddr = AudioHeap_AllocPermanent(tableType, realId, size); + if (ramAddr == NULL) { + return ramAddr; } - status = 5; + loadStatus = LOAD_STATUS_PERMANENTLY_LOADED; break; + case 1: - ret = AudioHeap_AllocCached(tableType, size, CACHE_PERSISTENT, realId); - if (ret == NULL) { - return ret; + ramAddr = AudioHeap_AllocCached(tableType, size, CACHE_PERSISTENT, realId); + if (ramAddr == NULL) { + return ramAddr; } break; + case 2: - ret = AudioHeap_AllocCached(tableType, size, CACHE_TEMPORARY, realId); - if (ret == NULL) { - return ret; + ramAddr = AudioHeap_AllocCached(tableType, size, CACHE_TEMPORARY, realId); + if (ramAddr == NULL) { + return ramAddr; } break; + case 3: case 4: - ret = AudioHeap_AllocCached(tableType, size, CACHE_EITHER, realId); - if (ret == NULL) { - return ret; + ramAddr = AudioHeap_AllocCached(tableType, size, CACHE_EITHER, realId); + if (ramAddr == NULL) { + return ramAddr; } break; } if (medium == MEDIUM_UNK) { - AudioLoad_StartAsyncLoadUnkMedium((s16)sp50->unkMediumParam, devAddr, ret, size, medium, nChunks, retQueue, - MK_ASYNC_MSG(retData, tableType, id, status)); + AudioLoad_StartAsyncLoadUnkMedium((s16)table->unkMediumParam, devAddr, ramAddr, size, medium, nChunks, + retQueue, MK_ASYNC_MSG(retData, tableType, id, loadStatus)); } else { - AudioLoad_StartAsyncLoad(devAddr, ret, size, medium, nChunks, retQueue, - MK_ASYNC_MSG(retData, tableType, realId, status)); + AudioLoad_StartAsyncLoad(devAddr, ramAddr, size, medium, nChunks, retQueue, + MK_ASYNC_MSG(retData, tableType, realId, loadStatus)); } - status = 1; + loadStatus = LOAD_STATUS_IN_PROGRESS; } switch (tableType) { case SEQUENCE_TABLE: - AudioLoad_SetSeqLoadStatus(realId, status); + AudioLoad_SetSeqLoadStatus(realId, loadStatus); break; + case FONT_TABLE: - AudioLoad_SetFontLoadStatus(realId, status); + AudioLoad_SetFontLoadStatus(realId, loadStatus); break; + case SAMPLE_TABLE: - AudioLoad_SetSampleFontLoadStatusAndApplyCaches(realId, status); + AudioLoad_SetSampleFontLoadStatusAndApplyCaches(realId, loadStatus); break; + default: break; } - return ret; + return ramAddr; } void AudioLoad_ProcessLoads(s32 resetStatus) { @@ -1058,22 +1074,20 @@ void AudioLoad_InitSoundFontMeta(s32 fontId) { } void AudioLoad_Init(void* heap, u32 heapSize) { - char pad[0x48]; + s32 pad[18]; s32 numFonts; - void* temp_v0_3; + void* ramAddr; s32 i; - u64* heapP; - u8* ctxP; - s16* u2974p; D_801755D0 = NULL; gAudioContext.resetTimer = 0; { s32 i; - u8* ctxP = (u8*)&gAudioContext; + u8* audioContextPtr = (u8*)&gAudioContext; + for (i = sizeof(gAudioContext); i >= 0; i--) { - *ctxP++ = 0; + *audioContextPtr++ = 0; } } @@ -1082,14 +1096,17 @@ void AudioLoad_Init(void* heap, u32 heapSize) { gAudioContext.unk_2960 = 20.03042f; gAudioContext.refreshRate = 50; break; + case OS_TV_MPAL: gAudioContext.unk_2960 = 16.546f; gAudioContext.refreshRate = 60; break; + case OS_TV_NTSC: default: gAudioContext.unk_2960 = 16.713f; gAudioContext.refreshRate = 60; + break; } Audio_InitMesgQueues(); @@ -1099,10 +1116,10 @@ void AudioLoad_Init(void* heap, u32 heapSize) { } gAudioContext.totalTaskCount = 0; - gAudioContext.rspTaskIdx = 0; - gAudioContext.curAIBufIdx = 0; + gAudioContext.rspTaskIndex = 0; + gAudioContext.curAiBufIndex = 0; gAudioContext.soundMode = 0; - gAudioContext.currTask = NULL; + gAudioContext.curTask = NULL; gAudioContext.rspTask[0].task.t.data_size = 0; gAudioContext.rspTask[1].task.t.data_size = 0; osCreateMesgQueue(&gAudioContext.syncDmaQueue, &gAudioContext.syncDmaMesg, 1); @@ -1111,7 +1128,7 @@ void AudioLoad_Init(void* heap, u32 heapSize) { osCreateMesgQueue(&gAudioContext.externalLoadQueue, gAudioContext.externalLoadMsgBuf, ARRAY_COUNT(gAudioContext.externalLoadMsgBuf)); osCreateMesgQueue(&gAudioContext.preloadSampleQueue, gAudioContext.preloadSampleMsgBuf, - ARRAY_COUNT(gAudioContext.externalLoadMsgBuf)); + ARRAY_COUNT(gAudioContext.preloadSampleMsgBuf)); gAudioContext.curAudioFrameDmaCount = 0; gAudioContext.sampleDmaCount = 0; gAudioContext.cartHandle = osCartRomInit(); @@ -1129,22 +1146,28 @@ void AudioLoad_Init(void* heap, u32 heapSize) { ((u64*)gAudioContext.audioHeap)[i] = 0; } + // Main Pool Split (split entirety of audio heap into initPool and sessionPool) AudioHeap_InitMainPools(D_8014A6C4.initPoolSize); + // Initialize the audio interface buffers for (i = 0; i < 3; i++) { gAudioContext.aiBuffers[i] = AudioHeap_AllocZeroed(&gAudioContext.audioInitPool, AIBUF_LEN * sizeof(s16)); } + // Set audio tables pointers gAudioContext.sequenceTable = (AudioTable*)gSequenceTable; gAudioContext.soundFontTable = (AudioTable*)gSoundFontTable; gAudioContext.sampleBankTable = (AudioTable*)gSampleBankTable; gAudioContext.sequenceFontTable = gSequenceFontTable; + gAudioContext.numSequences = gAudioContext.sequenceTable->numEntries; gAudioContext.audioResetSpecIdToLoad = 0; - gAudioContext.resetStatus = 1; + gAudioContext.resetStatus = 1; // Set reset to immediately initialize the audio heap AudioHeap_ResetStep(); + + // Initialize audio tables AudioLoad_InitTable(gAudioContext.sequenceTable, _AudioseqSegmentRomStart, 0); AudioLoad_InitTable(gAudioContext.soundFontTable, _AudiobankSegmentRomStart, 0); AudioLoad_InitTable(gAudioContext.sampleBankTable, _AudiotableSegmentRomStart, 0); @@ -1155,57 +1178,58 @@ void AudioLoad_Init(void* heap, u32 heapSize) { AudioLoad_InitSoundFontMeta(i); } - if (temp_v0_3 = AudioHeap_Alloc(&gAudioContext.audioInitPool, D_8014A6C4.permanentPoolSize), temp_v0_3 == NULL) { + ramAddr = AudioHeap_Alloc(&gAudioContext.audioInitPool, D_8014A6C4.permanentPoolSize); + if (ramAddr == NULL) { // cast away const from D_8014A6C4 *((u32*)&D_8014A6C4.permanentPoolSize) = 0; } - AudioHeap_AllocPoolInit(&gAudioContext.permanentPool, temp_v0_3, D_8014A6C4.permanentPoolSize); + AudioHeap_AllocPoolInit(&gAudioContext.permanentPool, ramAddr, D_8014A6C4.permanentPoolSize); gAudioContextInitalized = true; osSendMesg(gAudioContext.taskStartQueueP, (OSMesg)gAudioContext.totalTaskCount, OS_MESG_NOBLOCK); } void AudioLoad_InitSlowLoads(void) { - gAudioContext.slowLoads[0].status = 0; - gAudioContext.slowLoads[1].status = 0; + gAudioContext.slowLoads[0].state = SLOW_LOAD_STATE_WAITING; + gAudioContext.slowLoads[1].state = SLOW_LOAD_STATE_WAITING; } -s32 AudioLoad_SlowLoadSample(s32 fontId, s32 instId, s8* isDone) { +s32 AudioLoad_SlowLoadSample(s32 fontId, s32 instId, s8* status) { SoundFontSample* sample; AudioSlowLoad* slowLoad; sample = AudioLoad_GetFontSample(fontId, instId); if (sample == NULL) { - *isDone = 0; + *status = 0; return -1; } if (sample->medium == MEDIUM_RAM) { - *isDone = 2; + *status = 2; return 0; } slowLoad = &gAudioContext.slowLoads[gAudioContext.slowLoadPos]; - if (slowLoad->status == LOAD_STATUS_DONE) { - slowLoad->status = LOAD_STATUS_WAITING; + if (slowLoad->state == SLOW_LOAD_STATE_DONE) { + slowLoad->state = SLOW_LOAD_STATE_WAITING; } slowLoad->sample = *sample; - slowLoad->isDone = isDone; + slowLoad->status = status; slowLoad->curRamAddr = AudioHeap_AllocSampleCache(sample->size, fontId, sample->sampleAddr, sample->medium, CACHE_TEMPORARY); if (slowLoad->curRamAddr == NULL) { if (sample->medium == MEDIUM_UNK || sample->codec == CODEC_S16_INMEMORY) { - *isDone = 0; + *status = 0; return -1; } else { - *isDone = 3; + *status = 3; return -1; } } - slowLoad->status = LOAD_STATUS_START; + slowLoad->state = SLOW_LOAD_STATE_START; slowLoad->bytesRemaining = ALIGN16(sample->size); slowLoad->ramAddr = slowLoad->curRamAddr; slowLoad->curDevAddr = sample->sampleAddr; @@ -1221,28 +1245,31 @@ s32 AudioLoad_SlowLoadSample(s32 fontId, s32 instId, s8* isDone) { } SoundFontSample* AudioLoad_GetFontSample(s32 fontId, s32 instId) { - SoundFontSample* ret; + SoundFontSample* sample; if (instId < 0x80) { Instrument* instrument = Audio_GetInstrumentInner(fontId, instId); + if (instrument == NULL) { return NULL; } - ret = instrument->normalNotesSound.sample; + sample = instrument->normalNotesSound.sample; } else if (instId < 0x100) { Drum* drum = Audio_GetDrum(fontId, instId - 0x80); + if (drum == NULL) { return NULL; } - ret = drum->sound.sample; + sample = drum->sound.sample; } else { SoundFontSound* sound = Audio_GetSfx(fontId, instId - 0x100); + if (sound == NULL) { return NULL; } - ret = sound->sample; + sample = sound->sample; } - return ret; + return sample; } void AudioLoad_Unused2(void) { @@ -1271,26 +1298,27 @@ void AudioLoad_ProcessSlowLoads(s32 resetStatus) { for (i = 0; i < ARRAY_COUNT(gAudioContext.slowLoads); i++) { slowLoad = &gAudioContext.slowLoads[i]; - switch (gAudioContext.slowLoads[i].status) { - case LOAD_STATUS_LOADING: + switch (gAudioContext.slowLoads[i].state) { + case SLOW_LOAD_STATE_LOADING: if (slowLoad->medium != MEDIUM_UNK) { osRecvMesg(&slowLoad->msgQueue, NULL, OS_MESG_BLOCK); } if (resetStatus != 0) { - slowLoad->status = LOAD_STATUS_DONE; + slowLoad->state = SLOW_LOAD_STATE_DONE; continue; } FALLTHROUGH; - case LOAD_STATUS_START: - slowLoad->status = LOAD_STATUS_LOADING; + case SLOW_LOAD_STATE_START: + slowLoad->state = SLOW_LOAD_STATE_LOADING; if (slowLoad->bytesRemaining == 0) { AudioLoad_FinishSlowLoad(slowLoad); - slowLoad->status = LOAD_STATUS_DONE; - *slowLoad->isDone = 1; + slowLoad->state = SLOW_LOAD_STATE_DONE; + *slowLoad->status = 1; } else if (slowLoad->bytesRemaining < 0x400) { if (slowLoad->medium == MEDIUM_UNK) { u32 size = slowLoad->bytesRemaining; + AudioLoad_DmaSlowCopyUnkMedium(slowLoad->curDevAddr, slowLoad->curRamAddr, size, slowLoad->unkMediumParam); } else { @@ -1316,36 +1344,36 @@ void AudioLoad_ProcessSlowLoads(s32 resetStatus) { void AudioLoad_DmaSlowCopy(AudioSlowLoad* slowLoad, s32 size) { Audio_InvalDCache(slowLoad->curRamAddr, size); osCreateMesgQueue(&slowLoad->msgQueue, &slowLoad->msg, 1); - AudioLoad_Dma(&slowLoad->ioMesg, OS_MESG_PRI_NORMAL, 0, slowLoad->curDevAddr, slowLoad->curRamAddr, size, + AudioLoad_Dma(&slowLoad->ioMesg, OS_MESG_PRI_NORMAL, OS_READ, slowLoad->curDevAddr, slowLoad->curRamAddr, size, &slowLoad->msgQueue, slowLoad->medium, "SLOWCOPY"); } void AudioLoad_DmaSlowCopyUnkMedium(s32 devAddr, u8* ramAddr, s32 size, s32 arg3) { } -s32 AudioLoad_SlowLoadSeq(s32 seqId, u8* ramAddr, s8* isDone) { +s32 AudioLoad_SlowLoadSeq(s32 seqId, u8* ramAddr, s8* status) { AudioSlowLoad* slowLoad; AudioTable* seqTable; u32 size; if (seqId >= gAudioContext.numSequences) { - *isDone = 0; + *status = 0; return -1; } seqId = AudioLoad_GetRealTableIndex(SEQUENCE_TABLE, seqId); seqTable = AudioLoad_GetLoadTable(SEQUENCE_TABLE); slowLoad = &gAudioContext.slowLoads[gAudioContext.slowLoadPos]; - if (slowLoad->status == LOAD_STATUS_DONE) { - slowLoad->status = LOAD_STATUS_WAITING; + if (slowLoad->state == SLOW_LOAD_STATE_DONE) { + slowLoad->state = SLOW_LOAD_STATE_WAITING; } slowLoad->sample.sampleAddr = NULL; - slowLoad->isDone = isDone; + slowLoad->status = status; size = seqTable->entries[seqId].size; size = ALIGN16(size); slowLoad->curRamAddr = ramAddr; - slowLoad->status = LOAD_STATUS_START; + slowLoad->state = SLOW_LOAD_STATE_START; slowLoad->bytesRemaining = size; slowLoad->ramAddr = ramAddr; slowLoad->curDevAddr = seqTable->entries[seqId].romAddr; @@ -1400,7 +1428,7 @@ AudioAsyncLoad* AudioLoad_StartAsyncLoad(u32 devAddr, void* ramAddr, u32 size, s return NULL; } - asyncLoad->status = LOAD_STATUS_START; + asyncLoad->status = 1; asyncLoad->curDevAddr = devAddr; asyncLoad->ramAddr = ramAddr; asyncLoad->curRamAddr = ramAddr; @@ -1474,11 +1502,13 @@ void AudioLoad_FinishAsyncLoad(AudioAsyncLoad* asyncLoad) { if (1) {} switch (ASYNC_TBLTYPE(retMsg)) { case SEQUENCE_TABLE: - AudioLoad_SetSeqLoadStatus(ASYNC_ID(retMsg), ASYNC_STATUS(retMsg)); + AudioLoad_SetSeqLoadStatus(ASYNC_ID(retMsg), ASYNC_LOAD_STATUS(retMsg)); break; + case SAMPLE_TABLE: - AudioLoad_SetSampleFontLoadStatusAndApplyCaches(ASYNC_ID(retMsg), ASYNC_STATUS(retMsg)); + AudioLoad_SetSampleFontLoadStatusAndApplyCaches(ASYNC_ID(retMsg), ASYNC_LOAD_STATUS(retMsg)); break; + case FONT_TABLE: fontId = ASYNC_ID(retMsg); sampleBankId1 = gAudioContext.soundFonts[fontId].sampleBankId1; @@ -1489,14 +1519,14 @@ void AudioLoad_FinishAsyncLoad(AudioAsyncLoad* asyncLoad) { sampleBankId1 != 0xFF ? AudioLoad_GetSampleBank(sampleBankId1, &relocInfo.medium1) : 0; relocInfo.baseAddr2 = sampleBankId2 != 0xFF ? AudioLoad_GetSampleBank(sampleBankId2, &relocInfo.medium2) : 0; - AudioLoad_SetFontLoadStatus(fontId, ASYNC_STATUS(retMsg)); + AudioLoad_SetFontLoadStatus(fontId, ASYNC_LOAD_STATUS(retMsg)); AudioLoad_RelocateFontAndPreloadSamples(fontId, asyncLoad->ramAddr, &relocInfo, true); break; } doneMsg = asyncLoad->retMsg; if (1) {} - asyncLoad->status = LOAD_STATUS_WAITING; + asyncLoad->status = 0; osSendMesg(asyncLoad->retQueue, doneMsg, OS_MESG_NOBLOCK); } @@ -1513,7 +1543,7 @@ void AudioLoad_ProcessAsyncLoad(AudioAsyncLoad* asyncLoad, s32 resetStatus) { } else if (resetStatus != 0) { // Await the previous DMA response synchronously, then return. osRecvMesg(&asyncLoad->msgQueue, NULL, OS_MESG_BLOCK); - asyncLoad->status = LOAD_STATUS_WAITING; + asyncLoad->status = 0; return; } else if (osRecvMesg(&asyncLoad->msgQueue, NULL, OS_MESG_NOBLOCK) == -1) { // If the previous DMA step isn't done, return. @@ -1552,8 +1582,8 @@ void AudioLoad_AsyncDma(AudioAsyncLoad* asyncLoad, u32 size) { size = ALIGN16(size); Audio_InvalDCache(asyncLoad->curRamAddr, size); osCreateMesgQueue(&asyncLoad->msgQueue, &asyncLoad->msg, 1); - AudioLoad_Dma(&asyncLoad->ioMesg, 0, 0, asyncLoad->curDevAddr, asyncLoad->curRamAddr, size, &asyncLoad->msgQueue, - asyncLoad->medium, "BGCOPY"); + AudioLoad_Dma(&asyncLoad->ioMesg, OS_MESG_PRI_NORMAL, OS_READ, asyncLoad->curDevAddr, asyncLoad->curRamAddr, size, + &asyncLoad->msgQueue, asyncLoad->medium, "BGCOPY"); } void AudioLoad_AsyncDmaUnkMedium(u32 devAddr, void* ramAddr, u32 size, s16 arg3) { @@ -1604,7 +1634,7 @@ void AudioLoad_RelocateFontAndPreloadSamples(s32 fontId, SoundFontData* mem, Rel SoundFontSample* sample; s32 size; s32 nChunks; - u8* addr; + u8* sampleRamAddr; s32 preloadInProgress; s32 i; @@ -1630,48 +1660,48 @@ void AudioLoad_RelocateFontAndPreloadSamples(s32 fontId, SoundFontData* mem, Rel } sample = gAudioContext.usedSamples[i]; - addr = NULL; + sampleRamAddr = NULL; switch (async) { case false: if (sample->medium == relocInfo->medium1) { - addr = AudioHeap_AllocSampleCache(sample->size, relocInfo->sampleBankId1, sample->sampleAddr, - sample->medium, CACHE_PERSISTENT); + sampleRamAddr = AudioHeap_AllocSampleCache(sample->size, relocInfo->sampleBankId1, + sample->sampleAddr, sample->medium, CACHE_PERSISTENT); } else if (sample->medium == relocInfo->medium2) { - addr = AudioHeap_AllocSampleCache(sample->size, relocInfo->sampleBankId2, sample->sampleAddr, - sample->medium, CACHE_PERSISTENT); + sampleRamAddr = AudioHeap_AllocSampleCache(sample->size, relocInfo->sampleBankId2, + sample->sampleAddr, sample->medium, CACHE_PERSISTENT); } else if (sample->medium == MEDIUM_DISK_DRIVE) { - addr = AudioHeap_AllocSampleCache(sample->size, 0xFE, sample->sampleAddr, sample->medium, - CACHE_PERSISTENT); + sampleRamAddr = AudioHeap_AllocSampleCache(sample->size, 0xFE, sample->sampleAddr, sample->medium, + CACHE_PERSISTENT); } break; case true: if (sample->medium == relocInfo->medium1) { - addr = AudioHeap_AllocSampleCache(sample->size, relocInfo->sampleBankId1, sample->sampleAddr, - sample->medium, CACHE_TEMPORARY); + sampleRamAddr = AudioHeap_AllocSampleCache(sample->size, relocInfo->sampleBankId1, + sample->sampleAddr, sample->medium, CACHE_TEMPORARY); } else if (sample->medium == relocInfo->medium2) { - addr = AudioHeap_AllocSampleCache(sample->size, relocInfo->sampleBankId2, sample->sampleAddr, - sample->medium, CACHE_TEMPORARY); + sampleRamAddr = AudioHeap_AllocSampleCache(sample->size, relocInfo->sampleBankId2, + sample->sampleAddr, sample->medium, CACHE_TEMPORARY); } else if (sample->medium == MEDIUM_DISK_DRIVE) { - addr = AudioHeap_AllocSampleCache(sample->size, 0xFE, sample->sampleAddr, sample->medium, - CACHE_TEMPORARY); + sampleRamAddr = AudioHeap_AllocSampleCache(sample->size, 0xFE, sample->sampleAddr, sample->medium, + CACHE_TEMPORARY); } break; } - if (addr == NULL) { + if (sampleRamAddr == NULL) { continue; } switch (async) { case false: if (sample->medium == MEDIUM_UNK) { - AudioLoad_SyncDmaUnkMedium((u32)sample->sampleAddr, addr, sample->size, + AudioLoad_SyncDmaUnkMedium((u32)sample->sampleAddr, sampleRamAddr, sample->size, gAudioContext.sampleBankTable->unkMediumParam); - sample->sampleAddr = addr; + sample->sampleAddr = sampleRamAddr; sample->medium = MEDIUM_RAM; } else { - AudioLoad_SyncDma((u32)sample->sampleAddr, addr, sample->size, sample->medium); - sample->sampleAddr = addr; + AudioLoad_SyncDma((u32)sample->sampleAddr, sampleRamAddr, sample->size, sample->medium); + sample->sampleAddr = sampleRamAddr; sample->medium = MEDIUM_RAM; } if (sample->medium == MEDIUM_DISK_DRIVE) {} @@ -1680,7 +1710,7 @@ void AudioLoad_RelocateFontAndPreloadSamples(s32 fontId, SoundFontData* mem, Rel case true: preload = &gAudioContext.preloadSampleStack[gAudioContext.preloadSampleStackTop]; preload->sample = sample; - preload->ramAddr = addr; + preload->ramAddr = sampleRamAddr; preload->encodedInfo = (gAudioContext.preloadSampleStackTop << 24) | 0xFFFFFF; preload->isFree = false; preload->endAndMediumKey = (u32)sample->sampleAddr + sample->size + sample->medium; @@ -1712,11 +1742,11 @@ s32 AudioLoad_ProcessSamplePreloads(s32 resetStatus) { // Clear result queue and preload stack and return. osRecvMesg(&gAudioContext.preloadSampleQueue, (OSMesg*)&preloadIndex, OS_MESG_NOBLOCK); gAudioContext.preloadSampleStackTop = 0; - return 0; + return false; } if (osRecvMesg(&gAudioContext.preloadSampleQueue, (OSMesg*)&preloadIndex, OS_MESG_NOBLOCK) == -1) { // Previous preload is not done yet. - return 0; + return false; } preloadIndex >>= 24; @@ -1758,7 +1788,7 @@ s32 AudioLoad_ProcessSamplePreloads(s32 resetStatus) { } } } - return 1; + return true; } s32 AudioLoad_AddToSampleSet(SoundFontSample* sample, s32 numSamples, SoundFontSample** sampleSet) { @@ -1780,15 +1810,13 @@ s32 AudioLoad_AddToSampleSet(SoundFontSample* sample, s32 numSamples, SoundFontS s32 AudioLoad_GetSamplesForFont(s32 fontId, SoundFontSample** sampleSet) { s32 i; - s32 numDrums; - s32 numInstruments; s32 numSamples = 0; - - numDrums = gAudioContext.soundFonts[fontId].numDrums; - numInstruments = gAudioContext.soundFonts[fontId].numInstruments; + s32 numDrums = gAudioContext.soundFonts[fontId].numDrums; + s32 numInstruments = gAudioContext.soundFonts[fontId].numInstruments; for (i = 0; i < numDrums; i++) { Drum* drum = Audio_GetDrum(fontId, i); + if (1) {} if (drum != NULL) { numSamples = AudioLoad_AddToSampleSet(drum->sound.sample, numSamples, sampleSet); @@ -1797,6 +1825,7 @@ s32 AudioLoad_GetSamplesForFont(s32 fontId, SoundFontSample** sampleSet) { for (i = 0; i < numInstruments; i++) { Instrument* instrument = Audio_GetInstrumentInner(fontId, i); + if (instrument != NULL) { if (instrument->normalRangeLo != 0) { numSamples = AudioLoad_AddToSampleSet(instrument->lowNotesSound.sample, numSamples, sampleSet); @@ -1808,7 +1837,7 @@ s32 AudioLoad_GetSamplesForFont(s32 fontId, SoundFontSample** sampleSet) { } } - // Should really also process sfx, but this method is never called, so whatever. + // Should really also process sfx, but this method is never called. return numSamples; } @@ -1963,7 +1992,7 @@ void AudioLoad_LoadPermanentSamples(void) { s32 i; sampleBankTable = AudioLoad_GetLoadTable(SAMPLE_TABLE); - for (i = 0; i < gAudioContext.permanentPool.count; i++) { + for (i = 0; i < gAudioContext.permanentPool.numEntries; i++) { RelocInfo relocInfo; if (gAudioContext.permanentCache[i].tableType == FONT_TABLE) { @@ -1994,9 +2023,10 @@ void AudioLoad_Unused4(void) { void AudioLoad_Unused5(void) { } -void AudioLoad_ScriptLoad(s32 tableType, s32 id, s8* isDone) { +void AudioLoad_ScriptLoad(s32 tableType, s32 id, s8* status) { static u32 sLoadIndex = 0; - sScriptLoadDonePointers[sLoadIndex] = isDone; + + sScriptLoadDonePointers[sLoadIndex] = status; AudioLoad_AsyncLoad(tableType, id, 0, sLoadIndex, &sScriptLoadQueue); sLoadIndex++; if (sLoadIndex == 0x10) { @@ -2007,13 +2037,13 @@ void AudioLoad_ScriptLoad(s32 tableType, s32 id, s8* isDone) { void AudioLoad_ProcessScriptLoads(void) { u32 temp; u32 sp20; - s8* isDone; + s8* status; if (osRecvMesg(&sScriptLoadQueue, (OSMesg*)&sp20, OS_MESG_NOBLOCK) != -1) { temp = sp20 >> 24; - isDone = sScriptLoadDonePointers[temp]; - if (isDone != NULL) { - *isDone = 0; + status = sScriptLoadDonePointers[temp]; + if (status != NULL) { + *status = 0; } } } diff --git a/src/code/audio_playback.c b/src/code/audio_playback.c index 7c9a29d7f2..fb9f77e817 100644 --- a/src/code/audio_playback.c +++ b/src/code/audio_playback.c @@ -9,13 +9,13 @@ void Audio_InitNoteSub(Note* note, NoteSubEu* sub, NoteSubAttributes* attrs) { f32 vel; u8 pan; u8 reverbVol; - StereoData sp24; + StereoData stereoData; s32 stereoHeadsetEffects = note->playbackState.stereoHeadsetEffects; vel = attrs->velocity; pan = attrs->pan; reverbVol = attrs->reverbVol; - sp24 = attrs->stereo.s; + stereoData = attrs->stereo.s; sub->bitField0 = note->noteSubEu.bitField0; sub->bitField1 = note->noteSubEu.bitField1; @@ -28,8 +28,8 @@ void Audio_InitNoteSub(Note* note, NoteSubEu* sub, NoteSubAttributes* attrs) { sub->bitField0.stereoStrongRight = false; sub->bitField0.stereoStrongLeft = false; - sub->bitField0.stereoHeadsetEffects = sp24.stereoHeadsetEffects; - sub->bitField0.usesHeadsetPanEffects = sp24.usesHeadsetPanEffects; + sub->bitField0.stereoHeadsetEffects = stereoData.stereoHeadsetEffects; + sub->bitField0.usesHeadsetPanEffects = stereoData.usesHeadsetPanEffects; if (stereoHeadsetEffects && gAudioContext.soundMode == 1) { smallPanIndex = pan >> 1; if (smallPanIndex > 0x3F) { @@ -59,20 +59,23 @@ void Audio_InitNoteSub(Note* note, NoteSubEu* sub, NoteSubAttributes* attrs) { sub->bitField0.stereoStrongRight = strongRight; sub->bitField0.stereoStrongLeft = strongLeft; - switch (sp24.bit2) { + switch (stereoData.bit2) { case 0: break; + case 1: - sub->bitField0.stereoStrongRight = sp24.strongRight; - sub->bitField0.stereoStrongLeft = sp24.strongLeft; + sub->bitField0.stereoStrongRight = stereoData.strongRight; + sub->bitField0.stereoStrongLeft = stereoData.strongLeft; break; + case 2: - sub->bitField0.stereoStrongRight = sp24.strongRight | strongRight; - sub->bitField0.stereoStrongLeft = sp24.strongLeft | strongLeft; + sub->bitField0.stereoStrongRight = stereoData.strongRight | strongRight; + sub->bitField0.stereoStrongLeft = stereoData.strongLeft | strongLeft; break; + case 3: - sub->bitField0.stereoStrongRight = sp24.strongRight ^ strongRight; - sub->bitField0.stereoStrongLeft = sp24.strongLeft ^ strongLeft; + sub->bitField0.stereoStrongRight = stereoData.strongRight ^ strongRight; + sub->bitField0.stereoStrongLeft = stereoData.strongLeft ^ strongLeft; break; } @@ -82,8 +85,8 @@ void Audio_InitNoteSub(Note* note, NoteSubEu* sub, NoteSubAttributes* attrs) { volLeft = 0.707f; // approx 1/sqrt(2) volRight = 0.707f; } else { - sub->bitField0.stereoStrongRight = sp24.strongRight; - sub->bitField0.stereoStrongLeft = sp24.strongLeft; + sub->bitField0.stereoStrongRight = stereoData.strongRight; + sub->bitField0.stereoStrongLeft = stereoData.strongLeft; volLeft = gDefaultPanVolume[pan]; volRight = gDefaultPanVolume[0x7F - pan]; } @@ -94,7 +97,7 @@ void Audio_InitNoteSub(Note* note, NoteSubEu* sub, NoteSubAttributes* attrs) { 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; @@ -106,16 +109,11 @@ void Audio_NoteSetResamplingRate(NoteSubEu* noteSubEu, f32 resamplingRateInput) if (resamplingRateInput < 2.0f) { noteSubEu->bitField1.hasTwoParts = false; - - if (1.99998f < resamplingRateInput) { - resamplingRate = 1.99998f; - } else { - resamplingRate = resamplingRateInput; - } + resamplingRate = CLAMP_MAX(resamplingRateInput, 1.99998f); } else { noteSubEu->bitField1.hasTwoParts = true; - if (3.99996f < resamplingRateInput) { + if (resamplingRateInput > 3.99996f) { resamplingRate = 1.99998f; } else { resamplingRate = resamplingRateInput * 0.5f; @@ -255,7 +253,7 @@ void Audio_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; @@ -273,7 +271,7 @@ void Audio_ProcessNotes(void) { subAttrs.stereo = layer->stereo; } subAttrs.reverbVol = channel->reverb; - subAttrs.unk_1 = channel->unk_0C; + subAttrs.gain = channel->gain; subAttrs.filter = channel->filter; subAttrs.unk_14 = channel->unk_0F; subAttrs.unk_16 = channel->unk_20; @@ -297,6 +295,7 @@ void Audio_ProcessNotes(void) { SoundFontSound* Audio_InstrumentGetSound(Instrument* instrument, s32 semitone) { SoundFontSound* sound; + if (semitone < instrument->normalRangeLo) { sound = &instrument->lowNotesSound; } else if (semitone <= instrument->normalRangeHi) { @@ -470,7 +469,7 @@ void Audio_SeqLayerDecayRelease(SequenceLayer* layer, s32 target) { if (layer->channel != NULL) { chan = layer->channel; attrs->reverb = chan->reverb; - attrs->unk_1 = chan->unk_0C; + attrs->gain = chan->gain; attrs->filter = chan->filter; if (attrs->filter != NULL) { @@ -849,62 +848,62 @@ Note* Audio_AllocNoteFromActive(NotePool* pool, SequenceLayer* layer) { } Note* Audio_AllocNote(SequenceLayer* layer) { - Note* ret; + Note* note; u32 policy = layer->channel->noteAllocPolicy; if (policy & 1) { - ret = layer->note; - if (ret != NULL && ret->playbackState.prevParentLayer == layer && - ret->playbackState.wantedParentLayer == NO_LAYER) { - Audio_NoteReleaseAndTakeOwnership(ret, layer); - Audio_AudioListRemove(&ret->listItem); - AudioSeq_AudioListPushBack(&ret->listItem.pool->releasing, &ret->listItem); - return ret; + note = layer->note; + if (note != NULL && note->playbackState.prevParentLayer == layer && + note->playbackState.wantedParentLayer == NO_LAYER) { + Audio_NoteReleaseAndTakeOwnership(note, layer); + Audio_AudioListRemove(¬e->listItem); + AudioSeq_AudioListPushBack(¬e->listItem.pool->releasing, ¬e->listItem); + return note; } } if (policy & 2) { - if (!(ret = Audio_AllocNoteFromDisabled(&layer->channel->notePool, layer)) && - !(ret = Audio_AllocNoteFromDecaying(&layer->channel->notePool, layer)) && - !(ret = Audio_AllocNoteFromActive(&layer->channel->notePool, layer))) { + if (!(note = Audio_AllocNoteFromDisabled(&layer->channel->notePool, layer)) && + !(note = Audio_AllocNoteFromDecaying(&layer->channel->notePool, layer)) && + !(note = Audio_AllocNoteFromActive(&layer->channel->notePool, layer))) { goto null_return; } - return ret; + return note; } if (policy & 4) { - if (!(ret = Audio_AllocNoteFromDisabled(&layer->channel->notePool, layer)) && - !(ret = Audio_AllocNoteFromDisabled(&layer->channel->seqPlayer->notePool, layer)) && - !(ret = Audio_AllocNoteFromDecaying(&layer->channel->notePool, layer)) && - !(ret = Audio_AllocNoteFromDecaying(&layer->channel->seqPlayer->notePool, layer)) && - !(ret = Audio_AllocNoteFromActive(&layer->channel->notePool, layer)) && - !(ret = Audio_AllocNoteFromActive(&layer->channel->seqPlayer->notePool, layer))) { + if (!(note = Audio_AllocNoteFromDisabled(&layer->channel->notePool, layer)) && + !(note = Audio_AllocNoteFromDisabled(&layer->channel->seqPlayer->notePool, layer)) && + !(note = Audio_AllocNoteFromDecaying(&layer->channel->notePool, layer)) && + !(note = Audio_AllocNoteFromDecaying(&layer->channel->seqPlayer->notePool, layer)) && + !(note = Audio_AllocNoteFromActive(&layer->channel->notePool, layer)) && + !(note = Audio_AllocNoteFromActive(&layer->channel->seqPlayer->notePool, layer))) { goto null_return; } - return ret; + return note; } if (policy & 8) { - if (!(ret = Audio_AllocNoteFromDisabled(&gAudioContext.noteFreeLists, layer)) && - !(ret = Audio_AllocNoteFromDecaying(&gAudioContext.noteFreeLists, layer)) && - !(ret = Audio_AllocNoteFromActive(&gAudioContext.noteFreeLists, layer))) { + if (!(note = Audio_AllocNoteFromDisabled(&gAudioContext.noteFreeLists, layer)) && + !(note = Audio_AllocNoteFromDecaying(&gAudioContext.noteFreeLists, layer)) && + !(note = Audio_AllocNoteFromActive(&gAudioContext.noteFreeLists, layer))) { goto null_return; } - return ret; + return note; } - if (!(ret = Audio_AllocNoteFromDisabled(&layer->channel->notePool, layer)) && - !(ret = Audio_AllocNoteFromDisabled(&layer->channel->seqPlayer->notePool, layer)) && - !(ret = Audio_AllocNoteFromDisabled(&gAudioContext.noteFreeLists, layer)) && - !(ret = Audio_AllocNoteFromDecaying(&layer->channel->notePool, layer)) && - !(ret = Audio_AllocNoteFromDecaying(&layer->channel->seqPlayer->notePool, layer)) && - !(ret = Audio_AllocNoteFromDecaying(&gAudioContext.noteFreeLists, layer)) && - !(ret = Audio_AllocNoteFromActive(&layer->channel->notePool, layer)) && - !(ret = Audio_AllocNoteFromActive(&layer->channel->seqPlayer->notePool, layer)) && - !(ret = Audio_AllocNoteFromActive(&gAudioContext.noteFreeLists, layer))) { + if (!(note = Audio_AllocNoteFromDisabled(&layer->channel->notePool, layer)) && + !(note = Audio_AllocNoteFromDisabled(&layer->channel->seqPlayer->notePool, layer)) && + !(note = Audio_AllocNoteFromDisabled(&gAudioContext.noteFreeLists, layer)) && + !(note = Audio_AllocNoteFromDecaying(&layer->channel->notePool, layer)) && + !(note = Audio_AllocNoteFromDecaying(&layer->channel->seqPlayer->notePool, layer)) && + !(note = Audio_AllocNoteFromDecaying(&gAudioContext.noteFreeLists, layer)) && + !(note = Audio_AllocNoteFromActive(&layer->channel->notePool, layer)) && + !(note = Audio_AllocNoteFromActive(&layer->channel->seqPlayer->notePool, layer)) && + !(note = Audio_AllocNoteFromActive(&gAudioContext.noteFreeLists, layer))) { goto null_return; } - return ret; + return note; null_return: layer->bit3 = true; @@ -932,6 +931,6 @@ void Audio_NoteInitAll(void) { note->portamento.speed = 0; note->playbackState.stereoHeadsetEffects = false; note->unk_BC = 0; - note->synthesisState.synthesisBuffers = AudioHeap_AllocDmaMemory(&gAudioContext.notesAndBuffersPool, 0x1E0); + note->synthesisState.synthesisBuffers = AudioHeap_AllocDmaMemory(&gAudioContext.miscPool, 0x1E0); } } diff --git a/src/code/audio_seqplayer.c b/src/code/audio_seqplayer.c index 6001056076..483f93451f 100644 --- a/src/code/audio_seqplayer.c +++ b/src/code/audio_seqplayer.c @@ -243,7 +243,7 @@ void AudioSeq_InitSequenceChannel(SequenceChannel* channel) { channel->noteUnused = NULL; channel->reverbIndex = 0; channel->reverb = 0; - channel->unk_0C = 0; + channel->gain = 0; channel->notePriority = 3; channel->someOtherPriority = 1; channel->delay = 0; @@ -311,7 +311,7 @@ s32 AudioSeq_SeqChannelSetLayer(SequenceChannel* channel, s32 layerIdx) { layer->note = NULL; layer->instrument = NULL; layer->freqScale = 1.0f; - layer->unk_34 = 1.0f; + layer->bend = 1.0f; layer->velocitySquare2 = 0.0f; layer->instOrWave = 0xFF; return 0; @@ -410,10 +410,10 @@ void AudioSeq_SequencePlayerDisable(SequencePlayer* seqPlayer) { seqPlayer->finished = true; if (AudioLoad_IsSeqLoadComplete(seqPlayer->seqId)) { - AudioLoad_SetSeqLoadStatus(seqPlayer->seqId, 3); + AudioLoad_SetSeqLoadStatus(seqPlayer->seqId, LOAD_STATUS_DISCARDABLE); } if (AudioLoad_IsFontLoadComplete(seqPlayer->defaultFont)) { - AudioLoad_SetFontLoadStatus(seqPlayer->defaultFont, 4); + AudioLoad_SetFontLoadStatus(seqPlayer->defaultFont, LOAD_STATUS_MAYBE_DISCARDABLE); } if (seqPlayer->defaultFont == gAudioContext.fontCache.temporary.entries[0].id) { @@ -569,6 +569,7 @@ s32 AudioSeq_SeqLayerProcessScriptStep5(SequenceLayer* layer, s32 sameSound) { if (layer->note != NULL && layer->note->playbackState.parentLayer == layer) { Note* note = layer->note; + Audio_NotePortamentoInit(note); } return 0; @@ -707,7 +708,7 @@ s32 AudioSeq_SeqLayerProcessScriptStep2(SequenceLayer* layer) { case 0xCE: tempByte = AudioSeq_ScriptReadU8(state); - layer->unk_34 = gBendPitchTwoSemitonesFrequencies[(tempByte + 0x80) & 0xFF]; + layer->bend = gBendPitchTwoSemitonesFrequencies[(tempByte + 0x80) & 0xFF]; break; default: @@ -832,11 +833,13 @@ s32 AudioSeq_SeqLayerProcessScriptStep4(SequenceLayer* layer, s32 cmd) { 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; @@ -885,7 +888,7 @@ s32 AudioSeq_SeqLayerProcessScriptStep4(SequenceLayer* layer, s32 cmd) { } layer->delay2 = layer->delay; - layer->freqScale *= layer->unk_34; + layer->freqScale *= layer->bend; if (layer->delay == 0) { if (layer->sound != NULL) { time = (f32)layer->sound->sample->loop->end; @@ -905,6 +908,7 @@ s32 AudioSeq_SeqLayerProcessScriptStep4(SequenceLayer* layer, s32 cmd) { // set when this is reached...) if (PORTAMENTO_IS_SPECIAL(*portamento)) { s32 speed2; + speed2 = seqPlayer->tempo * 0x8000 / gAudioContext.tempoInternalToExternal; speed2 = speed2 * 0x100 / (layer->delay * layer->portamentoTime); if (speed2 >= 0x7FFF) { @@ -1431,7 +1435,7 @@ void AudioSeq_SequenceChannelProcessScript(SequenceChannel* channel) { channel->vibratoRateStart = 0; channel->vibratoRateChangeDelay = 0; channel->filter = NULL; - channel->unk_0C = 0; + channel->gain = 0; channel->adsr.sustain = 0; channel->velocityRandomVariance = 0; channel->gateTimeRandomVariance = 0; @@ -1447,7 +1451,7 @@ void AudioSeq_SequenceChannelProcessScript(SequenceChannel* channel) { case 0xED: cmd = (u8)cmdArgs[0]; - channel->unk_0C = cmd; + channel->gain = cmd; break; case 0xB0: @@ -1459,6 +1463,7 @@ void AudioSeq_SequenceChannelProcessScript(SequenceChannel* channel) { case 0xB1: channel->filter = NULL; break; + case 0xB3: cmd = cmdArgs[0]; @@ -1654,8 +1659,8 @@ void AudioSeq_SequencePlayerProcessSequence(SequencePlayer* seqPlayer) { return; } - AudioLoad_SetSeqLoadStatus(seqPlayer->seqId, 2); - AudioLoad_SetFontLoadStatus(seqPlayer->defaultFont, 2); + AudioLoad_SetSeqLoadStatus(seqPlayer->seqId, LOAD_STATUS_COMPLETE); + AudioLoad_SetFontLoadStatus(seqPlayer->defaultFont, LOAD_STATUS_COMPLETE); if (seqPlayer->muted && (seqPlayer->muteBehavior & 0x80)) { return; @@ -1714,15 +1719,18 @@ void AudioSeq_SequencePlayerProcessSequence(SequencePlayer* seqPlayer) { } if (dummy) {} break; + case 0xF0: Audio_NotePoolClear(&seqPlayer->notePool); break; + case 0xDF: seqPlayer->transposition = 0; FALLTHROUGH; case 0xDE: seqPlayer->transposition += (s8)AudioSeq_ScriptReadU8(seqScript); break; + case 0xDD: seqPlayer->tempo = AudioSeq_ScriptReadU8(seqScript) * 48; if (seqPlayer->tempo > gAudioContext.tempoInternalToExternal) { @@ -1732,9 +1740,11 @@ void AudioSeq_SequencePlayerProcessSequence(SequencePlayer* seqPlayer) { seqPlayer->tempo = 1; } break; + case 0xDC: seqPlayer->unk_0C = (s8)AudioSeq_ScriptReadU8(seqScript) * 48; break; + case 0xDA: command = AudioSeq_ScriptReadU8(seqScript); temp = AudioSeq_ScriptReadS16(seqScript); @@ -1746,6 +1756,7 @@ void AudioSeq_SequencePlayerProcessSequence(SequencePlayer* seqPlayer) { seqPlayer->state = command; } break; + case 2: seqPlayer->fadeTimer = temp; seqPlayer->state = command; @@ -1753,6 +1764,7 @@ void AudioSeq_SequencePlayerProcessSequence(SequencePlayer* seqPlayer) { break; } break; + case 0xDB: value = AudioSeq_ScriptReadU8(seqScript); switch (seqPlayer->state) { @@ -1769,29 +1781,37 @@ void AudioSeq_SequencePlayerProcessSequence(SequencePlayer* seqPlayer) { seqPlayer->fadeVolume = (s32)value / 127.0f; } break; + case 2: break; } break; + case 0xD9: seqPlayer->fadeVolumeScale = (s8)AudioSeq_ScriptReadU8(seqScript) / 127.0f; break; + case 0xD7: temp = AudioSeq_ScriptReadS16(seqScript); AudioSeq_SequencePlayerSetupChannels(seqPlayer, temp); break; + case 0xD6: AudioSeq_ScriptReadS16(seqScript); break; + case 0xD5: seqPlayer->muteVolumeScale = (s8)AudioSeq_ScriptReadU8(seqScript) / 127.0f; break; + case 0xD4: seqPlayer->muted = true; break; + case 0xD3: seqPlayer->muteBehavior = AudioSeq_ScriptReadU8(seqScript); break; + case 0xD1: case 0xD2: temp = AudioSeq_ScriptReadS16(seqScript); @@ -1802,9 +1822,11 @@ void AudioSeq_SequencePlayerProcessSequence(SequencePlayer* seqPlayer) { seqPlayer->shortNoteGateTimeTable = data3; } break; + case 0xD0: seqPlayer->noteAllocPolicy = AudioSeq_ScriptReadU8(seqScript); break; + case 0xCE: command = AudioSeq_ScriptReadU8(seqScript); if (command == 0) { @@ -1813,7 +1835,8 @@ void AudioSeq_SequencePlayerProcessSequence(SequencePlayer* seqPlayer) { seqScript->value = (gAudioContext.audioRandom >> 2) % command; } break; - case 0xCD: { + + case 0xCD: temp = AudioSeq_ScriptReadS16(seqScript); if ((seqScript->value != -1) && (seqScript->depth != 3)) { @@ -1825,32 +1848,39 @@ void AudioSeq_SequencePlayerProcessSequence(SequencePlayer* seqPlayer) { seqScript->pc = &seqPlayer->seqData[temp]; } break; - } + case 0xCC: seqScript->value = AudioSeq_ScriptReadU8(seqScript); break; + case 0xC9: seqScript->value &= AudioSeq_ScriptReadU8(seqScript); break; + case 0xC8: seqScript->value -= AudioSeq_ScriptReadU8(seqScript); break; + case 0xC7: command = AudioSeq_ScriptReadU8(seqScript); temp = AudioSeq_ScriptReadS16(seqScript); data2 = &seqPlayer->seqData[temp]; *data2 = (u8)seqScript->value + command; break; + case 0xC6: seqPlayer->stopScript = true; return; + case 0xC5: seqPlayer->scriptCounter = (u16)AudioSeq_ScriptReadS16(seqScript); break; + case 0xEF: AudioSeq_ScriptReadS16(seqScript); AudioSeq_ScriptReadU8(seqScript); break; + case 0xC4: command = AudioSeq_ScriptReadU8(seqScript); if (command == 0xFF) { @@ -1870,12 +1900,15 @@ void AudioSeq_SequencePlayerProcessSequence(SequencePlayer* seqPlayer) { case 0x00: seqScript->value = seqPlayer->channels[commandLow]->enabled ^ 1; break; + case 0x50: seqScript->value -= seqPlayer->soundScriptIO[commandLow]; break; + case 0x70: seqPlayer->soundScriptIO[commandLow] = seqScript->value; break; + case 0x80: seqScript->value = seqPlayer->soundScriptIO[commandLow]; if (commandLow < 2) { @@ -1885,20 +1918,24 @@ void AudioSeq_SequencePlayerProcessSequence(SequencePlayer* seqPlayer) { case 0x40: AudioSeq_SequenceChannelDisable(seqPlayer->channels[commandLow]); break; + case 0x90: temp = AudioSeq_ScriptReadS16(seqScript); AudioSeq_SequenceChannelEnable(seqPlayer, commandLow, (void*)&seqPlayer->seqData[temp]); break; + case 0xA0: tempS = AudioSeq_ScriptReadS16(seqScript); AudioSeq_SequenceChannelEnable(seqPlayer, commandLow, (void*)&seqScript->pc[tempS]); break; + case 0xB0: command = AudioSeq_ScriptReadU8(seqScript); temp = AudioSeq_ScriptReadS16(seqScript); data2 = &seqPlayer->seqData[temp]; AudioLoad_SlowLoadSeq(command, data2, &seqPlayer->soundScriptIO[commandLow]); break; + case 0x60: { command = AudioSeq_ScriptReadU8(seqScript); value = command; @@ -1976,7 +2013,7 @@ void AudioSeq_InitSequencePlayerChannels(s32 playerIdx) { s32 i, j; for (i = 0; i < 0x10; i++) { - seqPlayer->channels[i] = AudioHeap_AllocZeroed(&gAudioContext.notesAndBuffersPool, sizeof(SequenceChannel)); + seqPlayer->channels[i] = AudioHeap_AllocZeroed(&gAudioContext.miscPool, sizeof(SequenceChannel)); if (seqPlayer->channels[i] == NULL) { seqPlayer->channels[i] = &gAudioContext.sequenceChannelNone; } else { @@ -2002,14 +2039,14 @@ void AudioSeq_InitSequencePlayer(SequencePlayer* seqPlayer) { seqPlayer->muted = false; seqPlayer->fontDmaInProgress = false; seqPlayer->seqDmaInProgress = false; - seqPlayer->unk_0b1 = false; + seqPlayer->applyBend = false; for (j = 0; j < 8; j++) { seqPlayer->soundScriptIO[j] = -1; } seqPlayer->muteBehavior = 0x40 | 0x20; seqPlayer->fadeVolumeScale = 1.0f; - seqPlayer->unk_34 = 1.0f; + seqPlayer->bend = 1.0f; Audio_InitNoteLists(&seqPlayer->notePool); AudioSeq_ResetSequencePlayer(seqPlayer); } diff --git a/src/code/audio_synthesis.c b/src/code/audio_synthesis.c index eb680776df..58135c3356 100644 --- a/src/code/audio_synthesis.c +++ b/src/code/audio_synthesis.c @@ -4,6 +4,7 @@ #define DEFAULT_LEN_1CH 0x1A0 #define DEFAULT_LEN_2CH 0x340 +// DMEM Addresses for the RSP #define DMEM_TEMP 0x3C0 #define DMEM_UNCOMPRESSED_NOTE 0x580 #define DMEM_NOTE_PAN_TEMP 0x5C0 @@ -30,10 +31,10 @@ Acmd* AudioSynth_ProcessEnvelope(Acmd* cmd, NoteSubEu* noteSubEu, NoteSynthesisS Acmd* AudioSynth_FinalResample(Acmd* cmd, NoteSynthesisState* synthState, s32 count, u16 pitch, u16 inpDmem, s32 resampleFlags); -u32 D_801304A0 = 0x13000000; -u32 D_801304A4 = 0x5CAEC8E2; -u32 D_801304A8 = 0x945CC8E2; -u32 D_801304AC = 0x94AEC8E2; +u32 D_801304A0 = _SHIFTL(A_ENVMIXER, 24, 8); +u32 D_801304A4 = MK_CMD(DMEM_NOTE_PAN_TEMP >> 4, DMEM_RIGHT_CH >> 4, DMEM_WET_LEFT_CH >> 4, DMEM_WET_RIGHT_CH >> 4); +u32 D_801304A8 = MK_CMD(DMEM_LEFT_CH >> 4, DMEM_NOTE_PAN_TEMP >> 4, DMEM_WET_LEFT_CH >> 4, DMEM_WET_RIGHT_CH >> 4); +u32 D_801304AC = MK_CMD(DMEM_LEFT_CH >> 4, DMEM_RIGHT_CH >> 4, DMEM_WET_LEFT_CH >> 4, DMEM_WET_RIGHT_CH >> 4); u16 D_801304B0[] = { 0x7FFF, 0xD001, 0x3FFF, 0xF001, 0x5FFF, 0x9001, 0x7FFF, 0x8001, @@ -41,20 +42,20 @@ u16 D_801304B0[] = { u8 D_801304C0[] = { 0x40, 0x20, 0x10, 0x8 }; -void AudioSynth_InitNextRingBuf(s32 chunkLen, s32 bufIndex, s32 reverbIndex) { +void AudioSynth_InitNextRingBuf(s32 chunkLen, s32 updateIndex, s32 reverbIndex) { ReverbRingBufferItem* bufItem; s32 pad[3]; SynthesisReverb* reverb = &gAudioContext.synthesisReverbs[reverbIndex]; s32 temp_a0_2; s32 temp_a0_4; - s32 sampleCnt; + s32 numSamples; s32 extraSamples; s32 i; s32 j; if (reverb->downsampleRate >= 2) { if (reverb->framesToIgnore == 0) { - bufItem = &reverb->items[reverb->curFrame][bufIndex]; + bufItem = &reverb->items[reverb->curFrame][updateIndex]; Audio_InvalDCache(bufItem->toDownsampleLeft, DEFAULT_LEN_2CH); for (j = 0, i = 0; i < bufItem->lengthA / 2; j += reverb->downsampleRate, i++) { @@ -69,23 +70,24 @@ void AudioSynth_InitNextRingBuf(s32 chunkLen, s32 bufIndex, s32 reverbIndex) { } } - bufItem = &reverb->items[reverb->curFrame][bufIndex]; - sampleCnt = chunkLen / reverb->downsampleRate; - extraSamples = (sampleCnt + reverb->nextRingBufPos) - reverb->bufSizePerChan; + bufItem = &reverb->items[reverb->curFrame][updateIndex]; + numSamples = chunkLen / reverb->downsampleRate; + extraSamples = (numSamples + reverb->nextRingBufPos) - reverb->bufSizePerChan; temp_a0_2 = reverb->nextRingBufPos; if (extraSamples < 0) { - bufItem->lengthA = sampleCnt * 2; + bufItem->lengthA = numSamples * 2; bufItem->lengthB = 0; bufItem->startPos = reverb->nextRingBufPos; - reverb->nextRingBufPos += sampleCnt; + reverb->nextRingBufPos += numSamples; } else { - bufItem->lengthA = (sampleCnt - extraSamples) * 2; + // End of the buffer is reached. Loop back around + bufItem->lengthA = (numSamples - extraSamples) * 2; bufItem->lengthB = extraSamples * 2; bufItem->startPos = reverb->nextRingBufPos; reverb->nextRingBufPos = extraSamples; } - bufItem->numSamplesAfterDownsampling = sampleCnt; + bufItem->numSamplesAfterDownsampling = numSamples; bufItem->chunkLen = chunkLen; if (reverb->unk_14 != 0) { @@ -93,30 +95,31 @@ void AudioSynth_InitNextRingBuf(s32 chunkLen, s32 bufIndex, s32 reverbIndex) { if (temp_a0_4 >= reverb->bufSizePerChan) { temp_a0_4 -= reverb->bufSizePerChan; } - bufItem = &reverb->items2[reverb->curFrame][bufIndex]; - sampleCnt = chunkLen / reverb->downsampleRate; - extraSamples = (temp_a0_4 + sampleCnt) - reverb->bufSizePerChan; + bufItem = &reverb->items2[reverb->curFrame][updateIndex]; + numSamples = chunkLen / reverb->downsampleRate; + extraSamples = (temp_a0_4 + numSamples) - reverb->bufSizePerChan; if (extraSamples < 0) { - bufItem->lengthA = sampleCnt * 2; + bufItem->lengthA = numSamples * 2; bufItem->lengthB = 0; bufItem->startPos = temp_a0_4; } else { - bufItem->lengthA = (sampleCnt - extraSamples) * 2; + // End of the buffer is reached. Loop back around + bufItem->lengthA = (numSamples - extraSamples) * 2; bufItem->lengthB = extraSamples * 2; bufItem->startPos = temp_a0_4; } - bufItem->numSamplesAfterDownsampling = sampleCnt; + bufItem->numSamplesAfterDownsampling = numSamples; bufItem->chunkLen = chunkLen; } } -void func_800DB03C(s32 arg0) { +void func_800DB03C(s32 updateIndex) { NoteSubEu* subEu; NoteSubEu* subEu2; s32 baseIndex; s32 i; - baseIndex = gAudioContext.numNotes * arg0; + baseIndex = gAudioContext.numNotes * updateIndex; for (i = 0; i < gAudioContext.numNotes; i++) { subEu = &gAudioContext.notes[i].noteSubEu; subEu2 = &gAudioContext.noteSubsEu[baseIndex + i]; @@ -146,6 +149,7 @@ Acmd* AudioSynth_Update(Acmd* cmdStart, s32* cmdCnt, s16* aiStart, s32 aiBufLen) aiBufP = aiStart; gAudioContext.curLoadedBook = NULL; + for (i = gAudioContext.audioBufferParameters.updatesPerFrame; i > 0; i--) { if (i == 1) { chunkLen = aiBufLen; @@ -180,22 +184,22 @@ Acmd* AudioSynth_Update(Acmd* cmdStart, s32* cmdCnt, s16* aiStart, s32 aiBufLen) return cmdP; } -void func_800DB2C0(s32 updateIndexStart, s32 noteIndex) { - NoteSubEu* temp_v1; +void func_800DB2C0(s32 updateIndex, s32 noteIndex) { + NoteSubEu* noteSubEu; s32 i; - for (i = updateIndexStart + 1; i < gAudioContext.audioBufferParameters.updatesPerFrame; i++) { - temp_v1 = &gAudioContext.noteSubsEu[(gAudioContext.numNotes * i) + noteIndex]; - if (!temp_v1->bitField0.needsInit) { - temp_v1->bitField0.enabled = 0; + for (i = updateIndex + 1; i < gAudioContext.audioBufferParameters.updatesPerFrame; i++) { + noteSubEu = &gAudioContext.noteSubsEu[(gAudioContext.numNotes * i) + noteIndex]; + if (!noteSubEu->bitField0.needsInit) { + noteSubEu->bitField0.enabled = false; } else { break; } } } -Acmd* AudioSynth_LoadRingBuffer1AtTemp(Acmd* cmd, SynthesisReverb* reverb, s16 bufIndex) { - ReverbRingBufferItem* bufItem = &reverb->items[reverb->curFrame][bufIndex]; +Acmd* AudioSynth_LoadRingBuffer1AtTemp(Acmd* cmd, SynthesisReverb* reverb, s16 updateIndex) { + ReverbRingBufferItem* bufItem = &reverb->items[reverb->curFrame][updateIndex]; cmd = AudioSynth_LoadRingBufferPart(cmd, DMEM_WET_TEMP, bufItem->startPos, bufItem->lengthA, reverb); if (bufItem->lengthB != 0) { @@ -205,8 +209,8 @@ Acmd* AudioSynth_LoadRingBuffer1AtTemp(Acmd* cmd, SynthesisReverb* reverb, s16 b return cmd; } -Acmd* AudioSynth_SaveRingBuffer1AtTemp(Acmd* cmd, SynthesisReverb* reverb, s16 bufIndex) { - ReverbRingBufferItem* bufItem = &reverb->items[reverb->curFrame][bufIndex]; +Acmd* AudioSynth_SaveRingBuffer1AtTemp(Acmd* cmd, SynthesisReverb* reverb, s16 updateIndex) { + ReverbRingBufferItem* bufItem = &reverb->items[reverb->curFrame][updateIndex]; cmd = AudioSynth_SaveRingBufferPart(cmd, DMEM_WET_TEMP, bufItem->startPos, bufItem->lengthA, reverb); if (bufItem->lengthB != 0) { @@ -216,16 +220,18 @@ Acmd* AudioSynth_SaveRingBuffer1AtTemp(Acmd* cmd, SynthesisReverb* reverb, s16 b return cmd; } +/** + * Leak some audio from the left reverb channel into the right reverb channel and vice versa (pan) + */ Acmd* AudioSynth_LeakReverb(Acmd* cmd, SynthesisReverb* reverb) { - // Leak some audio from the left reverb channel into the right reverb channel and vice versa (pan) aDMEMMove(cmd++, DMEM_WET_LEFT_CH, DMEM_WET_SCRATCH, DEFAULT_LEN_1CH); aMix(cmd++, 0x1A, reverb->leakRtl, DMEM_WET_RIGHT_CH, DMEM_WET_LEFT_CH); aMix(cmd++, 0x1A, reverb->leakLtr, DMEM_WET_SCRATCH, DMEM_WET_RIGHT_CH); return cmd; } -Acmd* func_800DB4E4(Acmd* cmd, s32 arg1, SynthesisReverb* reverb, s16 arg3) { - ReverbRingBufferItem* item = &reverb->items[reverb->curFrame][arg3]; +Acmd* func_800DB4E4(Acmd* cmd, s32 aiBufLen, SynthesisReverb* reverb, s16 updateIndex) { + ReverbRingBufferItem* item = &reverb->items[reverb->curFrame][updateIndex]; s16 offsetA; s16 offsetB; @@ -236,15 +242,15 @@ Acmd* func_800DB4E4(Acmd* cmd, s32 arg1, SynthesisReverb* reverb, s16 arg3) { // Ring buffer wrapped cmd = AudioSynth_LoadRingBufferPart(cmd, DMEM_WET_TEMP + offsetB, 0, DEFAULT_LEN_1CH - offsetB, reverb); } - aSetBuffer(cmd++, 0, DMEM_WET_TEMP + offsetA, DMEM_WET_LEFT_CH, arg1 * 2); + aSetBuffer(cmd++, 0, DMEM_WET_TEMP + offsetA, DMEM_WET_LEFT_CH, aiBufLen * 2); aResample(cmd++, reverb->resampleFlags, reverb->unk_0E, reverb->unk_30); - aSetBuffer(cmd++, 0, DMEM_WET_TEMP + DEFAULT_LEN_1CH + offsetA, DMEM_WET_RIGHT_CH, arg1 * 2); + aSetBuffer(cmd++, 0, DMEM_WET_TEMP + DEFAULT_LEN_1CH + offsetA, DMEM_WET_RIGHT_CH, aiBufLen * 2); aResample(cmd++, reverb->resampleFlags, reverb->unk_0E, reverb->unk_34); return cmd; } -Acmd* func_800DB680(Acmd* cmd, SynthesisReverb* reverb, s16 bufIndex) { - ReverbRingBufferItem* bufItem = &reverb->items[reverb->curFrame][bufIndex]; +Acmd* func_800DB680(Acmd* cmd, SynthesisReverb* reverb, s16 updateIndex) { + ReverbRingBufferItem* bufItem = &reverb->items[reverb->curFrame][updateIndex]; aSetBuffer(cmd++, 0, DMEM_WET_LEFT_CH, DMEM_WET_SCRATCH, bufItem->unk_18 * 2); aResample(cmd++, reverb->resampleFlags, bufItem->unk_16, reverb->unk_38); @@ -268,29 +274,31 @@ Acmd* func_800DB680(Acmd* cmd, SynthesisReverb* reverb, s16 bufIndex) { return cmd; } -Acmd* func_800DB828(Acmd* cmd, s32 arg1, SynthesisReverb* reverb, s16 arg3) { - ReverbRingBufferItem* item = &reverb->items[reverb->curFrame][arg3]; +Acmd* func_800DB828(Acmd* cmd, s32 aiBufLen, SynthesisReverb* reverb, s16 updateIndex) { + ReverbRingBufferItem* item = &reverb->items[reverb->curFrame][updateIndex]; s16 offsetA; s16 offsetB; - item->unk_14 = (item->unk_18 << 0xF) / arg1; + item->unk_14 = (item->unk_18 << 0xF) / aiBufLen; offsetA = (item->startPos & 7) * 2; - item->unk_16 = (arg1 << 0xF) / item->unk_18; + item->unk_16 = (aiBufLen << 0xF) / item->unk_18; offsetB = ALIGN16(offsetA + item->lengthA); cmd = AudioSynth_LoadRingBufferPart(cmd, DMEM_WET_TEMP, item->startPos - (offsetA / 2), DEFAULT_LEN_1CH, reverb); if (item->lengthB != 0) { // Ring buffer wrapped cmd = AudioSynth_LoadRingBufferPart(cmd, DMEM_WET_TEMP + offsetB, 0, DEFAULT_LEN_1CH - offsetB, reverb); } - aSetBuffer(cmd++, 0, DMEM_WET_TEMP + offsetA, DMEM_WET_LEFT_CH, arg1 * 2); + aSetBuffer(cmd++, 0, DMEM_WET_TEMP + offsetA, DMEM_WET_LEFT_CH, aiBufLen * 2); aResample(cmd++, reverb->resampleFlags, item->unk_14, reverb->unk_30); - aSetBuffer(cmd++, 0, DMEM_WET_TEMP + DEFAULT_LEN_1CH + offsetA, DMEM_WET_RIGHT_CH, arg1 * 2); + aSetBuffer(cmd++, 0, DMEM_WET_TEMP + DEFAULT_LEN_1CH + offsetA, DMEM_WET_RIGHT_CH, aiBufLen * 2); aResample(cmd++, reverb->resampleFlags, item->unk_14, reverb->unk_34); return cmd; } +/** + * Apply a filter (convolution) to each reverb channel. + */ Acmd* AudioSynth_FilterReverb(Acmd* cmd, s32 count, SynthesisReverb* reverb) { - // Apply a filter (convolution) to each reverb channel. if (reverb->filterLeft != NULL) { aFilter(cmd++, 2, count, reverb->filterLeft); aFilter(cmd++, reverb->resampleFlags, DMEM_WET_LEFT_CH, reverb->filterLeftState); @@ -303,14 +311,14 @@ Acmd* AudioSynth_FilterReverb(Acmd* cmd, s32 count, SynthesisReverb* reverb) { return cmd; } -Acmd* AudioSynth_MaybeMixRingBuffer1(Acmd* cmd, SynthesisReverb* reverb, s32 arg2) { +Acmd* AudioSynth_MaybeMixRingBuffer1(Acmd* cmd, SynthesisReverb* reverb, s32 updateIndex) { SynthesisReverb* temp_a3; temp_a3 = &gAudioContext.synthesisReverbs[reverb->unk_05]; if (temp_a3->downsampleRate == 1) { - cmd = AudioSynth_LoadRingBuffer1AtTemp(cmd, temp_a3, arg2); + cmd = AudioSynth_LoadRingBuffer1AtTemp(cmd, temp_a3, updateIndex); aMix(cmd++, 0x34, reverb->unk_08, DMEM_WET_LEFT_CH, DMEM_WET_TEMP); - cmd = AudioSynth_SaveRingBuffer1AtTemp(cmd, temp_a3, arg2); + cmd = AudioSynth_SaveRingBuffer1AtTemp(cmd, temp_a3, updateIndex); } return cmd; } @@ -454,8 +462,8 @@ void AudioSynth_LoadFilterCount(Acmd* cmd, s32 count, s32 addr) { aFilter(cmd, 2, count, addr); } -Acmd* AudioSynth_LoadRingBuffer1(Acmd* cmd, s32 arg1, SynthesisReverb* reverb, s16 bufIndex) { - ReverbRingBufferItem* ringBufferItem = &reverb->items[reverb->curFrame][bufIndex]; +Acmd* AudioSynth_LoadRingBuffer1(Acmd* cmd, s32 aiBufLen, SynthesisReverb* reverb, s16 updateIndex) { + ReverbRingBufferItem* ringBufferItem = &reverb->items[reverb->curFrame][updateIndex]; cmd = AudioSynth_LoadRingBufferPart(cmd, DMEM_WET_LEFT_CH, ringBufferItem->startPos, ringBufferItem->lengthA, reverb); @@ -468,8 +476,8 @@ Acmd* AudioSynth_LoadRingBuffer1(Acmd* cmd, s32 arg1, SynthesisReverb* reverb, s return cmd; } -Acmd* AudioSynth_LoadRingBuffer2(Acmd* cmd, s32 arg1, SynthesisReverb* reverb, s16 bufIndex) { - ReverbRingBufferItem* bufItem = &reverb->items2[reverb->curFrame][bufIndex]; +Acmd* AudioSynth_LoadRingBuffer2(Acmd* cmd, s32 aiBufLen, SynthesisReverb* reverb, s16 updateIndex) { + ReverbRingBufferItem* bufItem = &reverb->items2[reverb->curFrame][updateIndex]; cmd = AudioSynth_LoadRingBufferPart(cmd, DMEM_WET_LEFT_CH, bufItem->startPos, bufItem->lengthA, reverb); if (bufItem->lengthB != 0) { @@ -496,34 +504,34 @@ Acmd* AudioSynth_SaveBufferOffset(Acmd* cmd, u16 dmem, u16 offset, s32 length, s return cmd; } -Acmd* AudioSynth_MaybeLoadRingBuffer2(Acmd* cmd, s32 arg1, SynthesisReverb* reverb, s16 bufIndex) { +Acmd* AudioSynth_MaybeLoadRingBuffer2(Acmd* cmd, s32 aiBufLen, SynthesisReverb* reverb, s16 updateIndex) { if (reverb->downsampleRate == 1) { - cmd = AudioSynth_LoadRingBuffer2(cmd, arg1, reverb, bufIndex); + cmd = AudioSynth_LoadRingBuffer2(cmd, aiBufLen, reverb, updateIndex); } return cmd; } -Acmd* func_800DC164(Acmd* cmd, s32 arg1, SynthesisReverb* reverb, s16 arg3) { +Acmd* AudioSynth_LoadReverbSamples(Acmd* cmd, s32 aiBufLen, SynthesisReverb* reverb, s16 updateIndex) { // Sets DMEM_WET_{LEFT,RIGHT}_CH, clobbers DMEM_TEMP if (reverb->downsampleRate == 1) { if (reverb->unk_18 != 0) { - cmd = func_800DB828(cmd, arg1, reverb, arg3); + cmd = func_800DB828(cmd, aiBufLen, reverb, updateIndex); } else { - cmd = AudioSynth_LoadRingBuffer1(cmd, arg1, reverb, arg3); + cmd = AudioSynth_LoadRingBuffer1(cmd, aiBufLen, reverb, updateIndex); } } else { - cmd = func_800DB4E4(cmd, arg1, reverb, arg3); + cmd = func_800DB4E4(cmd, aiBufLen, reverb, updateIndex); } return cmd; } -Acmd* AudioSynth_SaveReverbSamples(Acmd* cmd, SynthesisReverb* reverb, s16 bufIndex) { - ReverbRingBufferItem* bufItem = &reverb->items[reverb->curFrame][bufIndex]; +Acmd* AudioSynth_SaveReverbSamples(Acmd* cmd, SynthesisReverb* reverb, s16 updateIndex) { + ReverbRingBufferItem* bufItem = &reverb->items[reverb->curFrame][updateIndex]; if (reverb->downsampleRate == 1) { if (reverb->unk_18 != 0) { - cmd = func_800DB680(cmd, reverb, bufIndex); + cmd = func_800DB680(cmd, reverb, updateIndex); } else { // Put the oldest samples in the ring buffer into the wet channels cmd = AudioSynth_SaveRingBufferPart(cmd, DMEM_WET_LEFT_CH, bufItem->startPos, bufItem->lengthA, reverb); @@ -537,15 +545,15 @@ Acmd* AudioSynth_SaveReverbSamples(Acmd* cmd, SynthesisReverb* reverb, s16 bufIn // Downsampling is done later by CPU when RSP is done, therefore we need to have // double buffering. Left and right buffers are adjacent in memory. AudioSynth_SaveBuffer(cmd++, DMEM_WET_LEFT_CH, DEFAULT_LEN_2CH, - reverb->items[reverb->curFrame][bufIndex].toDownsampleLeft); + reverb->items[reverb->curFrame][updateIndex].toDownsampleLeft); } reverb->resampleFlags = 0; return cmd; } -Acmd* AudioSynth_SaveRingBuffer2(Acmd* cmd, SynthesisReverb* reverb, s16 bufIndex) { - ReverbRingBufferItem* bufItem = &reverb->items2[reverb->curFrame][bufIndex]; +Acmd* AudioSynth_SaveRingBuffer2(Acmd* cmd, SynthesisReverb* reverb, s16 updateIndex) { + ReverbRingBufferItem* bufItem = &reverb->items2[reverb->curFrame][updateIndex]; cmd = AudioSynth_SaveRingBufferPart(cmd, DMEM_WET_LEFT_CH, bufItem->startPos, bufItem->lengthA, reverb); if (bufItem->lengthB != 0) { @@ -594,24 +602,36 @@ Acmd* AudioSynth_DoOneAudioUpdate(s16* aiBuf, s32 aiBufLen, Acmd* cmd, s32 updat } aClearBuffer(cmd++, DMEM_LEFT_CH, DEFAULT_LEN_2CH); + i = 0; for (reverbIndex = 0; reverbIndex < gAudioContext.numSynthesisReverbs; reverbIndex++) { reverb = &gAudioContext.synthesisReverbs[reverbIndex]; useReverb = reverb->useReverb; if (useReverb) { - cmd = func_800DC164(cmd, aiBufLen, reverb, updateIndex); - aMix(cmd++, 0x34, reverb->unk_0A, DMEM_WET_LEFT_CH, DMEM_LEFT_CH); + + // Loads reverb samples from RDRAM (ringBuffer) into DMEM (DMEM_WET_LEFT_CH) + cmd = AudioSynth_LoadReverbSamples(cmd, aiBufLen, reverb, updateIndex); + + // Mixes reverb sample into the main dry channel + // reverb->volume is always set to 0x7FFF (audio spec), and DMEM_LEFT_CH is cleared before the loop. + // So for the first iteration, this is essentially a DMEMmove from DMEM_WET_LEFT_CH to DMEM_LEFT_CH + aMix(cmd++, DEFAULT_LEN_2CH >> 4, reverb->volume, DMEM_WET_LEFT_CH, DMEM_LEFT_CH); + unk14 = reverb->unk_14; if (unk14) { aDMEMMove(cmd++, DMEM_WET_LEFT_CH, DMEM_WET_TEMP, DEFAULT_LEN_2CH); } - aMix(cmd++, 0x34, reverb->unk_0C + 0x8000, DMEM_WET_LEFT_CH, DMEM_WET_LEFT_CH); + // Decays reverb over time. The (+ 0x8000) here is -100% + aMix(cmd++, DEFAULT_LEN_2CH >> 4, reverb->decayRatio + 0x8000, DMEM_WET_LEFT_CH, DMEM_WET_LEFT_CH); + + // Leak reverb between the left and right channels if (reverb->leakRtl != 0 || reverb->leakLtr != 0) { cmd = AudioSynth_LeakReverb(cmd, reverb); } if (unk14) { + // Saves the wet channel sample from DMEM (DMEM_WET_LEFT_CH) into RDRAM (ringBuffer) for future use cmd = AudioSynth_SaveReverbSamples(cmd, reverb, updateIndex); if (reverb->unk_05 != -1) { cmd = AudioSynth_MaybeMixRingBuffer1(cmd, reverb, updateIndex); @@ -637,6 +657,8 @@ Acmd* AudioSynth_DoOneAudioUpdate(s16* aiBuf, s32 aiBufLen, Acmd* cmd, s32 updat if (reverb->filterLeft != NULL || reverb->filterRight != NULL) { cmd = AudioSynth_FilterReverb(cmd, aiBufLen * 2, reverb); } + + // Saves the wet channel sample from DMEM (DMEM_WET_LEFT_CH) into RDRAM (ringBuffer) for future use if (unk14) { cmd = AudioSynth_SaveRingBuffer2(cmd, reverb, updateIndex); } else { @@ -675,7 +697,7 @@ Acmd* AudioSynth_ProcessNote(s32 noteIndex, NoteSubEu* noteSubEu, NoteSynthesisS u16 resamplingRateFixedPoint; s32 nSamplesInFirstFrame; s32 nTrailingSamplesToIgnore; - s32 phi_a1_2; + s32 gain; s32 frameIndex; s32 skipBytes; s32 temp_v1_6; @@ -835,16 +857,19 @@ Acmd* AudioSynth_ProcessNote(s32 noteIndex, NoteSubEu* noteSubEu, NoteSynthesisS skipInitialSamples = 16; sampleDataStart = 0; break; + case CODEC_SMALL_ADPCM: frameSize = 5; skipInitialSamples = 16; sampleDataStart = 0; break; + case CODEC_S8: frameSize = 16; skipInitialSamples = 16; sampleDataStart = 0; break; + case CODEC_S16_INMEMORY: AudioSynth_ClearBuffer(cmd++, DMEM_UNCOMPRESSED_NOTE, (samplesLenAdjusted * 2) + 0x20); flags = A_CONTINUE; @@ -852,6 +877,7 @@ Acmd* AudioSynth_ProcessNote(s32 noteIndex, NoteSubEu* noteSubEu, NoteSynthesisS nSamplesProcessed = samplesLenAdjusted; s5 = samplesLenAdjusted; goto skip; + case CODEC_S16: AudioSynth_ClearBuffer(cmd++, DMEM_UNCOMPRESSED_NOTE, (samplesLenAdjusted * 2) + 0x20); flags = A_CONTINUE; @@ -859,6 +885,7 @@ Acmd* AudioSynth_ProcessNote(s32 noteIndex, NoteSubEu* noteSubEu, NoteSynthesisS nSamplesProcessed = samplesLenAdjusted; s5 = samplesLenAdjusted; goto skip; + case CODEC_REVERB: break; } @@ -902,6 +929,7 @@ Acmd* AudioSynth_ProcessNote(s32 noteIndex, NoteSubEu* noteSubEu, NoteSynthesisS } else { phi_s4 = ALIGN16(s5 + 16); } + switch (audioFontSample->codec) { case CODEC_ADPCM: aligned = ALIGN16((nFramesToDecode * frameSize) + 0x10); @@ -910,6 +938,7 @@ Acmd* AudioSynth_ProcessNote(s32 noteIndex, NoteSubEu* noteSubEu, NoteSynthesisS nSamplesToDecode * 2); aADPCMdec(cmd++, flags, synthState->synthesisBuffers->adpcmdecState); break; + case CODEC_SMALL_ADPCM: aligned = ALIGN16((nFramesToDecode * frameSize) + 0x10); addr = DMEM_COMPRESSED_ADPCM_DATA - aligned; @@ -917,6 +946,7 @@ Acmd* AudioSynth_ProcessNote(s32 noteIndex, NoteSubEu* noteSubEu, NoteSynthesisS nSamplesToDecode * 2); aADPCMdec(cmd++, flags | 4, synthState->synthesisBuffers->adpcmdecState); break; + case CODEC_S8: aligned = ALIGN16((nFramesToDecode * frameSize) + 0x10); addr = DMEM_COMPRESSED_ADPCM_DATA - aligned; @@ -938,9 +968,11 @@ Acmd* AudioSynth_ProcessNote(s32 noteIndex, NoteSubEu* noteSubEu, NoteSynthesisS skipBytes = 0x20; s5 = (nSamplesToDecode + 0x10) * 2; break; + case A_LOOP: s5 = nSamplesInThisIteration * 2 + s5; break; + default: if (s5 != 0) { s5 = nSamplesInThisIteration * 2 + s5; @@ -974,6 +1006,7 @@ Acmd* AudioSynth_ProcessNote(s32 noteIndex, NoteSubEu* noteSubEu, NoteSynthesisS case 1: noteSamplesDmemAddrBeforeResampling = DMEM_UNCOMPRESSED_NOTE + skipBytes; break; + case 2: switch (curPart) { case 0: @@ -986,6 +1019,7 @@ Acmd* AudioSynth_ProcessNote(s32 noteIndex, NoteSubEu* noteSubEu, NoteSynthesisS samplesLenAdjusted + 0x10); } break; + case 1: AudioSynth_InterL(cmd++, DMEM_UNCOMPRESSED_NOTE + skipBytes, DMEM_TEMP + 0x20 + resampledTempLen, ALIGN8(samplesLenAdjusted / 2)); @@ -1014,12 +1048,13 @@ Acmd* AudioSynth_ProcessNote(s32 noteIndex, NoteSubEu* noteSubEu, NoteSynthesisS AudioSynth_UnkCmd3(cmd++, DMEM_TEMP, DMEM_TEMP, aiBufLen * 2); } - phi_a1_2 = noteSubEu->unk_2; - if (phi_a1_2 != 0) { - if (phi_a1_2 < 0x10) { - phi_a1_2 = 0x10; + gain = noteSubEu->gain; + if (gain != 0) { + // A gain of 0x10 (a UQ4.4 number) is equivalent to 1.0 and represents no volume change + if (gain < 0x10) { + gain = 0x10; } - AudioSynth_HiLoGain(cmd++, phi_a1_2, DMEM_TEMP, 0, (aiBufLen * 2) + 0x20); + AudioSynth_HiLoGain(cmd++, gain, DMEM_TEMP, 0, (aiBufLen * 2) + 0x20); } filter = noteSubEu->filter; diff --git a/src/code/code_800E4FE0.c b/src/code/code_800E4FE0.c index 93419f4bee..1be420f2ae 100644 --- a/src/code/code_800E4FE0.c +++ b/src/code/code_800E4FE0.c @@ -68,10 +68,10 @@ AudioTask* func_800E5000(void) { } osSendMesg(gAudioContext.taskStartQueueP, (OSMesg)gAudioContext.totalTaskCount, OS_MESG_NOBLOCK); - gAudioContext.rspTaskIdx ^= 1; - gAudioContext.curAIBufIdx++; - gAudioContext.curAIBufIdx %= 3; - index = (gAudioContext.curAIBufIdx - 2 + 3) % 3; + gAudioContext.rspTaskIndex ^= 1; + gAudioContext.curAiBufIndex++; + gAudioContext.curAiBufIndex %= 3; + index = (gAudioContext.curAiBufIndex - 2 + 3) % 3; samplesRemainingInAi = osAiGetLength() / 4; if (gAudioContext.resetTimer < 16) { @@ -130,10 +130,10 @@ AudioTask* func_800E5000(void) { gAudioContext.resetTimer++; } - gAudioContext.currTask = &gAudioContext.rspTask[gAudioContext.rspTaskIdx]; - gAudioContext.curAbiCmdBuf = gAudioContext.abiCmdBufs[gAudioContext.rspTaskIdx]; + gAudioContext.curTask = &gAudioContext.rspTask[gAudioContext.rspTaskIndex]; + gAudioContext.curAbiCmdBuf = gAudioContext.abiCmdBufs[gAudioContext.rspTaskIndex]; - index = gAudioContext.curAIBufIdx; + index = gAudioContext.curAiBufIndex; currAiBuffer = gAudioContext.aiBuffers[index]; gAudioContext.aiBufLengths[index] = @@ -171,11 +171,11 @@ AudioTask* func_800E5000(void) { gAudioContext.aiBuffers[index][gAudioContext.totalTaskCount & 0xFF] + gAudioContext.audioRandom; gWaveSamples[8] = (s16*)(((u8*)func_800E4FE0) + (gAudioContext.audioRandom & 0xFFF0)); - index = gAudioContext.rspTaskIdx; - gAudioContext.currTask->msgQueue = NULL; - gAudioContext.currTask->unk_44 = NULL; + index = gAudioContext.rspTaskIndex; + gAudioContext.curTask->msgQueue = NULL; + gAudioContext.curTask->unk_44 = NULL; - task = &gAudioContext.currTask->task.t; + task = &gAudioContext.curTask->task.t; task->type = M_AUDTASK; task->flags = 0; task->ucode_boot = aspMainTextStart; @@ -199,9 +199,9 @@ AudioTask* func_800E5000(void) { } if (gAudioContext.audioBufferParameters.specUnk4 == 1) { - return gAudioContext.currTask; + return gAudioContext.curTask; } else { - sWaitingAudioTask = gAudioContext.currTask; + sWaitingAudioTask = gAudioContext.curTask; return NULL; } } @@ -219,14 +219,17 @@ void func_800E5584(AudioCmd* cmd) { switch (cmd->op) { case 0x81: AudioLoad_SyncLoadSeqParts(cmd->arg1, cmd->arg2); - return; + break; + case 0x82: AudioLoad_SyncInitSeqPlayer(cmd->arg0, cmd->arg1, cmd->arg2); func_800E59AC(cmd->arg0, cmd->data); - return; + break; + case 0x85: AudioLoad_SyncInitSeqPlayerSkipTicks(cmd->arg0, cmd->arg1, cmd->data); - return; + break; + case 0x83: if (gAudioContext.seqPlayers[cmd->arg0].enabled) { if (cmd->asInt == 0) { @@ -235,22 +238,27 @@ void func_800E5584(AudioCmd* cmd) { func_800E5958(cmd->arg0, cmd->asInt); } } - return; + break; + case 0xF0: gAudioContext.soundMode = cmd->asUInt; - return; + break; + case 0xF1: for (i = 0; i < gAudioContext.audioBufferParameters.numSequencePlayers; i++) { SequencePlayer* seqPlayer = &gAudioContext.seqPlayers[i]; + seqPlayer->muted = 1; seqPlayer->recalculateVolume = 1; } - return; + break; + case 0xF2: if (cmd->asUInt == 1) { for (i = 0; i < gAudioContext.numNotes; i++) { Note* note = &gAudioContext.notes[i]; NoteSubEu* subEu = ¬e->noteSubEu; + if (subEu->bitField0.enabled && note->playbackState.unk_04 == 0) { if (note->playbackState.parentLayer->channel->muteBehavior & 8) { subEu->bitField0.finished = 1; @@ -261,58 +269,71 @@ void func_800E5584(AudioCmd* cmd) { for (i = 0; i < gAudioContext.audioBufferParameters.numSequencePlayers; i++) { SequencePlayer* seqPlayer = &gAudioContext.seqPlayers[i]; + seqPlayer->muted = 0; seqPlayer->recalculateVolume = 1; } + break; - return; case 0xF3: AudioLoad_SyncLoadInstrument(cmd->arg0, cmd->arg1, cmd->arg2); - return; + break; + case 0xF4: AudioLoad_AsyncLoadSampleBank(cmd->arg0, cmd->arg1, cmd->arg2, &gAudioContext.externalLoadQueue); - return; + break; + case 0xF5: AudioLoad_AsyncLoadFont(cmd->arg0, cmd->arg1, cmd->arg2, &gAudioContext.externalLoadQueue); - return; + break; + case 0xFC: AudioLoad_AsyncLoadSeq(cmd->arg0, cmd->arg1, cmd->arg2, &gAudioContext.externalLoadQueue); - return; + break; + case 0xF6: AudioLoad_DiscardSeqFonts(cmd->arg1); - return; + break; + case 0x90: gAudioContext.unk_5BDC[cmd->arg0] = cmd->asUShort; - return; + break; + case 0xF9: gAudioContext.resetStatus = 5; gAudioContext.audioResetSpecIdToLoad = cmd->asUInt; - return; + break; + case 0xFB: D_801755D0 = (void (*)(void))cmd->asUInt; - return; + break; + case 0xE0: case 0xE1: case 0xE2: Audio_SetFontInstrument(cmd->op - 0xE0, cmd->arg0, cmd->arg1, cmd->data); - return; + break; + case 0xFE: temp_t7 = cmd->asUInt; if (temp_t7 == 1) { for (i = 0; i < gAudioContext.audioBufferParameters.numSequencePlayers; i++) { SequencePlayer* seqPlayer = &gAudioContext.seqPlayers[i]; + if (seqPlayer->enabled) { AudioSeq_SequencePlayerDisableAsFinished(seqPlayer); } } } func_800E66C0(temp_t7); - return; + break; + case 0xE3: AudioHeap_PopCache(cmd->asInt); - return; + break; + default: - return; + break; } } @@ -332,6 +353,7 @@ void func_800E5958(s32 playerIdx, s32 fadeTimer) { // SetFadeInTimer void func_800E59AC(s32 playerIdx, s32 fadeTimer) { SequencePlayer* seqPlayer; + if (fadeTimer != 0) { seqPlayer = &gAudioContext.seqPlayers[playerIdx]; seqPlayer->state = 1; @@ -443,7 +465,7 @@ void Audio_ProcessCmd(AudioCmd* cmd) { } if (cmd->arg1 == 0xFF) { phi_v0 = gAudioContext.unk_5BDC[cmd->arg0]; - for (i = 0; i < 0x10; i++) { + for (i = 0; i < 16; i++) { if (phi_v0 & 1) { func_800E6300(seqPlayer->channels[i], cmd); } @@ -556,6 +578,7 @@ void Audio_PreNMIInternal(void) { s8 func_800E6070(s32 playerIdx, s32 channelIdx, s32 scriptIdx) { SequencePlayer* seqPlayer = &gAudioContext.seqPlayers[playerIdx]; SequenceChannel* channel; + if (seqPlayer->enabled) { channel = seqPlayer->channels[channelIdx]; return channel->soundScriptIO[scriptIdx]; @@ -564,45 +587,53 @@ s8 func_800E6070(s32 playerIdx, s32 channelIdx, s32 scriptIdx) { } } -s8 func_800E60C4(s32 playerIdx, s32 arg1) { - return gAudioContext.seqPlayers[playerIdx].soundScriptIO[arg1]; +s8 func_800E60C4(s32 playerIdx, s32 port) { + return gAudioContext.seqPlayers[playerIdx].soundScriptIO[port]; } -void Audio_InitExternalPool(void* mem, u32 size) { - AudioHeap_AllocPoolInit(&gAudioContext.externalPool, mem, size); +void Audio_InitExternalPool(void* ramAddr, u32 size) { + AudioHeap_AllocPoolInit(&gAudioContext.externalPool, ramAddr, size); } void Audio_DestroyExternalPool(void) { - gAudioContext.externalPool.start = NULL; + gAudioContext.externalPool.startRamAddr = NULL; } void func_800E6128(SequencePlayer* seqPlayer, AudioCmd* cmd) { f32 fadeVolume; + switch (cmd->op) { case 0x41: if (seqPlayer->fadeVolumeScale != cmd->asFloat) { seqPlayer->fadeVolumeScale = cmd->asFloat; seqPlayer->recalculateVolume = 1; } - return; + break; + case 0x47: seqPlayer->tempo = cmd->asInt * 0x30; - return; + break; + case 0x49: seqPlayer->unk_0C = cmd->asInt * 0x30; - return; + break; + case 0x4E: seqPlayer->unk_0C = cmd->asInt; - return; + break; + case 0x48: seqPlayer->transposition = cmd->asSbyte; - return; + break; + case 0x46: seqPlayer->soundScriptIO[cmd->arg2] = cmd->asSbyte; - return; + break; + case 0x4A: fadeVolume = (s32)cmd->arg1 / 127.0f; goto block_11; + case 0x4B: fadeVolume = ((s32)cmd->arg1 / 100.0f) * seqPlayer->fadeVolume; block_11: @@ -611,32 +642,40 @@ void func_800E6128(SequencePlayer* seqPlayer, AudioCmd* cmd) { if (cmd->asInt == 0) { seqPlayer->fadeVolume = fadeVolume; } else { - s32 tmp = cmd->asInt; + s32 fadeTimer = cmd->asInt; + seqPlayer->state = 0; - seqPlayer->fadeTimer = tmp; - seqPlayer->fadeVelocity = (fadeVolume - seqPlayer->fadeVolume) / tmp; + seqPlayer->fadeTimer = fadeTimer; + seqPlayer->fadeVelocity = (fadeVolume - seqPlayer->fadeVolume) / fadeTimer; } } - return; + break; + case 0x4C: if (seqPlayer->state != 2) { if (cmd->asInt == 0) { seqPlayer->fadeVolume = seqPlayer->volume; } else { - s32 tmp = cmd->asInt; + s32 fadeTimer = cmd->asInt; + seqPlayer->state = 0; - seqPlayer->fadeTimer = tmp; - seqPlayer->fadeVelocity = (seqPlayer->volume - seqPlayer->fadeVolume) / tmp; + seqPlayer->fadeTimer = fadeTimer; + seqPlayer->fadeVelocity = (seqPlayer->volume - seqPlayer->fadeVolume) / fadeTimer; } } - return; + break; + case 0x4D: - seqPlayer->unk_34 = cmd->asFloat; - if (seqPlayer->unk_34 == 1.0f) { - seqPlayer->unk_0b1 = 0; + seqPlayer->bend = cmd->asFloat; + if (seqPlayer->bend == 1.0f) { + seqPlayer->applyBend = false; } else { - seqPlayer->unk_0b1 = 1; + seqPlayer->applyBend = true; } + break; + + default: + break; } } @@ -647,64 +686,80 @@ void func_800E6300(SequenceChannel* channel, AudioCmd* cmd) { channel->volumeScale = cmd->asFloat; channel->changes.s.volume = 1; } - return; + break; + case CHAN_UPD_VOL: if (channel->volume != cmd->asFloat) { channel->volume = cmd->asFloat; channel->changes.s.volume = 1; } - return; + break; + case CHAN_UPD_PAN_SIGNED: if (channel->newPan != cmd->asSbyte) { channel->newPan = cmd->asSbyte; channel->changes.s.pan = 1; } - return; + break; + case CHAN_UPD_PAN_UNSIGNED: if (channel->newPan != cmd->asSbyte) { channel->panChannelWeight = cmd->asSbyte; channel->changes.s.pan = 1; } - return; + break; + case CHAN_UPD_FREQ_SCALE: if (channel->freqScale != cmd->asFloat) { channel->freqScale = cmd->asFloat; channel->changes.s.freqScale = 1; } - return; + break; + case CHAN_UPD_REVERB: if (channel->reverb != cmd->asSbyte) { channel->reverb = cmd->asSbyte; } - return; + break; + case CHAN_UPD_SCRIPT_IO: if (cmd->arg2 < 8) { channel->soundScriptIO[cmd->arg2] = cmd->asSbyte; } - return; + break; + case CHAN_UPD_STOP_SOMETHING2: channel->stopSomething2 = cmd->asSbyte; - return; + break; + case CHAN_UPD_MUTE_BEHAVE: channel->muteBehavior = cmd->asSbyte; - return; + break; + case CHAN_UPD_VIBE_X8: channel->vibratoExtentTarget = cmd->asUbyte * 8; channel->vibratoExtentChangeDelay = 1; - return; + break; + case CHAN_UPD_VIBE_X32: channel->vibratoRateTarget = cmd->asUbyte * 32; channel->vibratoRateChangeDelay = 1; - return; + break; + case CHAN_UPD_UNK_0F: channel->unk_0F = cmd->asUbyte; - return; + break; + case CHAN_UPD_UNK_20: channel->unk_20 = cmd->asUShort; - return; + break; + case CHAN_UPD_STEREO: channel->stereo.asByte = cmd->asUbyte; - return; + break; + + default: + break; } } diff --git a/src/code/code_800EC960.c b/src/code/code_800EC960.c index 523af6200f..72bdd600db 100644 --- a/src/code/code_800EC960.c +++ b/src/code/code_800EC960.c @@ -2873,8 +2873,8 @@ void AudioDebug_Draw(GfxPrint* printer) { GfxPrint_SetPos(printer, 3, 5); GfxPrint_Printf(printer, "DRIVER %05X / %05X", - gAudioContext.notesAndBuffersPool.cur - gAudioContext.notesAndBuffersPool.start, - gAudioContext.notesAndBuffersPool.size); + gAudioContext.miscPool.curRamAddr - gAudioContext.miscPool.startRamAddr, + gAudioContext.miscPool.size); GfxPrint_SetPos(printer, 3, 6); GfxPrint_Printf( @@ -2890,7 +2890,8 @@ void AudioDebug_Draw(GfxPrint* printer) { GfxPrint_SetPos(printer, 3, 8); GfxPrint_Printf(printer, "ST-SEQ %02Xseqs (%05X / %06X)", gAudioContext.seqCache.persistent.numEntries, - gAudioContext.seqCache.persistent.pool.cur - gAudioContext.seqCache.persistent.pool.start, + gAudioContext.seqCache.persistent.pool.curRamAddr - + gAudioContext.seqCache.persistent.pool.startRamAddr, gAudioContext.seqCache.persistent.pool.size); for (k = 0; (u32)k < gAudioContext.seqCache.persistent.numEntries; k++) { @@ -2900,7 +2901,8 @@ void AudioDebug_Draw(GfxPrint* printer) { GfxPrint_SetPos(printer, 3, 10); GfxPrint_Printf(printer, "ST-BNK %02Xbanks (%05X / %06X)", gAudioContext.fontCache.persistent.numEntries, - gAudioContext.fontCache.persistent.pool.cur - gAudioContext.fontCache.persistent.pool.start, + gAudioContext.fontCache.persistent.pool.curRamAddr - + gAudioContext.fontCache.persistent.pool.startRamAddr, gAudioContext.fontCache.persistent.pool.size); for (k = 0; (u32)k < gAudioContext.fontCache.persistent.numEntries; k++) { @@ -2910,7 +2912,7 @@ void AudioDebug_Draw(GfxPrint* printer) { GfxPrint_SetPos(printer, 3, 12); GfxPrint_Printf(printer, "E-MEM %05X / %05X", - gAudioContext.permanentPool.cur - gAudioContext.permanentPool.start, + gAudioContext.permanentPool.curRamAddr - gAudioContext.permanentPool.startRamAddr, gAudioContext.permanentPool.size); break;