From 78754246074a7377a5d163856caf99eb9dc93539 Mon Sep 17 00:00:00 2001 From: KiritoDv Date: Fri, 29 Nov 2024 11:00:09 -0600 Subject: [PATCH] Audio is now compiling but crashing yay --- src/audio/GameAudio.h | 12 + src/audio/heap.h | 4 +- src/audio/internal.h | 28 +- src/audio/load.c | 139 +-- src/audio/load.h | 3 +- src/audio/mixer.c | 576 +++++++++++-- src/audio/mixer.h | 94 +- src/audio/playback.c | 18 +- src/audio/port_eu.c | 34 + src/audio/seqplayer.c | 28 +- src/audio/synthesis.c | 18 +- src/audio/synthesis.h | 22 +- src/main.c | 2 +- src/port/Engine.cpp | 204 ++++- src/port/Engine.h | 25 + src/port/Game.cpp | 16 +- .../resource/importers/AudioBankFactory.cpp | 96 +++ .../resource/importers/AudioBankFactory.h | 11 + .../resource/importers/AudioSampleFactory.cpp | 47 + .../resource/importers/AudioSampleFactory.h | 11 + .../importers/AudioSequenceFactory.cpp | 33 + .../resource/importers/AudioSequenceFactory.h | 12 + src/port/resource/importers/ResourceUtil.h | 11 +- src/port/resource/type/AudioBank.cpp | 11 + src/port/resource/type/AudioBank.h | 59 ++ src/port/resource/type/AudioSample.cpp | 11 + src/port/resource/type/AudioSample.h | 47 + src/port/resource/type/AudioSequence.cpp | 11 + src/port/resource/type/AudioSequence.h | 32 + src/port/resource/type/ResourceType.h | 4 + yamls/us/sound/banks.yml | 83 ++ yamls/us/{audio.yml => sound/root.yml} | 5 +- yamls/us/sound/samples.yml | 807 ++++++++++++++++++ yamls/us/sound/sequences.yml | 239 ++++++ 34 files changed, 2489 insertions(+), 264 deletions(-) create mode 100644 src/audio/GameAudio.h create mode 100644 src/port/resource/importers/AudioBankFactory.cpp create mode 100644 src/port/resource/importers/AudioBankFactory.h create mode 100644 src/port/resource/importers/AudioSampleFactory.cpp create mode 100644 src/port/resource/importers/AudioSampleFactory.h create mode 100644 src/port/resource/importers/AudioSequenceFactory.cpp create mode 100644 src/port/resource/importers/AudioSequenceFactory.h create mode 100644 src/port/resource/type/AudioBank.cpp create mode 100644 src/port/resource/type/AudioBank.h create mode 100644 src/port/resource/type/AudioSample.cpp create mode 100644 src/port/resource/type/AudioSample.h create mode 100644 src/port/resource/type/AudioSequence.cpp create mode 100644 src/port/resource/type/AudioSequence.h create mode 100644 yamls/us/sound/banks.yml rename yamls/us/{audio.yml => sound/root.yml} (64%) create mode 100644 yamls/us/sound/samples.yml create mode 100644 yamls/us/sound/sequences.yml diff --git a/src/audio/GameAudio.h b/src/audio/GameAudio.h new file mode 100644 index 000000000..1135576f3 --- /dev/null +++ b/src/audio/GameAudio.h @@ -0,0 +1,12 @@ +#pragma once + +#include +#include + +static struct { + std::thread thread; + std::condition_variable cv_to_thread, cv_from_thread; + std::mutex mutex; + bool running; + bool processing; +} audio; diff --git a/src/audio/heap.h b/src/audio/heap.h index 0113212ba..ae71257c4 100644 --- a/src/audio/heap.h +++ b/src/audio/heap.h @@ -12,8 +12,8 @@ #define SOUND_LOAD_STATUS_4 4 #define SOUND_LOAD_STATUS_5 5 -#define IS_BANK_LOAD_COMPLETE(bankId) (gBankLoadStatus[bankId] >= SOUND_LOAD_STATUS_COMPLETE) -#define IS_SEQ_LOAD_COMPLETE(seqId) (gSeqLoadStatus[seqId] >= SOUND_LOAD_STATUS_COMPLETE) +#define IS_BANK_LOAD_COMPLETE(bankId) GameEngine_IsBankLoaded(bankId) +#define IS_SEQ_LOAD_COMPLETE(seqId) GameEngine_IsSequenceLoaded(seqId) struct SoundAllocPool { u8* start; diff --git a/src/audio/internal.h b/src/audio/internal.h index 1c615c29e..4d18f1d61 100644 --- a/src/audio/internal.h +++ b/src/audio/internal.h @@ -3,6 +3,7 @@ #include #include "common_structs.h" +#include "port/resource/type/AudioSequence.h" #define SEQUENCE_PLAYERS 4 #define SEQUENCE_CHANNELS 48 @@ -169,7 +170,7 @@ struct AudioBank { }; // dynamic size struct CtlEntry { - u8 unused; + u8 bankId; u8 numInstruments; u8 numDrums; struct Instrument** instruments; @@ -556,13 +557,14 @@ struct AudioBufferParametersEU { * The version of that function in MK64 is significantly different * from its SM64 counterpart * Or we just have a poor understanding of this part of the system. +**/ struct EuAudioCmd { union { #if IS_BIG_ENDIAN struct { u8 op; - u8 arg1; + u8 bankId; u8 arg2; u8 arg3; } s; @@ -570,7 +572,7 @@ struct EuAudioCmd { struct { u8 arg3; u8 arg2; - u8 arg1; + u8 bankId; u8 op; } s; #endif @@ -595,25 +597,7 @@ struct EuAudioCmd { #endif } u2; }; -**/ -struct EuAudioCmd { - union { - struct { - u8 op; - u8 bankId; - u8 arg2; - u8 arg3; - } s; - u32 first; - } u; - union { - s32 as_s32; - u32 as_u32; - f32 as_f32; - u8 as_u8; - s8 as_s8; - } u2; -}; +extern void create_next_audio_buffer(s16* samples, u32 num_samples); #endif // AUDIO_INTERNAL_H diff --git a/src/audio/load.c b/src/audio/load.c index 3d8c21d23..0a3a15536 100644 --- a/src/audio/load.c +++ b/src/audio/load.c @@ -9,6 +9,7 @@ #include "audio/synthesis.h" #include "audio/seqplayer.h" #include "audio/port_eu.h" +#include "port/Engine.h" #include "buffers/gfx_output_buffer.h" #include @@ -598,58 +599,19 @@ void* sequence_dma_async(s32 seqId, s32 arg1, struct SequencePlayer* seqPlayer) return ptr; } -u8 get_missing_bank(u32 seqId, s32* nonNullCount, s32* nullCount) { - void* temp; - u32 bankId; - u16 offset; - u8 i; - u8 ret; - - *nullCount = 0; - *nonNullCount = 0; - offset = ((u16*) gAlBankSets)[seqId]; - for (i = gAlBankSets[offset++], ret = 0; i != 0; i--) { - bankId = gAlBankSets[offset++]; - - if (IS_BANK_LOAD_COMPLETE(bankId) == true) { - temp = get_bank_or_seq(1, 2, bankId); - } else { - temp = NULL; - } - - if (temp == NULL) { - (*nullCount)++; - ret = bankId; - } else { - (*nonNullCount)++; - } - } - - return ret; +uint8_t* load_sequence_immediate(s32 seqId, s32 arg1) { + return GameEngine_LoadSequence(seqId)->data; } -struct AudioBank* load_banks_immediate(s32 seqId, u8* outDefaultBank) { - void* ret; +struct CtlEntry* load_banks_immediate(s32 seqId, u8 *outDefaultBank) { u32 bankId; - u16 offset; - u8 i; - - offset = ((u16*) gAlBankSets)[seqId]; - for (i = gAlBankSets[offset++]; i != 0; i--) { - bankId = gAlBankSets[offset++]; - - if (IS_BANK_LOAD_COMPLETE(bankId) == true) { - ret = get_bank_or_seq(1, 2, bankId); - } else { - ret = NULL; - } - - if (ret == NULL) { - ret = bank_load_immediate(bankId, 2); - } + struct AudioSequenceData *seqData = GameEngine_LoadSequence(seqId); + struct CtlEntry *output; + for(size_t i = 0; i < seqData->bankCount; i++) { + output = GameEngine_LoadBank(bankId = seqData->banks[i]); } *outDefaultBank = bankId; - return ret; + return output; } void preload_sequence(u32 seqId, u8 preloadMask) { @@ -660,9 +622,9 @@ void preload_sequence(u32 seqId, u8 preloadMask) { return; } - if (gSeqFileHeader->seqArray[seqId].len == 0) { - seqId = (u32) gSeqFileHeader->seqArray[seqId].offset; - } + // if (gSeqFileHeader->seqArray[seqId].len == 0) { + // seqId = (u32) gSeqFileHeader->seqArray[seqId].offset; + // } gAudioLoadLock = AUDIO_LOCK_LOADING; if (preloadMask & PRELOAD_BANKS) { @@ -671,8 +633,8 @@ void preload_sequence(u32 seqId, u8 preloadMask) { if (preloadMask & PRELOAD_SEQUENCE) { //! @bug should be IS_SEQ_LOAD_COMPLETE - if (IS_BANK_LOAD_COMPLETE(seqId) == true) { - sequenceData = get_bank_or_seq(0, 2, seqId); + if (IS_SEQ_LOAD_COMPLETE(seqId) == true) { + sequenceData = load_sequence_immediate(seqId, 2); } else { sequenceData = NULL; } @@ -696,63 +658,32 @@ void load_sequence(u32 player, u32 seqId, s32 loadAsync) { } void load_sequence_internal(u32 player, u32 seqId, s32 loadAsync) { - void* sequenceData; - struct SequencePlayer* seqPlayer = &gSequencePlayers[player]; - UNUSED u32 padding[2]; + struct SequencePlayer *seqPlayer = &gSequencePlayers[player]; if (seqId >= gSequenceCount) { return; } - if (gSeqFileHeader->seqArray[seqId].len == 0) { - seqId = (u32) gSeqFileHeader->seqArray[seqId].offset; + sequence_player_disable(seqPlayer); + struct CtlEntry* bank = load_banks_immediate(seqId, &seqPlayer->defaultBank[0]); + + if (bank == NULL) { + return; } - sequence_player_disable(seqPlayer); - if (loadAsync) { - s32 numMissingBanks = 0; - s32 dummy = 0; - s32 bankId = get_missing_bank(seqId, &dummy, &numMissingBanks); - if (numMissingBanks == 1) { - if (bank_load_async(bankId, 2, seqPlayer) == NULL) { - return; - } - /** - * @bug This should set the last bank (i.e. the first in the JSON) - * as default, not the missing one. This code path never gets - * taken, though -- all sequence loading is synchronous. - */ - seqPlayer->defaultBank[0] = bankId; - } else { - if (load_banks_immediate(seqId, &seqPlayer->defaultBank[0]) == NULL) { - return; - } - } - } else if (load_banks_immediate(seqId, &seqPlayer->defaultBank[0]) == NULL) { + eu_stubbed_printf_2("Seq %d:Default Load Id is %d\n", seqId, seqPlayer->defaultBank[0]); + eu_stubbed_printf_0("Seq Loading Start\n"); + + uint8_t* sequenceData = load_sequence_immediate(seqId, 2); + if (sequenceData == NULL) { return; } seqPlayer->seqId = seqId; - sequenceData = get_bank_or_seq(0, 2, seqId); - if (sequenceData == NULL) { - if (seqPlayer->seqDmaInProgress) { - return; - } - if (loadAsync) { - sequenceData = sequence_dma_async(seqId, 2, seqPlayer); - } else { - sequenceData = sequence_dma_immediate(seqId, 2); - } - - if (sequenceData == NULL) { - return; - } - } - init_sequence_player(player); seqPlayer->scriptState.depth = 0; seqPlayer->delay = 0; - seqPlayer->enabled = true; + seqPlayer->enabled = 1; seqPlayer->seqData = sequenceData; seqPlayer->scriptState.pc = sequenceData; } @@ -801,21 +732,8 @@ void audio_init(void) { #endif // UTODO: Which is the correct one? - switch (0) { /* irregular */ - case 0: - D_803B7178 = 20.03042f; - gRefreshRate = 0x00000032; - break; - case 2: - D_803B7178 = 16.546f; - gRefreshRate = 0x0000003C; - break; - case 1: - default: - D_803B7178 = 16.713f; - gRefreshRate = 0x0000003C; - break; - } + D_803B7178 = 16.713f; + gRefreshRate = 60; port_eu_init(); for (i = 0; i < NUMAIBUFFERS; i++) { gAiBufferLengths[i] = 0xa0; @@ -845,6 +763,7 @@ void audio_init(void) { gAudioResetPresetIdToLoad = 0; gAudioResetStatus = one; audio_shut_down_and_reset_step(); + gSequenceCount = GameEngine_GetSequenceCount(); #ifdef TARGET_N64 gSeqFileHeader = (ALSeqFile*) sp60; test = &_sequencesSegmentRomStart; diff --git a/src/audio/load.h b/src/audio/load.h index 81855ed30..e818e6806 100644 --- a/src/audio/load.h +++ b/src/audio/load.h @@ -39,8 +39,7 @@ struct AudioBank* bank_load_immediate(s32, s32); struct AudioBank* bank_load_async(s32, s32, struct SequencePlayer*); void* sequence_dma_immediate(s32, s32); void* sequence_dma_async(s32, s32, struct SequencePlayer*); -u8 get_missing_bank(u32 seqId, s32* nonNullCount, s32* nullCount); -struct AudioBank* load_banks_immediate(s32, u8*); +struct CtlEntry* load_banks_immediate(s32, u8*); void preload_sequence(u32, u8); void load_sequence(u32, u32, s32); void load_sequence_internal(u32, u32, s32); diff --git a/src/audio/mixer.c b/src/audio/mixer.c index 8ed6e12d6..26ff77dfa 100644 --- a/src/audio/mixer.c +++ b/src/audio/mixer.c @@ -1,7 +1,13 @@ -#include +#include +#include +#include +#include + #include "mixer.h" -#pragma GCC optimize("unroll-loops") +#ifndef __clang__ +#pragma GCC optimize ("unroll-loops") +#endif #define ROUND_UP_64(v) (((v) + 63) & ~63) #define ROUND_UP_32(v) (((v) + 31) & ~31) @@ -9,78 +15,548 @@ #define ROUND_UP_8(v) (((v) + 7) & ~7) #define ROUND_DOWN_16(v) ((v) & ~0xf) -#ifdef NEW_AUDIO_UCODE -#define BUF_SIZE 2880 -#define BUF_U8(a) (rspa.buf.as_u8 + ((a) - 0x450)) -#define BUF_S16(a) (rspa.buf.as_s16 + ((a) - 0x450) / sizeof(int16_t)) -#else -#define BUF_SIZE 2512 -#define BUF_U8(a) (rspa.buf.as_u8 + (a)) -#define BUF_S16(a) (rspa.buf.as_s16 + (a) / sizeof(int16_t)) -#endif +//#define DMEM_BUF_SIZE (0x1000 - 0x0330 - 0x10 - 0x40) +#define DMEM_BUF_SIZE 0xC80 +#define BUF_U8(a) (rspa.buf.as_u8 + ((a)-0x0330)) +#define BUF_S16(a) (rspa.buf.as_s16 + ((a)-0x0330) / sizeof(int16_t)) static struct { uint16_t in; uint16_t out; uint16_t nbytes; -#ifdef NEW_AUDIO_UCODE uint16_t vol[2]; uint16_t rate[2]; uint16_t vol_wet; uint16_t rate_wet; -#else - int16_t vol[2]; - uint16_t dry_right; - uint16_t wet_left; - uint16_t wet_right; - - int16_t target[2]; - int32_t rate[2]; - - int16_t vol_dry; - int16_t vol_wet; -#endif - - ADPCM_STATE* adpcm_loop_state; + ADPCM_STATE *adpcm_loop_state; int16_t adpcm_table[8][2][8]; -#ifdef NEW_AUDIO_UCODE uint16_t filter_count; int16_t filter[8]; -#endif union { - int16_t as_s16[BUF_SIZE / sizeof(int16_t)]; - uint8_t as_u8[BUF_SIZE]; + int16_t as_s16[DMEM_BUF_SIZE / sizeof(int16_t)]; + uint8_t as_u8[DMEM_BUF_SIZE]; } buf; } rspa; -void aDownsampleHalfImpl(uint16_t n_samples, uint16_t in_addr, uint16_t out_addr) { - int16_t* in = BUF_S16(in_addr); - int16_t* out = BUF_S16(out_addr); - int n = ROUND_UP_8(n_samples); +static int16_t resample_table[64][4] = { + {0x0c39, 0x66ad, 0x0d46, 0xffdf}, {0x0b39, 0x6696, 0x0e5f, 0xffd8}, + {0x0a44, 0x6669, 0x0f83, 0xffd0}, {0x095a, 0x6626, 0x10b4, 0xffc8}, + {0x087d, 0x65cd, 0x11f0, 0xffbf}, {0x07ab, 0x655e, 0x1338, 0xffb6}, + {0x06e4, 0x64d9, 0x148c, 0xffac}, {0x0628, 0x643f, 0x15eb, 0xffa1}, + {0x0577, 0x638f, 0x1756, 0xff96}, {0x04d1, 0x62cb, 0x18cb, 0xff8a}, + {0x0435, 0x61f3, 0x1a4c, 0xff7e}, {0x03a4, 0x6106, 0x1bd7, 0xff71}, + {0x031c, 0x6007, 0x1d6c, 0xff64}, {0x029f, 0x5ef5, 0x1f0b, 0xff56}, + {0x022a, 0x5dd0, 0x20b3, 0xff48}, {0x01be, 0x5c9a, 0x2264, 0xff3a}, + {0x015b, 0x5b53, 0x241e, 0xff2c}, {0x0101, 0x59fc, 0x25e0, 0xff1e}, + {0x00ae, 0x5896, 0x27a9, 0xff10}, {0x0063, 0x5720, 0x297a, 0xff02}, + {0x001f, 0x559d, 0x2b50, 0xfef4}, {0xffe2, 0x540d, 0x2d2c, 0xfee8}, + {0xffac, 0x5270, 0x2f0d, 0xfedb}, {0xff7c, 0x50c7, 0x30f3, 0xfed0}, + {0xff53, 0x4f14, 0x32dc, 0xfec6}, {0xff2e, 0x4d57, 0x34c8, 0xfebd}, + {0xff0f, 0x4b91, 0x36b6, 0xfeb6}, {0xfef5, 0x49c2, 0x38a5, 0xfeb0}, + {0xfedf, 0x47ed, 0x3a95, 0xfeac}, {0xfece, 0x4611, 0x3c85, 0xfeab}, + {0xfec0, 0x4430, 0x3e74, 0xfeac}, {0xfeb6, 0x424a, 0x4060, 0xfeaf}, + {0xfeaf, 0x4060, 0x424a, 0xfeb6}, {0xfeac, 0x3e74, 0x4430, 0xfec0}, + {0xfeab, 0x3c85, 0x4611, 0xfece}, {0xfeac, 0x3a95, 0x47ed, 0xfedf}, + {0xfeb0, 0x38a5, 0x49c2, 0xfef5}, {0xfeb6, 0x36b6, 0x4b91, 0xff0f}, + {0xfebd, 0x34c8, 0x4d57, 0xff2e}, {0xfec6, 0x32dc, 0x4f14, 0xff53}, + {0xfed0, 0x30f3, 0x50c7, 0xff7c}, {0xfedb, 0x2f0d, 0x5270, 0xffac}, + {0xfee8, 0x2d2c, 0x540d, 0xffe2}, {0xfef4, 0x2b50, 0x559d, 0x001f}, + {0xff02, 0x297a, 0x5720, 0x0063}, {0xff10, 0x27a9, 0x5896, 0x00ae}, + {0xff1e, 0x25e0, 0x59fc, 0x0101}, {0xff2c, 0x241e, 0x5b53, 0x015b}, + {0xff3a, 0x2264, 0x5c9a, 0x01be}, {0xff48, 0x20b3, 0x5dd0, 0x022a}, + {0xff56, 0x1f0b, 0x5ef5, 0x029f}, {0xff64, 0x1d6c, 0x6007, 0x031c}, + {0xff71, 0x1bd7, 0x6106, 0x03a4}, {0xff7e, 0x1a4c, 0x61f3, 0x0435}, + {0xff8a, 0x18cb, 0x62cb, 0x04d1}, {0xff96, 0x1756, 0x638f, 0x0577}, + {0xffa1, 0x15eb, 0x643f, 0x0628}, {0xffac, 0x148c, 0x64d9, 0x06e4}, + {0xffb6, 0x1338, 0x655e, 0x07ab}, {0xffbf, 0x11f0, 0x65cd, 0x087d}, + {0xffc8, 0x10b4, 0x6626, 0x095a}, {0xffd0, 0x0f83, 0x6669, 0x0a44}, + {0xffd8, 0x0e5f, 0x6696, 0x0b39}, {0xffdf, 0x0d46, 0x66ad, 0x0c39} +}; + +static inline int16_t clamp16(int32_t v) { + if (v < -0x8000) { + return -0x8000; + } else if (v > 0x7fff) { + return 0x7fff; + } + return (int16_t)v; +} + +static inline int32_t clamp32(int64_t v) { + if (v < -0x7fffffff - 1) { + return -0x7fffffff - 1; + } else if (v > 0x7fffffff) { + return 0x7fffffff; + } + return (int32_t)v; +} + +void aClearBufferImpl(uint16_t addr, int nbytes) { + nbytes = ROUND_UP_16(nbytes); + memset(BUF_U8(addr), 0, nbytes); +} + +void aLoadBufferImpl(const void *source_addr, uint16_t dest_addr, uint16_t nbytes) { +#if __SANITIZE_ADDRESS__ + for (size_t i = 0; i < ROUND_DOWN_16(nbytes); i++) { + BUF_U8(dest_addr)[i] = ((const unsigned char*)source_addr)[i]; + } +#else + memcpy(BUF_U8(dest_addr), source_addr, ROUND_DOWN_16(nbytes)); +#endif +} + +void aSaveBufferImpl(uint16_t source_addr, int16_t *dest_addr, uint16_t nbytes) { + //printf("source_addr: %x\n dest_addr; %x\n nbytes: %d\n", source_addr, dest_addr, nbytes); + //if (nbytes > 704) {nbytes = 704;} + memcpy(dest_addr, BUF_S16(source_addr), ROUND_DOWN_16(nbytes)); +} + +void aLoadADPCMImpl(int num_entries_times_16, const int16_t *book_source_addr) { + memcpy(rspa.adpcm_table, book_source_addr, num_entries_times_16); +} + +void aSetBufferImpl(uint8_t flags, uint16_t in, uint16_t out, uint16_t nbytes) { + rspa.in = in; + rspa.out = out; + rspa.nbytes = nbytes; +} + +void aInterleaveImpl(uint16_t dest, uint16_t left, uint16_t right, uint16_t c) { + if(rspa.nbytes == 0){ + return; + } + + int count = ROUND_UP_16(rspa.nbytes) >> 3; + + int16_t *l = BUF_S16(left); + int16_t *r = BUF_S16(right); + int16_t *d = BUF_S16(rspa.out); + + while (count > 0) { + int16_t l0 = *l++; + int16_t l1 = *l++; + int16_t l2 = *l++; + int16_t l3 = *l++; + int16_t r0 = *r++; + int16_t r1 = *r++; + int16_t r2 = *r++; + int16_t r3 = *r++; + *d++ = l0; + *d++ = r0; + *d++ = l1; + *d++ = r1; + *d++ = l2; + *d++ = r2; + *d++ = l3; + *d++ = r3; + --count; + } +} + +void aDMEMMoveImpl(uint16_t in_addr, uint16_t out_addr, int nbytes) { + nbytes = ROUND_UP_16(nbytes); + memmove(BUF_U8(out_addr), BUF_U8(in_addr), nbytes); +} + +void aSetLoopImpl(ADPCM_STATE *adpcm_loop_state) { + rspa.adpcm_loop_state = adpcm_loop_state; +} + +void aADPCMdecImpl(uint8_t flags, ADPCM_STATE state) { + uint8_t *in = BUF_U8(rspa.in); + int16_t *out = BUF_S16(rspa.out); + int nbytes = ROUND_UP_32(rspa.nbytes); + if (flags & A_INIT) { + memset(out, 0, 16 * sizeof(int16_t)); + } else if (flags & A_LOOP) { + memcpy(out, rspa.adpcm_loop_state, 16 * sizeof(int16_t)); + } else { + memcpy(out, state, 16 * sizeof(int16_t)); + } + out += 16; + + while (nbytes > 0) { + int shift = *in >> 4; // should be in 0..12 or 0..14 + int table_index = *in++ & 0xf; // should be in 0..7 + int16_t (*tbl)[8] = rspa.adpcm_table[table_index]; + int i; + + for (i = 0; i < 2; i++) { + int16_t ins[8]; + int16_t prev1 = out[-1]; + int16_t prev2 = out[-2]; + int j, k; + if (flags & 4) { + for (j = 0; j < 2; j++) { + ins[j * 4] = (((*in >> 6) << 30) >> 30) << shift; + ins[j * 4 + 1] = ((((*in >> 4) & 0x3) << 30) >> 30) << shift; + ins[j * 4 + 2] = ((((*in >> 2) & 0x3) << 30) >> 30) << shift; + ins[j * 4 + 3] = (((*in++ & 0x3) << 30) >> 30) << shift; + } + } else { + for (j = 0; j < 4; j++) { + ins[j * 2] = (((*in >> 4) << 28) >> 28) << shift; + ins[j * 2 + 1] = (((*in++ & 0xf) << 28) >> 28) << shift; + } + } + for (j = 0; j < 8; j++) { + int32_t acc = tbl[0][j] * prev2 + tbl[1][j] * prev1 + (ins[j] << 11); + for (k = 0; k < j; k++) { + acc += tbl[1][((j - k) - 1)] * ins[k]; + } + acc >>= 11; + *out++ = clamp16(acc); + } + } + nbytes -= 16 * sizeof(int16_t); + } + memcpy(state, out - 16, 16 * sizeof(int16_t)); +} + +void aResampleImpl(uint8_t flags, uint16_t pitch, RESAMPLE_STATE state) { + int16_t tmp[16]; + int16_t *in_initial = BUF_S16(rspa.in); + int16_t *in = in_initial; + int16_t *out = BUF_S16(rspa.out); + int nbytes = ROUND_UP_16(rspa.nbytes); + uint32_t pitch_accumulator; + int i; + int16_t *tbl; + int32_t sample; + + if (flags & A_INIT) { + memset(tmp, 0, 5 * sizeof(int16_t)); + } else { + memcpy(tmp, state, 16 * sizeof(int16_t)); + } + if (flags & 2) { + memcpy(in - 8, tmp + 8, 8 * sizeof(int16_t)); + in -= tmp[5] / sizeof(int16_t); + } + in -= 4; + pitch_accumulator = (uint16_t)tmp[4]; + memcpy(in, tmp, 4 * sizeof(int16_t)); do { - *out++ = *in++; - in++; - *out++ = *in++; - in++; - *out++ = *in++; - in++; - *out++ = *in++; - in++; - *out++ = *in++; - in++; - *out++ = *in++; - in++; - *out++ = *in++; - in++; - *out++ = *in++; - in++; + for (i = 0; i < 8; i++) { + tbl = resample_table[pitch_accumulator * 64 >> 16]; + sample = ((in[0] * tbl[0] + 0x4000) >> 15) + + ((in[1] * tbl[1] + 0x4000) >> 15) + + ((in[2] * tbl[2] + 0x4000) >> 15) + + ((in[3] * tbl[3] + 0x4000) >> 15); + *out++ = clamp16(sample); + + pitch_accumulator += (pitch << 1); + in += pitch_accumulator >> 16; + pitch_accumulator %= 0x10000; + } + nbytes -= 8 * sizeof(int16_t); + } while (nbytes > 0); + + state[4] = (int16_t)pitch_accumulator; + memcpy(state, in, 4 * sizeof(int16_t)); + i = (in - in_initial + 4) & 7; + in -= i; + if (i != 0) { + i = -8 - i; + } + state[5] = i; + memcpy(state + 8, in, 8 * sizeof(int16_t)); +} + +void aEnvSetup1Impl(uint8_t initial_vol_wet, uint16_t rate_wet, uint16_t rate_left, uint16_t rate_right) { + rspa.vol_wet = (uint16_t)(initial_vol_wet << 8); + rspa.rate_wet = rate_wet; + rspa.rate[0] = rate_left; + rspa.rate[1] = 0; // MK_Patch +} + +void aEnvSetup2Impl(uint16_t initial_vol_left, uint16_t initial_vol_right) { + rspa.vol[0] = initial_vol_left; + rspa.vol[1] = initial_vol_right; +} + +void aEnvMixerImpl(uint16_t in_addr, uint16_t n_samples, bool swap_reverb, + bool neg_3, bool neg_2, + bool neg_left, bool neg_right, + int32_t wet_dry_addr, uint32_t unk) +{ + int16_t *in = BUF_S16(in_addr); + int16_t *dry[2] = {BUF_S16(((wet_dry_addr >> 24) & 0xFF) << 4), BUF_S16(((wet_dry_addr >> 16) & 0xFF) << 4)}; + int16_t *wet[2] = {BUF_S16(((wet_dry_addr >> 8) & 0xFF) << 4), BUF_S16(((wet_dry_addr) & 0xFF) << 4)}; + int16_t negs[4] = {neg_left ? -1 : 0, neg_right ? -1 : 0, neg_3 ? -4 : 0, neg_2 ? -2 : 0}; + int swapped[2] = {swap_reverb ? 1 : 0, swap_reverb ? 0 : 1}; + int n = ROUND_UP_16(n_samples); + + uint16_t vols[2] = {rspa.vol[0], rspa.vol[1]}; + uint16_t rates[2] = {rspa.rate[0], rspa.rate[1]}; + uint16_t vol_wet = rspa.vol_wet; + uint16_t rate_wet = rspa.rate_wet; + + do { + for (int i = 0; i < 8; i++) { + int16_t samples[2] = {*in, *in}; in++; + for (int j = 0; j < 2; j++) { + samples[j] = (samples[j] * vols[j] >> 16) ^ negs[j]; + } + for (int j = 0; j < 2; j++) { + *dry[j] = clamp16(*dry[j] + samples[j]); dry[j]++; + *wet[j] = clamp16(*wet[j] + ((samples[swapped[j]] * vol_wet >> 16) ^ negs[2 + j])); wet[j]++; + } + } + vols[0] += rates[0]; + vols[1] += rates[1]; + vol_wet += rate_wet; n -= 8; } while (n > 0); } + +void aMixImpl(uint16_t count, int16_t gain, uint16_t in_addr, uint16_t out_addr) { + int nbytes = ROUND_UP_32(ROUND_DOWN_16(count << 4)); + int16_t *in = BUF_S16(in_addr); + int16_t *out = BUF_S16(out_addr); + int i; + int32_t sample; + + if (gain == -0x8000) { + while (nbytes > 0) { + for (i = 0; i < 16; i++) { + sample = *out - *in++; + *out++ = clamp16(sample); + } + nbytes -= 16 * sizeof(int16_t); + } + } + + while (nbytes > 0) { + for (i = 0; i < 16; i++) { + sample = ((*out * 0x7fff + *in++ * gain) + 0x4000) >> 15; + *out++ = clamp16(sample); + } + + nbytes -= 16 * sizeof(int16_t); + } +} + +void aS8DecImpl(uint8_t flags, ADPCM_STATE state) { + uint8_t *in = BUF_U8(rspa.in); + int16_t *out = BUF_S16(rspa.out); + int nbytes = ROUND_UP_32(rspa.nbytes); + if (flags & A_INIT) { + memset(out, 0, 16 * sizeof(int16_t)); + } else if (flags & A_LOOP) { + memcpy(out, rspa.adpcm_loop_state, 16 * sizeof(int16_t)); + } else { + memcpy(out, state, 16 * sizeof(int16_t)); + } + out += 16; + + while (nbytes > 0) { + *out++ = (int16_t)(*in++ << 8); + *out++ = (int16_t)(*in++ << 8); + *out++ = (int16_t)(*in++ << 8); + *out++ = (int16_t)(*in++ << 8); + *out++ = (int16_t)(*in++ << 8); + *out++ = (int16_t)(*in++ << 8); + *out++ = (int16_t)(*in++ << 8); + *out++ = (int16_t)(*in++ << 8); + *out++ = (int16_t)(*in++ << 8); + *out++ = (int16_t)(*in++ << 8); + *out++ = (int16_t)(*in++ << 8); + *out++ = (int16_t)(*in++ << 8); + *out++ = (int16_t)(*in++ << 8); + *out++ = (int16_t)(*in++ << 8); + *out++ = (int16_t)(*in++ << 8); + *out++ = (int16_t)(*in++ << 8); + + nbytes -= 16 * sizeof(int16_t); + } + + memcpy(state, out - 16, 16 * sizeof(int16_t)); +} + +void aAddMixerImpl(uint16_t count, uint16_t in_addr, uint16_t out_addr) { + int16_t *in = BUF_S16(in_addr); + int16_t *out = BUF_S16(out_addr); + int nbytes = ROUND_UP_64(ROUND_DOWN_16(count)); + + do { + *out = clamp16(*out + *in++); out++; + *out = clamp16(*out + *in++); out++; + *out = clamp16(*out + *in++); out++; + *out = clamp16(*out + *in++); out++; + *out = clamp16(*out + *in++); out++; + *out = clamp16(*out + *in++); out++; + *out = clamp16(*out + *in++); out++; + *out = clamp16(*out + *in++); out++; + *out = clamp16(*out + *in++); out++; + *out = clamp16(*out + *in++); out++; + *out = clamp16(*out + *in++); out++; + *out = clamp16(*out + *in++); out++; + *out = clamp16(*out + *in++); out++; + *out = clamp16(*out + *in++); out++; + *out = clamp16(*out + *in++); out++; + *out = clamp16(*out + *in++); out++; + + nbytes -= 16 * sizeof(int16_t); + } while (nbytes > 0); +} + +void aDuplicateImpl(uint16_t count, uint16_t in_addr, uint16_t out_addr) { + uint8_t* in = BUF_U8(in_addr); + uint8_t *out = BUF_U8(out_addr); + + uint8_t tmp[128]; + memcpy(tmp, in, 128); + do { + memcpy(out, tmp, 128); + out += 128; + } while (count-- > 0); +} + +void aResampleZohImpl(uint16_t pitch, uint16_t start_fract) { + int16_t *in = BUF_S16(rspa.in); + int16_t *out = BUF_S16(rspa.out); + int nbytes = ROUND_UP_8(rspa.nbytes); + uint32_t pos = start_fract; + uint32_t pitch_add = pitch << 2; + + do { + *out++ = in[pos >> 17]; pos += pitch_add; + *out++ = in[pos >> 17]; pos += pitch_add; + *out++ = in[pos >> 17]; pos += pitch_add; + *out++ = in[pos >> 17]; pos += pitch_add; + + nbytes -= 4 * sizeof(int16_t); + } while (nbytes > 0); +} + +void aDownsampleHalfImpl(uint16_t n_samples, uint16_t in_addr, uint16_t out_addr) { + int16_t *in = BUF_S16(in_addr); + int16_t *out = BUF_S16(out_addr); + int n = ROUND_UP_8(n_samples); + + do { + *out++ = *in++; in++; + *out++ = *in++; in++; + *out++ = *in++; in++; + *out++ = *in++; in++; + *out++ = *in++; in++; + *out++ = *in++; in++; + *out++ = *in++; in++; + *out++ = *in++; in++; + + n -= 8; + } while (n > 0); +} + +void aInterlImpl(uint16_t in_addr, uint16_t out_addr, uint16_t n_samples) { + int16_t *in = BUF_S16(in_addr); + int16_t *out = BUF_S16(out_addr); + int n = ROUND_UP_8(n_samples); + + do { + *out++ = *in++; in++; + *out++ = *in++; in++; + *out++ = *in++; in++; + *out++ = *in++; in++; + *out++ = *in++; in++; + *out++ = *in++; in++; + *out++ = *in++; in++; + *out++ = *in++; in++; + + n -= 8; + } while (n > 0); +} + +void aFilterImpl(uint8_t flags, uint16_t count_or_buf, int16_t *state_or_filter) { + if (flags > A_INIT) { + rspa.filter_count = ROUND_UP_16(count_or_buf); + memcpy(rspa.filter, state_or_filter, sizeof(rspa.filter)); + } else { + int16_t tmp[16], tmp2[8]; + int count = rspa.filter_count; + int16_t *buf = BUF_S16(count_or_buf); + + if (flags == A_INIT) { +#ifndef __clang__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmemset-elt-size" +#endif + memset(tmp, 0, 8 * sizeof(int16_t)); +#ifndef __clang__ +#pragma GCC diagnostic pop +#endif + memset(tmp2, 0, 8 * sizeof(int16_t)); + } else { + memcpy(tmp, state_or_filter, 8 * sizeof(int16_t)); + memcpy(tmp2, state_or_filter + 8, 8 * sizeof(int16_t)); + } + + for (int i = 0; i < 8; i++) { + rspa.filter[i] = (tmp2[i] + rspa.filter[i]) / 2; + } + + do { + memcpy(tmp + 8, buf, 8 * sizeof(int16_t)); + for (int i = 0; i < 8; i++) { + int64_t sample = 0x4000; // round term + for (int j = 0; j < 8; j++) { + sample += tmp[i + j] * rspa.filter[7 - j]; + } + buf[i] = clamp16((int32_t)(sample >> 15)); + } + memcpy(tmp, tmp + 8, 8 * sizeof(int16_t)); + + buf += 8; + count -= 8 * sizeof(int16_t); + } while (count > 0); + + memcpy(state_or_filter, tmp, 8 * sizeof(int16_t)); + memcpy(state_or_filter + 8, rspa.filter, 8 * sizeof(int16_t)); + } +} + +void aHiLoGainImpl(uint8_t g, uint16_t count, uint16_t addr) { + int16_t *samples = BUF_S16(addr); + int nbytes = ROUND_UP_32(count); + + do { + *samples = clamp16((*samples * g) >> 4); samples++; + *samples = clamp16((*samples * g) >> 4); samples++; + *samples = clamp16((*samples * g) >> 4); samples++; + *samples = clamp16((*samples * g) >> 4); samples++; + *samples = clamp16((*samples * g) >> 4); samples++; + *samples = clamp16((*samples * g) >> 4); samples++; + *samples = clamp16((*samples * g) >> 4); samples++; + *samples = clamp16((*samples * g) >> 4); samples++; + + nbytes -= 8; + } while (nbytes > 0); +} + +void aUnkCmd3Impl(uint16_t a, uint16_t b, uint16_t c) { +} + +void aUnkCmd19Impl(uint8_t f, uint16_t count, uint16_t out_addr, uint16_t in_addr) { + int nbytes = ROUND_UP_64(count); + int16_t *in = BUF_S16(in_addr + f); + int16_t *out = BUF_S16(out_addr); + int16_t tbl[32]; + + memcpy(tbl, in, 32 * sizeof(int16_t)); + do { + for (int i = 0; i < 32; i++) { + out[i] = clamp16(out[i] * tbl[i]); + } + out += 32; + nbytes -= 32 * sizeof(int16_t); + } while (nbytes > 0); +} \ No newline at end of file diff --git a/src/audio/mixer.h b/src/audio/mixer.h index f19009aa1..ee64f9156 100644 --- a/src/audio/mixer.h +++ b/src/audio/mixer.h @@ -1,11 +1,91 @@ -#ifndef MIXER_H -#define MIXER_H +#pragma once -#include - -void aDownsampleHalfImpl(uint16_t n_samples, uint16_t in_addr, uint16_t out_addr); +#include +#include +#include "libultraship/libultra/abi.h" +#undef aSegment +#undef aClearBuffer +#undef aSetBuffer +#undef aLoadBuffer +#undef aSaveBuffer +#undef aDMEMMove +#undef aMix +#undef aEnvMixer +#undef aResample +#undef aInterleave +#undef aSetVolume +#undef aSetVolume32 +#undef aSetLoop +#undef aLoadADPCM +#undef aADPCMdec +#undef aS8Dec +#undef aAddMixer +#undef aDuplicate +#undef aDMEMMove2 +#undef aResampleZoh #undef aDownsampleHalf -#define aDownsampleHalf(pkt, nSamples, i, o) aDownsampleHalfImpl(nSamples, i, o) +#undef aEnvSetup1 +#undef aEnvSetup2 +#undef aFilter +#undef aHiLoGain +#undef aInterl +#undef aUnkCmd3 +#undef aUnkCmd19 -#endif +void aClearBufferImpl(uint16_t addr, int nbytes); +void aLoadBufferImpl(const void* source_addr, uint16_t dest_addr, uint16_t nbytes); +void aSaveBufferImpl(uint16_t source_addr, int16_t* dest_addr, uint16_t nbytes); +void aLoadADPCMImpl(int num_entries_times_16, const int16_t* book_source_addr); +void aSetBufferImpl(uint8_t flags, uint16_t in, uint16_t out, uint16_t nbytes); +void aInterleaveImpl(uint16_t dest, uint16_t left, uint16_t right, uint16_t c); +void aDMEMMoveImpl(uint16_t in_addr, uint16_t out_addr, int nbytes); +void aSetLoopImpl(ADPCM_STATE* adpcm_loop_state); +void aADPCMdecImpl(uint8_t flags, ADPCM_STATE state); +void aResampleImpl(uint8_t flags, uint16_t pitch, RESAMPLE_STATE state); +void aEnvSetup1Impl(uint8_t initial_vol_wet, uint16_t rate_wet, uint16_t rate_left, uint16_t rate_right); +void aEnvSetup2Impl(uint16_t initial_vol_left, uint16_t initial_vol_right); +void aEnvMixerImpl(uint16_t in_addr, uint16_t n_samples, bool swap_reverb, bool neg_3, bool neg_2, bool neg_left, + bool neg_right, int32_t wet_dry_addr, u32 unk); +void aMixImpl(uint16_t count, int16_t gain, uint16_t in_addr, uint16_t out_addr); +void aS8DecImpl(uint8_t flags, ADPCM_STATE state); +void aAddMixerImpl(uint16_t count, uint16_t in_addr, uint16_t out_addr); +void aDuplicateImpl(uint16_t count, uint16_t in_addr, uint16_t out_addr); +void aDownsampleHalfImpl(uint16_t n_samples, uint16_t in_addr, uint16_t out_addr); +void aResampleZohImpl(uint16_t pitch, uint16_t start_fract); +void aInterlImpl(uint16_t in_addr, uint16_t out_addr, uint16_t n_samples); +void aFilterImpl(uint8_t flags, uint16_t count_or_buf, int16_t* state_or_filter); +void aHiLoGainImpl(uint8_t g, uint16_t count, uint16_t addr); +void aUnkCmd3Impl(uint16_t a, uint16_t b, uint16_t c); +void aUnkCmd19Impl(uint8_t f, uint16_t count, uint16_t out_addr, uint16_t in_addr); + +#define aSegment(pkt, s, b) \ + do { \ + } while (0) +#define aClearBuffer(pkt, d, c) aClearBufferImpl(d, c) +#define aLoadBuffer(pkt, s, d, c) aLoadBufferImpl(s, d, c) +#define aSaveBuffer(pkt, s, d, c) aSaveBufferImpl(s, d, c) +#define aLoadADPCM(pkt, c, d) aLoadADPCMImpl(c, d) +#define aSetBuffer(pkt, f, i, o, c) aSetBufferImpl(f, i, o, c) +#define aInterleave(pkt, o, l, r, c) aInterleaveImpl(o, l, r, c) +#define aDMEMMove(pkt, i, o, c) aDMEMMoveImpl(i, o, c) +#define aSetLoop(pkt, a) aSetLoopImpl(a) +#define aADPCMdec(pkt, f, s) aADPCMdecImpl(f, s) +#define aResample(pkt, f, p, s) aResampleImpl(f, p, s) +#define aEnvSetup1(pkt, initialVolReverb, rampReverb, rampLeft, rampRight) \ + aEnvSetup1Impl(initialVolReverb, rampReverb, rampLeft, rampRight) +#define aEnvSetup2(pkt, initialVolLeft, initialVolRight) aEnvSetup2Impl(initialVolLeft, initialVolRight) +#define aEnvMixer(pkt, inBuf, nSamples, swapReverb, negLeft, negRight, dryLeft, dryRight, wetLeft, wetRight) \ + aEnvMixerImpl(inBuf, nSamples, swapReverb, negLeft, negRight, dryLeft, dryRight, wetLeft, wetRight) +#define aMix(pkt, c, g, i, o) aMixImpl(c, g, i, o) +#define aS8Dec(pkt, f, s) aS8DecImpl(f, s) +#define aAddMixer(pkt, s, d, c) aAddMixerImpl(s, d, c) +#define aDuplicate(pkt, s, d, c) aDuplicateImpl(s, d, c) +#define aDMEMMove2(pkt, t, i, o, c) aDMEMMove2Impl(t, i, o, c) +#define aResampleZoh(pkt, pitch, startFract) aResampleZohImpl(pitch, startFract) +#define aInterl(pkt, dmemi, dmemo, count) aInterlImpl(dmemi, dmemo, count) +#define aFilter(pkt, f, countOrBuf, addr) aFilterImpl(f, countOrBuf, addr) +#define aDownsampleHalf(pkt, nSamples, i, o) aDownsampleHalfImpl(nSamples, i, o) +#define aHiLoGain(pkt, g, buflen, i, a4) aHiLoGainImpl(g, buflen, i) +#define aUnkCmd3(pkt, a1, a2, a3) aUnkCmd3Impl(a1, a2, a3) +#define aUnkCmd19(pkt, a1, a2, a3, a4) aUnkCmd19Impl(a1, a2, a3, a4) \ No newline at end of file diff --git a/src/audio/playback.c b/src/audio/playback.c index 95c1214f7..671a38260 100644 --- a/src/audio/playback.c +++ b/src/audio/playback.c @@ -9,6 +9,7 @@ #include "audio/effects.h" #include "audio/data.h" #include "audio/seqplayer.h" +#include "port/Engine.h" void note_set_vel_pan_reverb(struct Note* note, f32 velocity, u8 pan, u8 reverbVol) { struct NoteSubEu* sub = ¬e->noteSubEu; @@ -136,13 +137,15 @@ struct Instrument* get_instrument_inner(s32 bankId, s32 instId) { return NULL; } - if (instId >= gCtlEntries[bankId].numInstruments) { + struct CtlEntry* bank = GameEngine_LoadBank(bankId); + + if (instId >= bank->numInstruments) { stubbed_printf("Audio: voiceman: progNo. overflow %d,%d\n", instId, gCtlEntries[bankId].numInstruments); gAudioErrorFlags = ((bankId << 8) + instId) + 0x3000000; return NULL; } - inst = gCtlEntries[bankId].instruments[instId]; + inst = bank->instruments[instId]; if (inst == NULL) { stubbed_printf("Audio: voiceman: progNo. undefined %d,%d\n", bankId, instId); gAudioErrorFlags = ((bankId << 8) + instId) + 0x1000000; @@ -160,18 +163,15 @@ struct Drum* get_drum(s32 bankId, s32 drumId) { return NULL; } - if (drumId >= gCtlEntries[bankId].numDrums) { + struct CtlEntry* bank = GameEngine_LoadBank(bankId); + + if (drumId >= bank->numDrums) { stubbed_printf("Audio: voiceman: Percussion Overflow %d,%d\n", drumId, gCtlEntries[bankId].numDrums); gAudioErrorFlags = ((bankId << 8) + drumId) + 0x4000000; return NULL; } - if ((uintptr_t) gCtlEntries[bankId].drums < 0x80000000U) { - stubbed_printf("Audio: voiceman: Percussion table pointer (bank %d) is irregular.\n"); - return NULL; - } - - drum = gCtlEntries[bankId].drums[drumId]; + drum = bank->drums[drumId]; if (drum == NULL) { stubbed_printf("Audio: voiceman: Percpointer NULL %d,%d\n", bankId, drumId); gAudioErrorFlags = ((bankId << 8) + drumId) + 0x5000000; diff --git a/src/audio/port_eu.c b/src/audio/port_eu.c index 199e3facf..c40fc49d2 100644 --- a/src/audio/port_eu.c +++ b/src/audio/port_eu.c @@ -46,6 +46,40 @@ s32 D_800EA4A4 = 0; char port_eu_unused_string7[] = "Undefined Port Command %d\n"; +void create_next_audio_buffer(s16* samples, u32 num_samples) { + static s32 gMaxAbiCmdCnt = 128; + s32 abiCmdCount; + OSMesg specId; + OSMesg msg; + + gAudioFrameCount++; + gCurrAiBufferIndex %= 3; + + gCurrAudioFrameDmaCount = 0; + + if (osRecvMesg(D_800EA3B0, &specId, 0) != -1) { + gAudioResetPresetIdToLoad = specId.data8; + gAudioResetStatus = 5; + } + + if (gAudioResetStatus != 0) { + if (audio_shut_down_and_reset_step() == 0) { + if (gAudioResetStatus == 0) { + osSendMesg(D_800EA3B4, OS_MESG_8(gAudioResetPresetIdToLoad), OS_MESG_NOBLOCK); + } + return; + } + } + + if (osRecvMesg(D_800EA3AC, &msg, 0) != -1) { + func_800CBCB0(msg.data32); + } + + gAudioCmd = gAudioCmdBuffers[gAudioTaskIndex]; + gAudioCmd = synthesis_execute((Acmd*) gAudioCmd, &abiCmdCount, samples, num_samples); + gAudioRandom = osGetCount() * (gAudioRandom + gAudioFrameCount); +} + struct SPTask* create_next_audio_frame_task(void) { u32 samplesRemainingInAI; s32 writtenCmds; diff --git a/src/audio/seqplayer.c b/src/audio/seqplayer.c index 91919dbec..d5b5ed632 100644 --- a/src/audio/seqplayer.c +++ b/src/audio/seqplayer.c @@ -9,6 +9,7 @@ #include "audio/effects.h" #include "audio/playback.h" #include "audio/external.h" +#include "port/Engine.h" /** * Given that (almost) all of these are format strings, it is highly likely @@ -248,11 +249,11 @@ void sequence_player_disable(struct SequencePlayer* seqPlayer) { seqPlayer->enabled = false; if (IS_SEQ_LOAD_COMPLETE(seqPlayer->seqId) && gSeqLoadStatus[seqPlayer->seqId] != 5) { - gSeqLoadStatus[seqPlayer->seqId] = SOUND_LOAD_STATUS_DISCARDABLE; + GameEngine_UnloadSequence(seqPlayer->seqId); } if (IS_BANK_LOAD_COMPLETE(seqPlayer->defaultBank[0]) && gBankLoadStatus[seqPlayer->defaultBank[0]] != 5) { - gBankLoadStatus[seqPlayer->defaultBank[0]] = 4; + GameEngine_UnloadBank(seqPlayer->defaultBank[0]); } // (Note that if this is called from alloc_bank_or_seq, the side will get swapped @@ -732,11 +733,14 @@ void seq_channel_layer_process_script(struct SequenceChannelLayer* layer) { if (seqChannel) {} } -u8 get_instrument(struct SequenceChannel* seqChannel, u8 instId, struct Instrument** instOut, - struct AdsrSettings* adsr) { - struct Instrument* inst; - inst = get_instrument_inner(seqChannel->bankId, instId); - if (inst == NULL) { +u8 get_instrument(struct SequenceChannel *seqChannel, u8 instId, struct Instrument **instOut, struct AdsrSettings *adsr) { + struct CtlEntry *bank = GameEngine_LoadBank(seqChannel->bankId); + if(instId >= bank->numInstruments) { + *instOut = NULL; + return 0; + } + struct Instrument* inst = bank->instruments[instId]; + if(inst == NULL) { *instOut = NULL; return 0; } @@ -1005,10 +1009,9 @@ void sequence_channel_process_script(struct SequenceChannel* seqChannel) { case 0xC6: cmd = m64_read_u8(state); - sp5A = ((u16*) gAlBankSets)[seqPlayer->seqId]; - loBits = *(sp5A + gAlBankSets); - cmd = gAlBankSets[(sp5A + loBits) - cmd]; - if (get_bank_or_seq(1, 2, cmd) != NULL) { + struct AudioSequenceData *sequence = GameEngine_LoadSequence(seqPlayer->seqId); + cmd = sequence->banks[cmd]; + if(IS_BANK_LOAD_COMPLETE(cmd)) { seqChannel->bankId = cmd; } break; @@ -1210,6 +1213,9 @@ void sequence_player_process_sequence(struct SequencePlayer* seqPlayer) { if (seqPlayer->enabled == false) { return; } + + GameEngine_LoadSequence(seqPlayer->seqId); + GameEngine_LoadBank(seqPlayer->defaultBank[0]); if (seqPlayer->bankDmaInProgress == true) { if (osRecvMesg(&seqPlayer->bankDmaMesgQueue, NULL, 0) == -1) { diff --git a/src/audio/synthesis.c b/src/audio/synthesis.c index 0c7c653b1..cbe5e44e9 100644 --- a/src/audio/synthesis.c +++ b/src/audio/synthesis.c @@ -7,7 +7,7 @@ #include "audio/load.h" #include "audio/seqplayer.h" #include "audio/internal.h" -// #include "audio/external.h" +#include "port/Engine.h" #include #define aSetLoadBufferPair(pkt, c, off) \ @@ -161,8 +161,7 @@ Acmd* synthesis_execute(Acmd* acmd, s32* writtenCmds, s16* aiBuf, s32 bufLen) { process_sequences(i - 1); synthesis_load_note_subs_eu(gAudioBufferParameters.updatesPerFrame - i); } - // UTODO: Stubbed - // aSegment(cmd++, 0, 0); + aSegment(cmd++, 0, 0); aiBufPtr = (u32*) aiBuf; for (i = gAudioBufferParameters.updatesPerFrame; i > 0; i--) { if (i == 1) { @@ -294,7 +293,7 @@ Acmd* synthesis_do_one_audio_update(s16* aiBuf, s32 bufLen, Acmd* acmd, s32 upda aClearBuffer(acmd++, DMEM_ADDR_LEFT_CH, DEFAULT_LEN_2CH); i = 0; for (j = 0; j < gNumSynthesisReverbs; j++) { - gUseReverb = gSynthesisReverbs[j].useReverb; + gUseReverb = 0; //gSynthesisReverbs[j].useReverb; if (gUseReverb != 0) { acmd = synthesis_resample_and_mix_reverb(acmd, bufLen, j, updateIndex); } @@ -325,7 +324,7 @@ Acmd* synthesis_do_one_audio_update(s16* aiBuf, s32 bufLen, Acmd* acmd, s32 upda temp = bufLen * 2; aSetBuffer(acmd++, 0, 0, DMEM_ADDR_TEMP, temp); // UTODO: Stubbed - // aInterleave(acmd++, DMEM_ADDR_LEFT_CH, DMEM_ADDR_RIGHT_CH); + aInterleave(acmd++, 0, DMEM_ADDR_LEFT_CH, DMEM_ADDR_RIGHT_CH, 0); aSaveBuffer(acmd++, DMEM_ADDR_TEMP, VIRTUAL_TO_PHYSICAL2(aiBuf), temp * 2); return acmd; } @@ -613,16 +612,17 @@ Acmd* load_wave_samples(Acmd* acmd, struct NoteSubEu* noteSubEu, struct NoteSynt s32 nSamplesToLoad) { s32 a3; s32 repeats; - // UTODO: Stubbed - // aLoadBuffer(acmd++, VIRTUAL_TO_PHYSICAL2(noteSubEu->sound.samples), 0x1A0, 128); + aLoadBuffer(acmd++, VIRTUAL_TO_PHYSICAL2(noteSubEu->sound.samples), 0x1A0, 128); synthesisState->samplePosInt &= 0x3f; a3 = 64 - synthesisState->samplePosInt; if (a3 < nSamplesToLoad) { repeats = (nSamplesToLoad - a3 + 63) / 64; if (repeats != 0) { - // UTODO: Stubbed - // aDMEMMove2(acmd++, repeats, 0x1A0, 0x1A0 + 128, 128); + aDuplicate(cmd++, + /*dmemin*/ DMEM_ADDR_UNCOMPRESSED_NOTE, + /*dmemout*/ DMEM_ADDR_UNCOMPRESSED_NOTE + 128, + /*copies*/ repeats); } } return acmd; diff --git a/src/audio/synthesis.h b/src/audio/synthesis.h index e35627bb9..1cea88567 100644 --- a/src/audio/synthesis.h +++ b/src/audio/synthesis.h @@ -7,18 +7,16 @@ #define DEFAULT_LEN_1CH 0x180 #define DEFAULT_LEN_2CH 0x300 -#define DMEM_ADDR_TEMP 0x0 -#define DMEM_ADDR_RESAMPLED 0x20 -#define DMEM_ADDR_RESAMPLED2 0x1A0 -#define DMEM_ADDR_UNCOMPRESSED_NOTE 0x180 -#define DMEM_ADDR_NOTE_PAN_TEMP 0x200 -#define DMEM_ADDR_STEREO_STRONG_TEMP_DRY 0x200 -#define DMEM_ADDR_STEREO_STRONG_TEMP_WET 0x340 -#define DMEM_ADDR_COMPRESSED_ADPCM_DATA 0x3f0 -#define DMEM_ADDR_LEFT_CH 0x540 -#define DMEM_ADDR_RIGHT_CH 0x6C0 -#define DMEM_ADDR_WET_LEFT_CH 0x840 -#define DMEM_ADDR_WET_RIGHT_CH 0x9C0 +#define DMEM_ADDR_TEMP 0x450 +#define DMEM_ADDR_RESAMPLED 0x470 +#define DMEM_ADDR_RESAMPLED2 0x5f0 +#define DMEM_ADDR_UNCOMPRESSED_NOTE 0x5f0 +#define DMEM_ADDR_NOTE_PAN_TEMP 0x650 +#define DMEM_ADDR_COMPRESSED_ADPCM_DATA 0x990 +#define DMEM_ADDR_LEFT_CH 0x990 +#define DMEM_ADDR_RIGHT_CH 0xb10 +#define DMEM_ADDR_WET_LEFT_CH 0xc90 +#define DMEM_ADDR_WET_RIGHT_CH 0xe10 /* Its not clear what values these macros should have. Neither version seem to diff --git a/src/main.c b/src/main.c index cdbc4115d..5b3a02a79 100644 --- a/src/main.c +++ b/src/main.c @@ -1239,7 +1239,7 @@ void thread5_game_loop(void) { } void thread5_iteration(void) { - // func_800CB2C4(); + func_800CB2C4(); calculate_delta_time(); #ifdef TARGET_N64 while (true) { diff --git a/src/port/Engine.cpp b/src/port/Engine.cpp index 66b8cd2c3..ed85998c4 100644 --- a/src/port/Engine.cpp +++ b/src/port/Engine.cpp @@ -5,6 +5,9 @@ #include "libultraship/src/Context.h" #include "resource/type/ResourceType.h" #include "resource/importers/GenericArrayFactory.h" +#include "resource/importers/AudioBankFactory.h" +#include "resource/importers/AudioSampleFactory.h" +#include "resource/importers/AudioSequenceFactory.h" #include "resource/importers/Vec3fFactory.h" #include "resource/importers/Vec3sFactory.h" #include "resource/importers/KartAIFactory.h" @@ -31,6 +34,8 @@ float gInterpolationStep = 0.0f; #include #include #include +#include "audio/internal.h" +#include "audio/GameAudio.h" } GameEngine* GameEngine::Instance; @@ -57,7 +62,7 @@ GameEngine::GameEngine() { } } - this->context = Ship::Context::CreateInstance("Spaghettify", "skart64", "spaghettify.cfg.json", OTRFiles, {}, 3); + this->context = Ship::Context::CreateInstance("Spaghettify", "skart64", "spaghettify.cfg.json", OTRFiles, {}, 3, {32000, 1024, 2480}); auto wnd = std::dynamic_pointer_cast(Ship::Context::GetInstance()->GetWindow()); @@ -65,13 +70,18 @@ GameEngine::GameEngine() { this->context->InitGfxDebugger(); auto loader = context->GetResourceManager()->GetResourceLoader(); + loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, + "AudioBank", static_cast(SF64::ResourceType::Bank), 0); + loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, + "AudioSample", static_cast(SF64::ResourceType::Sample), 0); + loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, + "AudioSequence", static_cast(SF64::ResourceType::Sequence), 0); loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "Vec3f", static_cast(SF64::ResourceType::Vec3f), 0); loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "Vec3s", static_cast(SF64::ResourceType::Vec3s), 0); - loader->RegisterResourceFactory(std::make_shared(), - RESOURCE_FORMAT_BINARY, "GenericArray", - static_cast(SF64::ResourceType::GenericArray), 0); + loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, + "GenericArray", static_cast(SF64::ResourceType::GenericArray), 0); loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "Texture", static_cast(LUS::ResourceType::Texture), 0); loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, @@ -92,29 +102,27 @@ GameEngine::GameEngine() { "KartAI", static_cast(MK64::ResourceType::KartAI), 0); loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "CourseVtx", static_cast(MK64::ResourceType::CourseVertex), 0); - loader->RegisterResourceFactory(std::make_shared(), - RESOURCE_FORMAT_BINARY, "TrackSections", - static_cast(MK64::ResourceType::TrackSection), 0); - loader->RegisterResourceFactory(std::make_shared(), - RESOURCE_FORMAT_BINARY, "Waypoints", - static_cast(MK64::ResourceType::Waypoints), 0); - loader->RegisterResourceFactory(std::make_shared(), - RESOURCE_FORMAT_BINARY, "SpawnData", - static_cast(MK64::ResourceType::SpawnData), 0); - loader->RegisterResourceFactory(std::make_shared(), - RESOURCE_FORMAT_BINARY, "UnkSpawnData", - static_cast(MK64::ResourceType::UnkSpawnData), 0); + loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, + "TrackSections", static_cast(MK64::ResourceType::TrackSection), 0); + loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, + "Waypoints", static_cast(MK64::ResourceType::Waypoints), 0); + loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, + "SpawnData", static_cast(MK64::ResourceType::SpawnData), 0); + loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, + "UnkSpawnData", static_cast(MK64::ResourceType::UnkSpawnData), 0); } void GameEngine::Create() { const auto instance = Instance = new GameEngine(); + instance->AudioInit(); GameUI::SetupGuiElements(); #if defined(__SWITCH__) || defined(__WIIU__) CVarRegisterInteger("gControlNav", 1); // always enable controller nav on switch/wii u #endif } -void GameEngine::Destroy() { +void GameEngine::Destroy(){ + AudioExit(); } bool ShouldClearTextureCacheAtEndOfFrame = false; @@ -161,6 +169,106 @@ void GameEngine::ProcessGfxCommands(Gfx* commands) { } } +// Audio + +void GameEngine::HandleAudioThread(){ + while (audio.running) { + { + std::unique_lock Lock(audio.mutex); + while (!audio.processing && audio.running) { + audio.cv_to_thread.wait(Lock); + } + + if (!audio.running) { + break; + } + } + std::unique_lock Lock(audio.mutex); + + int samples_left = AudioPlayerBuffered(); + u32 num_audio_samples = samples_left < AudioPlayerGetDesiredBuffered() ? SAMPLES_HIGH : SAMPLES_LOW; + + s16 audio_buffer[SAMPLES_PER_FRAME]; + for (int i = 0; i < NUM_AUDIO_CHANNELS; i++) { + create_next_audio_buffer(audio_buffer + i * (num_audio_samples * 2), num_audio_samples); + } + + AudioPlayerPlayFrame((u8 *) audio_buffer, 2 * num_audio_samples * 4); + + audio.processing = false; + audio.cv_from_thread.notify_one(); + } +} + +void GameEngine::StartAudioFrame(){ + { + std::unique_lock Lock(audio.mutex); + audio.processing = true; + } + + audio.cv_to_thread.notify_one(); +} + +void GameEngine::EndAudioFrame(){ + { + std::unique_lock Lock(audio.mutex); + while (audio.processing) { + audio.cv_from_thread.wait(Lock); + } + } +} + +void GameEngine::AudioInit() { + const auto resourceMgr = Ship::Context::GetInstance()->GetResourceManager(); + resourceMgr->LoadDirectory("sound"); + const auto banksFiles = resourceMgr->GetArchiveManager()->ListFiles("sound/banks/*"); + const auto sequences_files = resourceMgr->GetArchiveManager()->ListFiles("sound/sequences/*"); + + Instance->sequenceTable.resize(512); + Instance->audioSequenceTable.resize(512); + Instance->banksTable.resize(512); + + for(auto& bank : *banksFiles){ + auto path = "__OTR__" + bank; + const auto ctl = static_cast(ResourceGetDataByName(path.c_str())); + this->bankMapTable[bank] = ctl->bankId; + SPDLOG_INFO("Loaded bank: {}", bank); + } + + for(auto& sequence : *sequences_files){ + auto path = "__OTR__" + sequence; + auto seq = static_cast(ResourceGetDataByName(path.c_str())); + Instance->sequenceTable[seq->id] = path; + SPDLOG_INFO("Loaded sequence: {}", sequence); + } + + if (!audio.running) { + audio.running = true; + audio.thread = std::thread(HandleAudioThread); + SPDLOG_INFO("Audio thread started"); + } +} + +void GameEngine::AudioExit() { + { + std::unique_lock lock(audio.mutex); + audio.running = false; + } + audio.cv_to_thread.notify_all(); + + // Wait until the audio thread quit + audio.thread.join(); +} + +uint8_t GameEngine::GetBankIdByName(const std::string& name) { + if(Instance->bankMapTable.contains(name)){ + return Instance->bankMapTable[name]; + } + return 0; +} + +// End + extern "C" uint32_t GameEngine_GetSampleRate() { auto player = Ship::Context::GetInstance()->GetAudio()->GetAudioPlayer(); if (player == nullptr) { @@ -178,7 +286,67 @@ extern "C" uint32_t GameEngine_GetSamplesPerFrame() { return SAMPLES_PER_FRAME; } -// End +extern "C" CtlEntry* GameEngine_LoadBank(const uint8_t bankId) { + const auto engine = GameEngine::Instance; + + if(bankId >= engine->bankMapTable.size()){ + return nullptr; + } + + if(engine->banksTable[bankId] != nullptr){ + return engine->banksTable[bankId]; + } + + for(auto& bank : engine->bankMapTable){ + if(bank.second == bankId){ + const auto ctl = static_cast(ResourceGetDataByName(("__OTR__" + bank.first).c_str())); + engine->banksTable[bankId] = ctl; + return ctl; + } + } + return nullptr; +} + +extern "C" uint8_t GameEngine_IsBankLoaded(const uint8_t bankId) { + const auto engine = GameEngine::Instance; + GameEngine_LoadBank(bankId); + return engine->banksTable[bankId] != nullptr; +} + +extern "C" void GameEngine_UnloadBank(const uint8_t bankId) { + const auto engine = GameEngine::Instance; + engine->banksTable[bankId] = nullptr; +} + +extern "C" AudioSequenceData* GameEngine_LoadSequence(const uint8_t seqId) { + auto engine = GameEngine::Instance; + + if(engine->sequenceTable[seqId].empty()){ + return nullptr; + } + + if(engine->audioSequenceTable[seqId] != nullptr){ + return engine->audioSequenceTable[seqId]; + } + + auto sequences = static_cast(ResourceGetDataByName(engine->sequenceTable[seqId].c_str())); + engine->audioSequenceTable[seqId] = sequences; + return sequences; +} + +extern "C" uint32_t GameEngine_GetSequenceCount(){ + auto engine = GameEngine::Instance; + return engine->sequenceTable.size(); +} + +extern "C" uint8_t GameEngine_IsSequenceLoaded(const uint8_t seqId) { + return GameEngine_LoadSequence(seqId) != nullptr; +} + +extern "C" void GameEngine_UnloadSequence(const uint8_t seqId) { + const auto engine = GameEngine::Instance; + engine->audioSequenceTable[seqId] = nullptr; +} extern "C" float GameEngine_GetAspectRatio() { return gfx_current_dimensions.aspect_ratio; diff --git a/src/port/Engine.h b/src/port/Engine.h index f466b0e6e..85fa6ba58 100644 --- a/src/port/Engine.h +++ b/src/port/Engine.h @@ -16,19 +16,35 @@ #define NUM_AUDIO_CHANNELS 2 #define SAMPLES_PER_FRAME (SAMPLES_HIGH * NUM_AUDIO_CHANNELS * 2) +struct CtlEntry; +struct AudioBankSample; +struct AudioSequenceData; + class GameEngine { public: static GameEngine* Instance; std::shared_ptr context; + std::vector banksTable; + std::vector sequenceTable; + std::vector audioSequenceTable; + std::unordered_map bankMapTable; GameEngine(); static void Create(); + + void AudioInit(); + static void HandleAudioThread(); + static void StartAudioFrame(); + static void EndAudioFrame(); + static void AudioExit(); + void StartFrame() const; static void RunCommands(Gfx* Commands); void ProcessFrame(void (*run_one_game_iter)()) const; static void Destroy(); static void ProcessGfxCommands(Gfx* commands); + static uint8_t GetBankIdByName(const std::string& name); float OTRGetAspectRatio(void); float OTRGetDimensionFromLeftEdge(float v); float OTRGetDimensionFromRightEdge(float v); @@ -39,7 +55,16 @@ class GameEngine { }; #else void GameEngine_ProcessGfxCommands(Gfx* commands); +uint32_t GameEngine_GetSampleRate(); +uint32_t GameEngine_GetSamplesPerFrame(); float GameEngine_GetAspectRatio(); +struct CtlEntry* GameEngine_LoadBank(uint8_t bankId); +uint8_t GameEngine_IsBankLoaded(uint8_t bankId); +void GameEngine_UnloadBank(uint8_t bankId); +struct AudioSequenceData* GameEngine_LoadSequence(uint8_t seqId); +uint32_t GameEngine_GetSequenceCount(); +uint8_t GameEngine_IsSequenceLoaded(uint8_t seqId); +void GameEngine_UnloadSequence(uint8_t seqId); uint8_t GameEngine_OTRSigCheck(char* imgData); float OTRGetAspectRatio(void); float OTRGetDimensionFromLeftEdge(float v); diff --git a/src/port/Game.cpp b/src/port/Game.cpp index 8a8c0b7cb..a47479bec 100644 --- a/src/port/Game.cpp +++ b/src/port/Game.cpp @@ -683,13 +683,13 @@ extern "C" { } void push_frame() { - // GameEngine::StartAudioFrame(); - GameEngine::Instance->StartFrame(); - thread5_iteration(); + GameEngine::StartAudioFrame(); + GameEngine::Instance->StartFrame(); + thread5_iteration(); + GameEngine::EndAudioFrame(); // thread5_game_loop(); // Graphics_ThreadUpdate();w // Timer_Update(); - // GameEngine::EndAudioFrame(); } #ifdef _WIN32 @@ -701,10 +701,10 @@ extern "C" int main(int argc, char* argv[]) { #endif - //load_wasm(); - GameEngine::Create(); - // audio_init(); - // sound_init(); + //load_wasm(); + GameEngine::Create(); + audio_init(); + sound_init(); CustomEngineInit(); thread5_game_loop(); diff --git a/src/port/resource/importers/AudioBankFactory.cpp b/src/port/resource/importers/AudioBankFactory.cpp new file mode 100644 index 000000000..90d70b9aa --- /dev/null +++ b/src/port/resource/importers/AudioBankFactory.cpp @@ -0,0 +1,96 @@ +#include "AudioBankFactory.h" +#include "../type/AudioBank.h" +#include "spdlog/spdlog.h" +#include "resourcebridge.h" +#include "ResourceUtil.h" + +std::shared_ptr SM64::AudioBankFactoryV0::ReadResource(std::shared_ptr file) { + if (!FileHasValidFormatAndReader(file)) { + return nullptr; + } + + std::shared_ptr bank = std::make_shared(file->InitData); + auto reader = std::get>(file->Reader); + + uint8_t bankId = reader->ReadUInt32(); + uint32_t instrumentCount = reader->ReadUInt32(); + + for(size_t i = 0; i < instrumentCount; i++){ + auto* instrument = new Instrument(); + bool valid = reader->ReadUByte(); + if(!valid){ + bank->instruments.push_back(nullptr); + continue; + } + instrument->loaded = 1; + instrument->releaseRate = reader->ReadUByte(); + instrument->normalRangeLo = reader->ReadUByte(); + instrument->normalRangeHi = reader->ReadUByte(); + + uint32_t envelopeSize = reader->ReadUInt32(); + if(envelopeSize != 0){ + instrument->envelope = new AdsrEnvelope[envelopeSize]; + for(size_t j = 0; j < envelopeSize; j++){ + instrument->envelope[j].delay = BSWAP16(reader->ReadInt16()); + instrument->envelope[j].arg = BSWAP16(reader->ReadInt16()); + } + } + + uint32_t soundFlags = reader->ReadUInt32(); + bool hasLo = soundFlags & (1 << 0); + bool hasMed = soundFlags & (1 << 1); + bool hasHi = soundFlags & (1 << 2); + + if(hasLo){ + std::string lowSampleName = reader->ReadString(); + instrument->lowNotesSound.sample = LoadChild(lowSampleName.c_str()); + instrument->lowNotesSound.tuning = reader->ReadFloat(); + } + + if(hasMed){ + std::string normalSampleName = reader->ReadString(); + instrument->normalNotesSound.sample = LoadChild(normalSampleName.c_str()); + instrument->normalNotesSound.tuning = reader->ReadFloat(); + } + + if(hasHi){ + std::string highSampleName = reader->ReadString(); + instrument->highNotesSound.sample = LoadChild(highSampleName.c_str()); + instrument->highNotesSound.tuning = reader->ReadFloat(); + } + + bank->instruments.push_back(instrument); + } + + uint32_t drumCount = reader->ReadUInt32(); + + for(size_t i = 0; i < drumCount; i++){ + auto* drum = new Drum(); + drum->releaseRate = reader->ReadUByte(); + drum->pan = reader->ReadUByte(); + drum->loaded = 1; + + uint32_t envelopeSize = reader->ReadUInt32(); + if(envelopeSize != 0){ + drum->envelope = new AdsrEnvelope[envelopeSize]; + for(size_t j = 0; j < envelopeSize; j++){ + drum->envelope[j].delay = BSWAP16(reader->ReadInt16()); + drum->envelope[j].arg = BSWAP16(reader->ReadInt16()); + } + } + + std::string sampleName = reader->ReadString(); + drum->sound.sample = LoadChild(sampleName.c_str()); + drum->sound.tuning = reader->ReadFloat(); + + bank->drums.push_back(drum); + } + + bank->mData.bankId = bankId; + bank->mData.numInstruments = instrumentCount; + bank->mData.numDrums = drumCount; + bank->mData.instruments = bank->instruments.data(); + bank->mData.drums = bank->drums.data(); + + return bank; +} \ No newline at end of file diff --git a/src/port/resource/importers/AudioBankFactory.h b/src/port/resource/importers/AudioBankFactory.h new file mode 100644 index 000000000..f76e2d830 --- /dev/null +++ b/src/port/resource/importers/AudioBankFactory.h @@ -0,0 +1,11 @@ +#pragma once + +#include "Resource.h" +#include "ResourceFactoryBinary.h" + +namespace SM64 { +class AudioBankFactoryV0 : public Ship::ResourceFactoryBinary { + public: + std::shared_ptr ReadResource(std::shared_ptr file) override; +}; +} diff --git a/src/port/resource/importers/AudioSampleFactory.cpp b/src/port/resource/importers/AudioSampleFactory.cpp new file mode 100644 index 000000000..f21389666 --- /dev/null +++ b/src/port/resource/importers/AudioSampleFactory.cpp @@ -0,0 +1,47 @@ +#include "AudioSampleFactory.h" +#include +#include "../type/AudioSample.h" +#include "spdlog/spdlog.h" + +std::shared_ptr SM64::AudioSampleFactoryV0::ReadResource(std::shared_ptr file) { + if (!FileHasValidFormatAndReader(file)) { + return nullptr; + } + + std::shared_ptr bank = std::make_shared(file->InitData); + auto reader = std::get>(file->Reader); + + bank->loop.start = reader->ReadUInt32(); + bank->loop.end = reader->ReadUInt32(); + bank->loop.count = reader->ReadInt32(); + bank->loop.pad = reader->ReadInt32(); + + uint32_t stateSize = reader->ReadUInt32(); + std::vector state; + if(stateSize > 0){ + bank->loop.state = new int16_t[stateSize]; + reader->Read((char*) bank->loop.state, stateSize * sizeof(int16_t)); + } else { + bank->loop.state = nullptr; + } + + bank->book.order = reader->ReadInt32(); + bank->book.npredictors = reader->ReadInt32(); + + uint32_t tableSize = reader->ReadUInt32(); + bank->book.book = new int16_t[tableSize]; + reader->Read((char*) bank->book.book, tableSize * sizeof(int16_t)); + + int32_t sampleSize = reader->ReadInt32(); + char* sampleData = new char[sampleSize]; + reader->Read(sampleData, sampleSize); + + bank->mData.unused = 0; + bank->mData.loaded = 1; + bank->mData.loop = &bank->loop; + bank->mData.book = &bank->book; + bank->mData.sampleAddr = (uint8_t*) sampleData; + bank->mData.sampleSize = sampleSize; + + return bank; +} \ No newline at end of file diff --git a/src/port/resource/importers/AudioSampleFactory.h b/src/port/resource/importers/AudioSampleFactory.h new file mode 100644 index 000000000..cf640bd5c --- /dev/null +++ b/src/port/resource/importers/AudioSampleFactory.h @@ -0,0 +1,11 @@ +#pragma once + +#include "Resource.h" +#include "ResourceFactoryBinary.h" + +namespace SM64 { +class AudioSampleFactoryV0 : public Ship::ResourceFactoryBinary { + public: + std::shared_ptr ReadResource(std::shared_ptr file) override; +}; +} diff --git a/src/port/resource/importers/AudioSequenceFactory.cpp b/src/port/resource/importers/AudioSequenceFactory.cpp new file mode 100644 index 000000000..d021e8dc0 --- /dev/null +++ b/src/port/resource/importers/AudioSequenceFactory.cpp @@ -0,0 +1,33 @@ +#include "AudioSequenceFactory.h" +#include "../type/AudioSequence.h" +#include "../type/AudioBank.h" +#include "spdlog/spdlog.h" +#include "port/Engine.h" + +std::shared_ptr SM64::AudioSequenceFactoryV0::ReadResource(std::shared_ptr file) { + if (!FileHasValidFormatAndReader(file)) { + return nullptr; + } + + std::shared_ptr bank = std::make_shared(file->InitData); + auto reader = std::get>(file->Reader); + + uint8_t id = reader->ReadUInt32(); + size_t bankCount = reader->ReadUInt32(); + for(size_t i = 0; i < bankCount; i++){ + std::string bankName = reader->ReadString(); + bank->banks.push_back(GameEngine::GetBankIdByName(bankName)); + } + + size_t sampleSize = reader->ReadUInt32(); + for(size_t i = 0; i < sampleSize; i++){ + bank->sampleData.push_back(reader->ReadUByte()); + } + + bank->mData.bankCount = bankCount; + bank->mData.banks = bank->banks.data(); + bank->mData.data = bank->sampleData.data(); + bank->mData.id = id; + + return bank; +} \ No newline at end of file diff --git a/src/port/resource/importers/AudioSequenceFactory.h b/src/port/resource/importers/AudioSequenceFactory.h new file mode 100644 index 000000000..dd08e5152 --- /dev/null +++ b/src/port/resource/importers/AudioSequenceFactory.h @@ -0,0 +1,12 @@ +#pragma once + +#include "Resource.h" +#include "ResourceFactoryBinary.h" +#include "../type/AudioSequence.h" + +namespace SM64 { +class AudioSequenceFactoryV0 : public Ship::ResourceFactoryBinary { + public: + std::shared_ptr ReadResource(std::shared_ptr file) override; +}; +} diff --git a/src/port/resource/importers/ResourceUtil.h b/src/port/resource/importers/ResourceUtil.h index f856eccd3..69d03a7d9 100644 --- a/src/port/resource/importers/ResourceUtil.h +++ b/src/port/resource/importers/ResourceUtil.h @@ -3,7 +3,7 @@ #include "resourcebridge.h" #include "Context.h" -namespace SF64 { +namespace SM64 { template T LoadChild(uint64_t crc) { auto path = ResourceGetNameByCrc(crc); if (path == nullptr) { @@ -12,4 +12,11 @@ template T LoadChild(uint64_t crc) { auto asset = Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(path); return asset ? static_cast(asset->GetRawPointer()) : nullptr; } -} // namespace SF64 +template T LoadChild(const char* path) { + if (path == nullptr) { + return nullptr; + } + auto asset = Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(path); + return asset ? static_cast(asset->GetRawPointer()) : nullptr; +} +} diff --git a/src/port/resource/type/AudioBank.cpp b/src/port/resource/type/AudioBank.cpp new file mode 100644 index 000000000..f91b767d2 --- /dev/null +++ b/src/port/resource/type/AudioBank.cpp @@ -0,0 +1,11 @@ +#include "AudioBank.h" + +namespace SM64 { +CtlEntry* AudioBank::GetPointer() { + return &mData; +} + +size_t AudioBank::GetPointerSize() { + return sizeof(mData); +} +} \ No newline at end of file diff --git a/src/port/resource/type/AudioBank.h b/src/port/resource/type/AudioBank.h new file mode 100644 index 000000000..a8541fe84 --- /dev/null +++ b/src/port/resource/type/AudioBank.h @@ -0,0 +1,59 @@ +#pragma once + +#include +#include "AudioSample.h" +#include "resource/Resource.h" + +struct AudioBankSound { + AudioBankSample *sample; + float tuning; // frequency scale factor +}; // size = 0x8 + +struct AdsrEnvelope { + int16_t delay; + int16_t arg; +}; // size = 0x4 + +struct Instrument { + /*0x00*/ uint8_t loaded; + /*0x01*/ uint8_t normalRangeLo; + /*0x02*/ uint8_t normalRangeHi; + /*0x03*/ uint8_t releaseRate; + /*0x04*/ AdsrEnvelope *envelope; + /*0x08*/ AudioBankSound lowNotesSound; + /*0x10*/ AudioBankSound normalNotesSound; + /*0x18*/ AudioBankSound highNotesSound; +}; // size = 0x20 + +struct Drum { + uint8_t releaseRate; + uint8_t pan; + uint8_t loaded; + AudioBankSound sound; + AdsrEnvelope *envelope; +}; + +struct CtlEntry { + uint8_t bankId; + uint8_t numInstruments; + uint8_t numDrums; + struct Instrument **instruments; + struct Drum **drums; +}; // size = 0xC + +namespace SM64 { +class AudioBank : public Ship::Resource { + public: + using Resource::Resource; + + AudioBank() : Resource(std::shared_ptr()) {} + + CtlEntry* GetPointer(); + size_t GetPointerSize(); + + CtlEntry mData; + + std::vector instruments; + std::vector drums; +}; +} \ No newline at end of file diff --git a/src/port/resource/type/AudioSample.cpp b/src/port/resource/type/AudioSample.cpp new file mode 100644 index 000000000..cbdbd6573 --- /dev/null +++ b/src/port/resource/type/AudioSample.cpp @@ -0,0 +1,11 @@ +#include "AudioSample.h" + +namespace SM64 { +AudioBankSample* AudioSample::GetPointer() { + return &mData; +} + +size_t AudioSample::GetPointerSize() { + return sizeof(mData); +} +} \ No newline at end of file diff --git a/src/port/resource/type/AudioSample.h b/src/port/resource/type/AudioSample.h new file mode 100644 index 000000000..35f1d8d33 --- /dev/null +++ b/src/port/resource/type/AudioSample.h @@ -0,0 +1,47 @@ +#pragma once + +#include +#include "resource/Resource.h" + +struct AdpcmLoop { + uint32_t start; + uint32_t end; + uint32_t count; + uint32_t pad; + int16_t* state; // only exists if count != 0. 8-byte aligned +}; + +struct AdpcmBook { + int32_t order; + int32_t npredictors; + int16_t* book; // size 8 * order * npredictors. 8-byte aligned +}; + +struct AudioBankSample { + uint8_t unused; + uint8_t loaded; + uint8_t *sampleAddr; + AdpcmLoop *loop; + AdpcmBook *book; + uint32_t sampleSize; // never read. either 0 or 1 mod 9, depending on padding +}; + +namespace SM64 { + + +class AudioSample : public Ship::Resource { + public: + using Resource::Resource; + + AudioSample() : Resource(std::shared_ptr()) {} + + AudioBankSample* GetPointer(); + size_t GetPointerSize(); + + AudioBankSample mData; + + AdpcmLoop loop; + AdpcmBook book; + std::vector sampleAddr; +}; +} \ No newline at end of file diff --git a/src/port/resource/type/AudioSequence.cpp b/src/port/resource/type/AudioSequence.cpp new file mode 100644 index 000000000..263530cfa --- /dev/null +++ b/src/port/resource/type/AudioSequence.cpp @@ -0,0 +1,11 @@ +#include "AudioSequence.h" + +namespace SM64 { +AudioSequenceData* AudioSequence::GetPointer() { + return &mData; +} + +size_t AudioSequence::GetPointerSize() { + return sizeof(mData); +} +} \ No newline at end of file diff --git a/src/port/resource/type/AudioSequence.h b/src/port/resource/type/AudioSequence.h new file mode 100644 index 000000000..44ab130eb --- /dev/null +++ b/src/port/resource/type/AudioSequence.h @@ -0,0 +1,32 @@ +#pragma once + +#ifdef __cplusplus +#include +#endif + +struct AudioSequenceData { + uint32_t bankCount; + uint8_t* banks; + uint8_t* data; + uint8_t id; +}; + +#ifdef __cplusplus +#include "resource/Resource.h" +namespace SM64 { + +class AudioSequence : public Ship::Resource { + public: + using Resource::Resource; + + AudioSequence() : Resource(std::shared_ptr()) {} + + AudioSequenceData* GetPointer(); + size_t GetPointerSize(); + + AudioSequenceData mData; + std::vector banks; + std::vector sampleData; +}; +} +#endif \ No newline at end of file diff --git a/src/port/resource/type/ResourceType.h b/src/port/resource/type/ResourceType.h index 5c340c234..fe27a7930 100644 --- a/src/port/resource/type/ResourceType.h +++ b/src/port/resource/type/ResourceType.h @@ -17,6 +17,10 @@ enum class ResourceType { Vec3f = 0x56433346, // VC3F Vec3s = 0x56433353, // VC3S GenericArray = 0x47415252, // GARR + // NAudio v0 + Bank = 0x42414E4B, // BANK + Sample = 0x41554643, // AIFC + Sequence = 0x53455143, // SEQC }; } // namespace SF64 diff --git a/yamls/us/sound/banks.yml b/yamls/us/sound/banks.yml new file mode 100644 index 000000000..0e9277b7d --- /dev/null +++ b/yamls/us/sound/banks.yml @@ -0,0 +1,83 @@ +bank_0: + type: NAUDIO:V0:BANK + id: 0 + +bank_1: + type: NAUDIO:V0:BANK + id: 1 + +bank_2: + type: NAUDIO:V0:BANK + id: 2 + +bank_3: + type: NAUDIO:V0:BANK + id: 3 + +bank_4: + type: NAUDIO:V0:BANK + id: 4 + +bank_5: + type: NAUDIO:V0:BANK + id: 5 + +bank_6: + type: NAUDIO:V0:BANK + id: 6 + +bank_7: + type: NAUDIO:V0:BANK + id: 7 + +bank_8: + type: NAUDIO:V0:BANK + id: 8 + +bank_9: + type: NAUDIO:V0:BANK + id: 9 + +bank_10: + type: NAUDIO:V0:BANK + id: 10 + +bank_11: + type: NAUDIO:V0:BANK + id: 11 + +bank_12: + type: NAUDIO:V0:BANK + id: 12 + +bank_13: + type: NAUDIO:V0:BANK + id: 13 + +bank_14: + type: NAUDIO:V0:BANK + id: 14 + +bank_15: + type: NAUDIO:V0:BANK + id: 15 + +bank_16: + type: NAUDIO:V0:BANK + id: 16 + +bank_17: + type: NAUDIO:V0:BANK + id: 17 + +bank_18: + type: NAUDIO:V0:BANK + id: 18 + +bank_19: + type: NAUDIO:V0:BANK + id: 19 + +bank_20: + type: NAUDIO:V0:BANK + id: 20 \ No newline at end of file diff --git a/yamls/us/audio.yml b/yamls/us/sound/root.yml similarity index 64% rename from yamls/us/audio.yml rename to yamls/us/sound/root.yml index cda86c71e..d99080128 100644 --- a/yamls/us/audio.yml +++ b/yamls/us/sound/root.yml @@ -13,4 +13,7 @@ header: size: 0x13840 tbl: offset: 0x979AA0 - size: 0x24C4C0 \ No newline at end of file + size: 0x24C4C0 + +audio_seq_font_table: + { type: ARRAY, count: 0x80, array_type: u8, offset: 0xBE90E0, symbol: gSeqFontTableInit } \ No newline at end of file diff --git a/yamls/us/sound/samples.yml b/yamls/us/sound/samples.yml new file mode 100644 index 000000000..cf5ee5606 --- /dev/null +++ b/yamls/us/sound/samples.yml @@ -0,0 +1,807 @@ +sample_0: + type: NAUDIO:V0:SAMPLE + id: 0 + +sample_1: + type: NAUDIO:V0:SAMPLE + id: 1 + +sample_2: + type: NAUDIO:V0:SAMPLE + id: 2 + +sample_3: + type: NAUDIO:V0:SAMPLE + id: 3 + +sample_4: + type: NAUDIO:V0:SAMPLE + id: 4 + +sample_5: + type: NAUDIO:V0:SAMPLE + id: 5 + +sample_6: + type: NAUDIO:V0:SAMPLE + id: 6 + +sample_7: + type: NAUDIO:V0:SAMPLE + id: 7 + +sample_8: + type: NAUDIO:V0:SAMPLE + id: 8 + +sample_9: + type: NAUDIO:V0:SAMPLE + id: 9 + +sample_10: + type: NAUDIO:V0:SAMPLE + id: 10 + +sample_11: + type: NAUDIO:V0:SAMPLE + id: 11 + +sample_12: + type: NAUDIO:V0:SAMPLE + id: 12 + +sample_13: + type: NAUDIO:V0:SAMPLE + id: 13 + +sample_14: + type: NAUDIO:V0:SAMPLE + id: 14 + +sample_15: + type: NAUDIO:V0:SAMPLE + id: 15 + +sample_16: + type: NAUDIO:V0:SAMPLE + id: 16 + +sample_17: + type: NAUDIO:V0:SAMPLE + id: 17 + +sample_18: + type: NAUDIO:V0:SAMPLE + id: 18 + +sample_19: + type: NAUDIO:V0:SAMPLE + id: 19 + +sample_20: + type: NAUDIO:V0:SAMPLE + id: 20 + +sample_21: + type: NAUDIO:V0:SAMPLE + id: 21 + +sample_22: + type: NAUDIO:V0:SAMPLE + id: 22 + +sample_23: + type: NAUDIO:V0:SAMPLE + id: 23 + +sample_24: + type: NAUDIO:V0:SAMPLE + id: 24 + +sample_25: + type: NAUDIO:V0:SAMPLE + id: 25 + +sample_26: + type: NAUDIO:V0:SAMPLE + id: 26 + +sample_27: + type: NAUDIO:V0:SAMPLE + id: 27 + +sample_28: + type: NAUDIO:V0:SAMPLE + id: 28 + +sample_29: + type: NAUDIO:V0:SAMPLE + id: 29 + +sample_30: + type: NAUDIO:V0:SAMPLE + id: 30 + +sample_31: + type: NAUDIO:V0:SAMPLE + id: 31 + +sample_32: + type: NAUDIO:V0:SAMPLE + id: 32 + +sample_33: + type: NAUDIO:V0:SAMPLE + id: 33 + +sample_34: + type: NAUDIO:V0:SAMPLE + id: 34 + +sample_35: + type: NAUDIO:V0:SAMPLE + id: 35 + +sample_36: + type: NAUDIO:V0:SAMPLE + id: 36 + +sample_37: + type: NAUDIO:V0:SAMPLE + id: 37 + +sample_38: + type: NAUDIO:V0:SAMPLE + id: 38 + +sample_39: + type: NAUDIO:V0:SAMPLE + id: 39 + +sample_40: + type: NAUDIO:V0:SAMPLE + id: 40 + +sample_41: + type: NAUDIO:V0:SAMPLE + id: 41 + +sample_42: + type: NAUDIO:V0:SAMPLE + id: 42 + +sample_43: + type: NAUDIO:V0:SAMPLE + id: 43 + +sample_44: + type: NAUDIO:V0:SAMPLE + id: 44 + +sample_45: + type: NAUDIO:V0:SAMPLE + id: 45 + +sample_46: + type: NAUDIO:V0:SAMPLE + id: 46 + +sample_47: + type: NAUDIO:V0:SAMPLE + id: 47 + +sample_48: + type: NAUDIO:V0:SAMPLE + id: 48 + +sample_49: + type: NAUDIO:V0:SAMPLE + id: 49 + +sample_50: + type: NAUDIO:V0:SAMPLE + id: 50 + +sample_51: + type: NAUDIO:V0:SAMPLE + id: 51 + +sample_52: + type: NAUDIO:V0:SAMPLE + id: 52 + +sample_53: + type: NAUDIO:V0:SAMPLE + id: 53 + +sample_54: + type: NAUDIO:V0:SAMPLE + id: 54 + +sample_55: + type: NAUDIO:V0:SAMPLE + id: 55 + +sample_56: + type: NAUDIO:V0:SAMPLE + id: 56 + +sample_57: + type: NAUDIO:V0:SAMPLE + id: 57 + +sample_58: + type: NAUDIO:V0:SAMPLE + id: 58 + +sample_59: + type: NAUDIO:V0:SAMPLE + id: 59 + +sample_60: + type: NAUDIO:V0:SAMPLE + id: 60 + +sample_61: + type: NAUDIO:V0:SAMPLE + id: 61 + +sample_62: + type: NAUDIO:V0:SAMPLE + id: 62 + +sample_63: + type: NAUDIO:V0:SAMPLE + id: 63 + +sample_64: + type: NAUDIO:V0:SAMPLE + id: 64 + +sample_65: + type: NAUDIO:V0:SAMPLE + id: 65 + +sample_66: + type: NAUDIO:V0:SAMPLE + id: 66 + +sample_67: + type: NAUDIO:V0:SAMPLE + id: 67 + +sample_68: + type: NAUDIO:V0:SAMPLE + id: 68 + +sample_69: + type: NAUDIO:V0:SAMPLE + id: 69 + +sample_70: + type: NAUDIO:V0:SAMPLE + id: 70 + +sample_71: + type: NAUDIO:V0:SAMPLE + id: 71 + +sample_72: + type: NAUDIO:V0:SAMPLE + id: 72 + +sample_73: + type: NAUDIO:V0:SAMPLE + id: 73 + +sample_74: + type: NAUDIO:V0:SAMPLE + id: 74 + +sample_75: + type: NAUDIO:V0:SAMPLE + id: 75 + +sample_76: + type: NAUDIO:V0:SAMPLE + id: 76 + +sample_77: + type: NAUDIO:V0:SAMPLE + id: 77 + +sample_78: + type: NAUDIO:V0:SAMPLE + id: 78 + +sample_79: + type: NAUDIO:V0:SAMPLE + id: 79 + +sample_80: + type: NAUDIO:V0:SAMPLE + id: 80 + +sample_81: + type: NAUDIO:V0:SAMPLE + id: 81 + +sample_82: + type: NAUDIO:V0:SAMPLE + id: 82 + +sample_83: + type: NAUDIO:V0:SAMPLE + id: 83 + +sample_84: + type: NAUDIO:V0:SAMPLE + id: 84 + +sample_85: + type: NAUDIO:V0:SAMPLE + id: 85 + +sample_86: + type: NAUDIO:V0:SAMPLE + id: 86 + +sample_87: + type: NAUDIO:V0:SAMPLE + id: 87 + +sample_88: + type: NAUDIO:V0:SAMPLE + id: 88 + +sample_89: + type: NAUDIO:V0:SAMPLE + id: 89 + +sample_90: + type: NAUDIO:V0:SAMPLE + id: 90 + +sample_91: + type: NAUDIO:V0:SAMPLE + id: 91 + +sample_92: + type: NAUDIO:V0:SAMPLE + id: 92 + +sample_93: + type: NAUDIO:V0:SAMPLE + id: 93 + +sample_94: + type: NAUDIO:V0:SAMPLE + id: 94 + +sample_95: + type: NAUDIO:V0:SAMPLE + id: 95 + +sample_96: + type: NAUDIO:V0:SAMPLE + id: 96 + +sample_97: + type: NAUDIO:V0:SAMPLE + id: 97 + +sample_98: + type: NAUDIO:V0:SAMPLE + id: 98 + +sample_99: + type: NAUDIO:V0:SAMPLE + id: 99 + +sample_100: + type: NAUDIO:V0:SAMPLE + id: 100 + +sample_101: + type: NAUDIO:V0:SAMPLE + id: 101 + +sample_102: + type: NAUDIO:V0:SAMPLE + id: 102 + +sample_103: + type: NAUDIO:V0:SAMPLE + id: 103 + +sample_104: + type: NAUDIO:V0:SAMPLE + id: 104 + +sample_105: + type: NAUDIO:V0:SAMPLE + id: 105 + +sample_106: + type: NAUDIO:V0:SAMPLE + id: 106 + +sample_107: + type: NAUDIO:V0:SAMPLE + id: 107 + +sample_108: + type: NAUDIO:V0:SAMPLE + id: 108 + +sample_109: + type: NAUDIO:V0:SAMPLE + id: 109 + +sample_110: + type: NAUDIO:V0:SAMPLE + id: 110 + +sample_111: + type: NAUDIO:V0:SAMPLE + id: 111 + +sample_112: + type: NAUDIO:V0:SAMPLE + id: 112 + +sample_113: + type: NAUDIO:V0:SAMPLE + id: 113 + +sample_114: + type: NAUDIO:V0:SAMPLE + id: 114 + +sample_115: + type: NAUDIO:V0:SAMPLE + id: 115 + +sample_116: + type: NAUDIO:V0:SAMPLE + id: 116 + +sample_117: + type: NAUDIO:V0:SAMPLE + id: 117 + +sample_118: + type: NAUDIO:V0:SAMPLE + id: 118 + +sample_119: + type: NAUDIO:V0:SAMPLE + id: 119 + +sample_120: + type: NAUDIO:V0:SAMPLE + id: 120 + +sample_121: + type: NAUDIO:V0:SAMPLE + id: 121 + +sample_122: + type: NAUDIO:V0:SAMPLE + id: 122 + +sample_123: + type: NAUDIO:V0:SAMPLE + id: 123 + +sample_124: + type: NAUDIO:V0:SAMPLE + id: 124 + +sample_125: + type: NAUDIO:V0:SAMPLE + id: 125 + +sample_126: + type: NAUDIO:V0:SAMPLE + id: 126 + +sample_127: + type: NAUDIO:V0:SAMPLE + id: 127 + +sample_128: + type: NAUDIO:V0:SAMPLE + id: 128 + +sample_129: + type: NAUDIO:V0:SAMPLE + id: 129 + +sample_130: + type: NAUDIO:V0:SAMPLE + id: 130 + +sample_131: + type: NAUDIO:V0:SAMPLE + id: 131 + +sample_132: + type: NAUDIO:V0:SAMPLE + id: 132 + +sample_133: + type: NAUDIO:V0:SAMPLE + id: 133 + +sample_134: + type: NAUDIO:V0:SAMPLE + id: 134 + +sample_135: + type: NAUDIO:V0:SAMPLE + id: 135 + +sample_136: + type: NAUDIO:V0:SAMPLE + id: 136 + +sample_137: + type: NAUDIO:V0:SAMPLE + id: 137 + +sample_138: + type: NAUDIO:V0:SAMPLE + id: 138 + +sample_139: + type: NAUDIO:V0:SAMPLE + id: 139 + +sample_140: + type: NAUDIO:V0:SAMPLE + id: 140 + +sample_141: + type: NAUDIO:V0:SAMPLE + id: 141 + +sample_142: + type: NAUDIO:V0:SAMPLE + id: 142 + +sample_143: + type: NAUDIO:V0:SAMPLE + id: 143 + +sample_144: + type: NAUDIO:V0:SAMPLE + id: 144 + +sample_145: + type: NAUDIO:V0:SAMPLE + id: 145 + +sample_146: + type: NAUDIO:V0:SAMPLE + id: 146 + +sample_147: + type: NAUDIO:V0:SAMPLE + id: 147 + +sample_148: + type: NAUDIO:V0:SAMPLE + id: 148 + +sample_149: + type: NAUDIO:V0:SAMPLE + id: 149 + +sample_150: + type: NAUDIO:V0:SAMPLE + id: 150 + +sample_151: + type: NAUDIO:V0:SAMPLE + id: 151 + +sample_152: + type: NAUDIO:V0:SAMPLE + id: 152 + +sample_153: + type: NAUDIO:V0:SAMPLE + id: 153 + +sample_154: + type: NAUDIO:V0:SAMPLE + id: 154 + +sample_155: + type: NAUDIO:V0:SAMPLE + id: 155 + +sample_156: + type: NAUDIO:V0:SAMPLE + id: 156 + +sample_157: + type: NAUDIO:V0:SAMPLE + id: 157 + +sample_158: + type: NAUDIO:V0:SAMPLE + id: 158 + +sample_159: + type: NAUDIO:V0:SAMPLE + id: 159 + +sample_160: + type: NAUDIO:V0:SAMPLE + id: 160 + +sample_161: + type: NAUDIO:V0:SAMPLE + id: 161 + +sample_162: + type: NAUDIO:V0:SAMPLE + id: 162 + +sample_163: + type: NAUDIO:V0:SAMPLE + id: 163 + +sample_164: + type: NAUDIO:V0:SAMPLE + id: 164 + +sample_165: + type: NAUDIO:V0:SAMPLE + id: 165 + +sample_166: + type: NAUDIO:V0:SAMPLE + id: 166 + +sample_167: + type: NAUDIO:V0:SAMPLE + id: 167 + +sample_168: + type: NAUDIO:V0:SAMPLE + id: 168 + +sample_169: + type: NAUDIO:V0:SAMPLE + id: 169 + +sample_170: + type: NAUDIO:V0:SAMPLE + id: 170 + +sample_171: + type: NAUDIO:V0:SAMPLE + id: 171 + +sample_172: + type: NAUDIO:V0:SAMPLE + id: 172 + +sample_173: + type: NAUDIO:V0:SAMPLE + id: 173 + +sample_174: + type: NAUDIO:V0:SAMPLE + id: 174 + +sample_175: + type: NAUDIO:V0:SAMPLE + id: 175 + +sample_176: + type: NAUDIO:V0:SAMPLE + id: 176 + +sample_177: + type: NAUDIO:V0:SAMPLE + id: 177 + +sample_178: + type: NAUDIO:V0:SAMPLE + id: 178 + +sample_179: + type: NAUDIO:V0:SAMPLE + id: 179 + +sample_180: + type: NAUDIO:V0:SAMPLE + id: 180 + +sample_181: + type: NAUDIO:V0:SAMPLE + id: 181 + +sample_182: + type: NAUDIO:V0:SAMPLE + id: 182 + +sample_183: + type: NAUDIO:V0:SAMPLE + id: 183 + +sample_184: + type: NAUDIO:V0:SAMPLE + id: 184 + +sample_185: + type: NAUDIO:V0:SAMPLE + id: 185 + +sample_186: + type: NAUDIO:V0:SAMPLE + id: 186 + +sample_187: + type: NAUDIO:V0:SAMPLE + id: 187 + +sample_188: + type: NAUDIO:V0:SAMPLE + id: 188 + +sample_189: + type: NAUDIO:V0:SAMPLE + id: 189 + +sample_190: + type: NAUDIO:V0:SAMPLE + id: 190 + +sample_191: + type: NAUDIO:V0:SAMPLE + id: 191 + +sample_192: + type: NAUDIO:V0:SAMPLE + id: 192 + +sample_193: + type: NAUDIO:V0:SAMPLE + id: 193 + +sample_194: + type: NAUDIO:V0:SAMPLE + id: 194 + +sample_195: + type: NAUDIO:V0:SAMPLE + id: 195 + +sample_196: + type: NAUDIO:V0:SAMPLE + id: 196 + +sample_197: + type: NAUDIO:V0:SAMPLE + id: 197 + +sample_198: + type: NAUDIO:V0:SAMPLE + id: 198 + +sample_199: + type: NAUDIO:V0:SAMPLE + id: 199 + +sample_200: + type: NAUDIO:V0:SAMPLE + id: 200 + +sample_201: + type: NAUDIO:V0:SAMPLE + id: 201 \ No newline at end of file diff --git a/yamls/us/sound/sequences.yml b/yamls/us/sound/sequences.yml new file mode 100644 index 000000000..d34c7a86c --- /dev/null +++ b/yamls/us/sound/sequences.yml @@ -0,0 +1,239 @@ +seq_00: + type: NAUDIO:V0:SEQUENCE + id: 0 + size: 0x2830 + offset: 0xBC6060 + banks: + - sound/banks/bank_0 + +title_screen: + type: NAUDIO:V0:SEQUENCE + id: 1 + size: 0x1B30 + offset: 0xBC8890 + banks: + - sound/banks/bank_1 + +main_menu: + type: NAUDIO:V0:SEQUENCE + id: 2 + size: 0x0D60 + offset: 0xBCA3C0 + banks: + - sound/banks/bank_2 + +raceways_wario_stadium: + type: NAUDIO:V0:SEQUENCE + id: 3 + size: 0x1A10 + offset: 0xBCB120 + banks: + - sound/banks/bank_3 + +moo_moo_fame_yoshi_valley: + type: NAUDIO:V0:SEQUENCE + id: 4 + size: 0x1CA0 + offset: 0xBCCB30 + banks: + - sound/banks/bank_4 + +choco_mountain: + type: NAUDIO:V0:SEQUENCE + id: 5 + size: 0x1F70 + offset: 0xBCE7D0 + banks: + - sound/banks/bank_5 + +koopa_troopa_beach: + type: NAUDIO:V0:SEQUENCE + id: 6 + size: 0x1EE0 + offset: 0xBD0740 + banks: + - sound/banks/bank_6 + +banshee_boardwalk: + type: NAUDIO:V0:SEQUENCE + id: 7 + size: 0x16D0 + offset: 0xBD2620 + banks: + - sound/banks/bank_7 + +seq_08: + type: NAUDIO:V0:SEQUENCE + id: 8 + size: 0x23D0 + offset: 0xBD3CF0 + banks: + - sound/banks/bank_8 + +seq_09: + type: NAUDIO:V0:SEQUENCE + id: 9 + size: 0x1800 + offset: 0xBD60C0 + banks: + - sound/banks/bank_9 + +kalimari_desert: + type: NAUDIO:V0:SEQUENCE + id: 10 + size: 0x1AE0 + offset: 0xBD78C0 + banks: + - sound/banks/bank_10 + +start_grid_gp_vs: + type: NAUDIO:V0:SEQUENCE + id: 11 + size: 0x05F0 + offset: 0xBD93A0 + banks: + - sound/banks/bank_11 + +final_lap_fanfare: + type: NAUDIO:V0:SEQUENCE + id: 12 + size: 0x03D0 + offset: 0xBD9990 + banks: + - sound/banks/bank_11 + +finish_1st_place: + type: NAUDIO:V0:SEQUENCE + id: 13 + size: 0x0360 + offset: 0xBD9D60 + banks: + - sound/banks/bank_11 + +finish_2nd_4th_place: + type: NAUDIO:V0:SEQUENCE + id: 14 + size: 0x02E0 + offset: 0xBDA0C0 + banks: + - sound/banks/bank_11 + +finish_5th_8th_place: + type: NAUDIO:V0:SEQUENCE + id: 15 + size: 0x04C0 + offset: 0xBDA3A0 + banks: + - sound/banks/bank_11 + +seq_10: + type: NAUDIO:V0:SEQUENCE + id: 16 + size: 0x1410 + offset: 0xBDA860 + banks: + - sound/banks/bank_12 + +star_jingle: + type: NAUDIO:V0:SEQUENCE + id: 17 + size: 0x06E0 + offset: 0xBDBC70 + banks: + - sound/banks/bank_14 + +rainbow_road: + type: NAUDIO:V0:SEQUENCE + id: 18 + size: 0x32F0 + offset: 0xBDC350 + banks: + - sound/banks/bank_15 + +maybe_boo_item: + type: NAUDIO:V0:SEQUENCE + id: 19 + size: 0x06C0 + offset: 0xBDF640 + banks: + - sound/banks/bank_16 + +game_over: + type: NAUDIO:V0:SEQUENCE + id: 20 + size: 0x04B0 + offset: 0xBDFD00 + banks: + - sound/banks/bank_11 + +toads_turnpike: + type: NAUDIO:V0:SEQUENCE + id: 21 + size: 0x1160 + offset: 0xBE01B0 + banks: + - sound/banks/bank_17 + +start_gird_time_attack: + type: NAUDIO:V0:SEQUENCE + id: 22 + size: 0x0310 + offset: 0xBE1310 + banks: + - sound/banks/bank_11 + +vs_battle_results: + type: NAUDIO:V0:SEQUENCE + id: 23 + size: 0x12B0 + offset: 0xBE1620 + banks: + - sound/banks/bank_13 + +losing_results: + type: NAUDIO:V0:SEQUENCE + id: 24 + size: 0x0600 + offset: 0xBE28D0 + banks: + - sound/banks/bank_12 + +battle_arenas: + type: NAUDIO:V0:SEQUENCE + id: 25 + size: 0x16E0 + offset: 0xBE2ED0 + banks: + - sound/banks/bank_18 + +award_ceremony_buildup: + type: NAUDIO:V0:SEQUENCE + id: 26 + size: 0x0AD0 + offset: 0xBE45B0 + banks: + - sound/banks/bank_19 + +award_ceremony_1st_3rd: + type: NAUDIO:V0:SEQUENCE + id: 27 + size: 0x0C80 + offset: 0xBE5080 + banks: + - sound/banks/bank_19 + +staff_roll: + type: NAUDIO:V0:SEQUENCE + id: 28 + size: 0x2750 + offset: 0xBE5D00 + banks: + - sound/banks/bank_20 + +award_ceremony_4th_8th: + type: NAUDIO:V0:SEQUENCE + id: 29 + size: 0x0C80 + offset: 0xBE8450 + banks: + - sound/banks/bank_19 \ No newline at end of file