1
0
Fork 0
mirror of https://github.com/zeldaret/oot.git synced 2025-10-20 13:40:02 +00:00

Document Audio Thread Commands (#1399)

* begin docs

* cleanup

* copy over progress

* cleanup

* small cleanup

* more docs, fill out cmds

* small touchup

* pan weight ganon comment

* fix specId

* seqcmd cleanup

* format

* small cleanup

* one more thing

* small feedback from MM

* partial PR

* some PR Suggestions

* small adjustments

* ticks, seqticks, frames, updates: term cleanup

* small fix

* PR Review

* PR Review

* PR Review

* rm param

* adjust comment

* update renamed functions

* format

---------

Co-authored-by: Dragorn421 <Dragorn421@users.noreply.github.com>
This commit is contained in:
engineer124 2024-02-01 10:25:23 +11:00 committed by GitHub
commit a0d31dba68
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
25 changed files with 1393 additions and 842 deletions

537
include/audiothread_cmd.h Normal file
View file

@ -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

View file

@ -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);

View file

@ -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))

View file

@ -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
/*

View file

@ -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;

View file

@ -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"

View file

@ -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,10 +977,15 @@ 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.