mirror of
https://github.com/HarbourMasters/Starship
synced 2026-05-23 06:54:39 -04:00
496 lines
17 KiB
C
496 lines
17 KiB
C
#include "sys.h"
|
|
#include "sf64audio_provisional.h"
|
|
#include "audiothread_cmd.h"
|
|
|
|
void AudioThread_ProcessCmds(u32 msg);
|
|
void AudioThread_SetFadeOutTimer(s32 seqPlayId, s32 fadeTime);
|
|
void AudioThread_SetFadeInTimer(s32 seqPlayId, s32 fadeTime);
|
|
|
|
OSMesgQueue sAudioTaskStartQueue;
|
|
OSMesgQueue sThreadCmdProcQueue;
|
|
OSMesgQueue sAudioSpecQueue;
|
|
OSMesgQueue sAudioResetQueue;
|
|
AudioCmd gThreadCmdBuffer[256];
|
|
OSMesg sAudioTaskStartMsg[1];
|
|
OSMesg sThreadCmdProcMsg[4];
|
|
OSMesg sAudioSpecMsg[1];
|
|
OSMesg sAudioResetMsg[1];
|
|
|
|
u8 gThreadCmdWritePos = 0;
|
|
u8 gThreadCmdReadPos = 0;
|
|
OSMesgQueue* gAudioTaskStartQueue = &sAudioTaskStartQueue;
|
|
OSMesgQueue* gThreadCmdProcQueue = &sThreadCmdProcQueue;
|
|
OSMesgQueue* gAudioSpecQueue = &sAudioSpecQueue;
|
|
OSMesgQueue* gAudioResetQueue = &sAudioResetQueue;
|
|
|
|
static const char devstr0[] = "DAC:Lost 1 Frame.\n";
|
|
static const char devstr1[] = "DMA: Request queue over.( %d )\n";
|
|
static const char devstr2[] = "Spec Change Override. %d -> %d\n";
|
|
static const char devstr3[] = "Audio:now-max tasklen is %d / %d\n";
|
|
static const char devstr4[] = "Audio:Warning:ABI Tasklist length over (%d)\n";
|
|
static const char devstr5[] = "BGLOAD Start %d\n";
|
|
static const char devstr6[] = "Error: OverFlow Your Request\n";
|
|
static const char devstr7[] = "---AudioSending (%d->%d) \n";
|
|
static const char devstr8[] = "AudioSend: %d -> %d (%d)\n";
|
|
static const char devstr9[] = "Continue Port\n";
|
|
static const char devstr10[] = "%d -> %d\n";
|
|
static const char devstr11[] = "Sync-Frame Break. (Remain %d)\n";
|
|
static const char devstr12[] = "Undefined Port Command %d\n";
|
|
static const char devstr13[] = "specchg conjunction error (Msg:%d Cur:%d)\n";
|
|
static const char devstr14[] = "Error : Queue is not empty ( %x ) \n";
|
|
|
|
void AudioThread_CreateNextAudioBuffer(s16 *samples, u32 num_samples) {
|
|
static s32 gMaxAbiCmdCnt = 128;
|
|
static SPTask* gWaitingAudioTask = NULL;
|
|
s32 abiCmdCount;
|
|
u32 specId;
|
|
OSMesg msg;
|
|
|
|
gAudioTaskCountQ++;
|
|
if ((gAudioTaskCountQ % gAudioBufferParams.count) != 0) {
|
|
return gWaitingAudioTask;
|
|
}
|
|
osSendMesg(gAudioTaskStartQueue, OS_MESG_32(gAudioTaskCountQ), OS_MESG_NOBLOCK);
|
|
gAudioTaskIndexQ ^= 1;
|
|
|
|
gCurAudioFrameDmaCount = 0;
|
|
AudioLoad_DecreaseSampleDmaTtls();
|
|
// AudioLoad_ProcessLoads(gAudioResetStep);
|
|
|
|
if (MQ_GET_MESG(gAudioSpecQueue, &specId)) {
|
|
if (gAudioResetStep == 0) {
|
|
gAudioResetStep = 5;
|
|
}
|
|
gAudioSpecId = specId;
|
|
}
|
|
|
|
if ((gAudioResetStep != 0) && (AudioHeap_ResetStep() == 0)) {
|
|
if (gAudioResetStep == 0) {
|
|
osSendMesg(gAudioResetQueue, OS_MESG_32((s32) gAudioSpecId), OS_MESG_NOBLOCK);
|
|
}
|
|
gWaitingAudioTask = NULL;
|
|
return NULL;
|
|
}
|
|
|
|
if (gAudioResetTimer > 16) {
|
|
return NULL;
|
|
}
|
|
if (gAudioResetTimer != 0) {
|
|
gAudioResetTimer++;
|
|
}
|
|
|
|
gAudioCurTask = &gAudioRspTasks[gAudioTaskIndexQ];
|
|
gCurAbiCmdBuffer = gAbiCmdBuffs[gAudioTaskIndexQ];
|
|
|
|
while (MQ_GET_MESG(gThreadCmdProcQueue, &msg)) {
|
|
AudioThread_ProcessCmds(msg.data32);
|
|
}
|
|
|
|
gCurAbiCmdBuffer = func_80009B64(gCurAbiCmdBuffer, &abiCmdCount, samples, num_samples);
|
|
gAudioRandom = osGetCount() * (gAudioRandom + gAudioTaskCountQ);
|
|
|
|
gAudioCurTask->msg = OS_MESG_PTR(NULL);
|
|
|
|
if (gMaxAbiCmdCnt < abiCmdCount) {
|
|
gMaxAbiCmdCnt = abiCmdCount;
|
|
}
|
|
}
|
|
|
|
SPTask* AudioThread_CreateTask() {
|
|
static s32 gMaxAbiCmdCnt = 128;
|
|
static SPTask* gWaitingAudioTask = NULL;
|
|
u32 aiSamplesLeft;
|
|
s32 abiCmdCount;
|
|
s32 aiBuffIndex;
|
|
s32 pad48;
|
|
OSTask_t* task;
|
|
u16* aiBuffer;
|
|
s32 pad3C;
|
|
u32 specId;
|
|
u32 msg;
|
|
s32 pad30;
|
|
|
|
gAudioTaskCountQ++;
|
|
if ((gAudioTaskCountQ % gAudioBufferParams.count) != 0) {
|
|
return gWaitingAudioTask;
|
|
}
|
|
osSendMesg(gAudioTaskStartQueue, OS_MESG_32(gAudioTaskCountQ), OS_MESG_NOBLOCK);
|
|
gAudioTaskIndexQ ^= 1;
|
|
gCurAiBuffIndex++;
|
|
gCurAiBuffIndex %= 3;
|
|
|
|
aiBuffIndex = (gCurAiBuffIndex + 1) % 3;
|
|
aiSamplesLeft = osAiGetLength() / 4;
|
|
|
|
if ((gAudioResetTimer < 16) && (gAiBuffLengths[aiBuffIndex] != 0)) {
|
|
osAiSetNextBuffer(gAiBuffers[aiBuffIndex], gAiBuffLengths[aiBuffIndex] * 4);
|
|
}
|
|
|
|
if (gCurAudioFrameDmaCount && gCurAudioFrameDmaCount) {} //! FAKE ?
|
|
|
|
gCurAudioFrameDmaCount = 0;
|
|
AudioLoad_DecreaseSampleDmaTtls();
|
|
AudioLoad_ProcessLoads(gAudioResetStep);
|
|
|
|
if (MQ_GET_MESG(gAudioSpecQueue, &specId)) {
|
|
if (gAudioResetStep == 0) {
|
|
gAudioResetStep = 5;
|
|
}
|
|
gAudioSpecId = specId;
|
|
}
|
|
|
|
if ((gAudioResetStep != 0) && (AudioHeap_ResetStep() == 0)) {
|
|
if (gAudioResetStep == 0) {
|
|
osSendMesg(gAudioResetQueue, OS_MESG_32((s32) gAudioSpecId), OS_MESG_NOBLOCK);
|
|
}
|
|
gWaitingAudioTask = NULL;
|
|
return NULL;
|
|
}
|
|
|
|
if (gAudioResetTimer > 16) {
|
|
return NULL;
|
|
}
|
|
if (gAudioResetTimer != 0) {
|
|
gAudioResetTimer++;
|
|
}
|
|
|
|
gAudioCurTask = &gAudioRspTasks[gAudioTaskIndexQ];
|
|
gCurAbiCmdBuffer = gAbiCmdBuffs[gAudioTaskIndexQ];
|
|
aiBuffIndex = gCurAiBuffIndex;
|
|
aiBuffer = gAiBuffers[aiBuffIndex];
|
|
gAiBuffLengths[aiBuffIndex] = ALIGN16_ALT(gAudioBufferParams.samplesPerFrameTarget - aiSamplesLeft + 0x80);
|
|
|
|
if (gAiBuffLengths[aiBuffIndex] < gAudioBufferParams.minAiBufferLength) {
|
|
gAiBuffLengths[aiBuffIndex] = gAudioBufferParams.minAiBufferLength;
|
|
}
|
|
if (gAiBuffLengths[aiBuffIndex] > gAudioBufferParams.maxAiBufferLength) {
|
|
gAiBuffLengths[aiBuffIndex] = gAudioBufferParams.maxAiBufferLength;
|
|
}
|
|
while (MQ_GET_MESG(gThreadCmdProcQueue, &msg)) {
|
|
AudioThread_ProcessCmds(msg);
|
|
}
|
|
gCurAbiCmdBuffer = func_80009B64(gCurAbiCmdBuffer, &abiCmdCount, aiBuffer, gAiBuffLengths[aiBuffIndex]);
|
|
gAudioRandom = osGetCount() * (gAudioRandom + gAudioTaskCountQ);
|
|
gAudioRandom = gAiBuffers[aiBuffIndex][gAudioTaskCountQ & 0xFF] + gAudioRandom;
|
|
|
|
aiBuffIndex = gAudioTaskIndexQ;
|
|
|
|
gAudioCurTask->msg = OS_MESG_PTR(NULL);
|
|
|
|
task = &gAudioCurTask->task.t;
|
|
|
|
task->type = 2;
|
|
task->flags = 0;
|
|
// task->ucode_boot = rspbootTextStart;
|
|
// task->ucode_boot_size = (uintptr_t) rspbootTextEnd - (uintptr_t) rspbootTextStart;
|
|
//
|
|
// task->ucode = aspMainTextStart;
|
|
// task->ucode_data = aspMainDataStart;
|
|
// task->ucode_size = SP_UCODE_SIZE;
|
|
// task->ucode_data_size = (aspMainDataEnd - aspMainDataStart) * 8;
|
|
|
|
task->dram_stack = NULL;
|
|
task->dram_stack_size = 0;
|
|
|
|
task->output_buff = NULL;
|
|
task->output_buff_size = NULL;
|
|
if (1) {}
|
|
task->data_ptr = (u64*) gAbiCmdBuffs[aiBuffIndex];
|
|
task->data_size = abiCmdCount * sizeof(Acmd);
|
|
|
|
task->yield_data_ptr = NULL;
|
|
task->yield_data_size = 0;
|
|
|
|
if (gMaxAbiCmdCnt < abiCmdCount) {
|
|
gMaxAbiCmdCnt = abiCmdCount;
|
|
}
|
|
|
|
if (gAudioBufferParams.count == 1) {
|
|
return gAudioCurTask;
|
|
} else {
|
|
gWaitingAudioTask = gAudioCurTask;
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
void AudioThread_ProcessGlobalCmd(AudioCmd* cmd) {
|
|
s32 i;
|
|
|
|
switch (cmd->op) {
|
|
case AUDIOCMD_OP_GLOBAL_SYNC_LOAD_SEQ_PARTS:
|
|
AudioLoad_SyncLoadSeqParts(cmd->arg1, 3);
|
|
break;
|
|
case AUDIOCMD_OP_GLOBAL_INIT_SEQPLAYER:
|
|
case AUDIOCMD_OP_GLOBAL_INIT_SEQPLAYER_ALT:
|
|
AudioLoad_SyncInitSeqPlayer(cmd->arg0, cmd->arg1, cmd->arg2);
|
|
AudioThread_SetFadeInTimer(cmd->arg0, (uintptr_t) cmd->data);
|
|
break;
|
|
case AUDIOCMD_OP_GLOBAL_DISABLE_SEQPLAYER:
|
|
if (gSeqPlayers[cmd->arg0].enabled) {
|
|
if (cmd->asInt == 0) {
|
|
func_800144E4(&gSeqPlayers[cmd->arg0]);
|
|
} else {
|
|
AudioThread_SetFadeOutTimer(cmd->arg0, cmd->asInt);
|
|
}
|
|
}
|
|
break;
|
|
case AUDIOCMD_OP_GLOBAL_UNK_84:
|
|
break;
|
|
case AUDIOCMD_OP_GLOBAL_SET_SOUND_MODE:
|
|
gAudioSoundMode = cmd->asUInt;
|
|
break;
|
|
case AUDIOCMD_OP_GLOBAL_MUTE:
|
|
for (i = 0; i < ARRAY_COUNT(gSeqPlayers); i++) {
|
|
SequencePlayer* seqplayer = &gSeqPlayers[i];
|
|
|
|
seqplayer->muted = true;
|
|
seqplayer->recalculateVolume = true;
|
|
}
|
|
break;
|
|
case AUDIOCMD_OP_GLOBAL_UNMUTE:
|
|
if (cmd->asUInt == 1) {
|
|
for (i = 0; i < gNumNotes; i++) {
|
|
Note* note = &gNotes[i];
|
|
NoteSubEu* noteSub = ¬e->noteSubEu;
|
|
|
|
if ((noteSub->bitField0.enabled) && (note->playbackState.unk_04 == 0) &&
|
|
(note->playbackState.parentLayer != NO_LAYER) &&
|
|
(note->playbackState.parentLayer->channel->muteBehavior & 8)) {
|
|
noteSub->bitField0.finished = true;
|
|
}
|
|
}
|
|
}
|
|
for (i = 0; i < ARRAY_COUNT(gSeqPlayers); i++) {
|
|
SequencePlayer* seqplayer = &gSeqPlayers[i];
|
|
|
|
seqplayer->muted = false;
|
|
seqplayer->recalculateVolume = true;
|
|
}
|
|
break;
|
|
case AUDIOCMD_OP_GLOBAL_SYNC_LOAD_INSTRUMENT:
|
|
AudioLoad_SyncLoadInstrument(cmd->arg0, cmd->arg1, cmd->arg2);
|
|
break;
|
|
case AUDIOCMD_OP_GLOBAL_ASYNC_LOAD_SAMPLE_BANK:
|
|
AudioLoad_AsyncLoadSampleBank(cmd->arg0, cmd->arg1, cmd->arg2, &gExternalLoadQueue);
|
|
break;
|
|
case AUDIOCMD_OP_GLOBAL_ASYNC_LOAD_FONT:
|
|
AudioLoad_AsyncLoadSeq(cmd->arg0, cmd->arg1, cmd->arg2, &gExternalLoadQueue);
|
|
break;
|
|
case AUDIOCMD_OP_GLOBAL_DISCARD_SEQ_FONTS:
|
|
AudioLoad_DiscardSeqFonts(cmd->arg1);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void AudioThread_SetFadeOutTimer(s32 seqPlayId, s32 fadeTime) {
|
|
if (fadeTime == 0) {
|
|
fadeTime = 1;
|
|
}
|
|
|
|
gSeqPlayers[seqPlayId].state = 2;
|
|
gSeqPlayers[seqPlayId].fadeTimer = fadeTime;
|
|
gSeqPlayers[seqPlayId].fadeVelocity = -(gSeqPlayers[seqPlayId].fadeVolume / fadeTime);
|
|
}
|
|
|
|
void AudioThread_SetFadeInTimer(s32 seqPlayId, s32 fadeTime) {
|
|
if (fadeTime != 0) {
|
|
gSeqPlayers[seqPlayId].state = 1;
|
|
gSeqPlayers[seqPlayId].fadeTimerUnkEu = fadeTime;
|
|
gSeqPlayers[seqPlayId].fadeTimer = fadeTime;
|
|
gSeqPlayers[seqPlayId].fadeVolume = 0.0f;
|
|
gSeqPlayers[seqPlayId].fadeVelocity = 0.0f;
|
|
}
|
|
}
|
|
|
|
void AudioThread_InitQueues(void) {
|
|
gThreadCmdWritePos = 0;
|
|
gThreadCmdReadPos = 0;
|
|
osCreateMesgQueue(gAudioTaskStartQueue, sAudioTaskStartMsg, 1);
|
|
osCreateMesgQueue(gThreadCmdProcQueue, sThreadCmdProcMsg, 4);
|
|
osCreateMesgQueue(gAudioSpecQueue, sAudioSpecMsg, 1);
|
|
osCreateMesgQueue(gAudioResetQueue, sAudioResetMsg, 1);
|
|
}
|
|
|
|
void AudioThread_QueueCmd(u32 opArgs, void** data) {
|
|
AudioCmd* audioCmd = &gThreadCmdBuffer[gThreadCmdWritePos & 0xFF];
|
|
|
|
audioCmd->opArgs = opArgs;
|
|
audioCmd->data = *data;
|
|
|
|
gThreadCmdWritePos++;
|
|
if (gThreadCmdWritePos == gThreadCmdReadPos) {
|
|
gThreadCmdWritePos--;
|
|
}
|
|
}
|
|
|
|
void AudioThread_QueueCmdF32(u32 opArgs, f32 val) {
|
|
AudioThread_QueueCmd(opArgs, (void**) &val);
|
|
}
|
|
|
|
void AudioThread_QueueCmdS32(u32 opArgs, u32 val) {
|
|
AudioThread_QueueCmd(opArgs, (void**) &val);
|
|
}
|
|
|
|
void AudioThread_QueueCmdS8(u32 opArgs, s8 val) {
|
|
s32 data = val << 0x18;
|
|
|
|
AudioThread_QueueCmd(opArgs, (void**) &data);
|
|
}
|
|
|
|
void AudioThread_ScheduleProcessCmds(void) {
|
|
static s32 D_800C7C70 = 0;
|
|
s32 msg;
|
|
|
|
if (D_800C7C70 < (u8) (gThreadCmdWritePos - gThreadCmdReadPos + 0x100)) {
|
|
D_800C7C70 = (u8) (gThreadCmdWritePos - gThreadCmdReadPos + 0x100);
|
|
}
|
|
msg = (((gThreadCmdReadPos & 0xFF) << 8) | (gThreadCmdWritePos & 0xFF));
|
|
osSendMesg32(gThreadCmdProcQueue, msg, OS_MESG_NOBLOCK);
|
|
gThreadCmdReadPos = gThreadCmdWritePos;
|
|
}
|
|
|
|
void AudioThread_ResetCmdQueue(void) {
|
|
gThreadCmdReadPos = gThreadCmdWritePos;
|
|
}
|
|
|
|
void AudioThread_ProcessCmds(u32 msg) {
|
|
static u8 gCurCmdReadPos = 0;
|
|
static u8 gThreadCmdQueueFinished = false;
|
|
AudioCmd* cmd;
|
|
SequenceChannel* channel;
|
|
SequencePlayer* player;
|
|
u8 writePos;
|
|
|
|
if (!gThreadCmdQueueFinished) {
|
|
gCurCmdReadPos = (msg >> 8) & 0xFF;
|
|
}
|
|
writePos = msg & 0xFF;
|
|
while (true) {
|
|
if (gCurCmdReadPos == writePos) {
|
|
gThreadCmdQueueFinished = 0;
|
|
break;
|
|
}
|
|
cmd = &gThreadCmdBuffer[gCurCmdReadPos & 0xFF];
|
|
gCurCmdReadPos++;
|
|
if (cmd->op == AUDIOCMD_OP_GLOBAL_STOP_AUDIOCMDS) {
|
|
gThreadCmdQueueFinished = true;
|
|
break;
|
|
}
|
|
if ((cmd->op & 0xF0) == 0xF0) {
|
|
AudioThread_ProcessGlobalCmd(cmd);
|
|
} else if (cmd->arg0 < ARRAY_COUNT(gSeqPlayers)) {
|
|
player = &gSeqPlayers[cmd->arg0];
|
|
if (cmd->op & 0x80) {
|
|
AudioThread_ProcessGlobalCmd(cmd);
|
|
} else if (cmd->op & 0x40) {
|
|
switch (cmd->op) {
|
|
case AUDIOCMD_OP_SEQPLAYER_FADE_VOLUME_SCALE:
|
|
if (player->fadeVolumeMod != cmd->asFloat) {
|
|
player->fadeVolumeMod = cmd->asFloat;
|
|
player->recalculateVolume = true;
|
|
}
|
|
break;
|
|
case AUDIOCMD_OP_SEQPLAYER_SET_TEMPO:
|
|
player->tempo = cmd->asInt * 48;
|
|
break;
|
|
case AUDIOCMD_OP_SEQPLAYER_SET_TRANSPOSITION:
|
|
player->transposition = cmd->asSbyte;
|
|
break;
|
|
case 0x46: // AUDIOCMD_OP_SEQPLAYER_SET_IO?
|
|
player->unk_07[cmd->arg2] = cmd->asSbyte;
|
|
break;
|
|
}
|
|
} else if ((player->enabled) && (cmd->arg1 < 16)) {
|
|
channel = player->channels[cmd->arg1];
|
|
if (IS_SEQUENCE_CHANNEL_VALID(channel)) {
|
|
switch (cmd->op) {
|
|
case AUDIOCMD_OP_CHANNEL_SET_VOL_SCALE:
|
|
if (channel->volumeMod != cmd->asFloat) {
|
|
channel->volumeMod = cmd->asFloat;
|
|
channel->changes.s.volume = true;
|
|
}
|
|
break;
|
|
case AUDIOCMD_OP_CHANNEL_SET_VOL:
|
|
if (channel->volume != cmd->asFloat) {
|
|
channel->volume = cmd->asFloat;
|
|
channel->changes.s.volume = true;
|
|
}
|
|
break;
|
|
case AUDIOCMD_OP_CHANNEL_SET_PAN:
|
|
if (channel->newPan != cmd->asSbyte) {
|
|
channel->newPan = cmd->asSbyte;
|
|
channel->changes.s.pan = true;
|
|
}
|
|
break;
|
|
case AUDIOCMD_OP_CHANNEL_SET_FREQ_SCALE:
|
|
if (channel->freqMod != cmd->asFloat) {
|
|
channel->freqMod = cmd->asFloat;
|
|
channel->changes.s.freqMod = true;
|
|
}
|
|
break;
|
|
case AUDIOCMD_OP_CHANNEL_SET_REVERB_VOLUME:
|
|
if (channel->targetReverbVol != cmd->asSbyte) {
|
|
channel->targetReverbVol = cmd->asSbyte;
|
|
}
|
|
break;
|
|
case AUDIOCMD_OP_CHANNEL_SET_IO:
|
|
if (cmd->arg2 < 8) {
|
|
channel->seqScriptIO[cmd->arg2] = cmd->asSbyte;
|
|
}
|
|
break;
|
|
case AUDIOCMD_OP_CHANNEL_SET_MUTE:
|
|
channel->muted = cmd->asSbyte;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
cmd->op = 0;
|
|
}
|
|
}
|
|
|
|
u32 AudioThread_GetAsyncLoadStatus(u32* outData) {
|
|
u32 loadStatus;
|
|
|
|
if (!MQ_GET_MESG(&gExternalLoadQueue, &loadStatus)) {
|
|
*outData = 0;
|
|
return 0;
|
|
}
|
|
*outData = loadStatus & 0xFFFFFF;
|
|
return loadStatus >> 0x18;
|
|
}
|
|
|
|
u8* AudioThread_GetFontsForSequence(s32 seqId, u32* outNumFonts) {
|
|
return AudioLoad_GetFontsForSequence(seqId, outNumFonts);
|
|
}
|
|
|
|
bool AudioThread_ResetComplete(void) {
|
|
s32 pad;
|
|
s32 sp18;
|
|
|
|
if (!MQ_GET_MESG(gAudioResetQueue, &sp18)) {
|
|
return false;
|
|
}
|
|
if (sp18 != gAudioSpecId) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void AudioThread_ResetAudioHeap(s32 specId) {
|
|
MQ_CLEAR_QUEUE(gAudioResetQueue);
|
|
|
|
AudioThread_ResetCmdQueue();
|
|
osSendMesg(gAudioSpecQueue, OS_MESG_32(specId), OS_MESG_NOBLOCK);
|
|
}
|
|
|
|
void AudioThread_PreNMIReset(void) {
|
|
gAudioResetTimer = 1;
|
|
AudioThread_ResetAudioHeap(AUDIOSPEC_CO);
|
|
gAudioResetStep = 0;
|
|
}
|
|
|
|
void AudioThread_Init(void) {
|
|
AudioThread_InitQueues();
|
|
}
|