1
0
Fork 0
mirror of https://github.com/zeldaret/oot.git synced 2025-05-11 11:33:48 +00:00

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 <fig02srl@gmail.com>
This commit is contained in:
engineer124 2022-06-04 05:59:02 +10:00 committed by GitHub
parent 1738b19d63
commit e989cb7ace
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 1177 additions and 907 deletions

View file

@ -1806,8 +1806,8 @@ void* AudioLoad_DmaSampleData(u32 devAddr, u32 size, s32 arg2, u8* dmaIndexRef,
void AudioLoad_InitSampleDmaBuffers(s32 arg0); void AudioLoad_InitSampleDmaBuffers(s32 arg0);
s32 AudioLoad_IsFontLoadComplete(s32 fontId); s32 AudioLoad_IsFontLoadComplete(s32 fontId);
s32 AudioLoad_IsSeqLoadComplete(s32 seqId); s32 AudioLoad_IsSeqLoadComplete(s32 seqId);
void AudioLoad_SetFontLoadStatus(s32 fontId, s32 status); void AudioLoad_SetFontLoadStatus(s32 fontId, s32 loadStatus);
void AudioLoad_SetSeqLoadStatus(s32 seqId, s32 status); void AudioLoad_SetSeqLoadStatus(s32 seqId, s32 loadStatus);
void AudioLoad_SyncLoadSeqParts(s32 seqId, s32 arg1); void AudioLoad_SyncLoadSeqParts(s32 seqId, s32 arg1);
s32 AudioLoad_SyncLoadInstrument(s32 fontId, s32 instId, s32 drumId); s32 AudioLoad_SyncLoadInstrument(s32 fontId, s32 instId, s32 drumId);
void AudioLoad_AsyncLoadSeq(s32 seqId, s32 arg1, s32 retData, OSMesgQueue* retQueue); 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_SetDmaHandler(DmaHandler callback);
void AudioLoad_Init(void* heap, u32 heapSize); void AudioLoad_Init(void* heap, u32 heapSize);
void AudioLoad_InitSlowLoads(void); void AudioLoad_InitSlowLoads(void);
s32 AudioLoad_SlowLoadSample(s32 fontId, s32 instId, s8* isDone); s32 AudioLoad_SlowLoadSample(s32 fontId, s32 instId, s8* status);
s32 AudioLoad_SlowLoadSeq(s32 seqId, u8* ramAddr, s8* isDone); s32 AudioLoad_SlowLoadSeq(s32 seqId, u8* ramAddr, s8* status);
void AudioLoad_InitAsyncLoads(void); void AudioLoad_InitAsyncLoads(void);
void AudioLoad_LoadPermanentSamples(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_ProcessScriptLoads(void);
void AudioLoad_InitScriptLoads(void); void AudioLoad_InitScriptLoads(void);
AudioTask* func_800E4FE0(void); AudioTask* func_800E4FE0(void);

View file

@ -126,8 +126,8 @@ extern s16 D_8012FBA8[];
extern f32 gHeadsetPanVolume[128]; extern f32 gHeadsetPanVolume[128];
extern f32 gStereoPanVolume[128]; extern f32 gStereoPanVolume[128];
extern f32 gDefaultPanVolume[128]; extern f32 gDefaultPanVolume[128];
extern s16 sLowPassFilterData[16*8]; extern s16 gLowPassFilterData[16 * 8];
extern s16 sHighPassFilterData[15*8]; extern s16 gHighPassFilterData[15 * 8];
extern s32 gAudioContextInitalized; extern s32 gAudioContextInitalized;
extern u8 gIsLargeSoundBank[7]; extern u8 gIsLargeSoundBank[7];
extern u8 gChannelsPerBank[4][7]; extern u8 gChannelsPerBank[4][7];

View file

@ -59,6 +59,15 @@ typedef enum {
/* 3 */ CACHE_PERMANENT /* 3 */ CACHE_PERMANENT
} AudioCacheType; } 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); typedef s32 (*DmaHandler)(OSPiHandle* handle, OSIoMesg* mb, s32 direction);
struct Note; struct Note;
@ -88,7 +97,7 @@ typedef struct NotePool {
/* 0x10 */ AudioListItem decaying; /* 0x10 */ AudioListItem decaying;
/* 0x20 */ AudioListItem releasing; /* 0x20 */ AudioListItem releasing;
/* 0x30 */ AudioListItem active; /* 0x30 */ AudioListItem active;
} NotePool; } NotePool; // size = 0x40
// Pitch sliding by up to one octave in the positive direction. Negative // Pitch sliding by up to one octave in the positive direction. Negative
// direction is "supported" by setting extent to be negative. The code // direction is "supported" by setting extent to be negative. The code
@ -158,8 +167,8 @@ typedef struct {
/* 0x005 */ s8 unk_05; /* 0x005 */ s8 unk_05;
/* 0x006 */ u16 windowSize; /* 0x006 */ u16 windowSize;
/* 0x008 */ s16 unk_08; /* 0x008 */ s16 unk_08;
/* 0x00A */ s16 unk_0A; /* 0x00A */ s16 volume;
/* 0x00C */ u16 unk_0C; /* 0x00C */ u16 decayRatio; // determines how much reverb persists
/* 0x00E */ u16 unk_0E; /* 0x00E */ u16 unk_0E;
/* 0x010 */ s16 leakRtl; /* 0x010 */ s16 leakRtl;
/* 0x012 */ s16 leakLtr; /* 0x012 */ s16 leakLtr;
@ -205,8 +214,8 @@ typedef struct {
/* 0x01 */ u8 pan; /* 0x01 */ u8 pan;
/* 0x02 */ u8 loaded; /* 0x02 */ u8 loaded;
/* 0x04 */ SoundFontSound sound; /* 0x04 */ SoundFontSound sound;
/* 0x14 */ AdsrEnvelope* envelope; /* 0x0C */ AdsrEnvelope* envelope;
} Drum; // size = 0x14 } Drum; // size = 0x10
typedef struct { typedef struct {
/* 0x00 */ u8 numInstruments; /* 0x00 */ u8 numInstruments;
@ -220,9 +229,9 @@ typedef struct {
} SoundFont; // size = 0x14 } SoundFont; // size = 0x14
typedef struct { typedef struct {
/* 0x00 */ u8* pc; /* 0x00 */ u8* pc; // program counter
/* 0x04 */ u8* stack[4]; /* 0x04 */ u8* stack[4];
/* 0x14 */ u8 remLoopIters[4]; /* 0x14 */ u8 remLoopIters[4]; // remaining loop iterations
/* 0x18 */ u8 depth; /* 0x18 */ u8 depth;
/* 0x19 */ s8 value; /* 0x19 */ s8 value;
} SeqScriptState; // size = 0x1C } SeqScriptState; // size = 0x1C
@ -236,7 +245,7 @@ typedef struct {
/* 0x000 */ u8 fontDmaInProgress : 1; /* 0x000 */ u8 fontDmaInProgress : 1;
/* 0x000 */ u8 recalculateVolume : 1; /* 0x000 */ u8 recalculateVolume : 1;
/* 0x000 */ u8 stopScript : 1; /* 0x000 */ u8 stopScript : 1;
/* 0x000 */ u8 unk_0b1 : 1; /* 0x000 */ u8 applyBend : 1;
/* 0x001 */ u8 state; /* 0x001 */ u8 state;
/* 0x002 */ u8 noteAllocPolicy; /* 0x002 */ u8 noteAllocPolicy;
/* 0x003 */ u8 muteBehavior; /* 0x003 */ u8 muteBehavior;
@ -258,7 +267,7 @@ typedef struct {
/* 0x028 */ f32 muteVolumeScale; /* 0x028 */ f32 muteVolumeScale;
/* 0x02C */ f32 fadeVolumeScale; /* 0x02C */ f32 fadeVolumeScale;
/* 0x030 */ f32 appliedFadeVolume; /* 0x030 */ f32 appliedFadeVolume;
/* 0x034 */ f32 unk_34; /* 0x034 */ f32 bend;
/* 0x038 */ struct SequenceChannel* channels[16]; /* 0x038 */ struct SequenceChannel* channels[16];
/* 0x078 */ SeqScriptState scriptState; /* 0x078 */ SeqScriptState scriptState;
/* 0x094 */ u8* shortNoteVelocityTable; /* 0x094 */ u8* shortNoteVelocityTable;
@ -296,7 +305,7 @@ typedef struct {
/* 0x14 */ f32 target; /* 0x14 */ f32 target;
/* 0x18 */ char unk_18[4]; /* 0x18 */ char unk_18[4];
/* 0x1C */ AdsrEnvelope* envelope; /* 0x1C */ AdsrEnvelope* envelope;
} AdsrState; } AdsrState; // size = 0x20
typedef struct { typedef struct {
/* 0x00 */ u8 unused : 2; /* 0x00 */ u8 unused : 2;
@ -305,16 +314,16 @@ typedef struct {
/* 0x00 */ u8 strongLeft : 1; /* 0x00 */ u8 strongLeft : 1;
/* 0x00 */ u8 stereoHeadsetEffects : 1; /* 0x00 */ u8 stereoHeadsetEffects : 1;
/* 0x00 */ u8 usesHeadsetPanEffects : 1; /* 0x00 */ u8 usesHeadsetPanEffects : 1;
} StereoData; } StereoData; // size = 0x1
typedef union { typedef union {
/* 0x00 */ StereoData s; /* 0x00 */ StereoData s;
/* 0x00 */ u8 asByte; /* 0x00 */ u8 asByte;
} Stereo; } Stereo; // size = 0x1
typedef struct { typedef struct {
/* 0x00 */ u8 reverb; /* 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; /* 0x02 */ u8 pan;
/* 0x03 */ Stereo stereo; /* 0x03 */ Stereo stereo;
/* 0x04 */ u8 unk_4; /* 0x04 */ u8 unk_4;
@ -353,7 +362,7 @@ typedef struct SequenceChannel {
/* 0x09 */ u8 bookOffset; /* 0x09 */ u8 bookOffset;
/* 0x0A */ u8 newPan; /* 0x0A */ u8 newPan;
/* 0x0B */ u8 panChannelWeight; // proportion of pan that comes from the channel (0..128) /* 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; /* 0x0D */ u8 velocityRandomVariance;
/* 0x0E */ u8 gateTimeRandomVariance; /* 0x0E */ u8 gateTimeRandomVariance;
/* 0x0F */ u8 unk_0F; /* 0x0F */ u8 unk_0F;
@ -419,7 +428,7 @@ typedef struct SequenceLayer {
/* 0x20 */ Portamento portamento; /* 0x20 */ Portamento portamento;
/* 0x2C */ struct Note* note; /* 0x2C */ struct Note* note;
/* 0x30 */ f32 freqScale; /* 0x30 */ f32 freqScale;
/* 0x34 */ f32 unk_34; /* 0x34 */ f32 bend;
/* 0x38 */ f32 velocitySquare2; /* 0x38 */ f32 velocitySquare2;
/* 0x3C */ f32 velocitySquare; // not sure which one of those corresponds to the sm64 original /* 0x3C */ f32 velocitySquare; // not sure which one of those corresponds to the sm64 original
/* 0x40 */ f32 noteVelocity; /* 0x40 */ f32 noteVelocity;
@ -487,8 +496,8 @@ typedef struct {
/* 0x18 */ SequenceLayer* wantedParentLayer; /* 0x18 */ SequenceLayer* wantedParentLayer;
/* 0x1C */ NoteAttributes attributes; /* 0x1C */ NoteAttributes attributes;
/* 0x40 */ AdsrState adsr; /* 0x40 */ AdsrState adsr;
// may contain portamento, vibratoState, if those are not part of Note itself // Majora's Mask suggests this struct contains portamento, vibratoState
} NotePlaybackState; } NotePlaybackState; // size = 0x60
typedef struct { typedef struct {
struct { struct {
@ -508,7 +517,7 @@ typedef struct {
/* 0x01 */ u8 hasTwoParts : 1; /* 0x01 */ u8 hasTwoParts : 1;
/* 0x01 */ u8 usesHeadsetPanEffects2 : 1; /* 0x01 */ u8 usesHeadsetPanEffects2 : 1;
} bitField1; } bitField1;
/* 0x02 */ u8 unk_2; /* 0x02 */ u8 gain; // Increases volume by a multiplicative scaling factor. Represented as a UQ4.4 number
/* 0x03 */ u8 headsetPanRight; /* 0x03 */ u8 headsetPanRight;
/* 0x04 */ u8 headsetPanLeft; /* 0x04 */ u8 headsetPanLeft;
/* 0x05 */ u8 reverbVol; /* 0x05 */ u8 reverbVol;
@ -540,10 +549,10 @@ typedef struct Note {
typedef struct { typedef struct {
/* 0x00 */ u8 downsampleRate; /* 0x00 */ u8 downsampleRate;
/* 0x02 */ u16 windowSize; /* 0x02 */ u16 windowSize;
/* 0x04 */ u16 unk_4; /* 0x04 */ u16 decayRatio; // determines how much reverb persists
/* 0x06 */ u16 unk_6; /* 0x06 */ u16 unk_6;
/* 0x08 */ u16 unk_8; /* 0x08 */ u16 unk_8;
/* 0x0A */ u16 unk_A; /* 0x0A */ u16 volume;
/* 0x0C */ u16 leakRtl; /* 0x0C */ u16 leakRtl;
/* 0x0E */ u16 leakLtr; /* 0x0E */ u16 leakLtr;
/* 0x10 */ s8 unk_10; /* 0x10 */ s8 unk_10;
@ -552,8 +561,12 @@ typedef struct {
/* 0x16 */ s16 lowPassFilterCutoffRight; /* 0x16 */ s16 lowPassFilterCutoffRight;
} ReverbSettings; // size = 0x18 } 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 { typedef struct {
/* 0x00 */ u32 frequency; /* 0x00 */ u32 samplingFrequency; // Target sampling rate in Hz
/* 0x04 */ u8 unk_04; /* 0x04 */ u8 unk_04;
/* 0x05 */ u8 numNotes; /* 0x05 */ u8 numNotes;
/* 0x06 */ u8 numSequencePlayers; /* 0x06 */ u8 numSequencePlayers;
@ -561,23 +574,28 @@ typedef struct {
/* 0x08 */ u8 unk_08; // unused, set to zero /* 0x08 */ u8 unk_08; // unused, set to zero
/* 0x09 */ u8 numReverbs; /* 0x09 */ u8 numReverbs;
/* 0x0C */ ReverbSettings* reverbSettings; /* 0x0C */ ReverbSettings* reverbSettings;
/* 0x10 */ u16 sampleDmaBufSize1; /* 0x10 */ u16 sampleDmaBufSize1; // size of buffers in the audio misc pool to store small snippets of individual samples. Stored short-lived.
/* 0x12 */ u16 sampleDmaBufSize2; /* 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; /* 0x14 */ u16 unk_14;
/* 0x18 */ u32 persistentSeqMem; /* 0x18 */ u32 persistentSeqCacheSize; // size of cache on audio pool to store sequences persistently
/* 0x1C */ u32 persistentFontMem; /* 0x1C */ u32 persistentFontCacheSize; // size of cache on audio pool to store soundFonts persistently
/* 0x20 */ u32 persistentSampleMem; /* 0x20 */ u32 persistentSampleBankCacheSize; // size of cache on audio pool to store entire sample banks persistently
/* 0x24 */ u32 temporarySeqMem; /* 0x24 */ u32 temporarySeqCacheSize; // size of cache on audio pool to store sequences temporarily
/* 0x28 */ u32 temporaryFontMem; /* 0x28 */ u32 temporaryFontCacheSize; // size of cache on audio pool to store soundFonts temporarily
/* 0x2C */ u32 temporarySampleMem; /* 0x2C */ u32 temporarySampleBankCacheSize; // size of cache on audio pool to store entire sample banks temporarily
/* 0x30 */ s32 persistentSampleCacheMem; /* 0x30 */ s32 persistentSampleCacheSize; // size of cache in the audio misc pool to store individual samples persistently
/* 0x34 */ s32 temporarySampleCacheMem; /* 0x34 */ s32 temporarySampleCacheSize; // size of cache in the audio misc pool to store individual samples temporarily
} AudioSpec; // size = 0x38 } 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 { typedef struct {
/* 0x00 */ s16 specUnk4; /* 0x00 */ s16 specUnk4;
/* 0x02 */ u16 frequency; /* 0x02 */ u16 samplingFrequency; // Target sampling rate in Hz
/* 0x04 */ u16 aiFrequency; /* 0x04 */ u16 aiSamplingFrequency; // True sampling rate of the audio interface (AI), see `osAiSetFrequency`
/* 0x06 */ s16 samplesPerFrameTarget; /* 0x06 */ s16 samplesPerFrameTarget;
/* 0x08 */ s16 maxAiBufferLength; /* 0x08 */ s16 maxAiBufferLength;
/* 0x0A */ s16 minAiBufferLength; /* 0x0A */ s16 minAiBufferLength;
@ -592,20 +610,29 @@ typedef struct {
/* 0x24 */ f32 updatesPerFrameScaled; // updatesPerFrame scaled down by a factor of 4 /* 0x24 */ f32 updatesPerFrameScaled; // updatesPerFrame scaled down by a factor of 4
} AudioBufferParameters; // size = 0x28 } AudioBufferParameters; // size = 0x28
/**
* Meta-data associated with a pool (contained within the Audio Heap)
*/
typedef struct { typedef struct {
/* 0x0 */ u8* start; /* 0x0 */ u8* startRamAddr; // start addr of the pool
/* 0x4 */ u8* cur; /* 0x4 */ u8* curRamAddr; // address of the next available memory for allocation
/* 0x8 */ s32 size; /* 0x8 */ s32 size; // size of the pool
/* 0xC */ s32 count; /* 0xC */ s32 numEntries; // number of entries allocated to the pool
} AudioAllocPool; // size = 0x10 } AudioAllocPool; // size = 0x10
/**
* Audio cache entry data to store a single entry containing either a sequence, soundfont, or entire sample banks
*/
typedef struct { typedef struct {
/* 0x0 */ u8* ptr; /* 0x0 */ u8* ramAddr;
/* 0x4 */ u32 size; /* 0x4 */ u32 size;
/* 0x8 */ s16 tableType; /* 0x8 */ s16 tableType;
/* 0xA */ s16 id; /* 0xA */ s16 id;
} AudioCacheEntry; // size = 0xC } AudioCacheEntry; // size = 0xC
/**
* Audio cache entry data to store a single entry containing an individual sample
*/
typedef struct { typedef struct {
/* 0x00 */ s8 inUse; /* 0x00 */ s8 inUse;
/* 0x01 */ s8 origMedium; /* 0x01 */ s8 origMedium;
@ -616,10 +643,13 @@ typedef struct {
/* 0x10 */ u32 size; /* 0x10 */ u32 size;
} SampleCacheEntry; // size = 0x14 } SampleCacheEntry; // size = 0x14
/**
* Audio cache entry data to store individual samples
*/
typedef struct { typedef struct {
/* 0x000 */ AudioAllocPool pool; /* 0x000 */ AudioAllocPool pool;
/* 0x010 */ SampleCacheEntry entries[32]; /* 0x010 */ SampleCacheEntry entries[32];
/* 0x290 */ s32 size; /* 0x290 */ s32 numEntries;
} AudioSampleCache; // size = 0x294 } AudioSampleCache; // size = 0x294
typedef struct { typedef struct {
@ -641,22 +671,21 @@ typedef struct {
} AudioCache; // size = 0x110 } AudioCache; // size = 0x110
typedef struct { typedef struct {
u32 wantPersistent; /* 0x0 */ u32 persistentCommonPoolSize;
u32 wantTemporary; /* 0x4 */ u32 temporaryCommonPoolSize;
} AudioPoolSplit2; // size = 0x8 } AudioCachePoolSplit; // size = 0x8
typedef struct { typedef struct {
u32 wantSeq; /* 0x0 */ u32 seqCacheSize;
u32 wantFont; /* 0x4 */ u32 fontCacheSize;
u32 wantSample; /* 0x8 */ u32 sampleBankCacheSize;
} AudioPoolSplit3; // size = 0xC } AudioCommonPoolSplit; // size = 0xC
typedef struct { typedef struct {
u32 wantSeq; /* 0x0 */ u32 miscPoolSize;
u32 wantFont; /* 0x4 */ u32 unkSizes[2];
u32 wantSample; /* 0xC */ u32 cachePoolSize;
u32 wantCustom; } AudioSessionPoolSplit; // size = 0x10
} AudioPoolSplit4; // size = 0x10
typedef struct { typedef struct {
/* 0x00 */ u32 endAndMediumKey; /* 0x00 */ u32 endAndMediumKey;
@ -666,8 +695,11 @@ typedef struct {
/* 0x10 */ s32 isFree; /* 0x10 */ s32 isFree;
} AudioPreloadReq; // size = 0x14 } AudioPreloadReq; // size = 0x14
/**
* Audio commands used to transfer audio requests from the graph thread to the audio thread
*/
typedef struct { typedef struct {
union{ /* 0x0 */ union{
u32 opArgs; u32 opArgs;
struct { struct {
u8 op; u8 op;
@ -676,7 +708,7 @@ typedef struct {
u8 arg2; u8 arg2;
}; };
}; };
union { /* 0x4 */ union {
void* data; void* data;
f32 asFloat; f32 asFloat;
s32 asInt; s32 asInt;
@ -685,7 +717,7 @@ typedef struct {
u8 asUbyte; u8 asUbyte;
u32 asUInt; u32 asUInt;
}; };
} AudioCmd; } AudioCmd; // size = 0x8
typedef struct { typedef struct {
/* 0x00 */ s8 status; /* 0x00 */ s8 status;
@ -712,9 +744,9 @@ typedef struct {
/* 0x08 */ s32 curDevAddr; /* 0x08 */ s32 curDevAddr;
/* 0x0C */ u8* curRamAddr; /* 0x0C */ u8* curRamAddr;
/* 0x10 */ u8* ramAddr; /* 0x10 */ u8* ramAddr;
/* 0x14 */ s32 status; /* 0x14 */ s32 state;
/* 0x18 */ s32 bytesRemaining; /* 0x18 */ s32 bytesRemaining;
/* 0x1C */ s8* isDone; /* 0x1C */ s8* status; // write-only
/* 0x20 */ SoundFontSample sample; /* 0x20 */ SoundFontSample sample;
/* 0x30 */ OSMesgQueue msgQueue; /* 0x30 */ OSMesgQueue msgQueue;
/* 0x48 */ OSMesg msg; /* 0x48 */ OSMesg msg;
@ -759,7 +791,7 @@ typedef struct {
typedef struct { typedef struct {
/* 0x0000 */ char unk_0000; /* 0x0000 */ char unk_0000;
/* 0x0001 */ s8 numSynthesisReverbs; /* 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; /* 0x0004 */ u16 unk_4;
/* 0x0006 */ char unk_0006[0x0A]; /* 0x0006 */ char unk_0006[0x0A];
/* 0x0010 */ s16* curLoadedBook; /* 0x0010 */ s16* curLoadedBook;
@ -794,10 +826,10 @@ typedef struct {
/* 0x2628 */ s32 unused2628; /* 0x2628 */ s32 unused2628;
/* 0x262C */ u8 sampleDmaReuseQueue1[0x100]; // read pos <= write pos, wrapping mod 256 /* 0x262C */ u8 sampleDmaReuseQueue1[0x100]; // read pos <= write pos, wrapping mod 256
/* 0x272C */ u8 sampleDmaReuseQueue2[0x100]; /* 0x272C */ u8 sampleDmaReuseQueue2[0x100];
/* 0x282C */ u8 sampleDmaReuseQueue1RdPos; /* 0x282C */ u8 sampleDmaReuseQueue1RdPos; // Read position for short-lived sampleDma
/* 0x282D */ u8 sampleDmaReuseQueue2RdPos; /* 0x282D */ u8 sampleDmaReuseQueue2RdPos; // Read position for long-lived sampleDma
/* 0x282E */ u8 sampleDmaReuseQueue1WrPos; /* 0x282E */ u8 sampleDmaReuseQueue1WrPos; // Write position for short-lived sampleDma
/* 0x282F */ u8 sampleDmaReuseQueue2WrPos; /* 0x282F */ u8 sampleDmaReuseQueue2WrPos; // Write position for long-lived sampleDma
/* 0x2830 */ AudioTable* sequenceTable; /* 0x2830 */ AudioTable* sequenceTable;
/* 0x2834 */ AudioTable* soundFontTable; /* 0x2834 */ AudioTable* soundFontTable;
/* 0x2838 */ AudioTable* sampleBankTable; /* 0x2838 */ AudioTable* sampleBankTable;
@ -814,13 +846,13 @@ typedef struct {
/* 0x2894 */ s32 numNotes; /* 0x2894 */ s32 numNotes;
/* 0x2898 */ s16 tempoInternalToExternal; /* 0x2898 */ s16 tempoInternalToExternal;
/* 0x289A */ s8 soundMode; /* 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; /* 0x28A0 */ s32 curAudioFrameDmaCount;
/* 0x28A4 */ s32 rspTaskIdx; /* 0x28A4 */ s32 rspTaskIndex;
/* 0x28A8 */ s32 curAIBufIdx; /* 0x28A8 */ s32 curAiBufIndex;
/* 0x28AC */ Acmd* abiCmdBufs[2]; /* 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; /* 0x28B4 */ Acmd* curAbiCmdBuf; // Pointer to the currently active abiCmdBufs
/* 0x28B8 */ AudioTask* currTask; /* 0x28B8 */ AudioTask* curTask;
/* 0x28BC */ char unk_28BC[0x4]; /* 0x28BC */ char unk_28BC[0x4];
/* 0x28C0 */ AudioTask rspTask[2]; /* 0x28C0 */ AudioTask rspTask[2];
/* 0x2960 */ f32 unk_2960; /* 0x2960 */ f32 unk_2960;
@ -831,25 +863,25 @@ typedef struct {
/* 0x2980 */ s32 audioErrorFlags; /* 0x2980 */ s32 audioErrorFlags;
/* 0x2984 */ volatile u32 resetTimer; /* 0x2984 */ volatile u32 resetTimer;
/* 0x2988 */ char unk_2988[0x8]; /* 0x2988 */ char unk_2988[0x8];
/* 0x2990 */ AudioAllocPool audioSessionPool; /* 0x2990 */ AudioAllocPool audioSessionPool; // A sub-pool to main pool, contains all sub-pools and data that changes every audio reset
/* 0x29A0 */ AudioAllocPool externalPool; /* 0x29A0 */ AudioAllocPool externalPool; // pool allocated externally to the audio heap. Never used in game
/* 0x29B0 */ AudioAllocPool audioInitPool; /* 0x29B0 */ AudioAllocPool audioInitPool;// A sub-pool to the main pool, contains all sub-pools and data that persists every audio reset
/* 0x29C0 */ AudioAllocPool notesAndBuffersPool; /* 0x29C0 */ AudioAllocPool miscPool; // A sub-pool to the session pool.
/* 0x29D0 */ char unk_29D0[0x20]; // probably two unused pools /* 0x29D0 */ char unk_29D0[0x20]; // probably two unused pools
/* 0x29F0 */ AudioAllocPool cachePool; /* 0x29F0 */ AudioAllocPool cachePool; // The common pool for cache entries
/* 0x2A00 */ AudioAllocPool persistentCommonPool; /* 0x2A00 */ AudioAllocPool persistentCommonPool; // A sub-pool to the cache pool, contains caches for data stored persistently
/* 0x2A10 */ AudioAllocPool temporaryCommonPool; /* 0x2A10 */ AudioAllocPool temporaryCommonPool; // A sub-pool to the cache pool, contains caches for data stored temporarily
/* 0x2A20 */ AudioCache seqCache; /* 0x2A20 */ AudioCache seqCache; // Cache to store sequences
/* 0x2B30 */ AudioCache fontCache; /* 0x2B30 */ AudioCache fontCache; // Cache to store soundFonts
/* 0x2C40 */ AudioCache sampleBankCache; /* 0x2C40 */ AudioCache sampleBankCache; // Cache for loading entire sample banks
/* 0x2D50 */ AudioAllocPool permanentPool; /* 0x2D50 */ AudioAllocPool permanentPool; // Pool to store audio data that is always loaded. Used for sfxs
/* 0x2D60 */ AudioCacheEntry permanentCache[32]; /* 0x2D60 */ AudioCacheEntry permanentCache[32]; // individual entries to the permanent pool
/* 0x2EE0 */ AudioSampleCache persistentSampleCache; /* 0x2EE0 */ AudioSampleCache persistentSampleCache; // Stores individual samples persistently
/* 0x3174 */ AudioSampleCache temporarySampleCache; /* 0x3174 */ AudioSampleCache temporarySampleCache; // Stores individual samples temporarily
/* 0x3408 */ AudioPoolSplit4 sessionPoolSplit; /* 0x3408 */ AudioSessionPoolSplit sessionPoolSplit; // splits session pool into the cache pool and misc pool
/* 0x3418 */ AudioPoolSplit2 cachePoolSplit; /* 0x3418 */ AudioCachePoolSplit cachePoolSplit; // splits cache pool into the persistent & temporary common pools
/* 0x3420 */ AudioPoolSplit3 persistentCommonPoolSplit; /* 0x3420 */ AudioCommonPoolSplit persistentCommonPoolSplit;// splits persistent common pool into caches for sequences, soundFonts, sample banks
/* 0x342C */ AudioPoolSplit3 temporaryCommonPoolSplit; /* 0x342C */ AudioCommonPoolSplit temporaryCommonPoolSplit; // splits temporary common pool into caches for sequences, soundFonts, sample banks
/* 0x3438 */ u8 sampleFontLoadStatus[0x30]; /* 0x3438 */ u8 sampleFontLoadStatus[0x30];
/* 0x3468 */ u8 fontLoadStatus[0x30]; /* 0x3468 */ u8 fontLoadStatus[0x30];
/* 0x3498 */ u8 seqLoadStatus[0x80]; /* 0x3498 */ u8 seqLoadStatus[0x80];
@ -879,12 +911,12 @@ typedef struct {
/* 0x5C38 */ OSMesg taskStartMsgBuf[1]; /* 0x5C38 */ OSMesg taskStartMsgBuf[1];
/* 0x5C3C */ OSMesg audioResetMsgBuf[1]; /* 0x5C3C */ OSMesg audioResetMsgBuf[1];
/* 0x5C40 */ OSMesg cmdProcMsgBuf[4]; /* 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 } AudioContext; // size = 0x6450
typedef struct { typedef struct {
/* 0x00 */ u8 reverbVol; /* 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; /* 0x02 */ u8 pan;
/* 0x03 */ Stereo stereo; /* 0x03 */ Stereo stereo;
/* 0x04 */ f32 frequency; /* 0x04 */ f32 frequency;
@ -896,8 +928,8 @@ typedef struct {
} NoteSubAttributes; // size = 0x18 } NoteSubAttributes; // size = 0x18
typedef struct { typedef struct {
/* 0x00 */ u32 heapSize; /* 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; /* 0x04 */ u32 initPoolSize; // The entire audio heap is split into two pools.
/* 0x08 */ u32 permanentPoolSize; /* 0x08 */ u32 permanentPoolSize;
} AudioContextInitSizes; // size = 0xC } AudioContextInitSizes; // size = 0xC

View file

@ -625,7 +625,7 @@ f32 gDefaultPanVolume[] = {
0.086471f, 0.074143f, 0.061803f, 0.049454f, 0.037097f, 0.024734f, 0.012368f, 0.0f, 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) /* 0x0 */ 0, 0, 0, 32767, 0, 0, 0, 0, // Identity filter (delta function)
/* 0x1 */ 3854, 4188, 4398, 4469, 4398, 4188, 3854, 3416, /* 0x1 */ 3854, 4188, 4398, 4469, 4398, 4188, 3854, 3416,
/* 0x2 */ 3415, 4314, 4915, 5126, 4915, 4314, 3415, 2351, /* 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, /* 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, /* 0x0 */ -289, -291, -289, 30736, -289, -291, -289, -290,
/* 0x1 */ -464, -467, -467, 29506, -467, -467, -464, -463, /* 0x1 */ -464, -467, -467, 29506, -467, -467, -464, -463,
/* 0x2 */ -662, -670, -672, 28101, -672, -670, -662, -656, /* 0x2 */ -662, -670, -672, 28101, -672, -670, -662, -656,

View file

@ -1,7 +1,7 @@
#include "ultra64.h" #include "ultra64.h"
#include "global.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 channelVolume;
f32 chanFreqScale; f32 chanFreqScale;
s32 i; s32 i;
@ -19,13 +19,14 @@ void Audio_SequenceChannelProcessSound(SequenceChannel* channel, s32 recalculate
} }
chanFreqScale = channel->freqScale; chanFreqScale = channel->freqScale;
if (b != 0) { if (applyBend) {
chanFreqScale *= channel->seqPlayer->unk_34; chanFreqScale *= channel->seqPlayer->bend;
channel->changes.s.freqScale = true; channel->changes.s.freqScale = true;
} }
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
SequenceLayer* layer = channel->layers[i]; SequenceLayer* layer = channel->layers[i];
if (layer != NULL && layer->enabled && layer->note != NULL) { if (layer != NULL && layer->enabled && layer->note != NULL) {
if (layer->notePropertiesNeedInit) { if (layer->notePropertiesNeedInit) {
layer->noteFreqScale = layer->freqScale * chanFreqScale; layer->noteFreqScale = layer->freqScale * chanFreqScale;
@ -58,11 +59,12 @@ void Audio_SequencePlayerProcessSound(SequencePlayer* seqPlayer) {
if (seqPlayer->fadeVolume > 1.0f) { if (seqPlayer->fadeVolume > 1.0f) {
seqPlayer->fadeVolume = 1.0f; seqPlayer->fadeVolume = 1.0f;
} }
if (seqPlayer->fadeVolume < 0) { if (seqPlayer->fadeVolume < 0.0f) {
seqPlayer->fadeVolume = 0; seqPlayer->fadeVolume = 0.0f;
} }
if (--seqPlayer->fadeTimer == 0 && seqPlayer->state == 2) { seqPlayer->fadeTimer--;
if (seqPlayer->fadeTimer == 0 && seqPlayer->state == 2) {
AudioSeq_SequencePlayerDisable(seqPlayer); AudioSeq_SequencePlayerDisable(seqPlayer);
return; return;
} }
@ -74,31 +76,34 @@ void Audio_SequencePlayerProcessSound(SequencePlayer* seqPlayer) {
for (i = 0; i < 16; i++) { for (i = 0; i < 16; i++) {
if (seqPlayer->channels[i]->enabled == 1) { 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; seqPlayer->recalculateVolume = false;
} }
f32 Audio_GetPortamentoFreqScale(Portamento* p) { f32 Audio_GetPortamentoFreqScale(Portamento* portamento) {
u32 loResCur; u32 loResCur;
f32 result; f32 portamentoFreq;
p->cur += p->speed; portamento->cur += portamento->speed;
loResCur = (p->cur >> 8) & 0xFF; loResCur = (portamento->cur >> 8) & 0xFF;
if (loResCur >= 127) { if (loResCur >= 127) {
loResCur = 127; loResCur = 127;
p->mode = 0; portamento->mode = 0;
} }
result = 1.0f + p->extent * (gBendPitchOneOctaveFrequencies[loResCur + 128] - 1.0f); portamentoFreq = 1.0f + portamento->extent * (gBendPitchOneOctaveFrequencies[loResCur + 128] - 1.0f);
return result;
return portamentoFreq;
} }
s16 Audio_GetVibratoPitchChange(VibratoState* vib) { s16 Audio_GetVibratoPitchChange(VibratoState* vib) {
s32 index; s32 index;
vib->time += (s32)vib->rate; vib->time += (s32)vib->rate;
index = (vib->time >> 10) & 0x3F; index = (vib->time >> 10) & 0x3F;
return vib->curve[index]; return vib->curve[index];
@ -116,7 +121,7 @@ f32 Audio_GetVibratoFreqScale(VibratoState* vib) {
if (vib->delay != 0) { if (vib->delay != 0) {
vib->delay--; vib->delay--;
return 1; return 1.0f;
} }
//! @bug this probably meant to compare with gAudioContext.sequenceChannelNone. //! @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; return 1.0f;
} }

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -9,13 +9,13 @@ void Audio_InitNoteSub(Note* note, NoteSubEu* sub, NoteSubAttributes* attrs) {
f32 vel; f32 vel;
u8 pan; u8 pan;
u8 reverbVol; u8 reverbVol;
StereoData sp24; StereoData stereoData;
s32 stereoHeadsetEffects = note->playbackState.stereoHeadsetEffects; s32 stereoHeadsetEffects = note->playbackState.stereoHeadsetEffects;
vel = attrs->velocity; vel = attrs->velocity;
pan = attrs->pan; pan = attrs->pan;
reverbVol = attrs->reverbVol; reverbVol = attrs->reverbVol;
sp24 = attrs->stereo.s; stereoData = attrs->stereo.s;
sub->bitField0 = note->noteSubEu.bitField0; sub->bitField0 = note->noteSubEu.bitField0;
sub->bitField1 = note->noteSubEu.bitField1; sub->bitField1 = note->noteSubEu.bitField1;
@ -28,8 +28,8 @@ void Audio_InitNoteSub(Note* note, NoteSubEu* sub, NoteSubAttributes* attrs) {
sub->bitField0.stereoStrongRight = false; sub->bitField0.stereoStrongRight = false;
sub->bitField0.stereoStrongLeft = false; sub->bitField0.stereoStrongLeft = false;
sub->bitField0.stereoHeadsetEffects = sp24.stereoHeadsetEffects; sub->bitField0.stereoHeadsetEffects = stereoData.stereoHeadsetEffects;
sub->bitField0.usesHeadsetPanEffects = sp24.usesHeadsetPanEffects; sub->bitField0.usesHeadsetPanEffects = stereoData.usesHeadsetPanEffects;
if (stereoHeadsetEffects && gAudioContext.soundMode == 1) { if (stereoHeadsetEffects && gAudioContext.soundMode == 1) {
smallPanIndex = pan >> 1; smallPanIndex = pan >> 1;
if (smallPanIndex > 0x3F) { if (smallPanIndex > 0x3F) {
@ -59,20 +59,23 @@ void Audio_InitNoteSub(Note* note, NoteSubEu* sub, NoteSubAttributes* attrs) {
sub->bitField0.stereoStrongRight = strongRight; sub->bitField0.stereoStrongRight = strongRight;
sub->bitField0.stereoStrongLeft = strongLeft; sub->bitField0.stereoStrongLeft = strongLeft;
switch (sp24.bit2) { switch (stereoData.bit2) {
case 0: case 0:
break; break;
case 1: case 1:
sub->bitField0.stereoStrongRight = sp24.strongRight; sub->bitField0.stereoStrongRight = stereoData.strongRight;
sub->bitField0.stereoStrongLeft = sp24.strongLeft; sub->bitField0.stereoStrongLeft = stereoData.strongLeft;
break; break;
case 2: case 2:
sub->bitField0.stereoStrongRight = sp24.strongRight | strongRight; sub->bitField0.stereoStrongRight = stereoData.strongRight | strongRight;
sub->bitField0.stereoStrongLeft = sp24.strongLeft | strongLeft; sub->bitField0.stereoStrongLeft = stereoData.strongLeft | strongLeft;
break; break;
case 3: case 3:
sub->bitField0.stereoStrongRight = sp24.strongRight ^ strongRight; sub->bitField0.stereoStrongRight = stereoData.strongRight ^ strongRight;
sub->bitField0.stereoStrongLeft = sp24.strongLeft ^ strongLeft; sub->bitField0.stereoStrongLeft = stereoData.strongLeft ^ strongLeft;
break; break;
} }
@ -82,8 +85,8 @@ void Audio_InitNoteSub(Note* note, NoteSubEu* sub, NoteSubAttributes* attrs) {
volLeft = 0.707f; // approx 1/sqrt(2) volLeft = 0.707f; // approx 1/sqrt(2)
volRight = 0.707f; volRight = 0.707f;
} else { } else {
sub->bitField0.stereoStrongRight = sp24.strongRight; sub->bitField0.stereoStrongRight = stereoData.strongRight;
sub->bitField0.stereoStrongLeft = sp24.strongLeft; sub->bitField0.stereoStrongLeft = stereoData.strongLeft;
volLeft = gDefaultPanVolume[pan]; volLeft = gDefaultPanVolume[pan];
volRight = gDefaultPanVolume[0x7F - 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->targetVolLeft = (s32)((vel * volLeft) * (0x1000 - 0.001f));
sub->targetVolRight = (s32)((vel * volRight) * (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->filter = attrs->filter;
sub->unk_07 = attrs->unk_14; sub->unk_07 = attrs->unk_14;
sub->unk_0E = attrs->unk_16; sub->unk_0E = attrs->unk_16;
@ -106,16 +109,11 @@ void Audio_NoteSetResamplingRate(NoteSubEu* noteSubEu, f32 resamplingRateInput)
if (resamplingRateInput < 2.0f) { if (resamplingRateInput < 2.0f) {
noteSubEu->bitField1.hasTwoParts = false; noteSubEu->bitField1.hasTwoParts = false;
resamplingRate = CLAMP_MAX(resamplingRateInput, 1.99998f);
if (1.99998f < resamplingRateInput) {
resamplingRate = 1.99998f;
} else {
resamplingRate = resamplingRateInput;
}
} else { } else {
noteSubEu->bitField1.hasTwoParts = true; noteSubEu->bitField1.hasTwoParts = true;
if (3.99996f < resamplingRateInput) { if (resamplingRateInput > 3.99996f) {
resamplingRate = 1.99998f; resamplingRate = 1.99998f;
} else { } else {
resamplingRate = resamplingRateInput * 0.5f; resamplingRate = resamplingRateInput * 0.5f;
@ -255,7 +253,7 @@ void Audio_ProcessNotes(void) {
subAttrs.pan = attrs->pan; subAttrs.pan = attrs->pan;
subAttrs.reverbVol = attrs->reverb; subAttrs.reverbVol = attrs->reverb;
subAttrs.stereo = attrs->stereo; subAttrs.stereo = attrs->stereo;
subAttrs.unk_1 = attrs->unk_1; subAttrs.gain = attrs->gain;
subAttrs.filter = attrs->filter; subAttrs.filter = attrs->filter;
subAttrs.unk_14 = attrs->unk_4; subAttrs.unk_14 = attrs->unk_4;
subAttrs.unk_16 = attrs->unk_6; subAttrs.unk_16 = attrs->unk_6;
@ -273,7 +271,7 @@ void Audio_ProcessNotes(void) {
subAttrs.stereo = layer->stereo; subAttrs.stereo = layer->stereo;
} }
subAttrs.reverbVol = channel->reverb; subAttrs.reverbVol = channel->reverb;
subAttrs.unk_1 = channel->unk_0C; subAttrs.gain = channel->gain;
subAttrs.filter = channel->filter; subAttrs.filter = channel->filter;
subAttrs.unk_14 = channel->unk_0F; subAttrs.unk_14 = channel->unk_0F;
subAttrs.unk_16 = channel->unk_20; subAttrs.unk_16 = channel->unk_20;
@ -297,6 +295,7 @@ void Audio_ProcessNotes(void) {
SoundFontSound* Audio_InstrumentGetSound(Instrument* instrument, s32 semitone) { SoundFontSound* Audio_InstrumentGetSound(Instrument* instrument, s32 semitone) {
SoundFontSound* sound; SoundFontSound* sound;
if (semitone < instrument->normalRangeLo) { if (semitone < instrument->normalRangeLo) {
sound = &instrument->lowNotesSound; sound = &instrument->lowNotesSound;
} else if (semitone <= instrument->normalRangeHi) { } else if (semitone <= instrument->normalRangeHi) {
@ -470,7 +469,7 @@ void Audio_SeqLayerDecayRelease(SequenceLayer* layer, s32 target) {
if (layer->channel != NULL) { if (layer->channel != NULL) {
chan = layer->channel; chan = layer->channel;
attrs->reverb = chan->reverb; attrs->reverb = chan->reverb;
attrs->unk_1 = chan->unk_0C; attrs->gain = chan->gain;
attrs->filter = chan->filter; attrs->filter = chan->filter;
if (attrs->filter != NULL) { if (attrs->filter != NULL) {
@ -849,62 +848,62 @@ Note* Audio_AllocNoteFromActive(NotePool* pool, SequenceLayer* layer) {
} }
Note* Audio_AllocNote(SequenceLayer* layer) { Note* Audio_AllocNote(SequenceLayer* layer) {
Note* ret; Note* note;
u32 policy = layer->channel->noteAllocPolicy; u32 policy = layer->channel->noteAllocPolicy;
if (policy & 1) { if (policy & 1) {
ret = layer->note; note = layer->note;
if (ret != NULL && ret->playbackState.prevParentLayer == layer && if (note != NULL && note->playbackState.prevParentLayer == layer &&
ret->playbackState.wantedParentLayer == NO_LAYER) { note->playbackState.wantedParentLayer == NO_LAYER) {
Audio_NoteReleaseAndTakeOwnership(ret, layer); Audio_NoteReleaseAndTakeOwnership(note, layer);
Audio_AudioListRemove(&ret->listItem); Audio_AudioListRemove(&note->listItem);
AudioSeq_AudioListPushBack(&ret->listItem.pool->releasing, &ret->listItem); AudioSeq_AudioListPushBack(&note->listItem.pool->releasing, &note->listItem);
return ret; return note;
} }
} }
if (policy & 2) { if (policy & 2) {
if (!(ret = Audio_AllocNoteFromDisabled(&layer->channel->notePool, layer)) && if (!(note = Audio_AllocNoteFromDisabled(&layer->channel->notePool, layer)) &&
!(ret = Audio_AllocNoteFromDecaying(&layer->channel->notePool, layer)) && !(note = Audio_AllocNoteFromDecaying(&layer->channel->notePool, layer)) &&
!(ret = Audio_AllocNoteFromActive(&layer->channel->notePool, layer))) { !(note = Audio_AllocNoteFromActive(&layer->channel->notePool, layer))) {
goto null_return; goto null_return;
} }
return ret; return note;
} }
if (policy & 4) { if (policy & 4) {
if (!(ret = Audio_AllocNoteFromDisabled(&layer->channel->notePool, layer)) && if (!(note = Audio_AllocNoteFromDisabled(&layer->channel->notePool, layer)) &&
!(ret = Audio_AllocNoteFromDisabled(&layer->channel->seqPlayer->notePool, layer)) && !(note = Audio_AllocNoteFromDisabled(&layer->channel->seqPlayer->notePool, layer)) &&
!(ret = Audio_AllocNoteFromDecaying(&layer->channel->notePool, layer)) && !(note = Audio_AllocNoteFromDecaying(&layer->channel->notePool, layer)) &&
!(ret = Audio_AllocNoteFromDecaying(&layer->channel->seqPlayer->notePool, layer)) && !(note = Audio_AllocNoteFromDecaying(&layer->channel->seqPlayer->notePool, layer)) &&
!(ret = Audio_AllocNoteFromActive(&layer->channel->notePool, layer)) && !(note = Audio_AllocNoteFromActive(&layer->channel->notePool, layer)) &&
!(ret = Audio_AllocNoteFromActive(&layer->channel->seqPlayer->notePool, layer))) { !(note = Audio_AllocNoteFromActive(&layer->channel->seqPlayer->notePool, layer))) {
goto null_return; goto null_return;
} }
return ret; return note;
} }
if (policy & 8) { if (policy & 8) {
if (!(ret = Audio_AllocNoteFromDisabled(&gAudioContext.noteFreeLists, layer)) && if (!(note = Audio_AllocNoteFromDisabled(&gAudioContext.noteFreeLists, layer)) &&
!(ret = Audio_AllocNoteFromDecaying(&gAudioContext.noteFreeLists, layer)) && !(note = Audio_AllocNoteFromDecaying(&gAudioContext.noteFreeLists, layer)) &&
!(ret = Audio_AllocNoteFromActive(&gAudioContext.noteFreeLists, layer))) { !(note = Audio_AllocNoteFromActive(&gAudioContext.noteFreeLists, layer))) {
goto null_return; goto null_return;
} }
return ret; return note;
} }
if (!(ret = Audio_AllocNoteFromDisabled(&layer->channel->notePool, layer)) && if (!(note = Audio_AllocNoteFromDisabled(&layer->channel->notePool, layer)) &&
!(ret = Audio_AllocNoteFromDisabled(&layer->channel->seqPlayer->notePool, layer)) && !(note = Audio_AllocNoteFromDisabled(&layer->channel->seqPlayer->notePool, layer)) &&
!(ret = Audio_AllocNoteFromDisabled(&gAudioContext.noteFreeLists, layer)) && !(note = Audio_AllocNoteFromDisabled(&gAudioContext.noteFreeLists, layer)) &&
!(ret = Audio_AllocNoteFromDecaying(&layer->channel->notePool, layer)) && !(note = Audio_AllocNoteFromDecaying(&layer->channel->notePool, layer)) &&
!(ret = Audio_AllocNoteFromDecaying(&layer->channel->seqPlayer->notePool, layer)) && !(note = Audio_AllocNoteFromDecaying(&layer->channel->seqPlayer->notePool, layer)) &&
!(ret = Audio_AllocNoteFromDecaying(&gAudioContext.noteFreeLists, layer)) && !(note = Audio_AllocNoteFromDecaying(&gAudioContext.noteFreeLists, layer)) &&
!(ret = Audio_AllocNoteFromActive(&layer->channel->notePool, layer)) && !(note = Audio_AllocNoteFromActive(&layer->channel->notePool, layer)) &&
!(ret = Audio_AllocNoteFromActive(&layer->channel->seqPlayer->notePool, layer)) && !(note = Audio_AllocNoteFromActive(&layer->channel->seqPlayer->notePool, layer)) &&
!(ret = Audio_AllocNoteFromActive(&gAudioContext.noteFreeLists, layer))) { !(note = Audio_AllocNoteFromActive(&gAudioContext.noteFreeLists, layer))) {
goto null_return; goto null_return;
} }
return ret; return note;
null_return: null_return:
layer->bit3 = true; layer->bit3 = true;
@ -932,6 +931,6 @@ void Audio_NoteInitAll(void) {
note->portamento.speed = 0; note->portamento.speed = 0;
note->playbackState.stereoHeadsetEffects = false; note->playbackState.stereoHeadsetEffects = false;
note->unk_BC = 0; note->unk_BC = 0;
note->synthesisState.synthesisBuffers = AudioHeap_AllocDmaMemory(&gAudioContext.notesAndBuffersPool, 0x1E0); note->synthesisState.synthesisBuffers = AudioHeap_AllocDmaMemory(&gAudioContext.miscPool, 0x1E0);
} }
} }

View file

@ -243,7 +243,7 @@ void AudioSeq_InitSequenceChannel(SequenceChannel* channel) {
channel->noteUnused = NULL; channel->noteUnused = NULL;
channel->reverbIndex = 0; channel->reverbIndex = 0;
channel->reverb = 0; channel->reverb = 0;
channel->unk_0C = 0; channel->gain = 0;
channel->notePriority = 3; channel->notePriority = 3;
channel->someOtherPriority = 1; channel->someOtherPriority = 1;
channel->delay = 0; channel->delay = 0;
@ -311,7 +311,7 @@ s32 AudioSeq_SeqChannelSetLayer(SequenceChannel* channel, s32 layerIdx) {
layer->note = NULL; layer->note = NULL;
layer->instrument = NULL; layer->instrument = NULL;
layer->freqScale = 1.0f; layer->freqScale = 1.0f;
layer->unk_34 = 1.0f; layer->bend = 1.0f;
layer->velocitySquare2 = 0.0f; layer->velocitySquare2 = 0.0f;
layer->instOrWave = 0xFF; layer->instOrWave = 0xFF;
return 0; return 0;
@ -410,10 +410,10 @@ void AudioSeq_SequencePlayerDisable(SequencePlayer* seqPlayer) {
seqPlayer->finished = true; seqPlayer->finished = true;
if (AudioLoad_IsSeqLoadComplete(seqPlayer->seqId)) { if (AudioLoad_IsSeqLoadComplete(seqPlayer->seqId)) {
AudioLoad_SetSeqLoadStatus(seqPlayer->seqId, 3); AudioLoad_SetSeqLoadStatus(seqPlayer->seqId, LOAD_STATUS_DISCARDABLE);
} }
if (AudioLoad_IsFontLoadComplete(seqPlayer->defaultFont)) { 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) { 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) { if (layer->note != NULL && layer->note->playbackState.parentLayer == layer) {
Note* note = layer->note; Note* note = layer->note;
Audio_NotePortamentoInit(note); Audio_NotePortamentoInit(note);
} }
return 0; return 0;
@ -707,7 +708,7 @@ s32 AudioSeq_SeqLayerProcessScriptStep2(SequenceLayer* layer) {
case 0xCE: case 0xCE:
tempByte = AudioSeq_ScriptReadU8(state); tempByte = AudioSeq_ScriptReadU8(state);
layer->unk_34 = gBendPitchTwoSemitonesFrequencies[(tempByte + 0x80) & 0xFF]; layer->bend = gBendPitchTwoSemitonesFrequencies[(tempByte + 0x80) & 0xFF];
break; break;
default: default:
@ -832,11 +833,13 @@ s32 AudioSeq_SeqLayerProcessScriptStep4(SequenceLayer* layer, s32 cmd) {
freqScale2 = temp_f2; freqScale2 = temp_f2;
freqScale = temp_f14; freqScale = temp_f14;
break; break;
case PORTAMENTO_MODE_2: case PORTAMENTO_MODE_2:
case PORTAMENTO_MODE_4: case PORTAMENTO_MODE_4:
freqScale = temp_f2; freqScale = temp_f2;
freqScale2 = temp_f14; freqScale2 = temp_f14;
break; break;
default: default:
freqScale = temp_f2; freqScale = temp_f2;
freqScale2 = temp_f2; freqScale2 = temp_f2;
@ -885,7 +888,7 @@ s32 AudioSeq_SeqLayerProcessScriptStep4(SequenceLayer* layer, s32 cmd) {
} }
layer->delay2 = layer->delay; layer->delay2 = layer->delay;
layer->freqScale *= layer->unk_34; layer->freqScale *= layer->bend;
if (layer->delay == 0) { if (layer->delay == 0) {
if (layer->sound != NULL) { if (layer->sound != NULL) {
time = (f32)layer->sound->sample->loop->end; time = (f32)layer->sound->sample->loop->end;
@ -905,6 +908,7 @@ s32 AudioSeq_SeqLayerProcessScriptStep4(SequenceLayer* layer, s32 cmd) {
// set when this is reached...) // set when this is reached...)
if (PORTAMENTO_IS_SPECIAL(*portamento)) { if (PORTAMENTO_IS_SPECIAL(*portamento)) {
s32 speed2; s32 speed2;
speed2 = seqPlayer->tempo * 0x8000 / gAudioContext.tempoInternalToExternal; speed2 = seqPlayer->tempo * 0x8000 / gAudioContext.tempoInternalToExternal;
speed2 = speed2 * 0x100 / (layer->delay * layer->portamentoTime); speed2 = speed2 * 0x100 / (layer->delay * layer->portamentoTime);
if (speed2 >= 0x7FFF) { if (speed2 >= 0x7FFF) {
@ -1431,7 +1435,7 @@ void AudioSeq_SequenceChannelProcessScript(SequenceChannel* channel) {
channel->vibratoRateStart = 0; channel->vibratoRateStart = 0;
channel->vibratoRateChangeDelay = 0; channel->vibratoRateChangeDelay = 0;
channel->filter = NULL; channel->filter = NULL;
channel->unk_0C = 0; channel->gain = 0;
channel->adsr.sustain = 0; channel->adsr.sustain = 0;
channel->velocityRandomVariance = 0; channel->velocityRandomVariance = 0;
channel->gateTimeRandomVariance = 0; channel->gateTimeRandomVariance = 0;
@ -1447,7 +1451,7 @@ void AudioSeq_SequenceChannelProcessScript(SequenceChannel* channel) {
case 0xED: case 0xED:
cmd = (u8)cmdArgs[0]; cmd = (u8)cmdArgs[0];
channel->unk_0C = cmd; channel->gain = cmd;
break; break;
case 0xB0: case 0xB0:
@ -1459,6 +1463,7 @@ void AudioSeq_SequenceChannelProcessScript(SequenceChannel* channel) {
case 0xB1: case 0xB1:
channel->filter = NULL; channel->filter = NULL;
break; break;
case 0xB3: case 0xB3:
cmd = cmdArgs[0]; cmd = cmdArgs[0];
@ -1654,8 +1659,8 @@ void AudioSeq_SequencePlayerProcessSequence(SequencePlayer* seqPlayer) {
return; return;
} }
AudioLoad_SetSeqLoadStatus(seqPlayer->seqId, 2); AudioLoad_SetSeqLoadStatus(seqPlayer->seqId, LOAD_STATUS_COMPLETE);
AudioLoad_SetFontLoadStatus(seqPlayer->defaultFont, 2); AudioLoad_SetFontLoadStatus(seqPlayer->defaultFont, LOAD_STATUS_COMPLETE);
if (seqPlayer->muted && (seqPlayer->muteBehavior & 0x80)) { if (seqPlayer->muted && (seqPlayer->muteBehavior & 0x80)) {
return; return;
@ -1714,15 +1719,18 @@ void AudioSeq_SequencePlayerProcessSequence(SequencePlayer* seqPlayer) {
} }
if (dummy) {} if (dummy) {}
break; break;
case 0xF0: case 0xF0:
Audio_NotePoolClear(&seqPlayer->notePool); Audio_NotePoolClear(&seqPlayer->notePool);
break; break;
case 0xDF: case 0xDF:
seqPlayer->transposition = 0; seqPlayer->transposition = 0;
FALLTHROUGH; FALLTHROUGH;
case 0xDE: case 0xDE:
seqPlayer->transposition += (s8)AudioSeq_ScriptReadU8(seqScript); seqPlayer->transposition += (s8)AudioSeq_ScriptReadU8(seqScript);
break; break;
case 0xDD: case 0xDD:
seqPlayer->tempo = AudioSeq_ScriptReadU8(seqScript) * 48; seqPlayer->tempo = AudioSeq_ScriptReadU8(seqScript) * 48;
if (seqPlayer->tempo > gAudioContext.tempoInternalToExternal) { if (seqPlayer->tempo > gAudioContext.tempoInternalToExternal) {
@ -1732,9 +1740,11 @@ void AudioSeq_SequencePlayerProcessSequence(SequencePlayer* seqPlayer) {
seqPlayer->tempo = 1; seqPlayer->tempo = 1;
} }
break; break;
case 0xDC: case 0xDC:
seqPlayer->unk_0C = (s8)AudioSeq_ScriptReadU8(seqScript) * 48; seqPlayer->unk_0C = (s8)AudioSeq_ScriptReadU8(seqScript) * 48;
break; break;
case 0xDA: case 0xDA:
command = AudioSeq_ScriptReadU8(seqScript); command = AudioSeq_ScriptReadU8(seqScript);
temp = AudioSeq_ScriptReadS16(seqScript); temp = AudioSeq_ScriptReadS16(seqScript);
@ -1746,6 +1756,7 @@ void AudioSeq_SequencePlayerProcessSequence(SequencePlayer* seqPlayer) {
seqPlayer->state = command; seqPlayer->state = command;
} }
break; break;
case 2: case 2:
seqPlayer->fadeTimer = temp; seqPlayer->fadeTimer = temp;
seqPlayer->state = command; seqPlayer->state = command;
@ -1753,6 +1764,7 @@ void AudioSeq_SequencePlayerProcessSequence(SequencePlayer* seqPlayer) {
break; break;
} }
break; break;
case 0xDB: case 0xDB:
value = AudioSeq_ScriptReadU8(seqScript); value = AudioSeq_ScriptReadU8(seqScript);
switch (seqPlayer->state) { switch (seqPlayer->state) {
@ -1769,29 +1781,37 @@ void AudioSeq_SequencePlayerProcessSequence(SequencePlayer* seqPlayer) {
seqPlayer->fadeVolume = (s32)value / 127.0f; seqPlayer->fadeVolume = (s32)value / 127.0f;
} }
break; break;
case 2: case 2:
break; break;
} }
break; break;
case 0xD9: case 0xD9:
seqPlayer->fadeVolumeScale = (s8)AudioSeq_ScriptReadU8(seqScript) / 127.0f; seqPlayer->fadeVolumeScale = (s8)AudioSeq_ScriptReadU8(seqScript) / 127.0f;
break; break;
case 0xD7: case 0xD7:
temp = AudioSeq_ScriptReadS16(seqScript); temp = AudioSeq_ScriptReadS16(seqScript);
AudioSeq_SequencePlayerSetupChannels(seqPlayer, temp); AudioSeq_SequencePlayerSetupChannels(seqPlayer, temp);
break; break;
case 0xD6: case 0xD6:
AudioSeq_ScriptReadS16(seqScript); AudioSeq_ScriptReadS16(seqScript);
break; break;
case 0xD5: case 0xD5:
seqPlayer->muteVolumeScale = (s8)AudioSeq_ScriptReadU8(seqScript) / 127.0f; seqPlayer->muteVolumeScale = (s8)AudioSeq_ScriptReadU8(seqScript) / 127.0f;
break; break;
case 0xD4: case 0xD4:
seqPlayer->muted = true; seqPlayer->muted = true;
break; break;
case 0xD3: case 0xD3:
seqPlayer->muteBehavior = AudioSeq_ScriptReadU8(seqScript); seqPlayer->muteBehavior = AudioSeq_ScriptReadU8(seqScript);
break; break;
case 0xD1: case 0xD1:
case 0xD2: case 0xD2:
temp = AudioSeq_ScriptReadS16(seqScript); temp = AudioSeq_ScriptReadS16(seqScript);
@ -1802,9 +1822,11 @@ void AudioSeq_SequencePlayerProcessSequence(SequencePlayer* seqPlayer) {
seqPlayer->shortNoteGateTimeTable = data3; seqPlayer->shortNoteGateTimeTable = data3;
} }
break; break;
case 0xD0: case 0xD0:
seqPlayer->noteAllocPolicy = AudioSeq_ScriptReadU8(seqScript); seqPlayer->noteAllocPolicy = AudioSeq_ScriptReadU8(seqScript);
break; break;
case 0xCE: case 0xCE:
command = AudioSeq_ScriptReadU8(seqScript); command = AudioSeq_ScriptReadU8(seqScript);
if (command == 0) { if (command == 0) {
@ -1813,7 +1835,8 @@ void AudioSeq_SequencePlayerProcessSequence(SequencePlayer* seqPlayer) {
seqScript->value = (gAudioContext.audioRandom >> 2) % command; seqScript->value = (gAudioContext.audioRandom >> 2) % command;
} }
break; break;
case 0xCD: {
case 0xCD:
temp = AudioSeq_ScriptReadS16(seqScript); temp = AudioSeq_ScriptReadS16(seqScript);
if ((seqScript->value != -1) && (seqScript->depth != 3)) { if ((seqScript->value != -1) && (seqScript->depth != 3)) {
@ -1825,32 +1848,39 @@ void AudioSeq_SequencePlayerProcessSequence(SequencePlayer* seqPlayer) {
seqScript->pc = &seqPlayer->seqData[temp]; seqScript->pc = &seqPlayer->seqData[temp];
} }
break; break;
}
case 0xCC: case 0xCC:
seqScript->value = AudioSeq_ScriptReadU8(seqScript); seqScript->value = AudioSeq_ScriptReadU8(seqScript);
break; break;
case 0xC9: case 0xC9:
seqScript->value &= AudioSeq_ScriptReadU8(seqScript); seqScript->value &= AudioSeq_ScriptReadU8(seqScript);
break; break;
case 0xC8: case 0xC8:
seqScript->value -= AudioSeq_ScriptReadU8(seqScript); seqScript->value -= AudioSeq_ScriptReadU8(seqScript);
break; break;
case 0xC7: case 0xC7:
command = AudioSeq_ScriptReadU8(seqScript); command = AudioSeq_ScriptReadU8(seqScript);
temp = AudioSeq_ScriptReadS16(seqScript); temp = AudioSeq_ScriptReadS16(seqScript);
data2 = &seqPlayer->seqData[temp]; data2 = &seqPlayer->seqData[temp];
*data2 = (u8)seqScript->value + command; *data2 = (u8)seqScript->value + command;
break; break;
case 0xC6: case 0xC6:
seqPlayer->stopScript = true; seqPlayer->stopScript = true;
return; return;
case 0xC5: case 0xC5:
seqPlayer->scriptCounter = (u16)AudioSeq_ScriptReadS16(seqScript); seqPlayer->scriptCounter = (u16)AudioSeq_ScriptReadS16(seqScript);
break; break;
case 0xEF: case 0xEF:
AudioSeq_ScriptReadS16(seqScript); AudioSeq_ScriptReadS16(seqScript);
AudioSeq_ScriptReadU8(seqScript); AudioSeq_ScriptReadU8(seqScript);
break; break;
case 0xC4: case 0xC4:
command = AudioSeq_ScriptReadU8(seqScript); command = AudioSeq_ScriptReadU8(seqScript);
if (command == 0xFF) { if (command == 0xFF) {
@ -1870,12 +1900,15 @@ void AudioSeq_SequencePlayerProcessSequence(SequencePlayer* seqPlayer) {
case 0x00: case 0x00:
seqScript->value = seqPlayer->channels[commandLow]->enabled ^ 1; seqScript->value = seqPlayer->channels[commandLow]->enabled ^ 1;
break; break;
case 0x50: case 0x50:
seqScript->value -= seqPlayer->soundScriptIO[commandLow]; seqScript->value -= seqPlayer->soundScriptIO[commandLow];
break; break;
case 0x70: case 0x70:
seqPlayer->soundScriptIO[commandLow] = seqScript->value; seqPlayer->soundScriptIO[commandLow] = seqScript->value;
break; break;
case 0x80: case 0x80:
seqScript->value = seqPlayer->soundScriptIO[commandLow]; seqScript->value = seqPlayer->soundScriptIO[commandLow];
if (commandLow < 2) { if (commandLow < 2) {
@ -1885,20 +1918,24 @@ void AudioSeq_SequencePlayerProcessSequence(SequencePlayer* seqPlayer) {
case 0x40: case 0x40:
AudioSeq_SequenceChannelDisable(seqPlayer->channels[commandLow]); AudioSeq_SequenceChannelDisable(seqPlayer->channels[commandLow]);
break; break;
case 0x90: case 0x90:
temp = AudioSeq_ScriptReadS16(seqScript); temp = AudioSeq_ScriptReadS16(seqScript);
AudioSeq_SequenceChannelEnable(seqPlayer, commandLow, (void*)&seqPlayer->seqData[temp]); AudioSeq_SequenceChannelEnable(seqPlayer, commandLow, (void*)&seqPlayer->seqData[temp]);
break; break;
case 0xA0: case 0xA0:
tempS = AudioSeq_ScriptReadS16(seqScript); tempS = AudioSeq_ScriptReadS16(seqScript);
AudioSeq_SequenceChannelEnable(seqPlayer, commandLow, (void*)&seqScript->pc[tempS]); AudioSeq_SequenceChannelEnable(seqPlayer, commandLow, (void*)&seqScript->pc[tempS]);
break; break;
case 0xB0: case 0xB0:
command = AudioSeq_ScriptReadU8(seqScript); command = AudioSeq_ScriptReadU8(seqScript);
temp = AudioSeq_ScriptReadS16(seqScript); temp = AudioSeq_ScriptReadS16(seqScript);
data2 = &seqPlayer->seqData[temp]; data2 = &seqPlayer->seqData[temp];
AudioLoad_SlowLoadSeq(command, data2, &seqPlayer->soundScriptIO[commandLow]); AudioLoad_SlowLoadSeq(command, data2, &seqPlayer->soundScriptIO[commandLow]);
break; break;
case 0x60: { case 0x60: {
command = AudioSeq_ScriptReadU8(seqScript); command = AudioSeq_ScriptReadU8(seqScript);
value = command; value = command;
@ -1976,7 +2013,7 @@ void AudioSeq_InitSequencePlayerChannels(s32 playerIdx) {
s32 i, j; s32 i, j;
for (i = 0; i < 0x10; i++) { 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) { if (seqPlayer->channels[i] == NULL) {
seqPlayer->channels[i] = &gAudioContext.sequenceChannelNone; seqPlayer->channels[i] = &gAudioContext.sequenceChannelNone;
} else { } else {
@ -2002,14 +2039,14 @@ void AudioSeq_InitSequencePlayer(SequencePlayer* seqPlayer) {
seqPlayer->muted = false; seqPlayer->muted = false;
seqPlayer->fontDmaInProgress = false; seqPlayer->fontDmaInProgress = false;
seqPlayer->seqDmaInProgress = false; seqPlayer->seqDmaInProgress = false;
seqPlayer->unk_0b1 = false; seqPlayer->applyBend = false;
for (j = 0; j < 8; j++) { for (j = 0; j < 8; j++) {
seqPlayer->soundScriptIO[j] = -1; seqPlayer->soundScriptIO[j] = -1;
} }
seqPlayer->muteBehavior = 0x40 | 0x20; seqPlayer->muteBehavior = 0x40 | 0x20;
seqPlayer->fadeVolumeScale = 1.0f; seqPlayer->fadeVolumeScale = 1.0f;
seqPlayer->unk_34 = 1.0f; seqPlayer->bend = 1.0f;
Audio_InitNoteLists(&seqPlayer->notePool); Audio_InitNoteLists(&seqPlayer->notePool);
AudioSeq_ResetSequencePlayer(seqPlayer); AudioSeq_ResetSequencePlayer(seqPlayer);
} }

View file

@ -4,6 +4,7 @@
#define DEFAULT_LEN_1CH 0x1A0 #define DEFAULT_LEN_1CH 0x1A0
#define DEFAULT_LEN_2CH 0x340 #define DEFAULT_LEN_2CH 0x340
// DMEM Addresses for the RSP
#define DMEM_TEMP 0x3C0 #define DMEM_TEMP 0x3C0
#define DMEM_UNCOMPRESSED_NOTE 0x580 #define DMEM_UNCOMPRESSED_NOTE 0x580
#define DMEM_NOTE_PAN_TEMP 0x5C0 #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, Acmd* AudioSynth_FinalResample(Acmd* cmd, NoteSynthesisState* synthState, s32 count, u16 pitch, u16 inpDmem,
s32 resampleFlags); s32 resampleFlags);
u32 D_801304A0 = 0x13000000; u32 D_801304A0 = _SHIFTL(A_ENVMIXER, 24, 8);
u32 D_801304A4 = 0x5CAEC8E2; 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 = 0x945CC8E2; 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 = 0x94AEC8E2; 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[] = { u16 D_801304B0[] = {
0x7FFF, 0xD001, 0x3FFF, 0xF001, 0x5FFF, 0x9001, 0x7FFF, 0x8001, 0x7FFF, 0xD001, 0x3FFF, 0xF001, 0x5FFF, 0x9001, 0x7FFF, 0x8001,
@ -41,20 +42,20 @@ u16 D_801304B0[] = {
u8 D_801304C0[] = { 0x40, 0x20, 0x10, 0x8 }; 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; ReverbRingBufferItem* bufItem;
s32 pad[3]; s32 pad[3];
SynthesisReverb* reverb = &gAudioContext.synthesisReverbs[reverbIndex]; SynthesisReverb* reverb = &gAudioContext.synthesisReverbs[reverbIndex];
s32 temp_a0_2; s32 temp_a0_2;
s32 temp_a0_4; s32 temp_a0_4;
s32 sampleCnt; s32 numSamples;
s32 extraSamples; s32 extraSamples;
s32 i; s32 i;
s32 j; s32 j;
if (reverb->downsampleRate >= 2) { if (reverb->downsampleRate >= 2) {
if (reverb->framesToIgnore == 0) { if (reverb->framesToIgnore == 0) {
bufItem = &reverb->items[reverb->curFrame][bufIndex]; bufItem = &reverb->items[reverb->curFrame][updateIndex];
Audio_InvalDCache(bufItem->toDownsampleLeft, DEFAULT_LEN_2CH); Audio_InvalDCache(bufItem->toDownsampleLeft, DEFAULT_LEN_2CH);
for (j = 0, i = 0; i < bufItem->lengthA / 2; j += reverb->downsampleRate, i++) { 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]; bufItem = &reverb->items[reverb->curFrame][updateIndex];
sampleCnt = chunkLen / reverb->downsampleRate; numSamples = chunkLen / reverb->downsampleRate;
extraSamples = (sampleCnt + reverb->nextRingBufPos) - reverb->bufSizePerChan; extraSamples = (numSamples + reverb->nextRingBufPos) - reverb->bufSizePerChan;
temp_a0_2 = reverb->nextRingBufPos; temp_a0_2 = reverb->nextRingBufPos;
if (extraSamples < 0) { if (extraSamples < 0) {
bufItem->lengthA = sampleCnt * 2; bufItem->lengthA = numSamples * 2;
bufItem->lengthB = 0; bufItem->lengthB = 0;
bufItem->startPos = reverb->nextRingBufPos; bufItem->startPos = reverb->nextRingBufPos;
reverb->nextRingBufPos += sampleCnt; reverb->nextRingBufPos += numSamples;
} else { } 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->lengthB = extraSamples * 2;
bufItem->startPos = reverb->nextRingBufPos; bufItem->startPos = reverb->nextRingBufPos;
reverb->nextRingBufPos = extraSamples; reverb->nextRingBufPos = extraSamples;
} }
bufItem->numSamplesAfterDownsampling = sampleCnt; bufItem->numSamplesAfterDownsampling = numSamples;
bufItem->chunkLen = chunkLen; bufItem->chunkLen = chunkLen;
if (reverb->unk_14 != 0) { if (reverb->unk_14 != 0) {
@ -93,30 +95,31 @@ void AudioSynth_InitNextRingBuf(s32 chunkLen, s32 bufIndex, s32 reverbIndex) {
if (temp_a0_4 >= reverb->bufSizePerChan) { if (temp_a0_4 >= reverb->bufSizePerChan) {
temp_a0_4 -= reverb->bufSizePerChan; temp_a0_4 -= reverb->bufSizePerChan;
} }
bufItem = &reverb->items2[reverb->curFrame][bufIndex]; bufItem = &reverb->items2[reverb->curFrame][updateIndex];
sampleCnt = chunkLen / reverb->downsampleRate; numSamples = chunkLen / reverb->downsampleRate;
extraSamples = (temp_a0_4 + sampleCnt) - reverb->bufSizePerChan; extraSamples = (temp_a0_4 + numSamples) - reverb->bufSizePerChan;
if (extraSamples < 0) { if (extraSamples < 0) {
bufItem->lengthA = sampleCnt * 2; bufItem->lengthA = numSamples * 2;
bufItem->lengthB = 0; bufItem->lengthB = 0;
bufItem->startPos = temp_a0_4; bufItem->startPos = temp_a0_4;
} else { } 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->lengthB = extraSamples * 2;
bufItem->startPos = temp_a0_4; bufItem->startPos = temp_a0_4;
} }
bufItem->numSamplesAfterDownsampling = sampleCnt; bufItem->numSamplesAfterDownsampling = numSamples;
bufItem->chunkLen = chunkLen; bufItem->chunkLen = chunkLen;
} }
} }
void func_800DB03C(s32 arg0) { void func_800DB03C(s32 updateIndex) {
NoteSubEu* subEu; NoteSubEu* subEu;
NoteSubEu* subEu2; NoteSubEu* subEu2;
s32 baseIndex; s32 baseIndex;
s32 i; s32 i;
baseIndex = gAudioContext.numNotes * arg0; baseIndex = gAudioContext.numNotes * updateIndex;
for (i = 0; i < gAudioContext.numNotes; i++) { for (i = 0; i < gAudioContext.numNotes; i++) {
subEu = &gAudioContext.notes[i].noteSubEu; subEu = &gAudioContext.notes[i].noteSubEu;
subEu2 = &gAudioContext.noteSubsEu[baseIndex + i]; subEu2 = &gAudioContext.noteSubsEu[baseIndex + i];
@ -146,6 +149,7 @@ Acmd* AudioSynth_Update(Acmd* cmdStart, s32* cmdCnt, s16* aiStart, s32 aiBufLen)
aiBufP = aiStart; aiBufP = aiStart;
gAudioContext.curLoadedBook = NULL; gAudioContext.curLoadedBook = NULL;
for (i = gAudioContext.audioBufferParameters.updatesPerFrame; i > 0; i--) { for (i = gAudioContext.audioBufferParameters.updatesPerFrame; i > 0; i--) {
if (i == 1) { if (i == 1) {
chunkLen = aiBufLen; chunkLen = aiBufLen;
@ -180,22 +184,22 @@ Acmd* AudioSynth_Update(Acmd* cmdStart, s32* cmdCnt, s16* aiStart, s32 aiBufLen)
return cmdP; return cmdP;
} }
void func_800DB2C0(s32 updateIndexStart, s32 noteIndex) { void func_800DB2C0(s32 updateIndex, s32 noteIndex) {
NoteSubEu* temp_v1; NoteSubEu* noteSubEu;
s32 i; s32 i;
for (i = updateIndexStart + 1; i < gAudioContext.audioBufferParameters.updatesPerFrame; i++) { for (i = updateIndex + 1; i < gAudioContext.audioBufferParameters.updatesPerFrame; i++) {
temp_v1 = &gAudioContext.noteSubsEu[(gAudioContext.numNotes * i) + noteIndex]; noteSubEu = &gAudioContext.noteSubsEu[(gAudioContext.numNotes * i) + noteIndex];
if (!temp_v1->bitField0.needsInit) { if (!noteSubEu->bitField0.needsInit) {
temp_v1->bitField0.enabled = 0; noteSubEu->bitField0.enabled = false;
} else { } else {
break; break;
} }
} }
} }
Acmd* AudioSynth_LoadRingBuffer1AtTemp(Acmd* cmd, SynthesisReverb* reverb, s16 bufIndex) { Acmd* AudioSynth_LoadRingBuffer1AtTemp(Acmd* cmd, SynthesisReverb* reverb, s16 updateIndex) {
ReverbRingBufferItem* bufItem = &reverb->items[reverb->curFrame][bufIndex]; ReverbRingBufferItem* bufItem = &reverb->items[reverb->curFrame][updateIndex];
cmd = AudioSynth_LoadRingBufferPart(cmd, DMEM_WET_TEMP, bufItem->startPos, bufItem->lengthA, reverb); cmd = AudioSynth_LoadRingBufferPart(cmd, DMEM_WET_TEMP, bufItem->startPos, bufItem->lengthA, reverb);
if (bufItem->lengthB != 0) { if (bufItem->lengthB != 0) {
@ -205,8 +209,8 @@ Acmd* AudioSynth_LoadRingBuffer1AtTemp(Acmd* cmd, SynthesisReverb* reverb, s16 b
return cmd; return cmd;
} }
Acmd* AudioSynth_SaveRingBuffer1AtTemp(Acmd* cmd, SynthesisReverb* reverb, s16 bufIndex) { Acmd* AudioSynth_SaveRingBuffer1AtTemp(Acmd* cmd, SynthesisReverb* reverb, s16 updateIndex) {
ReverbRingBufferItem* bufItem = &reverb->items[reverb->curFrame][bufIndex]; ReverbRingBufferItem* bufItem = &reverb->items[reverb->curFrame][updateIndex];
cmd = AudioSynth_SaveRingBufferPart(cmd, DMEM_WET_TEMP, bufItem->startPos, bufItem->lengthA, reverb); cmd = AudioSynth_SaveRingBufferPart(cmd, DMEM_WET_TEMP, bufItem->startPos, bufItem->lengthA, reverb);
if (bufItem->lengthB != 0) { if (bufItem->lengthB != 0) {
@ -216,16 +220,18 @@ Acmd* AudioSynth_SaveRingBuffer1AtTemp(Acmd* cmd, SynthesisReverb* reverb, s16 b
return cmd; 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) { 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); 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->leakRtl, DMEM_WET_RIGHT_CH, DMEM_WET_LEFT_CH);
aMix(cmd++, 0x1A, reverb->leakLtr, DMEM_WET_SCRATCH, DMEM_WET_RIGHT_CH); aMix(cmd++, 0x1A, reverb->leakLtr, DMEM_WET_SCRATCH, DMEM_WET_RIGHT_CH);
return cmd; return cmd;
} }
Acmd* func_800DB4E4(Acmd* cmd, s32 arg1, SynthesisReverb* reverb, s16 arg3) { Acmd* func_800DB4E4(Acmd* cmd, s32 aiBufLen, SynthesisReverb* reverb, s16 updateIndex) {
ReverbRingBufferItem* item = &reverb->items[reverb->curFrame][arg3]; ReverbRingBufferItem* item = &reverb->items[reverb->curFrame][updateIndex];
s16 offsetA; s16 offsetA;
s16 offsetB; s16 offsetB;
@ -236,15 +242,15 @@ Acmd* func_800DB4E4(Acmd* cmd, s32 arg1, SynthesisReverb* reverb, s16 arg3) {
// Ring buffer wrapped // Ring buffer wrapped
cmd = AudioSynth_LoadRingBufferPart(cmd, DMEM_WET_TEMP + offsetB, 0, DEFAULT_LEN_1CH - offsetB, reverb); 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); 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); aResample(cmd++, reverb->resampleFlags, reverb->unk_0E, reverb->unk_34);
return cmd; return cmd;
} }
Acmd* func_800DB680(Acmd* cmd, SynthesisReverb* reverb, s16 bufIndex) { Acmd* func_800DB680(Acmd* cmd, SynthesisReverb* reverb, s16 updateIndex) {
ReverbRingBufferItem* bufItem = &reverb->items[reverb->curFrame][bufIndex]; ReverbRingBufferItem* bufItem = &reverb->items[reverb->curFrame][updateIndex];
aSetBuffer(cmd++, 0, DMEM_WET_LEFT_CH, DMEM_WET_SCRATCH, bufItem->unk_18 * 2); aSetBuffer(cmd++, 0, DMEM_WET_LEFT_CH, DMEM_WET_SCRATCH, bufItem->unk_18 * 2);
aResample(cmd++, reverb->resampleFlags, bufItem->unk_16, reverb->unk_38); 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; return cmd;
} }
Acmd* func_800DB828(Acmd* cmd, s32 arg1, SynthesisReverb* reverb, s16 arg3) { Acmd* func_800DB828(Acmd* cmd, s32 aiBufLen, SynthesisReverb* reverb, s16 updateIndex) {
ReverbRingBufferItem* item = &reverb->items[reverb->curFrame][arg3]; ReverbRingBufferItem* item = &reverb->items[reverb->curFrame][updateIndex];
s16 offsetA; s16 offsetA;
s16 offsetB; s16 offsetB;
item->unk_14 = (item->unk_18 << 0xF) / arg1; item->unk_14 = (item->unk_18 << 0xF) / aiBufLen;
offsetA = (item->startPos & 7) * 2; 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); offsetB = ALIGN16(offsetA + item->lengthA);
cmd = AudioSynth_LoadRingBufferPart(cmd, DMEM_WET_TEMP, item->startPos - (offsetA / 2), DEFAULT_LEN_1CH, reverb); cmd = AudioSynth_LoadRingBufferPart(cmd, DMEM_WET_TEMP, item->startPos - (offsetA / 2), DEFAULT_LEN_1CH, reverb);
if (item->lengthB != 0) { if (item->lengthB != 0) {
// Ring buffer wrapped // Ring buffer wrapped
cmd = AudioSynth_LoadRingBufferPart(cmd, DMEM_WET_TEMP + offsetB, 0, DEFAULT_LEN_1CH - offsetB, reverb); 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); 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); aResample(cmd++, reverb->resampleFlags, item->unk_14, reverb->unk_34);
return cmd; return cmd;
} }
/**
* Apply a filter (convolution) to each reverb channel.
*/
Acmd* AudioSynth_FilterReverb(Acmd* cmd, s32 count, SynthesisReverb* reverb) { Acmd* AudioSynth_FilterReverb(Acmd* cmd, s32 count, SynthesisReverb* reverb) {
// Apply a filter (convolution) to each reverb channel.
if (reverb->filterLeft != NULL) { if (reverb->filterLeft != NULL) {
aFilter(cmd++, 2, count, reverb->filterLeft); aFilter(cmd++, 2, count, reverb->filterLeft);
aFilter(cmd++, reverb->resampleFlags, DMEM_WET_LEFT_CH, reverb->filterLeftState); 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; return cmd;
} }
Acmd* AudioSynth_MaybeMixRingBuffer1(Acmd* cmd, SynthesisReverb* reverb, s32 arg2) { Acmd* AudioSynth_MaybeMixRingBuffer1(Acmd* cmd, SynthesisReverb* reverb, s32 updateIndex) {
SynthesisReverb* temp_a3; SynthesisReverb* temp_a3;
temp_a3 = &gAudioContext.synthesisReverbs[reverb->unk_05]; temp_a3 = &gAudioContext.synthesisReverbs[reverb->unk_05];
if (temp_a3->downsampleRate == 1) { 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); 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; return cmd;
} }
@ -454,8 +462,8 @@ void AudioSynth_LoadFilterCount(Acmd* cmd, s32 count, s32 addr) {
aFilter(cmd, 2, count, addr); aFilter(cmd, 2, count, addr);
} }
Acmd* AudioSynth_LoadRingBuffer1(Acmd* cmd, s32 arg1, SynthesisReverb* reverb, s16 bufIndex) { Acmd* AudioSynth_LoadRingBuffer1(Acmd* cmd, s32 aiBufLen, SynthesisReverb* reverb, s16 updateIndex) {
ReverbRingBufferItem* ringBufferItem = &reverb->items[reverb->curFrame][bufIndex]; ReverbRingBufferItem* ringBufferItem = &reverb->items[reverb->curFrame][updateIndex];
cmd = cmd =
AudioSynth_LoadRingBufferPart(cmd, DMEM_WET_LEFT_CH, ringBufferItem->startPos, ringBufferItem->lengthA, reverb); 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; return cmd;
} }
Acmd* AudioSynth_LoadRingBuffer2(Acmd* cmd, s32 arg1, SynthesisReverb* reverb, s16 bufIndex) { Acmd* AudioSynth_LoadRingBuffer2(Acmd* cmd, s32 aiBufLen, SynthesisReverb* reverb, s16 updateIndex) {
ReverbRingBufferItem* bufItem = &reverb->items2[reverb->curFrame][bufIndex]; ReverbRingBufferItem* bufItem = &reverb->items2[reverb->curFrame][updateIndex];
cmd = AudioSynth_LoadRingBufferPart(cmd, DMEM_WET_LEFT_CH, bufItem->startPos, bufItem->lengthA, reverb); cmd = AudioSynth_LoadRingBufferPart(cmd, DMEM_WET_LEFT_CH, bufItem->startPos, bufItem->lengthA, reverb);
if (bufItem->lengthB != 0) { if (bufItem->lengthB != 0) {
@ -496,34 +504,34 @@ Acmd* AudioSynth_SaveBufferOffset(Acmd* cmd, u16 dmem, u16 offset, s32 length, s
return cmd; 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) { if (reverb->downsampleRate == 1) {
cmd = AudioSynth_LoadRingBuffer2(cmd, arg1, reverb, bufIndex); cmd = AudioSynth_LoadRingBuffer2(cmd, aiBufLen, reverb, updateIndex);
} }
return cmd; 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 // Sets DMEM_WET_{LEFT,RIGHT}_CH, clobbers DMEM_TEMP
if (reverb->downsampleRate == 1) { if (reverb->downsampleRate == 1) {
if (reverb->unk_18 != 0) { if (reverb->unk_18 != 0) {
cmd = func_800DB828(cmd, arg1, reverb, arg3); cmd = func_800DB828(cmd, aiBufLen, reverb, updateIndex);
} else { } else {
cmd = AudioSynth_LoadRingBuffer1(cmd, arg1, reverb, arg3); cmd = AudioSynth_LoadRingBuffer1(cmd, aiBufLen, reverb, updateIndex);
} }
} else { } else {
cmd = func_800DB4E4(cmd, arg1, reverb, arg3); cmd = func_800DB4E4(cmd, aiBufLen, reverb, updateIndex);
} }
return cmd; return cmd;
} }
Acmd* AudioSynth_SaveReverbSamples(Acmd* cmd, SynthesisReverb* reverb, s16 bufIndex) { Acmd* AudioSynth_SaveReverbSamples(Acmd* cmd, SynthesisReverb* reverb, s16 updateIndex) {
ReverbRingBufferItem* bufItem = &reverb->items[reverb->curFrame][bufIndex]; ReverbRingBufferItem* bufItem = &reverb->items[reverb->curFrame][updateIndex];
if (reverb->downsampleRate == 1) { if (reverb->downsampleRate == 1) {
if (reverb->unk_18 != 0) { if (reverb->unk_18 != 0) {
cmd = func_800DB680(cmd, reverb, bufIndex); cmd = func_800DB680(cmd, reverb, updateIndex);
} else { } else {
// Put the oldest samples in the ring buffer into the wet channels // 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); 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 // 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. // double buffering. Left and right buffers are adjacent in memory.
AudioSynth_SaveBuffer(cmd++, DMEM_WET_LEFT_CH, DEFAULT_LEN_2CH, 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; reverb->resampleFlags = 0;
return cmd; return cmd;
} }
Acmd* AudioSynth_SaveRingBuffer2(Acmd* cmd, SynthesisReverb* reverb, s16 bufIndex) { Acmd* AudioSynth_SaveRingBuffer2(Acmd* cmd, SynthesisReverb* reverb, s16 updateIndex) {
ReverbRingBufferItem* bufItem = &reverb->items2[reverb->curFrame][bufIndex]; ReverbRingBufferItem* bufItem = &reverb->items2[reverb->curFrame][updateIndex];
cmd = AudioSynth_SaveRingBufferPart(cmd, DMEM_WET_LEFT_CH, bufItem->startPos, bufItem->lengthA, reverb); cmd = AudioSynth_SaveRingBufferPart(cmd, DMEM_WET_LEFT_CH, bufItem->startPos, bufItem->lengthA, reverb);
if (bufItem->lengthB != 0) { 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); aClearBuffer(cmd++, DMEM_LEFT_CH, DEFAULT_LEN_2CH);
i = 0; i = 0;
for (reverbIndex = 0; reverbIndex < gAudioContext.numSynthesisReverbs; reverbIndex++) { for (reverbIndex = 0; reverbIndex < gAudioContext.numSynthesisReverbs; reverbIndex++) {
reverb = &gAudioContext.synthesisReverbs[reverbIndex]; reverb = &gAudioContext.synthesisReverbs[reverbIndex];
useReverb = reverb->useReverb; useReverb = reverb->useReverb;
if (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; unk14 = reverb->unk_14;
if (unk14) { if (unk14) {
aDMEMMove(cmd++, DMEM_WET_LEFT_CH, DMEM_WET_TEMP, DEFAULT_LEN_2CH); 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) { if (reverb->leakRtl != 0 || reverb->leakLtr != 0) {
cmd = AudioSynth_LeakReverb(cmd, reverb); cmd = AudioSynth_LeakReverb(cmd, reverb);
} }
if (unk14) { 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); cmd = AudioSynth_SaveReverbSamples(cmd, reverb, updateIndex);
if (reverb->unk_05 != -1) { if (reverb->unk_05 != -1) {
cmd = AudioSynth_MaybeMixRingBuffer1(cmd, reverb, updateIndex); 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) { if (reverb->filterLeft != NULL || reverb->filterRight != NULL) {
cmd = AudioSynth_FilterReverb(cmd, aiBufLen * 2, reverb); 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) { if (unk14) {
cmd = AudioSynth_SaveRingBuffer2(cmd, reverb, updateIndex); cmd = AudioSynth_SaveRingBuffer2(cmd, reverb, updateIndex);
} else { } else {
@ -675,7 +697,7 @@ Acmd* AudioSynth_ProcessNote(s32 noteIndex, NoteSubEu* noteSubEu, NoteSynthesisS
u16 resamplingRateFixedPoint; u16 resamplingRateFixedPoint;
s32 nSamplesInFirstFrame; s32 nSamplesInFirstFrame;
s32 nTrailingSamplesToIgnore; s32 nTrailingSamplesToIgnore;
s32 phi_a1_2; s32 gain;
s32 frameIndex; s32 frameIndex;
s32 skipBytes; s32 skipBytes;
s32 temp_v1_6; s32 temp_v1_6;
@ -835,16 +857,19 @@ Acmd* AudioSynth_ProcessNote(s32 noteIndex, NoteSubEu* noteSubEu, NoteSynthesisS
skipInitialSamples = 16; skipInitialSamples = 16;
sampleDataStart = 0; sampleDataStart = 0;
break; break;
case CODEC_SMALL_ADPCM: case CODEC_SMALL_ADPCM:
frameSize = 5; frameSize = 5;
skipInitialSamples = 16; skipInitialSamples = 16;
sampleDataStart = 0; sampleDataStart = 0;
break; break;
case CODEC_S8: case CODEC_S8:
frameSize = 16; frameSize = 16;
skipInitialSamples = 16; skipInitialSamples = 16;
sampleDataStart = 0; sampleDataStart = 0;
break; break;
case CODEC_S16_INMEMORY: case CODEC_S16_INMEMORY:
AudioSynth_ClearBuffer(cmd++, DMEM_UNCOMPRESSED_NOTE, (samplesLenAdjusted * 2) + 0x20); AudioSynth_ClearBuffer(cmd++, DMEM_UNCOMPRESSED_NOTE, (samplesLenAdjusted * 2) + 0x20);
flags = A_CONTINUE; flags = A_CONTINUE;
@ -852,6 +877,7 @@ Acmd* AudioSynth_ProcessNote(s32 noteIndex, NoteSubEu* noteSubEu, NoteSynthesisS
nSamplesProcessed = samplesLenAdjusted; nSamplesProcessed = samplesLenAdjusted;
s5 = samplesLenAdjusted; s5 = samplesLenAdjusted;
goto skip; goto skip;
case CODEC_S16: case CODEC_S16:
AudioSynth_ClearBuffer(cmd++, DMEM_UNCOMPRESSED_NOTE, (samplesLenAdjusted * 2) + 0x20); AudioSynth_ClearBuffer(cmd++, DMEM_UNCOMPRESSED_NOTE, (samplesLenAdjusted * 2) + 0x20);
flags = A_CONTINUE; flags = A_CONTINUE;
@ -859,6 +885,7 @@ Acmd* AudioSynth_ProcessNote(s32 noteIndex, NoteSubEu* noteSubEu, NoteSynthesisS
nSamplesProcessed = samplesLenAdjusted; nSamplesProcessed = samplesLenAdjusted;
s5 = samplesLenAdjusted; s5 = samplesLenAdjusted;
goto skip; goto skip;
case CODEC_REVERB: case CODEC_REVERB:
break; break;
} }
@ -902,6 +929,7 @@ Acmd* AudioSynth_ProcessNote(s32 noteIndex, NoteSubEu* noteSubEu, NoteSynthesisS
} else { } else {
phi_s4 = ALIGN16(s5 + 16); phi_s4 = ALIGN16(s5 + 16);
} }
switch (audioFontSample->codec) { switch (audioFontSample->codec) {
case CODEC_ADPCM: case CODEC_ADPCM:
aligned = ALIGN16((nFramesToDecode * frameSize) + 0x10); aligned = ALIGN16((nFramesToDecode * frameSize) + 0x10);
@ -910,6 +938,7 @@ Acmd* AudioSynth_ProcessNote(s32 noteIndex, NoteSubEu* noteSubEu, NoteSynthesisS
nSamplesToDecode * 2); nSamplesToDecode * 2);
aADPCMdec(cmd++, flags, synthState->synthesisBuffers->adpcmdecState); aADPCMdec(cmd++, flags, synthState->synthesisBuffers->adpcmdecState);
break; break;
case CODEC_SMALL_ADPCM: case CODEC_SMALL_ADPCM:
aligned = ALIGN16((nFramesToDecode * frameSize) + 0x10); aligned = ALIGN16((nFramesToDecode * frameSize) + 0x10);
addr = DMEM_COMPRESSED_ADPCM_DATA - aligned; addr = DMEM_COMPRESSED_ADPCM_DATA - aligned;
@ -917,6 +946,7 @@ Acmd* AudioSynth_ProcessNote(s32 noteIndex, NoteSubEu* noteSubEu, NoteSynthesisS
nSamplesToDecode * 2); nSamplesToDecode * 2);
aADPCMdec(cmd++, flags | 4, synthState->synthesisBuffers->adpcmdecState); aADPCMdec(cmd++, flags | 4, synthState->synthesisBuffers->adpcmdecState);
break; break;
case CODEC_S8: case CODEC_S8:
aligned = ALIGN16((nFramesToDecode * frameSize) + 0x10); aligned = ALIGN16((nFramesToDecode * frameSize) + 0x10);
addr = DMEM_COMPRESSED_ADPCM_DATA - aligned; addr = DMEM_COMPRESSED_ADPCM_DATA - aligned;
@ -938,9 +968,11 @@ Acmd* AudioSynth_ProcessNote(s32 noteIndex, NoteSubEu* noteSubEu, NoteSynthesisS
skipBytes = 0x20; skipBytes = 0x20;
s5 = (nSamplesToDecode + 0x10) * 2; s5 = (nSamplesToDecode + 0x10) * 2;
break; break;
case A_LOOP: case A_LOOP:
s5 = nSamplesInThisIteration * 2 + s5; s5 = nSamplesInThisIteration * 2 + s5;
break; break;
default: default:
if (s5 != 0) { if (s5 != 0) {
s5 = nSamplesInThisIteration * 2 + s5; s5 = nSamplesInThisIteration * 2 + s5;
@ -974,6 +1006,7 @@ Acmd* AudioSynth_ProcessNote(s32 noteIndex, NoteSubEu* noteSubEu, NoteSynthesisS
case 1: case 1:
noteSamplesDmemAddrBeforeResampling = DMEM_UNCOMPRESSED_NOTE + skipBytes; noteSamplesDmemAddrBeforeResampling = DMEM_UNCOMPRESSED_NOTE + skipBytes;
break; break;
case 2: case 2:
switch (curPart) { switch (curPart) {
case 0: case 0:
@ -986,6 +1019,7 @@ Acmd* AudioSynth_ProcessNote(s32 noteIndex, NoteSubEu* noteSubEu, NoteSynthesisS
samplesLenAdjusted + 0x10); samplesLenAdjusted + 0x10);
} }
break; break;
case 1: case 1:
AudioSynth_InterL(cmd++, DMEM_UNCOMPRESSED_NOTE + skipBytes, AudioSynth_InterL(cmd++, DMEM_UNCOMPRESSED_NOTE + skipBytes,
DMEM_TEMP + 0x20 + resampledTempLen, ALIGN8(samplesLenAdjusted / 2)); 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); AudioSynth_UnkCmd3(cmd++, DMEM_TEMP, DMEM_TEMP, aiBufLen * 2);
} }
phi_a1_2 = noteSubEu->unk_2; gain = noteSubEu->gain;
if (phi_a1_2 != 0) { if (gain != 0) {
if (phi_a1_2 < 0x10) { // A gain of 0x10 (a UQ4.4 number) is equivalent to 1.0 and represents no volume change
phi_a1_2 = 0x10; 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; filter = noteSubEu->filter;

View file

@ -68,10 +68,10 @@ AudioTask* func_800E5000(void) {
} }
osSendMesg(gAudioContext.taskStartQueueP, (OSMesg)gAudioContext.totalTaskCount, OS_MESG_NOBLOCK); osSendMesg(gAudioContext.taskStartQueueP, (OSMesg)gAudioContext.totalTaskCount, OS_MESG_NOBLOCK);
gAudioContext.rspTaskIdx ^= 1; gAudioContext.rspTaskIndex ^= 1;
gAudioContext.curAIBufIdx++; gAudioContext.curAiBufIndex++;
gAudioContext.curAIBufIdx %= 3; gAudioContext.curAiBufIndex %= 3;
index = (gAudioContext.curAIBufIdx - 2 + 3) % 3; index = (gAudioContext.curAiBufIndex - 2 + 3) % 3;
samplesRemainingInAi = osAiGetLength() / 4; samplesRemainingInAi = osAiGetLength() / 4;
if (gAudioContext.resetTimer < 16) { if (gAudioContext.resetTimer < 16) {
@ -130,10 +130,10 @@ AudioTask* func_800E5000(void) {
gAudioContext.resetTimer++; gAudioContext.resetTimer++;
} }
gAudioContext.currTask = &gAudioContext.rspTask[gAudioContext.rspTaskIdx]; gAudioContext.curTask = &gAudioContext.rspTask[gAudioContext.rspTaskIndex];
gAudioContext.curAbiCmdBuf = gAudioContext.abiCmdBufs[gAudioContext.rspTaskIdx]; gAudioContext.curAbiCmdBuf = gAudioContext.abiCmdBufs[gAudioContext.rspTaskIndex];
index = gAudioContext.curAIBufIdx; index = gAudioContext.curAiBufIndex;
currAiBuffer = gAudioContext.aiBuffers[index]; currAiBuffer = gAudioContext.aiBuffers[index];
gAudioContext.aiBufLengths[index] = gAudioContext.aiBufLengths[index] =
@ -171,11 +171,11 @@ AudioTask* func_800E5000(void) {
gAudioContext.aiBuffers[index][gAudioContext.totalTaskCount & 0xFF] + gAudioContext.audioRandom; gAudioContext.aiBuffers[index][gAudioContext.totalTaskCount & 0xFF] + gAudioContext.audioRandom;
gWaveSamples[8] = (s16*)(((u8*)func_800E4FE0) + (gAudioContext.audioRandom & 0xFFF0)); gWaveSamples[8] = (s16*)(((u8*)func_800E4FE0) + (gAudioContext.audioRandom & 0xFFF0));
index = gAudioContext.rspTaskIdx; index = gAudioContext.rspTaskIndex;
gAudioContext.currTask->msgQueue = NULL; gAudioContext.curTask->msgQueue = NULL;
gAudioContext.currTask->unk_44 = NULL; gAudioContext.curTask->unk_44 = NULL;
task = &gAudioContext.currTask->task.t; task = &gAudioContext.curTask->task.t;
task->type = M_AUDTASK; task->type = M_AUDTASK;
task->flags = 0; task->flags = 0;
task->ucode_boot = aspMainTextStart; task->ucode_boot = aspMainTextStart;
@ -199,9 +199,9 @@ AudioTask* func_800E5000(void) {
} }
if (gAudioContext.audioBufferParameters.specUnk4 == 1) { if (gAudioContext.audioBufferParameters.specUnk4 == 1) {
return gAudioContext.currTask; return gAudioContext.curTask;
} else { } else {
sWaitingAudioTask = gAudioContext.currTask; sWaitingAudioTask = gAudioContext.curTask;
return NULL; return NULL;
} }
} }
@ -219,14 +219,17 @@ void func_800E5584(AudioCmd* cmd) {
switch (cmd->op) { switch (cmd->op) {
case 0x81: case 0x81:
AudioLoad_SyncLoadSeqParts(cmd->arg1, cmd->arg2); AudioLoad_SyncLoadSeqParts(cmd->arg1, cmd->arg2);
return; break;
case 0x82: case 0x82:
AudioLoad_SyncInitSeqPlayer(cmd->arg0, cmd->arg1, cmd->arg2); AudioLoad_SyncInitSeqPlayer(cmd->arg0, cmd->arg1, cmd->arg2);
func_800E59AC(cmd->arg0, cmd->data); func_800E59AC(cmd->arg0, cmd->data);
return; break;
case 0x85: case 0x85:
AudioLoad_SyncInitSeqPlayerSkipTicks(cmd->arg0, cmd->arg1, cmd->data); AudioLoad_SyncInitSeqPlayerSkipTicks(cmd->arg0, cmd->arg1, cmd->data);
return; break;
case 0x83: case 0x83:
if (gAudioContext.seqPlayers[cmd->arg0].enabled) { if (gAudioContext.seqPlayers[cmd->arg0].enabled) {
if (cmd->asInt == 0) { if (cmd->asInt == 0) {
@ -235,22 +238,27 @@ void func_800E5584(AudioCmd* cmd) {
func_800E5958(cmd->arg0, cmd->asInt); func_800E5958(cmd->arg0, cmd->asInt);
} }
} }
return; break;
case 0xF0: case 0xF0:
gAudioContext.soundMode = cmd->asUInt; gAudioContext.soundMode = cmd->asUInt;
return; break;
case 0xF1: case 0xF1:
for (i = 0; i < gAudioContext.audioBufferParameters.numSequencePlayers; i++) { for (i = 0; i < gAudioContext.audioBufferParameters.numSequencePlayers; i++) {
SequencePlayer* seqPlayer = &gAudioContext.seqPlayers[i]; SequencePlayer* seqPlayer = &gAudioContext.seqPlayers[i];
seqPlayer->muted = 1; seqPlayer->muted = 1;
seqPlayer->recalculateVolume = 1; seqPlayer->recalculateVolume = 1;
} }
return; break;
case 0xF2: case 0xF2:
if (cmd->asUInt == 1) { if (cmd->asUInt == 1) {
for (i = 0; i < gAudioContext.numNotes; i++) { for (i = 0; i < gAudioContext.numNotes; i++) {
Note* note = &gAudioContext.notes[i]; Note* note = &gAudioContext.notes[i];
NoteSubEu* subEu = &note->noteSubEu; NoteSubEu* subEu = &note->noteSubEu;
if (subEu->bitField0.enabled && note->playbackState.unk_04 == 0) { if (subEu->bitField0.enabled && note->playbackState.unk_04 == 0) {
if (note->playbackState.parentLayer->channel->muteBehavior & 8) { if (note->playbackState.parentLayer->channel->muteBehavior & 8) {
subEu->bitField0.finished = 1; subEu->bitField0.finished = 1;
@ -261,58 +269,71 @@ void func_800E5584(AudioCmd* cmd) {
for (i = 0; i < gAudioContext.audioBufferParameters.numSequencePlayers; i++) { for (i = 0; i < gAudioContext.audioBufferParameters.numSequencePlayers; i++) {
SequencePlayer* seqPlayer = &gAudioContext.seqPlayers[i]; SequencePlayer* seqPlayer = &gAudioContext.seqPlayers[i];
seqPlayer->muted = 0; seqPlayer->muted = 0;
seqPlayer->recalculateVolume = 1; seqPlayer->recalculateVolume = 1;
} }
break;
return;
case 0xF3: case 0xF3:
AudioLoad_SyncLoadInstrument(cmd->arg0, cmd->arg1, cmd->arg2); AudioLoad_SyncLoadInstrument(cmd->arg0, cmd->arg1, cmd->arg2);
return; break;
case 0xF4: case 0xF4:
AudioLoad_AsyncLoadSampleBank(cmd->arg0, cmd->arg1, cmd->arg2, &gAudioContext.externalLoadQueue); AudioLoad_AsyncLoadSampleBank(cmd->arg0, cmd->arg1, cmd->arg2, &gAudioContext.externalLoadQueue);
return; break;
case 0xF5: case 0xF5:
AudioLoad_AsyncLoadFont(cmd->arg0, cmd->arg1, cmd->arg2, &gAudioContext.externalLoadQueue); AudioLoad_AsyncLoadFont(cmd->arg0, cmd->arg1, cmd->arg2, &gAudioContext.externalLoadQueue);
return; break;
case 0xFC: case 0xFC:
AudioLoad_AsyncLoadSeq(cmd->arg0, cmd->arg1, cmd->arg2, &gAudioContext.externalLoadQueue); AudioLoad_AsyncLoadSeq(cmd->arg0, cmd->arg1, cmd->arg2, &gAudioContext.externalLoadQueue);
return; break;
case 0xF6: case 0xF6:
AudioLoad_DiscardSeqFonts(cmd->arg1); AudioLoad_DiscardSeqFonts(cmd->arg1);
return; break;
case 0x90: case 0x90:
gAudioContext.unk_5BDC[cmd->arg0] = cmd->asUShort; gAudioContext.unk_5BDC[cmd->arg0] = cmd->asUShort;
return; break;
case 0xF9: case 0xF9:
gAudioContext.resetStatus = 5; gAudioContext.resetStatus = 5;
gAudioContext.audioResetSpecIdToLoad = cmd->asUInt; gAudioContext.audioResetSpecIdToLoad = cmd->asUInt;
return; break;
case 0xFB: case 0xFB:
D_801755D0 = (void (*)(void))cmd->asUInt; D_801755D0 = (void (*)(void))cmd->asUInt;
return; break;
case 0xE0: case 0xE0:
case 0xE1: case 0xE1:
case 0xE2: case 0xE2:
Audio_SetFontInstrument(cmd->op - 0xE0, cmd->arg0, cmd->arg1, cmd->data); Audio_SetFontInstrument(cmd->op - 0xE0, cmd->arg0, cmd->arg1, cmd->data);
return; break;
case 0xFE: case 0xFE:
temp_t7 = cmd->asUInt; temp_t7 = cmd->asUInt;
if (temp_t7 == 1) { if (temp_t7 == 1) {
for (i = 0; i < gAudioContext.audioBufferParameters.numSequencePlayers; i++) { for (i = 0; i < gAudioContext.audioBufferParameters.numSequencePlayers; i++) {
SequencePlayer* seqPlayer = &gAudioContext.seqPlayers[i]; SequencePlayer* seqPlayer = &gAudioContext.seqPlayers[i];
if (seqPlayer->enabled) { if (seqPlayer->enabled) {
AudioSeq_SequencePlayerDisableAsFinished(seqPlayer); AudioSeq_SequencePlayerDisableAsFinished(seqPlayer);
} }
} }
} }
func_800E66C0(temp_t7); func_800E66C0(temp_t7);
return; break;
case 0xE3: case 0xE3:
AudioHeap_PopCache(cmd->asInt); AudioHeap_PopCache(cmd->asInt);
return; break;
default: default:
return; break;
} }
} }
@ -332,6 +353,7 @@ void func_800E5958(s32 playerIdx, s32 fadeTimer) {
// SetFadeInTimer // SetFadeInTimer
void func_800E59AC(s32 playerIdx, s32 fadeTimer) { void func_800E59AC(s32 playerIdx, s32 fadeTimer) {
SequencePlayer* seqPlayer; SequencePlayer* seqPlayer;
if (fadeTimer != 0) { if (fadeTimer != 0) {
seqPlayer = &gAudioContext.seqPlayers[playerIdx]; seqPlayer = &gAudioContext.seqPlayers[playerIdx];
seqPlayer->state = 1; seqPlayer->state = 1;
@ -443,7 +465,7 @@ void Audio_ProcessCmd(AudioCmd* cmd) {
} }
if (cmd->arg1 == 0xFF) { if (cmd->arg1 == 0xFF) {
phi_v0 = gAudioContext.unk_5BDC[cmd->arg0]; phi_v0 = gAudioContext.unk_5BDC[cmd->arg0];
for (i = 0; i < 0x10; i++) { for (i = 0; i < 16; i++) {
if (phi_v0 & 1) { if (phi_v0 & 1) {
func_800E6300(seqPlayer->channels[i], cmd); func_800E6300(seqPlayer->channels[i], cmd);
} }
@ -556,6 +578,7 @@ void Audio_PreNMIInternal(void) {
s8 func_800E6070(s32 playerIdx, s32 channelIdx, s32 scriptIdx) { s8 func_800E6070(s32 playerIdx, s32 channelIdx, s32 scriptIdx) {
SequencePlayer* seqPlayer = &gAudioContext.seqPlayers[playerIdx]; SequencePlayer* seqPlayer = &gAudioContext.seqPlayers[playerIdx];
SequenceChannel* channel; SequenceChannel* channel;
if (seqPlayer->enabled) { if (seqPlayer->enabled) {
channel = seqPlayer->channels[channelIdx]; channel = seqPlayer->channels[channelIdx];
return channel->soundScriptIO[scriptIdx]; return channel->soundScriptIO[scriptIdx];
@ -564,45 +587,53 @@ s8 func_800E6070(s32 playerIdx, s32 channelIdx, s32 scriptIdx) {
} }
} }
s8 func_800E60C4(s32 playerIdx, s32 arg1) { s8 func_800E60C4(s32 playerIdx, s32 port) {
return gAudioContext.seqPlayers[playerIdx].soundScriptIO[arg1]; return gAudioContext.seqPlayers[playerIdx].soundScriptIO[port];
} }
void Audio_InitExternalPool(void* mem, u32 size) { void Audio_InitExternalPool(void* ramAddr, u32 size) {
AudioHeap_AllocPoolInit(&gAudioContext.externalPool, mem, size); AudioHeap_AllocPoolInit(&gAudioContext.externalPool, ramAddr, size);
} }
void Audio_DestroyExternalPool(void) { void Audio_DestroyExternalPool(void) {
gAudioContext.externalPool.start = NULL; gAudioContext.externalPool.startRamAddr = NULL;
} }
void func_800E6128(SequencePlayer* seqPlayer, AudioCmd* cmd) { void func_800E6128(SequencePlayer* seqPlayer, AudioCmd* cmd) {
f32 fadeVolume; f32 fadeVolume;
switch (cmd->op) { switch (cmd->op) {
case 0x41: case 0x41:
if (seqPlayer->fadeVolumeScale != cmd->asFloat) { if (seqPlayer->fadeVolumeScale != cmd->asFloat) {
seqPlayer->fadeVolumeScale = cmd->asFloat; seqPlayer->fadeVolumeScale = cmd->asFloat;
seqPlayer->recalculateVolume = 1; seqPlayer->recalculateVolume = 1;
} }
return; break;
case 0x47: case 0x47:
seqPlayer->tempo = cmd->asInt * 0x30; seqPlayer->tempo = cmd->asInt * 0x30;
return; break;
case 0x49: case 0x49:
seqPlayer->unk_0C = cmd->asInt * 0x30; seqPlayer->unk_0C = cmd->asInt * 0x30;
return; break;
case 0x4E: case 0x4E:
seqPlayer->unk_0C = cmd->asInt; seqPlayer->unk_0C = cmd->asInt;
return; break;
case 0x48: case 0x48:
seqPlayer->transposition = cmd->asSbyte; seqPlayer->transposition = cmd->asSbyte;
return; break;
case 0x46: case 0x46:
seqPlayer->soundScriptIO[cmd->arg2] = cmd->asSbyte; seqPlayer->soundScriptIO[cmd->arg2] = cmd->asSbyte;
return; break;
case 0x4A: case 0x4A:
fadeVolume = (s32)cmd->arg1 / 127.0f; fadeVolume = (s32)cmd->arg1 / 127.0f;
goto block_11; goto block_11;
case 0x4B: case 0x4B:
fadeVolume = ((s32)cmd->arg1 / 100.0f) * seqPlayer->fadeVolume; fadeVolume = ((s32)cmd->arg1 / 100.0f) * seqPlayer->fadeVolume;
block_11: block_11:
@ -611,32 +642,40 @@ void func_800E6128(SequencePlayer* seqPlayer, AudioCmd* cmd) {
if (cmd->asInt == 0) { if (cmd->asInt == 0) {
seqPlayer->fadeVolume = fadeVolume; seqPlayer->fadeVolume = fadeVolume;
} else { } else {
s32 tmp = cmd->asInt; s32 fadeTimer = cmd->asInt;
seqPlayer->state = 0; seqPlayer->state = 0;
seqPlayer->fadeTimer = tmp; seqPlayer->fadeTimer = fadeTimer;
seqPlayer->fadeVelocity = (fadeVolume - seqPlayer->fadeVolume) / tmp; seqPlayer->fadeVelocity = (fadeVolume - seqPlayer->fadeVolume) / fadeTimer;
} }
} }
return; break;
case 0x4C: case 0x4C:
if (seqPlayer->state != 2) { if (seqPlayer->state != 2) {
if (cmd->asInt == 0) { if (cmd->asInt == 0) {
seqPlayer->fadeVolume = seqPlayer->volume; seqPlayer->fadeVolume = seqPlayer->volume;
} else { } else {
s32 tmp = cmd->asInt; s32 fadeTimer = cmd->asInt;
seqPlayer->state = 0; seqPlayer->state = 0;
seqPlayer->fadeTimer = tmp; seqPlayer->fadeTimer = fadeTimer;
seqPlayer->fadeVelocity = (seqPlayer->volume - seqPlayer->fadeVolume) / tmp; seqPlayer->fadeVelocity = (seqPlayer->volume - seqPlayer->fadeVolume) / fadeTimer;
} }
} }
return; break;
case 0x4D: case 0x4D:
seqPlayer->unk_34 = cmd->asFloat; seqPlayer->bend = cmd->asFloat;
if (seqPlayer->unk_34 == 1.0f) { if (seqPlayer->bend == 1.0f) {
seqPlayer->unk_0b1 = 0; seqPlayer->applyBend = false;
} else { } 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->volumeScale = cmd->asFloat;
channel->changes.s.volume = 1; channel->changes.s.volume = 1;
} }
return; break;
case CHAN_UPD_VOL: case CHAN_UPD_VOL:
if (channel->volume != cmd->asFloat) { if (channel->volume != cmd->asFloat) {
channel->volume = cmd->asFloat; channel->volume = cmd->asFloat;
channel->changes.s.volume = 1; channel->changes.s.volume = 1;
} }
return; break;
case CHAN_UPD_PAN_SIGNED: case CHAN_UPD_PAN_SIGNED:
if (channel->newPan != cmd->asSbyte) { if (channel->newPan != cmd->asSbyte) {
channel->newPan = cmd->asSbyte; channel->newPan = cmd->asSbyte;
channel->changes.s.pan = 1; channel->changes.s.pan = 1;
} }
return; break;
case CHAN_UPD_PAN_UNSIGNED: case CHAN_UPD_PAN_UNSIGNED:
if (channel->newPan != cmd->asSbyte) { if (channel->newPan != cmd->asSbyte) {
channel->panChannelWeight = cmd->asSbyte; channel->panChannelWeight = cmd->asSbyte;
channel->changes.s.pan = 1; channel->changes.s.pan = 1;
} }
return; break;
case CHAN_UPD_FREQ_SCALE: case CHAN_UPD_FREQ_SCALE:
if (channel->freqScale != cmd->asFloat) { if (channel->freqScale != cmd->asFloat) {
channel->freqScale = cmd->asFloat; channel->freqScale = cmd->asFloat;
channel->changes.s.freqScale = 1; channel->changes.s.freqScale = 1;
} }
return; break;
case CHAN_UPD_REVERB: case CHAN_UPD_REVERB:
if (channel->reverb != cmd->asSbyte) { if (channel->reverb != cmd->asSbyte) {
channel->reverb = cmd->asSbyte; channel->reverb = cmd->asSbyte;
} }
return; break;
case CHAN_UPD_SCRIPT_IO: case CHAN_UPD_SCRIPT_IO:
if (cmd->arg2 < 8) { if (cmd->arg2 < 8) {
channel->soundScriptIO[cmd->arg2] = cmd->asSbyte; channel->soundScriptIO[cmd->arg2] = cmd->asSbyte;
} }
return; break;
case CHAN_UPD_STOP_SOMETHING2: case CHAN_UPD_STOP_SOMETHING2:
channel->stopSomething2 = cmd->asSbyte; channel->stopSomething2 = cmd->asSbyte;
return; break;
case CHAN_UPD_MUTE_BEHAVE: case CHAN_UPD_MUTE_BEHAVE:
channel->muteBehavior = cmd->asSbyte; channel->muteBehavior = cmd->asSbyte;
return; break;
case CHAN_UPD_VIBE_X8: case CHAN_UPD_VIBE_X8:
channel->vibratoExtentTarget = cmd->asUbyte * 8; channel->vibratoExtentTarget = cmd->asUbyte * 8;
channel->vibratoExtentChangeDelay = 1; channel->vibratoExtentChangeDelay = 1;
return; break;
case CHAN_UPD_VIBE_X32: case CHAN_UPD_VIBE_X32:
channel->vibratoRateTarget = cmd->asUbyte * 32; channel->vibratoRateTarget = cmd->asUbyte * 32;
channel->vibratoRateChangeDelay = 1; channel->vibratoRateChangeDelay = 1;
return; break;
case CHAN_UPD_UNK_0F: case CHAN_UPD_UNK_0F:
channel->unk_0F = cmd->asUbyte; channel->unk_0F = cmd->asUbyte;
return; break;
case CHAN_UPD_UNK_20: case CHAN_UPD_UNK_20:
channel->unk_20 = cmd->asUShort; channel->unk_20 = cmd->asUShort;
return; break;
case CHAN_UPD_STEREO: case CHAN_UPD_STEREO:
channel->stereo.asByte = cmd->asUbyte; channel->stereo.asByte = cmd->asUbyte;
return; break;
default:
break;
} }
} }

View file

@ -2873,8 +2873,8 @@ void AudioDebug_Draw(GfxPrint* printer) {
GfxPrint_SetPos(printer, 3, 5); GfxPrint_SetPos(printer, 3, 5);
GfxPrint_Printf(printer, "DRIVER %05X / %05X", GfxPrint_Printf(printer, "DRIVER %05X / %05X",
gAudioContext.notesAndBuffersPool.cur - gAudioContext.notesAndBuffersPool.start, gAudioContext.miscPool.curRamAddr - gAudioContext.miscPool.startRamAddr,
gAudioContext.notesAndBuffersPool.size); gAudioContext.miscPool.size);
GfxPrint_SetPos(printer, 3, 6); GfxPrint_SetPos(printer, 3, 6);
GfxPrint_Printf( GfxPrint_Printf(
@ -2890,7 +2890,8 @@ void AudioDebug_Draw(GfxPrint* printer) {
GfxPrint_SetPos(printer, 3, 8); GfxPrint_SetPos(printer, 3, 8);
GfxPrint_Printf(printer, "ST-SEQ %02Xseqs (%05X / %06X)", gAudioContext.seqCache.persistent.numEntries, 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); gAudioContext.seqCache.persistent.pool.size);
for (k = 0; (u32)k < gAudioContext.seqCache.persistent.numEntries; k++) { 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_SetPos(printer, 3, 10);
GfxPrint_Printf(printer, "ST-BNK %02Xbanks (%05X / %06X)", gAudioContext.fontCache.persistent.numEntries, 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); gAudioContext.fontCache.persistent.pool.size);
for (k = 0; (u32)k < gAudioContext.fontCache.persistent.numEntries; k++) { 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_SetPos(printer, 3, 12);
GfxPrint_Printf(printer, "E-MEM %05X / %05X", GfxPrint_Printf(printer, "E-MEM %05X / %05X",
gAudioContext.permanentPool.cur - gAudioContext.permanentPool.start, gAudioContext.permanentPool.curRamAddr - gAudioContext.permanentPool.startRamAddr,
gAudioContext.permanentPool.size); gAudioContext.permanentPool.size);
break; break;