summaryrefslogtreecommitdiff
path: root/src/code/code_800F9280.c
diff options
context:
space:
mode:
authorengineer124 <47598039+engineer124@users.noreply.github.com>2023-07-07 07:55:10 +1000
committerGitHub <noreply@github.com>2023-07-06 17:55:10 -0400
commitd307a3723313507726d5ebcfda0b5b9cef224d91 (patch)
tree0323cee010466202839a01911697709e8a10e989 /src/code/code_800F9280.c
parent0ce03133425867723dd81fc66f57bbb8d40aaf7a (diff)
Reorganize Audio Files & Name Remaining Audio Files (#1494)
* reorganize audio files * audio code files * split audio and libaudio * audio_init_params to audio_configuration * simplify file names * move aisetnextbuf to libaudio * move src/audio -> src/code/audio * adjust makefile comment * reorganize again into internal/external * adjust comment * restructure again
Diffstat (limited to 'src/code/code_800F9280.c')
-rw-r--r--src/code/code_800F9280.c827
1 files changed, 0 insertions, 827 deletions
diff --git a/src/code/code_800F9280.c b/src/code/code_800F9280.c
deleted file mode 100644
index 115789fe5..000000000
--- a/src/code/code_800F9280.c
+++ /dev/null
@@ -1,827 +0,0 @@
-/**
- * @file code_800F9280.c
- *
- * This file implements a set of high-level audio sequence commands that allow sequences to be modified in real-time.
- * These commands are intended to interface external to the audio library.
- *
- * These commands are generated using `Audio_QueueSeqCmd`, and a user-friendly interface for this function
- * can be found in `seqcmd.h`
- *
- * These commands change sequences by generating internal audio commands `Audio_QueueCmd` which allows these
- * sequence requests to be passed onto the audio thread. It is worth noting all functions in this file are
- * called from the graph thread.
- *
- * These commands are not to be confused with the sequence instructions used by the sequences themselves
- * which are a midi-based scripting language.
- *
- * Nor are these commands to be confused with the internal audio commands used to transfer requests from
- * the graph thread to the audio thread.
- */
-#include "ultra64.h"
-#include "global.h"
-#include "ultra64/abi.h"
-
-// Direct audio command (skips the queueing system)
-#define SEQCMD_SET_PLAYER_VOLUME_NOW(seqPlayerIndex, duration, volume) \
- Audio_ProcessSeqCmd((SEQCMD_OP_SET_PLAYER_VOLUME << 28) | ((u8)(seqPlayerIndex) << 24) | ((u8)(duration) << 16) | \
- ((u8)((volume)*127.0f)));
-
-typedef struct {
- u8 seqId;
- u8 priority; // higher values have higher priority
-} SeqRequest;
-
-SeqRequest sSeqRequests[4][5];
-u8 sNumSeqRequests[4];
-u32 sAudioSeqCmds[0x100];
-ActiveSequence gActiveSeqs[4];
-
-void Audio_StartSequence(u8 seqPlayerIndex, u8 seqId, u8 seqArgs, u16 fadeInDuration) {
- u8 channelIndex;
- u16 duration;
- s32 pad;
-
- if (!gStartSeqDisabled || (seqPlayerIndex == SEQ_PLAYER_SFX)) {
- seqArgs &= 0x7F;
- if (seqArgs == 0x7F) {
- // `fadeInDuration` is interpreted as skip ticks
- duration = (fadeInDuration >> 3) * 60 * gAudioCtx.audioBufferParameters.updatesPerFrame;
- Audio_QueueCmdS32(0x85000000 | _SHIFTL(seqPlayerIndex, 16, 8) | _SHIFTL(seqId, 8, 8), duration);
- } else {
- // `fadeInDuration` is interpreted as number of frames at 30 fps
- Audio_QueueCmdS32(0x82000000 | _SHIFTL(seqPlayerIndex, 16, 8) | _SHIFTL(seqId, 8, 8),
- (fadeInDuration * (u16)gAudioCtx.audioBufferParameters.updatesPerFrame) / 4);
- }
-
- gActiveSeqs[seqPlayerIndex].seqId = seqId | (seqArgs << 8);
- gActiveSeqs[seqPlayerIndex].prevSeqId = seqId | (seqArgs << 8);
-
- if (gActiveSeqs[seqPlayerIndex].volCur != 1.0f) {
- Audio_QueueCmdF32(0x41000000 | _SHIFTL(seqPlayerIndex, 16, 8), gActiveSeqs[seqPlayerIndex].volCur);
- }
-
- gActiveSeqs[seqPlayerIndex].tempoTimer = 0;
- gActiveSeqs[seqPlayerIndex].tempoOriginal = 0;
- gActiveSeqs[seqPlayerIndex].tempoCmd = 0;
-
- for (channelIndex = 0; channelIndex < SEQ_NUM_CHANNELS; channelIndex++) {
- gActiveSeqs[seqPlayerIndex].channelData[channelIndex].volCur = 1.0f;
- gActiveSeqs[seqPlayerIndex].channelData[channelIndex].volTimer = 0;
- gActiveSeqs[seqPlayerIndex].channelData[channelIndex].freqScaleCur = 1.0f;
- gActiveSeqs[seqPlayerIndex].channelData[channelIndex].freqScaleTimer = 0;
- }
-
- gActiveSeqs[seqPlayerIndex].freqScaleChannelFlags = 0;
- gActiveSeqs[seqPlayerIndex].volChannelFlags = 0;
- }
-}
-
-void Audio_StopSequence(u8 seqPlayerIndex, u16 fadeOutDuration) {
- Audio_QueueCmdS32(0x83000000 | ((u8)seqPlayerIndex << 16),
- (fadeOutDuration * (u16)gAudioCtx.audioBufferParameters.updatesPerFrame) / 4);
- gActiveSeqs[seqPlayerIndex].seqId = NA_BGM_DISABLED;
-}
-
-void Audio_ProcessSeqCmd(u32 cmd) {
- s32 priority;
- s32 channelMaskEnable;
- u16 channelMaskDisable;
- u16 fadeTimer;
- u16 val;
- u8 oldSpec;
- u8 spec;
- u8 op;
- u8 subOp;
- u8 seqPlayerIndex;
- u8 seqId;
- u8 seqArgs;
- u8 found;
- u8 port;
- u8 duration;
- u8 channelIndex;
- u8 i;
- f32 freqScaleTarget;
- s32 pad;
-
- if (gAudioDebugPrintSeqCmd && (cmd & SEQCMD_OP_MASK) != (SEQCMD_OP_SET_PLAYER_IO << 28)) {
- AudioDebug_ScrPrt("SEQ H", (cmd >> 16) & 0xFFFF);
- AudioDebug_ScrPrt(" L", cmd & 0xFFFF);
- }
-
- op = cmd >> 28;
- seqPlayerIndex = (cmd & 0xF000000) >> 24;
-
- switch (op) {
- case SEQCMD_OP_PLAY_SEQUENCE:
- // Play a new sequence
- seqId = cmd & 0xFF;
- seqArgs = (cmd & 0xFF00) >> 8;
- // `fadeTimer` is only shifted 13 bits instead of 16 bits.
- // `fadeTimer` continues to be scaled in `Audio_StartSequence`
- fadeTimer = (cmd & 0xFF0000) >> 13;
- if (!gActiveSeqs[seqPlayerIndex].isWaitingForFonts && (seqArgs < 0x80)) {
- Audio_StartSequence(seqPlayerIndex, seqId, seqArgs, fadeTimer);
- }
- break;
-
- case SEQCMD_OP_STOP_SEQUENCE:
- // Stop a sequence and disable the sequence player
- fadeTimer = (cmd & 0xFF0000) >> 13;
- Audio_StopSequence(seqPlayerIndex, fadeTimer);
- break;
-
- case SEQCMD_OP_QUEUE_SEQUENCE:
- // Queue a sequence into `sSeqRequests`
- seqId = cmd & 0xFF;
- seqArgs = (cmd & 0xFF00) >> 8;
- fadeTimer = (cmd & 0xFF0000) >> 13;
- priority = seqArgs;
-
- // Checks if the requested sequence is first in the list of requests
- // If it is already queued and first in the list, then play the sequence immediately
- for (i = 0; i < sNumSeqRequests[seqPlayerIndex]; i++) {
- if (sSeqRequests[seqPlayerIndex][i].seqId == seqId) {
- if (i == 0) {
- Audio_StartSequence(seqPlayerIndex, seqId, seqArgs, fadeTimer);
- }
- return;
- }
- }
-
- // Searches the sequence requests for the first request that does not have a higher priority
- // than the current incoming request
- found = sNumSeqRequests[seqPlayerIndex];
- for (i = 0; i < sNumSeqRequests[seqPlayerIndex]; i++) {
- if (priority >= sSeqRequests[seqPlayerIndex][i].priority) {
- found = i;
- i = sNumSeqRequests[seqPlayerIndex]; // "break;"
- }
- }
-
- // Check if the queue is full
- if (sNumSeqRequests[seqPlayerIndex] < ARRAY_COUNT(sSeqRequests[seqPlayerIndex])) {
- sNumSeqRequests[seqPlayerIndex]++;
- }
-
- for (i = sNumSeqRequests[seqPlayerIndex] - 1; i != found; i--) {
- // Move all requests of lower priority backwards 1 place in the queue
- // If the queue is full, overwrite the entry with the lowest priority
- sSeqRequests[seqPlayerIndex][i].priority = sSeqRequests[seqPlayerIndex][i - 1].priority;
- sSeqRequests[seqPlayerIndex][i].seqId = sSeqRequests[seqPlayerIndex][i - 1].seqId;
- }
-
- // Fill the newly freed space in the queue with the new request
- sSeqRequests[seqPlayerIndex][found].priority = seqArgs;
- sSeqRequests[seqPlayerIndex][found].seqId = seqId;
-
- // The sequence is first in queue, so start playing.
- if (found == 0) {
- Audio_StartSequence(seqPlayerIndex, seqId, seqArgs, fadeTimer);
- }
- break;
-
- case SEQCMD_OP_UNQUEUE_SEQUENCE:
- // Unqueue sequence
- fadeTimer = (cmd & 0xFF0000) >> 13;
-
- found = sNumSeqRequests[seqPlayerIndex];
- for (i = 0; i < sNumSeqRequests[seqPlayerIndex]; i++) {
- seqId = cmd & 0xFF;
- if (sSeqRequests[seqPlayerIndex][i].seqId == seqId) {
- found = i;
- i = sNumSeqRequests[seqPlayerIndex]; // "break;"
- }
- }
-
- if (found != sNumSeqRequests[seqPlayerIndex]) {
- // Move all requests of lower priority forward 1 place in the queue
- for (i = found; i < sNumSeqRequests[seqPlayerIndex] - 1; i++) {
- sSeqRequests[seqPlayerIndex][i].priority = sSeqRequests[seqPlayerIndex][i + 1].priority;
- sSeqRequests[seqPlayerIndex][i].seqId = sSeqRequests[seqPlayerIndex][i + 1].seqId;
- }
- sNumSeqRequests[seqPlayerIndex]--;
- }
-
- // If the sequence was first in queue (it is currently playing),
- // Then stop the sequence and play the next sequence in the queue.
- if (found == 0) {
- Audio_StopSequence(seqPlayerIndex, fadeTimer);
- if (sNumSeqRequests[seqPlayerIndex] != 0) {
- Audio_StartSequence(seqPlayerIndex, sSeqRequests[seqPlayerIndex][0].seqId,
- sSeqRequests[seqPlayerIndex][0].priority, fadeTimer);
- }
- }
- break;
-
- case SEQCMD_OP_SET_PLAYER_VOLUME:
- // Transition volume to a target volume for an entire player
- duration = (cmd & 0xFF0000) >> 15;
- val = cmd & 0xFF;
- if (duration == 0) {
- duration++;
- }
- // Volume is scaled relative to 127
- gActiveSeqs[seqPlayerIndex].volTarget = (f32)val / 127.0f;
- if (gActiveSeqs[seqPlayerIndex].volCur != gActiveSeqs[seqPlayerIndex].volTarget) {
- gActiveSeqs[seqPlayerIndex].volStep =
- (gActiveSeqs[seqPlayerIndex].volCur - gActiveSeqs[seqPlayerIndex].volTarget) / (f32)duration;
- gActiveSeqs[seqPlayerIndex].volTimer = duration;
- }
- break;
-
- case SEQCMD_OP_SET_PLAYER_FREQ:
- // Transition freq scale to a target freq for all channels
- duration = (cmd & 0xFF0000) >> 15;
- val = cmd & 0xFFFF;
- if (duration == 0) {
- duration++;
- }
- // Frequency is scaled relative to 1000
- freqScaleTarget = (f32)val / 1000.0f;
- for (i = 0; i < SEQ_NUM_CHANNELS; i++) {
- gActiveSeqs[seqPlayerIndex].channelData[i].freqScaleTarget = freqScaleTarget;
- gActiveSeqs[seqPlayerIndex].channelData[i].freqScaleTimer = duration;
- gActiveSeqs[seqPlayerIndex].channelData[i].freqScaleStep =
- (gActiveSeqs[seqPlayerIndex].channelData[i].freqScaleCur - freqScaleTarget) / (f32)duration;
- }
- gActiveSeqs[seqPlayerIndex].freqScaleChannelFlags = 0xFFFF;
- break;
-
- case SEQCMD_OP_SET_CHANNEL_FREQ:
- // Transition freq scale to a target for a specific channel
- duration = (cmd & 0xFF0000) >> 15;
- channelIndex = (cmd & 0xF000) >> 12;
- val = cmd & 0xFFF;
- if (duration == 0) {
- duration++;
- }
- // Frequency is scaled relative to 1000
- freqScaleTarget = (f32)val / 1000.0f;
- gActiveSeqs[seqPlayerIndex].channelData[channelIndex].freqScaleTarget = freqScaleTarget;
- gActiveSeqs[seqPlayerIndex].channelData[channelIndex].freqScaleStep =
- (gActiveSeqs[seqPlayerIndex].channelData[channelIndex].freqScaleCur - freqScaleTarget) / (f32)duration;
- gActiveSeqs[seqPlayerIndex].channelData[channelIndex].freqScaleTimer = duration;
- gActiveSeqs[seqPlayerIndex].freqScaleChannelFlags |= 1 << channelIndex;
- break;
-
- case SEQCMD_OP_SET_CHANNEL_VOLUME:
- // Transition volume to a target volume for a specific channel
- duration = (cmd & 0xFF0000) >> 15;
- channelIndex = (cmd & 0xF00) >> 8;
- val = cmd & 0xFF;
- if (duration == 0) {
- duration++;
- }
- // Volume is scaled relative to 127
- gActiveSeqs[seqPlayerIndex].channelData[channelIndex].volTarget = (f32)val / 127.0f;
- if (gActiveSeqs[seqPlayerIndex].channelData[channelIndex].volCur !=
- gActiveSeqs[seqPlayerIndex].channelData[channelIndex].volTarget) {
- gActiveSeqs[seqPlayerIndex].channelData[channelIndex].volStep =
- (gActiveSeqs[seqPlayerIndex].channelData[channelIndex].volCur -
- gActiveSeqs[seqPlayerIndex].channelData[channelIndex].volTarget) /
- (f32)duration;
- gActiveSeqs[seqPlayerIndex].channelData[channelIndex].volTimer = duration;
- gActiveSeqs[seqPlayerIndex].volChannelFlags |= 1 << channelIndex;
- }
- break;
-
- case SEQCMD_OP_SET_PLAYER_IO:
- // Set global io port
- port = (cmd & 0xFF0000) >> 16;
- val = cmd & 0xFF;
- Audio_QueueCmdS8(0x46000000 | _SHIFTL(seqPlayerIndex, 16, 8) | _SHIFTL(port, 0, 8), val);
- break;
-
- case SEQCMD_OP_SET_CHANNEL_IO:
- // Set io port if channel masked
- channelIndex = (cmd & 0xF00) >> 8;
- port = (cmd & 0xFF0000) >> 16;
- val = cmd & 0xFF;
- if (!(gActiveSeqs[seqPlayerIndex].channelPortMask & (1 << channelIndex))) {
- Audio_QueueCmdS8(0x06000000 | _SHIFTL(seqPlayerIndex, 16, 8) | _SHIFTL(channelIndex, 8, 8) |
- _SHIFTL(port, 0, 8),
- val);
- }
- break;
-
- case SEQCMD_OP_SET_CHANNEL_IO_DISABLE_MASK:
- // Disable channel io specifically for
- // `SEQCMD_OP_SET_CHANNEL_IO` This can be bypassed by setting channel io through `Audio_QueueCmdS8` 0x6
- // directly. This is accomplished by setting a channel mask.
- gActiveSeqs[seqPlayerIndex].channelPortMask = cmd & 0xFFFF;
- break;
-
- case SEQCMD_OP_SET_CHANNEL_DISABLE_MASK:
- // Disable or Reenable channels
-
- // Disable channels
- channelMaskDisable = cmd & 0xFFFF;
- if (channelMaskDisable != 0) {
- // Apply channel mask `channelMaskDisable`
- Audio_QueueCmdU16(0x90000000 | _SHIFTL(seqPlayerIndex, 16, 8), channelMaskDisable);
- // Disable channels
- Audio_QueueCmdS8(0x08000000 | _SHIFTL(seqPlayerIndex, 16, 8) | 0xFF00, 1);
- }
-
- // Reenable channels
- channelMaskEnable = (channelMaskDisable ^ 0xFFFF);
- if (channelMaskEnable != 0) {
- // Apply channel mask `channelMaskEnable`
- Audio_QueueCmdU16(0x90000000 | _SHIFTL(seqPlayerIndex, 16, 8), channelMaskEnable);
- // Enable channels
- Audio_QueueCmdS8(0x08000000 | _SHIFTL(seqPlayerIndex, 16, 8) | 0xFF00, 0);
- }
- break;
-
- case SEQCMD_OP_TEMPO_CMD:
- // Update a tempo using a sub-command system.
- // Stores the cmd for processing elsewhere.
- gActiveSeqs[seqPlayerIndex].tempoCmd = cmd;
- break;
-
- case SEQCMD_OP_SETUP_CMD:
- // Queue a sub-command to execute once the sequence is finished playing
- subOp = (cmd & 0xF00000) >> 20;
- if (subOp != SEQCMD_SUB_OP_SETUP_RESET_SETUP_CMDS) {
- // Ensure the maximum number of setup commands is not exceeded
- if (gActiveSeqs[seqPlayerIndex].setupCmdNum < (ARRAY_COUNT(gActiveSeqs[seqPlayerIndex].setupCmd) - 1)) {
- found = gActiveSeqs[seqPlayerIndex].setupCmdNum++;
- if (found < ARRAY_COUNT(gActiveSeqs[seqPlayerIndex].setupCmd)) {
- gActiveSeqs[seqPlayerIndex].setupCmd[found] = cmd;
- // Adds a delay of 2 frames before executing any setup commands.
- // This allows setup commands to be requested along with a new sequence on a seqPlayerIndex.
- // This 2 frame delay ensures the player is enabled before its state is checked for
- // the purpose of deciding if the setup commands should be run.
- // Otherwise, the setup commands will be executed before the sequence starts,
- // when the player is still disabled, instead of when the newly played sequence ends.
- gActiveSeqs[seqPlayerIndex].setupCmdTimer = 2;
- }
- }
- } else {
- // `SEQCMD_SUB_OP_SETUP_RESET_SETUP_CMDS`
- // Discard all setup command requests on `seqPlayerIndex`
- gActiveSeqs[seqPlayerIndex].setupCmdNum = 0;
- }
- break;
-
- case SEQCMD_OP_GLOBAL_CMD:
- // Apply a command that applies to all sequence players
- subOp = (cmd & 0xF00) >> 8;
- val = cmd & 0xFF;
- switch (subOp) {
- case SEQCMD_SUB_OP_GLOBAL_SET_SOUND_MODE:
- // Set sound mode
- Audio_QueueCmdS32(0xF0000000, gSoundModeList[val]);
- break;
-
- case SEQCMD_SUB_OP_GLOBAL_DISABLE_NEW_SEQUENCES:
- // Disable the starting of new sequences (except for the sfx player)
- gStartSeqDisabled = val & 1;
- break;
- }
- break;
-
- case SEQCMD_OP_RESET_AUDIO_HEAP:
- // Resets the audio heap based on the audio specifications and sfx channel layout
- spec = cmd & 0xFF;
- gSfxChannelLayout = (cmd & 0xFF00) >> 8;
- oldSpec = gAudioSpecId;
- gAudioSpecId = spec;
- func_800E5F88(spec);
- func_800F71BC(oldSpec);
- Audio_QueueCmdS32(0xF8000000, 0);
- break;
- }
-}
-
-/**
- * Add the sequence cmd to the `sAudioSeqCmds` queue
- */
-void Audio_QueueSeqCmd(u32 cmd) {
- sAudioSeqCmds[gSeqCmdWritePos++] = cmd;
-}
-
-void Audio_ProcessSeqCmds(void) {
- while (gSeqCmdWritePos != gSeqCmdReadPos) {
- Audio_ProcessSeqCmd(sAudioSeqCmds[gSeqCmdReadPos++]);
- }
-}
-
-u16 Audio_GetActiveSeqId(u8 seqPlayerIndex) {
- if (!gAudioCtx.seqPlayers[seqPlayerIndex].enabled) {
- return NA_BGM_DISABLED;
- }
- return gActiveSeqs[seqPlayerIndex].seqId;
-}
-
-s32 Audio_IsSeqCmdNotQueued(u32 cmdVal, u32 cmdMask) {
- u8 i;
-
- for (i = gSeqCmdReadPos; i != gSeqCmdWritePos; i++) {
- if ((sAudioSeqCmds[i] & cmdMask) == cmdVal) {
- return false;
- }
- }
-
- return true;
-}
-
-// Unused
-void Audio_ResetSequenceRequests(u8 seqPlayerIndex) {
- sNumSeqRequests[seqPlayerIndex] = 0;
-}
-
-/**
- * Check if the setup command is queued. If it is, then replace the command
- * with `SEQCMD_SUB_OP_SETUP_RESTORE_VOLUME`.
- * Unused
- */
-void Audio_ReplaceSeqCmdSetupOpVolRestore(u8 seqPlayerIndex, u8 setupOpDisabled) {
- u8 i;
-
- for (i = 0; i < gActiveSeqs[seqPlayerIndex].setupCmdNum; i++) {
- u8 setupOp = (gActiveSeqs[seqPlayerIndex].setupCmd[i] & 0xF00000) >> 20;
-
- if (setupOp == setupOpDisabled) {
- gActiveSeqs[seqPlayerIndex].setupCmd[i] = 0xFF000000;
- }
- }
-}
-
-void Audio_SetVolumeScale(u8 seqPlayerIndex, u8 scaleIndex, u8 targetVol, u8 volFadeTimer) {
- f32 volScale;
- u8 i;
-
- gActiveSeqs[seqPlayerIndex].volScales[scaleIndex] = targetVol & 0x7F;
-
- if (volFadeTimer != 0) {
- gActiveSeqs[seqPlayerIndex].fadeVolUpdate = true;
- gActiveSeqs[seqPlayerIndex].volFadeTimer = volFadeTimer;
- } else {
- for (i = 0, volScale = 1.0f; i < VOL_SCALE_INDEX_MAX; i++) {
- volScale *= gActiveSeqs[seqPlayerIndex].volScales[i] / 127.0f;
- }
-
- SEQCMD_SET_PLAYER_VOLUME_NOW(seqPlayerIndex, volFadeTimer, volScale);
- }
-}
-
-/**
- * Update different commands and requests for active sequences
- */
-void Audio_UpdateActiveSequences(void) {
- u32 tempoCmd;
- u8 tempoOp;
- u16 tempoPrev;
- u16 tempoTarget;
- u8 setupOp;
- u8 targetSeqPlayerIndex;
- u8 setupVal2;
- u8 setupVal1;
- u16 seqId;
- s32 pad[2];
- u16 channelMask;
- u32 retMsg;
- f32 volume;
- u8 tempoTimer;
- u8 seqPlayerIndex;
- u8 j;
- u8 channelIndex;
-
- for (seqPlayerIndex = 0; seqPlayerIndex < 4; seqPlayerIndex++) {
-
- // The setup for this block of code was not fully implemented until Majora's Mask.
- // The intent was to load soundfonts asynchronously before playing a
- // sequence in `Audio_StartSequence` using `(seqArgs & 0x80)`.
- // Checks if the requested sequence is finished loading fonts
- if (gActiveSeqs[seqPlayerIndex].isWaitingForFonts) {
- switch (func_800E5E20(&retMsg)) {
- case SEQ_PLAYER_BGM_MAIN + 1:
- case SEQ_PLAYER_FANFARE + 1:
- case SEQ_PLAYER_SFX + 1:
- case SEQ_PLAYER_BGM_SUB + 1:
- // The fonts have been loaded successfully.
- gActiveSeqs[seqPlayerIndex].isWaitingForFonts = false;
- // Queue the same command that was stored previously
- // The code to store this command is missing in OoT, so no command is executed
- Audio_ProcessSeqCmd(gActiveSeqs[seqPlayerIndex].startSeqCmd);
- break;
- }
- }
-
- // Update global volume
- if (gActiveSeqs[seqPlayerIndex].fadeVolUpdate) {
- volume = 1.0f;
- for (j = 0; j < VOL_SCALE_INDEX_MAX; j++) {
- volume *= (gActiveSeqs[seqPlayerIndex].volScales[j] / 127.0f);
- }
- SEQCMD_SET_PLAYER_VOLUME(seqPlayerIndex, gActiveSeqs[seqPlayerIndex].volFadeTimer, (u8)(volume * 127.0f));
- gActiveSeqs[seqPlayerIndex].fadeVolUpdate = false;
- }
-
- if (gActiveSeqs[seqPlayerIndex].volTimer != 0) {
- gActiveSeqs[seqPlayerIndex].volTimer--;
-
- if (gActiveSeqs[seqPlayerIndex].volTimer != 0) {
- gActiveSeqs[seqPlayerIndex].volCur -= gActiveSeqs[seqPlayerIndex].volStep;
- } else {
- gActiveSeqs[seqPlayerIndex].volCur = gActiveSeqs[seqPlayerIndex].volTarget;
- }
-
- Audio_QueueCmdF32(0x41000000 | _SHIFTL(seqPlayerIndex, 16, 8), gActiveSeqs[seqPlayerIndex].volCur);
- }
-
- // Process tempo
- if (gActiveSeqs[seqPlayerIndex].tempoCmd != 0) {
- tempoCmd = gActiveSeqs[seqPlayerIndex].tempoCmd;
- tempoTimer = (tempoCmd & 0xFF0000) >> 15;
- tempoTarget = tempoCmd & 0xFFF;
- if (tempoTimer == 0) {
- tempoTimer++;
- }
-
- // Process tempo commands
- if (gAudioCtx.seqPlayers[seqPlayerIndex].enabled) {
- tempoPrev = gAudioCtx.seqPlayers[seqPlayerIndex].tempo / TATUMS_PER_BEAT;
- tempoOp = (tempoCmd & 0xF000) >> 12;
- switch (tempoOp) {
- case SEQCMD_SUB_OP_TEMPO_SPEED_UP:
- // Speed up tempo by `tempoTarget` amount
- tempoTarget += tempoPrev;
- break;
-
- case SEQCMD_SUB_OP_TEMPO_SLOW_DOWN:
- // Slow down tempo by `tempoTarget` amount
- if (tempoTarget < tempoPrev) {
- tempoTarget = tempoPrev - tempoTarget;
- }
- break;
-
- case SEQCMD_SUB_OP_TEMPO_SCALE:
- // Scale tempo by a multiplicative factor
- tempoTarget = tempoPrev * (tempoTarget / 100.0f);
- break;
-
- case SEQCMD_SUB_OP_TEMPO_RESET:
- // Reset tempo to original tempo
- tempoTarget = (gActiveSeqs[seqPlayerIndex].tempoOriginal != 0)
- ? gActiveSeqs[seqPlayerIndex].tempoOriginal
- : tempoPrev;
- break;
-
- default: // `SEQCMD_SUB_OP_TEMPO_SET`
- // `tempoTarget` is the new tempo
- break;
- }
-
- if (tempoTarget > 300) {
- tempoTarget = 300;
- }
-
- if (gActiveSeqs[seqPlayerIndex].tempoOriginal == 0) {
- gActiveSeqs[seqPlayerIndex].tempoOriginal = tempoPrev;
- }
-
- gActiveSeqs[seqPlayerIndex].tempoTarget = tempoTarget;
- gActiveSeqs[seqPlayerIndex].tempoCur = gAudioCtx.seqPlayers[seqPlayerIndex].tempo / TATUMS_PER_BEAT;
- gActiveSeqs[seqPlayerIndex].tempoStep =
- (gActiveSeqs[seqPlayerIndex].tempoCur - gActiveSeqs[seqPlayerIndex].tempoTarget) / tempoTimer;
- gActiveSeqs[seqPlayerIndex].tempoTimer = tempoTimer;
- gActiveSeqs[seqPlayerIndex].tempoCmd = 0;
- }
- }
-
- // Step tempo to target
- if (gActiveSeqs[seqPlayerIndex].tempoTimer != 0) {
- gActiveSeqs[seqPlayerIndex].tempoTimer--;
- if (gActiveSeqs[seqPlayerIndex].tempoTimer != 0) {
- gActiveSeqs[seqPlayerIndex].tempoCur -= gActiveSeqs[seqPlayerIndex].tempoStep;
- } else {
- gActiveSeqs[seqPlayerIndex].tempoCur = gActiveSeqs[seqPlayerIndex].tempoTarget;
- }
- // Set tempo
- Audio_QueueCmdS32(0x47000000 | _SHIFTL(seqPlayerIndex, 16, 8), gActiveSeqs[seqPlayerIndex].tempoCur);
- }
-
- // Update channel volumes
- if (gActiveSeqs[seqPlayerIndex].volChannelFlags != 0) {
- for (channelIndex = 0; channelIndex < SEQ_NUM_CHANNELS; channelIndex++) {
- if (gActiveSeqs[seqPlayerIndex].channelData[channelIndex].volTimer != 0) {
- gActiveSeqs[seqPlayerIndex].channelData[channelIndex].volTimer--;
- if (gActiveSeqs[seqPlayerIndex].channelData[channelIndex].volTimer != 0) {
- gActiveSeqs[seqPlayerIndex].channelData[channelIndex].volCur -=
- gActiveSeqs[seqPlayerIndex].channelData[channelIndex].volStep;
- } else {
- gActiveSeqs[seqPlayerIndex].channelData[channelIndex].volCur =
- gActiveSeqs[seqPlayerIndex].channelData[channelIndex].volTarget;
- gActiveSeqs[seqPlayerIndex].volChannelFlags ^= (1 << channelIndex);
- }
- // `CHAN_UPD_VOL_SCALE`
- Audio_QueueCmdF32(0x01000000 | _SHIFTL(seqPlayerIndex, 16, 8) | _SHIFTL(channelIndex, 8, 8),
- gActiveSeqs[seqPlayerIndex].channelData[channelIndex].volCur);
- }
- }
- }
-
- // Update frequencies
- if (gActiveSeqs[seqPlayerIndex].freqScaleChannelFlags != 0) {
- for (channelIndex = 0; channelIndex < SEQ_NUM_CHANNELS; channelIndex++) {
- if (gActiveSeqs[seqPlayerIndex].channelData[channelIndex].freqScaleTimer != 0) {
- gActiveSeqs[seqPlayerIndex].channelData[channelIndex].freqScaleTimer--;
- if (gActiveSeqs[seqPlayerIndex].channelData[channelIndex].freqScaleTimer != 0) {
- gActiveSeqs[seqPlayerIndex].channelData[channelIndex].freqScaleCur -=
- gActiveSeqs[seqPlayerIndex].channelData[channelIndex].freqScaleStep;
- } else {
- gActiveSeqs[seqPlayerIndex].channelData[channelIndex].freqScaleCur =
- gActiveSeqs[seqPlayerIndex].channelData[channelIndex].freqScaleTarget;
- gActiveSeqs[seqPlayerIndex].freqScaleChannelFlags ^= (1 << channelIndex);
- }
- // `CHAN_UPD_FREQ_SCALE`
- Audio_QueueCmdF32(0x04000000 | _SHIFTL(seqPlayerIndex, 16, 8) | _SHIFTL(channelIndex, 8, 8),
- gActiveSeqs[seqPlayerIndex].channelData[channelIndex].freqScaleCur);
- }
- }
- }
-
- // Process setup commands
- if (gActiveSeqs[seqPlayerIndex].setupCmdNum != 0) {
- // If there is a SeqCmd to reset the audio heap queued, then drop all setup commands
- if (!Audio_IsSeqCmdNotQueued(SEQCMD_OP_RESET_AUDIO_HEAP << 28, SEQCMD_OP_MASK)) {
- gActiveSeqs[seqPlayerIndex].setupCmdNum = 0;
- return;
- }
-
- // Only process setup commands once the timer reaches zero
- if (gActiveSeqs[seqPlayerIndex].setupCmdTimer != 0) {
- gActiveSeqs[seqPlayerIndex].setupCmdTimer--;
- continue;
- }
-
- // Only process setup commands if `seqPlayerIndex` if no longer playing
- // i.e. the `seqPlayer` is no longer enabled
- if (gAudioCtx.seqPlayers[seqPlayerIndex].enabled) {
- continue;
- }
-
- for (j = 0; j < gActiveSeqs[seqPlayerIndex].setupCmdNum; j++) {
- setupOp = (gActiveSeqs[seqPlayerIndex].setupCmd[j] & 0x00F00000) >> 20;
- targetSeqPlayerIndex = (gActiveSeqs[seqPlayerIndex].setupCmd[j] & 0x000F0000) >> 16;
- setupVal2 = (gActiveSeqs[seqPlayerIndex].setupCmd[j] & 0xFF00) >> 8;
- setupVal1 = gActiveSeqs[seqPlayerIndex].setupCmd[j] & 0xFF;
-
- switch (setupOp) {
- case SEQCMD_SUB_OP_SETUP_RESTORE_VOLUME:
- // Restore `targetSeqPlayerIndex` volume back to normal levels
- Audio_SetVolumeScale(targetSeqPlayerIndex, VOL_SCALE_INDEX_FANFARE, 0x7F, setupVal1);
- break;
-
- case SEQCMD_SUB_OP_SETUP_RESTORE_VOLUME_IF_QUEUED:
- // Restore `targetSeqPlayerIndex` volume back to normal levels,
- // but only if the number of sequence queue requests from `sSeqRequests`
- // exactly matches the argument to the command
- if (setupVal1 == sNumSeqRequests[seqPlayerIndex]) {
- Audio_SetVolumeScale(targetSeqPlayerIndex, VOL_SCALE_INDEX_FANFARE, 0x7F, setupVal2);
- }
- break;
-
- case SEQCMD_SUB_OP_SETUP_SEQ_UNQUEUE:
- // Unqueue `seqPlayerIndex` from sSeqRequests
- //! @bug this command does not work as intended as unqueueing
- //! the sequence relies on `gActiveSeqs[seqPlayerIndex].seqId`
- //! However, `gActiveSeqs[seqPlayerIndex].seqId` is reset before the sequence on
- //! `seqPlayerIndex` is requested to stop, i.e. before the sequence is disabled and setup
- //! commands (including this command) can run. A simple fix would have been to unqueue based on
- //! `gActiveSeqs[seqPlayerIndex].prevSeqId` instead
- SEQCMD_UNQUEUE_SEQUENCE(seqPlayerIndex, 0, gActiveSeqs[seqPlayerIndex].seqId);
- break;
-
- case SEQCMD_SUB_OP_SETUP_RESTART_SEQ:
- // Restart the currently active sequence on `targetSeqPlayerIndex` with full volume.
- // Sequence on `targetSeqPlayerIndex` must still be active to play (can be muted)
- SEQCMD_PLAY_SEQUENCE(targetSeqPlayerIndex, 1, 0, gActiveSeqs[targetSeqPlayerIndex].seqId);
- gActiveSeqs[targetSeqPlayerIndex].fadeVolUpdate = true;
- gActiveSeqs[targetSeqPlayerIndex].volScales[VOL_SCALE_INDEX_FANFARE] = 0x7F;
- break;
-
- case SEQCMD_SUB_OP_SETUP_TEMPO_SCALE:
- // Scale tempo by a multiplicative factor
- SEQCMD_SCALE_TEMPO(targetSeqPlayerIndex, setupVal2, setupVal1);
- break;
-
- case SEQCMD_SUB_OP_SETUP_TEMPO_RESET:
- // Reset tempo to previous tempo
- SEQCMD_RESET_TEMPO(targetSeqPlayerIndex, setupVal1);
- break;
-
- case SEQCMD_SUB_OP_SETUP_PLAY_SEQ:
- // Play the requested sequence
- // Uses the fade timer set by `SEQCMD_SUB_OP_SETUP_SET_FADE_TIMER`
- seqId = gActiveSeqs[seqPlayerIndex].setupCmd[j] & 0xFFFF;
- SEQCMD_PLAY_SEQUENCE(targetSeqPlayerIndex, gActiveSeqs[targetSeqPlayerIndex].setupFadeTimer, 0,
- seqId);
- Audio_SetVolumeScale(targetSeqPlayerIndex, VOL_SCALE_INDEX_FANFARE, 0x7F, 0);
- gActiveSeqs[targetSeqPlayerIndex].setupFadeTimer = 0;
- break;
-
- case SEQCMD_SUB_OP_SETUP_SET_FADE_TIMER:
- // A command specifically to support `SEQCMD_SUB_OP_SETUP_PLAY_SEQ`
- // Sets the fade timer for the sequence requested in `SEQCMD_SUB_OP_SETUP_PLAY_SEQ`
- gActiveSeqs[seqPlayerIndex].setupFadeTimer = setupVal2;
- break;
-
- case SEQCMD_SUB_OP_SETUP_RESTORE_VOLUME_WITH_SCALE_INDEX:
- // Restore the volume back to default levels
- // Allows a `scaleIndex` to be specified.
- Audio_SetVolumeScale(targetSeqPlayerIndex, setupVal2, 0x7F, setupVal1);
- break;
-
- case SEQCMD_SUB_OP_SETUP_POP_PERSISTENT_CACHE:
- // Discard audio data by popping one more audio caches from the audio heap
- if (setupVal1 & (1 << SEQUENCE_TABLE)) {
- Audio_QueueCmdS32(0xE3000000, SEQUENCE_TABLE);
- }
- if (setupVal1 & (1 << FONT_TABLE)) {
- Audio_QueueCmdS32(0xE3000000, FONT_TABLE);
- }
- if (setupVal1 & (1 << SAMPLE_TABLE)) {
- Audio_QueueCmdS32(0xE3000000, SAMPLE_TABLE);
- }
- break;
-
- case SEQCMD_SUB_OP_SETUP_SET_CHANNEL_DISABLE_MASK:
- // Disable (or reenable) specific channels of `targetSeqPlayerIndex`
- channelMask = gActiveSeqs[seqPlayerIndex].setupCmd[j] & 0xFFFF;
- SEQCMD_SET_CHANNEL_DISABLE_MASK(targetSeqPlayerIndex, channelMask);
- break;
-
- case SEQCMD_SUB_OP_SETUP_SET_PLAYER_FREQ:
- // Scale all channels of `targetSeqPlayerIndex`
- SEQCMD_SET_PLAYER_FREQ(targetSeqPlayerIndex, setupVal2, (setupVal1 * 10) & 0xFFFF);
- break;
- }
- }
-
- gActiveSeqs[seqPlayerIndex].setupCmdNum = 0;
- }
- }
-}
-
-u8 func_800FAD34(void) {
- if (D_80133418 != 0) {
- if (D_80133418 == 1) {
- if (func_800E5EDC() == 1) {
- D_80133418 = 0;
- Audio_QueueCmdS8(0x46020000, gSfxChannelLayout);
- func_800F7170();
- }
- } else if (D_80133418 == 2) {
- while (func_800E5EDC() != 1) {}
- D_80133418 = 0;
- Audio_QueueCmdS8(0x46020000, gSfxChannelLayout);
- func_800F7170();
- }
- }
-
- return D_80133418;
-}
-
-void Audio_ResetActiveSequences(void) {
- u8 seqPlayerIndex;
- u8 scaleIndex;
-
- for (seqPlayerIndex = 0; seqPlayerIndex < 4; seqPlayerIndex++) {
- sNumSeqRequests[seqPlayerIndex] = 0;
-
- gActiveSeqs[seqPlayerIndex].seqId = NA_BGM_DISABLED;
- gActiveSeqs[seqPlayerIndex].prevSeqId = NA_BGM_DISABLED;
- gActiveSeqs[seqPlayerIndex].tempoTimer = 0;
- gActiveSeqs[seqPlayerIndex].tempoOriginal = 0;
- gActiveSeqs[seqPlayerIndex].tempoCmd = 0;
- gActiveSeqs[seqPlayerIndex].channelPortMask = 0;
- gActiveSeqs[seqPlayerIndex].setupCmdNum = 0;
- gActiveSeqs[seqPlayerIndex].setupFadeTimer = 0;
- gActiveSeqs[seqPlayerIndex].freqScaleChannelFlags = 0;
- gActiveSeqs[seqPlayerIndex].volChannelFlags = 0;
- for (scaleIndex = 0; scaleIndex < VOL_SCALE_INDEX_MAX; scaleIndex++) {
- gActiveSeqs[seqPlayerIndex].volScales[scaleIndex] = 0x7F;
- }
-
- gActiveSeqs[seqPlayerIndex].volFadeTimer = 1;
- gActiveSeqs[seqPlayerIndex].fadeVolUpdate = true;
- }
-}
-
-void Audio_ResetActiveSequencesAndVolume(void) {
- u8 seqPlayerIndex;
- u8 scaleIndex;
-
- for (seqPlayerIndex = 0; seqPlayerIndex < 4; seqPlayerIndex++) {
- gActiveSeqs[seqPlayerIndex].volCur = 1.0f;
- gActiveSeqs[seqPlayerIndex].volTimer = 0;
- gActiveSeqs[seqPlayerIndex].fadeVolUpdate = false;
- for (scaleIndex = 0; scaleIndex < VOL_SCALE_INDEX_MAX; scaleIndex++) {
- gActiveSeqs[seqPlayerIndex].volScales[scaleIndex] = 0x7F;
- }
- }
- Audio_ResetActiveSequences();
-}