From b88bd4366ef4e964c7a1e1e0efadfd48901bd76e Mon Sep 17 00:00:00 2001 From: Unnunu Date: Mon, 5 May 2025 15:47:26 +0300 Subject: [PATCH] match and document audiosfx.c (#550) * match func_80004668 and adjust types * match _handleEvent * documentation WIP * wip * document audiosfx.c * fix build * a few type renames * update score * remove comment * fix type * fix typo --- README.md | 22 +- include/PR/libaudio.h | 23 - include/macros.h | 3 + include/structs.h | 31 +- libultra/src/audio/mips1/auxbus.c | 2 +- libultra/src/audio/mips1/csplayer.c | 2 +- src/audio.c | 127 ++-- src/audio.h | 14 +- src/audio_spatial.c | 11 +- src/audio_spatial.h | 18 +- src/audio_vehicle.c | 55 +- src/audio_vehicle.h | 8 +- src/audiomgr.c | 1 - src/audiomgr.h | 1 - src/audiosfx.c | 861 ++++++++++++++++++++------- src/audiosfx.h | 212 +++---- src/game.c | 8 +- src/game_ui.c | 28 +- src/game_ui.h | 2 +- src/menu.c | 54 +- src/object_functions.c | 10 +- src/objects.c | 8 +- src/racer.c | 40 +- src/thread3_main.c | 6 +- src/vehicle_bubbler.c | 2 +- src/vehicle_smokey.c | 2 +- ver/symbols/symbol_addrs.jpn.v79.txt | 60 +- ver/symbols/symbol_addrs.pal.v77.txt | 60 +- ver/symbols/symbol_addrs.pal.v80.txt | 60 +- ver/symbols/symbol_addrs.us.v77.txt | 60 +- ver/symbols/symbol_addrs.us.v80.txt | 60 +- 31 files changed, 1109 insertions(+), 742 deletions(-) diff --git a/README.md b/README.md index 9781c356..8296b846 100644 --- a/README.md +++ b/README.md @@ -7,9 +7,9 @@ All versions are supported, and the US 1.0 version (SHA1 = 0cb115d8716dbbc2922fd As of May 5, 2025, this is our current score: -    Decomp progress: 84.46% +    Decomp progress: 84.89% -    Documentation progress: 53.79% +    Documentation progress: 54.49% --- @@ -121,26 +121,26 @@ As of May 5, 2025, this is our current score: ``` ======================================================== ADVENTURE ONE (ASM -> C Decompilation) - -------- 84.46% Complete (86.01% NON_MATCHING) --------- - # Decompiled functions: 1878 - # GLOBAL_ASM remaining: 73 + -------- 84.89% Complete (86.44% NON_MATCHING) --------- + # Decompiled functions: 1880 + # GLOBAL_ASM remaining: 71 # NON_MATCHING functions: 8 - # NON_EQUIVALENT WIP functions: 26 + # NON_EQUIVALENT WIP functions: 25 --------------------- Game Status ---------------------- Balloons: 39/47, Keys: 4/4, Trophies: 4/5 T.T. Amulets: 4/4, Wizpig Amulets: 4/4 -------------------------------------------------------- - We are racing the wizard pig boss Wizpig. (Lap 3/3) + We are racing in Spacedust Alley. (Lap 1/3) ======================================================== ADVENTURE TWO (Cleanup & Documentation) - ------------------- 53.79% Complete -------------------- - # Documented functions: 1138 - # Undocumented remaining: 516 + ------------------- 54.49% Complete -------------------- + # Documented functions: 1154 + # Undocumented remaining: 500 --------------------- Game Status ---------------------- Balloons: 26/47, Keys: 3/4, Trophies: 2/5 T.T. Amulets: 2/4, Wizpig Amulets: 2/4 -------------------------------------------------------- - We are battling in Darkwater Beach. (2 opponents remain) + We are battling in Darkwater Beach. (1 opponent remains) ======================================================== ``` diff --git a/include/PR/libaudio.h b/include/PR/libaudio.h index 737c35e3..ecd975e4 100644 --- a/include/PR/libaudio.h +++ b/include/PR/libaudio.h @@ -592,28 +592,6 @@ typedef struct { u8 chan; } ALOscEvent; -typedef struct ALSoundState { - /* 0x00 */ struct ALSoundState *next; - /* 0x04 */ struct ALSoundState *prev; - /* 0x08 */ struct ALSoundState *unk8; - /* 0x0C */ ALVoice voice; - /* 0x28 */ ALSound *sound; /* sound referenced here */ - /* 0x2C */ s16 priority; - /* 0x30 */ struct ALSoundState *unk30; - /* 0x34 */ u8 pad34[0x2]; - /* 0x34 */ u8 soundPriority; - /* 0x38 */ s16 vol; /* volume - combined with volume from bank */ - /* 0x3A */ ALPan pan; /* pan - 0 = left, 127 = right */ - /* 0x3C */ u8 fxMix; /* wet/dry mix - 0 = dry, 127 = wet */ - /* 0x3C */ u8 pad3C[2]; - /* 0x3E */ u8 flags; - /* 0x3F */ u8 soundState; - } ALSoundState; - -typedef struct { - ALSoundState *soundState; -} ALSoundEvent; - typedef struct { s16 type; union { @@ -628,7 +606,6 @@ typedef struct { ALSeqpSeqEvent spseq; ALSeqpBankEvent spbank; ALOscEvent osc; - ALSoundEvent sndpevent; } msg; } ALEvent; diff --git a/include/macros.h b/include/macros.h index d4ca4ab4..30e374e5 100644 --- a/include/macros.h +++ b/include/macros.h @@ -81,4 +81,7 @@ // A few systems in the game use an array as a cache table. This gives you the pointer to the asset #define ASSETCACHE_PTR(x) ((x << 1) + 1) +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#define MAX(a, b) ((a) > (b) ? (a) : (b)) + #endif diff --git a/include/structs.h b/include/structs.h index 4fa7ee67..3589b523 100644 --- a/include/structs.h +++ b/include/structs.h @@ -9,6 +9,7 @@ #include "object_properties.h" #include "gbi.h" #include "PR/libaudio.h" +#include "audio.h" typedef struct Vec4f { union { @@ -109,7 +110,7 @@ typedef struct SoundMask { /* 0x11 */ u8 unk11; /* 0x12 */ u8 unk12; /* 0x14 */ s32 distance; - /* 0x18 */ ALSoundState *soundPtr; + /* 0x18 */ SoundHandle soundPtr; /* 0x1C */ struct SoundMask **soundMask; /* 0x20 */ u8 unk20; /* 0x21 */ u8 unk21; @@ -964,7 +965,7 @@ typedef struct Object_Animation { /* 0x0C */ f32 x; /* 0x10 */ f32 y; /* 0x14 */ f32 z; - /* 0x18 */ u8 *unk18; + /* 0x18 */ SoundHandle unk18; /* 0x1C */ struct Object *unk1C; /* 0x20 */ s32 unk20; /* 0x24 */ s16 unk24; @@ -1031,7 +1032,7 @@ typedef struct Object_Weapon { /* 0x18 */ u8 weaponID; /* 0x19 */ s8 checkpoint; /* 0x19 */ s16 unk1A; - /* 0x19 */ SoundMask *soundMask; + /* 0x19 */ SoundHandle soundMask; } Object_Weapon; typedef struct Object_Butterfly { @@ -1225,11 +1226,11 @@ typedef struct Object_Racer { /* 0x004 */ s32 unk4; /* 0x008 */ f32 forwardVel; /* 0x00C */ f32 animationSpeed; - /* 0x010 */ s32 unk10; - /* 0x014 */ s32 unk14; - /* 0x018 */ s32 unk18; - /* 0x01C */ s32 unk1C; - /* 0x020 */ s32 unk20; + /* 0x010 */ SoundHandle unk10; + /* 0x014 */ SoundHandle unk14; + /* 0x018 */ SoundHandle unk18; + /* 0x01C */ SoundHandle unk1C; + /* 0x020 */ SoundHandle unk20; /* 0x024 */ SoundMask *soundMask; /* 0x028 */ u16 lastSoundID; /* 0x02A */ u16 unk2A; @@ -1312,7 +1313,7 @@ typedef struct Object_Racer { /* 0x174 */ s8 balloon_level; /* 0x175 */ s8 magnetTimer; /* 0x176 */ s16 unk176; - /* 0x178 */ void *magnetSoundMask; + /* 0x178 */ SoundHandle magnetSoundMask; /* 0x17C */ SoundMask *shieldSoundMask; /* 0x180 */ SoundMask *bananaSoundMask; /* 0x184 */ s8 magnetModelID; @@ -1427,14 +1428,14 @@ typedef struct Object_Racer { /* 0x215 */ s8 unk215; /* 0x216 */ u8 unk216; /* 0x217 */ u8 unk217; - /* 0x218 */ s32 weaponSoundMask; - /* 0x21C */ SoundMask *unk21C; - /* 0x220 */ s32 unk220; + /* 0x218 */ SoundHandle weaponSoundMask; + /* 0x21C */ SoundHandle unk21C; + /* 0x220 */ SoundHandle unk220; } Object_Racer; typedef struct Object_Door { /* 0x00 */ f32 homeY; - /* 0x04 */ SoundMask *soundMask; + /* 0x04 */ SoundHandle soundMask; /* 0x08 */ s32 jingleTimer; /* 0x0A */ s16 jingleCooldown; /* 0x0E */ s8 doorID; @@ -1551,7 +1552,7 @@ typedef struct Object_TT { typedef struct Object_Bridge_WhaleRamp { /* 0x0 */ f32 homeY; - /* 0x4 */ SoundMask *soundMask; + /* 0x4 */ SoundHandle soundMask; } Object_Bridge_WhaleRamp; typedef struct Object_64_80021400 { @@ -1578,7 +1579,7 @@ typedef struct Object_Log { typedef struct Object_Fireball_Octoweapon { u8 pad0[0x1C]; - s32 soundMask; + SoundHandle soundMask; } Object_Fireball_Octoweapon; typedef struct Object_AnimatedObject { diff --git a/libultra/src/audio/mips1/auxbus.c b/libultra/src/audio/mips1/auxbus.c index 2871d553..5519ba1c 100644 --- a/libultra/src/audio/mips1/auxbus.c +++ b/libultra/src/audio/mips1/auxbus.c @@ -69,7 +69,7 @@ s32 alAuxBusParam(void *filter, s32 paramID, void *param) { } -void func_80065A80(ALSynth *arg0, PVoice *arg1, s16 arg2) { +void func_80065A80(ALSynth *arg0, struct PVoice_s *arg1, s16 arg2) { if (arg2 != arg1->unkDC) { alAuxBusParam(&arg0->auxBus[arg1->unkDC], AL_FILTER_UNK11, &arg1->envmixer); alAuxBusParam(&arg0->auxBus[arg2], AL_FILTER_ADD_SOURCE, &arg1->envmixer); diff --git a/libultra/src/audio/mips1/csplayer.c b/libultra/src/audio/mips1/csplayer.c index e0229a3b..a008008e 100644 --- a/libultra/src/audio/mips1/csplayer.c +++ b/libultra/src/audio/mips1/csplayer.c @@ -56,7 +56,7 @@ static void __CSPHandleMIDIMsg(ALCSPlayer_Custom *seqp, ALEvent *eve static void __CSPHandleMetaMsg(ALCSPlayer *seqp, ALEvent *event); static void __CSPRepostEvent(ALEventQueue *evtq, ALEventListItem *item); static void __setUsptFromTempo(ALCSPlayer *seqp, f32 tempo); /* sct 1/8/96 */ - void func_80065A80(ALSynth *arg0, PVoice *arg1, s16 arg2); + void func_80065A80(ALSynth *arg0, struct PVoice_s *arg1, s16 arg2); /* diff --git a/src/audio.c b/src/audio.c index d3bfafa4..6a9eaa0c 100644 --- a/src/audio.c +++ b/src/audio.c @@ -5,7 +5,6 @@ #include "macros.h" #include "asset_enums.h" #include "asset_loading.h" -#include "audio_internal.h" #include "audiomgr.h" #include "audiosfx.h" #include "audio_spatial.h" @@ -67,9 +66,9 @@ ALCSeq gJingleSequence; u8 gSkipResetChannels; // Stored and used by a single function, but redundant. u8 gAudioVolumeSetting; u32 gDynamicMusicChannelMask; -SoundMask *gGlobalSoundMask; -SoundMask *gSpatialSoundMask; -SoundMask *gRacerSoundMask; +SoundHandle gGlobalSoundMask; +SoundHandle gSpatialSoundMask; +SoundHandle gRacerSoundMask; /******************************/ @@ -142,16 +141,16 @@ void audio_init(OSSched *sc) { gJinglePlayer = sound_seqplayer_init(16, 50); gMusicSequenceData = mempool_alloc_safe(seqLength, COLOUR_TAG_CYAN); gJingleSequenceData = mempool_alloc_safe(seqLength, COLOUR_TAG_CYAN); - audConfig.unk04 = 150; - audConfig.unk00 = 32; + audConfig.maxEvents = 150; + audConfig.maxSounds = 32; audConfig.maxChannels = AUDIO_CHANNELS; - audConfig.unk10 = 1; - audConfig.hp = &gALHeap; - alSndPNew(&audConfig); + audConfig.numGroups = 1; + audConfig.heap = &gALHeap; + sndp_init_player(&audConfig); audioStartThread(); sound_volume_change(VOLUME_NORMAL); mempool_free(addrPtr); - set_sound_channel_count(10); + sndp_set_active_sound_limit(10); gBlockMusicChange = FALSE; gMusicPlaying = FALSE; gJinglePlaying = FALSE; @@ -173,10 +172,10 @@ void sound_volume_reset(u8 skipReset) { if (gSkipResetChannels == FALSE) { gGlobalMusicVolume = 256; music_volume_set(gMusicBaseVolume); - set_sound_channel_volume(0, gGlobalMusicVolume * 128 - 1); - set_sound_channel_volume(1, gGlobalMusicVolume * 128 - 1); - set_sound_channel_volume(2, gGlobalMusicVolume * 128 - 1); - set_sound_channel_volume(4, gGlobalMusicVolume * 128 - 1); + sndp_set_group_volume(0, gGlobalMusicVolume * 128 - 1); + sndp_set_group_volume(1, gGlobalMusicVolume * 128 - 1); + sndp_set_group_volume(2, gGlobalMusicVolume * 128 - 1); + sndp_set_group_volume(4, gGlobalMusicVolume * 128 - 1); } } } @@ -187,32 +186,32 @@ void sound_volume_reset(u8 skipReset) { void sound_volume_change(s32 behaviour) { switch (behaviour) { case VOLUME_LOWER: // Mute most sound effects and half the volume of music. - set_sound_channel_volume(0, 0); - set_sound_channel_volume(1, 32767); - set_sound_channel_volume(2, 0); - set_sound_channel_volume(4, 0); + sndp_set_group_volume(0, 0); + sndp_set_group_volume(1, 32767); + sndp_set_group_volume(2, 0); + sndp_set_group_volume(4, 0); alCSPSetVol(gMusicPlayer, (s16) (gMusicBaseVolume * gMusicSliderVolume >> 2)); alCSPSetVol(gJinglePlayer, 0); break; case VOLUME_LOWER_AMBIENT: // Mute the ambient channel, making course elements stop making noise. - set_sound_channel_volume(0, 0); - set_sound_channel_volume(1, 32767); - set_sound_channel_volume(2, 32767); - set_sound_channel_volume(4, 32767); + sndp_set_group_volume(0, 0); + sndp_set_group_volume(1, 32767); + sndp_set_group_volume(2, 32767); + sndp_set_group_volume(4, 32767); break; case VOLUME_UNK03: - set_sound_channel_volume(0, 0); - set_sound_channel_volume(1, 32767); - set_sound_channel_volume(2, 0); - set_sound_channel_volume(4, 0); + sndp_set_group_volume(0, 0); + sndp_set_group_volume(1, 32767); + sndp_set_group_volume(2, 0); + sndp_set_group_volume(4, 0); break; default: // Restore sound back to normal. - set_sound_channel_volume(0, 32767); - set_sound_channel_volume(1, 32767); - set_sound_channel_volume(2, 32767); - set_sound_channel_volume(4, 32767); + sndp_set_group_volume(0, 32767); + sndp_set_group_volume(1, 32767); + sndp_set_group_volume(2, 32767); + sndp_set_group_volume(4, 32767); alCSPSetVol(gMusicPlayer, (s16) (gMusicBaseVolume * gMusicSliderVolume)); - alCSPSetVol(gJinglePlayer, (s16) (get_sfx_volume_slider() * sfxRelativeVolume)); + alCSPSetVol(gJinglePlayer, (s16) (sndp_get_global_volume() * sfxRelativeVolume)); break; } gAudioVolumeSetting = behaviour; @@ -337,13 +336,13 @@ void sound_update_queue(u8 updateRate) { gDelayedSounds[i].timer -= updateRate; if (gDelayedSounds[i].timer <= 0) { j = i; - sound_play(gDelayedSounds[i].soundId, (s32 *) gDelayedSounds[i].soundMask); + sound_play(gDelayedSounds[i].soundId, gDelayedSounds[i].handlePtr); gDelayedSoundsCount -= 1; while (j < gDelayedSoundsCount) { gDelayedSounds[i].soundId = gDelayedSounds[i + 1].soundId; gDelayedSounds[i].timer = gDelayedSounds[i + 1].timer; - gDelayedSounds[i].soundMask = gDelayedSounds[i + 1].soundMask; + gDelayedSounds[i].handlePtr = gDelayedSounds[i + 1].handlePtr; j++; } j++; @@ -364,10 +363,10 @@ void sound_update_queue(u8 updateRate) { * Add a sound to a queue to play after a set time has passed. * Delay time is in seconds. (1.0f = 1 second) */ -void sound_play_delayed(u16 soundId, SoundMask *soundMask, f32 delayTime) { +void sound_play_delayed(u16 soundId, SoundHandle *handlePtr, f32 delayTime) { if (gDelayedSoundsCount < 8) { gDelayedSounds[gDelayedSoundsCount].soundId = soundId; - gDelayedSounds[gDelayedSoundsCount].soundMask = soundMask; + gDelayedSounds[gDelayedSoundsCount].handlePtr = handlePtr; gDelayedSounds[gDelayedSoundsCount].timer = delayTime * 60.0f; gDelayedSoundsCount++; } @@ -735,7 +734,7 @@ s32 music_volume_config(void) { */ void music_jingle_volume_set(u8 arg0) { sfxRelativeVolume = arg0; - alCSPSetVol(gJinglePlayer, (s16) (get_sfx_volume_slider() * sfxRelativeVolume)); + alCSPSetVol(gJinglePlayer, (s16) (sndp_get_global_volume() * sfxRelativeVolume)); } /** @@ -777,7 +776,7 @@ u32 music_jingle_playing(void) { UNUSED void sound_channel_volume_all(u16 volume) { u32 i; for (i = 0; i < 64; i++) { - set_sound_channel_volume(i, volume << 8); + sndp_set_group_volume(i, volume << 8); } } @@ -795,37 +794,37 @@ u16 sound_distance(u16 soundId) { * Add the requested sound to the queue and update the mask to show that this sound is playing at that source. * If no soundmask is provided, then instead use the global mask. */ -void sound_play(u16 soundID, s32 *soundMask) { +void sound_play(u16 soundID, SoundHandle *handlePtr) { f32 pitch; s32 soundBite; if (soundID > gSoundCount) { - if (soundMask != NULL) { - *soundMask = NULL; + if (handlePtr != NULL) { + *handlePtr = NULL; } stubbed_printf("amSndPlay: Illegal sound effects table index\n"); return; } soundBite = gSoundTable[soundID].soundBite; if (soundBite == NULL) { - if (soundMask != NULL) { - *soundMask = NULL; + if (handlePtr != NULL) { + *handlePtr = NULL; } return; } pitch = gSoundTable[soundID].pitch / 100.0f; - if (soundMask != NULL) { - func_80004668(gSoundBank->bankArray[0], soundBite, gSoundTable[soundID].unk8, (SoundMask *) soundMask); - if (*soundMask != NULL) { - sound_event_update(*soundMask, AL_SNDP_VOL_EVT, gSoundTable[soundID].volume * 256); - sound_event_update(*soundMask, AL_SNDP_PITCH_EVT, *((u32 *) &pitch)); + if (handlePtr != NULL) { + sndp_play_with_priority(gSoundBank->bankArray[0], soundBite, gSoundTable[soundID].unk8, handlePtr); + if (*handlePtr != NULL) { + sndp_set_param(*handlePtr, AL_SNDP_VOL_EVT, gSoundTable[soundID].volume * 256); + sndp_set_param(*handlePtr, AL_SNDP_PITCH_EVT, *((u32 *) &pitch)); } } else { - soundMask = (s32 *) &gGlobalSoundMask; - func_80004668(gSoundBank->bankArray[0], soundBite, gSoundTable[soundID].unk8, (SoundMask *) &gGlobalSoundMask); - if (*soundMask != NULL) { - sound_event_update(*soundMask, AL_SNDP_VOL_EVT, gSoundTable[soundID].volume * 256); - sound_event_update(*soundMask, AL_SNDP_PITCH_EVT, *((u32 *) &pitch)); + handlePtr = &gGlobalSoundMask; + sndp_play_with_priority(gSoundBank->bankArray[0], soundBite, gSoundTable[soundID].unk8, &gGlobalSoundMask); + if (*handlePtr != NULL) { + sndp_set_param(*handlePtr, AL_SNDP_VOL_EVT, gSoundTable[soundID].volume * 256); + sndp_set_param(*handlePtr, AL_SNDP_PITCH_EVT, *((u32 *) &pitch)); } } } @@ -835,7 +834,7 @@ void sound_play(u16 soundID, s32 *soundMask) { * This then makes the audio pan around in 3D space. * If it is not given a mask, then it will use the global mask. */ -void sound_play_spatial(u16 soundID, f32 x, f32 y, f32 z, s32 **soundMask) { +void sound_play_spatial(u16 soundID, f32 x, f32 y, f32 z, SoundHandle *soundMask) { if (soundMask == NULL) { soundMask = (s32 **) &gSpatialSoundMask; } @@ -856,28 +855,28 @@ void func_80001F14(u16 soundID, s32 *soundMask) { return; } if (soundMask) { - func_80004638(gSoundBank->bankArray[0], (s16) soundID, (SoundMask *) soundMask); + sndp_play(gSoundBank->bankArray[0], (s16) soundID, soundMask); } else { - func_80004638(gSoundBank->bankArray[0], (s16) soundID, (SoundMask *) &gRacerSoundMask); + sndp_play(gSoundBank->bankArray[0], (s16) soundID, &gRacerSoundMask); } } /** * Set the volume of the sound relative to the baseline volume of the sound ID. */ -void sound_volume_set_relative(u16 soundID, void *soundState, u8 volume) { +void sound_volume_set_relative(u16 soundID, SoundHandle soundHandle, u8 volume) { s32 newVolume = ((s32) (gSoundTable[soundID].volume * (volume / 127.0f))) * 256; - if (soundState) { - sound_event_update((s32) soundState, AL_SNDP_VOL_EVT, newVolume); + if (soundHandle) { + sndp_set_param(soundHandle, AL_SNDP_VOL_EVT, newVolume); } } /** * Updates the volume of the given sound mask. */ -UNUSED void sound_volume_set(SoundMask *soundMask, u8 arg1) { - if (soundMask != NULL) { - sound_event_update((s32) soundMask, AL_SNDP_VOL_EVT, arg1 * 256); +UNUSED void sound_volume_set(SoundHandle soundHandle, u8 arg1) { + if (soundHandle != NULL) { + sndp_set_param(soundHandle, AL_SNDP_VOL_EVT, arg1 * 256); } } @@ -885,10 +884,10 @@ UNUSED void sound_volume_set(SoundMask *soundMask, u8 arg1) { * Updates the pitch of the given sound mask. * Official name: amSndSetPitchDirect */ -UNUSED void sound_pitch_set(SoundMask *soundMask, u32 pitch) { +UNUSED void sound_pitch_set(SoundHandle soundHandle, u32 pitch) { u32 *pitchAddr = &pitch; - if (soundMask != NULL) { - sound_event_update((s32) soundMask, AL_SNDP_PITCH_EVT, *pitchAddr); + if (soundHandle != NULL) { + sndp_set_param(soundHandle, AL_SNDP_PITCH_EVT, *pitchAddr); } } diff --git a/src/audio.h b/src/audio.h index 752c5e37..f81fbfc2 100644 --- a/src/audio.h +++ b/src/audio.h @@ -2,9 +2,7 @@ #define _AUDIO_H_ #include "types.h" -#include "audio_internal.h" #include "sched.h" -#include "structs.h" #define AUDIO_CHANNELS 16 #define MUSIC_CHAN_MASK_NONE 0xFFFFFFFF @@ -16,6 +14,8 @@ enum AudioVolumeBehaviour { VOLUME_UNK03, }; +typedef struct ALSoundState* SoundHandle; + /* Size: 0x0A bytes */ typedef struct SoundData { u16 soundBite; // Audio file index. @@ -40,7 +40,7 @@ typedef struct MusicData { typedef struct DelayedSound { /* 0x00 */ u16 soundId; /* 0x02 */ s16 timer; - /* 0x04 */ SoundMask *soundMask; + /* 0x04 */ SoundHandle handlePtr; } DelayedSound; void alCSPNew(ALCSPlayer *seqp, ALSeqpConfig *config); //lib/src/al/csplayer.c @@ -74,7 +74,7 @@ void music_jingle_voicelimit_set(u8 voiceLimit); void music_fade(s32 time); void music_volume_reset(void); void sound_update_queue(u8 updateRate); -void sound_play_delayed(u16 soundId, SoundMask *soundMask, f32 delayTime); +void sound_play_delayed(u16 soundId, SoundHandle *soundMask, f32 delayTime); void sound_clear_delayed(void); u16 music_channel_get_mask(void); void music_dynamic_set(u16 channelMask); @@ -106,7 +106,7 @@ void music_jingle_pan_set(ALPan pan); void music_jingle_play(u8 seqID); u32 music_jingle_playing(void); u16 sound_distance(u16 soundId); -void sound_play_spatial(u16 soundID, f32 x, f32 y, f32 z, s32 **soundMask); +void sound_play_spatial(u16 soundID, f32 x, f32 y, f32 z, SoundHandle*soundMask); void func_80001F14(u16 soundID, s32 *soundMask); u16 sound_count(void); u8 music_sequence_count(void); @@ -118,9 +118,9 @@ void music_sequence_stop(ALCSPlayer *seqPlayer); void sound_reverb_set(u8 setting); void alSeqFileNew(ALSeqFile *file, u8 *base); void func_80063A90(ALCSPlayer *seqp, u8 channel); -void sound_volume_set_relative(u16 soundID, void *soundState, u8 volume); +void sound_volume_set_relative(u16 soundID, SoundHandle soundState, u8 volume); void music_sequence_init(ALCSPlayer *seqp, void *sequence, u8 *seqID, ALCSeq *seq); -void sound_play(u16 soundID, s32* soundMask); +void sound_play(u16 soundID, SoundHandle* handlePtr); f32 music_animation_fraction(void); #endif diff --git a/src/audio_spatial.c b/src/audio_spatial.c index 9f2350e6..d46ede65 100644 --- a/src/audio_spatial.c +++ b/src/audio_spatial.c @@ -1,7 +1,6 @@ #include "audio_spatial.h" #include "types.h" #include "macros.h" -#include "audio_internal.h" #include "audio_vehicle.h" #include "memory.h" #include "audio.h" @@ -85,7 +84,7 @@ void audioline_on(void) { void audioline_reset(void) { s32 i; s32 j; - ALSoundState *sound; + SoundHandle sound; SoundMask *heap; f32 *ptr; @@ -103,7 +102,7 @@ void audioline_reset(void) { sound = gSoundMaskHeapUsed[i]->soundPtr; gSoundMaskHeapUsed[i]->unk12 = 0; if (sound != NULL) { - sound_stop(sound); + sndp_stop(sound); } } gUsedMasks = 0; @@ -112,7 +111,7 @@ void audioline_reset(void) { D_80119C58[i].soundID = 0; if (D_80119C58[i].soundPtr != 0) { if (D_80119C58[i].unk0_02 == 0) { - sound_stop(D_80119C58[i].soundPtr); + sndp_stop(D_80119C58[i].soundPtr); } else if (D_80119C58[i].unk0_02 == 1) { music_jingle_stop(); } @@ -439,7 +438,7 @@ void audioline_reverb(s32 *soundState, f32 x, f32 y, f32 z) { } } if (soundState != NULL) { - sound_event_update((s32) soundState, AL_SNDP_FX_EVT, (u32) volume); + sndp_set_param((s32) soundState, AL_SNDP_FX_EVT, (u32) volume); } } @@ -549,7 +548,7 @@ void debug_render_audio_effects(Gfx **dList, Vertex **verts, Triangle **tris) { void func_8000A2E8(s32 arg0) { if (gUsedMasks != 0) { if (gSoundMaskHeapUsed[arg0]->soundPtr != 0) { - sound_stop(gSoundMaskHeapUsed[arg0]->soundPtr); + sndp_stop(gSoundMaskHeapUsed[arg0]->soundPtr); } if (gSoundMaskHeapUsed[arg0]->soundMask != NULL) { *gSoundMaskHeapUsed[arg0]->soundMask = NULL; diff --git a/src/audio_spatial.h b/src/audio_spatial.h index 5bf23780..09f6b1b7 100644 --- a/src/audio_spatial.h +++ b/src/audio_spatial.h @@ -16,13 +16,6 @@ typedef struct floatXYZVals { f32 z2; } floatXYZVals; -/* Size: 0x0C / 12 bytes - Possibly just a Vec3f? */ -typedef struct unk8011A6D8_04 { - /* 0x00 */ f32 unk0; - /* 0x04 */ f32 unk4; - /* 0x08 */ f32 unk8; -} unk8011A6D8_04; - /* Size: 0x180 / 384 bytes */ typedef struct unk80119C58 { /* 0x000 */ u8 unk0_02; @@ -33,7 +26,7 @@ typedef struct unk80119C58 { /* 0x175 */ u8 unk175; /* 0x176 */ u8 unk176; /* 0x177 */ u8 unk177; - /* 0x178 */ ALSoundState *soundPtr; + /* 0x178 */ SoundHandle soundPtr; /* 0x17C */ s8 unk17C; /* 0x17D */ u8 unk17D; /* 0x17E */ u8 unk17E; @@ -48,15 +41,6 @@ typedef struct unk8011A6D8 { /* 0xBC */ f32 unkBC; } unk8011A6D8; -typedef struct unk800A414_arg3 { - f32 unk0; - f32 unk4; - f32 unk8; - f32 unkC; - f32 unk10; - f32 unk14; -} unk800A414_arg3; - void audioline_on(void); void func_800096F8(SoundMask *); void audioline_off(void); diff --git a/src/audio_vehicle.c b/src/audio_vehicle.c index 147b5704..8c37ab7e 100644 --- a/src/audio_vehicle.c +++ b/src/audio_vehicle.c @@ -310,7 +310,7 @@ void func_80005254(Object *obj, u32 buttonsPressed, u32 buttonsHeld, s32 updateR if (((gSoundRacerObj->unk10 != 0) || (gSoundRacerObj->unk14 != 0) || !(buttonsHeld & B_BUTTON) || (gSoundRacerObj->velocity > -0.1) || (gSoundRacerObj->vehicleID == 4)) && (gRacerSound->unkA8 != 0)) { - sound_stop(gRacerSound->unkA8); + sndp_stop(gRacerSound->unkA8); gRacerSound->unkA8 = 0; } else if ((buttonsPressed & B_BUTTON) && (gRacerSound->unkA8 == 0) && (gSoundRacerObj->playerIndex >= 0)) { if (gSoundRacerObj->velocity < 0.0f) { @@ -325,7 +325,7 @@ void func_80005254(Object *obj, u32 buttonsPressed, u32 buttonsHeld, s32 updateR sp6C = (((var_f20 * 0.5) / 12.0) + 0.5); temp_a0_4 = (s32) gRacerSound->unkA8; if (temp_a0_4 != 0) { - sound_event_update(temp_a0_4, AL_SNDP_PITCH_EVT, *((u32 *) &sp6C)); + sndp_set_param(temp_a0_4, AL_SNDP_PITCH_EVT, *((u32 *) &sp6C)); } gRacerSound->unkAC = 110; gRacerSound->unkD0 = 0; @@ -337,9 +337,9 @@ void func_80005254(Object *obj, u32 buttonsPressed, u32 buttonsHeld, s32 updateR gRacerSound->unkD0 = 0; } if (gRacerSound->unkD0 >= 10) { - sound_event_update((s32) gRacerSound->unkA8, AL_SNDP_VOL_EVT, 0); + sndp_set_param((s32) gRacerSound->unkA8, AL_SNDP_VOL_EVT, 0); } else { - sound_event_update((s32) gRacerSound->unkA8, AL_SNDP_VOL_EVT, gRacerSound->unkAC << 8); + sndp_set_param((s32) gRacerSound->unkA8, AL_SNDP_VOL_EVT, gRacerSound->unkAC << 8); audioline_reverb((s32 *) gRacerSound->unkA8, obj->segment.trans.x_position, obj->segment.trans.y_position, obj->segment.trans.z_position); } @@ -549,7 +549,7 @@ void func_800063EC(Object *obj, UNUSED u32 buttonsPressed, u32 buttonsHeld, s32 } else if (gSoundRacerObj->spinout_timer == 0) { gRacerSound->brakeSound = FALSE; if (gRacerSound->brakeSoundMask != NULL) { - sound_stop(gRacerSound->brakeSoundMask); + sndp_stop(gRacerSound->brakeSoundMask); } } } @@ -567,16 +567,16 @@ void racer_sound_free(Object *obj) { if (gRacerSound != NULL) { for (i = 0; i != 2; i++) { if (gRacerSound->unk48[i] != NULL) { - sound_stop(gRacerSound->unk48[i]); + sndp_stop(gRacerSound->unk48[i]); gRacerSound->unk48[i] = 0; } } if (gRacerSound->unk50 != NULL) { - sound_stop(gRacerSound->unk50); + sndp_stop(gRacerSound->unk50); gRacerSound->unk50 = NULL; } if (gRacerSound->unkA8 != NULL) { - sound_stop(gRacerSound->unkA8); + sndp_stop(gRacerSound->unkA8); gRacerSound->unkA8 = 0; } for (i = 0; i < ARRAY_COUNT(D_80119C30); i++) { @@ -732,17 +732,17 @@ void func_80006FC8(Object **objs, s32 numRacers, ObjectSegment *segment, u8 arg3 audioline_reverb((s32 *) gRacerSound->unk50, objs[loopCount1]->segment.trans.x_position, objs[loopCount1]->segment.trans.y_position, objs[loopCount1]->segment.trans.z_position); - sound_event_update((s32) gRacerSound->unk50, AL_SNDP_VOL_EVT, temp_s3 << 8); - sound_event_update((s32) gRacerSound->unk50, AL_SNDP_PITCH_EVT, *((u32 *) &sp8C)); - func_80004604((ALSoundState *) gRacerSound->unk50, 80); - sound_event_update((s32) gRacerSound->unk50, AL_SNDP_PAN_EVT, gRacerSound->unk91[0]); + sndp_set_param(gRacerSound->unk50, AL_SNDP_VOL_EVT, temp_s3 << 8); + sndp_set_param(gRacerSound->unk50, AL_SNDP_PITCH_EVT, *((u32 *) &sp8C)); + sndp_set_priority(gRacerSound->unk50, 80); + sndp_set_param(gRacerSound->unk50, AL_SNDP_PAN_EVT, gRacerSound->unk91[0]); } } else if (gRacerSound->unk50 != NULL) { - sound_stop(gRacerSound->unk50); + sndp_stop(gRacerSound->unk50); gRacerSound->unk50 = 0; } } else if (gRacerSound->unk50 != NULL) { - sound_stop(gRacerSound->unk50); + sndp_stop(gRacerSound->unk50); gRacerSound->unk50 = 0; } for (loopCount2 = 0; loopCount2 < 2 && gRacerSound->unk0[loopCount2] != 0 && var_f26 != 0.0; loopCount2++) { @@ -754,12 +754,12 @@ void func_80006FC8(Object **objs, s32 numRacers, ObjectSegment *segment, u8 arg3 } if ((loopCount2 == 0) && (gRacerSound->unk44[0] & 1)) { if (gRacerSound->unk48[0] != NULL) { - sound_stop(gRacerSound->unk48[0]); + sndp_stop(gRacerSound->unk48[0]); gRacerSound->unk48[0] = NULL; } } else { if ((gRacerSound->unk48[loopCount2] != NULL) && (temp_s3 == 0)) { - sound_stop(gRacerSound->unk48[loopCount2]); + sndp_stop(gRacerSound->unk48[loopCount2]); gRacerSound->unk48[loopCount2] = NULL; } else { if (gRacerSound->unk48[loopCount2] == NULL) { @@ -769,15 +769,14 @@ void func_80006FC8(Object **objs, s32 numRacers, ObjectSegment *segment, u8 arg3 audioline_reverb( (s32 *) gRacerSound->unk48[loopCount2], objs[loopCount1]->segment.trans.x_position, objs[loopCount1]->segment.trans.y_position, objs[loopCount1]->segment.trans.z_position); - sound_event_update((s32) gRacerSound->unk48[loopCount2], AL_SNDP_VOL_EVT, temp_s3 << 8); - sound_event_update((s32) gRacerSound->unk48[loopCount2], AL_SNDP_PITCH_EVT, - *((u32 *) &sp8C)); - func_80004604((ALSoundState *) gRacerSound->unk48[loopCount2], 80); + sndp_set_param(gRacerSound->unk48[loopCount2], AL_SNDP_VOL_EVT, temp_s3 << 8); + sndp_set_param(gRacerSound->unk48[loopCount2], AL_SNDP_PITCH_EVT, *((u32 *) &sp8C)); + sndp_set_priority(gRacerSound->unk48[loopCount2], 80); if (arg3 != 1) { gRacerSound->unk91[0] = 64; } - sound_event_update((s32) gRacerSound->unk48[loopCount2], AL_SNDP_PAN_EVT, - gRacerSound->unk91[0]); + sndp_set_param(gRacerSound->unk48[loopCount2], AL_SNDP_PAN_EVT, + gRacerSound->unk91[0]); } } } @@ -847,7 +846,7 @@ void func_80006FC8(Object **objs, s32 numRacers, ObjectSegment *segment, u8 arg3 for (loopCount3 = 0; loopCount3 < ARRAY_COUNT(D_80119C30); loopCount3++) { if (D_80119C30[loopCount3] != NULL) { if (D_80119C30[loopCount3]->unk48[0] != NULL && D_80119C30[loopCount3]->unk88 < 8) { - sound_stop(D_80119C30[loopCount3]->unk48[0]); + sndp_stop(D_80119C30[loopCount3]->unk48[0]); D_80119C30[loopCount3]->unk48[0] = NULL; D_80119C30[loopCount3]->unk74 = 0; D_80119C30[loopCount3] = NULL; @@ -884,7 +883,7 @@ void func_80006FC8(Object **objs, s32 numRacers, ObjectSegment *segment, u8 arg3 gRacerSound->unk74 = 2; if (D_80119C30[loopCount3] != NULL) { if (D_80119C30[loopCount3]->unk48[0] != NULL) { - sound_stop(D_80119C30[loopCount3]->unk48[0]); + sndp_stop(D_80119C30[loopCount3]->unk48[0]); D_80119C30[loopCount3]->unk48[0] = NULL; gRacerSound->unk74 = 1; } @@ -912,13 +911,13 @@ void func_80006FC8(Object **objs, s32 numRacers, ObjectSegment *segment, u8 arg3 if (temp->unk48[0] != NULL) { audioline_reverb((s32 *) temp->unk48[0], temp->racerPos.x, temp->racerPos.y, temp->racerPos.z); - sound_event_update((s32) temp->unk48[0], AL_SNDP_VOL_EVT, temp->unk88 << 8); - sound_event_update((s32) temp->unk48[0], AL_SNDP_PITCH_EVT, *((u32 *) &temp->unk8C)); + sndp_set_param(temp->unk48[0], AL_SNDP_VOL_EVT, temp->unk88 << 8); + sndp_set_param(temp->unk48[0], AL_SNDP_PITCH_EVT, *((u32 *) &temp->unk8C)); if (arg3 != 1) { temp->unk91[0] = 64; } - sound_event_update((s32) temp->unk48[0], AL_SNDP_PAN_EVT, temp->unk91[0]); - func_80004604((ALSoundState *) temp->unk48[0], 70); + sndp_set_param(temp->unk48[0], AL_SNDP_PAN_EVT, temp->unk91[0]); + sndp_set_priority(temp->unk48[0], 70); } } } diff --git a/src/audio_vehicle.h b/src/audio_vehicle.h index a76a819c..f9da5397 100644 --- a/src/audio_vehicle.h +++ b/src/audio_vehicle.h @@ -33,8 +33,8 @@ typedef struct VehicleSoundData { /* 0x3C */ f32 bananaPitch; /* 0x40 */ f32 unk40; /* 0x44 */ u8 unk44[4]; - /* 0x48 */ u8 *unk48[2]; //soundMask / soundState? - /* 0x50 */ u8 *unk50; + /* 0x48 */ SoundHandle unk48[2]; //soundMask / soundState? + /* 0x50 */ SoundHandle unk50; /* 0x54 */ f32 unk54[2]; /* 0x5C */ f32 unk5C[2]; /* 0x64 */ u8 unk64; @@ -52,7 +52,7 @@ typedef struct VehicleSoundData { /* 0x99 */ u8 pad99[0x7]; /* 0xA0 */ u8 unkA0; /* 0xA4 */ f32 throttlePitch; // Engine noise for the hovercraft and plane. - /* 0xA8 */ SoundMask *unkA8; + /* 0xA8 */ SoundHandle unkA8; /* 0xAC */ u16 unkAC; /* 0xB0 */ f32 throttlePitchVel; /* 0xB4 */ f32 throttlePitchDecay; @@ -65,7 +65,7 @@ typedef struct VehicleSoundData { /* 0xD0 */ u8 unkD0; /* 0xD4 */ f32 basePitch; /* 0xD8 */ u8 brakeSound; //Sound is playing bool? - /* 0xDC */ SoundMask *brakeSoundMask; //soundMask / soundState? + /* 0xDC */ SoundHandle brakeSoundMask; //soundMask / soundState? } VehicleSoundData; /* Size: 0x4C / 76 Bytes */ diff --git a/src/audiomgr.c b/src/audiomgr.c index ad5d4ab2..43897b66 100644 --- a/src/audiomgr.c +++ b/src/audiomgr.c @@ -1,6 +1,5 @@ #include "audiomgr.h" #include "memory.h" -#include "audio_internal.h" #include "video.h" #include "math_util.h" #include "asset_loading.h" diff --git a/src/audiomgr.h b/src/audiomgr.h index de17893d..70f052df 100644 --- a/src/audiomgr.h +++ b/src/audiomgr.h @@ -3,7 +3,6 @@ #include "types.h" #include "macros.h" -#include "audio_internal.h" #include "asset_enums.h" #include #include "sched.h" diff --git a/src/audiosfx.c b/src/audiosfx.c index 1f0c0435..e77fc950 100644 --- a/src/audiosfx.c +++ b/src/audiosfx.c @@ -1,18 +1,25 @@ #include "audiosfx.h" #include "memory.h" -#include "audio_internal.h" #include "video.h" #include "math_util.h" #include "asset_loading.h" #include "objects.h" #include "PR/libaudio.h" -ALUnkStruct D_800DC6B0 = { NULL, NULL, NULL }; -unk800DC6BC gAlSndPlayer; -unk800DC6BC *gAlSndPlayerPtr = &gAlSndPlayer; -s32 sfxVolumeSlider = 256; -s16 D_800DC6C4 = 0; -u16 *gSoundChannelVolume; +#define SOUND_PARAM_DURATION(m) (m->velocityMax * 33333) +#define SOUND_PARAM_NEXT_SOUND(m) (m->velocityMin + (m->keyMin & 0xC0) * 4) +#define SOUND_PARAM_GROUP(m) (m->keyMin & 0x3F) +#define SOUND_PARAM_FLAGS(m) (m->keyMax & 0xF0) +#define SOUND_PARAM_FXMIX(m) (m->keyMax & 0xF) +#define SOUND_PARAM_PITCH_SLIDE_RATE(m) (m->detune) +#define SOUND_PARAM_PITCH(m) (m->keyBase * 100 - 6000) + +ALSoundStateLists gSoundStateLists = { NULL, NULL, NULL }; +SoundPlayer gSoundPlayer; +SoundPlayer *gSoundPlayerPtr = &gSoundPlayer; +s32 gSoundGlobalVolume = 256; +s16 gNumActiveSounds = 0; +s16 *gSoundGroupVolume; /**** Debug strings ****/ const char D_800E4AB0[] = "Bad soundState: voices =%d, states free =%d, states busy =%d, type %d data %x\n"; @@ -22,28 +29,35 @@ const char D_800E4B34[] = "Sound state allocate failed - sndId %d\n"; const char D_800E4B5C[] = "Don't worry - game should cope OK\n"; const char D_800E4B80[] = "WARNING: Attempt to stop NULL sound aborted\n"; -static void _removeEvents(ALEventQueue *, ALSoundState *, u16); +static void sndp_remove_events(ALEventQueue *, ALSoundState *, u16); +void func_80065A80(ALSynth *arg0, struct PVoice_s *arg1, s16 arg2); -void set_sfx_volume_slider(u32 volume) { +/** + * Sets the global volume level for all sounds. + */ +void sndp_set_global_volume(u32 volume) { if (volume > 256) { volume = 256; } - sfxVolumeSlider = volume; + gSoundGlobalVolume = volume; } -s32 get_sfx_volume_slider(void) { - return sfxVolumeSlider; +/** + * Returns the global volume level applied to all sounds. + */ +s32 sndp_get_global_volume(void) { + return gSoundGlobalVolume; } /** * Sets the number of active sound channels to either the passed number, or the maximum amount, whichever's lower. */ -void set_sound_channel_count(s32 numChannels) { - if (gAlSndPlayerPtr->soundChannelsMax >= numChannels) { - gAlSndPlayerPtr->soundChannels = numChannels; +void sndp_set_active_sound_limit(s32 numSounds) { + if (gSoundPlayerPtr->maxSystemSoundChannels >= numSounds) { + gSoundPlayerPtr->maxActiveSounds = numSounds; } else { - gAlSndPlayerPtr->soundChannels = gAlSndPlayerPtr->soundChannelsMax; + gSoundPlayerPtr->maxActiveSounds = gSoundPlayerPtr->maxSystemSoundChannels; } } @@ -51,53 +65,68 @@ void set_sound_channel_count(s32 numChannels) { * Initialise a sound player and ready it for use with the sound event system. * Official Name: gsSndpNew */ -void alSndPNew(audioMgrConfig *c) { +void sndp_init_player(audioMgrConfig *c) { u32 i; - unk800DC6BC_40 *tmp1; + ALSoundState *sounds; ALEvent evt; + ALEventListItem *items; /* * Init member variables */ - gAlSndPlayerPtr->soundChannelsMax = c->maxChannels; - gAlSndPlayerPtr->soundChannels = c->maxChannels; - gAlSndPlayerPtr->unk3C = 0; - gAlSndPlayerPtr->frameTime = 33000; // AL_USEC_PER_FRAME /* time between API events */ - gAlSndPlayerPtr->unk40 = (unk800DC6BC_40 *) alHeapAlloc(c->hp, 1, c->unk00 * sizeof(unk800DC6BC_40)); - alEvtqNew(&(gAlSndPlayerPtr->evtq), alHeapAlloc(c->hp, 1, (c->unk04) * 28), c->unk04); - D_800DC6B0.unk8 = (ALSoundState *) gAlSndPlayerPtr->unk40; - for (i = 1; i < c->unk00; i++) { - tmp1 = gAlSndPlayerPtr->unk40; - alLink((ALLink *) (i + tmp1), (ALLink *) (i + tmp1 - 1)); - } + gSoundPlayerPtr->maxSystemSoundChannels = c->maxChannels; + gSoundPlayerPtr->maxActiveSounds = c->maxChannels; + gSoundPlayerPtr->lastSoundState = NULL; + gSoundPlayerPtr->frameTime = 33000; // AL_USEC_PER_FRAME /* time between API events */ + gSoundPlayerPtr->soundStatesArray = (ALSoundState *) alHeapAlloc(c->heap, 1, c->maxSounds * sizeof(ALSoundState)); /* * init the event queue */ - gSoundChannelVolume = alHeapAlloc(c->hp, 2, c->unk10); - for (i = 0; i < c->unk10; i++) { - gSoundChannelVolume[i] = 32767; + items = (ALEventListItem *) alHeapAlloc(c->heap, 1, c->maxEvents * sizeof(ALEventListItem)); + alEvtqNew(&gSoundPlayerPtr->evtq, items, c->maxEvents); + + /* + * Link all sound states into a linked list. + */ + gSoundStateLists.freeHead = (ALSoundState *) gSoundPlayerPtr->soundStatesArray; + for (i = 1; i < c->maxSounds; i++) { + sounds = gSoundPlayerPtr->soundStatesArray; + alLink(&(sounds + i)->next, &(sounds + i - 1)->next); + } + + /* + * Allocate and initialize the per-group volume table. + * Each group starts with maximum volume (32767). + */ + gSoundGroupVolume = alHeapAlloc(c->heap, sizeof(*gSoundGroupVolume), c->numGroups); + for (i = 0; i < c->numGroups; i++) { + gSoundGroupVolume[i] = AL_SNDP_GROUP_VOLUME_MAX; } /* * add ourselves to the driver */ - gAlSndPlayerPtr->drvr = (ALSynth *) alGlobals; - gAlSndPlayerPtr->node.next = NULL; - gAlSndPlayerPtr->node.handler = _sndpVoiceHandler; - gAlSndPlayerPtr->node.clientData = gAlSndPlayerPtr; - alSynAddPlayer(gAlSndPlayerPtr->drvr, (ALPlayer *) gAlSndPlayerPtr); + gSoundPlayerPtr->drvr = &alGlobals->drvr; + gSoundPlayerPtr->node.next = NULL; + gSoundPlayerPtr->node.handler = sndp_voice_handler; + gSoundPlayerPtr->node.clientData = gSoundPlayerPtr; + alSynAddPlayer(gSoundPlayerPtr->drvr, &gSoundPlayerPtr->node); /* * Start responding to API events */ evt.type = AL_SNDP_API_EVT; - alEvtqPostEvent(&gAlSndPlayerPtr->evtq, (ALEvent *) &evt, gAlSndPlayerPtr->frameTime); - gAlSndPlayerPtr->nextDelta = alEvtqNextEvent(&gAlSndPlayerPtr->evtq, &gAlSndPlayerPtr->nextEvent); + alEvtqPostEvent(&gSoundPlayerPtr->evtq, (ALEvent *) &evt, gSoundPlayerPtr->frameTime); + gSoundPlayerPtr->nextDelta = alEvtqNextEvent(&gSoundPlayerPtr->evtq, &gSoundPlayerPtr->nextEvent); } -ALMicroTime _sndpVoiceHandler(void *node) { - unk800DC6BC *sndp = (unk800DC6BC *) node; +/** + * Copy of _sndpVoiceHandler from libultra. + * Processes all queued events that are due at the current time. + */ +ALMicroTime sndp_voice_handler(void *node) { + SoundPlayer *sndp = (SoundPlayer *) node; ALSndpEvent evt; u32 eventType = AL_SNDP_API_EVT; @@ -109,7 +138,7 @@ ALMicroTime _sndpVoiceHandler(void *node) { break; default: - _handleEvent(sndp, (ALSndpEvent *) &sndp->nextEvent); + sndp_handle_event(sndp, (ALSndpEvent *) &sndp->nextEvent); break; } sndp->nextDelta = alEvtqNextEvent(&sndp->evtq, &sndp->nextEvent); @@ -119,29 +148,338 @@ ALMicroTime _sndpVoiceHandler(void *node) { return sndp->nextDelta; } -#pragma GLOBAL_ASM("asm/nonmatchings/audiosfx/_handleEvent.s") +/** + * Modified version of _handleEvent from libultra. + * Processes the current event for the sound player. + */ +void sndp_handle_event(SoundPlayer *sndp, ALSndpEvent *event) { + ALVoiceConfig config; + ALVoice *voice; + s32 delta; + s32 limitReached; + ALSndpEvent spAC; + ALSndpEvent nextStateEvent; + ALSound *sound; + ALKeyMap *keyMap; + s32 volume; + s32 fxMix; + s32 isEventForSingleSound; + ALPan pan; + s32 lastInSequence; + s32 isVoiceAllocated; + ALSoundState *soundState; + ALSoundState *nextState; -void func_8000410C(ALSoundState *state) { - if (state->flags & AL_SNDP_PAN_EVT) { - alSynStopVoice(gAlSndPlayerPtr->drvr, &state->voice); - alSynFreeVoice(gAlSndPlayerPtr->drvr, &state->voice); + lastInSequence = TRUE; + isVoiceAllocated = FALSE; + soundState = NULL; + nextState = NULL; + + do { + if (nextState != NULL) { + nextStateEvent.common.state = soundState; + nextStateEvent.common.type = event->common.type; + nextStateEvent.common.param = event->common.param; + event = &nextStateEvent; + } + + soundState = event->common.state; + sound = soundState->sound; + + if (sound == NULL) { + u16 numFree, numAlloc; + sndp_get_state_counts(&numFree, &numAlloc); + return; + } + + keyMap = sound->keyMap; + nextState = soundState->next; + + switch (event->common.type) { + case AL_SNDP_PLAY_EVT: + if (soundState->state != SOUND_STATE_INIT && soundState->state != SOUND_STATE_WAIT_VOICE) { + return; + } + + config.fxBus = 0; + config.priority = soundState->priority; + config.unityPitch = 0; + + limitReached = sndp->maxActiveSounds <= gNumActiveSounds; + + if (!limitReached || (soundState->flags & SOUND_FLAG_RETRIGGER)) { + // Allocate a voice for the sound + // for retriggered sounds, ignore the limit + isVoiceAllocated = alSynAllocVoice(sndp->drvr, &soundState->voice, &config); + } + if (isVoiceAllocated) { + func_80065A80(sndp->drvr, soundState->voice.pvoice, 1); + } + + voice = &soundState->voice; + if (!isVoiceAllocated) { + // No free voices available, wait for another sound to stop. + if ((soundState->flags & (SOUND_FLAG_RETRIGGER | SOUND_FLAG_LOOPED)) || soundState->retries > 0) { + // Retry on the next frame. + // For looped and retriggered sounds, keep retrying on each frame. + soundState->state = SOUND_STATE_WAIT_VOICE; + soundState->retries--; + alEvtqPostEvent(&sndp->evtq, (ALEvent *) event, 33333); + } else { + // Not a looped or retriggered sound, and all retries have been exhausted. + if (limitReached) { + // Check if we can preempt a lower-priority sound. + ALSoundState *iterState = gSoundStateLists.allocTail; + + do { + if (iterState->priority <= soundState->priority && + iterState->state != SOUND_STATE_PREEMPT) { + // Found a lower-priority sound; it can be preempted + ALSndpEvent interruptEvent; + + interruptEvent.common.type = AL_SNDP_END_EVT; + interruptEvent.common.state = iterState; + iterState->state = SOUND_STATE_PREEMPT; + limitReached = FALSE; + alEvtqPostEvent(&sndp->evtq, (ALEvent *) &interruptEvent, 1000); + alSynSetVol(sndp->drvr, &iterState->voice, (soundState->state == 1) * 0, + 1000); // FAKE + } + iterState = iterState->prev; + } while (limitReached && iterState != NULL); + + if (!limitReached) { + // Retry the sound that was preempted. + soundState->retries = 2; + alEvtqPostEvent(&sndp->evtq, (ALEvent *) event, 1001); + } else { + // No lower-priority sound to preempt, so stop the sound. + sndp_end(soundState); + } + } else { + // It seems the developers made a mistake with the logic here. + // Should we stop the sound immediately if the maximum number of sounds hasn't been reached? + // Perhaps it would be better to look for a sound to preempt, just like when the limit is + // reached. It's strange that we only check for sounds to preempt when the limit is reached, + // but not when it hasn't been. + sndp_end(soundState); + } + } + return; + } + + soundState->flags |= SOUND_FLAG_PLAYING; + alSynStartVoice(sndp->drvr, voice, sound->wavetable); + soundState->state = SOUND_STATE_PLAYING; + gNumActiveSounds++; + + // Set volume + delta = sound->envelope->attackTime / soundState->pitch / soundState->slideMult; + volume = + MAX(0, gSoundGroupVolume[SOUND_PARAM_GROUP(keyMap)] * + (sound->envelope->attackVolume * soundState->volume * sound->sampleVolume / 16129) / + AL_SNDP_GROUP_VOLUME_MAX - + 1); + volume = (u32) (volume * gSoundGlobalVolume) >> 8; + alSynSetVol(sndp->drvr, &soundState->voice, 0, 0); + alSynSetVol(sndp->drvr, &soundState->voice, volume, delta); + + // Set pan + pan = MIN(MAX((soundState->pan + sound->samplePan - AL_PAN_CENTER), AL_PAN_LEFT), AL_PAN_RIGHT); + alSynSetPan(sndp->drvr, &soundState->voice, pan); + + // Set pitch + alSynSetPitch(sndp->drvr, &soundState->voice, soundState->pitch * soundState->slideMult); + + // Set FX mix + //!@bug: SOUND_PARAM_FXMIX is allocated only four bits, so it needs to be multiplied by 8 + // to scale it to a range of 0 to 127. + // However, it's unclear why soundState->fxmix also needs to be multiplied by 8. + // The same issue appears in the AL_SNDP_FX_EVT handler. + fxMix = (soundState->fxmix + SOUND_PARAM_FXMIX(keyMap)) * 8; + fxMix = MIN(127, MAX(0, fxMix)); + alSynSetFXMix(sndp->drvr, &soundState->voice, fxMix); + + // Queue the decay event + spAC.common.type = AL_SNDP_DECAY_EVT; + spAC.common.state = soundState; + alEvtqPostEvent(&sndp->evtq, (ALEvent *) &spAC, + sound->envelope->attackTime / soundState->pitch / soundState->slideMult); + break; + case AL_SNDP_RELEASE_EVT: + case AL_SNDP_STOP_EVT: + case AL_SNDP_RELEASE_NEXT_EVT: + // If any sound in the composite sound is in the release phase, ignore this event for all other sounds + // in the sequence, because they haven't started yet. + // However, if the other sound is looped, process the event anyway. + // + // The purpose of checking for a looped sound seems unclear. + // Does it imply that a composite sound can't contain looped simple sounds? + // It seems logical, but the check may still be redundant. + if (event->common.type != AL_SNDP_RELEASE_NEXT_EVT || (soundState->flags & SOUND_FLAG_LOOPED)) { + switch (soundState->state) { + case SOUND_STATE_PLAYING: + sndp_remove_events(&sndp->evtq, soundState, AL_SNDP_DECAY_EVT); + delta = sound->envelope->releaseTime / soundState->slideMult / soundState->pitch; + alSynSetVol(sndp->drvr, &soundState->voice, 0, delta); + if (delta != 0) { + spAC.common.type = AL_SNDP_END_EVT; + spAC.common.state = soundState; + alEvtqPostEvent(&sndp->evtq, (ALEvent *) &spAC, delta); + soundState->state = SOUND_STATE_STOPPING; + } else { + sndp_end(soundState); + } + break; + case SOUND_STATE_WAIT_VOICE: + case SOUND_STATE_INIT: + sndp_end(soundState); + break; + } + if (event->common.type == AL_SNDP_RELEASE_EVT) { + event->common.type = AL_SNDP_RELEASE_NEXT_EVT; + } + } + break; + case AL_SNDP_PAN_EVT: + soundState->pan = event->common.param; + if (soundState->state == SOUND_STATE_PLAYING) { + pan = MIN(MAX((soundState->pan + sound->samplePan - AL_PAN_CENTER), AL_PAN_LEFT), AL_PAN_RIGHT); + alSynSetPan(sndp->drvr, &soundState->voice, pan); + } + break; + case AL_SNDP_PITCH_EVT: + soundState->pitch = *(f32 *) &event->common.param; + if (soundState->state == SOUND_STATE_PLAYING) { + alSynSetPitch(sndp->drvr, &soundState->voice, soundState->pitch * soundState->slideMult); + if (soundState->flags & SOUND_FLAG_PITCH_SLIDE) { + sndp_apply_pitch_slide(soundState); + } + } + break; + case AL_SNDP_FX_EVT: + soundState->fxmix = event->common.param; + if (soundState->state == SOUND_STATE_PLAYING) { + //!@bug: unnecessary multiplication by 8 + // The same issue appears in the AL_SNDP_PLAY_EVT handler. + fxMix = (soundState->fxmix + SOUND_PARAM_FXMIX(keyMap)) * 8; + fxMix = MIN(127, MAX(0, fxMix)); + alSynSetFXMix(sndp->drvr, &soundState->voice, fxMix); + } + break; + case AL_SNDP_VOL_EVT: + soundState->volume = event->common.param; + if (soundState->state == SOUND_STATE_PLAYING) { + volume = MAX( + 0, gSoundGroupVolume[SOUND_PARAM_GROUP(keyMap)] * + (sound->envelope->decayVolume * soundState->volume * sound->sampleVolume / 16129) / + AL_SNDP_GROUP_VOLUME_MAX - + 1); + volume = (u32) (volume * gSoundGlobalVolume) >> 8; + alSynSetVol(sndp->drvr, &soundState->voice, volume, 1000); + } + break; + case AL_SNDP_GROUP_VOL_EVT: + if (soundState->state == SOUND_STATE_PLAYING) { + delta = sound->envelope->releaseTime / soundState->slideMult / soundState->pitch; + volume = MAX( + 0, gSoundGroupVolume[SOUND_PARAM_GROUP(keyMap)] * + (sound->envelope->decayVolume * soundState->volume * sound->sampleVolume / 16129) / + AL_SNDP_GROUP_VOLUME_MAX - + 1); + volume = (u32) (volume * gSoundGlobalVolume) >> 8; + alSynSetVol(sndp->drvr, &soundState->voice, volume, delta); + } + break; + case AL_SNDP_DECAY_EVT: + /* + * The voice has theoretically reached its attack velocity, + * set up callback for release envelope - except for a looped sound + */ + if (!(soundState->flags & SOUND_FLAG_LOOPED)) { + volume = MAX( + 0, gSoundGroupVolume[SOUND_PARAM_GROUP(keyMap)] * + (sound->envelope->decayVolume * soundState->volume * sound->sampleVolume / 16129) / + AL_SNDP_GROUP_VOLUME_MAX - + 1); + volume = (u32) (volume * gSoundGlobalVolume) >> 8; + delta = sound->envelope->decayTime / soundState->slideMult / soundState->pitch; + alSynSetVol(sndp->drvr, &soundState->voice, volume, delta); + + spAC.common.type = AL_SNDP_RELEASE_EVT; + spAC.common.state = soundState; + alEvtqPostEvent(&sndp->evtq, (ALEvent *) &spAC, delta); + + // Start applying the pitch slide only when the decay phase is reached. + if (soundState->flags & SOUND_FLAG_PITCH_SLIDE) { + sndp_apply_pitch_slide(soundState); + } + } + break; + case AL_SNDP_END_EVT: + sndp_end(soundState); + break; + case AL_SNDP_RETRIGGER_EVT: + if (soundState->flags & SOUND_FLAG_RETRIGGER) { + // Start the new sound and copy the parameters from the old one + // to the new one. + ALSoundState *newSound = + sndp_play(event->retrigger.bank, event->retrigger.soundIndex, soundState->userHandle); + if (newSound != NULL) { + sndp_set_param(newSound, AL_SNDP_VOL_EVT, soundState->volume); + if ((!event) && (!event)) {} // Fake + sndp_set_param(newSound, AL_SNDP_PAN_EVT, soundState->pan); + sndp_set_param(newSound, AL_SNDP_FX_EVT, soundState->fxmix); + sndp_set_param(newSound, AL_SNDP_PITCH_EVT, *(s32 *) &soundState->pitch); + } + } + break; + default: + break; + } + + soundState = nextState; + isEventForSingleSound = event->common.type & (AL_SNDP_PLAY_EVT | AL_SNDP_PITCH_EVT | AL_SNDP_DECAY_EVT | + AL_SNDP_END_EVT | AL_SNDP_RETRIGGER_EVT); + + if (soundState != NULL && !isEventForSingleSound) { + lastInSequence = soundState->flags & SOUND_FLAG_FINAL_IN_SEQUENCE; + } + + } while (!lastInSequence && soundState != NULL && !isEventForSingleSound); +} + +/** + * Immediately stop the sound and release all associated resources. + */ +void sndp_end(ALSoundState *state) { + if (state->flags & SOUND_FLAG_PLAYING) { + alSynStopVoice(gSoundPlayerPtr->drvr, &state->voice); + alSynFreeVoice(gSoundPlayerPtr->drvr, &state->voice); } - func_80004520(state); - _removeEvents(&gAlSndPlayerPtr->evtq, state, 0xFFFF); + sndp_deallocate(state); + sndp_remove_events(&gSoundPlayerPtr->evtq, state, 0xFFFF); } -void func_8000418C(ALVoiceState *voiceState) { - ALEvent_unk8000418C evt; - f32 sp1C; +/** + * Changes the pitch slide and enqueues an event to continue the pitch slide on the next frame + */ +void sndp_apply_pitch_slide(ALSoundState *soundState) { + ALSndpEvent evt; + f32 pitch; - sp1C = alCents2Ratio(((ALLink_unk8000418C *) voiceState->voice.node.prev->prev)->unk5) * voiceState->vibrato; - evt.type = AL_SEQP_STOP_EVT; - evt.unk4 = voiceState; - evt.unk8 = *((s32 *) &sp1C); // But why tho? - alEvtqPostEvent(&gAlSndPlayerPtr->evtq, (ALEvent *) &evt, 33333); + pitch = alCents2Ratio(SOUND_PARAM_PITCH_SLIDE_RATE(soundState->sound->keyMap)) * soundState->pitch; + evt.common.type = AL_SNDP_PITCH_EVT; + evt.common.state = soundState; + evt.common.param = *((s32 *) &pitch); + alEvtqPostEvent(&gSoundPlayerPtr->evtq, (ALEvent *) &evt, 33333); } -static void _removeEvents(ALEventQueue *evtq, ALSoundState *state, u16 eventType) { +/** + * Modified version of _sndpRemoveEvents from libultra. + * Removes all events associated with the given sound state, filtered by eventTypeMask, from the event queue. + */ +static void sndp_remove_events(ALEventQueue *evtq, ALSoundState *state, u16 eventTypeMask) { ALLink *thisNode; ALLink *nextNode; ALEventListItem *thisItem; @@ -157,7 +495,7 @@ static void _removeEvents(ALEventQueue *evtq, ALSoundState *state, u16 eventType thisItem = (ALEventListItem *) thisNode; nextItem = (ALEventListItem *) nextNode; thisEvent = (ALSndpEvent *) &thisItem->evt; - if (thisEvent->common.state == state && (u16) thisEvent->msg.type & eventType) { + if (thisEvent->common.state == state && (thisEvent->common.type & eventTypeMask)) { if (nextItem) { nextItem->delta += thisItem->delta; } @@ -171,230 +509,338 @@ static void _removeEvents(ALEventQueue *evtq, ALSoundState *state, u16 eventType } /** + * Takes two pointers as arguments and writes the number of free and allocated sound states to them. + * Additionally, it counts the number of allocated sound states in reverse order. + * But why? It should be the same as in the forward order. * Official Name: getSoundStateCounts */ -u16 func_800042CC(u16 *lastAllocListIndex, u16 *lastFreeListIndex) { +u16 sndp_get_state_counts(u16 *numFree, u16 *numAllocated) { OSIntMask mask; - u16 freeListNextIndex; - u16 allocListNextIndex; - u16 freeListLastIndex; - ALSoundState *nextAllocList; - ALSoundState *nextFreeList; - ALSoundState *prevFreeList; - ALSoundState *queue; + u16 allocatedCounter; + u16 freeCounter; + u16 allocatedRevCounter; + ALSoundState *freePtr; + ALSoundState *allocatedPtr; + ALSoundState *allocatedRevPtr; mask = osSetIntMask(OS_IM_NONE); - queue = (ALSoundState *) &D_800DC6B0; - nextFreeList = queue->next; - nextAllocList = queue->unk8; - prevFreeList = queue->prev; + allocatedPtr = gSoundStateLists.allocHead; + freePtr = gSoundStateLists.freeHead; + allocatedRevPtr = gSoundStateLists.allocTail; - for (freeListNextIndex = 0; nextFreeList != NULL; freeListNextIndex++) { - nextFreeList = nextFreeList->next; + for (allocatedCounter = 0; allocatedPtr != NULL; allocatedCounter++) { + allocatedPtr = allocatedPtr->next; } - for (allocListNextIndex = 0; nextAllocList != NULL; allocListNextIndex++) { - nextAllocList = nextAllocList->next; + for (freeCounter = 0; freePtr != NULL; freeCounter++) { + freePtr = freePtr->next; } - for (freeListLastIndex = 0; prevFreeList != NULL; freeListLastIndex++) { - prevFreeList = prevFreeList->prev; + for (allocatedRevCounter = 0; allocatedRevPtr != NULL; allocatedRevCounter++) { + allocatedRevPtr = allocatedRevPtr->prev; } - *lastAllocListIndex = allocListNextIndex; - *lastFreeListIndex = freeListNextIndex; + *numFree = freeCounter; + *numAllocated = allocatedCounter; osSetIntMask(mask); - return freeListLastIndex; + return allocatedRevCounter; } -// This function is full of names like next / prev that I made up based on other funcs. -// It's in no way guaranteed to be correct. -// I'm really not even sure what it's supposed to be returning as a type. -ALSound *func_80004384(UNUSED ALBank *arg0, ALSound *arg1) { - s32 temp; - ALKeyMap *temp_a2; - unk80004384 *nextAllocList; +/** + * Allocates a sound and sets its initial parameters, + * including values from the ALKeyMap structure. + * Returns NULL if there are no free sound states available. + */ +ALSoundState *sndp_allocate(UNUSED ALBank *bank, ALSound *sound) { + s32 isLooping; + ALKeyMap *keyMap; + ALSoundState *state; u32 mask; - s32 temp_a1; + s32 priority; - nextAllocList = (unk80004384 *) D_800DC6B0.unk8; - temp_a2 = arg1->keyMap; - if (nextAllocList != NULL) { + state = gSoundStateLists.freeHead; + keyMap = sound->keyMap; + if (state != NULL) { mask = osSetIntMask(OS_IM_NONE); - D_800DC6B0.unk8 = nextAllocList->next; - alUnlink((ALLink *) nextAllocList); - if (D_800DC6B0.next != NULL) { - nextAllocList->next = D_800DC6B0.next; - nextAllocList->prev = NULL; - D_800DC6B0.next->prev = (ALSoundState *) nextAllocList; - D_800DC6B0.next = (ALSoundState *) nextAllocList; + gSoundStateLists.freeHead = state->next; + alUnlink((ALLink *) state); + if (gSoundStateLists.allocHead != NULL) { + state->next = gSoundStateLists.allocHead; + state->prev = NULL; + gSoundStateLists.allocHead->prev = state; + gSoundStateLists.allocHead = state; } else { - nextAllocList->prev = NULL; - nextAllocList->next = NULL; - D_800DC6B0.next = (ALSoundState *) nextAllocList; - D_800DC6B0.prev = (ALSoundState *) nextAllocList; + state->prev = NULL; + state->next = NULL; + gSoundStateLists.allocHead = state; + gSoundStateLists.allocTail = state; } osSetIntMask(mask); - temp = ((arg1->envelope->decayTime + 1) == 0); - temp_a1 = temp + 0x40; - temp = 6000; - nextAllocList->unk36 = temp_a1; - nextAllocList->unk3F = 5; - nextAllocList->unk38 = 2; - nextAllocList->unk8 = (ALSoundState *) arg1; - nextAllocList->unk2C = 1.0f; - nextAllocList->unk3E = temp_a2->keyMax & 0xF0; - nextAllocList->unk30 = 0; - if (nextAllocList->unk3E & 0x20) { - nextAllocList->unk28 = alCents2Ratio((temp_a2->keyBase * 100) - temp); + + isLooping = sound->envelope->decayTime == -1; + priority = isLooping + AL_SNDP_PRIORITY_DEFAULT; // Looped sounds are assigned higher priority + isLooping = 6000; // required to match + state->priority = priority; + state->state = SOUND_STATE_INIT; + state->retries = 2; + state->sound = sound; + state->pitch = 1.0f; + state->flags = SOUND_PARAM_FLAGS(keyMap); + state->userHandle = NULL; + if (state->flags & SOUND_FLAG_PITCH_SLIDE) { + state->slideMult = alCents2Ratio(SOUND_PARAM_PITCH(keyMap)); } else { - nextAllocList->unk28 = alCents2Ratio(((temp_a2->keyBase * 100) + temp_a2->detune) - temp); + state->slideMult = alCents2Ratio(SOUND_PARAM_PITCH(keyMap) + SOUND_PARAM_PITCH_SLIDE_RATE(keyMap)); } - if (temp_a1 != 0x40) { - nextAllocList->unk3E |= 2; + if (priority != AL_SNDP_PRIORITY_DEFAULT) { + state->flags |= SOUND_FLAG_LOOPED; } - nextAllocList->unk3D = 0; - nextAllocList->unk3C = 0x40; - nextAllocList->unk34 = 0x7FFF; + state->fxmix = 0; + state->pan = AL_PAN_CENTER; + state->volume = 0x7FFF; } - return (ALSound *) nextAllocList; + return state; } -void func_80004520(ALSoundState *soundState) { - if (soundState == D_800DC6B0.next) { - D_800DC6B0.next = soundState->next; +/** + * Deallocates a sound state and returns it to the free list. + * If the sound state is currently playing, it decrements the active sound count. + * If the sound state has a user handle, it sets it to NULL, to notify the user that the sound has stopped. + */ +void sndp_deallocate(ALSoundState *state) { + if (state == gSoundStateLists.allocHead) { + gSoundStateLists.allocHead = state->next; } - if (soundState == D_800DC6B0.prev) { - D_800DC6B0.prev = soundState->prev; + if (state == gSoundStateLists.allocTail) { + gSoundStateLists.allocTail = state->prev; } - alUnlink((ALLink *) soundState); - if (D_800DC6B0.unk8 != NULL) { - soundState->next = D_800DC6B0.unk8; - soundState->prev = NULL; - D_800DC6B0.unk8->prev = soundState; - D_800DC6B0.unk8 = soundState; + alUnlink((ALLink *) state); + if (gSoundStateLists.freeHead != NULL) { + state->next = gSoundStateLists.freeHead; + state->prev = NULL; + gSoundStateLists.freeHead->prev = state; + gSoundStateLists.freeHead = state; } else { - soundState->prev = NULL; - soundState->next = NULL; - D_800DC6B0.unk8 = soundState; + state->prev = NULL; + state->next = NULL; + gSoundStateLists.freeHead = state; } - if (soundState->flags & AL_SNDP_PAN_EVT) { - D_800DC6C4--; + if (state->flags & SOUND_FLAG_PLAYING) { + gNumActiveSounds--; } - soundState->soundState = 0; - if (soundState->unk30 != NULL) { - if (soundState == soundState->unk30->next) { - soundState->unk30->next = NULL; + state->state = SOUND_STATE_NONE; + if (state->userHandle != NULL) { + if (state == *state->userHandle) { + *state->userHandle = NULL; } - soundState->unk30 = NULL; + state->userHandle = NULL; } } /** + * Sets the priority for voice allocation and for preempting another sound. * Official Name: gsSndpSetPriority */ -void func_80004604(ALSoundState *sndp, u8 priority) { +void sndp_set_priority(ALSoundState *sndp, u8 priority) { if (sndp != NULL) { - sndp->soundPriority = priority; + sndp->priority = priority; } } /** + * Retrieves the current sound state, refer to the SoundStates enum. * Official Name: gsSndpGetState */ -UNUSED u8 func_8000461C(ALSoundState *sndp) { +UNUSED u8 sndp_get_state(ALSoundState *sndp) { if (sndp != NULL) { - return sndp->soundState; + return sndp->state; } else { - return 0; + return SOUND_STATE_NONE; } } -s32 func_80004638(ALBank *bnk, s16 sndIndx, SoundMask *soundMask) { - return func_80004668(bnk, sndIndx, 0, soundMask); +/** + * Plays the sound with the default priority, store the handle in the provided pointer. + */ +ALSoundState *sndp_play(ALBank *bnk, s16 sndIndx, ALSoundState **handlePtr) { + return sndp_play_with_priority(bnk, sndIndx, 0, handlePtr); } -#ifdef NON_EQUIVALENT -s32 func_80004668(ALBank *bnk, s16 sndIndx, u8 arg2, SoundMask *soundMask) { - return 0; -} -#else -#pragma GLOBAL_ASM("asm/nonmatchings/audiosfx/func_80004668.s") -#endif - /** - * input typing not right (some type of struct) - * 99% sure this function will clear the audio buffer associated with a given sound mask. + * Plays the sound with the given priority. + * For composite sounds, creates all the individual sounds in the sequence to start playing at the correct times, + * though this part of the code contains bugs. + * Also, for retriggered sounds, schedules an event to restart them. + */ +ALSoundState *sndp_play_with_priority(ALBank *bank, s16 sndIndx, u8 priority, ALSoundState **handlePtr) { + ALSound *sound; + ALSoundState *lastSoundState; + ALSoundState *soundState; + ALMicroTime totalDuration; + s16 retriggeredSoundID; + ALMicroTime retriggerInterval; + ALMicroTime duration; + ALKeyMap *keyMap; + + lastSoundState = NULL; + retriggeredSoundID = 0; + totalDuration = 0; + + if (sndIndx == SOUND_NONE) { + return NULL; + } + + do { + sound = bank->instArray[0]->soundArray[sndIndx - 1]; + soundState = sndp_allocate(bank, sound); + if (soundState != NULL) { + ALSndpEvent playEvent; + + gSoundPlayerPtr->lastSoundState = soundState; + + playEvent.common.type = AL_SNDP_PLAY_EVT; + playEvent.common.state = soundState; + duration = SOUND_PARAM_DURATION(sound->keyMap); + + // zero priority means default priority which is set in sndp_allocate + if (priority != 0) { + soundState->priority = priority; + } + + if (soundState->flags & SOUND_FLAG_RETRIGGER) { + //!@bug probably: + // If the sequence contains multiple retriggered sounds, only the last one will be retriggered. + // Also, there seems to be confusion between durations, intervals, etc. + // Needs verification, but SOUND_PARAM_DURATION likely refers to the duration of each individual sound. + // If so, then each sound should begin with a delay of `totalDuration` (which is handled correctly + // here). And if `retriggerInterval` is set to duration + 1, the retriggering will occur at correct + // intervals, but the first retrigger will happen at the wrong time if the retriggered sound is part of + // a composite sound. Possibly, the developers didn't intend for retriggered sounds to be part of + // composite sequences — but that's unclear. + soundState->flags &= ~SOUND_FLAG_RETRIGGER; + alEvtqPostEvent(&gSoundPlayerPtr->evtq, (ALEvent *) &playEvent, totalDuration + 1); + retriggerInterval = duration + 1; + retriggeredSoundID = sndIndx; + } else { + //!@bug: Duration handling is definitely incorrect here. + // A delay of totalDuration + 1 should be used, as done above, + // otherwise sounds will start at the wrong time. + alEvtqPostEvent(&gSoundPlayerPtr->evtq, (ALEvent *) &playEvent, duration + 1); + } + + lastSoundState = soundState; + } + + // Potential UB: 'duration' may be uninitialized, but loop exits before `totalDuration` is used, + // so this has no observable effect + totalDuration += duration; + + keyMap = sound->keyMap; + sndIndx = SOUND_PARAM_NEXT_SOUND(keyMap); + + } while (sndIndx != SOUND_NONE && soundState != NULL); + + if (lastSoundState != NULL) { + lastSoundState->flags |= SOUND_FLAG_FINAL_IN_SEQUENCE; + + // Only the last sound in the sequence stores a pointer to the user handle. + lastSoundState->userHandle = handlePtr; + + // Schedule the retrigger event. + if (retriggeredSoundID != SOUND_NONE) { + ALSndpEvent evtRetrigger; + lastSoundState->flags |= SOUND_FLAG_RETRIGGER; + evtRetrigger.retrigger.type = AL_SNDP_RETRIGGER_EVT; + evtRetrigger.retrigger.state = lastSoundState; + evtRetrigger.retrigger.soundIndex = retriggeredSoundID; + evtRetrigger.retrigger.bank = bank; + alEvtqPostEvent(&gSoundPlayerPtr->evtq, (ALEvent *) &evtRetrigger, retriggerInterval); + } + } + + if (handlePtr != NULL) { + *handlePtr = lastSoundState; + } + return lastSoundState; +} + +/** + * Schedules a stop event for the given sound state and disables the retrigger flag. * Official Name: gsSndpStop */ -void sound_stop(ALSoundState *sndp) { - ALEvent alEvent; +void sndp_stop(ALSoundState *state) { + ALSndpEvent alEvent; - alEvent.type = AL_SNDP_UNK_10_EVT; - alEvent.msg.sndpevent.soundState = sndp; - if (sndp != NULL) { - sndp->flags &= ~AL_SNDP_PITCH_EVT; - alEvtqPostEvent(&gAlSndPlayerPtr->evtq, &alEvent, 0); + alEvent.common.type = AL_SNDP_STOP_EVT; + alEvent.common.state = state; + if (state != NULL) { + state->flags &= ~SOUND_FLAG_RETRIGGER; + alEvtqPostEvent(&gSoundPlayerPtr->evtq, &alEvent, 0); } else { // From JFG // osSyncPrintf("WARNING: Attempt to stop NULL sound aborted\n"); } } -void func_800048D8(u8 event) { +/** + * Schedules a stop event for all sound states that have the specified flags set. + */ +void sndp_stop_with_flags(u8 flags) { OSIntMask mask; - ALEvent evt; - ALSoundState *queue; + ALSndpEvent evt; + ALSoundState *soundState; mask = osSetIntMask(OS_IM_NONE); - queue = D_800DC6B0.next; - while (queue != NULL) { - evt.type = AL_SNDP_UNK_10_EVT; - evt.msg.sndpevent.soundState = queue; - if ((queue->flags & event) == event) { - evt.msg.sndpevent.soundState->flags &= ~AL_SNDP_PITCH_EVT; - alEvtqPostEvent(&gAlSndPlayerPtr->evtq, &evt, 0); + soundState = gSoundStateLists.allocHead; + while (soundState != NULL) { + evt.common.type = AL_SNDP_STOP_EVT; + evt.common.state = soundState; + if ((soundState->flags & flags) == flags) { + evt.common.state->flags &= ~SOUND_FLAG_RETRIGGER; + alEvtqPostEvent(&gSoundPlayerPtr->evtq, &evt, 0); } - queue = queue->next; + soundState = soundState->next; } osSetIntMask(mask); } /** + * Stops all sounds from playing. * Official Name: gsSndpStopAll */ -UNUSED void func_80004998(void) { - func_800048D8(AL_SNDP_PLAY_EVT); +UNUSED void sndp_stop_all(void) { + sndp_stop_with_flags(SOUND_FLAG_FINAL_IN_SEQUENCE); } /** + * Stops all retriggered sounds from playing. * Official Name: gsSndpStopAllRetrigger */ -UNUSED void func_800049B8(void) { - func_800048D8(AL_SNDP_PLAY_EVT | AL_SNDP_PITCH_EVT); +UNUSED void sndp_stop_all_retrigger(void) { + sndp_stop_with_flags(SOUND_FLAG_FINAL_IN_SEQUENCE | SOUND_FLAG_RETRIGGER); } /** - * Stops all sounds from playing. + * Stops all looped sounds from playing. * Official Name: gsSndpStopAllLooped */ -void sound_stop_all(void) { - func_800048D8(AL_SNDP_PLAY_EVT | AL_SNDP_STOP_EVT); +void sndp_stop_all_looped(void) { + sndp_stop_with_flags(SOUND_FLAG_FINAL_IN_SEQUENCE | SOUND_FLAG_LOOPED); } /** * Send a message to the sound player to update an existing property of the sound entry. * Official Name: gsSndpSetParam */ -void sound_event_update(s32 soundMask, s16 type, u32 volume) { - ALEvent2 sndEvt; - sndEvt.snd_event.type = type; - sndEvt.snd_event.state = (void *) soundMask; - sndEvt.snd_event.param = volume; +void sndp_set_param(SoundHandle soundMask, s16 type, u32 paramValue) { + ALSndpEvent evt; + evt.common.type = type; + evt.common.state = soundMask; + evt.common.param = paramValue; if (soundMask != NULL) { - alEvtqPostEvent(&gAlSndPlayerPtr->evtq, (ALEvent *) &sndEvt, 0); + alEvtqPostEvent(&gSoundPlayerPtr->evtq, (ALEvent *) &evt, 0); } else { // From JFG // osSyncPrintf("WARNING: Attempt to modify NULL sound aborted\n"); @@ -405,34 +851,35 @@ void sound_event_update(s32 soundMask, s16 type, u32 volume) { * Returns the volume level of the channel ID. * Official Name: gsSndpGetMasterVolume */ -u16 get_sound_channel_volume(u8 channel) { - return gSoundChannelVolume[channel]; +u16 sndp_get_group_volume(u8 groupID) { + return gSoundGroupVolume[groupID]; } -// TODO: The structs used here are almost definitely wrong, but they do match, so it can at least show the pattern we're -// looking for. /** - * Looks for the intended audio channel in the main buffer and adjusts its volume + * Sets the volume for the specified group and updates the volume of all sounds in that group. + * + * !@bug: No bounds checking is performed on the group index. In DKR, only one group is defined and memory is allocated for a single group. + * This leads to out-of-bounds access, which can cause undefined behavior, including potential crashes. + * * Official Name: gsSndpSetMasterVolume */ -void set_sound_channel_volume(u8 channel, u16 volume) { +void sndp_set_group_volume(u8 groupID, u16 volume) { OSIntMask mask; - ALEventQueue *queue; + ALSoundState *state; UNUSED s32 pad; - ALEvent evt; + ALSndpEvent evt; mask = osSetIntMask(OS_IM_NONE); - queue = (ALEventQueue *) D_800DC6B0.next; - gSoundChannelVolume[channel] = volume; + state = gSoundStateLists.allocHead; + gSoundGroupVolume[groupID] = volume; - while (queue != NULL) { - // This is almost definitely the wrong struct list, but it matches so I'm not going to complain - if ((((ALInstrument *) queue->allocList.next->prev)->priority & 0x3F) == channel) { - evt.type = AL_SNDP_UNK_11_EVT; - evt.msg.spseq.seq = (void *) queue; - alEvtqPostEvent(&gAlSndPlayerPtr->evtq, &evt, 0); + while (state != NULL) { + if (SOUND_PARAM_GROUP(state->sound->keyMap) == groupID) { + evt.common.type = AL_SNDP_GROUP_VOL_EVT; + evt.common.state = state; + alEvtqPostEvent(&gSoundPlayerPtr->evtq, (ALEvent *) &evt, 0); } - queue = (ALEventQueue *) queue->freeList.next; + state = state->next; } osSetIntMask(mask); diff --git a/src/audiosfx.h b/src/audiosfx.h index c9278b69..51d896dd 100644 --- a/src/audiosfx.h +++ b/src/audiosfx.h @@ -3,14 +3,14 @@ #include "types.h" #include "macros.h" -#include "audio_internal.h" #include "asset_enums.h" #include #include "sched.h" #include "structs.h" +#include "audio.h" #define AL_SNDP_PLAY_EVT (1 << 0) -#define AL_SNDP_STOP_EVT (1 << 1) +#define AL_SNDP_RELEASE_EVT (1 << 1) #define AL_SNDP_PAN_EVT (1 << 2) #define AL_SNDP_VOL_EVT (1 << 3) #define AL_SNDP_PITCH_EVT (1 << 4) @@ -18,161 +18,121 @@ #define AL_SNDP_DECAY_EVT (1 << 6) #define AL_SNDP_END_EVT (1 << 7) #define AL_SNDP_FX_EVT (1 << 8) -#define AL_SNDP_UNK_9_EVT (1 << 9) -#define AL_SNDP_UNK_10_EVT (1 << 10) -#define AL_SNDP_UNK_11_EVT (1 << 11) +#define AL_SNDP_RETRIGGER_EVT (1 << 9) +#define AL_SNDP_STOP_EVT (1 << 10) +#define AL_SNDP_GROUP_VOL_EVT (1 << 11) +#define AL_SNDP_RELEASE_NEXT_EVT (1 << 12) -typedef struct ALUnkStruct { - /* 0x00 */ struct ALSoundState *next; - /* 0x04 */ struct ALSoundState *prev; - /* 0x08 */ struct ALSoundState *unk8; -} ALUnkStruct; +#define AL_SNDP_PRIORITY_DEFAULT 64 +#define AL_SNDP_GROUP_VOLUME_MAX 32767 -// typedef struct { -// u8 pad[0x36]; -// u8 priority; -// u8 pad37[0x7]; -// u8 flags; -// u8 state; -// } AlMsgUnk400Type_Unk0; +enum SoundFlags { + SOUND_FLAG_FINAL_IN_SEQUENCE = 1 << 0, + SOUND_FLAG_LOOPED = 1 << 1, + SOUND_FLAG_PLAYING = 1 << 2, + SOUND_FLAG_RETRIGGER = 1 << 4, + SOUND_FLAG_PITCH_SLIDE = 1 << 5 +}; -typedef struct unk80004384 { - /* 0x00 */ struct ALSoundState *next; - /* 0x04 */ struct ALSoundState *prev; - /* 0x08 */ struct ALSoundState *unk8; - /* 0x0C */ ALVoice voice; - /* 0x28 */ f32 unk28; - /* 0x2C */ f32 unk2C; - /* 0x30 */ s32 unk30; - /* 0x34 */ s16 unk34; - /* 0x36 */ u8 unk36; - /* 0x38 */ s32 unk38; - /* 0x3C */ u8 unk3C; - /* 0x3C */ u8 unk3D; - /* 0x3C */ u8 unk3E; - /* 0x3F */ u8 unk3F; -} unk80004384; // ALSoundState based? +enum SoundStates { + SOUND_STATE_NONE, + SOUND_STATE_PLAYING, + SOUND_STATE_STOPPING, + SOUND_STATE_PREEMPT, + SOUND_STATE_WAIT_VOICE, + SOUND_STATE_INIT +}; -typedef struct unk800DC6BC_40 { - ALLink node; - u8 pad0C[0x38]; -} unk800DC6BC_40; //ALSoundState +typedef struct ALSoundState { + /* 0x00 */ struct ALSoundState *next; + /* 0x04 */ struct ALSoundState *prev; + /* 0x08 */ ALSound *sound; + /* 0x0C */ ALVoice voice; + /* 0x28 */ f32 slideMult; + /* 0x2C */ f32 pitch; + /* 0x30 */ struct ALSoundState **userHandle; + /* 0x34 */ s16 volume; + /* 0x36 */ u8 priority; + /* 0x38 */ s32 retries; + /* 0x3C */ ALPan pan; + /* 0x3D */ u8 fxmix; + /* 0x3E */ u8 flags; + /* 0x3F */ u8 state; +} ALSoundState; -typedef struct ALLink_unk8000418C { - u8 pad0[5]; - s8 unk5; -} ALLink_unk8000418C; - -typedef struct ALEvent_unk8000418C { - s16 type; - ALVoiceState *unk4; - s32 unk8; - u8 pad[4]; // Not sure how big this is supposed to be. -} ALEvent_unk8000418C; +typedef struct ALSoundStateLists { + /* 0x00 */ ALSoundState *allocHead; + /* 0x04 */ ALSoundState *allocTail; + /* 0x08 */ ALSoundState *freeHead; + } ALSoundStateLists; /* Unknown Size */ -typedef struct unk800DC6BC { +typedef struct SoundPlayer { ALPlayer node; ALEventQueue evtq; ALEvent nextEvent; ALSynth *drvr; - u32 unk3C; - unk800DC6BC_40 *unk40; - s32 soundChannelsMax; - s32 soundChannels; + u32 lastSoundState; + ALSoundState *soundStatesArray; + s32 maxSystemSoundChannels; + s32 maxActiveSounds; s32 frameTime; ALMicroTime nextDelta; ALMicroTime curTime; -} unk800DC6BC; //ALSndPlayer - -typedef union { - ALEvent msg; - - struct{ - s16 type; - SoundMask *state; - u32 param; - }snd_event; - -} ALEvent2; +} SoundPlayer; typedef union { ALEvent msg; struct { - s16 type; + u16 type; ALSoundState *state; + s32 param; } common; - + struct { s16 type; ALSoundState *state; - s16 vol; - } vol; - - struct { - s16 type; - ALSoundState *state; - f32 pitch; - } pitch; - - struct { - s16 type; - ALSoundState *state; - ALPan pan; - } pan; - - struct { - s16 type; - ALSoundState *state; - u8 mix; - } fx; + s32 soundIndex; + ALBank *bank; + } retrigger; } ALSndpEvent; typedef struct audioMgrConfig_s{ - u32 unk00; - u32 unk04; - u32 maxChannels; - ALHeap *hp; - u16 unk10; // Heap Size? + /* 0x00 */ s32 maxSounds; // Number of ALSoundState structures + /* 0x04 */ s32 maxEvents; // Maximum number of events that can be held in the queue + /* 0x08 */ s32 maxChannels; + /* 0x0C */ ALHeap *heap; + /* 0x10 */ u16 numGroups; } audioMgrConfig; -typedef struct AudQueueCustom { - ALEventQueue alQ; - struct TempAud *next; - u8 unk0[0x26]; - u8 unk3E; -} AudQueueCustom; +extern void *alHeapDBAlloc(u8 *file, s32 line, ALHeap *hp, s32 num, s32 size); +extern void alEvtqNew(ALEventQueue *evtq, ALEventListItem *items, s32 itemCount); +extern ALMicroTime alEvtqNextEvent(ALEventQueue *evtq, ALEvent *evt); +extern void alSynAddPlayer(ALSynth *drvr, ALPlayer *client); +extern void alEvtqPostEvent(ALEventQueue *evtq, ALEvent *evt, ALMicroTime delta); -extern void *alHeapDBAlloc(u8 *file, s32 line, ALHeap *hp, s32 num, s32 size); //lib/src/al -extern void alEvtqNew(ALEventQueue *evtq, ALEventListItem *items, s32 itemCount); //lib/src/unknown_0C9C90.c -extern ALMicroTime alEvtqNextEvent(ALEventQueue *evtq, ALEvent *evt); //lib/src/unknown_0C9C90.c -extern void alSynAddPlayer(ALSynth *drvr, ALPlayer *client); //lib/src/unknown_0C9C90.c -extern void alEvtqPostEvent(ALEventQueue *evtq, ALEvent *evt, ALMicroTime delta); //lib/src/unknown_0C9C90.c Non Matching - -void set_sfx_volume_slider(u32 volume); -s32 get_sfx_volume_slider(void); -void set_sound_channel_count(s32 numChannels); -void alSndPNew(audioMgrConfig *c); -ALMicroTime _sndpVoiceHandler(void *node); -void func_8000410C(ALSoundState *state); -u16 func_800042CC(u16 *lastAllocListIndex, u16 *lastFreeListIndex); -void func_80004604(ALSoundState *sndp, u8 priority); -s32 func_80004638(ALBank *bnk, s16 sndIndx, SoundMask *soundMask); -void sound_stop_all(void); -void sound_event_update(s32 soundMask, s16 type, u32 volume); -u16 get_sound_channel_volume(u8 channel); -void set_sound_channel_volume(u8 channel, u16 volume); -void func_8000418C(ALVoiceState *voiceState); -void func_800048D8(u8 event); -INCONSISTENT void sound_stop(); -ALSound *func_80004384(UNUSED ALBank *arg0, ALSound *arg1); - -// Non Matching -void func_80004520(ALSoundState *); -s32 func_80004668(ALBank *bnk, s16 sndIndx, u8, SoundMask *soundMask); -void _handleEvent(unk800DC6BC *sndp, ALSndpEvent *event); +void sndp_set_global_volume(u32 volume); +s32 sndp_get_global_volume(void); +void sndp_set_active_sound_limit(s32 numChannels); +void sndp_init_player(audioMgrConfig *c); +ALMicroTime sndp_voice_handler(void *node); +void sndp_end(ALSoundState *state); +u16 sndp_get_state_counts(u16 *numFree, u16 *numAllocated); +void sndp_set_priority(ALSoundState *sndp, u8 priority); +ALSoundState *sndp_play(ALBank *bnk, s16 sndIndx, SoundHandle *soundMask); +void sndp_stop_all_looped(void); +void sndp_set_param(SoundHandle soundMask, s16 type, u32 volume); +u16 sndp_get_group_volume(u8 channel); +void sndp_set_group_volume(u8 channel, u16 volume); +void sndp_apply_pitch_slide(ALSoundState *voiceState); +void sndp_stop_with_flags(u8 event); +void sndp_stop(SoundHandle soundMask); +ALSoundState *sndp_allocate(UNUSED ALBank *arg0, ALSound *arg1); +void sndp_deallocate(ALSoundState *); +ALSoundState *sndp_play_with_priority(ALBank *bnk, s16 sndIndx, u8 priority, SoundHandle *soundMask); +void sndp_handle_event(SoundPlayer *sndp, ALSndpEvent *event); #endif diff --git a/src/game.c b/src/game.c index 80d4bc23..21e08ac2 100644 --- a/src/game.c +++ b/src/game.c @@ -385,11 +385,11 @@ void load_level(s32 levelId, s32 numberOfPlayers, s32 entranceId, Vehicle vehicl } if (numberOfPlayers == ONE_PLAYER) { - set_sound_channel_count(8); + sndp_set_active_sound_limit(8); } else if (numberOfPlayers == TWO_PLAYERS) { - set_sound_channel_count(12); + sndp_set_active_sound_limit(12); } else { - set_sound_channel_count(16); + sndp_set_active_sound_limit(16); } settings = get_settings(); gTempAssetTable = (s32 *) load_asset_section_from_rom(ASSET_LEVEL_HEADERS_TABLE); @@ -698,7 +698,7 @@ void clear_audio_and_track(void) { free_ai_behaviour_table(); bgdraw_primcolour(0, 0, 0); mempool_free(gCurrentLevelHeader); - sound_stop_all(); + sndp_stop_all_looped(); music_stop(); music_jingle_stop(); music_channel_reset_all(); diff --git a/src/game_ui.c b/src/game_ui.c index b0e85c62..f8df1840 100644 --- a/src/game_ui.c +++ b/src/game_ui.c @@ -224,9 +224,9 @@ u8 gHudSlide; u8 gHideRaceTimer; u8 gNumActivePlayers; u8 gWrongWayNagPrefix; -SoundMask *gRaceStartSoundMask; -s32 gHUDVoiceSoundMask; -SoundMask *gHudBalloonSoundMask; +SoundHandle gRaceStartSoundMask; +SoundHandle gHUDVoiceSoundMask; +SoundHandle gHudBalloonSoundMask; u16 D_80126D48; s32 D_80126D4C; s32 D_80126D50; @@ -321,14 +321,14 @@ void hud_init(UNUSED s32 viewportCount) { gMinimapXlu = 0; D_80127194 = (LevelHeader_70 *) get_misc_asset(ASSET_MISC_58); func_8007F1E8(D_80127194); - set_sound_channel_volume(0, 32767); - set_sound_channel_volume(2, 32767); + sndp_set_group_volume(0, 32767); + sndp_set_group_volume(2, 32767); for (i = 0; i < 2; i++) { gHudAudioData[i].volume = 0; gHudAudioData[i].volumeRamp = 0; gHudAudioData[i].playerIndex = PLAYER_COMPUTER; if (gHudAudioData[i].soundMask) { - sound_stop(gHudAudioData[i].soundMask); + sndp_stop(gHudAudioData[i].soundMask); } } } @@ -694,7 +694,7 @@ void hud_render_player(Gfx **dList, MatrixS **mtx, Vertex **vertexList, Object * music_stop(); music_channel_reset_all(); music_play(SEQUENCE_RACE_START_FANFARE); - set_sound_channel_count(12); + sndp_set_active_sound_limit(12); } else { start_level_music(1.0f); } @@ -816,7 +816,7 @@ void hud_audio_init(void) { s32 i; for (i = 0; i < 2; i++) { if (gHudAudioData[i].soundMask) { - sound_stop(gHudAudioData[i].soundMask); + sndp_stop(gHudAudioData[i].soundMask); gHudAudioData[i].soundMask = NULL; gHudAudioData[i].volume = 0; } @@ -844,7 +844,7 @@ void hud_audio_update(s32 updateRate) { for (i = 0; i < 2; i++) { if (gHudAudioData[i].volume) { if (gHudAudioData[i].soundMask == NULL) { - sound_play(gHudAudioData[i].soundID, (s32 *) &gHudAudioData[i].soundMask); + sound_play(gHudAudioData[i].soundID, &gHudAudioData[i].soundMask); } sound_volume_set_relative(gHudAudioData[i].soundID, gHudAudioData[i].soundMask, gHudAudioData[i].volume); if (gHudAudioData[i].volumeRamp > 0) { @@ -866,7 +866,7 @@ void hud_audio_update(s32 updateRate) { } } else { if (gHudAudioData[i].soundMask) { - sound_stop(gHudAudioData[i].soundMask); + sndp_stop(gHudAudioData[i].soundMask); gHudAudioData[i].soundMask = 0; } } @@ -874,11 +874,11 @@ void hud_audio_update(s32 updateRate) { if (gHudAudioReset && gHudAudioData[0].volume == 0) { gHudAudioReset = FALSE; if (gNumActivePlayers == 1) { - set_sound_channel_count(8); + sndp_set_active_sound_limit(8); } else if (gNumActivePlayers == 2) { - set_sound_channel_count(12); + sndp_set_active_sound_limit(12); } else { - set_sound_channel_count(16); + sndp_set_active_sound_limit(16); } } } @@ -2895,7 +2895,7 @@ void hud_balloons(UNUSED Object_Racer *racer) { balloonCount = *settings->balloonsPtr; if (cutscene_id() == 10) { if (get_balloon_cutscene_timer() < balloonTickTimer + 8 && gHudBalloonSoundMask == NULL) { - sound_play(SOUND_HUD_LAP_TICK, (s32 *) &gHudBalloonSoundMask); + sound_play(SOUND_HUD_LAP_TICK, &gHudBalloonSoundMask); } } } diff --git a/src/game_ui.h b/src/game_ui.h index a166b7ba..651a66c5 100644 --- a/src/game_ui.h +++ b/src/game_ui.h @@ -370,7 +370,7 @@ typedef struct HudAudio { u16 soundID; u8 volume; s8 volumeRamp; - SoundMask *soundMask; + SoundHandle soundMask; s32 unk8; s8 playerIndex; s8 unkD; diff --git a/src/menu.c b/src/menu.c index 56d205c3..804a8e99 100644 --- a/src/menu.c +++ b/src/menu.c @@ -372,7 +372,7 @@ s32 gMenuButtons[5]; // Buttons pressed per player plus an an extra containing e s8 *gCinematicParams; s32 buttonsPressed[5]; s8 *gCinematicPortraits; -SoundMask *gMenuSoundMasks[MAXCONTROLLERS]; // Soundmask values +SoundHandle gMenuSoundMasks[MAXCONTROLLERS]; // Soundmask values s16 gMenuStickX[5]; s32 gCinematicEnd; UNUSED s8 sUnused_80126828; // Set to 0 in menu_init, and never used again. @@ -380,9 +380,9 @@ UNUSED s32 D_8012682C; s16 gMenuStickY[5]; s16 D_8012683A; s32 gCinematicSkipA; -SoundMask *gTrackTTSoundMask; +SoundHandle gTrackTTSoundMask; s32 gCinematicSkipB; -SoundMask *D_80126848; +SoundHandle D_80126848; s32 gCinematicMusicChangeOff; s32 *D_80126850; // Never set, but it's read? Is it part of a larger struct being set? s32 gMenuElementScaleTimer; @@ -423,7 +423,7 @@ f32 gTrackSelectTargetY; char *gTrackMenuHubName; s32 gSelectedTrackX; s32 gSelectedTrackY; -SoundMask *gSoundOptionMask; +SoundHandle gSoundOptionMask; s32 gSaveMenuOptionCountLower; SaveFileData *gSaveMenuFilesDest; s32 gSaveMenuOptionCountUpper; @@ -3472,22 +3472,22 @@ s32 menu_title_screen_loop(s32 updateRate) { if (gTitleRevealTimer) { if (gTitleRevealTimer < 32) { if (gTitleRevealTimer == 1) { - sound_play(SOUND_WHOOSH1, 0); + sound_play(SOUND_WHOOSH1, NULL); } gTitleRevealTimer += updateRate; if (gTitleRevealTimer >= 32) { gTitleRevealTimer = 32; sp18->object.distanceToCamera = 8.0f; - sound_play(SOUND_EXPLOSION, 0); + sound_play(SOUND_EXPLOSION, NULL); } } else { if (gTitleAudioCounter < 6.0f) { gTitleAudioCounter += updateRateF; if (gTitleAudioCounter > 0.67f && gMenuStage == TITLESCREEN_START) { - sound_play(SOUND_VOICE_TT_DIDDY_KONG_RACING, 0); + sound_play(SOUND_VOICE_TT_DIDDY_KONG_RACING, NULL); gMenuStage = TITLESCREEN_NAME; } else if (gTitleAudioCounter > 2.83f && gMenuStage == TITLESCREEN_NAME) { - sound_play(SOUND_VOICE_TT_PRESS_START, 0); + sound_play(SOUND_VOICE_TT_PRESS_START, NULL); gMenuStage = TITLESCREEN_PRESS_START; } } @@ -3527,7 +3527,7 @@ s32 menu_title_screen_loop(s32 updateRate) { gMenuDelay = 1; transition_begin(&sMenuTransitionFadeIn); enable_new_screen_transitions(); - sound_play(SOUND_SELECT2, 0); + sound_play(SOUND_SELECT2, NULL); } } if (gMenuDelay > 30) { @@ -3803,7 +3803,7 @@ void menu_audio_options_init(void) { transition_begin(&sMenuTransitionFadeOut); func_8007FFEC(2); gMusicVolumeSliderValue = music_volume_config(); - gSfxVolumeSliderValue = get_sfx_volume_slider(); + gSfxVolumeSliderValue = sndp_get_global_volume(); if (gActiveMagicCodes & CHEAT_MUSIC_MENU) { // Check if "JUKEBOX" cheat is active gAudioMenuStrings[6].text = gMusicTestString; gAudioMenuStrings[3].y = 212; @@ -3986,7 +3986,7 @@ s32 menu_audio_options_loop(s32 updateRate) { } else if (gSfxVolumeSliderValue > 256) { gSfxVolumeSliderValue = 256; } - set_sfx_volume_slider(gSfxVolumeSliderValue); + sndp_set_global_volume(gSfxVolumeSliderValue); } else if (gOptionsMenuItemIndex == 2) { gMusicVolumeSliderValue += contXAxis; if (gMusicVolumeSliderValue < 0) { @@ -4026,10 +4026,10 @@ s32 menu_audio_options_loop(s32 updateRate) { } if (gOptionsMenuItemIndex == 1) { if (gSoundOptionMask == NULL) { - sound_play(SOUND_VOICE_DIDDY_POSITIVE5, (s32 *) &gSoundOptionMask); + sound_play(SOUND_VOICE_DIDDY_POSITIVE5, &gSoundOptionMask); } } else if (gSoundOptionMask != NULL) { - sound_stop(gSoundOptionMask); + sndp_stop(gSoundOptionMask); } if (playSound == 3) { sound_play(SOUND_MENU_BACK3, NULL); @@ -4054,7 +4054,7 @@ s32 menu_audio_options_loop(s32 updateRate) { */ void soundoptions_free(void) { if (gSoundOptionMask != NULL) { - sound_stop(gSoundOptionMask); + sndp_stop(gSoundOptionMask); } if (gOpacityDecayTimer >= 0) { music_voicelimit_set(24); @@ -6900,11 +6900,11 @@ void charselect_pick(void) { } } if (gMenuSoundMasks[characterSelected] != 0) { - sound_stop(gMenuSoundMasks[characterSelected]); + sndp_stop(gMenuSoundMasks[characterSelected]); } sound_play((*gCurrCharacterSelectData)[gPlayersCharacterArray[characterSelected]].voiceID + SOUND_VOICE_CHARACTER_SELECTED, - (s32 *) &gMenuSoundMasks[characterSelected]); + &gMenuSoundMasks[characterSelected]); if (gNumberOfActivePlayers > 2 || (gNumberOfActivePlayers > 1 && !(gActiveMagicCodes & CHEAT_TWO_PLAYER_ADVENTURE)) || gEnteredCharSelectFrom == 1) { @@ -6918,11 +6918,11 @@ void charselect_pick(void) { gCharselectStatus[i] = 0; gNumberOfReadyPlayers--; if (gMenuSoundMasks[i] != 0) { - sound_stop(gMenuSoundMasks[i]); + sndp_stop(gMenuSoundMasks[i]); } sound_play(((*gCurrCharacterSelectData)[gPlayersCharacterArray[i]].voiceID + SOUND_VOICE_CHARACTER_DESELECTED), - (s32 *) &gMenuSoundMasks[i]); + &gMenuSoundMasks[i]); } } } @@ -6947,11 +6947,11 @@ void charselect_input(s8 *activePlayers) { gCharselectStatus[i] = 0; gNumberOfReadyPlayers -= 1; if (gMenuSoundMasks[i] != 0) { - sound_stop(gMenuSoundMasks[i]); + sndp_stop(gMenuSoundMasks[i]); } sound_play(((*gCurrCharacterSelectData)[gPlayersCharacterArray[i]].voiceID + SOUND_VOICE_CHARACTER_DESELECTED), - (s32 *) &gMenuSoundMasks[i]); + &gMenuSoundMasks[i]); } } else { if (gMenuButtons[i] & B_BUTTON) { @@ -6982,11 +6982,11 @@ void charselect_input(s8 *activePlayers) { gCharselectStatus[i] = 1; gNumberOfReadyPlayers++; if (gMenuSoundMasks[i] != 0) { - sound_stop(gMenuSoundMasks[i]); + sndp_stop(gMenuSoundMasks[i]); } sound_play( ((*gCurrCharacterSelectData)[gPlayersCharacterArray[i]].voiceID + SOUND_VOICE_CHARACTER_SELECT), - (s32 *) &gMenuSoundMasks[i]); + &gMenuSoundMasks[i]); } else { charSelectData = (*gCurrCharacterSelectData) + gPlayersCharacterArray[i]; if (gMenuStickY[i] > 0) { @@ -9068,7 +9068,7 @@ void trackmenu_input(s32 updateRate) { */ void trackmenu_timetrial_sound(UNUSED s32 updateRate) { if (gMenuStage == TRACKMENU_CHOOSE && gTracksMenuTimeTrialHighlightIndex == 0 && gTrackTTSoundMask == NULL) { - sound_play(SOUND_VOICE_TT_SNORE, (s32 *) &gTrackTTSoundMask); + sound_play(SOUND_VOICE_TT_SNORE, &gTrackTTSoundMask); } } @@ -9603,7 +9603,7 @@ void func_80092188(s32 updateRate) { } if (gMenuStickY[0] > 0 && gTracksMenuTimeTrialHighlightIndex > 0) { if (D_80126848 != NULL) { - sound_stop((u8 *) D_80126848); + sndp_stop(D_80126848); } gTracksMenuTimeTrialHighlightIndex--; menuChanged = TRUE; @@ -9612,12 +9612,12 @@ void func_80092188(s32 updateRate) { if (gTracksMenuTimeTrialHighlightIndex <= 0) { menuChanged = TRUE; if (gTrackTTSoundMask != NULL) { - sound_stop((u8 *) gTrackTTSoundMask); + sndp_stop(gTrackTTSoundMask); } if (get_random_number_from_range(0, 255) >= 128) { - sound_play(SOUND_VOICE_TT_INTRO, (s32 *) &D_80126848); + sound_play(SOUND_VOICE_TT_INTRO, &D_80126848); } else { - sound_play(SOUND_VOICE_TT_GO_FOR_IT, (s32 *) &D_80126848); + sound_play(SOUND_VOICE_TT_GO_FOR_IT, &D_80126848); } gTracksMenuTimeTrialHighlightIndex++; } diff --git a/src/object_functions.c b/src/object_functions.c index cad18319..e6a727fe 100644 --- a/src/object_functions.c +++ b/src/object_functions.c @@ -96,8 +96,8 @@ VertexPosition D_800DCB28[6] = { /************ .bss ************/ f32 gNPCPosY; -s32 gTajSoundMask; -s32 gTTSoundMask; +SoundHandle gTajSoundMask; +SoundHandle gTTSoundMask; s32 gRocketSoundTimer; s8 gTajDialogueChoice; s16 gTajSoundID; // Taj Voice clips @@ -307,7 +307,7 @@ void obj_loop_fireball_octoweapon(Object *obj, s32 updateRate) { if (obj->properties.fireball.timer == 0) { soundMask = weapon->soundMask; if (soundMask != NULL) { - sound_stop(soundMask); + sndp_stop(soundMask); } play_sound_at_position(SOUND_POP, obj->segment.trans.x_position, obj->segment.trans.y_position, obj->segment.trans.z_position, 4, NULL); @@ -1419,7 +1419,7 @@ void obj_loop_stopwatchman(Object *obj, s32 updateRate) { */ void play_tt_voice_clip(u16 soundID, s32 interrupt) { if (gTTSoundMask && interrupt & 1) { - sound_stop(gTTSoundMask); // This is likely wrong and will need to be fixed + sndp_stop(gTTSoundMask); gTTSoundMask = NULL; } if (gTTSoundMask == NULL) { @@ -3144,7 +3144,7 @@ void obj_loop_parkwarden(Object *obj, s32 updateRate) { */ void play_taj_voice_clip(u16 soundID, s32 interrupt) { if (gTajSoundMask && interrupt & 1) { - sound_stop(gTajSoundMask); + sndp_stop(gTajSoundMask); gTajSoundMask = NULL; } if (!gTajSoundMask) { diff --git a/src/objects.c b/src/objects.c index 9ab31689..4590436a 100644 --- a/src/objects.c +++ b/src/objects.c @@ -4016,7 +4016,7 @@ void func_80016500(Object *obj, Object_Racer *racer) { } if (racer->unk1F6 == 0) { sound_play(SOUND_CRASH_CHARACTER, &racer->unk220); - sound_volume_set_relative(SOUND_CRASH_CHARACTER, (s32 *) racer->unk220, angle); + sound_volume_set_relative(SOUND_CRASH_CHARACTER, racer->unk220, angle); } if (racer->unk1F6 == 0 && angle >= 56) { if (!racer->raceFinished) { @@ -4479,7 +4479,7 @@ void race_transition_adventure(s32 updateRate) { sp30 = i; } if (racer->magnetSoundMask != NULL) { - sound_stop(racer->magnetSoundMask); + sndp_stop(racer->magnetSoundMask); } if (racer->shieldSoundMask != NULL) { func_800096F8(racer->shieldSoundMask); @@ -4491,7 +4491,7 @@ void race_transition_adventure(s32 updateRate) { racer_sound_free((*gRacers)[0]); hud_audio_init(); reset_rocket_sound_timer(); - sound_stop_all(); + sndp_stop_all_looped(); if (is_in_two_player_adventure()) { set_scene_viewport_num(0); set_active_viewports_and_max(0); @@ -5997,7 +5997,7 @@ void obj_init_animcamera(Object *arg0, Object *animObj) { anim->unk3C = animEntry->fadeAlpha; anim->unk42 = 0xFF; if (anim->unk18 != NULL) { - sound_stop(anim->unk18); + sndp_stop(anim->unk18); } anim->unk18 = NULL; anim->unk43 = animEntry->unk30; diff --git a/src/racer.c b/src/racer.c index 09896250..22b2ddd8 100644 --- a/src/racer.c +++ b/src/racer.c @@ -1203,7 +1203,7 @@ void func_80046524(s32 updateRate, f32 updateRateF, Object *obj, Object_Racer *r if (racer->trickType != 0) { if (racer->groundedWheels) { if (gRaceStartTimer != 100 && racer->playerIndex != PLAYER_COMPUTER && racer->trickType >= 6) { - sound_play(SOUND_BOUNCE, (s32 *) &racer->unk21C); + sound_play(SOUND_BOUNCE, &racer->unk21C); sound_volume_set_relative(SOUND_BOUNCE, racer->unk21C, (racer->trickType * 2) + 50); } } else if (racer->approachTarget == NULL) { @@ -2701,7 +2701,7 @@ void update_player_racer(Object *obj, s32 updateRate) { } if (tempRacer->magnetTimer == 0) { if (tempRacer->magnetSoundMask) { - sound_stop(tempRacer->magnetSoundMask); + sndp_stop(tempRacer->magnetSoundMask); tempRacer->magnetSoundMask = NULL; } } @@ -3056,7 +3056,7 @@ void func_8004F7F4(s32 updateRate, f32 updateRateF, Object *racerObj, Object_Rac update_car_velocity_offground(racerObj, racer, updateRate, updateRateF); } if (racer->unk1C != 0) { - sound_stop((u8 *) racer->unk1C); + sndp_stop((s32) racer->unk1C); // type cast required to match racer->unk1C = 0; } if (racer->buoyancy != 0.0f && racer->vehicleIDPrev != VEHICLE_BUBBLER) { @@ -3113,7 +3113,7 @@ void func_8004F7F4(s32 updateRate, f32 updateRateF, Object *racerObj, Object_Rac if (D_8011D550) { if (gCurrentPlayerIndex != PLAYER_COMPUTER && D_8011D550 != SOUND_STOMP5) { sound_play_spatial(D_8011D550, racerObj->segment.trans.x_position, racerObj->segment.trans.y_position, - racerObj->segment.trans.z_position, (s32 **) &racer->unk21C); + racerObj->segment.trans.z_position, &racer->unk21C); sound_volume_set_relative(D_8011D550, racer->unk21C, D_8011D552); } racer->stretch_height_cap = (1.0 - ((f32) (D_8011D552 - 40) * 0.004)); @@ -3517,25 +3517,25 @@ void func_80050A28(Object *obj, Object_Racer *racer, s32 updateRate, f32 updateR if (racer->drift_direction != 0 || racer->drifting != 0 || racer->unk1FB != 0) { if (racer->unk10 == 0) { sound_play_spatial(SOUND_CAR_SLIDE, obj->segment.trans.x_position, obj->segment.trans.y_position, - obj->segment.trans.z_position, (s32 **) &racer->unk10); + obj->segment.trans.z_position, &racer->unk10); } else { - audioline_reverb((void *) racer->unk10, obj->segment.trans.x_position, obj->segment.trans.y_position, + audioline_reverb((s32) racer->unk10, obj->segment.trans.x_position, obj->segment.trans.y_position, obj->segment.trans.z_position); } if (racer->unk14) { - sound_stop((void *) racer->unk14); + sndp_stop((s32) racer->unk14); // type cast required to match } } else { if (racer->unk10) { - sound_stop((void *) racer->unk10); + sndp_stop((s32) racer->unk10); // type cast required to match } } } else { if (racer->unk10) { - sound_stop((void *) racer->unk10); + sndp_stop((s32) racer->unk10); // type cast required to match } if (racer->unk14) { - sound_stop((void *) racer->unk14); + sndp_stop((s32) racer->unk14); // type cast required to match } } // Velocity of steering input @@ -3710,11 +3710,11 @@ void func_80050A28(Object *obj, Object_Racer *racer, s32 updateRate, f32 updateR } // Play a sound on grass and sand when landing on it surfaceType = gSurfaceSoundTable[surfaceType]; - if (racer->unk18 == NULL && surfaceType != SOUND_NONE && racer->velocity < -2.0) { + if (racer->unk18 == 0 && surfaceType != SOUND_NONE && racer->velocity < -2.0) { sound_play(surfaceType, &racer->unk18); } - if (racer->unk18 != NULL && (surfaceType == SOUND_NONE || racer->velocity > -2.0)) { - sound_stop((void *) racer->unk18); + if (racer->unk18 != 0 && (surfaceType == SOUND_NONE || racer->velocity > -2.0)) { + sndp_stop((s32) racer->unk18); // type cast required to match } // Apply a bobbing effect when on grass and sand. if (racer->velocity < -2.0 && sp68 >= 4) { @@ -4170,13 +4170,13 @@ void update_car_velocity_offground(Object *obj, Object_Racer *racer, s32 updateR racer->x_rotation_vel += (angle >> 3); //!@Delta } if (racer->unk18) { - sound_stop((void *) racer->unk18); + sndp_stop((s32) racer->unk18); // type cast required to match } if (racer->unk10) { - sound_stop((void *) racer->unk10); + sndp_stop((s32) racer->unk10); // type cast required to match } if (racer->unk14) { - sound_stop((void *) racer->unk14); + sndp_stop((s32) racer->unk14); // type cast required to match } if (racer->unk1FE == 1 || racer->unk1FE == 3) { racer->unk1E8 = racer->steerAngle; @@ -5475,10 +5475,10 @@ void handle_racer_items(Object *obj, Object_Racer *racer, UNUSED s32 updateRate) NULL); } else { if (racer->weaponSoundMask) { - sound_stop(racer->weaponSoundMask); + sndp_stop(racer->weaponSoundMask); } sound_play_spatial(soundID, obj->segment.trans.x_position, obj->segment.trans.y_position, - obj->segment.trans.z_position, (s32 **) &racer->weaponSoundMask); + obj->segment.trans.z_position, &racer->weaponSoundMask); } } } @@ -5612,7 +5612,7 @@ void racer_activate_magnet(Object *obj, Object_Racer *racer, s32 updateRate) { racer->boostType |= EMPOWER_BOOST; } if (racer->magnetSoundMask == NULL && racer->raceFinished == FALSE) { - sound_play(SOUND_MAGNET_HUM, (void *) &racer->magnetSoundMask); + sound_play(SOUND_MAGNET_HUM, &racer->magnetSoundMask); } } else { racer->magnetTimer = 0; @@ -7140,7 +7140,7 @@ void update_AI_racer(Object *obj, Object_Racer *racer, s32 updateRate, f32 updat } if (racer->magnetTimer == 0) { if (racer->magnetSoundMask != NULL) { - sound_stop(racer->magnetSoundMask); + sndp_stop(racer->magnetSoundMask); racer->magnetSoundMask = NULL; } } diff --git a/src/thread3_main.c b/src/thread3_main.c index 63cd486d..ab98c8a4 100644 --- a/src/thread3_main.c +++ b/src/thread3_main.c @@ -828,9 +828,9 @@ void load_menu_with_level_background(s32 menuId, s32 levelId, s32 cutsceneId) { alloc_displaylist_heap(PLAYER_ONE); gGameMode = GAMEMODE_MENU; gRenderMenu = TRUE; - set_sound_channel_volume(0, 32767); - set_sound_channel_volume(1, 32767); - set_sound_channel_volume(2, 32767); + sndp_set_group_volume(0, 32767); + sndp_set_group_volume(1, 32767); + sndp_set_group_volume(2, 32767); camera_init(); if (!gIsLoading) { diff --git a/src/vehicle_bubbler.c b/src/vehicle_bubbler.c index 00bd4c42..7c2b0216 100644 --- a/src/vehicle_bubbler.c +++ b/src/vehicle_bubbler.c @@ -100,7 +100,7 @@ void update_bubbler(s32 updateRate, f32 updateRateF, Object *obj, Object_Racer * obj->segment.object.animationID = ANIM_BUBBLER_DAMAGE; obj->segment.y_velocity += 7.5; play_random_boss_sound(BOSS_SOUND_NEGATIVE); - sound_play(SOUND_EXPLOSION, 0); + sound_play(SOUND_EXPLOSION, NULL); set_camera_shake(12.0f); racer->velocity *= 0.3; racer->animationSpeed = 0.0f; diff --git a/src/vehicle_smokey.c b/src/vehicle_smokey.c index 27fa6c18..1734d86b 100644 --- a/src/vehicle_smokey.c +++ b/src/vehicle_smokey.c @@ -106,7 +106,7 @@ void update_smokey(s32 updateRate, f32 updateRateF, Object *obj, Object_Racer *r obj->segment.animFrame = animFrame; if (racer->attackType != ATTACK_NONE && obj->segment.object.animationID != ANIM_SMOKEY_DAMAGE) { play_random_boss_sound(BOSS_SOUND_NEGATIVE); - sound_play(SOUND_EXPLOSION, 0); + sound_play(SOUND_EXPLOSION, NULL); set_camera_shake(12.0f); obj->segment.object.animationID = ANIM_SMOKEY_DAMAGE; obj->segment.x_velocity *= 0.27; diff --git a/ver/symbols/symbol_addrs.jpn.v79.txt b/ver/symbols/symbol_addrs.jpn.v79.txt index 3ee14017..3c9582db 100644 --- a/ver/symbols/symbol_addrs.jpn.v79.txt +++ b/ver/symbols/symbol_addrs.jpn.v79.txt @@ -93,30 +93,30 @@ __amDmaNew = 0x80003008; __clearAudioDMA = 0x80003040; //audiosfx.c .text -set_sfx_volume_slider = 0x80003160; -get_sfx_volume_slider = 0x8000317C; -set_sound_channel_count = 0x8000318C; -alSndPNew = 0x800031C0; -_sndpVoiceHandler = 0x800033C8; -_handleEvent = 0x80003470; -func_8000410C = 0x8000410C; -func_8000418C = 0x8000418C; -_removeEvents = 0x800041FC; -func_800042CC = 0x800042CC; -func_80004384 = 0x80004384; -func_80004520 = 0x80004520; -func_80004604 = 0x80004604; -func_8000461C = 0x8000461C; -func_80004638 = 0x80004638; -func_80004668 = 0x80004668; -sound_stop = 0x8000488C; -func_800048D8 = 0x800048D8; -func_80004998 = 0x80004998; -func_800049B8 = 0x800049B8; -sound_stop_all = 0x800049D8; -sound_event_update = 0x800049F8; -get_sound_channel_volume = 0x80004A3C; -set_sound_channel_volume = 0x80004A60; +sndp_set_global_volume = 0x80003160; +sndp_get_global_volume = 0x8000317C; +sndp_set_active_sound_limit = 0x8000318C; +sndp_init_player = 0x800031C0; +sndp_voice_handler = 0x800033C8; +sndp_handle_event = 0x80003470; +sndp_end = 0x8000410C; +sndp_apply_pitch_slide = 0x8000418C; +sndp_remove_events = 0x800041FC; +sndp_get_state_counts = 0x800042CC; +sndp_allocate = 0x80004384; +sndp_deallocate = 0x80004520; +sndp_set_priority = 0x80004604; +sndp_get_state = 0x8000461C; +sndp_play = 0x80004638; +sndp_play_with_priority = 0x80004668; +sndp_stop = 0x8000488C; +sndp_stop_with_flags = 0x800048D8; +sndp_stop_all = 0x80004998; +sndp_stop_all_retrigger = 0x800049B8; +sndp_stop_all_looped = 0x800049D8; +sndp_set_param = 0x800049F8; +sndp_get_group_volume = 0x80004A3C; +sndp_set_group_volume = 0x80004A60; // audio_vehicle.c .text func_80004B40 = 0x80004B40; @@ -2186,10 +2186,10 @@ gFunc80019808Checksum = 0x800DE020; gFunc80019808Length = 0x800DE024; // audiosfx.c .data -D_800DC6B0 = 0x800DE040; // size:0xC -gAlSndPlayerPtr = 0x800DE04C; -sfxVolumeSlider = 0x800DE050; -D_800DC6C4 = 0x800DE054; +gSoundStateLists = 0x800DE040; // size:0xC +gSoundPlayerPtr = 0x800DE04C; +gSoundGlobalVolume = 0x800DE050; +gNumActiveSounds = 0x800DE054; // audio_vehicle.c .data gVehicleSounds = 0x800DE060; @@ -3547,8 +3547,8 @@ audDMAMessageQ = 0x8011B560; audDMAMessageBuf = 0x8011B578; // audiosfx .bss -gAlSndPlayer = 0x8011B640; -gSoundChannelVolume = 0x8011B698; +gSoundPlayer = 0x8011B640; +gSoundGroupVolume = 0x8011B698; // audio_vehicle .bss D_80119C30 = 0x8011B6A0; diff --git a/ver/symbols/symbol_addrs.pal.v77.txt b/ver/symbols/symbol_addrs.pal.v77.txt index 9bfba410..2de0dce3 100644 --- a/ver/symbols/symbol_addrs.pal.v77.txt +++ b/ver/symbols/symbol_addrs.pal.v77.txt @@ -93,30 +93,30 @@ __amDmaNew = 0x80003008; __clearAudioDMA = 0x80003040; //audiosfx.c .text -set_sfx_volume_slider = 0x80003160; -get_sfx_volume_slider = 0x8000317C; -set_sound_channel_count = 0x8000318C; -alSndPNew = 0x800031C0; -_sndpVoiceHandler = 0x800033C8; -_handleEvent = 0x80003470; -func_8000410C = 0x8000410C; -func_8000418C = 0x8000418C; -_removeEvents = 0x800041FC; -func_800042CC = 0x800042CC; -func_80004384 = 0x80004384; -func_80004520 = 0x80004520; -func_80004604 = 0x80004604; -func_8000461C = 0x8000461C; -func_80004638 = 0x80004638; -func_80004668 = 0x80004668; -sound_stop = 0x8000488C; -func_800048D8 = 0x800048D8; -func_80004998 = 0x80004998; -func_800049B8 = 0x800049B8; -sound_stop_all = 0x800049D8; -sound_event_update = 0x800049F8; -get_sound_channel_volume = 0x80004A3C; -set_sound_channel_volume = 0x80004A60; +sndp_set_global_volume = 0x80003160; +sndp_get_global_volume = 0x8000317C; +sndp_set_active_sound_limit = 0x8000318C; +sndp_init_player = 0x800031C0; +sndp_voice_handler = 0x800033C8; +sndp_handle_event = 0x80003470; +sndp_end = 0x8000410C; +sndp_apply_pitch_slide = 0x8000418C; +sndp_remove_events = 0x800041FC; +sndp_get_state_counts = 0x800042CC; +sndp_allocate = 0x80004384; +sndp_deallocate = 0x80004520; +sndp_set_priority = 0x80004604; +sndp_get_state = 0x8000461C; +sndp_play = 0x80004638; +sndp_play_with_priority = 0x80004668; +sndp_stop = 0x8000488C; +sndp_stop_with_flags = 0x800048D8; +sndp_stop_all = 0x80004998; +sndp_stop_all_retrigger = 0x800049B8; +sndp_stop_all_looped = 0x800049D8; +sndp_set_param = 0x800049F8; +sndp_get_group_volume = 0x80004A3C; +sndp_set_group_volume = 0x80004A60; // audio_vehicle.c .text func_80004B40 = 0x80004B40; @@ -2092,10 +2092,10 @@ curAcmdList = 0x800DC718; gAntiPiracyAudioFreq = 0x800DC71C; gFunc80019808Checksum = 0x800DC720; gFunc80019808Length = 0x800DC724; -D_800DC6B0 = 0x800DC740; // size:0xC -gAlSndPlayerPtr = 0x800DC74C; -sfxVolumeSlider = 0x800DC750; -D_800DC6C4 = 0x800DC754; +gSoundStateLists = 0x800DC740; // size:0xC +gSoundPlayerPtr = 0x800DC74C; +gSoundGlobalVolume = 0x800DC750; +gNumActiveSounds = 0x800DC754; gVehicleSounds = 0x800DC760; D_800DC6D4 = 0x800DC764; D_800DC6D8 = 0x800DC768; @@ -3298,8 +3298,8 @@ gAntiPiracyCRCStart = 0x801196C8; audDMAIOMesgBuf = 0x801196D0; audDMAMessageQ = 0x80119B80; audDMAMessageBuf = 0x80119B98; -gAlSndPlayer = 0x80119C60; -gSoundChannelVolume = 0x80119CB8; +gSoundPlayer = 0x80119C60; +gSoundGroupVolume = 0x80119CB8; D_80119C30 = 0x80119CC0; gRacerSound = 0x80119CC8; gSoundRacerObj = 0x80119CCC; diff --git a/ver/symbols/symbol_addrs.pal.v80.txt b/ver/symbols/symbol_addrs.pal.v80.txt index 1cb07061..d3ee8273 100644 --- a/ver/symbols/symbol_addrs.pal.v80.txt +++ b/ver/symbols/symbol_addrs.pal.v80.txt @@ -93,30 +93,30 @@ __amDmaNew = 0x80003008; __clearAudioDMA = 0x80003040; //audiosfx.c .text -set_sfx_volume_slider = 0x80003160; -get_sfx_volume_slider = 0x8000317C; -set_sound_channel_count = 0x8000318C; -alSndPNew = 0x800031C0; -_sndpVoiceHandler = 0x800033C8; -_handleEvent = 0x80003470; -func_8000410C = 0x8000410C; -func_8000418C = 0x8000418C; -_removeEvents = 0x800041FC; -func_800042CC = 0x800042CC; -func_80004384 = 0x80004384; -func_80004520 = 0x80004520; -func_80004604 = 0x80004604; -func_8000461C = 0x8000461C; -func_80004638 = 0x80004638; -func_80004668 = 0x80004668; -sound_stop = 0x8000488C; -func_800048D8 = 0x800048D8; -func_80004998 = 0x80004998; -func_800049B8 = 0x800049B8; -sound_stop_all = 0x800049D8; -sound_event_update = 0x800049F8; -get_sound_channel_volume = 0x80004A3C; -set_sound_channel_volume = 0x80004A60; +sndp_set_global_volume = 0x80003160; +sndp_get_global_volume = 0x8000317C; +sndp_set_active_sound_limit = 0x8000318C; +sndp_init_player = 0x800031C0; +sndp_voice_handler = 0x800033C8; +sndp_handle_event = 0x80003470; +sndp_end = 0x8000410C; +sndp_apply_pitch_slide = 0x8000418C; +sndp_remove_events = 0x800041FC; +sndp_get_state_counts = 0x800042CC; +sndp_allocate = 0x80004384; +sndp_deallocate = 0x80004520; +sndp_set_priority = 0x80004604; +sndp_get_state = 0x8000461C; +sndp_play = 0x80004638; +sndp_play_with_priority = 0x80004668; +sndp_stop = 0x8000488C; +sndp_stop_with_flags = 0x800048D8; +sndp_stop_all = 0x80004998; +sndp_stop_all_retrigger = 0x800049B8; +sndp_stop_all_looped = 0x800049D8; +sndp_set_param = 0x800049F8; +sndp_get_group_volume = 0x80004A3C; +sndp_set_group_volume = 0x80004A60; // audio_vehicle.c .text func_80004B40 = 0x80004B40; @@ -2019,10 +2019,10 @@ curAcmdList = 0x800DCC88; gAntiPiracyAudioFreq = 0x800DCC8C; gFunc80019808Checksum = 0x800DCC90; gFunc80019808Length = 0x800DCC94; -D_800DC6B0 = 0x800DCCB0; // size:0xC -gAlSndPlayerPtr = 0x800DCCBC; -sfxVolumeSlider = 0x800DCCC0; -D_800DC6C4 = 0x800DCCC4; +gSoundStateLists = 0x800DCCB0; // size:0xC +gSoundPlayerPtr = 0x800DCCBC; +gSoundGlobalVolume = 0x800DCCC0; +gNumActiveSounds = 0x800DCCC4; gVehicleSounds = 0x800DCCD0; D_800DC6D4 = 0x800DCCD4; D_800DC6D8 = 0x800DCCD8; @@ -3228,8 +3228,8 @@ gAntiPiracyCRCStart = 0x80119C48; audDMAIOMesgBuf = 0x80119C50; audDMAMessageQ = 0x8011A100; audDMAMessageBuf = 0x8011A118; -gAlSndPlayer = 0x8011A1E0; -gSoundChannelVolume = 0x8011A238; +gSoundPlayer = 0x8011A1E0; +gSoundGroupVolume = 0x8011A238; D_80119C30 = 0x8011A240; gRacerSound = 0x8011A248; gSoundRacerObj = 0x8011A24C; diff --git a/ver/symbols/symbol_addrs.us.v77.txt b/ver/symbols/symbol_addrs.us.v77.txt index e5bd80b4..e86b3a28 100644 --- a/ver/symbols/symbol_addrs.us.v77.txt +++ b/ver/symbols/symbol_addrs.us.v77.txt @@ -93,30 +93,30 @@ __amDmaNew = 0x80003008; __clearAudioDMA = 0x80003040; //audiosfx.c .text -set_sfx_volume_slider = 0x80003160; -get_sfx_volume_slider = 0x8000317C; -set_sound_channel_count = 0x8000318C; -alSndPNew = 0x800031C0; -_sndpVoiceHandler = 0x800033C8; -_handleEvent = 0x80003470; -func_8000410C = 0x8000410C; -func_8000418C = 0x8000418C; -_removeEvents = 0x800041FC; -func_800042CC = 0x800042CC; -func_80004384 = 0x80004384; -func_80004520 = 0x80004520; -func_80004604 = 0x80004604; -func_8000461C = 0x8000461C; -func_80004638 = 0x80004638; -func_80004668 = 0x80004668; -sound_stop = 0x8000488C; -func_800048D8 = 0x800048D8; -func_80004998 = 0x80004998; -func_800049B8 = 0x800049B8; -sound_stop_all = 0x800049D8; -sound_event_update = 0x800049F8; -get_sound_channel_volume = 0x80004A3C; -set_sound_channel_volume = 0x80004A60; +sndp_set_global_volume = 0x80003160; +sndp_get_global_volume = 0x8000317C; +sndp_set_active_sound_limit = 0x8000318C; +sndp_init_player = 0x800031C0; +sndp_voice_handler = 0x800033C8; +sndp_handle_event = 0x80003470; +sndp_end = 0x8000410C; +sndp_apply_pitch_slide = 0x8000418C; +sndp_remove_events = 0x800041FC; +sndp_get_state_counts = 0x800042CC; +sndp_allocate = 0x80004384; +sndp_deallocate = 0x80004520; +sndp_set_priority = 0x80004604; +sndp_get_state = 0x8000461C; +sndp_play = 0x80004638; +sndp_play_with_priority = 0x80004668; +sndp_stop = 0x8000488C; +sndp_stop_with_flags = 0x800048D8; +sndp_stop_all = 0x80004998; +sndp_stop_all_retrigger = 0x800049B8; +sndp_stop_all_looped = 0x800049D8; +sndp_set_param = 0x800049F8; +sndp_get_group_volume = 0x80004A3C; +sndp_set_group_volume = 0x80004A60; // audio_vehicle.c .text func_80004B40 = 0x80004B40; @@ -2181,10 +2181,10 @@ gFunc80019808Checksum = 0x800DC690; gFunc80019808Length = 0x800DC694; // audiosfx.c .data -D_800DC6B0 = 0x800DC6B0; // size:0xC -gAlSndPlayerPtr = 0x800DC6BC; -sfxVolumeSlider = 0x800DC6C0; -D_800DC6C4 = 0x800DC6C4; +gSoundStateLists = 0x800DC6B0; // size:0xC +gSoundPlayerPtr = 0x800DC6BC; +gSoundGlobalVolume = 0x800DC6C0; +gNumActiveSounds = 0x800DC6C4; // audio_vehicle.c .data gVehicleSounds = 0x800DC6D0; @@ -3669,8 +3669,8 @@ audDMAMessageQ = 0x80119AF0; audDMAMessageBuf = 0x80119B08; // audiosfx .bss -gAlSndPlayer = 0x80119BD0; -gSoundChannelVolume = 0x80119C28; +gSoundPlayer = 0x80119BD0; +gSoundGroupVolume = 0x80119C28; // audio_vehicle .bss D_80119C30 = 0x80119C30; diff --git a/ver/symbols/symbol_addrs.us.v80.txt b/ver/symbols/symbol_addrs.us.v80.txt index 0f2d00bf..62426e8b 100644 --- a/ver/symbols/symbol_addrs.us.v80.txt +++ b/ver/symbols/symbol_addrs.us.v80.txt @@ -93,30 +93,30 @@ __amDmaNew = 0x80003008; __clearAudioDMA = 0x80003040; //audiosfx.c .text -set_sfx_volume_slider = 0x80003160; -get_sfx_volume_slider = 0x8000317C; -set_sound_channel_count = 0x8000318C; -alSndPNew = 0x800031C0; -_sndpVoiceHandler = 0x800033C8; -_handleEvent = 0x80003470; -func_8000410C = 0x8000410C; -func_8000418C = 0x8000418C; -_removeEvents = 0x800041FC; -func_800042CC = 0x800042CC; -func_80004384 = 0x80004384; -func_80004520 = 0x80004520; -func_80004604 = 0x80004604; -func_8000461C = 0x8000461C; -func_80004638 = 0x80004638; -func_80004668 = 0x80004668; -sound_stop = 0x8000488C; -func_800048D8 = 0x800048D8; -func_80004998 = 0x80004998; -func_800049B8 = 0x800049B8; -sound_stop_all = 0x800049D8; -sound_event_update = 0x800049F8; -get_sound_channel_volume = 0x80004A3C; -set_sound_channel_volume = 0x80004A60; +sndp_set_global_volume = 0x80003160; +sndp_get_global_volume = 0x8000317C; +sndp_set_active_sound_limit = 0x8000318C; +sndp_init_player = 0x800031C0; +sndp_voice_handler = 0x800033C8; +sndp_handle_event = 0x80003470; +sndp_end = 0x8000410C; +sndp_apply_pitch_slide = 0x8000418C; +sndp_remove_events = 0x800041FC; +sndp_get_state_counts = 0x800042CC; +sndp_allocate = 0x80004384; +sndp_deallocate = 0x80004520; +sndp_set_priority = 0x80004604; +sndp_get_state = 0x8000461C; +sndp_play = 0x80004638; +sndp_play_with_priority = 0x80004668; +sndp_stop = 0x8000488C; +sndp_stop_with_flags = 0x800048D8; +sndp_stop_all = 0x80004998; +sndp_stop_all_retrigger = 0x800049B8; +sndp_stop_all_looped = 0x800049D8; +sndp_set_param = 0x800049F8; +sndp_get_group_volume = 0x80004A3C; +sndp_set_group_volume = 0x80004A60; // audio_vehicle.c .text func_80004B40 = 0x80004B40; @@ -2016,10 +2016,10 @@ curAcmdList = 0x800DCBF8; gAntiPiracyAudioFreq = 0x800DCBFC; gFunc80019808Checksum = 0x800DCC00; gFunc80019808Length = 0x800DCC04; -D_800DC6B0 = 0x800DCC20; // size:0xC -gAlSndPlayerPtr = 0x800DCC2C; -sfxVolumeSlider = 0x800DCC30; -D_800DC6C4 = 0x800DCC34; +gSoundStateLists = 0x800DCC20; // size:0xC +gSoundPlayerPtr = 0x800DCC2C; +gSoundGlobalVolume = 0x800DCC30; +gNumActiveSounds = 0x800DCC34; gVehicleSounds = 0x800DCC40; D_800DC6D4 = 0x800DCC44; D_800DC6D8 = 0x800DCC48; @@ -3224,8 +3224,8 @@ gAntiPiracyCRCStart = 0x80119BB8; audDMAIOMesgBuf = 0x80119BC0; audDMAMessageQ = 0x8011A070; audDMAMessageBuf = 0x8011A088; -gAlSndPlayer = 0x8011A150; -gSoundChannelVolume = 0x8011A1A8; +gSoundPlayer = 0x8011A150; +gSoundGroupVolume = 0x8011A1A8; D_80119C30 = 0x8011A1B0; gRacerSound = 0x8011A1B8; gSoundRacerObj = 0x8011A1BC;