Audio is now compiling but crashing yay

This commit is contained in:
KiritoDv
2024-11-29 11:00:09 -06:00
parent a4a03820b4
commit 7875424607
34 changed files with 2489 additions and 264 deletions
+12
View File
@@ -0,0 +1,12 @@
#pragma once
#include <thread>
#include <condition_variable>
static struct {
std::thread thread;
std::condition_variable cv_to_thread, cv_from_thread;
std::mutex mutex;
bool running;
bool processing;
} audio;
+2 -2
View File
@@ -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;
+6 -22
View File
@@ -3,6 +3,7 @@
#include <libultraship.h>
#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
+29 -110
View File
@@ -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 <string.h>
@@ -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;
+1 -2
View File
@@ -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);
+526 -50
View File
@@ -1,7 +1,13 @@
#include <libultraship.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#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);
}
+87 -7
View File
@@ -1,11 +1,91 @@
#ifndef MIXER_H
#define MIXER_H
#pragma once
#include <libultraship.h>
void aDownsampleHalfImpl(uint16_t n_samples, uint16_t in_addr, uint16_t out_addr);
#include <stdbool.h>
#include <stdint.h>
#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)
+9 -9
View File
@@ -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 = &note->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;
+34
View File
@@ -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;
+17 -11
View File
@@ -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) {
+9 -9
View File
@@ -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 <libultra/abi.h>
#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;
+10 -12
View File
@@ -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
+1 -1
View File
@@ -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) {
+186 -18
View File
@@ -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 <BlobFactory.h>
#include <VertexFactory.h>
#include <LightFactory.h>
#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<Fast::Fast3dWindow>(Ship::Context::GetInstance()->GetWindow());
@@ -65,13 +70,18 @@ GameEngine::GameEngine() {
this->context->InitGfxDebugger();
auto loader = context->GetResourceManager()->GetResourceLoader();
loader->RegisterResourceFactory(std::make_shared<SM64::AudioBankFactoryV0>(), RESOURCE_FORMAT_BINARY,
"AudioBank", static_cast<uint32_t>(SF64::ResourceType::Bank), 0);
loader->RegisterResourceFactory(std::make_shared<SM64::AudioSampleFactoryV0>(), RESOURCE_FORMAT_BINARY,
"AudioSample", static_cast<uint32_t>(SF64::ResourceType::Sample), 0);
loader->RegisterResourceFactory(std::make_shared<SM64::AudioSequenceFactoryV0>(), RESOURCE_FORMAT_BINARY,
"AudioSequence", static_cast<uint32_t>(SF64::ResourceType::Sequence), 0);
loader->RegisterResourceFactory(std::make_shared<SF64::ResourceFactoryBinaryVec3fV0>(), RESOURCE_FORMAT_BINARY,
"Vec3f", static_cast<uint32_t>(SF64::ResourceType::Vec3f), 0);
loader->RegisterResourceFactory(std::make_shared<SF64::ResourceFactoryBinaryVec3sV0>(), RESOURCE_FORMAT_BINARY,
"Vec3s", static_cast<uint32_t>(SF64::ResourceType::Vec3s), 0);
loader->RegisterResourceFactory(std::make_shared<SF64::ResourceFactoryBinaryGenericArrayV0>(),
RESOURCE_FORMAT_BINARY, "GenericArray",
static_cast<uint32_t>(SF64::ResourceType::GenericArray), 0);
loader->RegisterResourceFactory(std::make_shared<SF64::ResourceFactoryBinaryGenericArrayV0>(), RESOURCE_FORMAT_BINARY,
"GenericArray", static_cast<uint32_t>(SF64::ResourceType::GenericArray), 0);
loader->RegisterResourceFactory(std::make_shared<LUS::ResourceFactoryBinaryTextureV0>(), RESOURCE_FORMAT_BINARY,
"Texture", static_cast<uint32_t>(LUS::ResourceType::Texture), 0);
loader->RegisterResourceFactory(std::make_shared<LUS::ResourceFactoryBinaryTextureV1>(), RESOURCE_FORMAT_BINARY,
@@ -92,29 +102,27 @@ GameEngine::GameEngine() {
"KartAI", static_cast<uint32_t>(MK64::ResourceType::KartAI), 0);
loader->RegisterResourceFactory(std::make_shared<MK64::ResourceFactoryBinaryCourseVtxV0>(), RESOURCE_FORMAT_BINARY,
"CourseVtx", static_cast<uint32_t>(MK64::ResourceType::CourseVertex), 0);
loader->RegisterResourceFactory(std::make_shared<MK64::ResourceFactoryBinaryTrackSectionsV0>(),
RESOURCE_FORMAT_BINARY, "TrackSections",
static_cast<uint32_t>(MK64::ResourceType::TrackSection), 0);
loader->RegisterResourceFactory(std::make_shared<MK64::ResourceFactoryBinaryTrackWaypointsV0>(),
RESOURCE_FORMAT_BINARY, "Waypoints",
static_cast<uint32_t>(MK64::ResourceType::Waypoints), 0);
loader->RegisterResourceFactory(std::make_shared<MK64::ResourceFactoryBinaryActorSpawnDataV0>(),
RESOURCE_FORMAT_BINARY, "SpawnData",
static_cast<uint32_t>(MK64::ResourceType::SpawnData), 0);
loader->RegisterResourceFactory(std::make_shared<MK64::ResourceFactoryBinaryUnkActorSpawnDataV0>(),
RESOURCE_FORMAT_BINARY, "UnkSpawnData",
static_cast<uint32_t>(MK64::ResourceType::UnkSpawnData), 0);
loader->RegisterResourceFactory(std::make_shared<MK64::ResourceFactoryBinaryTrackSectionsV0>(), RESOURCE_FORMAT_BINARY,
"TrackSections", static_cast<uint32_t>(MK64::ResourceType::TrackSection), 0);
loader->RegisterResourceFactory(std::make_shared<MK64::ResourceFactoryBinaryTrackWaypointsV0>(), RESOURCE_FORMAT_BINARY,
"Waypoints", static_cast<uint32_t>(MK64::ResourceType::Waypoints), 0);
loader->RegisterResourceFactory(std::make_shared<MK64::ResourceFactoryBinaryActorSpawnDataV0>(), RESOURCE_FORMAT_BINARY,
"SpawnData", static_cast<uint32_t>(MK64::ResourceType::SpawnData), 0);
loader->RegisterResourceFactory(std::make_shared<MK64::ResourceFactoryBinaryUnkActorSpawnDataV0>(), RESOURCE_FORMAT_BINARY,
"UnkSpawnData", static_cast<uint32_t>(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<std::mutex> Lock(audio.mutex);
while (!audio.processing && audio.running) {
audio.cv_to_thread.wait(Lock);
}
if (!audio.running) {
break;
}
}
std::unique_lock<std::mutex> 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<std::mutex> Lock(audio.mutex);
audio.processing = true;
}
audio.cv_to_thread.notify_one();
}
void GameEngine::EndAudioFrame(){
{
std::unique_lock<std::mutex> 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<CtlEntry *>(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<AudioSequenceData *>(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<CtlEntry *>(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<AudioSequenceData *>(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;
+25
View File
@@ -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<Ship::Context> context;
std::vector<CtlEntry*> banksTable;
std::vector<std::string> sequenceTable;
std::vector<AudioSequenceData*> audioSequenceTable;
std::unordered_map<std::string, uint8_t> 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);
+8 -8
View File
@@ -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();
@@ -0,0 +1,96 @@
#include "AudioBankFactory.h"
#include "../type/AudioBank.h"
#include "spdlog/spdlog.h"
#include "resourcebridge.h"
#include "ResourceUtil.h"
std::shared_ptr<Ship::IResource> SM64::AudioBankFactoryV0::ReadResource(std::shared_ptr<Ship::File> file) {
if (!FileHasValidFormatAndReader(file)) {
return nullptr;
}
std::shared_ptr<AudioBank> bank = std::make_shared<AudioBank>(file->InitData);
auto reader = std::get<std::shared_ptr<Ship::BinaryReader>>(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<AudioBankSample*>(lowSampleName.c_str());
instrument->lowNotesSound.tuning = reader->ReadFloat();
}
if(hasMed){
std::string normalSampleName = reader->ReadString();
instrument->normalNotesSound.sample = LoadChild<AudioBankSample*>(normalSampleName.c_str());
instrument->normalNotesSound.tuning = reader->ReadFloat();
}
if(hasHi){
std::string highSampleName = reader->ReadString();
instrument->highNotesSound.sample = LoadChild<AudioBankSample*>(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<AudioBankSample*>(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;
}
@@ -0,0 +1,11 @@
#pragma once
#include "Resource.h"
#include "ResourceFactoryBinary.h"
namespace SM64 {
class AudioBankFactoryV0 : public Ship::ResourceFactoryBinary {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::File> file) override;
};
}
@@ -0,0 +1,47 @@
#include "AudioSampleFactory.h"
#include <iostream>
#include "../type/AudioSample.h"
#include "spdlog/spdlog.h"
std::shared_ptr<Ship::IResource> SM64::AudioSampleFactoryV0::ReadResource(std::shared_ptr<Ship::File> file) {
if (!FileHasValidFormatAndReader(file)) {
return nullptr;
}
std::shared_ptr<AudioSample> bank = std::make_shared<AudioSample>(file->InitData);
auto reader = std::get<std::shared_ptr<Ship::BinaryReader>>(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<int16_t> 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;
}
@@ -0,0 +1,11 @@
#pragma once
#include "Resource.h"
#include "ResourceFactoryBinary.h"
namespace SM64 {
class AudioSampleFactoryV0 : public Ship::ResourceFactoryBinary {
public:
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::File> file) override;
};
}
@@ -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<Ship::IResource> SM64::AudioSequenceFactoryV0::ReadResource(std::shared_ptr<Ship::File> file) {
if (!FileHasValidFormatAndReader(file)) {
return nullptr;
}
std::shared_ptr<AudioSequence> bank = std::make_shared<AudioSequence>(file->InitData);
auto reader = std::get<std::shared_ptr<Ship::BinaryReader>>(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;
}
@@ -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<Ship::IResource> ReadResource(std::shared_ptr<Ship::File> file) override;
};
}
+9 -2
View File
@@ -3,7 +3,7 @@
#include "resourcebridge.h"
#include "Context.h"
namespace SF64 {
namespace SM64 {
template <typename T> T LoadChild(uint64_t crc) {
auto path = ResourceGetNameByCrc(crc);
if (path == nullptr) {
@@ -12,4 +12,11 @@ template <typename T> T LoadChild(uint64_t crc) {
auto asset = Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(path);
return asset ? static_cast<T>(asset->GetRawPointer()) : nullptr;
}
} // namespace SF64
template <typename T> T LoadChild(const char* path) {
if (path == nullptr) {
return nullptr;
}
auto asset = Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(path);
return asset ? static_cast<T>(asset->GetRawPointer()) : nullptr;
}
}
+11
View File
@@ -0,0 +1,11 @@
#include "AudioBank.h"
namespace SM64 {
CtlEntry* AudioBank::GetPointer() {
return &mData;
}
size_t AudioBank::GetPointerSize() {
return sizeof(mData);
}
}
+59
View File
@@ -0,0 +1,59 @@
#pragma once
#include <cstdint>
#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<CtlEntry> {
public:
using Resource::Resource;
AudioBank() : Resource(std::shared_ptr<Ship::ResourceInitData>()) {}
CtlEntry* GetPointer();
size_t GetPointerSize();
CtlEntry mData;
std::vector<Instrument*> instruments;
std::vector<Drum*> drums;
};
}
+11
View File
@@ -0,0 +1,11 @@
#include "AudioSample.h"
namespace SM64 {
AudioBankSample* AudioSample::GetPointer() {
return &mData;
}
size_t AudioSample::GetPointerSize() {
return sizeof(mData);
}
}
+47
View File
@@ -0,0 +1,47 @@
#pragma once
#include <cstdint>
#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<AudioBankSample> {
public:
using Resource::Resource;
AudioSample() : Resource(std::shared_ptr<Ship::ResourceInitData>()) {}
AudioBankSample* GetPointer();
size_t GetPointerSize();
AudioBankSample mData;
AdpcmLoop loop;
AdpcmBook book;
std::vector<uint8_t> sampleAddr;
};
}
+11
View File
@@ -0,0 +1,11 @@
#include "AudioSequence.h"
namespace SM64 {
AudioSequenceData* AudioSequence::GetPointer() {
return &mData;
}
size_t AudioSequence::GetPointerSize() {
return sizeof(mData);
}
}
+32
View File
@@ -0,0 +1,32 @@
#pragma once
#ifdef __cplusplus
#include <cstdint>
#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<AudioSequenceData> {
public:
using Resource::Resource;
AudioSequence() : Resource(std::shared_ptr<Ship::ResourceInitData>()) {}
AudioSequenceData* GetPointer();
size_t GetPointerSize();
AudioSequenceData mData;
std::vector<uint8_t> banks;
std::vector<uint8_t> sampleData;
};
}
#endif
+4
View File
@@ -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
+83
View File
@@ -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
@@ -13,4 +13,7 @@ header:
size: 0x13840
tbl:
offset: 0x979AA0
size: 0x24C4C0
size: 0x24C4C0
audio_seq_font_table:
{ type: ARRAY, count: 0x80, array_type: u8, offset: 0xBE90E0, symbol: gSeqFontTableInit }
+807
View File
@@ -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
+239
View File
@@ -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