diff options
Diffstat (limited to 'include')
| -rw-r--r-- | include/audiothread_cmd.h | 537 | ||||
| -rw-r--r-- | include/functions.h | 32 | ||||
| -rw-r--r-- | include/seqcmd.h | 66 | ||||
| -rw-r--r-- | include/sfx.h | 36 | ||||
| -rw-r--r-- | include/variables.h | 5 | ||||
| -rw-r--r-- | include/z64.h | 1 | ||||
| -rw-r--r-- | include/z64audio.h | 118 |
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; |
