1
0
Fork 0
mirror of https://github.com/zeldaret/oot.git synced 2024-11-25 17:54:15 +00:00

Document SoundFont Relocation (#1237)

* Document fontData relocation

* Fix

* More cleanup

* typo

* sample -> sampleHeader

* Revert name

* Just a little more

* Another comment change

* Fix Drum

* fix

* K0BASE

* Update relocs

* consistency

* clearer phrasing

* Fix

* PR/Discord Suggestions

* typo

* Revert Sound Font Sample Struct for another PR

* Missed a function

* PR Suggestions

* sample bank reloc

* Revert header description

* better text

* SoundFount Relocation: some cleanup (#6)

* `fontDataStartAddr` for relocation, `fontData` for reading data (`AudioLoad_RelocateFont`)

* Comment "cleanup" in `AudioLoad_RelocateFont`

* Comment "cleanup" in `AudioLoad_RelocateSample`

* Cleanup cast and compares to 0 (offsets) / NULL (pointers)

* Cleanup

* Edit comments

* phrasing

Co-authored-by: Dragorn421 <Dragorn421@users.noreply.github.com>
This commit is contained in:
engineer124 2022-06-13 09:33:56 +10:00 committed by GitHub
parent feadb0d9ee
commit 605f13327a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 223 additions and 137 deletions

View file

@ -18,6 +18,8 @@
#define AIBUF_LEN 0x580 #define AIBUF_LEN 0x580
#define AUDIO_RELOCATED_ADDRESS_START K0BASE
typedef enum { typedef enum {
/* 0 */ ADSR_STATE_DISABLED, /* 0 */ ADSR_STATE_DISABLED,
/* 1 */ ADSR_STATE_INITIAL, /* 1 */ ADSR_STATE_INITIAL,
@ -130,14 +132,14 @@ typedef struct {
} AdpcmBook; // size >= 0x8 } AdpcmBook; // size >= 0x8
typedef struct { typedef struct {
/* 0x00 */ u32 codec : 4; /* 0x00 */ u32 codec : 4; // The state of compression or decompression
/* 0x00 */ u32 medium : 2; /* 0x00 */ u32 medium : 2; // Medium where sample is currently stored
/* 0x00 */ u32 unk_bit26 : 1; /* 0x00 */ u32 unk_bit26 : 1;
/* 0x00 */ u32 unk_bit25 : 1; /* 0x00 */ u32 isRelocated : 1; // Has the sample header been relocated (offsets to pointers)
/* 0x01 */ u32 size : 24; /* 0x01 */ u32 size : 24; // Size of the sample
/* 0x04 */ u8* sampleAddr; /* 0x04 */ u8* sampleAddr; // Raw sample data. Offset from the start of the sample bank or absolute address to either rom or ram
/* 0x08 */ AdpcmLoop* loop; /* 0x08 */ AdpcmLoop* loop; // Adpcm loop parameters used by the sample. Offset from the start of the sound font / pointer to ram
/* 0x0C */ AdpcmBook* book; /* 0x0C */ AdpcmBook* book; // Adpcm book parameters used by the sample. Offset from the start of the sound font / pointer to ram
} SoundFontSample; // size = 0x10 } SoundFontSample; // size = 0x10
typedef struct { typedef struct {
@ -199,7 +201,7 @@ typedef struct {
} SynthesisReverb; // size = 0x2C8 } SynthesisReverb; // size = 0x2C8
typedef struct { typedef struct {
/* 0x00 */ u8 loaded; /* 0x00 */ u8 isRelocated; // have the envelope and all samples been relocated (offsets to pointers)
/* 0x01 */ u8 normalRangeLo; /* 0x01 */ u8 normalRangeLo;
/* 0x02 */ u8 normalRangeHi; /* 0x02 */ u8 normalRangeHi;
/* 0x03 */ u8 adsrDecayIndex; // index used to obtain adsr decay rate from adsrDecayTable /* 0x03 */ u8 adsrDecayIndex; // index used to obtain adsr decay rate from adsrDecayTable
@ -212,7 +214,7 @@ typedef struct {
typedef struct { typedef struct {
/* 0x00 */ u8 adsrDecayIndex; // index used to obtain adsr decay rate from adsrDecayTable /* 0x00 */ u8 adsrDecayIndex; // index used to obtain adsr decay rate from adsrDecayTable
/* 0x01 */ u8 pan; /* 0x01 */ u8 pan;
/* 0x02 */ u8 loaded; /* 0x02 */ u8 isRelocated; // have sound.sample and envelope been relocated (offsets to pointers)
/* 0x04 */ SoundFontSound sound; /* 0x04 */ SoundFontSound sound;
/* 0x0C */ AdsrEnvelope* envelope; /* 0x0C */ AdsrEnvelope* envelope;
} Drum; // size = 0x10 } Drum; // size = 0x10

View file

@ -21,9 +21,9 @@ typedef struct {
/* 0x0C */ s32 baseAddr2; /* 0x0C */ s32 baseAddr2;
/* 0x10 */ u32 medium1; /* 0x10 */ u32 medium1;
/* 0x14 */ u32 medium2; /* 0x14 */ u32 medium2;
} RelocInfo; // size = 0x18 } SampleBankRelocInfo; // size = 0x18
// opaque type for unpatched sound font data (should maybe get rid of this?) // opaque type for soundfont data loaded into ram (should maybe get rid of this?)
typedef void SoundFontData; typedef void SoundFontData;
/* forward declarations */ /* forward declarations */
@ -33,8 +33,9 @@ SoundFontSample* AudioLoad_GetFontSample(s32 fontId, s32 instId);
void AudioLoad_ProcessAsyncLoads(s32 resetStatus); void AudioLoad_ProcessAsyncLoads(s32 resetStatus);
void AudioLoad_ProcessAsyncLoadUnkMedium(AudioAsyncLoad* asyncLoad, s32 resetStatus); void AudioLoad_ProcessAsyncLoadUnkMedium(AudioAsyncLoad* asyncLoad, s32 resetStatus);
void AudioLoad_ProcessAsyncLoad(AudioAsyncLoad* asyncLoad, s32 resetStatus); void AudioLoad_ProcessAsyncLoad(AudioAsyncLoad* asyncLoad, s32 resetStatus);
void AudioLoad_RelocateFontAndPreloadSamples(s32 fontId, SoundFontData* mem, RelocInfo* relocInfo, s32 async); void AudioLoad_RelocateFontAndPreloadSamples(s32 fontId, SoundFontData* fontData, SampleBankRelocInfo* sampleBankReloc,
void AudioLoad_RelocateSample(SoundFontSound* sound, SoundFontData* mem, RelocInfo* relocInfo); s32 async);
void AudioLoad_RelocateSample(SoundFontSound* sound, SoundFontData* fontData, SampleBankRelocInfo* sampleBankReloc);
void AudioLoad_DiscardFont(s32 fontId); void AudioLoad_DiscardFont(s32 fontId);
u32 AudioLoad_TrySyncLoadSampleBank(u32 sampleBankId, u32* outMedium, s32 noLoad); u32 AudioLoad_TrySyncLoadSampleBank(u32 sampleBankId, u32* outMedium, s32 noLoad);
void* AudioLoad_SyncLoad(u32 tableType, u32 tableId, s32* didAllocate); void* AudioLoad_SyncLoad(u32 tableType, u32 tableId, s32* didAllocate);
@ -397,7 +398,7 @@ void AudioLoad_SyncLoadSeqParts(s32 seqId, s32 arg1) {
s32 AudioLoad_SyncLoadSample(SoundFontSample* sample, s32 fontId) { s32 AudioLoad_SyncLoadSample(SoundFontSample* sample, s32 fontId) {
void* sampleAddr; void* sampleAddr;
if (sample->unk_bit25 == 1) { if (sample->isRelocated == true) {
if (sample->medium != MEDIUM_RAM) { if (sample->medium != MEDIUM_RAM) {
sampleAddr = AudioHeap_AllocSampleCache(sample->size, fontId, (void*)sample->sampleAddr, sample->medium, sampleAddr = AudioHeap_AllocSampleCache(sample->size, fontId, (void*)sample->sampleAddr, sample->medium,
CACHE_PERSISTENT); CACHE_PERSISTENT);
@ -623,7 +624,7 @@ SoundFontData* AudioLoad_SyncLoadFont(u32 fontId) {
s32 sampleBankId1; s32 sampleBankId1;
s32 sampleBankId2; s32 sampleBankId2;
s32 didAllocate; s32 didAllocate;
RelocInfo relocInfo; SampleBankRelocInfo sampleBankReloc;
s32 realFontId = AudioLoad_GetRealTableIndex(FONT_TABLE, fontId); s32 realFontId = AudioLoad_GetRealTableIndex(FONT_TABLE, fontId);
if (gAudioContext.fontLoadStatus[realFontId] == LOAD_STATUS_IN_PROGRESS) { if (gAudioContext.fontLoadStatus[realFontId] == LOAD_STATUS_IN_PROGRESS) {
@ -632,18 +633,18 @@ SoundFontData* AudioLoad_SyncLoadFont(u32 fontId) {
sampleBankId1 = gAudioContext.soundFonts[realFontId].sampleBankId1; sampleBankId1 = gAudioContext.soundFonts[realFontId].sampleBankId1;
sampleBankId2 = gAudioContext.soundFonts[realFontId].sampleBankId2; sampleBankId2 = gAudioContext.soundFonts[realFontId].sampleBankId2;
relocInfo.sampleBankId1 = sampleBankId1; sampleBankReloc.sampleBankId1 = sampleBankId1;
relocInfo.sampleBankId2 = sampleBankId2; sampleBankReloc.sampleBankId2 = sampleBankId2;
if (sampleBankId1 != 0xFF) { if (sampleBankId1 != 0xFF) {
relocInfo.baseAddr1 = AudioLoad_TrySyncLoadSampleBank(sampleBankId1, &relocInfo.medium1, false); sampleBankReloc.baseAddr1 = AudioLoad_TrySyncLoadSampleBank(sampleBankId1, &sampleBankReloc.medium1, false);
} else { } else {
relocInfo.baseAddr1 = 0; sampleBankReloc.baseAddr1 = 0;
} }
if (sampleBankId2 != 0xFF) { if (sampleBankId2 != 0xFF) {
relocInfo.baseAddr2 = AudioLoad_TrySyncLoadSampleBank(sampleBankId2, &relocInfo.medium2, false); sampleBankReloc.baseAddr2 = AudioLoad_TrySyncLoadSampleBank(sampleBankId2, &sampleBankReloc.medium2, false);
} else { } else {
relocInfo.baseAddr2 = 0; sampleBankReloc.baseAddr2 = 0;
} }
fontData = AudioLoad_SyncLoad(FONT_TABLE, fontId, &didAllocate); fontData = AudioLoad_SyncLoad(FONT_TABLE, fontId, &didAllocate);
@ -651,7 +652,7 @@ SoundFontData* AudioLoad_SyncLoadFont(u32 fontId) {
return NULL; return NULL;
} }
if (didAllocate == true) { if (didAllocate == true) {
AudioLoad_RelocateFontAndPreloadSamples(realFontId, fontData, &relocInfo, false); AudioLoad_RelocateFontAndPreloadSamples(realFontId, fontData, &sampleBankReloc, false);
} }
return fontData; return fontData;
@ -790,9 +791,17 @@ AudioTable* AudioLoad_GetLoadTable(s32 tableType) {
return table; return table;
} }
void AudioLoad_RelocateFont(s32 fontId, SoundFontData* mem, RelocInfo* relocInfo) { /**
u32 reloc; * Read and extract information from soundFont binary loaded into ram.
u32 reloc2; * Also relocate offsets into pointers within this loaded soundFont
*
* @param fontId index of font being processed
* @param fontData ram address of raw soundfont binary loaded into cache
* @param sampleBankReloc information on the sampleBank containing raw audio samples
*/
void AudioLoad_RelocateFont(s32 fontId, SoundFontData* fontDataStartAddr, SampleBankRelocInfo* sampleBankReloc) {
u32 soundOffset; // Relative offset from the beginning of fontData directly to the sound/envelope
u32 soundListOffset; // Relative offset from the beginning of fontData to the list of soundOffsets/sfxs
Instrument* inst; Instrument* inst;
Drum* drum; Drum* drum;
SoundFontSound* sfx; SoundFontSound* sfx;
@ -800,73 +809,117 @@ void AudioLoad_RelocateFont(s32 fontId, SoundFontData* mem, RelocInfo* relocInfo
s32 numDrums = gAudioContext.soundFonts[fontId].numDrums; s32 numDrums = gAudioContext.soundFonts[fontId].numDrums;
s32 numInstruments = gAudioContext.soundFonts[fontId].numInstruments; s32 numInstruments = gAudioContext.soundFonts[fontId].numInstruments;
s32 numSfx = gAudioContext.soundFonts[fontId].numSfx; s32 numSfx = gAudioContext.soundFonts[fontId].numSfx;
void** ptrs = (void**)mem; void** fontData = (void**)fontDataStartAddr;
#define BASE_OFFSET(x) (void*)((u32)(x) + (u32)(mem)) // Relocate an offset (relative to the start of the font data) to a pointer (a ram address)
#define RELOC_TO_RAM(offset) (void*)((u32)(offset) + (u32)(fontDataStartAddr))
reloc2 = ptrs[0]; // Drums relocation
// The first u32 in fontData is an offset to a list of offsets to the drums
soundListOffset = fontData[0];
if (1) {} if (1) {}
if ((reloc2 != 0) && (numDrums != 0)) {
ptrs[0] = BASE_OFFSET(reloc2); // If the soundFont has drums
if ((soundListOffset != 0) && (numDrums != 0)) {
fontData[0] = RELOC_TO_RAM(soundListOffset);
// Loop through the drum offsets
for (i = 0; i < numDrums; i++) { for (i = 0; i < numDrums; i++) {
reloc = ((Drum**)ptrs[0])[i]; // Get the i'th drum offset
if (reloc != 0) { soundOffset = ((Drum**)fontData[0])[i];
reloc = BASE_OFFSET(reloc);
((Drum**)ptrs[0])[i] = drum = reloc; // Some drum data entries are empty, represented by an offset of 0 in the list of drum offsets
if (!drum->loaded) { if (soundOffset != 0) {
AudioLoad_RelocateSample(&drum->sound, mem, relocInfo); soundOffset = RELOC_TO_RAM(soundOffset);
reloc = drum->envelope; ((Drum**)fontData[0])[i] = drum = soundOffset;
drum->envelope = BASE_OFFSET(reloc);
drum->loaded = 1; // The drum may be in the list multiple times and already relocated
if (!drum->isRelocated) {
AudioLoad_RelocateSample(&drum->sound, fontDataStartAddr, sampleBankReloc);
soundOffset = drum->envelope;
drum->envelope = RELOC_TO_RAM(soundOffset);
drum->isRelocated = true;
} }
} }
} }
} }
reloc2 = ptrs[1]; // Sound effects relocation
// The second u32 in fontData is an offset to the first sound effect entry
soundListOffset = fontData[1];
if (1) {} if (1) {}
if ((reloc2 != 0) && (numSfx != 0)) {
ptrs[1] = BASE_OFFSET(reloc2); // If the soundFont has sound effects
if ((soundListOffset != 0) && (numSfx != 0)) {
fontData[1] = RELOC_TO_RAM(soundListOffset);
// Loop through the sound effects
for (i = 0; i < numSfx; i++) { for (i = 0; i < numSfx; i++) {
reloc = (SoundFontSound*)ptrs[1] + i; // Get a pointer to the i'th sound effect
if (reloc != 0) { soundOffset = ((SoundFontSound*)fontData[1]) + i;
sfx = reloc;
if (sfx->sample != NULL) { // Check for NULL (note: the pointer is guaranteed to be in fontData and can never be NULL)
AudioLoad_RelocateSample(sfx, mem, relocInfo); if ((SoundFontSound*)soundOffset != NULL) {
sfx = soundOffset;
if ((u32)sfx->sample != 0) {
AudioLoad_RelocateSample(sfx, fontDataStartAddr, sampleBankReloc);
} }
} }
} }
} }
if (numInstruments > 0x7E) { // Instruments relocation
numInstruments = 0x7E;
// Instrument Id 126 and above is reserved.
// There can only be 126 instruments, indexed from 0 to 125
if (numInstruments > 126) {
numInstruments = 126;
} }
// Starting from the 3rd u32 in fontData is the list of offsets to the instruments
// Loop through the instruments
for (i = 2; i <= 2 + numInstruments - 1; i++) { for (i = 2; i <= 2 + numInstruments - 1; i++) {
if (ptrs[i] != NULL) { // Some instrument data entries are empty, represented by an offset of 0 in the list of instrument offsets
ptrs[i] = BASE_OFFSET(ptrs[i]); if ((u32)fontData[i] != 0) {
inst = ptrs[i]; fontData[i] = RELOC_TO_RAM(fontData[i]);
if (!inst->loaded) { inst = fontData[i];
// The instrument may be in the list multiple times and already relocated
if (!inst->isRelocated) {
// Some instruments have a different sample for low pitches
if (inst->normalRangeLo != 0) { if (inst->normalRangeLo != 0) {
AudioLoad_RelocateSample(&inst->lowNotesSound, mem, relocInfo); AudioLoad_RelocateSample(&inst->lowNotesSound, fontDataStartAddr, sampleBankReloc);
}
AudioLoad_RelocateSample(&inst->normalNotesSound, mem, relocInfo);
if (inst->normalRangeHi != 0x7F) {
AudioLoad_RelocateSample(&inst->highNotesSound, mem, relocInfo);
} }
reloc = inst->envelope; // Every instrument has a sample for the default range
inst->envelope = BASE_OFFSET(reloc); AudioLoad_RelocateSample(&inst->normalNotesSound, fontDataStartAddr, sampleBankReloc);
inst->loaded = true;
// Some instruments have a different sample for high pitches
if (inst->normalRangeHi != 0x7F) {
AudioLoad_RelocateSample(&inst->highNotesSound, fontDataStartAddr, sampleBankReloc);
}
soundOffset = inst->envelope;
inst->envelope = RELOC_TO_RAM(soundOffset);
inst->isRelocated = true;
} }
} }
} }
#undef BASE_OFFSET #undef FONT_DATA_RELOC
gAudioContext.soundFonts[fontId].drums = ptrs[0]; // Store the relocated pointers to the sound lists in the soundFonts meta-data struct
gAudioContext.soundFonts[fontId].soundEffects = ptrs[1]; gAudioContext.soundFonts[fontId].drums = (Drum**)fontData[0];
gAudioContext.soundFonts[fontId].instruments = (Instrument**)(ptrs + 2); gAudioContext.soundFonts[fontId].soundEffects = (SoundFontSound*)fontData[1];
gAudioContext.soundFonts[fontId].instruments = (Instrument**)(fontData + 2);
} }
void AudioLoad_SyncDma(u32 devAddr, u8* ramAddr, u32 size, s32 medium) { void AudioLoad_SyncDma(u32 devAddr, u8* ramAddr, u32 size, s32 medium) {
@ -1497,7 +1550,7 @@ void AudioLoad_FinishAsyncLoad(AudioAsyncLoad* asyncLoad) {
OSMesg doneMsg; OSMesg doneMsg;
u32 sampleBankId1; u32 sampleBankId1;
u32 sampleBankId2; u32 sampleBankId2;
RelocInfo relocInfo; SampleBankRelocInfo sampleBankReloc;
if (1) {} if (1) {}
switch (ASYNC_TBLTYPE(retMsg)) { switch (ASYNC_TBLTYPE(retMsg)) {
@ -1513,14 +1566,14 @@ void AudioLoad_FinishAsyncLoad(AudioAsyncLoad* asyncLoad) {
fontId = ASYNC_ID(retMsg); fontId = ASYNC_ID(retMsg);
sampleBankId1 = gAudioContext.soundFonts[fontId].sampleBankId1; sampleBankId1 = gAudioContext.soundFonts[fontId].sampleBankId1;
sampleBankId2 = gAudioContext.soundFonts[fontId].sampleBankId2; sampleBankId2 = gAudioContext.soundFonts[fontId].sampleBankId2;
relocInfo.sampleBankId1 = sampleBankId1; sampleBankReloc.sampleBankId1 = sampleBankId1;
relocInfo.sampleBankId2 = sampleBankId2; sampleBankReloc.sampleBankId2 = sampleBankId2;
relocInfo.baseAddr1 = sampleBankReloc.baseAddr1 =
sampleBankId1 != 0xFF ? AudioLoad_GetSampleBank(sampleBankId1, &relocInfo.medium1) : 0; sampleBankId1 != 0xFF ? AudioLoad_GetSampleBank(sampleBankId1, &sampleBankReloc.medium1) : 0;
relocInfo.baseAddr2 = sampleBankReloc.baseAddr2 =
sampleBankId2 != 0xFF ? AudioLoad_GetSampleBank(sampleBankId2, &relocInfo.medium2) : 0; sampleBankId2 != 0xFF ? AudioLoad_GetSampleBank(sampleBankId2, &sampleBankReloc.medium2) : 0;
AudioLoad_SetFontLoadStatus(fontId, ASYNC_LOAD_STATUS(retMsg)); AudioLoad_SetFontLoadStatus(fontId, ASYNC_LOAD_STATUS(retMsg));
AudioLoad_RelocateFontAndPreloadSamples(fontId, asyncLoad->ramAddr, &relocInfo, true); AudioLoad_RelocateFontAndPreloadSamples(fontId, asyncLoad->ramAddr, &sampleBankReloc, true);
break; break;
} }
@ -1589,28 +1642,49 @@ void AudioLoad_AsyncDma(AudioAsyncLoad* asyncLoad, u32 size) {
void AudioLoad_AsyncDmaUnkMedium(u32 devAddr, void* ramAddr, u32 size, s16 arg3) { void AudioLoad_AsyncDmaUnkMedium(u32 devAddr, void* ramAddr, u32 size, s16 arg3) {
} }
#define RELOC(v, base) (reloc = (void*)((u32)(v) + (u32)(base))) /**
* Read and extract information from SoundFontSound and its SoundFontSample
void AudioLoad_RelocateSample(SoundFontSound* sound, SoundFontData* mem, RelocInfo* relocInfo) { * contained in the soundFont binary loaded into ram
* SoundFontSound contains metadata on a sample used by a particular instrument/drum/sfx
* Also relocate offsets into pointers within this loaded SoundFontSound
*
* @param fontId index of font being processed
* @param fontData ram address of raw soundfont binary loaded into cache
* @param sampleBankReloc information on the sampleBank containing raw audio samples
*/
void AudioLoad_RelocateSample(SoundFontSound* sound, SoundFontData* fontData, SampleBankRelocInfo* sampleBankReloc) {
SoundFontSample* sample; SoundFontSample* sample;
void* reloc; void* reloc;
if ((u32)sound->sample <= 0x80000000) { // Relocate an offset (relative to data loaded in ram at `base`) to a pointer (a ram address)
sample = sound->sample = RELOC(sound->sample, mem); #define AUDIO_RELOC(offset, base) (reloc = (void*)((u32)(offset) + (u32)(base)))
if (sample->size != 0 && sample->unk_bit25 != 1) {
sample->loop = RELOC(sample->loop, mem);
sample->book = RELOC(sample->book, mem);
// Resolve the sample medium 2-bit bitfield into a real value based on relocInfo. // If this has not already been relocated
if ((u32)sound->sample <= AUDIO_RELOCATED_ADDRESS_START) {
sample = sound->sample = AUDIO_RELOC(sound->sample, fontData);
// If the sample exists and has not already been relocated
// Note: this is important, as the same sample can be used by different drums, sound effects, instruments
if ((sample->size != 0) && (sample->isRelocated != true)) {
sample->loop = AUDIO_RELOC(sample->loop, fontData);
sample->book = AUDIO_RELOC(sample->book, fontData);
// Resolve the sample medium 2-bit bitfield into a real value based on sampleBankReloc.
// Then relocate the offset sample within the sampleBank (not the fontData) into absolute address.
// sampleAddr can be either rom or ram depending on sampleBank cache policy
// in practice, this is always in rom
switch (sample->medium) { switch (sample->medium) {
case 0: case 0:
sample->sampleAddr = RELOC(sample->sampleAddr, relocInfo->baseAddr1); sample->sampleAddr = AUDIO_RELOC(sample->sampleAddr, sampleBankReloc->baseAddr1);
sample->medium = relocInfo->medium1; sample->medium = sampleBankReloc->medium1;
break; break;
case 1: case 1:
sample->sampleAddr = RELOC(sample->sampleAddr, relocInfo->baseAddr2); sample->sampleAddr = AUDIO_RELOC(sample->sampleAddr, sampleBankReloc->baseAddr2);
sample->medium = relocInfo->medium2; sample->medium = sampleBankReloc->medium2;
break; break;
case 2: case 2:
case 3: case 3:
// Invalid? This leaves sample->medium as MEDIUM_CART and MEDIUM_DISK_DRIVE // Invalid? This leaves sample->medium as MEDIUM_CART and MEDIUM_DISK_DRIVE
@ -1618,17 +1692,25 @@ void AudioLoad_RelocateSample(SoundFontSound* sound, SoundFontData* mem, RelocIn
break; break;
} }
sample->unk_bit25 = 1; sample->isRelocated = true;
if (sample->unk_bit26 && (sample->medium != MEDIUM_RAM)) { if (sample->unk_bit26 && (sample->medium != MEDIUM_RAM)) {
gAudioContext.usedSamples[gAudioContext.numUsedSamples++] = sample; gAudioContext.usedSamples[gAudioContext.numUsedSamples++] = sample;
} }
} }
} }
#undef AUDIO_RELOC
} }
#undef RELOC /**
* @param fontId index of font being processed
void AudioLoad_RelocateFontAndPreloadSamples(s32 fontId, SoundFontData* mem, RelocInfo* relocInfo, s32 async) { * @param fontData ram address of raw soundfont binary loaded into cache
* @param sampleBankReloc information on the sampleBank containing raw audio samples
* @param isAsync bool for whether this is an asynchronous load or not
*/
void AudioLoad_RelocateFontAndPreloadSamples(s32 fontId, SoundFontData* fontData, SampleBankRelocInfo* sampleBankReloc,
s32 isAsync) {
AudioPreloadReq* preload; AudioPreloadReq* preload;
AudioPreloadReq* topPreload; AudioPreloadReq* topPreload;
SoundFontSample* sample; SoundFontSample* sample;
@ -1646,7 +1728,7 @@ void AudioLoad_RelocateFontAndPreloadSamples(s32 fontId, SoundFontData* mem, Rel
} }
gAudioContext.numUsedSamples = 0; gAudioContext.numUsedSamples = 0;
AudioLoad_RelocateFont(fontId, mem, relocInfo); AudioLoad_RelocateFont(fontId, fontData, sampleBankReloc);
size = 0; size = 0;
for (i = 0; i < gAudioContext.numUsedSamples; i++) { for (i = 0; i < gAudioContext.numUsedSamples; i++) {
@ -1661,13 +1743,13 @@ void AudioLoad_RelocateFontAndPreloadSamples(s32 fontId, SoundFontData* mem, Rel
sample = gAudioContext.usedSamples[i]; sample = gAudioContext.usedSamples[i];
sampleRamAddr = NULL; sampleRamAddr = NULL;
switch (async) { switch (isAsync) {
case false: case false:
if (sample->medium == relocInfo->medium1) { if (sample->medium == sampleBankReloc->medium1) {
sampleRamAddr = AudioHeap_AllocSampleCache(sample->size, relocInfo->sampleBankId1, sampleRamAddr = AudioHeap_AllocSampleCache(sample->size, sampleBankReloc->sampleBankId1,
sample->sampleAddr, sample->medium, CACHE_PERSISTENT); sample->sampleAddr, sample->medium, CACHE_PERSISTENT);
} else if (sample->medium == relocInfo->medium2) { } else if (sample->medium == sampleBankReloc->medium2) {
sampleRamAddr = AudioHeap_AllocSampleCache(sample->size, relocInfo->sampleBankId2, sampleRamAddr = AudioHeap_AllocSampleCache(sample->size, sampleBankReloc->sampleBankId2,
sample->sampleAddr, sample->medium, CACHE_PERSISTENT); sample->sampleAddr, sample->medium, CACHE_PERSISTENT);
} else if (sample->medium == MEDIUM_DISK_DRIVE) { } else if (sample->medium == MEDIUM_DISK_DRIVE) {
sampleRamAddr = AudioHeap_AllocSampleCache(sample->size, 0xFE, sample->sampleAddr, sample->medium, sampleRamAddr = AudioHeap_AllocSampleCache(sample->size, 0xFE, sample->sampleAddr, sample->medium,
@ -1676,11 +1758,11 @@ void AudioLoad_RelocateFontAndPreloadSamples(s32 fontId, SoundFontData* mem, Rel
break; break;
case true: case true:
if (sample->medium == relocInfo->medium1) { if (sample->medium == sampleBankReloc->medium1) {
sampleRamAddr = AudioHeap_AllocSampleCache(sample->size, relocInfo->sampleBankId1, sampleRamAddr = AudioHeap_AllocSampleCache(sample->size, sampleBankReloc->sampleBankId1,
sample->sampleAddr, sample->medium, CACHE_TEMPORARY); sample->sampleAddr, sample->medium, CACHE_TEMPORARY);
} else if (sample->medium == relocInfo->medium2) { } else if (sample->medium == sampleBankReloc->medium2) {
sampleRamAddr = AudioHeap_AllocSampleCache(sample->size, relocInfo->sampleBankId2, sampleRamAddr = AudioHeap_AllocSampleCache(sample->size, sampleBankReloc->sampleBankId2,
sample->sampleAddr, sample->medium, CACHE_TEMPORARY); sample->sampleAddr, sample->medium, CACHE_TEMPORARY);
} else if (sample->medium == MEDIUM_DISK_DRIVE) { } else if (sample->medium == MEDIUM_DISK_DRIVE) {
sampleRamAddr = AudioHeap_AllocSampleCache(sample->size, 0xFE, sample->sampleAddr, sample->medium, sampleRamAddr = AudioHeap_AllocSampleCache(sample->size, 0xFE, sample->sampleAddr, sample->medium,
@ -1692,7 +1774,7 @@ void AudioLoad_RelocateFontAndPreloadSamples(s32 fontId, SoundFontData* mem, Rel
continue; continue;
} }
switch (async) { switch (isAsync) {
case false: case false:
if (sample->medium == MEDIUM_UNK) { if (sample->medium == MEDIUM_UNK) {
AudioLoad_SyncDmaUnkMedium((u32)sample->sampleAddr, sampleRamAddr, sample->size, AudioLoad_SyncDmaUnkMedium((u32)sample->sampleAddr, sampleRamAddr, sample->size,
@ -1844,12 +1926,12 @@ s32 AudioLoad_GetSamplesForFont(s32 fontId, SoundFontSample** sampleSet) {
void AudioLoad_AddUsedSample(SoundFontSound* sound) { void AudioLoad_AddUsedSample(SoundFontSound* sound) {
SoundFontSample* sample = sound->sample; SoundFontSample* sample = sound->sample;
if ((sample->size != 0) && (sample->unk_bit26) && (sample->medium != MEDIUM_RAM)) { if ((sample->size != 0) && sample->unk_bit26 && (sample->medium != MEDIUM_RAM)) {
gAudioContext.usedSamples[gAudioContext.numUsedSamples++] = sample; gAudioContext.usedSamples[gAudioContext.numUsedSamples++] = sample;
} }
} }
void AudioLoad_PreloadSamplesForFont(s32 fontId, s32 async, RelocInfo* relocInfo) { void AudioLoad_PreloadSamplesForFont(s32 fontId, s32 async, SampleBankRelocInfo* sampleBankReloc) {
s32 numDrums; s32 numDrums;
s32 numInstruments; s32 numInstruments;
s32 numSfx; s32 numSfx;
@ -1925,21 +2007,21 @@ void AudioLoad_PreloadSamplesForFont(s32 fontId, s32 async, RelocInfo* relocInfo
switch (async) { switch (async) {
case false: case false:
if (sample->medium == relocInfo->medium1) { if (sample->medium == sampleBankReloc->medium1) {
addr = AudioHeap_AllocSampleCache(sample->size, relocInfo->sampleBankId1, sample->sampleAddr, addr = AudioHeap_AllocSampleCache(sample->size, sampleBankReloc->sampleBankId1, sample->sampleAddr,
sample->medium, CACHE_PERSISTENT); sample->medium, CACHE_PERSISTENT);
} else if (sample->medium == relocInfo->medium2) { } else if (sample->medium == sampleBankReloc->medium2) {
addr = AudioHeap_AllocSampleCache(sample->size, relocInfo->sampleBankId2, sample->sampleAddr, addr = AudioHeap_AllocSampleCache(sample->size, sampleBankReloc->sampleBankId2, sample->sampleAddr,
sample->medium, CACHE_PERSISTENT); sample->medium, CACHE_PERSISTENT);
} }
break; break;
case true: case true:
if (sample->medium == relocInfo->medium1) { if (sample->medium == sampleBankReloc->medium1) {
addr = AudioHeap_AllocSampleCache(sample->size, relocInfo->sampleBankId1, sample->sampleAddr, addr = AudioHeap_AllocSampleCache(sample->size, sampleBankReloc->sampleBankId1, sample->sampleAddr,
sample->medium, CACHE_TEMPORARY); sample->medium, CACHE_TEMPORARY);
} else if (sample->medium == relocInfo->medium2) { } else if (sample->medium == sampleBankReloc->medium2) {
addr = AudioHeap_AllocSampleCache(sample->size, relocInfo->sampleBankId2, sample->sampleAddr, addr = AudioHeap_AllocSampleCache(sample->size, sampleBankReloc->sampleBankId2, sample->sampleAddr,
sample->medium, CACHE_TEMPORARY); sample->medium, CACHE_TEMPORARY);
} }
break; break;
@ -1993,23 +2075,25 @@ void AudioLoad_LoadPermanentSamples(void) {
sampleBankTable = AudioLoad_GetLoadTable(SAMPLE_TABLE); sampleBankTable = AudioLoad_GetLoadTable(SAMPLE_TABLE);
for (i = 0; i < gAudioContext.permanentPool.numEntries; i++) { for (i = 0; i < gAudioContext.permanentPool.numEntries; i++) {
RelocInfo relocInfo; SampleBankRelocInfo sampleBankReloc;
if (gAudioContext.permanentCache[i].tableType == FONT_TABLE) { if (gAudioContext.permanentCache[i].tableType == FONT_TABLE) {
fontId = AudioLoad_GetRealTableIndex(FONT_TABLE, gAudioContext.permanentCache[i].id); fontId = AudioLoad_GetRealTableIndex(FONT_TABLE, gAudioContext.permanentCache[i].id);
relocInfo.sampleBankId1 = gAudioContext.soundFonts[fontId].sampleBankId1; sampleBankReloc.sampleBankId1 = gAudioContext.soundFonts[fontId].sampleBankId1;
relocInfo.sampleBankId2 = gAudioContext.soundFonts[fontId].sampleBankId2; sampleBankReloc.sampleBankId2 = gAudioContext.soundFonts[fontId].sampleBankId2;
if (relocInfo.sampleBankId1 != 0xFF) { if (sampleBankReloc.sampleBankId1 != 0xFF) {
relocInfo.sampleBankId1 = AudioLoad_GetRealTableIndex(SAMPLE_TABLE, relocInfo.sampleBankId1); sampleBankReloc.sampleBankId1 =
relocInfo.medium1 = sampleBankTable->entries[relocInfo.sampleBankId1].medium; AudioLoad_GetRealTableIndex(SAMPLE_TABLE, sampleBankReloc.sampleBankId1);
sampleBankReloc.medium1 = sampleBankTable->entries[sampleBankReloc.sampleBankId1].medium;
} }
if (relocInfo.sampleBankId2 != 0xFF) { if (sampleBankReloc.sampleBankId2 != 0xFF) {
relocInfo.sampleBankId2 = AudioLoad_GetRealTableIndex(SAMPLE_TABLE, relocInfo.sampleBankId2); sampleBankReloc.sampleBankId2 =
relocInfo.medium2 = sampleBankTable->entries[relocInfo.sampleBankId2].medium; AudioLoad_GetRealTableIndex(SAMPLE_TABLE, sampleBankReloc.sampleBankId2);
sampleBankReloc.medium2 = sampleBankTable->entries[sampleBankReloc.sampleBankId2].medium;
} }
AudioLoad_PreloadSamplesForFont(fontId, false, &relocInfo); AudioLoad_PreloadSamplesForFont(fontId, false, &sampleBankReloc);
} }
} }
} }

View file

@ -348,7 +348,7 @@ Drum* Audio_GetDrum(s32 fontId, s32 drumId) {
gAudioContext.audioErrorFlags = ((fontId << 8) + drumId) + 0x4000000; gAudioContext.audioErrorFlags = ((fontId << 8) + drumId) + 0x4000000;
return NULL; return NULL;
} }
if ((u32)gAudioContext.soundFonts[fontId].drums < 0x80000000) { if ((u32)gAudioContext.soundFonts[fontId].drums < AUDIO_RELOCATED_ADDRESS_START) {
return NULL; return NULL;
} }
drum = gAudioContext.soundFonts[fontId].drums[drumId]; drum = gAudioContext.soundFonts[fontId].drums[drumId];
@ -377,7 +377,7 @@ SoundFontSound* Audio_GetSfx(s32 fontId, s32 sfxId) {
return NULL; return NULL;
} }
if ((u32)gAudioContext.soundFonts[fontId].soundEffects < 0x80000000) { if ((u32)gAudioContext.soundFonts[fontId].soundEffects < AUDIO_RELOCATED_ADDRESS_START) {
return NULL; return NULL;
} }

View file

@ -687,7 +687,7 @@ Acmd* AudioSynth_DoOneAudioUpdate(s16* aiBuf, s32 aiBufLen, Acmd* cmd, s32 updat
Acmd* AudioSynth_ProcessNote(s32 noteIndex, NoteSubEu* noteSubEu, NoteSynthesisState* synthState, s16* aiBuf, Acmd* AudioSynth_ProcessNote(s32 noteIndex, NoteSubEu* noteSubEu, NoteSynthesisState* synthState, s16* aiBuf,
s32 aiBufLen, Acmd* cmd, s32 updateIndex) { s32 aiBufLen, Acmd* cmd, s32 updateIndex) {
s32 pad1[3]; s32 pad1[3];
SoundFontSample* audioFontSample; SoundFontSample* sample;
AdpcmLoop* loopInfo; AdpcmLoop* loopInfo;
s32 nSamplesUntilLoopEnd; s32 nSamplesUntilLoopEnd;
s32 nSamplesInThisIteration; s32 nSamplesInThisIteration;
@ -778,10 +778,10 @@ Acmd* AudioSynth_ProcessNote(s32 noteIndex, NoteSubEu* noteSubEu, NoteSynthesisS
noteSamplesDmemAddrBeforeResampling = DMEM_UNCOMPRESSED_NOTE + (synthState->samplePosInt * 2); noteSamplesDmemAddrBeforeResampling = DMEM_UNCOMPRESSED_NOTE + (synthState->samplePosInt * 2);
synthState->samplePosInt += nSamplesToLoad; synthState->samplePosInt += nSamplesToLoad;
} else { } else {
audioFontSample = noteSubEu->sound.soundFontSound->sample; sample = noteSubEu->sound.soundFontSound->sample;
loopInfo = audioFontSample->loop; loopInfo = sample->loop;
loopEndPos = loopInfo->end; loopEndPos = loopInfo->end;
sampleAddr = audioFontSample->sampleAddr; sampleAddr = sample->sampleAddr;
resampledTempLen = 0; resampledTempLen = 0;
for (curPart = 0; curPart < nParts; curPart++) { for (curPart = 0; curPart < nParts; curPart++) {
@ -796,8 +796,8 @@ Acmd* AudioSynth_ProcessNote(s32 noteIndex, NoteSubEu* noteSubEu, NoteSynthesisS
samplesLenAdjusted = nSamplesToLoad; samplesLenAdjusted = nSamplesToLoad;
} }
if (audioFontSample->codec == CODEC_ADPCM || audioFontSample->codec == CODEC_SMALL_ADPCM) { if (sample->codec == CODEC_ADPCM || sample->codec == CODEC_SMALL_ADPCM) {
if (gAudioContext.curLoadedBook != audioFontSample->book->book) { if (gAudioContext.curLoadedBook != sample->book->book) {
u32 nEntries; u32 nEntries;
switch (bookOffset) { switch (bookOffset) {
case 1: case 1:
@ -806,13 +806,13 @@ Acmd* AudioSynth_ProcessNote(s32 noteIndex, NoteSubEu* noteSubEu, NoteSynthesisS
case 2: case 2:
case 3: case 3:
default: default:
gAudioContext.curLoadedBook = audioFontSample->book->book; gAudioContext.curLoadedBook = sample->book->book;
break; break;
} }
if (1) {} if (1) {}
if (1) {} if (1) {}
if (1) {} if (1) {}
nEntries = 16 * audioFontSample->book->order * audioFontSample->book->npredictors; nEntries = 16 * sample->book->order * sample->book->npredictors;
aLoadADPCM(cmd++, nEntries, gAudioContext.curLoadedBook); aLoadADPCM(cmd++, nEntries, gAudioContext.curLoadedBook);
} }
} }
@ -851,7 +851,7 @@ Acmd* AudioSynth_ProcessNote(s32 noteIndex, NoteSubEu* noteSubEu, NoteSynthesisS
} }
} }
switch (audioFontSample->codec) { switch (sample->codec) {
case CODEC_ADPCM: case CODEC_ADPCM:
frameSize = 9; frameSize = 9;
skipInitialSamples = 16; skipInitialSamples = 16;
@ -893,14 +893,14 @@ Acmd* AudioSynth_ProcessNote(s32 noteIndex, NoteSubEu* noteSubEu, NoteSynthesisS
if (nFramesToDecode != 0) { if (nFramesToDecode != 0) {
frameIndex = (synthState->samplePosInt + skipInitialSamples - nFirstFrameSamplesToIgnore) / 16; frameIndex = (synthState->samplePosInt + skipInitialSamples - nFirstFrameSamplesToIgnore) / 16;
sampleDataOffset = frameIndex * frameSize; sampleDataOffset = frameIndex * frameSize;
if (audioFontSample->medium == MEDIUM_RAM) { if (sample->medium == MEDIUM_RAM) {
sampleData = (u8*)(sampleDataStart + sampleDataOffset + sampleAddr); sampleData = (u8*)(sampleDataStart + sampleDataOffset + sampleAddr);
} else if (audioFontSample->medium == MEDIUM_UNK) { } else if (sample->medium == MEDIUM_UNK) {
return cmd; return cmd;
} else { } else {
sampleData = AudioLoad_DmaSampleData(sampleDataStart + sampleDataOffset + sampleAddr, sampleData = AudioLoad_DmaSampleData(sampleDataStart + sampleDataOffset + sampleAddr,
ALIGN16((nFramesToDecode * frameSize) + 0x10), flags, ALIGN16((nFramesToDecode * frameSize) + 0x10), flags,
&synthState->sampleDmaIndex, audioFontSample->medium); &synthState->sampleDmaIndex, sample->medium);
} }
if (sampleData == NULL) { if (sampleData == NULL) {
@ -917,7 +917,7 @@ Acmd* AudioSynth_ProcessNote(s32 noteIndex, NoteSubEu* noteSubEu, NoteSynthesisS
} }
if (synthState->restart) { if (synthState->restart) {
aSetLoop(cmd++, audioFontSample->loop->state); aSetLoop(cmd++, sample->loop->state);
flags = A_LOOP; flags = A_LOOP;
synthState->restart = false; synthState->restart = false;
} }
@ -930,7 +930,7 @@ Acmd* AudioSynth_ProcessNote(s32 noteIndex, NoteSubEu* noteSubEu, NoteSynthesisS
phi_s4 = ALIGN16(s5 + 16); phi_s4 = ALIGN16(s5 + 16);
} }
switch (audioFontSample->codec) { switch (sample->codec) {
case CODEC_ADPCM: case CODEC_ADPCM:
aligned = ALIGN16((nFramesToDecode * frameSize) + 0x10); aligned = ALIGN16((nFramesToDecode * frameSize) + 0x10);
addr = DMEM_COMPRESSED_ADPCM_DATA - aligned; addr = DMEM_COMPRESSED_ADPCM_DATA - aligned;