summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/audiothread_cmd.h537
-rw-r--r--include/functions.h32
-rw-r--r--include/seqcmd.h66
-rw-r--r--include/sfx.h36
-rw-r--r--include/variables.h5
-rw-r--r--include/z64.h1
-rw-r--r--include/z64audio.h118
7 files changed, 677 insertions, 118 deletions
diff --git a/include/audiothread_cmd.h b/include/audiothread_cmd.h
new file mode 100644
index 000000000..3ec2cdeba
--- /dev/null
+++ b/include/audiothread_cmd.h
@@ -0,0 +1,537 @@
+#ifndef AUDIOTHREAD_CMD_H
+#define AUDIOTHREAD_CMD_H
+
+/**
+ * Audio thread commands to safely transfer information/requests/data
+ * from the external graph thread to the internal audio thread
+ */
+
+typedef enum {
+ // Channel Commands
+ /* 0x00 */ AUDIOCMD_OP_NOOP,
+ /* 0x01 */ AUDIOCMD_OP_CHANNEL_SET_VOL_SCALE,
+ /* 0x02 */ AUDIOCMD_OP_CHANNEL_SET_VOL,
+ /* 0x03 */ AUDIOCMD_OP_CHANNEL_SET_PAN,
+ /* 0x04 */ AUDIOCMD_OP_CHANNEL_SET_FREQ_SCALE,
+ /* 0x05 */ AUDIOCMD_OP_CHANNEL_SET_REVERB_VOLUME,
+ /* 0x06 */ AUDIOCMD_OP_CHANNEL_SET_IO,
+ /* 0x07 */ AUDIOCMD_OP_CHANNEL_SET_PAN_WEIGHT,
+ /* 0x08 */ AUDIOCMD_OP_CHANNEL_SET_MUTE,
+ /* 0x09 */ AUDIOCMD_OP_CHANNEL_SET_MUTE_BEHAVIOR,
+ /* 0x0A */ AUDIOCMD_OP_CHANNEL_SET_VIBRATO_DEPTH,
+ /* 0x0B */ AUDIOCMD_OP_CHANNEL_SET_VIBRATO_RATE,
+ /* 0x0C */ AUDIOCMD_OP_CHANNEL_SET_COMB_FILTER_SIZE,
+ /* 0x0D */ AUDIOCMD_OP_CHANNEL_SET_COMB_FILTER_GAIN,
+ /* 0x0E */ AUDIOCMD_OP_CHANNEL_SET_STEREO,
+ // SeqPlayer Commands
+ /* 0x41 */ AUDIOCMD_OP_SEQPLAYER_FADE_VOLUME_SCALE = 0x41,
+ /* 0x46 */ AUDIOCMD_OP_SEQPLAYER_SET_IO = 0x46,
+ /* 0x47 */ AUDIOCMD_OP_SEQPLAYER_SET_TEMPO,
+ /* 0x48 */ AUDIOCMD_OP_SEQPLAYER_SET_TRANSPOSITION,
+ /* 0x49 */ AUDIOCMD_OP_SEQPLAYER_CHANGE_TEMPO,
+ /* 0x4A */ AUDIOCMD_OP_SEQPLAYER_FADE_TO_SET_VOLUME,
+ /* 0x4B */ AUDIOCMD_OP_SEQPLAYER_FADE_TO_SCALED_VOLUME,
+ /* 0x4C */ AUDIOCMD_OP_SEQPLAYER_RESET_VOLUME,
+ /* 0x4D */ AUDIOCMD_OP_SEQPLAYER_SET_BEND,
+ /* 0x4E */ AUDIOCMD_OP_SEQPLAYER_CHANGE_TEMPO_SEQTICKS,
+ // Global Commands
+ /* 0x81 */ AUDIOCMD_OP_GLOBAL_SYNC_LOAD_SEQ_PARTS = 0x81,
+ /* 0x82 */ AUDIOCMD_OP_GLOBAL_INIT_SEQPLAYER,
+ /* 0x83 */ AUDIOCMD_OP_GLOBAL_DISABLE_SEQPLAYER,
+ /* 0x85 */ AUDIOCMD_OP_GLOBAL_INIT_SEQPLAYER_SKIP_TICKS = 0x85,
+ /* 0x90 */ AUDIOCMD_OP_GLOBAL_SET_CHANNEL_MASK = 0x90,
+ /* 0xE0 */ AUDIOCMD_OP_GLOBAL_SET_DRUM_FONT = 0xE0,
+ /* 0xE1 */ AUDIOCMD_OP_GLOBAL_SET_SFX_FONT,
+ /* 0xE2 */ AUDIOCMD_OP_GLOBAL_SET_INSTRUMENT_FONT,
+ /* 0xE3 */ AUDIOCMD_OP_GLOBAL_POP_PERSISTENT_CACHE,
+ /* 0xF0 */ AUDIOCMD_OP_GLOBAL_SET_SOUND_MODE = 0xF0,
+ /* 0xF1 */ AUDIOCMD_OP_GLOBAL_MUTE,
+ /* 0xF2 */ AUDIOCMD_OP_GLOBAL_UNMUTE,
+ /* 0xF3 */ AUDIOCMD_OP_GLOBAL_SYNC_LOAD_INSTRUMENT,
+ /* 0xF4 */ AUDIOCMD_OP_GLOBAL_ASYNC_LOAD_SAMPLE_BANK,
+ /* 0xF5 */ AUDIOCMD_OP_GLOBAL_ASYNC_LOAD_FONT,
+ /* 0xF6 */ AUDIOCMD_OP_GLOBAL_DISCARD_SEQ_FONTS,
+ /* 0xF8 */ AUDIOCMD_OP_GLOBAL_STOP_AUDIOCMDS = 0xF8,
+ /* 0xF9 */ AUDIOCMD_OP_GLOBAL_RESET_AUDIO_HEAP,
+ /* 0xFA */ AUDIOCMD_OP_GLOBAL_NOOP_1, // used but no code exists for it
+ /* 0xFB */ AUDIOCMD_OP_GLOBAL_SET_CUSTOM_UPDATE_FUNCTION,
+ /* 0xFC */ AUDIOCMD_OP_GLOBAL_ASYNC_LOAD_SEQ,
+ /* 0xFD */ AUDIOCMD_OP_GLOBAL_NOOP_2, // used but no code exists for it
+ /* 0xFE */ AUDIOCMD_OP_GLOBAL_DISABLE_ALL_SEQPLAYERS
+} AudioThreadCmdOp;
+
+// Pass to a AUDIOCMD_CHANNEL_ command in place of a channelIndex to try and apply to all channels.
+// Then uses `threadCmdChannelMask` to determine which channels to apply the command to.
+#define AUDIOCMD_ALL_CHANNELS 0xFF
+
+// ==== Audio Thread Channel Commands ====
+
+/**
+ * Set the volumeScale on a given channel
+ *
+ * @param seqPlayerIndex the index of the seqPlayer to modify
+ * @param channelIndex the index of the channel to modify
+ * @param volumeScale (f32) the volume scale for the sequence. No change in volume is 1.0f
+ */
+#define AUDIOCMD_CHANNEL_SET_VOL_SCALE(seqPlayerIndex, channelIndex, volumeScale) \
+ AudioThread_QueueCmdF32(AUDIO_MK_CMD(AUDIOCMD_OP_CHANNEL_SET_VOL_SCALE, seqPlayerIndex, channelIndex, 0), \
+ volumeScale)
+
+/**
+ * Set the volume on a given channel
+ *
+ * @param seqPlayerIndex the index of the seqPlayer to modify
+ * @param channelIndex the index of the channel to modify
+ * @param volume (f32) the target volume for the sequence. Default volume is 1.0f
+ */
+#define AUDIOCMD_CHANNEL_SET_VOL(seqPlayerIndex, channelIndex, volume) \
+ AudioThread_QueueCmdF32(AUDIO_MK_CMD(AUDIOCMD_OP_CHANNEL_SET_VOL, seqPlayerIndex, channelIndex, 0), volume)
+
+/**
+ * Set the pan
+ *
+ * @param seqPlayerIndex the index of the seqPlayer to modify
+ * @param channelIndex the index of the channel to modify
+ * @param pan (s8) the pan applied to the channel
+ */
+#define AUDIOCMD_CHANNEL_SET_PAN(seqPlayerIndex, channelIndex, pan) \
+ AudioThread_QueueCmdS8(AUDIO_MK_CMD(AUDIOCMD_OP_CHANNEL_SET_PAN, seqPlayerIndex, channelIndex, 0), pan)
+
+/**
+ * Set frequency scale
+ *
+ * @param seqPlayerIndex the index of the seqPlayer to modify
+ * @param channelIndex the index of the channel to modify
+ * @param freqScale (f32) the scaling factor to shift the pitch.
+ */
+#define AUDIOCMD_CHANNEL_SET_FREQ_SCALE(seqPlayerIndex, channelIndex, freqScale) \
+ AudioThread_QueueCmdF32(AUDIO_MK_CMD(AUDIOCMD_OP_CHANNEL_SET_FREQ_SCALE, seqPlayerIndex, channelIndex, 0), \
+ freqScale)
+
+/**
+ * Set reverb volume
+ *
+ * @param seqPlayerIndex the index of the seqPlayer to modify
+ * @param channelIndex the index of the channel to modify
+ * @param reverbVolume (s8) volume to set the reverb to (dry/wet mix)
+ */
+#define AUDIOCMD_CHANNEL_SET_REVERB_VOLUME(seqPlayerIndex, channelIndex, reverbVolume) \
+ AudioThread_QueueCmdS8(AUDIO_MK_CMD(AUDIOCMD_OP_CHANNEL_SET_REVERB_VOLUME, seqPlayerIndex, channelIndex, 0), \
+ reverbVolume)
+
+/**
+ * Write a value that can be read as input directly by the sequence itself. This will be set to the channel
+ * ioPort, which will only affect a single channel
+ *
+ * @param seqPlayerIndex the index of the seqPlayer to write the input to
+ * @param channelIndex the index of the channel to write the input to
+ * @param ioPort the index of the array to store the input-output value
+ * @param ioData (s8) the value that's written to the input-output array
+ */
+#define AUDIOCMD_CHANNEL_SET_IO(seqPlayerIndex, channelIndex, ioPort, ioData) \
+ AudioThread_QueueCmdS8(AUDIO_MK_CMD(AUDIOCMD_OP_CHANNEL_SET_IO, (seqPlayerIndex), (channelIndex), (ioPort)), \
+ (ioData))
+
+/**
+ * Set the proportion of pan that comes from the channel
+ *
+ * @param seqPlayerIndex the index of the seqPlayer to modify
+ * @param channelIndex the index of the channel to modify
+ * @param panChannelWeight (s8) proportion of pan that comes from the channel.
+ * Set to 0 for layer-only, and 128 for channel-only.
+ * As the type used is `s8` and internally cast to u8 later,
+ * pass `-128` to produce 128, or just use 127 instead
+ */
+#define AUDIOCMD_CHANNEL_SET_PAN_WEIGHT(seqPlayerIndex, channelIndex, panChannelWeight) \
+ AudioThread_QueueCmdS8(AUDIO_MK_CMD(AUDIOCMD_OP_CHANNEL_SET_PAN_WEIGHT, seqPlayerIndex, channelIndex, 0), \
+ panChannelWeight)
+
+/**
+ * Mute a specified channel. How a muted channel behaves will depend on channel mute flags
+ *
+ * @param seqPlayerIndex the index of the seqPlayer to modify
+ * @param channelIndex the index of the channel to modify
+ * @param muted (s8) set true to mute
+ */
+#define AUDIOCMD_CHANNEL_SET_MUTE(seqPlayerIndex, channelIndex, muted) \
+ AudioThread_QueueCmdS8(AUDIO_MK_CMD(AUDIOCMD_OP_CHANNEL_SET_MUTE, seqPlayerIndex, channelIndex, 0), muted)
+
+/**
+ * Set the muteBehavior for a specified channel
+ *
+ * @param seqPlayerIndex the index of the seqPlayer to modify
+ * @param channelIndex the index of the channel to modify
+ * @param muteBehavior (s8) Affected how a muted channel behaves. See `MUTE_BEHAVIOR_` macros
+ */
+#define AUDIOCMD_CHANNEL_SET_MUTE_BEHAVIOR(seqPlayerIndex, channelIndex, muteBehavior) \
+ AudioThread_QueueCmdS8(AUDIO_MK_CMD(AUDIOCMD_OP_CHANNEL_SET_MUTE_BEHAVIOR, seqPlayerIndex, channelIndex, 0), \
+ muteBehavior)
+
+/**
+ * Set the vibrato depth (also called magnitude/amplitude/extent)
+ *
+ * @param seqPlayerIndex the index of the seqPlayer to modify
+ * @param channelIndex the index of the channel to modify
+ * @param vibratoDepthTarget (s8) the vibrato depth scaled down by 1/8th
+ */
+#define AUDIOCMD_CHANNEL_SET_VIBRATO_DEPTH(seqPlayerIndex, channelIndex, vibratoDepthTarget) \
+ AudioThread_QueueCmdS8(AUDIO_MK_CMD(AUDIOCMD_OP_CHANNEL_SET_VIBRATO_DEPTH, seqPlayerIndex, channelIndex, 0), \
+ vibratoDepthTarget)
+
+/**
+ * Set the vibrato rate (freq/pitch)
+ *
+ * @param seqPlayerIndex the index of the seqPlayer to modify
+ * @param channelIndex the index of the channel to modify
+ * @param vibratoRateTarget (s8) the vibrato rate scaled down by 1/32nd
+ */
+#define AUDIOCMD_CHANNEL_SET_VIBRATO_RATE(seqPlayerIndex, channelIndex, vibratoRateTarget) \
+ AudioThread_QueueCmdS8(AUDIO_MK_CMD(AUDIOCMD_OP_CHANNEL_SET_VIBRATO_RATE, seqPlayerIndex, channelIndex, 0), \
+ vibratoRateTarget)
+
+/**
+ * Set the comb filter size
+ *
+ * @param seqPlayerIndex the index of the seqPlayer to modify
+ * @param channelIndex the index of the channel to modify
+ * @param combFilterSize (s8) delay number of sample bytes to offset and add back to itself
+ */
+#define AUDIOCMD_CHANNEL_SET_COMB_FILTER_SIZE(seqPlayerIndex, channelIndex, combFilterSize) \
+ AudioThread_QueueCmdS8(AUDIO_MK_CMD(AUDIOCMD_OP_CHANNEL_SET_COMB_FILTER_SIZE, seqPlayerIndex, channelIndex, 0), \
+ combFilterSize)
+
+/**
+ * Set the comb filter gain
+ *
+ * @param seqPlayerIndex the index of the seqPlayer to modify
+ * @param channelIndex the index of the channel to modify
+ * @param combFilterGain (u16) strength of the signal added back to itself
+ */
+#define AUDIOCMD_CHANNEL_SET_COMB_FILTER_GAIN(seqPlayerIndex, channelIndex, combFilterGain) \
+ AudioThread_QueueCmdU16(AUDIO_MK_CMD(AUDIOCMD_OP_CHANNEL_SET_COMB_FILTER_GAIN, seqPlayerIndex, channelIndex, 0), \
+ combFilterGain)
+
+/**
+ * Set the stereo bits
+ *
+ * @param seqPlayerIndex the index of the seqPlayer to modify
+ * @param channelIndex the index of the channel to modify
+ * @param stereoData (s8) bit-packed stereo information. See `StereoData`
+ */
+#define AUDIOCMD_CHANNEL_SET_STEREO(seqPlayerIndex, channelIndex, stereoData) \
+ AudioThread_QueueCmdS8(AUDIO_MK_CMD(AUDIOCMD_OP_CHANNEL_SET_STEREO, seqPlayerIndex, channelIndex, 0), stereoData)
+
+// ==== Audio Thread SeqPlayer Commands ====
+
+/**
+ * Set the fade volume scale
+ *
+ * @param seqPlayerIndex the index of the seqPlayer to modify
+ * @param fadeVolumeScale (f32) multiplicative scaling factor to apply to volume
+ */
+#define AUDIOCMD_SEQPLAYER_FADE_VOLUME_SCALE(seqPlayerIndex, fadeVolumeScale) \
+ AudioThread_QueueCmdF32(AUDIO_MK_CMD(AUDIOCMD_OP_SEQPLAYER_FADE_VOLUME_SCALE, seqPlayerIndex, 0, 0), \
+ fadeVolumeScale)
+
+/**
+ * Write a value that can be read as input directly by the sequence itself. This will be set to the global
+ * ioPort, which can affect the entire sequence
+ *
+ * @param seqPlayerIndex the index of the seqPlayer to write the input to
+ * @param ioPort the index of the array to store the input-output value
+ * @param ioData (s8) the value that's written to the input-output array
+ */
+#define AUDIOCMD_SEQPLAYER_SET_IO(seqPlayerIndex, ioPort, ioData) \
+ AudioThread_QueueCmdS8(AUDIO_MK_CMD(AUDIOCMD_OP_SEQPLAYER_SET_IO, seqPlayerIndex, 0, ioPort), ioData)
+
+/**
+ * Set the tempo (bpm) of a sequence on a given seqPlayer
+ *
+ * @param seqPlayerIndex the index of the seqPlayer to modify
+ * @param tempo (s32) the tempo for the sequence, in bpm
+ */
+#define AUDIOCMD_SEQPLAYER_SET_TEMPO(seqPlayerIndex, tempo) \
+ AudioThread_QueueCmdS32(AUDIO_MK_CMD(AUDIOCMD_OP_SEQPLAYER_SET_TEMPO, seqPlayerIndex, 0, 0), tempo)
+
+/**
+ * Set the transposition
+ *
+ * @param seqPlayerIndex the index of the seqPlayer to modify
+ * @param transposition (s8) the number of semitones to increase or decrease by for all notes on the seqPlayer
+ */
+#define AUDIOCMD_SEQPLAYER_SET_TRANSPOSITION(seqPlayerIndex, transposition) \
+ AudioThread_QueueCmdS8(AUDIO_MK_CMD(AUDIOCMD_OP_SEQPLAYER_SET_TRANSPOSITION, seqPlayerIndex, 0, 0), transposition)
+
+/**
+ * Set tempoChange in bpm
+ *
+ * @param seqPlayerIndex the index of the seqPlayer to modify
+ * @param tempoChange (s32) difference in tempo to change, in bpm
+ */
+#define AUDIOCMD_SEQPLAYER_CHANGE_TEMPO(seqPlayerIndex, tempoChange) \
+ AudioThread_QueueCmdS32(AUDIO_MK_CMD(AUDIOCMD_OP_SEQPLAYER_CHANGE_TEMPO, seqPlayerIndex, 0, 0), tempoChange)
+
+/**
+ * Set tempoChange in seqTicks per minute
+ *
+ * @param seqPlayerIndex the index of the seqPlayer to modify
+ * @param tempoChange (s32) difference in tempo to change, in seqTicks per minute
+ */
+#define AUDIOCMD_SEQPLAYER_CHANGE_TEMPO_SEQTICKS(seqPlayerIndex, tempoChange) \
+ AudioThread_QueueCmdS32(AUDIO_MK_CMD(AUDIOCMD_OP_SEQPLAYER_CHANGE_TEMPO_SEQTICKS, seqPlayerIndex, 0, 0), tempoChange)
+
+/**
+ * Fade the volume to the target volume requested in the command
+ *
+ * @param seqPlayerIndex the index of the seqPlayer to modify
+ * @param fadeVolume target volume to fade to
+ * @param fadeTimer (s32) number of ticks to fade to `fadeVolume`
+ */
+#define AUDIOCMD_SEQPLAYER_FADE_TO_SET_VOLUME(seqPlayerIndex, fadeVolume, fadeTimer) \
+ AudioThread_QueueCmdS32(AUDIO_MK_CMD(AUDIOCMD_OP_SEQPLAYER_FADE_TO_SET_VOLUME, seqPlayerIndex, fadeVolume, 0), \
+ fadeTimer)
+
+/**
+ * Fade the volume to the current volume scaled by a scale factor
+ *
+ * @param seqPlayerIndex the index of the seqPlayer to modify
+ * @param fadeVolumeScale scaling factor to apply to volume to get the targetVolume
+ * @param fadeTimer (s32) number of ticks to fade to `targetVolume`
+ */
+#define AUDIOCMD_SEQPLAYER_FADE_TO_SCALED_VOLUME(seqPlayerIndex, fadeVolumeScale, fadeTimer) \
+ AudioThread_QueueCmdS32( \
+ AUDIO_MK_CMD(AUDIOCMD_OP_SEQPLAYER_FADE_TO_SCALED_VOLUME, seqPlayerIndex, fadeVolumeScale, 0), fadeTimer)
+
+/**
+ * Reset to the default volume of the seqPlayer
+ *
+ * @param seqPlayerIndex the index of the seqPlayer to modify
+ * @param fadeTimer (s32) number of ticks to fade the sequence back to its default volume
+ */
+#define AUDIOCMD_SEQPLAYER_RESET_VOLUME(seqPlayerIndex, fadeTimer) \
+ AudioThread_QueueCmdS32(AUDIO_MK_CMD(AUDIOCMD_OP_SEQPLAYER_RESET_VOLUME, seqPlayerIndex, 0, 0), fadeTimer)
+
+/**
+ * Set the bend
+ *
+ * @param seqPlayerIndex the index of the seqPlayer to modify
+ * @param bend (f32) ratio relative to 1.0f to scale channel frequencies by
+ */
+#define AUDIOCMD_SEQPLAYER_SET_BEND(seqPlayerIndex, bend) \
+ AudioThread_QueueCmdF32(AUDIO_MK_CMD(AUDIOCMD_OP_SEQPLAYER_SET_BEND, seqPlayerIndex, 0, 0), bend)
+
+// ==== Audio Thread Global Commands ====
+
+/**
+ * Synchronously load a sequence in parts
+ *
+ * @param seqId the id of the sequence to load, see `SeqId`
+ * @param flags set `& 1` to load the sequence, set `& 2` to load the soundfonts
+ */
+#define AUDIOCMD_GLOBAL_SYNC_LOAD_SEQ_PARTS(seqId, flags) \
+ AudioThread_QueueCmdS32(AUDIO_MK_CMD(AUDIOCMD_OP_GLOBAL_SYNC_LOAD_SEQ_PARTS, 0, seqId, flags), 0)
+
+/**
+ * Synchronously initialize a sequence player
+ *
+ * @param seqPlayerIndex the index of the seqPlayer to modify
+ * @param seqId the id of the sequence to play, see `SeqId`
+ * @param fadeInTimer (s32) number of ticks to fade in the sequence to the requested volume
+ */
+#define AUDIOCMD_GLOBAL_INIT_SEQPLAYER(seqPlayerIndex, seqId, fadeInTimer) \
+ AudioThread_QueueCmdS32(AUDIO_MK_CMD(AUDIOCMD_OP_GLOBAL_INIT_SEQPLAYER, seqPlayerIndex, seqId, 0), fadeInTimer)
+
+/**
+ * Disable a sequence player
+ *
+ * @param seqPlayerIndex the index of the seqPlayer to modify
+ * @param fadeOutTimer (s32) number of ticks to fade out the sequence
+ */
+#define AUDIOCMD_GLOBAL_DISABLE_SEQPLAYER(seqPlayerIndex, fadeOutTimer) \
+ AudioThread_QueueCmdS32(AUDIO_MK_CMD(AUDIOCMD_OP_GLOBAL_DISABLE_SEQPLAYER, seqPlayerIndex, 0, 0), fadeOutTimer)
+
+/**
+ * Synchronously initialize a sequence player and skip ticks,
+ * allowing the sequence to start somewhere other than the beginning of the sequences
+ *
+ * @param seqPlayerIndex the index of the seqPlayer to modify
+ * @param seqId the id of the sequence to play, see `SeqId`
+ * @param skipTicks (s32) number of ticks to skip before starting the sequence
+ */
+#define AUDIOCMD_GLOBAL_INIT_SEQPLAYER_SKIP_TICKS(seqPlayerIndex, seqId, skipTicks) \
+ AudioThread_QueueCmdS32(AUDIO_MK_CMD(AUDIOCMD_OP_GLOBAL_INIT_SEQPLAYER_SKIP_TICKS, seqPlayerIndex, seqId, 0), \
+ skipTicks)
+
+/**
+ * When processing an audio thread channel command on all channels, set which channels to process
+ *
+ * @param seqPlayerIndex the index of the seqPlayer to modify
+ * @param threadCmdChannelMask (u16) bitfield for 16 channels. Turn bit on to allow audio thread commands of type
+ * "Channel" to process that channel with `AUDIOCMD_ALL_CHANNELS` set.
+ */
+#define AUDIOCMD_GLOBAL_SET_CHANNEL_MASK(seqPlayerIndex, threadCmdChannelMask) \
+ AudioThread_QueueCmdU16(AUDIO_MK_CMD(AUDIOCMD_OP_GLOBAL_SET_CHANNEL_MASK, seqPlayerIndex, 0, 0), \
+ threadCmdChannelMask)
+
+/**
+ * Set a drum ptr within a soundfont
+ *
+ * @param fontId the id of the soundfont to set the drum in
+ * @param drumId the id of the drum to set
+ * @param drumPtr (s32) the ptr to the `Drum` struct
+ */
+#define AUDIOCMD_GLOBAL_SET_DRUM_FONT(fontId, drumId, drumPtr) \
+ AudioThread_QueueCmdS32(AUDIO_MK_CMD(AUDIOCMD_OP_GLOBAL_SET_DRUM_FONT, fontId, drumId, 0), drumPtr)
+
+/**
+ * Set a soundeffect ptr within a soundfont
+ *
+ * @param fontId the id of the soundfont to set the sound effect in
+ * @param soundEffectId the id of the sound effect to set
+ * @param soundEffectPtr (s32) the ptr to the `SoundEffect` struct
+ */
+#define AUDIOCMD_GLOBAL_SET_SFX_FONT(fontId, soundEffectId, soundEffectPtr) \
+ AudioThread_QueueCmdS32(AUDIO_MK_CMD(AUDIOCMD_OP_GLOBAL_SET_SFX_FONT, fontId, soundEffectId, 0), soundEffectPtr)
+
+/**
+ * Set an instrument ptr within a soundfont
+ *
+ * @param fontId the id of the soundfont to set the instrument in
+ * @param instId the id of the instrument to set
+ * @param instPtr (s32) the ptr to the `Instrument` struct
+ */
+#define AUDIOCMD_GLOBAL_SET_INSTRUMENT_FONT(fontId, instId, instPtr) \
+ AudioThread_QueueCmdS32(AUDIO_MK_CMD(AUDIOCMD_OP_GLOBAL_SET_INSTRUMENT_FONT, fontId, instId, 0), instPtr)
+
+/**
+ * Pop the persistent cache of the specified table
+ *
+ * @param tableType (s32) see the `SampleBankTableType` enum
+ */
+#define AUDIOCMD_GLOBAL_POP_PERSISTENT_CACHE(tableType) \
+ AudioThread_QueueCmdS32(AUDIO_MK_CMD(AUDIOCMD_OP_GLOBAL_POP_PERSISTENT_CACHE, 0, 0, 0), tableType)
+
+/**
+ * Change the sound mode of audio
+ *
+ * @param soundMode (s32) see the `SoundMode` enum
+ */
+#define AUDIOCMD_GLOBAL_SET_SOUND_MODE(soundMode) \
+ AudioThread_QueueCmdS32(AUDIO_MK_CMD(AUDIOCMD_OP_GLOBAL_SET_SOUND_MODE, 0, 0, 0), soundMode)
+
+/**
+ * Mute all sequence players
+ */
+#define AUDIOCMD_GLOBAL_MUTE() \
+ AudioThread_QueueCmdS32(AUDIO_MK_CMD(AUDIOCMD_OP_GLOBAL_MUTE, 0, 0, 0), 0)
+
+/**
+ * Unmute all sequence players
+ *
+ * @param restartNotes (s32) if set to 1, then notes with the `MUTE_BEHAVIOR_STOP_SAMPLES` flag set
+ * are marked as finished for all seqPlayers
+ */
+#define AUDIOCMD_GLOBAL_UNMUTE(restartNotes) \
+ AudioThread_QueueCmdS32(AUDIO_MK_CMD(AUDIOCMD_OP_GLOBAL_UNMUTE, 0, 0, 0), restartNotes)
+
+/**
+ * Synchronously load an instrument
+ *
+ * @param fontId the id of the soundfont to load
+ * @param instId If below 0x7F, the id of the instrument to use. If equal to 0x7F, load the drum using the drumId
+ * @param drumId the id of the drum to use
+ */
+#define AUDIOCMD_GLOBAL_SYNC_LOAD_INSTRUMENT(fontId, instId, drumId) \
+ AudioThread_QueueCmdS8(AUDIO_MK_CMD(AUDIOCMD_OP_GLOBAL_SYNC_LOAD_INSTRUMENT, fontId, instId, drumId), 0)
+
+/**
+ * Asynchronously load a sample bank
+ *
+ * @param sampleBankId the id of the samplebank to load
+ * @param retData return data from `externalLoadQueue`
+ */
+#define AUDIOCMD_GLOBAL_ASYNC_LOAD_SAMPLE_BANK(sampleBankId, retData) \
+ AudioThread_QueueCmdS8(AUDIO_MK_CMD(AUDIOCMD_OP_GLOBAL_ASYNC_LOAD_SAMPLE_BANK, sampleBankId, 0, retData), 0)
+
+/**
+ * Asynchronously load a font
+ *
+ * @param fontId the id of the soundfont to load
+ * @param retData return data from `externalLoadQueue`
+ */
+#define AUDIOCMD_GLOBAL_ASYNC_LOAD_FONT(fontId, retData) \
+ AudioThread_QueueCmdS8(AUDIO_MK_CMD(AUDIOCMD_OP_GLOBAL_ASYNC_LOAD_FONT, fontId, 0, retData), 0)
+
+/**
+ * Discard sequence fonts
+ *
+ * @param seqId the id of the sequence to discard, see `SeqId`
+ */
+#define AUDIOCMD_GLOBAL_DISCARD_SEQ_FONTS(seqId) \
+ AudioThread_QueueCmdS32(AUDIO_MK_CMD(AUDIOCMD_OP_GLOBAL_DISCARD_SEQ_FONTS, 0, seqId, 0), 0)
+
+/**
+ * Stop processing all audio thread commands
+ */
+#define AUDIOCMD_GLOBAL_STOP_AUDIOCMDS() \
+ AudioThread_QueueCmdS32(AUDIO_MK_CMD(AUDIOCMD_OP_GLOBAL_STOP_AUDIOCMDS, 0, 0, 0), 0)
+
+/**
+ * Reset Audio Heap
+ *
+ * @param specId (s32) index for the audio specifications to set high-level audio parameters
+ */
+#define AUDIOCMD_GLOBAL_RESET_AUDIO_HEAP(specId) \
+ AudioThread_QueueCmdS32(AUDIO_MK_CMD(AUDIOCMD_OP_GLOBAL_RESET_AUDIO_HEAP, 0, 0, 0), specId)
+
+/**
+ * No Operation. No code exists for this OP
+ *
+ * @param arg0 No info
+ * @param arg1 No info
+ * @param arg2 No info
+ * @param data (s32) No info
+ */
+#define AUDIOCMD_GLOBAL_NOOP_1(arg0, arg1, arg2, data) \
+ AudioThread_QueueCmdS32(AUDIO_MK_CMD(AUDIOCMD_OP_GLOBAL_NOOP_1, arg0, arg1, arg2), data)
+
+/**
+ * Set a custom function that runs every audio thread update, see `AudioCustomUpdateFunction`
+ *
+ * @param functionPtr (s32) address of the function to run once every audio frame
+ */
+#define AUDIOCMD_GLOBAL_SET_CUSTOM_UPDATE_FUNCTION(functionPtr) \
+ AudioThread_QueueCmdS32(AUDIO_MK_CMD(AUDIOCMD_OP_GLOBAL_SET_CUSTOM_UPDATE_FUNCTION, 0, 0, 0), functionPtr)
+
+/**
+ * Asynchronously load a sequence
+ *
+ * @param seqId the id of the sequence to load, see `SeqId`
+ * @param retData return data from `externalLoadQueue`
+ */
+#define AUDIOCMD_GLOBAL_ASYNC_LOAD_SEQ(seqId, retData) \
+ AudioThread_QueueCmdS8(AUDIO_MK_CMD(AUDIOCMD_OP_GLOBAL_ASYNC_LOAD_SEQ, seqId, 0, retData), 0)
+
+/**
+ * No Operation. No code exists for this OP
+ *
+ * @param arg0 No info
+ * @param arg1 No info
+ * @param arg2 No info
+ * @param data (s32) No info
+ */
+#define AUDIOCMD_GLOBAL_NOOP_2(arg0, arg1, arg2, data) \
+ AudioThread_QueueCmdS32(AUDIO_MK_CMD(AUDIOCMD_OP_GLOBAL_NOOP_2, arg0, arg1, arg2), data)
+
+/**
+ * Disable all sequence players
+ *
+ * @param flags (s32) Set `& 1` to discard all sequences.
+ *
+ * @note Setting `& 3` will also only discard sampled notes, but the sequences are disabled anyway.
+ * Not setting `& 1` should make this command useless TODO: Test
+ */
+#define AUDIOCMD_GLOBAL_DISABLE_ALL_SEQPLAYERS(flags) \
+ AudioThread_QueueCmdS32(AUDIO_MK_CMD(AUDIOCMD_OP_GLOBAL_DISABLE_ALL_SEQPLAYERS, 0, 0, 0), flags)
+
+#endif
diff --git a/include/functions.h b/include/functions.h
index fd6187141..8305b9410 100644
--- a/include/functions.h
+++ b/include/functions.h
@@ -1536,20 +1536,22 @@ void AudioLoad_LoadPermanentSamples(void);
void AudioLoad_ScriptLoad(s32 tableType, s32 id, s8* status);
void AudioLoad_ProcessScriptLoads(void);
void AudioLoad_InitScriptLoads(void);
-AudioTask* func_800E4FE0(void);
-void Audio_QueueCmdF32(u32 opArgs, f32 data);
-void Audio_QueueCmdS32(u32 opArgs, s32 data);
-void Audio_QueueCmdS8(u32 opArgs, s8 data);
-void Audio_QueueCmdU16(u32 opArgs, u16 data);
-s32 Audio_ScheduleProcessCmds(void);
+
+AudioTask* AudioThread_Update(void);
+void AudioThread_QueueCmdF32(u32 opArgs, f32 data);
+void AudioThread_QueueCmdS32(u32 opArgs, s32 data);
+void AudioThread_QueueCmdS8(u32 opArgs, s8 data);
+void AudioThread_QueueCmdU16(u32 opArgs, u16 data);
+s32 AudioThread_ScheduleProcessCmds(void);
u32 func_800E5E20(u32* out);
-u8* func_800E5E84(s32 arg0, u32* arg1);
+u8* AudioThread_GetFontsForSequence(s32 seqId, u32* outNumFonts);
s32 func_800E5EDC(void);
-s32 func_800E5F88(s32 resetPreloadID);
-void Audio_PreNMIInternal(void);
+s32 AudioThread_ResetAudioHeap(s32 specId);
+void AudioThread_PreNMIInternal(void);
s32 func_800E6680(void);
-u32 Audio_NextRandom(void);
-void Audio_InitMesgQueues(void);
+u32 AudioThread_NextRandom(void);
+void AudioThread_InitMesgQueues(void);
+
void Audio_InvalDCache(void* buf, s32 size);
void Audio_WritebackDCache(void* buf, s32 size);
s32 osAiSetNextBuffer(void*, u32);
@@ -1616,8 +1618,8 @@ s32 AudioOcarina_MemoryGameNextNote(void);
void AudioOcarina_PlayLongScarecrowSong(void);
void AudioDebug_Draw(GfxPrint* printer);
void AudioDebug_ScrPrt(const char* str, u16 num);
-void func_800F3054(void);
-void Audio_SetSfxProperties(u8 bankId, u8 entryIdx, u8 channelIdx);
+void Audio_Update(void);
+void Audio_SetSfxProperties(u8 bankId, u8 entryIdx, u8 channelIndex);
void Audio_PlayCutsceneEffectsSequence(u8 csEffectType);
void func_800F4010(Vec3f* pos, u16 sfxId, f32);
void Audio_PlaySfxRandom(Vec3f* pos, u16 baseSfxId, u8 randLim);
@@ -1680,8 +1682,8 @@ void Audio_InitSound(void);
void func_800F7170(void);
void func_800F71BC(s32 arg0);
void Audio_SetSfxBanksMute(u16 muteMask);
-void Audio_QueueSeqCmdMute(u8 channelIdx);
-void Audio_ClearBGMMute(u8 channelIdx);
+void Audio_QueueSeqCmdMute(u8 channelIndex);
+void Audio_ClearBGMMute(u8 channelIndex);
void Audio_PlaySfxGeneral(u16 sfxId, Vec3f* pos, u8 token, f32* freqScale, f32* vol, s8* reverbAdd);
void Audio_ProcessSfxRequest(void);
void Audio_ChooseActiveSfx(u8 bankId);
diff --git a/include/seqcmd.h b/include/seqcmd.h
index a2649b775..f6c42b701 100644
--- a/include/seqcmd.h
+++ b/include/seqcmd.h
@@ -10,10 +10,10 @@ typedef enum {
/* 0x1 */ SEQCMD_OP_STOP_SEQUENCE,
/* 0x2 */ SEQCMD_OP_QUEUE_SEQUENCE,
/* 0x3 */ SEQCMD_OP_UNQUEUE_SEQUENCE,
- /* 0x4 */ SEQCMD_OP_SET_PLAYER_VOLUME,
- /* 0x5 */ SEQCMD_OP_SET_PLAYER_FREQ,
+ /* 0x4 */ SEQCMD_OP_SET_SEQPLAYER_VOLUME,
+ /* 0x5 */ SEQCMD_OP_SET_SEQPLAYER_FREQ,
/* 0x6 */ SEQCMD_OP_SET_CHANNEL_VOLUME,
- /* 0x7 */ SEQCMD_OP_SET_PLAYER_IO,
+ /* 0x7 */ SEQCMD_OP_SET_SEQPLAYER_IO,
/* 0x8 */ SEQCMD_OP_SET_CHANNEL_IO,
/* 0x9 */ SEQCMD_OP_SET_CHANNEL_IO_DISABLE_MASK,
/* 0xA */ SEQCMD_OP_SET_CHANNEL_DISABLE_MASK,
@@ -37,17 +37,17 @@ typedef enum {
// Subset of `SEQCMD_OP_SETUP_CMD`
typedef enum {
- /* 0x0 */ SEQCMD_SUB_OP_SETUP_RESTORE_VOLUME,
+ /* 0x0 */ SEQCMD_SUB_OP_SETUP_RESTORE_SEQPLAYER_VOLUME,
/* 0x1 */ SEQCMD_SUB_OP_SETUP_SEQ_UNQUEUE,
/* 0x2 */ SEQCMD_SUB_OP_SETUP_RESTART_SEQ,
/* 0x3 */ SEQCMD_SUB_OP_SETUP_TEMPO_SCALE,
/* 0x4 */ SEQCMD_SUB_OP_SETUP_TEMPO_RESET,
/* 0x5 */ SEQCMD_SUB_OP_SETUP_PLAY_SEQ,
/* 0x6 */ SEQCMD_SUB_OP_SETUP_SET_FADE_TIMER,
- /* 0x7 */ SEQCMD_SUB_OP_SETUP_RESTORE_VOLUME_IF_QUEUED,
- /* 0x8 */ SEQCMD_SUB_OP_SETUP_RESTORE_VOLUME_WITH_SCALE_INDEX,
+ /* 0x7 */ SEQCMD_SUB_OP_SETUP_RESTORE_SEQPLAYER_VOLUME_IF_QUEUED,
+ /* 0x8 */ SEQCMD_SUB_OP_SETUP_RESTORE_SEQPLAYER_VOLUME_WITH_SCALE_INDEX,
/* 0x9 */ SEQCMD_SUB_OP_SETUP_SET_CHANNEL_DISABLE_MASK,
- /* 0xA */ SEQCMD_SUB_OP_SETUP_SET_PLAYER_FREQ,
+ /* 0xA */ SEQCMD_SUB_OP_SETUP_SET_SEQPLAYER_FREQ,
/* 0xE */ SEQCMD_SUB_OP_SETUP_POP_PERSISTENT_CACHE = 0xE,
/* 0xF */ SEQCMD_SUB_OP_SETUP_RESET_SETUP_CMDS
} SeqCmdSetupCmdOp;
@@ -64,13 +64,15 @@ typedef enum {
* Play a sequence on a given seqPlayer
*
* @param seqPlayerIndex the index of the seqPlayer to play the sequence
- * @param fadeInDuration duration the sequence will fade in over
- * @param seqArg no effect: < 0x7F, skip ticks: = 0x7F, will not play: >= 0x80 (see note)
+ * @param fadeInDuration effect will depend on seqArg. See below
+ * @param seqArg no effect: < 0x7F, skip ahead: = 0x7F, will not play: >= 0x80 (see note)
* @param seqId the id of the sequence to play, see `SeqId`
*
* @note seqArg will also be stored in gActiveSeqs.seqId, any check against that seqId must also include seqArg.
- * seqArg = 0x7F will interpret the duration as the number of ticks to skip.
- * seqArg >= 0x80 was intented to load a soundFont asynchronously but the code is unfinished (based on MM).
+ * seqArg < 0x7F: fade in the sequence over `fadeInDuration` in units of (1/30th) seconds
+ * seqArg = 0x7F: start the sequence immediately, but begins `fadeInDuration` number of second into the sequence.
+ * seqArg >= 0x80: no sequence will play. Intended to load a soundFont asynchronously but was only half implemented
+ * (inferred from MM).
*/
#define SEQCMD_PLAY_SEQUENCE(seqPlayerIndex, fadeInDuration, seqArg, seqId) \
Audio_QueueSeqCmd((SEQCMD_OP_PLAY_SEQUENCE << 28) | ((u8)(seqPlayerIndex) << 24) | ((u8)(fadeInDuration) << 16) | \
@@ -79,7 +81,7 @@ typedef enum {
/**
* Stop a sequence on a given seqPlayer
*
- * @param seqPlayerIndex the index of the seqPlayer to play the sequence
+ * @param seqPlayerIndex the index of the seqPlayer to stop the sequence
* @param fadeOutDuration duration the sequence will fade out over
*
* @note the 0xFF in the command is not read from at all, but is common in all Stop SeqPlayer Commands
@@ -125,8 +127,8 @@ typedef enum {
* @param duration duration to transition to the volume
* @param volume the target volume for the sequence. Ranged from 0-0xFF, with 0x7F mapping to 1.0f
*/
-#define SEQCMD_SET_PLAYER_VOLUME(seqPlayerIndex, duration, volume) \
- Audio_QueueSeqCmd((SEQCMD_OP_SET_PLAYER_VOLUME << 28) | ((u8)(seqPlayerIndex) << 24) | ((duration) << 16) | \
+#define SEQCMD_SET_SEQPLAYER_VOLUME(seqPlayerIndex, duration, volume) \
+ Audio_QueueSeqCmd((SEQCMD_OP_SET_SEQPLAYER_VOLUME << 28) | ((u8)(seqPlayerIndex) << 24) | ((duration) << 16) | \
(volume))
/**
@@ -139,8 +141,8 @@ typedef enum {
* @note 2000 will double the frequency (raise an octave), 500 will halve the frequency (lower an octave).
* Cannot be used with `SEQCMD_SET_CHANNEL_FREQ` as they will overwrite one another.
*/
-#define SEQCMD_SET_PLAYER_FREQ(seqPlayerIndex, duration, freqScale) \
- Audio_QueueSeqCmd((SEQCMD_OP_SET_PLAYER_FREQ << 28) | ((u8)(seqPlayerIndex) << 24) | ((duration) << 16) | \
+#define SEQCMD_SET_SEQPLAYER_FREQ(seqPlayerIndex, duration, freqScale) \
+ Audio_QueueSeqCmd((SEQCMD_OP_SET_SEQPLAYER_FREQ << 28) | ((u8)(seqPlayerIndex) << 24) | ((duration) << 16) | \
(freqScale))
/**
@@ -152,7 +154,7 @@ typedef enum {
* @param freqScale the scaling factor to shift the pitch. Ranged from 0-0xFFF, with 1000 mapping to 1.0f
*
* @note a frequency of 2000 will double the frequency (raise an octave), 500 will halve the frequency (lower an octave).
- * Cannot be used with `SEQCMD_SET_PLAYER_FREQ` as they will overwrite one another.
+ * Cannot be used with `SEQCMD_SET_SEQPLAYER_FREQ` as they will overwrite one another.
*/
#define SEQCMD_SET_CHANNEL_FREQ(seqPlayerIndex, channelIndex, duration, freqScale) \
Audio_QueueSeqCmd((SEQCMD_OP_SET_CHANNEL_FREQ << 28) | ((u8)(seqPlayerIndex) << 24) | ((duration) << 16) | \
@@ -175,15 +177,15 @@ typedef enum {
* ioPort, which can affect the entire sequence.
*
* @param seqPlayerIndex the index of the seqPlayer to write the input to
- * @param ioPort the index of the array to store the input-output value,
+ * @param ioPort the index of the array to store the input-output value
* @param ioData the value s8 that's written to the input-output array
*
* @note Each seqPlayer has 8 global ioPorts indexed 0-7.
* ioPort 0 and 1 are read-only-once, and will reset after being read by the sequence.
* ioPort 2-7 can be read multiple times.
*/
-#define SEQCMD_SET_PLAYER_IO(seqPlayerIndex, ioPort, ioData) \
- Audio_QueueSeqCmd((SEQCMD_OP_SET_PLAYER_IO << 28) | ((u8)(seqPlayerIndex) << 24) | ((u8)(ioPort) << 16) | \
+#define SEQCMD_SET_SEQPLAYER_IO(seqPlayerIndex, ioPort, ioData) \
+ Audio_QueueSeqCmd((SEQCMD_OP_SET_SEQPLAYER_IO << 28) | ((u8)(seqPlayerIndex) << 24) | ((u8)(ioPort) << 16) | \
(u8)(ioData))
/**
@@ -209,7 +211,7 @@ typedef enum {
* @param seqPlayerIndex the index of the seqPlayer to modify
* @param channelMask a 16 bit mask where each bit maps to a channel. Bitflag on to disable
*
- * @note using Audio_QueueCmdS8 0x06 will bypass this channelMask
+ * @note using AUDIOCMD_CHANNEL_SET_IO will bypass this channelMask
*/
#define SEQCMD_SET_CHANNEL_IO_DISABLE_MASK(seqPlayerIndex, channelMask) \
Audio_QueueSeqCmd((SEQCMD_OP_SET_CHANNEL_IO_DISABLE_MASK << 28) | ((u8)(seqPlayerIndex) << 24) | (u16)(channelMask))
@@ -304,8 +306,8 @@ typedef enum {
* @param targetSeqPlayerIndex the index of the seqPlayer to modify
* @param duration duration to transition to the volume
*/
-#define SEQCMD_SETUP_RESTORE_PLAYER_VOLUME(setupSeqPlayerIndex, targetSeqPlayerIndex, duration) \
- Audio_QueueSeqCmd((SEQCMD_OP_SETUP_CMD << 28) | (SEQCMD_SUB_OP_SETUP_RESTORE_VOLUME << 20) | \
+#define SEQCMD_SETUP_RESTORE_SEQPLAYER_VOLUME(setupSeqPlayerIndex, targetSeqPlayerIndex, duration) \
+ Audio_QueueSeqCmd((SEQCMD_OP_SETUP_CMD << 28) | (SEQCMD_SUB_OP_SETUP_RESTORE_SEQPLAYER_VOLUME << 20) | \
((u8)(setupSeqPlayerIndex) << 24) | ((u8)(targetSeqPlayerIndex) << 16) | (u8)(duration))
/**
@@ -394,9 +396,9 @@ typedef enum {
* @param duration duration to transition to the volume
* @param numSeqRequests the number of sequence requests queued that must match the actual number of sequence requests
*/
-#define SEQCMD_SETUP_RESTORE_PLAYER_VOLUME_IF_QUEUED(setupSeqPlayerIndex, targetSeqPlayerIndex, duration, \
- numSeqRequests) \
- Audio_QueueSeqCmd((SEQCMD_OP_SETUP_CMD << 28) | (SEQCMD_SUB_OP_SETUP_RESTORE_VOLUME_IF_QUEUED << 20) | \
+#define SEQCMD_SETUP_RESTORE_SEQPLAYER_VOLUME_IF_QUEUED(setupSeqPlayerIndex, targetSeqPlayerIndex, duration, \
+ numSeqRequests) \
+ Audio_QueueSeqCmd((SEQCMD_OP_SETUP_CMD << 28) | (SEQCMD_SUB_OP_SETUP_RESTORE_SEQPLAYER_VOLUME_IF_QUEUED << 20) | \
((u8)(setupSeqPlayerIndex) << 24) | ((u8)(targetSeqPlayerIndex) << 16) | ((u8)(duration) << 8) | \
(u8)(numSeqRequests))
@@ -409,9 +411,11 @@ typedef enum {
* @param scaleIndex the scale index of a seqPlayer
* @param duration duration to transition to the volume
*/
-#define SEQCMD_SETUP_RESTORE_PLAYER_VOLUME_WITH_SCALE_INDEX(setupSeqPlayerIndex, targetSeqPlayerIndex, scaleIndex, duration) \
- Audio_QueueSeqCmd((SEQCMD_OP_SETUP_CMD << 28) | (SEQCMD_SUB_OP_SETUP_RESTORE_VOLUME_WITH_SCALE_INDEX << 20) | \
- ((u8)(setupSeqPlayerIndex) << 24) | ((u8)(targetSeqPlayerIndex) << 16) | \
+#define SEQCMD_SETUP_RESTORE_SEQPLAYER_VOLUME_WITH_SCALE_INDEX(setupSeqPlayerIndex, targetSeqPlayerIndex, scaleIndex, \
+ duration) \
+ Audio_QueueSeqCmd((SEQCMD_OP_SETUP_CMD << 28) | \
+ (SEQCMD_SUB_OP_SETUP_RESTORE_SEQPLAYER_VOLUME_WITH_SCALE_INDEX << 20) | \
+ ((u8)(setupSeqPlayerIndex) << 24) | ((u8)(targetSeqPlayerIndex) << 16) | \
((u8)(scaleIndex) << 8) | (u8)(duration))
/**
@@ -438,8 +442,8 @@ typedef enum {
* @note The base value for frequency, 100, is 10 times smaller than other frequency commands.
* 200 will double the frequency (raise an octave), 50 will halve the frequency (lower an octave).
*/
-#define SEQCMD_SETUP_SET_PLAYER_FREQ(setupSeqPlayerIndex, targetSeqPlayerIndex, duration, freqScale) \
- Audio_QueueSeqCmd((SEQCMD_OP_SETUP_CMD << 28) | (SEQCMD_SUB_OP_SETUP_SET_PLAYER_FREQ << 20) | \
+#define SEQCMD_SETUP_SET_SEQPLAYER_FREQ(setupSeqPlayerIndex, targetSeqPlayerIndex, duration, freqScale) \
+ Audio_QueueSeqCmd((SEQCMD_OP_SETUP_CMD << 28) | (SEQCMD_SUB_OP_SETUP_SET_SEQPLAYER_FREQ << 20) | \
((u8)(setupSeqPlayerIndex) << 24) | ((u8)(targetSeqPlayerIndex) << 16) | ((u8)(duration) << 8) | \
(u8)(freqScale))
diff --git a/include/sfx.h b/include/sfx.h
index e008d1372..d5545af8d 100644
--- a/include/sfx.h
+++ b/include/sfx.h
@@ -21,24 +21,24 @@ typedef enum {
} SfxState;
typedef struct {
- /* 0x00 */ f32* posX;
- /* 0x04 */ f32* posY;
- /* 0x08 */ f32* posZ;
- /* 0x0C */ u8 token;
- /* 0x10 */ f32* freqScale;
- /* 0x14 */ f32* vol;
- /* 0x18 */ s8* reverbAdd;
- /* 0x1C */ f32 dist;
- /* 0x20 */ u32 priority; // lower is more prioritized
- /* 0x24 */ u8 sfxImportance;
- /* 0x26 */ u16 sfxParams;
- /* 0x28 */ u16 sfxId;
- /* 0x2A */ u8 state; // uses SfxState enum
- /* 0x2B */ u8 freshness;
- /* 0x2C */ u8 prev;
- /* 0x2D */ u8 next;
- /* 0x2E */ u8 channelIdx;
- /* 0x2F */ u8 unk_2F;
+ /* 0x00 */ f32* posX;
+ /* 0x04 */ f32* posY;
+ /* 0x08 */ f32* posZ;
+ /* 0x0C */ u8 token;
+ /* 0x10 */ f32* freqScale;
+ /* 0x14 */ f32* vol;
+ /* 0x18 */ s8* reverbAdd;
+ /* 0x1C */ f32 dist;
+ /* 0x20 */ u32 priority; // lower is more prioritized
+ /* 0x24 */ u8 sfxImportance;
+ /* 0x26 */ u16 sfxParams;
+ /* 0x28 */ u16 sfxId;
+ /* 0x2A */ u8 state; // uses SfxState enum
+ /* 0x2B */ u8 freshness;
+ /* 0x2C */ u8 prev;
+ /* 0x2D */ u8 next;
+ /* 0x2E */ u8 channelIndex;
+ /* 0x2F */ u8 unk_2F;
} SfxBankEntry; // size = 0x30
/*
diff --git a/include/variables.h b/include/variables.h
index 12b8e734b..922a3c15f 100644
--- a/include/variables.h
+++ b/include/variables.h
@@ -157,8 +157,7 @@ extern s32 gSystemArenaLogSeverity;
extern u8 __osPfsInodeCacheBank;
extern s32 __osPfsLastChannel;
-extern const s16 D_8014A6C0[];
-#define gTatumsPerBeat (D_8014A6C0[1])
+extern const TempoData gTempoData;
extern const AudioHeapInitSizes gAudioHeapInitSizes;
extern s16 gOcarinaSongItemMap[];
extern u8 gSoundFontTable[];
@@ -215,7 +214,7 @@ extern u16 gAudioSfxSwapTarget[10];
extern u8 gAudioSfxSwapMode[10];
extern ActiveSequence gActiveSeqs[4];
extern AudioContext gAudioCtx;
-extern void(*D_801755D0)(void);
+extern AudioCustomUpdateFunction gAudioCustomUpdateFunction;
extern u32 __osMalloc_FreeBlockTest_Enable;
extern Arena gSystemArena;
diff --git a/include/z64.h b/include/z64.h
index 976d932cc..0d8b37d84 100644
--- a/include/z64.h
+++ b/include/z64.h
@@ -38,6 +38,7 @@
#include "z64view.h"
#include "z64vis.h"
#include "alignment.h"
+#include "audiothread_cmd.h"
#include "seqcmd.h"
#include "sequence.h"
#include "sfx.h"
diff --git a/include/z64audio.h b/include/z64audio.h
index 7e6f4e40b..1ec0f4a4d 100644
--- a/include/z64audio.h
+++ b/include/z64audio.h
@@ -1,11 +1,25 @@
#ifndef Z64_AUDIO_H
#define Z64_AUDIO_H
-#define MK_CMD(b0,b1,b2,b3) ((((b0) & 0xFF) << 0x18) | (((b1) & 0xFF) << 0x10) | (((b2) & 0xFF) << 0x8) | (((b3) & 0xFF) << 0))
+typedef void (*AudioCustomUpdateFunction)(void);
+
+
+#define REFRESH_RATE_PAL 50
+#define REFRESH_RATE_MPAL 60
+#define REFRESH_RATE_NTSC 60
+
+// Small deviation parameters used in estimating the max tempo
+// It is unclear why these vary by region, and aren't all just 1
+#define REFRESH_RATE_DEVIATION_PAL 1.001521f
+#define REFRESH_RATE_DEVIATION_MPAL 0.99276f
+#define REFRESH_RATE_DEVIATION_NTSC 1.00278f
+
+#define AUDIO_MK_CMD(b0,b1,b2,b3) ((((b0) & 0xFF) << 0x18) | (((b1) & 0xFF) << 0x10) | (((b2) & 0xFF) << 0x8) | (((b3) & 0xFF) << 0))
#define NO_LAYER ((SequenceLayer*)(-1))
-#define TATUMS_PER_BEAT 48
+// Also known as "Pulses Per Quarter Note" or "Tatums Per Beat"
+#define SEQTICKS_PER_BEAT 48
#define IS_SEQUENCE_CHANNEL_VALID(ptr) ((u32)(ptr) != (u32)&gAudioCtx.sequenceChannelNone)
#define SEQ_NUM_CHANNELS 16
@@ -297,12 +311,12 @@ typedef struct {
/* 0x005 */ u8 defaultFont;
/* 0x006 */ u8 unk_06[1];
/* 0x007 */ s8 playerIdx;
- /* 0x008 */ u16 tempo; // tatums per minute
- /* 0x00A */ u16 tempoAcc;
- /* 0x00C */ u16 unk_0C;
+ /* 0x008 */ u16 tempo; // seqTicks per minute
+ /* 0x00A */ u16 tempoAcc; // tempo accumulation, used in a discretized algorithm to apply tempo.
+ /* 0x00C */ u16 tempoChange; // Used to adjust the tempo without altering the base tempo.
/* 0x00E */ s16 transposition;
/* 0x010 */ u16 delay;
- /* 0x012 */ u16 fadeTimer;
+ /* 0x012 */ u16 fadeTimer; // in ticks
/* 0x014 */ u16 fadeTimerUnkEu;
/* 0x018 */ u8* seqData;
/* 0x01C */ f32 fadeVolume;
@@ -320,7 +334,7 @@ typedef struct {
/* 0x0DC */ s32 skipTicks;
/* 0x0E0 */ u32 scriptCounter;
/* 0x0E4 */ char unk_E4[0x74]; // unused struct members for sequence/sound font dma management, according to sm64 decomp
- /* 0x158 */ s8 soundScriptIO[8];
+ /* 0x158 */ s8 seqScriptIO[8];
} SequencePlayer; // size = 0x160
typedef struct {
@@ -332,7 +346,7 @@ typedef struct {
typedef struct {
/* 0x00 */ union {
struct A {
- /* 0x00 */ u8 unk_0b80 : 1;
+ /* 0x00 */ u8 unused : 1;
/* 0x00 */ u8 hang : 1;
/* 0x00 */ u8 decay : 1;
/* 0x00 */ u8 release : 1;
@@ -370,8 +384,8 @@ typedef struct {
/* 0x01 */ u8 gain; // Increases volume by a multiplicative scaling factor. Represented as a UQ4.4 number
/* 0x02 */ u8 pan;
/* 0x03 */ Stereo stereo;
- /* 0x04 */ u8 unk_4;
- /* 0x06 */ u16 unk_6;
+ /* 0x04 */ u8 combFilterSize;
+ /* 0x06 */ u16 combFilterGain;
/* 0x08 */ f32 freqScale;
/* 0x0C */ f32 velocity;
/* 0x10 */ s16* filter;
@@ -383,7 +397,7 @@ typedef struct SequenceChannel {
/* 0x00 */ u8 enabled : 1;
/* 0x00 */ u8 finished : 1;
/* 0x00 */ u8 stopScript : 1;
- /* 0x00 */ u8 stopSomething2 : 1; // sets SequenceLayer.stopSomething
+ /* 0x00 */ u8 muted : 1; // sets SequenceLayer.muted
/* 0x00 */ u8 hasInstrument : 1;
/* 0x00 */ u8 stereoHeadsetEffects : 1;
/* 0x00 */ u8 largeNotes : 1; // notes specify duration and velocity
@@ -398,7 +412,7 @@ typedef struct SequenceChannel {
} changes;
/* 0x02 */ u8 noteAllocPolicy;
/* 0x03 */ u8 muteBehavior;
- /* 0x04 */ u8 reverb; // or dry/wet mix
+ /* 0x04 */ u8 targetReverbVol;
/* 0x05 */ u8 notePriority; // 0-3
/* 0x06 */ u8 someOtherPriority;
/* 0x07 */ u8 fontId;
@@ -409,16 +423,16 @@ typedef struct SequenceChannel {
/* 0x0C */ u8 gain; // Increases volume by a multiplicative scaling factor. Represented as a UQ4.4 number
/* 0x0D */ u8 velocityRandomVariance;
/* 0x0E */ u8 gateTimeRandomVariance;
- /* 0x0F */ u8 unk_0F;
+ /* 0x0F */ u8 combFilterSize;
/* 0x10 */ u16 vibratoRateStart;
- /* 0x12 */ u16 vibratoExtentStart;
+ /* 0x12 */ u16 vibratoDepthStart;
/* 0x14 */ u16 vibratoRateTarget;
- /* 0x16 */ u16 vibratoExtentTarget;
+ /* 0x16 */ u16 vibratoDepthTarget;
/* 0x18 */ u16 vibratoRateChangeDelay;
- /* 0x1A */ u16 vibratoExtentChangeDelay;
+ /* 0x1A */ u16 vibratoDepthChangeDelay;
/* 0x1C */ u16 vibratoDelay;
/* 0x1E */ u16 delay;
- /* 0x20 */ u16 unk_20;
+ /* 0x20 */ u16 combFilterGain;
/* 0x22 */ u16 unk_22;
/* 0x24 */ s16 instOrWave; // either 0 (none), instrument index + 1, or
// 0x80..0x83 for sawtooth/triangle/sine/square waves.
@@ -437,7 +451,7 @@ typedef struct SequenceChannel {
/* 0x60 */ SeqScriptState scriptState;
/* 0x7C */ AdsrSettings adsr;
/* 0x84 */ NotePool notePool;
- /* 0xC4 */ s8 soundScriptIO[8]; // bridge between sound script and audio lib, "io ports"
+ /* 0xC4 */ s8 seqScriptIO[8]; // bridge between .seq script and audio lib, "io ports"
/* 0xCC */ s16* filter;
/* 0xD0 */ Stereo stereo;
} SequenceChannel; // size = 0xD4
@@ -446,7 +460,7 @@ typedef struct SequenceChannel {
typedef struct SequenceLayer {
/* 0x00 */ u8 enabled : 1;
/* 0x00 */ u8 finished : 1;
- /* 0x00 */ u8 stopSomething : 1;
+ /* 0x00 */ u8 muted : 1;
/* 0x00 */ u8 continuousNotes : 1; // keep the same note for consecutive notes with the same sound
/* 0x00 */ u8 bit3 : 1; // "loaded"?
/* 0x00 */ u8 ignoreDrumPan : 1;
@@ -490,7 +504,7 @@ typedef struct {
/* 0x040 */ s16 mixEnvelopeState[32];
/* 0x080 */ s16 unusedState[16];
/* 0x0A0 */ s16 haasEffectDelayState[32];
- /* 0x0E0 */ s16 unkState[128];
+ /* 0x0E0 */ s16 combFilterState[128];
} NoteSynthesisBuffers; // size = 0x1E0
typedef struct {
@@ -505,23 +519,20 @@ typedef struct {
/* 0x0C */ NoteSynthesisBuffers* synthesisBuffers;
/* 0x10 */ s16 curVolLeft;
/* 0x12 */ s16 curVolRight;
- /* 0x14 */ u16 unk_14;
- /* 0x16 */ u16 unk_16;
- /* 0x18 */ u16 unk_18;
- /* 0x1A */ u8 unk_1A;
- /* 0x1C */ u16 unk_1C;
- /* 0x1E */ u16 unk_1E;
+ /* 0x14 */ char unk_14[0x6];
+ /* 0x1A */ u8 combFilterNeedsInit;
+ /* 0x1C */ char unk_1C[0x4];
} NoteSynthesisState; // size = 0x20
typedef struct {
/* 0x00 */ struct SequenceChannel* channel;
/* 0x04 */ u32 time;
- /* 0x08 */ s16* curve;
- /* 0x0C */ f32 extent;
+ /* 0x08 */ s16* curve; // sineWave
+ /* 0x0C */ f32 depth;
/* 0x10 */ f32 rate;
/* 0x14 */ u8 active;
/* 0x16 */ u16 rateChangeTimer;
- /* 0x18 */ u16 extentChangeTimer;
+ /* 0x18 */ u16 depthChangeTimer;
/* 0x1A */ u16 delay;
} VibratoState; // size = 0x1C
@@ -567,11 +578,11 @@ typedef struct {
/* 0x04 */ u8 haasEffectRightDelaySize;
/* 0x05 */ u8 reverbVol;
/* 0x06 */ u8 harmonicIndexCurAndPrev; // bits 3..2 store curHarmonicIndex, bits 1..0 store prevHarmonicIndex
- /* 0x07 */ u8 unk_07;
+ /* 0x07 */ u8 combFilterSize;
/* 0x08 */ u16 targetVolLeft;
/* 0x0A */ u16 targetVolRight;
/* 0x0C */ u16 resamplingRateFixedPoint;
- /* 0x0E */ u16 unk_0E;
+ /* 0x0E */ u16 combFilterGain;
/* 0x10 */ union {
TunedSample* tunedSample;
s16* waveSampleAddr; // used for synthetic waves
@@ -642,15 +653,15 @@ typedef struct {
/* 0x06 */ s16 samplesPerFrameTarget;
/* 0x08 */ s16 maxAiBufferLength;
/* 0x0A */ s16 minAiBufferLength;
- /* 0x0C */ s16 updatesPerFrame; // for each frame of the audio thread (default 60 fps), number of updates to process audio
- /* 0x0E */ s16 samplesPerUpdate;
- /* 0x10 */ s16 samplesPerUpdateMax;
- /* 0x12 */ s16 samplesPerUpdateMin;
+ /* 0x0C */ s16 ticksPerUpdate; // for each audio thread update, number of ticks to process audio
+ /* 0x0E */ s16 samplesPerTick;
+ /* 0x10 */ s16 samplesPerTickMax;
+ /* 0x12 */ s16 samplesPerTickMin;
/* 0x14 */ s16 numSequencePlayers;
/* 0x18 */ f32 resampleRate;
- /* 0x1C */ f32 updatesPerFrameInv; // inverse (reciprocal) of updatesPerFrame
- /* 0x20 */ f32 updatesPerFrameInvScaled; // updatesPerFrameInv scaled down by a factor of 256
- /* 0x24 */ f32 updatesPerFrameScaled; // updatesPerFrame scaled down by a factor of 4
+ /* 0x1C */ f32 ticksPerUpdateInv; // inverse (reciprocal) of ticksPerUpdate
+ /* 0x20 */ f32 ticksPerUpdateInvScaled; // ticksPerUpdateInv scaled down by a factor of 256
+ /* 0x24 */ f32 ticksPerUpdateScaled; // ticksPerUpdate scaled down by a factor of 4
} AudioBufferParameters; // size = 0x28
/**
@@ -887,7 +898,7 @@ typedef struct {
/* 0x288C */ s32 sampleDmaBufSize;
/* 0x2890 */ s32 maxAudioCmds;
/* 0x2894 */ s32 numNotes;
- /* 0x2898 */ s16 tempoInternalToExternal;
+ /* 0x2898 */ s16 maxTempo; // Maximum possible tempo (seqTicks per minute), using every tick as a seqTick to process a .seq file
/* 0x289A */ s8 soundMode;
/* 0x289C */ s32 totalTaskCount; // The total number of times the top-level function on the audio thread has run since audio was initialized
/* 0x28A0 */ s32 curAudioFrameDmaCount;
@@ -898,7 +909,7 @@ typedef struct {
/* 0x28B8 */ AudioTask* curTask;
/* 0x28BC */ char unk_28BC[0x4];
/* 0x28C0 */ AudioTask rspTask[2];
- /* 0x2960 */ f32 unk_2960;
+ /* 0x2960 */ f32 maxTempoTvTypeFactors; // tvType factors that impact maxTempo, in units of milliseconds/frame
/* 0x2964 */ s32 refreshRate;
/* 0x2968 */ s16* aiBuffers[3];
/* 0x2974 */ s16 aiBufLengths[3];
@@ -929,7 +940,7 @@ typedef struct {
/* 0x3468 */ u8 fontLoadStatus[0x30];
/* 0x3498 */ u8 seqLoadStatus[0x80];
/* 0x3518 */ volatile u8 resetStatus;
- /* 0x3519 */ u8 audioResetSpecIdToLoad;
+ /* 0x3519 */ u8 specId;
/* 0x351C */ s32 audioResetFadeOutFramesLeft;
/* 0x3520 */ f32* adsrDecayTable; // A table on the audio heap that stores decay rates used for adsr
/* 0x3524 */ u8* audioHeap;
@@ -941,20 +952,20 @@ typedef struct {
/* 0x5B84 */ s32 noteSubEuOffset;
/* 0x5B88 */ AudioListItem layerFreeList;
/* 0x5B98 */ NotePool noteFreeLists;
- /* 0x5BD8 */ u8 cmdWrPos;
- /* 0x5BD9 */ u8 cmdRdPos;
- /* 0x5BDA */ u8 cmdQueueFinished;
- /* 0x5BDC */ u16 unk_5BDC[4];
+ /* 0x5BD8 */ u8 threadCmdWritePos;
+ /* 0x5BD9 */ u8 threadCmdReadPos;
+ /* 0x5BDA */ u8 threadCmdQueueFinished;
+ /* 0x5BDC */ u16 threadCmdChannelMask[4]; // bitfield for 16 channels. When processing an audio thread channel command on all channels, only process channels with their bit set.
/* 0x5BE4 */ OSMesgQueue* audioResetQueueP;
/* 0x5BE8 */ OSMesgQueue* taskStartQueueP;
- /* 0x5BEC */ OSMesgQueue* cmdProcQueueP;
+ /* 0x5BEC */ OSMesgQueue* threadCmdProcQueueP;
/* 0x5BF0 */ OSMesgQueue taskStartQueue;
- /* 0x5C08 */ OSMesgQueue cmdProcQueue;
+ /* 0x5C08 */ OSMesgQueue threadCmdProcQueue;
/* 0x5C20 */ OSMesgQueue audioResetQueue;
/* 0x5C38 */ OSMesg taskStartMsgBuf[1];
/* 0x5C3C */ OSMesg audioResetMsgBuf[1];
- /* 0x5C40 */ OSMesg cmdProcMsgBuf[4];
- /* 0x5C50 */ AudioCmd cmdBuf[0x100]; // Audio commands used to transfer audio requests from the graph thread to the audio thread
+ /* 0x5C40 */ OSMesg threadCmdProcMsgBuf[4];
+ /* 0x5C50 */ AudioCmd threadCmdBuf[0x100]; // Audio thread commands used to transfer audio requests from the graph thread to the audio thread
} AudioContext; // size = 0x6450
typedef struct {
@@ -966,11 +977,16 @@ typedef struct {
/* 0x08 */ f32 velocity;
/* 0x0C */ char unk_0C[0x4];
/* 0x10 */ s16* filter;
- /* 0x14 */ u8 unk_14;
- /* 0x16 */ u16 unk_16;
+ /* 0x14 */ u8 combFilterSize;
+ /* 0x16 */ u16 combFilterGain;
} NoteSubAttributes; // size = 0x18
typedef struct {
+ /* 0x0 */ s16 unk_00; // set to 0x1C00, unused
+ /* 0x2 */ s16 seqTicksPerBeat;
+} TempoData; // size = 0x4
+
+typedef struct {
/* 0x00 */ u32 heapSize; // total number of bytes allocated to the audio heap. Must be <= the size of `gAudioHeap` (ideally about the same size)
/* 0x04 */ u32 initPoolSize; // The entire audio heap is split into two pools.
/* 0x08 */ u32 permanentPoolSize;