mirror of
https://github.com/zeldaret/mm.git
synced 2026-07-09 05:43:18 -04:00
Audio Sfx (code_801A5BD0 and selected sfx functions in code_8019AF00.c) OK and Documented (#798)
* Rename functions * code_801A5BD0 OK * PR 1, improve spacing * Rename unused struct * Rename Sfx Variables * PR Feedback, update names * Add comment * cleanup vars * Fix merge * Rework documentation, include more functions in sfx system * PR suggestions * fix AudioSfx_MuteBanks * missed enum * more cleanup * more suggestions
This commit is contained in:
@@ -1208,7 +1208,7 @@ void AudioLoad_Init(void* heap, size_t heapSize) {
|
||||
gAudioContext.refreshRate = 60;
|
||||
}
|
||||
|
||||
Audio_InitMesgQueues();
|
||||
AudioThread_InitMesgQueues();
|
||||
|
||||
for (i = 0; i < ARRAY_COUNT(gAudioContext.aiBufLengths); i++) {
|
||||
gAudioContext.aiBufLengths[i] = 0xA0;
|
||||
@@ -1217,7 +1217,7 @@ void AudioLoad_Init(void* heap, size_t heapSize) {
|
||||
gAudioContext.totalTaskCount = 0;
|
||||
gAudioContext.rspTaskIndex = 0;
|
||||
gAudioContext.curAiBuffferIndex = 0;
|
||||
gAudioContext.soundMode = AUDIO_MODE_STEREO;
|
||||
gAudioContext.soundMode = SOUNDMODE_STEREO;
|
||||
gAudioContext.curTask = NULL;
|
||||
gAudioContext.rspTask[0].task.t.dataSize = 0;
|
||||
gAudioContext.rspTask[1].task.t.dataSize = 0;
|
||||
|
||||
@@ -34,7 +34,7 @@ void AudioPlayback_InitNoteSub(Note* note, NoteSubEu* sub, NoteSubAttributes* at
|
||||
sub->bitField0.stereoStrongLeft = false;
|
||||
sub->bitField0.stereoHeadsetEffects = stereoData.stereoHeadsetEffects;
|
||||
sub->bitField0.usesHeadsetPanEffects = stereoData.usesHeadsetPanEffects;
|
||||
if (stereoHeadsetEffects && gAudioContext.soundMode == AUDIO_MODE_HEADSET) {
|
||||
if (stereoHeadsetEffects && gAudioContext.soundMode == SOUNDMODE_HEADSET) {
|
||||
smallPanIndex = pan >> 1;
|
||||
if (smallPanIndex > 0x3F) {
|
||||
smallPanIndex = 0x3F;
|
||||
@@ -46,7 +46,7 @@ void AudioPlayback_InitNoteSub(Note* note, NoteSubEu* sub, NoteSubAttributes* at
|
||||
|
||||
volLeft = gHeadsetPanVolume[pan];
|
||||
volRight = gHeadsetPanVolume[0x7F - pan];
|
||||
} else if (stereoHeadsetEffects && gAudioContext.soundMode == AUDIO_MODE_STEREO) {
|
||||
} else if (stereoHeadsetEffects && gAudioContext.soundMode == SOUNDMODE_STEREO) {
|
||||
strongLeft = strongRight = false;
|
||||
sub->headsetPanRight = 0;
|
||||
sub->headsetPanLeft = 0;
|
||||
@@ -80,7 +80,7 @@ void AudioPlayback_InitNoteSub(Note* note, NoteSubEu* sub, NoteSubAttributes* at
|
||||
break;
|
||||
}
|
||||
|
||||
} else if (gAudioContext.soundMode == AUDIO_MODE_MONO) {
|
||||
} else if (gAudioContext.soundMode == SOUNDMODE_MONO) {
|
||||
sub->bitField0.stereoHeadsetEffects = false;
|
||||
sub->bitField0.usesHeadsetPanEffects = false;
|
||||
volLeft = 0.707f; // approx 1/sqrt(2)
|
||||
|
||||
@@ -1633,7 +1633,7 @@ void AudioSeq_SequenceChannelProcessScript(SequenceChannel* channel) {
|
||||
break;
|
||||
|
||||
case 0xA8: // channel: random range large (only cmd that differs from OoT)
|
||||
rand = Audio_NextRandom();
|
||||
rand = AudioThread_NextRandom();
|
||||
channel->unk_22 = (cmdArgs[0] == 0) ? (rand & 0xFFFF) : (rand % cmdArgs[0]);
|
||||
channel->unk_22 += cmdArgs[1];
|
||||
temp2 = (channel->unk_22 / 0x100) + 0x80;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#include "global.h"
|
||||
|
||||
#define DEFINE_SFX(_0, importance, distParam, randParam, flags2, flags1) \
|
||||
{ importance, flags2, \
|
||||
((((distParam) << SFX_PARAM_01_SHIFT) & SFX_PARAM_01_MASK) | \
|
||||
(((randParam) << SFX_PARAM_67_SHIFT) & SFX_PARAM_67_MASK) | (flags1)) },
|
||||
#define DEFINE_SFX(_0, importance, distParam, randParam, flags2, flags1) \
|
||||
{ importance, flags2, \
|
||||
((((distParam) << SFX_PARAM_DIST_RANGE_SHIFT) & SFX_PARAM_DIST_RANGE_MASK) | \
|
||||
(((randParam) << SFX_PARAM_RAND_FREQ_RAISE_SHIFT) & SFX_PARAM_RAND_FREQ_RAISE_MASK) | (flags1)) },
|
||||
|
||||
SfxParams sEnemyBankParams[] = {
|
||||
#include "tables/sfx/enemybank_table.h"
|
||||
|
||||
@@ -16,13 +16,13 @@
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_80192BE0/func_80193858.s")
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_80192BE0/func_8019387C.s")
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_80192BE0/AudioThread_QueueCmdS32.s")
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_80192BE0/Audio_QueueCmdS8.s")
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_80192BE0/AudioThread_QueueCmdS8.s")
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_80192BE0/func_801938D0.s")
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_80192BE0/func_80193900.s")
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_80192BE0/AudioThread_ScheduleProcessCmds.s")
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_80192BE0/func_80193990.s")
|
||||
|
||||
@@ -76,6 +76,6 @@
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_80192BE0/func_80194568.s")
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_80192BE0/Audio_NextRandom.s")
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_80192BE0/AudioThread_NextRandom.s")
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_80192BE0/Audio_InitMesgQueues.s")
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_80192BE0/AudioThread_InitMesgQueues.s")
|
||||
|
||||
+603
-72
@@ -18,15 +18,15 @@ typedef struct {
|
||||
} SfxSettings; // size = 0x9
|
||||
|
||||
typedef struct {
|
||||
/* 0x0 */ f32 vol;
|
||||
/* 0x0 */ f32 volume;
|
||||
/* 0x4 */ f32 freqScale;
|
||||
/* 0x8 */ s8 reverb;
|
||||
/* 0x9 */ s8 panSigned;
|
||||
/* 0xA */ s8 stereoBits;
|
||||
/* 0xB */ u8 filter;
|
||||
/* 0xC */ u8 unk_0C;
|
||||
/* 0xD */ u8 unk_0D;
|
||||
} SfxPlayerState; // size = 0xE
|
||||
/* 0xC */ u8 combFilterGain;
|
||||
/* 0xD */ u8 zVolume;
|
||||
} SfxChannelState; // size = 0xE
|
||||
|
||||
typedef enum {
|
||||
/* 0x0 */ SFX_CHANNEL_PLAYER0, // SfxPlayerBank
|
||||
@@ -91,7 +91,7 @@ f32* sSfxVolumeCur;
|
||||
f32 sSfxVolumeTarget;
|
||||
f32 sSfxVolumeRate;
|
||||
u16 sSceneSeqId1;
|
||||
SfxPlayerState sSfxChannelState[16];
|
||||
SfxChannelState sSfxChannelState[16];
|
||||
|
||||
// Sequence bss
|
||||
u8 D_801FD3A8;
|
||||
@@ -154,7 +154,8 @@ OcarinaNote sScarecrowsLongSongSecondNote;
|
||||
u16 sCustomSequencePc;
|
||||
|
||||
// Sfx Data
|
||||
u8 D_801D6600[] = {
|
||||
// If the Sfx Bank has more than 255 values (max value of u8)
|
||||
u8 gIsLargeSfxBank[] = {
|
||||
true, false, true, true, false, false, true,
|
||||
};
|
||||
u8 D_801D6608[] = {
|
||||
@@ -192,7 +193,7 @@ u8 sEnterGanonsTowerTimer = 0;
|
||||
u16 sSfxVolumeDuration = 0;
|
||||
|
||||
// System Data
|
||||
s8 sAudioFileSelectSetting = AUDIO_FS_STEREO;
|
||||
s8 sSoundMode = SOUNDMODE_STEREO;
|
||||
s8 sAudioIsWindowOpen = false;
|
||||
s8 sAudioCutsceneFlag = false;
|
||||
s8 sSpecReverb = 0;
|
||||
@@ -2495,7 +2496,7 @@ void AudioOcarina_PlayControllerInput(u8 isOcarinaSfxSuppressedWhenCancelled) {
|
||||
// Add vibrato of the ocarina note based on the x control stick
|
||||
sCurOcarinaVibrato = ABS_ALT(sOcarinaInputStickRel.x) >> 2;
|
||||
// Sets vibrato to io port 6
|
||||
Audio_QueueCmdS8(0x6 << 24 | SEQ_PLAYER_SFX << 16 | SFX_CHANNEL_OCARINA << 8 | 6, sCurOcarinaVibrato);
|
||||
AudioThread_QueueCmdS8(0x6 << 24 | SEQ_PLAYER_SFX << 16 | SFX_CHANNEL_OCARINA << 8 | 6, sCurOcarinaVibrato);
|
||||
} else {
|
||||
// no bending or vibrato for recording state OCARINA_RECORD_SCARECROW_SPAWN
|
||||
sCurOcarinaBendIndex = 0;
|
||||
@@ -2507,15 +2508,16 @@ void AudioOcarina_PlayControllerInput(u8 isOcarinaSfxSuppressedWhenCancelled) {
|
||||
if ((sCurOcarinaPitch != OCARINA_PITCH_NONE) && (sPrevOcarinaPitch != sCurOcarinaPitch)) {
|
||||
// Sets ocarina instrument Id to io port 7, which is used
|
||||
// as an index in seq 0 to get the true instrument Id
|
||||
Audio_QueueCmdS8(0x6 << 24 | SEQ_PLAYER_SFX << 16 | SFX_CHANNEL_OCARINA << 8 | 7, sOcarinaInstrumentId - 1);
|
||||
AudioThread_QueueCmdS8(0x6 << 24 | SEQ_PLAYER_SFX << 16 | SFX_CHANNEL_OCARINA << 8 | 7,
|
||||
sOcarinaInstrumentId - 1);
|
||||
// Sets pitch to io port 5
|
||||
Audio_QueueCmdS8(0x6 << 24 | SEQ_PLAYER_SFX << 16 | SFX_CHANNEL_OCARINA << 8 | 5, sCurOcarinaPitch);
|
||||
Audio_PlaySfxGeneral(NA_SE_OC_OCARINA, &gSfxDefaultPos, 4, &sCurOcarinaBendFreq, &sDefaultOcarinaVolume,
|
||||
&gSfxDefaultReverb);
|
||||
AudioThread_QueueCmdS8(0x6 << 24 | SEQ_PLAYER_SFX << 16 | SFX_CHANNEL_OCARINA << 8 | 5, sCurOcarinaPitch);
|
||||
AudioSfx_PlaySfx(NA_SE_OC_OCARINA, &gSfxDefaultPos, 4, &sCurOcarinaBendFreq, &sDefaultOcarinaVolume,
|
||||
&gSfxDefaultReverb);
|
||||
} else if ((sPrevOcarinaPitch != OCARINA_PITCH_NONE) && (sCurOcarinaPitch == OCARINA_PITCH_NONE) &&
|
||||
!isOcarinaSfxSuppressedWhenCancelled) {
|
||||
// Stops ocarina sound when transitioning from playing to not playing a note
|
||||
Audio_StopSfxById(NA_SE_OC_OCARINA);
|
||||
AudioSfx_StopById(NA_SE_OC_OCARINA);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2540,10 +2542,10 @@ void AudioOcarina_ResetAndMute(void) {
|
||||
sOcarinaInputButtonStart = 0xFFFF;
|
||||
|
||||
AudioOcarina_PlayControllerInput(false);
|
||||
Audio_StopSfxById(NA_SE_OC_OCARINA);
|
||||
AudioSfx_StopById(NA_SE_OC_OCARINA);
|
||||
|
||||
if (gAudioSpecId != 12) {
|
||||
Audio_SetSfxBanksMute(0);
|
||||
AudioSfx_MuteBanks(0);
|
||||
}
|
||||
|
||||
sPlaybackState = 0;
|
||||
@@ -2553,7 +2555,7 @@ void AudioOcarina_ResetAndMute(void) {
|
||||
sOcarinaFlags = 0;
|
||||
|
||||
// return to full volume for both bgm players after ocarina is finished
|
||||
Audio_ClearFlagForBgmVolumeLow(SFX_CHANNEL_OCARINA);
|
||||
AudioSfx_RestoreBgmVolume(SFX_CHANNEL_OCARINA);
|
||||
// return to full volume for all sfx channels except system & ocarina banks
|
||||
Audio_SetSfxVolumeExceptSystemAndOcarinaBanks(0x7F);
|
||||
}
|
||||
@@ -2602,7 +2604,7 @@ u32 AudioOcarina_SetInstrument(u8 ocarinaInstrumentId) {
|
||||
// lowers volume of all sfx channels except system & ocarina banks
|
||||
Audio_SetSfxVolumeExceptSystemAndOcarinaBanks(0x40);
|
||||
// lowers volume of bgm players while playing ocarina
|
||||
Audio_SetFlagForBgmVolumeLow(SFX_CHANNEL_OCARINA);
|
||||
AudioSfx_LowerBgmVolume(SFX_CHANNEL_OCARINA);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2612,7 +2614,7 @@ void AudioOcarina_SetPlaybackSong(s8 songIndexPlusOne, u8 playbackState) {
|
||||
|
||||
if (songIndexPlusOne == 0) {
|
||||
sPlaybackState = 0;
|
||||
Audio_StopSfxById(NA_SE_OC_OCARINA);
|
||||
AudioSfx_StopById(NA_SE_OC_OCARINA);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2700,7 +2702,7 @@ void AudioOcarina_PlaybackSong(void) {
|
||||
sPlaybackStaffPos = 0;
|
||||
sPlaybackPitch = OCARINA_PITCH_NONE;
|
||||
} else {
|
||||
Audio_StopSfxById(NA_SE_OC_OCARINA);
|
||||
AudioSfx_StopById(NA_SE_OC_OCARINA);
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
@@ -2716,7 +2718,7 @@ void AudioOcarina_PlaybackSong(void) {
|
||||
// Update vibrato
|
||||
sNotePlaybackVibrato = sPlaybackSong[sPlaybackNotePos].vibrato;
|
||||
// Sets vibrato to io port 6
|
||||
Audio_QueueCmdS8(0x6 << 24 | SEQ_PLAYER_SFX << 16 | SFX_CHANNEL_OCARINA << 8 | 6, sNotePlaybackVibrato);
|
||||
AudioThread_QueueCmdS8(0x6 << 24 | SEQ_PLAYER_SFX << 16 | SFX_CHANNEL_OCARINA << 8 | 6, sNotePlaybackVibrato);
|
||||
|
||||
// Update bend
|
||||
if (sNotePlaybackBend != sPlaybackSong[sPlaybackNotePos].bend) {
|
||||
@@ -2746,14 +2748,14 @@ void AudioOcarina_PlaybackSong(void) {
|
||||
sPlaybackStaffPos++;
|
||||
// Sets ocarina instrument Id to io port 7, which is used
|
||||
// as an index in seq 0 to get the true instrument Id
|
||||
Audio_QueueCmdS8(0x6 << 24 | SEQ_PLAYER_SFX << 16 | SFX_CHANNEL_OCARINA << 8 | 7,
|
||||
sOcarinaInstrumentId - 1);
|
||||
Audio_QueueCmdS8(0x6 << 24 | SEQ_PLAYER_SFX << 16 | SFX_CHANNEL_OCARINA << 8 | 5,
|
||||
sPlaybackPitch & OCARINA_BUTTON_MASK_PITCH);
|
||||
Audio_PlaySfxGeneral(NA_SE_OC_OCARINA, &gSfxDefaultPos, 4, &sRelativeNotePlaybackBend,
|
||||
&sRelativeNotePlaybackVolume, &gSfxDefaultReverb);
|
||||
AudioThread_QueueCmdS8(0x6 << 24 | SEQ_PLAYER_SFX << 16 | SFX_CHANNEL_OCARINA << 8 | 7,
|
||||
sOcarinaInstrumentId - 1);
|
||||
AudioThread_QueueCmdS8(0x6 << 24 | SEQ_PLAYER_SFX << 16 | SFX_CHANNEL_OCARINA << 8 | 5,
|
||||
sPlaybackPitch & OCARINA_BUTTON_MASK_PITCH);
|
||||
AudioSfx_PlaySfx(NA_SE_OC_OCARINA, &gSfxDefaultPos, 4, &sRelativeNotePlaybackBend,
|
||||
&sRelativeNotePlaybackVolume, &gSfxDefaultReverb);
|
||||
} else {
|
||||
Audio_StopSfxById(NA_SE_OC_OCARINA);
|
||||
AudioSfx_StopById(NA_SE_OC_OCARINA);
|
||||
}
|
||||
}
|
||||
sPlaybackNotePos++;
|
||||
@@ -3073,7 +3075,7 @@ void AudioOcarina_TerminaWallGenerateNotes(void) {
|
||||
j = 0;
|
||||
|
||||
for (; i < 8; i++) {
|
||||
randomButtonIndex = Audio_NextRandom() % ARRAY_COUNT(sButtonToPitchMap);
|
||||
randomButtonIndex = AudioThread_NextRandom() % ARRAY_COUNT(sButtonToPitchMap);
|
||||
sOcarinaSongNotes[OCARINA_SONG_TERMINA_WALL][j].pitch = sButtonToPitchMap[randomButtonIndex];
|
||||
sOcarinaSongNotes[OCARINA_SONG_TERMINA_WALL][j].length = 19;
|
||||
sOcarinaSongNotes[OCARINA_SONG_TERMINA_WALL][j].volume = 80;
|
||||
@@ -3094,7 +3096,7 @@ void AudioOcarina_TerminaWallGenerateNotes(void) {
|
||||
sOcarinaSongNotes[OCARINA_SONG_TERMINA_WALL][j + 1].length = 0;
|
||||
AudioOcarina_MapSongFromPitchToButton(OCARINA_SONG_TERMINA_WALL, OCARINA_SONG_TERMINA_WALL, 8);
|
||||
} else {
|
||||
j = Audio_NextRandom() % ARRAY_COUNT(sOoTOcarinaSongNotes);
|
||||
j = AudioThread_NextRandom() % ARRAY_COUNT(sOoTOcarinaSongNotes);
|
||||
ocarinaNote = sOoTOcarinaSongNotes[j];
|
||||
|
||||
for (; ocarinaNote[i].length != 0; i++) {
|
||||
@@ -3140,7 +3142,7 @@ s32 AudioOcarina_MemoryGameNextNote(void) {
|
||||
return true;
|
||||
}
|
||||
|
||||
randomButtonIndex = Audio_NextRandom();
|
||||
randomButtonIndex = AudioThread_NextRandom();
|
||||
randomPitch = sButtonToPitchMap[randomButtonIndex % ARRAY_COUNT(sButtonToPitchMap)];
|
||||
|
||||
if (sOcarinaSongNotes[OCARINA_SONG_MEMORY_GAME][sOcarinaMemoryGameAppendPos - 1].pitch == randomPitch) {
|
||||
@@ -3234,7 +3236,7 @@ void AudioOcarina_PlayLongScarecrowAfterCredits(void) {
|
||||
break;
|
||||
|
||||
case 1:
|
||||
Audio_SetSfxBanksMute(0);
|
||||
AudioSfx_MuteBanks(0);
|
||||
AudioOcarina_SetInstrument(sScarecrowAfterCreditsIntrumentId);
|
||||
AudioOcarina_SetPlaybackSong(OCARINA_SONG_SCARECROW_LONG + 1, 1);
|
||||
sScarecrowAfterCreditsIntrumentId++;
|
||||
@@ -3475,20 +3477,6 @@ void AudioOcarina_ResetStaffs(void) {
|
||||
D_801D8534 = 0;
|
||||
}
|
||||
|
||||
s8 D_801D8B30[] = {
|
||||
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
|
||||
34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
|
||||
56, 56, 57, 57, 58, 58, 59, 59, 60, 60, 60, 61, 61, 61, 62, 62, 62, 63, 63, 63, 64, 64,
|
||||
64, 65, 65, 65, 66, 66, 66, 67, 67, 67, 68, 68, 69, 69, 70, 70, 71, 71, 72, 73, 74, 75,
|
||||
76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
|
||||
98, 99, 100, 101, 102, 103, 105, 107, 109, 111, 113, 115, 117, 119, 121, 123, 125, 127,
|
||||
};
|
||||
f32 sBigBellsVolume[8] = {
|
||||
1.0f, 0.9f, 0.8f, 0.7f, 0.6f, 0.5f, 0.4f, 0.3f,
|
||||
};
|
||||
u8 sBgmPlayers[2] = { SEQ_PLAYER_BGM_MAIN, SEQ_PLAYER_BGM_SUB };
|
||||
f32 sSfxOriginalPos[] = { 0.0f, 0.0f, 0.0f };
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/func_8019DFF8.s")
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/func_8019E000.s")
|
||||
@@ -3503,23 +3491,447 @@ f32 sSfxOriginalPos[] = { 0.0f, 0.0f, 0.0f };
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/func_8019E110.s")
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/func_8019E14C.s")
|
||||
f32 AudioSfx_ComputeVolume(u8 bankId, u8 entryIndex) {
|
||||
SfxBankEntry* bankEntry = &gSfxBanks[bankId][entryIndex];
|
||||
f32 minDist;
|
||||
f32 phi_f14;
|
||||
f32 baseDist;
|
||||
f32 phi_f12;
|
||||
f32 volume; // Also acts as intermediate volumeSquared
|
||||
s32 pad[3];
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/func_8019E324.s")
|
||||
if (bankEntry->sfxParams & SFX_FLAG_VOLUME_NO_DIST) {
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/func_8019E4B0.s")
|
||||
if (bankEntry->dist > 10000.0f) {
|
||||
volume = 0.0f;
|
||||
} else {
|
||||
if (bankEntry->sfxParams & SFX_PARAM_DIST_RANGE_MASK_UPPER) {
|
||||
phi_f12 = 0.35f;
|
||||
phi_f14 = 0.65f;
|
||||
} else {
|
||||
phi_f12 = 0.81f;
|
||||
phi_f14 = 0.19f;
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/func_8019E634.s")
|
||||
switch (bankEntry->sfxParams & SFX_PARAM_DIST_RANGE_MASK) {
|
||||
case 0:
|
||||
baseDist = 500.0f;
|
||||
break;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/func_8019E864.s")
|
||||
case 1:
|
||||
baseDist = 666.6667f;
|
||||
break;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/func_8019EA40.s")
|
||||
case 2:
|
||||
baseDist = 952.381f;
|
||||
break;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/func_8019EB2C.s")
|
||||
case 3:
|
||||
baseDist = 3846.154f;
|
||||
break;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/func_8019F024.s")
|
||||
case 4:
|
||||
baseDist = 1000.0f;
|
||||
break;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/func_8019F05C.s")
|
||||
case 5:
|
||||
baseDist = 666.6667f;
|
||||
break;
|
||||
|
||||
case 6:
|
||||
baseDist = 500.0f;
|
||||
break;
|
||||
|
||||
case 7:
|
||||
baseDist = 400.0f;
|
||||
break;
|
||||
}
|
||||
|
||||
minDist = baseDist / 5.0f;
|
||||
|
||||
if (bankEntry->dist < minDist) {
|
||||
volume = 1.0f;
|
||||
} else if (bankEntry->dist < baseDist) {
|
||||
volume =
|
||||
((((baseDist - minDist) - (bankEntry->dist - minDist)) / (baseDist - minDist)) * phi_f14) + phi_f12;
|
||||
} else {
|
||||
volume = (1.0f - ((bankEntry->dist - baseDist) / (10000.0f - baseDist))) * phi_f12;
|
||||
}
|
||||
|
||||
volume = SQ(volume);
|
||||
}
|
||||
|
||||
return volume;
|
||||
}
|
||||
|
||||
s8 AudioSfx_ComputeReverb(u8 bankId, u8 entryIndex, u8 channelIndex) {
|
||||
s8 distAdd = 0;
|
||||
s32 scriptAdd = 0;
|
||||
SfxBankEntry* entry = &gSfxBanks[bankId][entryIndex];
|
||||
s32 reverb;
|
||||
|
||||
if (!(entry->sfxParams & SFX_FLAG_REVERB_NO_DIST)) {
|
||||
if (entry->dist < 2500.0f) {
|
||||
distAdd = *entry->posZ > 0.0f ? (entry->dist / 2500.0f) * 70.0f : (entry->dist / 2500.0f) * 91.0f;
|
||||
} else {
|
||||
distAdd = 70;
|
||||
}
|
||||
}
|
||||
|
||||
if (IS_SEQUENCE_CHANNEL_VALID(gAudioContext.seqPlayers[SEQ_PLAYER_SFX].channels[channelIndex])) {
|
||||
scriptAdd = gAudioContext.seqPlayers[SEQ_PLAYER_SFX].channels[channelIndex]->soundScriptIO[1];
|
||||
if (gAudioContext.seqPlayers[SEQ_PLAYER_SFX].channels[channelIndex]->soundScriptIO[1] < 0) {
|
||||
scriptAdd = 0;
|
||||
}
|
||||
}
|
||||
|
||||
reverb = (*entry->reverbAdd & 0x7F) + distAdd;
|
||||
|
||||
if (entry->state != SFX_STATE_READY) {
|
||||
reverb += scriptAdd;
|
||||
}
|
||||
|
||||
if ((bankId != BANK_OCARINA) || (SFX_INDEX(entry->sfxId) >= 2)) {
|
||||
reverb += sAudioEnvReverb + (sAudioCodeReverb & 0x3F) + sSpecReverb;
|
||||
}
|
||||
|
||||
if (reverb > 0x7F) {
|
||||
reverb = 0x7F;
|
||||
}
|
||||
|
||||
return reverb;
|
||||
}
|
||||
|
||||
s8 AudioSfx_ComputePanSigned(f32 x, f32 z, u8 token) {
|
||||
f32 absX = ABS_ALT(x);
|
||||
f32 absZ = ABS_ALT(z);
|
||||
f32 pan;
|
||||
|
||||
if (absX > 8000.0f) {
|
||||
absX = 8000.0f;
|
||||
}
|
||||
|
||||
if (absZ > 8000.0f) {
|
||||
absZ = 8000.0f;
|
||||
}
|
||||
|
||||
if ((x == 0.0f) && (z == 0.0f)) {
|
||||
pan = 0.5f;
|
||||
} else if (absZ <= absX) {
|
||||
pan = (16000.0f - absX) / (4.5f * (16000.0f - absZ));
|
||||
if (x >= 0.0f) {
|
||||
pan = 1.0f - pan;
|
||||
}
|
||||
} else {
|
||||
pan = (x / (3.6f * absZ)) + 0.5f;
|
||||
}
|
||||
|
||||
if ((absZ < 50.0f) && (absX < 50.0f)) {
|
||||
pan = ((pan - 0.5f) * SQ(absX / 50.0f)) + 0.5f;
|
||||
}
|
||||
|
||||
return (pan * 127.0f) + 0.5f;
|
||||
}
|
||||
|
||||
f32 AudioSfx_ComputeFreqScale(u8 bankId, u8 entryIndex) {
|
||||
s32 applyRandScaling = false;
|
||||
SfxBankEntry* entry = &gSfxBanks[bankId][entryIndex];
|
||||
f32 dist;
|
||||
f32 freq = 1.0f;
|
||||
|
||||
if (entry->sfxParams & SFX_PARAM_RAND_FREQ_LOWER) {
|
||||
freq = 1.0f - ((gAudioContext.audioRandom & 0xF) / 192.0f);
|
||||
}
|
||||
|
||||
switch (bankId) {
|
||||
case BANK_VOICE:
|
||||
if (((entry->sfxId & 0xFF) < 0x40) && (sAudioBaseFilter2 != 0)) {
|
||||
applyRandScaling = true;
|
||||
} else if (((entry->sfxId & 0xFF) >= 0x40) && (sAudioExtraFilter2 != 0)) {
|
||||
applyRandScaling = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case BANK_PLAYER:
|
||||
case BANK_ITEM:
|
||||
if (sAudioBaseFilter2 != 0) {
|
||||
applyRandScaling = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case BANK_ENV:
|
||||
case BANK_ENEMY:
|
||||
if (((*entry->reverbAdd & 0x80) != 0) | (sAudioExtraFilter2 != 0)) {
|
||||
applyRandScaling = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case BANK_SYSTEM:
|
||||
case BANK_OCARINA:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if ((applyRandScaling == true) && !(entry->sfxParams & SFX_PARAM_RAND_FREQ_SCALE)) {
|
||||
freq *= 1.0293 - ((gAudioContext.audioRandom & 0xF) / 144.0f);
|
||||
}
|
||||
|
||||
dist = entry->dist;
|
||||
if (!(entry->sfxParams & SFX_FLAG_VOLUME_NO_DIST) && !(entry->sfxParams & SFX_FLAG_FREQ_NO_DIST)) {
|
||||
if (dist >= 10000.0f) {
|
||||
freq += 0.2f;
|
||||
} else {
|
||||
freq += (0.2f * (dist / 10000.0f));
|
||||
}
|
||||
}
|
||||
|
||||
if ((entry->sfxParams & SFX_PARAM_RAND_FREQ_RAISE_MASK) != (0 << SFX_PARAM_RAND_FREQ_RAISE_SHIFT)) {
|
||||
freq += (entry->randFreq / 192.0f);
|
||||
}
|
||||
|
||||
return freq;
|
||||
}
|
||||
|
||||
u8 AudioSfx_ComputeSurroundSoundFilter(f32 behindScreenZ, SfxBankEntry* entry, s8 panSigned) {
|
||||
u8 lowPassCutoff;
|
||||
u8 highPassCutoff;
|
||||
u16* sfxParams;
|
||||
f32 distParam;
|
||||
f32 dist;
|
||||
|
||||
// Remnant of OoT
|
||||
if (*entry->posZ < behindScreenZ) {
|
||||
lowPassCutoff = 0;
|
||||
} else {
|
||||
lowPassCutoff = 0;
|
||||
}
|
||||
|
||||
sfxParams = &entry->sfxParams;
|
||||
|
||||
if (*sfxParams & SFX_FLAG_SURROUND_LOWPASS_FILTER) {
|
||||
lowPassCutoff = 0xF;
|
||||
}
|
||||
|
||||
switch ((*sfxParams & SFX_PARAM_DIST_RANGE_MASK)) {
|
||||
case 0:
|
||||
distParam = 15.0f;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
distParam = 12.0f;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
distParam = 9.0f;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
distParam = 6.0f;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
distParam = 18.0f;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
distParam = 21.0f;
|
||||
break;
|
||||
|
||||
case 6:
|
||||
distParam = 24.0f;
|
||||
break;
|
||||
|
||||
case 7:
|
||||
distParam = 27.0f;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(entry->sfxFlags & SFX_FLAG2_SURROUND_NO_HIGHPASS_FILTER)) {
|
||||
if (entry->dist > 1923.077f) {
|
||||
dist = 1923.077f;
|
||||
} else {
|
||||
dist = entry->dist;
|
||||
}
|
||||
|
||||
highPassCutoff = (distParam * dist) / (2 * 1923.077f);
|
||||
} else {
|
||||
highPassCutoff = 0;
|
||||
}
|
||||
|
||||
return (lowPassCutoff << 4) + highPassCutoff;
|
||||
}
|
||||
|
||||
s8 AudioSfx_ComputeCombFilter(f32 posY, u16 sfxParams) {
|
||||
s8 combFilterGain;
|
||||
|
||||
if (posY < 0.0f) {
|
||||
if (posY < -625.0f) {
|
||||
combFilterGain = -32;
|
||||
} else {
|
||||
combFilterGain = (s8)(((625.0f + posY) / 625.0f) * 31.0f) + 0xE0;
|
||||
}
|
||||
} else if (posY > 1250.0f) {
|
||||
combFilterGain = 127;
|
||||
} else {
|
||||
combFilterGain = (posY / 1250.0f) * 126.0f;
|
||||
}
|
||||
|
||||
return combFilterGain | 1;
|
||||
}
|
||||
|
||||
void AudioSfx_SetProperties(u8 bankId, u8 entryIndex, u8 channelIndex) {
|
||||
static s8 sZVolumes[] = {
|
||||
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
|
||||
34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
|
||||
56, 56, 57, 57, 58, 58, 59, 59, 60, 60, 60, 61, 61, 61, 62, 62, 62, 63, 63, 63, 64, 64,
|
||||
64, 65, 65, 65, 66, 66, 66, 67, 67, 67, 68, 68, 69, 69, 70, 70, 71, 71, 72, 73, 74, 75,
|
||||
76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
|
||||
98, 99, 100, 101, 102, 103, 105, 107, 109, 111, 113, 115, 117, 119, 121, 123, 125, 127,
|
||||
};
|
||||
f32 volume = 1.0f;
|
||||
s8 volumeS8;
|
||||
s8 reverb = 0;
|
||||
f32 freqScale = 1.0f;
|
||||
s8 panSigned = 0x40;
|
||||
u8 pad;
|
||||
u8 filter = 0;
|
||||
s8 combFilterGain = 0;
|
||||
s8 zVolume = -1;
|
||||
f32 behindScreenZ;
|
||||
u8 baseFilter = 0;
|
||||
SfxBankEntry* entry = &gSfxBanks[bankId][entryIndex];
|
||||
s32 pad2;
|
||||
|
||||
switch (bankId) {
|
||||
case BANK_PLAYER:
|
||||
case BANK_ITEM:
|
||||
case BANK_ENV:
|
||||
case BANK_ENEMY:
|
||||
case BANK_VOICE:
|
||||
if (sSoundMode == SOUNDMODE_SURROUND) {
|
||||
combFilterGain = AudioSfx_ComputeCombFilter(*entry->posY, entry->sfxParams);
|
||||
}
|
||||
// fallthrough
|
||||
case BANK_OCARINA:
|
||||
entry->dist = sqrtf(entry->dist * 10.0f);
|
||||
volume = AudioSfx_ComputeVolume(bankId, entryIndex) * *entry->volume;
|
||||
reverb = AudioSfx_ComputeReverb(bankId, entryIndex, channelIndex);
|
||||
panSigned = AudioSfx_ComputePanSigned(*entry->posX, *entry->posZ, entry->token);
|
||||
freqScale = AudioSfx_ComputeFreqScale(bankId, entryIndex) * *entry->freqScale;
|
||||
|
||||
if (sSoundMode == SOUNDMODE_SURROUND) {
|
||||
if (*entry->posZ >= 0.0f) {
|
||||
if (*entry->posZ < 200.0f) {
|
||||
zVolume = 32.0f - ((*entry->posZ / 300.0f) * 32.0f);
|
||||
} else {
|
||||
zVolume = 0;
|
||||
}
|
||||
} else if (*entry->posZ < 0.0f) {
|
||||
if (*entry->posZ > -300.0f) {
|
||||
zVolume = 32.0f - ((*entry->posZ / 300.0f) * 95.0f);
|
||||
} else {
|
||||
zVolume = 127;
|
||||
}
|
||||
}
|
||||
zVolume = sZVolumes[zVolume];
|
||||
}
|
||||
|
||||
if (sAudioBaseFilter != 0) {
|
||||
if ((bankId == BANK_PLAYER) || (bankId == BANK_ITEM) ||
|
||||
((bankId == BANK_VOICE) && (((entry->sfxId & 0xFF) < 0x40) || ((entry->sfxId & 0xFF) >= 0x80)))) {
|
||||
baseFilter = sAudioBaseFilter;
|
||||
if (sAudioExtraFilter) {
|
||||
reverb >>= 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (((*entry->reverbAdd & 0x80) | baseFilter | sAudioExtraFilter |
|
||||
(entry->sfxFlags & SFX_FLAG2_APPLY_LOWPASS_FILTER)) != 0) {
|
||||
filter = ((((*entry->reverbAdd & 0x80) >> 2) | baseFilter | sAudioExtraFilter |
|
||||
((entry->sfxFlags & SFX_FLAG2_APPLY_LOWPASS_FILTER) >> 2)) *
|
||||
2);
|
||||
filter &= 0xFF;
|
||||
} else if ((sSoundMode == SOUNDMODE_SURROUND) && !(entry->sfxParams & SFX_FLAG_VOLUME_NO_DIST)) {
|
||||
filter = AudioSfx_ComputeSurroundSoundFilter(behindScreenZ, entry, panSigned);
|
||||
}
|
||||
break;
|
||||
|
||||
case BANK_SYSTEM:
|
||||
break;
|
||||
}
|
||||
|
||||
if (sSfxChannelState[channelIndex].volume != volume) {
|
||||
volumeS8 = (u8)(volume * 127.0f);
|
||||
sSfxChannelState[channelIndex].volume = volume;
|
||||
} else {
|
||||
volumeS8 = -1;
|
||||
}
|
||||
|
||||
//! FAKE:
|
||||
if (1) {}
|
||||
|
||||
// CHAN_UPD_SCRIPT_IO (slot 2, sets volume)
|
||||
AudioThread_QueueCmdS8((0x6 << 24) | (SEQ_PLAYER_SFX << 16) | (channelIndex << 8) | 2, volumeS8);
|
||||
|
||||
if (sSfxChannelState[channelIndex].reverb != reverb) {
|
||||
sSfxChannelState[channelIndex].reverb = reverb;
|
||||
}
|
||||
if (sSfxChannelState[channelIndex].freqScale != freqScale) {
|
||||
sSfxChannelState[channelIndex].freqScale = freqScale;
|
||||
}
|
||||
if (sSfxChannelState[channelIndex].stereoBits != 0) {
|
||||
sSfxChannelState[channelIndex].stereoBits = 0;
|
||||
}
|
||||
if (sSfxChannelState[channelIndex].filter != filter) {
|
||||
sSfxChannelState[channelIndex].filter = filter;
|
||||
}
|
||||
if (sSfxChannelState[channelIndex].combFilterGain != combFilterGain) {
|
||||
sSfxChannelState[channelIndex].combFilterGain = combFilterGain;
|
||||
}
|
||||
if (sSfxChannelState[channelIndex].zVolume != zVolume) {
|
||||
sSfxChannelState[channelIndex].zVolume = zVolume;
|
||||
}
|
||||
if (sSfxChannelState[channelIndex].panSigned != panSigned) {
|
||||
sSfxChannelState[channelIndex].panSigned = panSigned;
|
||||
}
|
||||
}
|
||||
|
||||
u32 AudioSfx_SetFreqAndStereoBits(u8 seqScriptValIn, SequenceChannel* channel) {
|
||||
channel->stereo.asByte = sSfxChannelState[seqScriptValIn].stereoBits;
|
||||
channel->freqScale = sSfxChannelState[seqScriptValIn].freqScale;
|
||||
channel->changes.s.freqScale = true;
|
||||
|
||||
return seqScriptValIn;
|
||||
}
|
||||
|
||||
void AudioSfx_ResetSfxChannelState(void) {
|
||||
SfxChannelState* state;
|
||||
u8 i;
|
||||
|
||||
for (i = 0; i < ARRAY_COUNT(sSfxChannelState); i++) {
|
||||
state = &sSfxChannelState[i];
|
||||
state->volume = 1.0f;
|
||||
state->freqScale = 1.0f;
|
||||
state->reverb = 0;
|
||||
state->panSigned = 0x40;
|
||||
state->stereoBits = 0;
|
||||
state->filter = 0xFF;
|
||||
state->combFilterGain = 0xFF;
|
||||
state->zVolume = 0xFF;
|
||||
}
|
||||
|
||||
sSfxChannelState[SFX_CHANNEL_OCARINA].combFilterGain = 0;
|
||||
sPrevSeqMode = SEQ_MODE_DEFAULT;
|
||||
sAudioCodeReverb = 0;
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/play_sound.s")
|
||||
|
||||
@@ -3533,9 +3945,75 @@ f32 sSfxOriginalPos[] = { 0.0f, 0.0f, 0.0f };
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/func_8019F230.s")
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/func_8019F258.s")
|
||||
SfxSettings* AudioSfx_AddSfxSetting(Vec3f* pos) {
|
||||
SfxSettings* sfxSettings;
|
||||
u8 i = 0;
|
||||
u8 sfxSettingIndex = 0xFF;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/func_8019F300.s")
|
||||
for (; i < ARRAY_COUNT(sSfxSettings); i++) {
|
||||
sfxSettings = &sSfxSettings[i];
|
||||
|
||||
if ((sfxSettings->pos == NULL) && (sfxSettingIndex == 0xFF)) {
|
||||
sfxSettingIndex = i;
|
||||
}
|
||||
|
||||
if (sfxSettings->pos == pos) {
|
||||
return sfxSettings;
|
||||
}
|
||||
}
|
||||
|
||||
if (sfxSettingIndex != 0xFF) {
|
||||
sSfxSettingsFlags |= 1 << sfxSettingIndex;
|
||||
sfxSettings = &sSfxSettings[sfxSettingIndex];
|
||||
sfxSettings->pos = pos;
|
||||
return sfxSettings;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void AudioSfx_ProcessSfxSettings(void) {
|
||||
SfxBankEntry* entry;
|
||||
u8 sfxSettingsFlags;
|
||||
u8 sfxSettingIndex = 0;
|
||||
u8 bankId;
|
||||
u8 entryIndex;
|
||||
s32 found;
|
||||
|
||||
if (sSfxSettingsFlags != 0) {
|
||||
sfxSettingsFlags = sSfxSettingsFlags;
|
||||
|
||||
while (sfxSettingsFlags != 0) {
|
||||
bankId = BANK_ENV;
|
||||
if ((sfxSettingsFlags & (1 << sfxSettingIndex))) {
|
||||
|
||||
found = false;
|
||||
while ((bankId <= BANK_ENEMY) && !found) {
|
||||
entryIndex = gSfxBanks[bankId]->next;
|
||||
|
||||
while (entryIndex != 0xFF) {
|
||||
entry = &gSfxBanks[bankId][entryIndex];
|
||||
entryIndex = 0xFF;
|
||||
if (entry->posX == &sSfxSettings[sfxSettingIndex].pos->x) {
|
||||
found = true;
|
||||
} else {
|
||||
entryIndex = entry->next;
|
||||
}
|
||||
}
|
||||
bankId++;
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
sSfxSettingsFlags ^= (1 << sfxSettingIndex);
|
||||
sSfxSettings[sfxSettingIndex].pos = NULL;
|
||||
}
|
||||
|
||||
sfxSettingsFlags ^= (1 << sfxSettingIndex);
|
||||
}
|
||||
sfxSettingIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/func_8019F420.s")
|
||||
|
||||
@@ -3543,7 +4021,17 @@ f32 sSfxOriginalPos[] = { 0.0f, 0.0f, 0.0f };
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/func_8019F540.s")
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/func_8019F570.s")
|
||||
void AudioSfx_LowerSfxSettingsReverb(Vec3f* pos, s8 isReverbLowered) {
|
||||
SfxSettings* sfxSettings = AudioSfx_AddSfxSetting(pos);
|
||||
|
||||
if (sfxSettings != NULL) {
|
||||
if (isReverbLowered) {
|
||||
sfxSettings->reverbAdd = -0x80;
|
||||
} else {
|
||||
sfxSettings->reverbAdd = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/func_8019F5AC.s")
|
||||
|
||||
@@ -3585,15 +4073,15 @@ f32 sSfxOriginalPos[] = { 0.0f, 0.0f, 0.0f };
|
||||
* Used for EnRiverSound
|
||||
*/
|
||||
void Audio_PlaySfxForRiver(Vec3f* pos, f32 freqScale) {
|
||||
if (!Audio_IsSfxPlaying(NA_SE_EV_RIVER_STREAM - SFX_FLAG)) {
|
||||
if (!AudioSfx_IsPlaying(NA_SE_EV_RIVER_STREAM - SFX_FLAG)) {
|
||||
sRiverFreqScaleLerp.value = freqScale;
|
||||
} else if (freqScale != sRiverFreqScaleLerp.value) {
|
||||
sRiverFreqScaleLerp.target = freqScale;
|
||||
sRiverFreqScaleLerp.remainingFrames = 40;
|
||||
sRiverFreqScaleLerp.step = (sRiverFreqScaleLerp.target - sRiverFreqScaleLerp.value) / 40;
|
||||
}
|
||||
Audio_PlaySfxGeneral(NA_SE_EV_RIVER_STREAM - SFX_FLAG, pos, 4, &sRiverFreqScaleLerp.value, &D_801DB4B0,
|
||||
&gSfxDefaultReverb);
|
||||
AudioSfx_PlaySfx(NA_SE_EV_RIVER_STREAM - SFX_FLAG, pos, 4, &sRiverFreqScaleLerp.value, &gSfxDefaultFreqAndVolScale,
|
||||
&gSfxDefaultReverb);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3601,15 +4089,15 @@ void Audio_PlaySfxForRiver(Vec3f* pos, f32 freqScale) {
|
||||
* Used for Zora's River Waterfall
|
||||
*/
|
||||
void Audio_PlaySfxForWaterfall(Vec3f* pos, f32 freqScale) {
|
||||
if (!Audio_IsSfxPlaying(NA_SE_EV_WATER_WALL_BIG - SFX_FLAG)) {
|
||||
if (!AudioSfx_IsPlaying(NA_SE_EV_WATER_WALL_BIG - SFX_FLAG)) {
|
||||
sWaterfallFreqScaleLerp.value = freqScale;
|
||||
} else if (freqScale != sWaterfallFreqScaleLerp.value) {
|
||||
sWaterfallFreqScaleLerp.target = freqScale;
|
||||
sWaterfallFreqScaleLerp.remainingFrames = 40;
|
||||
sWaterfallFreqScaleLerp.step = (sWaterfallFreqScaleLerp.target - sWaterfallFreqScaleLerp.value) / 40;
|
||||
}
|
||||
Audio_PlaySfxGeneral(NA_SE_EV_WATER_WALL_BIG - SFX_FLAG, pos, 4, &sWaterfallFreqScaleLerp.value,
|
||||
&sWaterfallFreqScaleLerp.value, &gSfxDefaultReverb);
|
||||
AudioSfx_PlaySfx(NA_SE_EV_WATER_WALL_BIG - SFX_FLAG, pos, 4, &sWaterfallFreqScaleLerp.value,
|
||||
&sWaterfallFreqScaleLerp.value, &gSfxDefaultReverb);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3626,6 +4114,9 @@ void Audio_StepFreqLerp(FreqLerp* lerp) {
|
||||
}
|
||||
}
|
||||
|
||||
f32 sBigBellsVolume[8] = {
|
||||
1.0f, 0.9f, 0.8f, 0.7f, 0.6f, 0.5f, 0.4f, 0.3f,
|
||||
};
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/func_801A0124.s")
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/func_801A0184.s")
|
||||
@@ -3652,7 +4143,7 @@ void Audio_SetGanonsTowerBgmVolumeLevel(u8 ganonsTowerLevel) {
|
||||
|
||||
for (channelIndex = 0; channelIndex < 16; channelIndex++) {
|
||||
// CHAN_UPD_PAN_UNSIGNED
|
||||
Audio_QueueCmdS8(((u8)(u32)channelIndex << 8) | 0x7000000, pan);
|
||||
AudioThread_QueueCmdS8(((u8)(u32)channelIndex << 8) | 0x7000000, pan);
|
||||
}
|
||||
|
||||
// Lowest room in Ganon's Tower (Entrance Room)
|
||||
@@ -3710,9 +4201,9 @@ s32 Audio_SetGanonsTowerBgmVolume(u8 targetVolume) {
|
||||
}
|
||||
|
||||
// CHAN_UPD_REVERB
|
||||
Audio_QueueCmdS8(_SHIFTL(5, 24, 8) | _SHIFTL(SEQ_PLAYER_BGM_MAIN, 16, 8) |
|
||||
_SHIFTL(channelIndex, 8, 8),
|
||||
(u8)reverb);
|
||||
AudioThread_QueueCmdS8(_SHIFTL(5, 24, 8) | _SHIFTL(SEQ_PLAYER_BGM_MAIN, 16, 8) |
|
||||
_SHIFTL(channelIndex, 8, 8),
|
||||
(u8)reverb);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3768,7 +4259,29 @@ void Audio_UpdateRiverSoundVolumes(void) {
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/func_801A05F0.s")
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/func_801A0654.s")
|
||||
void AudioSfx_SetChannelIO(Vec3f* pos, u16 sfxId, u8 ioData) {
|
||||
u8 channelIndex = 0;
|
||||
u8 bankId = SFX_BANK_SHIFT(sfxId);
|
||||
u8 entryIndex;
|
||||
u8 i;
|
||||
|
||||
for (i = 0; i < bankId; i++) {
|
||||
channelIndex += gChannelsPerBank[gSfxChannelLayout][i];
|
||||
}
|
||||
|
||||
for (i = 0; i < gChannelsPerBank[gSfxChannelLayout][bankId]; i++) {
|
||||
entryIndex = gActiveSfx[bankId][i].entryIndex;
|
||||
|
||||
if (entryIndex != 0xFF) {
|
||||
if ((sfxId == gSfxBanks[bankId][entryIndex].sfxId) && (&pos->x == gSfxBanks[bankId][entryIndex].posX)) {
|
||||
AudioThread_QueueCmdS8(_SHIFTL(6, 24, 8) | _SHIFTL(SEQ_PLAYER_SFX, 16, 8) |
|
||||
_SHIFTL(channelIndex, 8, 8) | _SHIFTL(6, 0, 8),
|
||||
ioData);
|
||||
}
|
||||
}
|
||||
channelIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/func_801A0810.s")
|
||||
|
||||
@@ -3814,7 +4327,7 @@ void func_801A09D4(Vec3f* pos, f32 xzDistToPlayer) {
|
||||
if (channelIndex != 9) {
|
||||
Audio_QueueSeqCmd(((u32)(6) << 28) | ((u32)(SEQ_PLAYER_BGM_MAIN) << 24) | ((u32)(2) << 16) |
|
||||
((u32)(channelIndex) << 8) | ((u8)(127.0f * volumeRel)));
|
||||
Audio_QueueCmdS8(0x03000000 | ((u8)((u32)channelIndex) << 8), pan);
|
||||
AudioThread_QueueCmdS8(0x03000000 | ((u8)((u32)channelIndex) << 8), pan);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3837,6 +4350,7 @@ void Audio_ClearSariaBgmAtPos(Vec3f* pos) {
|
||||
}
|
||||
}
|
||||
|
||||
u8 sBgmPlayers[2] = { SEQ_PLAYER_BGM_MAIN, SEQ_PLAYER_BGM_SUB };
|
||||
void Audio_SplitBgmChannels(s8 volumeSplit);
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/Audio_SplitBgmChannels.s")
|
||||
|
||||
@@ -4043,6 +4557,7 @@ void Audio_ClearSariaBgm2(void) {
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/func_801A46F8.s")
|
||||
|
||||
f32 sSfxOriginalPos[] = { 0.0f, 0.0f, 0.0f };
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/func_801A4748.s")
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/func_801A479C.s")
|
||||
@@ -4053,11 +4568,27 @@ void Audio_ClearSariaBgm2(void) {
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/func_801A4A28.s")
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/func_801A4B80.s")
|
||||
u32 Audio_SetNatureAmbienceRandomBend(u8 seqScriptValIn, SequenceChannel* channel);
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/Audio_SetNatureAmbienceRandomBend.s")
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/func_801A4C30.s")
|
||||
void Audio_Init(void) {
|
||||
AudioLoad_Init(NULL, 0);
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/func_801A4C54.s")
|
||||
void AudioSfx_Init(u16 fadeTimer) {
|
||||
u8 channelIndex;
|
||||
|
||||
AudioThread_ScheduleProcessCmds();
|
||||
Audio_StartSequence(SEQ_PLAYER_SFX, NA_BGM_GENERAL_SFX, 0x70, fadeTimer);
|
||||
|
||||
for (channelIndex = 0; channelIndex < ARRAY_COUNT(sSfxChannelState); channelIndex++) {
|
||||
AudioThread_QueueCmdS32(0x10 << 24 | SEQ_PLAYER_SFX << 16 | ((u8)(u32)channelIndex << 8),
|
||||
&sSfxChannelState[channelIndex]);
|
||||
}
|
||||
|
||||
AudioThread_QueueCmdS32(0xE4000000, AudioSfx_SetFreqAndStereoBits);
|
||||
AudioThread_QueueCmdS32(0xE4000001, Audio_SetNatureAmbienceRandomBend);
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/func_801A4D00.s")
|
||||
|
||||
|
||||
+928
-22
@@ -1,45 +1,951 @@
|
||||
#include "global.h"
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_801A5BD0/Audio_SetSfxBanksMute.s")
|
||||
typedef struct {
|
||||
/* 0x00 */ u16 sfxId;
|
||||
/* 0x02 */ u8 token;
|
||||
/* 0x04 */ s8* reverbAdd;
|
||||
/* 0x08 */ Vec3f* pos;
|
||||
/* 0x0C */ f32* freqScale;
|
||||
/* 0x10 */ f32* volume;
|
||||
} SfxRequest; // size = 0x14
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_801A5BD0/Audio_SetFlagForBgmVolumeLow.s")
|
||||
typedef struct {
|
||||
/* 0x0 */ f32 value;
|
||||
/* 0x4 */ f32 target;
|
||||
/* 0x8 */ f32 step;
|
||||
/* 0xC */ u16 remainingFrames;
|
||||
} SfxBankLerp; // size = 0x10
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_801A5BD0/Audio_ClearFlagForBgmVolumeLow.s")
|
||||
typedef enum {
|
||||
/* 0 */ SFX_RM_REQ_BY_BANK,
|
||||
/* 1 */ SFX_RM_REQ_BY_POS_AND_BANK,
|
||||
/* 2 */ SFX_RM_REQ_BY_POS,
|
||||
/* 3 */ SFX_RM_REQ_BY_POS_AND_ID,
|
||||
/* 4 */ SFX_RM_REQ_BY_TOKEN_AND_ID,
|
||||
/* 5 */ SFX_RM_REQ_BY_ID
|
||||
} SfxRemoveRequest;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_801A5BD0/Audio_PlaySfxGeneral.s")
|
||||
SfxBankEntry sSfxPlayerBank[9];
|
||||
SfxBankEntry sSfxItemBank[12];
|
||||
SfxBankEntry sSfxEnvironmentBank[32];
|
||||
SfxBankEntry sSfxEnemyBank[20];
|
||||
SfxBankEntry sSfxSystemBank[8];
|
||||
SfxBankEntry sSfxOcarinaBank[3];
|
||||
SfxBankEntry sSfxVoiceBank[5];
|
||||
SfxRequest sSfxRequests[0x100];
|
||||
u8 sSfxBankListEnd[7];
|
||||
u8 sSfxBankFreeListStart[7];
|
||||
u8 sSfxBankUnused[7];
|
||||
ActiveSfx gActiveSfx[7][3];
|
||||
u8 sCurSfxPlayerChannelIndex;
|
||||
u8 gSfxBankMuted[7];
|
||||
SfxBankLerp sSfxBankLerp[7];
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_801A5BD0/func_801A5DDC.s")
|
||||
// sSfxRequests ring buffer endpoints. read index <= write index, wrapping around mod 256.
|
||||
u8 sSfxRequestWriteIndex = 0;
|
||||
u8 sSfxRequestReadIndex = 0;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_801A5BD0/func_801A5F7C.s")
|
||||
/**
|
||||
* Array of pointers to arrays of SfxBankEntry of sizes: 9, 12, 32, 20, 8, 3, 5
|
||||
*
|
||||
* 0 : Player Bank size 9
|
||||
* 1 : Item Bank size 12
|
||||
* 2 : Environment Bank size 32
|
||||
* 3 : Enemy Bank size 20
|
||||
* 4 : System Bank size 8
|
||||
* 5 : Ocarina Bank size 3
|
||||
* 6 : Voice Bank size 5
|
||||
*/
|
||||
SfxBankEntry* gSfxBanks[7] = {
|
||||
sSfxPlayerBank, sSfxItemBank, sSfxEnvironmentBank, sSfxEnemyBank, sSfxSystemBank, sSfxOcarinaBank, sSfxVoiceBank,
|
||||
};
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_801A5BD0/func_801A6430.s")
|
||||
u8 sSfxBankSizes[ARRAY_COUNT(gSfxBanks)] = {
|
||||
ARRAY_COUNT(sSfxPlayerBank), ARRAY_COUNT(sSfxItemBank), ARRAY_COUNT(sSfxEnvironmentBank),
|
||||
ARRAY_COUNT(sSfxEnemyBank), ARRAY_COUNT(sSfxSystemBank), ARRAY_COUNT(sSfxOcarinaBank),
|
||||
ARRAY_COUNT(sSfxVoiceBank),
|
||||
};
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_801A5BD0/func_801A65C8.s")
|
||||
u8 gSfxChannelLayout = 0;
|
||||
u16 sSfxChannelLowVolumeFlag = 0;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_801A5BD0/func_801A6D0C.s")
|
||||
// The center of the screen in projected coordinates.
|
||||
// Gives the impression that the sfx has no specific location
|
||||
Vec3f gSfxDefaultPos = { 0.0f, 0.0f, 0.0f };
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_801A5BD0/func_801A7084.s")
|
||||
// Reused as either frequency or volume multiplicative scaling factor
|
||||
// Does not alter or change frequency or volume
|
||||
f32 gSfxDefaultFreqAndVolScale = 1.0f;
|
||||
s32 D_801DB4B4 = 0; // unused
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_801A5BD0/func_801A7168.s")
|
||||
// Adds no reverb to the existing reverb
|
||||
s8 gSfxDefaultReverb = 0;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_801A5BD0/func_801A7284.s")
|
||||
void AudioSfx_MuteBanks(u16 muteMask) {
|
||||
u8 bankId;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_801A5BD0/Audio_StopSfxByPos.s")
|
||||
for (bankId = 0; bankId < ARRAY_COUNT(gSfxBanks); bankId++) {
|
||||
if (muteMask & 1) {
|
||||
gSfxBankMuted[bankId] = true;
|
||||
} else {
|
||||
gSfxBankMuted[bankId] = false;
|
||||
}
|
||||
muteMask = muteMask >> 1;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_801A5BD0/func_801A7328.s")
|
||||
/**
|
||||
* Lowers volumes of both bgm players so that sfx can be more pronounced.
|
||||
* Each sfx channel stores its own bit to lower the volume.
|
||||
* Only a single channel needs to request this to lower the volume.
|
||||
*/
|
||||
void AudioSfx_LowerBgmVolume(u8 channelIndex) {
|
||||
sSfxChannelLowVolumeFlag |= (1 << channelIndex);
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_801A5BD0/func_801A7484.s")
|
||||
Audio_SetVolumeScale(SEQ_PLAYER_BGM_MAIN, 2, 0x40, 0xF);
|
||||
Audio_SetVolumeScale(SEQ_PLAYER_BGM_SUB, 2, 0x40, 0xF);
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_801A5BD0/Audio_StopSfxById.s")
|
||||
/**
|
||||
* Clears the flag for the specific channel to lower volume.
|
||||
* If all flags are cleared, then both bgm players return to full volume
|
||||
*/
|
||||
void AudioSfx_RestoreBgmVolume(u8 channelIndex) {
|
||||
sSfxChannelLowVolumeFlag &= ((1 << channelIndex) ^ 0xFFFF);
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_801A5BD0/func_801A7720.s")
|
||||
if (sSfxChannelLowVolumeFlag == 0) {
|
||||
Audio_SetVolumeScale(SEQ_PLAYER_BGM_MAIN, 2, 0x7F, 0xF);
|
||||
Audio_SetVolumeScale(SEQ_PLAYER_BGM_SUB, 2, 0x7F, 0xF);
|
||||
}
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_801A5BD0/func_801A7794.s")
|
||||
/**
|
||||
* The main function to request a sfx. All sfx requests begin here.
|
||||
*/
|
||||
void AudioSfx_PlaySfx(u16 sfxId, Vec3f* pos, u8 token, f32* freqScale, f32* volume, s8* reverbAdd) {
|
||||
u8 i;
|
||||
SfxRequest* reqWrite;
|
||||
SfxRequest* reqRead;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_801A5BD0/func_801A7828.s")
|
||||
if (!gSfxBankMuted[SFX_BANK_SHIFT(sfxId)]) {
|
||||
reqWrite = &sSfxRequests[sSfxRequestWriteIndex];
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_801A5BD0/func_801A787C.s")
|
||||
for (i = sSfxRequestReadIndex; sSfxRequestWriteIndex != i; i++) {
|
||||
reqRead = &sSfxRequests[i];
|
||||
if ((reqRead->pos == pos) && (reqRead->sfxId == sfxId)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_801A5BD0/Audio_IsSfxPlaying.s")
|
||||
reqWrite->sfxId = sfxId;
|
||||
reqWrite->pos = pos;
|
||||
reqWrite->token = token;
|
||||
reqWrite->freqScale = freqScale;
|
||||
reqWrite->volume = volume;
|
||||
reqWrite->reverbAdd = reverbAdd;
|
||||
sSfxRequestWriteIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_801A5BD0/func_801A794C.s")
|
||||
void AudioSfx_RemoveMatchingRequests(u8 aspect, SfxBankEntry* entry) {
|
||||
SfxRequest* req;
|
||||
s32 remove;
|
||||
u8 i = sSfxRequestReadIndex;
|
||||
|
||||
for (; i != sSfxRequestWriteIndex; i++) {
|
||||
remove = false;
|
||||
req = &sSfxRequests[i];
|
||||
|
||||
switch (aspect) {
|
||||
case SFX_RM_REQ_BY_BANK:
|
||||
if (SFX_BANK_MASK(req->sfxId) == SFX_BANK_MASK(entry->sfxId)) {
|
||||
remove = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case SFX_RM_REQ_BY_POS_AND_BANK:
|
||||
if ((SFX_BANK_MASK(req->sfxId) == SFX_BANK_MASK(entry->sfxId)) && (&req->pos->x == entry->posX)) {
|
||||
remove = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case SFX_RM_REQ_BY_POS:
|
||||
if (&req->pos->x == entry->posX) {
|
||||
remove = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case SFX_RM_REQ_BY_POS_AND_ID:
|
||||
if ((&req->pos->x == entry->posX) && (req->sfxId == entry->sfxId)) {
|
||||
remove = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case SFX_RM_REQ_BY_TOKEN_AND_ID:
|
||||
if ((req->token == entry->token) && (req->sfxId == entry->sfxId)) {
|
||||
remove = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case SFX_RM_REQ_BY_ID:
|
||||
if (req->sfxId == entry->sfxId) {
|
||||
remove = true;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (remove) {
|
||||
req->sfxId = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AudioSfx_ProcessRequest(void) {
|
||||
u16 sfxId;
|
||||
u8 channelCount;
|
||||
u8 index;
|
||||
SfxRequest* req = &sSfxRequests[sSfxRequestReadIndex];
|
||||
SfxBankEntry* entry;
|
||||
SfxParams* sfxParams;
|
||||
s32 bankId;
|
||||
u8 evictImportance;
|
||||
u8 evictIndex = 0x80;
|
||||
|
||||
if (req->sfxId == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
bankId = SFX_BANK(req->sfxId);
|
||||
channelCount = 0;
|
||||
index = gSfxBanks[bankId][0].next;
|
||||
|
||||
// Compare the sfx request to all sfx bank entries
|
||||
while ((index != 0xFF) && (index != 0)) {
|
||||
|
||||
// If an existing sfx from the same source exists in the bank, then we should either:
|
||||
// renew if it is the same sfx, check if any sfx channels are available for that bank,
|
||||
// interrupt that sfx and replace it with the new sfx request, or drop the new sfx request.
|
||||
if (gSfxBanks[bankId][index].posX == &req->pos->x) {
|
||||
|
||||
// If the new sfx has equal importance to the existing sfx,
|
||||
// drop the request if the existing sfx has the "SFX_FLAG_BLOCK_EQUAL_IMPORTANCE" flag.
|
||||
// Otherwise, keep processing the new sfx request
|
||||
if ((gSfxParams[SFX_BANK_SHIFT(req->sfxId)][SFX_INDEX(req->sfxId)].params &
|
||||
SFX_FLAG_BLOCK_EQUAL_IMPORTANCE) &&
|
||||
(gSfxParams[SFX_BANK_SHIFT(req->sfxId)][SFX_INDEX(req->sfxId)].importance ==
|
||||
gSfxBanks[bankId][index].sfxImportance)) {
|
||||
// Drop the new request
|
||||
return;
|
||||
}
|
||||
|
||||
if (gSfxBanks[bankId][index].sfxId == req->sfxId) {
|
||||
// The new sfx is the same as the existing sfx
|
||||
// Set channelCount to max value to reprocess the sfx
|
||||
channelCount = gUsedChannelsPerBank[gSfxChannelLayout][bankId];
|
||||
} else {
|
||||
// Determine which sfx to evict based on importance if there are no more channels available
|
||||
if (channelCount == 0) {
|
||||
// If this is the first sfx at the same source, than store the existing sfx info into evict temps
|
||||
evictIndex = index;
|
||||
sfxId = gSfxBanks[bankId][index].sfxId & 0xFFFF;
|
||||
evictImportance = gSfxParams[SFX_BANK_SHIFT(sfxId)][SFX_INDEX(sfxId)].importance;
|
||||
} else if (gSfxBanks[bankId][index].sfxImportance < evictImportance) {
|
||||
// If a different existing sfx is at the same source, than update the evict temps if the next
|
||||
// existing src has lower importance than the previous existing source
|
||||
evictIndex = index;
|
||||
sfxId = gSfxBanks[bankId][index].sfxId & 0xFFFF;
|
||||
evictImportance = gSfxParams[SFX_BANK_SHIFT(sfxId)][SFX_INDEX(sfxId)].importance;
|
||||
}
|
||||
|
||||
channelCount++;
|
||||
|
||||
// There are no channels available, evict the lowest importance
|
||||
if (channelCount == gUsedChannelsPerBank[gSfxChannelLayout][bankId]) {
|
||||
if (gSfxParams[SFX_BANK_SHIFT(req->sfxId)][SFX_INDEX(req->sfxId)].importance >= evictImportance) {
|
||||
index = evictIndex;
|
||||
} else {
|
||||
index = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Process this sfx by refreshing or replacing and existing sfx
|
||||
if (channelCount == gUsedChannelsPerBank[gSfxChannelLayout][bankId]) {
|
||||
sfxParams = &gSfxParams[SFX_BANK_SHIFT(req->sfxId)][SFX_INDEX(req->sfxId)];
|
||||
|
||||
// Interrupt existing sfx and play the new sfx instead.
|
||||
if ((req->sfxId & SFX_FLAG_MASK) || (sfxParams->flags & SFX_FLAG2_FORCE_RESET) ||
|
||||
(index == evictIndex)) {
|
||||
|
||||
// Restore bgm if the sfx about to be replaced has the right flag
|
||||
if ((gSfxBanks[bankId][index].sfxParams & SFX_FLAG_LOWER_VOLUME_BGM) &&
|
||||
(gSfxBanks[bankId][index].state != SFX_STATE_QUEUED)) {
|
||||
AudioSfx_RestoreBgmVolume(gSfxBanks[bankId][index].channelIndex);
|
||||
}
|
||||
|
||||
gSfxBanks[bankId][index].token = req->token;
|
||||
gSfxBanks[bankId][index].sfxId = req->sfxId;
|
||||
gSfxBanks[bankId][index].state = SFX_STATE_QUEUED;
|
||||
gSfxBanks[bankId][index].freshness = 2;
|
||||
gSfxBanks[bankId][index].freqScale = req->freqScale;
|
||||
gSfxBanks[bankId][index].volume = req->volume;
|
||||
gSfxBanks[bankId][index].reverbAdd = req->reverbAdd;
|
||||
gSfxBanks[bankId][index].sfxParams = sfxParams->params;
|
||||
gSfxBanks[bankId][index].sfxFlags = sfxParams->flags;
|
||||
gSfxBanks[bankId][index].sfxImportance = sfxParams->importance;
|
||||
} else if (gSfxBanks[bankId][index].state == SFX_STATE_PLAYING_ONE_FRAME) {
|
||||
// The new sfx is "one-frame" and equals the existing sfx,
|
||||
// continue playing the "one-frame" sfx by setting "SFX_STATE_PLAYING".
|
||||
// This will avoid triggering deletion and get "SFX_STATE_REFRESH"
|
||||
// The state will be set back to "SFX_STATE_PLAYING_ONE_FRAME" at the end of the cycle
|
||||
gSfxBanks[bankId][index].state = SFX_STATE_PLAYING;
|
||||
}
|
||||
// Terminate loop, function is finished (nothing more is processed)
|
||||
index = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (index != 0) {
|
||||
index = gSfxBanks[bankId][index].next;
|
||||
}
|
||||
}
|
||||
|
||||
if ((gSfxBanks[bankId][sSfxBankFreeListStart[bankId]].next != 0xFF) && (index != 0)) {
|
||||
// Allocate from free list
|
||||
index = sSfxBankFreeListStart[bankId];
|
||||
|
||||
entry = &gSfxBanks[bankId][index];
|
||||
entry->posX = &req->pos->x;
|
||||
entry->posY = &req->pos->y;
|
||||
entry->posZ = &req->pos->z;
|
||||
entry->token = req->token;
|
||||
entry->freqScale = req->freqScale;
|
||||
entry->volume = req->volume;
|
||||
entry->reverbAdd = req->reverbAdd;
|
||||
|
||||
sfxParams = &gSfxParams[SFX_BANK_SHIFT(req->sfxId)][SFX_INDEX(req->sfxId)];
|
||||
|
||||
entry->sfxParams = sfxParams->params;
|
||||
entry->sfxFlags = sfxParams->flags;
|
||||
entry->sfxImportance = sfxParams->importance;
|
||||
entry->sfxId = req->sfxId;
|
||||
entry->state = SFX_STATE_QUEUED;
|
||||
entry->freshness = 2;
|
||||
entry->prev = sSfxBankListEnd[bankId];
|
||||
|
||||
gSfxBanks[bankId][sSfxBankListEnd[bankId]].next = sSfxBankFreeListStart[bankId];
|
||||
sSfxBankListEnd[bankId] = sSfxBankFreeListStart[bankId];
|
||||
sSfxBankFreeListStart[bankId] = gSfxBanks[bankId][sSfxBankFreeListStart[bankId]].next;
|
||||
gSfxBanks[bankId][sSfxBankFreeListStart[bankId]].prev = 0xFF;
|
||||
|
||||
entry->next = 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
void AudioSfx_RemoveBankEntry(u8 bankId, u8 entryIndex) {
|
||||
SfxBankEntry* entry = &gSfxBanks[bankId][entryIndex];
|
||||
u8 i;
|
||||
|
||||
if (entry->sfxParams & SFX_FLAG_LOWER_VOLUME_BGM) {
|
||||
AudioSfx_RestoreBgmVolume(entry->channelIndex);
|
||||
}
|
||||
|
||||
if (entryIndex == sSfxBankListEnd[bankId]) {
|
||||
sSfxBankListEnd[bankId] = entry->prev;
|
||||
} else {
|
||||
gSfxBanks[bankId][entry->next].prev = entry->prev;
|
||||
}
|
||||
|
||||
gSfxBanks[bankId][entry->prev].next = entry->next;
|
||||
entry->next = sSfxBankFreeListStart[bankId];
|
||||
entry->prev = 0xFF;
|
||||
gSfxBanks[bankId][sSfxBankFreeListStart[bankId]].prev = entryIndex;
|
||||
sSfxBankFreeListStart[bankId] = entryIndex;
|
||||
entry->state = SFX_STATE_EMPTY;
|
||||
|
||||
for (i = 0; i < gChannelsPerBank[gSfxChannelLayout][bankId]; i++) {
|
||||
if (gActiveSfx[bankId][i].entryIndex == entryIndex) {
|
||||
gActiveSfx[bankId][i].entryIndex = 0xFF;
|
||||
i = gChannelsPerBank[gSfxChannelLayout][bankId];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AudioSfx_ChooseActiveSfx(u8 bankId) {
|
||||
u8 numChosenSfx = 0;
|
||||
u8 numChannels;
|
||||
u8 entryIndex;
|
||||
u8 i;
|
||||
u8 j;
|
||||
u8 k;
|
||||
u8 sfxImportance;
|
||||
u8 needNewSfx;
|
||||
u8 chosenEntryIndex;
|
||||
s32 pad;
|
||||
SfxBankEntry* entry;
|
||||
ActiveSfx chosenSfx[MAX_CHANNELS_PER_BANK];
|
||||
ActiveSfx* activeSfx;
|
||||
f32 entryPosY;
|
||||
f32 entryPosX;
|
||||
|
||||
for (i = 0; i < MAX_CHANNELS_PER_BANK; i++) {
|
||||
chosenSfx[i].priority = 0x7FFFFFFF;
|
||||
chosenSfx[i].entryIndex = 0xFF;
|
||||
}
|
||||
|
||||
entryIndex = gSfxBanks[bankId][0].next;
|
||||
k = 0;
|
||||
|
||||
// Delete stale sfx and prioritize remaining sfx into the gActiveSfx arrays
|
||||
while (entryIndex != 0xFF) {
|
||||
|
||||
// Update the freshness for an "all-frame" sfx if it is still queued
|
||||
if ((gSfxBanks[bankId][entryIndex].state == SFX_STATE_QUEUED) &&
|
||||
(gSfxBanks[bankId][entryIndex].sfxId & SFX_FLAG_MASK)) {
|
||||
gSfxBanks[bankId][entryIndex].freshness--;
|
||||
|
||||
// If a "one-frame" sfx is still in "SFX_STATE_PLAYING_ONE_FRAME", then remove the sfx
|
||||
} else if (!(gSfxBanks[bankId][entryIndex].sfxId & SFX_FLAG_MASK) &&
|
||||
(gSfxBanks[bankId][entryIndex].state == SFX_STATE_PLAYING_ONE_FRAME)) {
|
||||
// CHAN_UPD_SCRIPT_IO (ioPort 0, force stop sfx in seq 0)
|
||||
AudioThread_QueueCmdS8(
|
||||
(0x6 << 24) | (SEQ_PLAYER_SFX << 16) | (gSfxBanks[bankId][entryIndex].channelIndex << 8), 0);
|
||||
AudioSfx_RemoveBankEntry(bankId, entryIndex);
|
||||
}
|
||||
|
||||
// If a "all-frame" sfx goes 2 frames in the "queued" state
|
||||
// (because it is too low priority), then remove the sfx
|
||||
if (gSfxBanks[bankId][entryIndex].freshness == 0) {
|
||||
AudioSfx_RemoveBankEntry(bankId, entryIndex);
|
||||
} else if (gSfxBanks[bankId][entryIndex].state != SFX_STATE_EMPTY) {
|
||||
// process the entry
|
||||
entry = &gSfxBanks[bankId][entryIndex];
|
||||
|
||||
// Recompute distSq each frame since the sound's position may have changed
|
||||
// (later converted into dist)
|
||||
if (&gSfxDefaultPos.x == entry[0].posX) {
|
||||
entry->dist = 0.0f;
|
||||
} else {
|
||||
entryPosY = *entry->posY * 1;
|
||||
entryPosX = *entry->posX * 0.5f;
|
||||
entry->dist = (SQ(entryPosX) + SQ(entryPosY) + SQ(*entry->posZ)) / 10.0f;
|
||||
}
|
||||
|
||||
// Recompute priority, possibly based on sfx position relative to the camera.
|
||||
// (Note that the priority is the opposite of importance; lower is more preserved)
|
||||
sfxImportance = entry->sfxImportance;
|
||||
|
||||
if (entry->sfxParams & SFX_FLAG_PRIORITY_NO_DIST) {
|
||||
// Priority is independent of distance
|
||||
entry->priority = SQ(0xFF - sfxImportance) * SQ(76);
|
||||
} else {
|
||||
// Priority value increases with distance (more likely to eject)
|
||||
if (entry->dist > 0x7FFFFFD0) {
|
||||
// max distance
|
||||
entry->dist = 0x70000008;
|
||||
}
|
||||
|
||||
entry->priority = (u32)entry->dist + (SQ(0xFF - sfxImportance) * SQ(76));
|
||||
if (*entry->posZ < 0.0f) {
|
||||
entry->priority += (s32)(-*entry->posZ * 6.0f);
|
||||
}
|
||||
}
|
||||
|
||||
// Sfx is too far away, do not consider for chosen sfx
|
||||
if (entry->dist > SQ(1e5f)) {
|
||||
|
||||
// If too far away and also playing, stop playing
|
||||
if (entry->state == SFX_STATE_PLAYING) {
|
||||
// CHAN_UPD_SCRIPT_IO (ioPort 0, force stop sfx in seq 0)
|
||||
AudioThread_QueueCmdS8((0x6 << 24) | (SEQ_PLAYER_SFX << 16) | (entry->channelIndex << 8), 0);
|
||||
if (entry->sfxId & SFX_FLAG_MASK) {
|
||||
AudioSfx_RemoveBankEntry(bankId, entryIndex);
|
||||
entryIndex = k;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Loop through all channels allocated to a specific bank
|
||||
// Choose which sfx from gSfxBanks to play
|
||||
// This includes all sfx requests and sfx already playing
|
||||
// Sort all current sfx entries in gSfxBanks by priority
|
||||
// This is where the "active" sfx are chosen
|
||||
numChannels = gChannelsPerBank[gSfxChannelLayout][bankId];
|
||||
|
||||
for (i = 0; i < numChannels; i++) {
|
||||
// Sort all sfx entries by priority
|
||||
if (chosenSfx[i].priority >= entry->priority) {
|
||||
// Update the number of sfx to attampt to play
|
||||
if (numChosenSfx < gChannelsPerBank[gSfxChannelLayout][bankId]) {
|
||||
numChosenSfx++;
|
||||
}
|
||||
|
||||
for (j = numChannels - 1; j > i; j--) {
|
||||
chosenSfx[j].priority = chosenSfx[j - 1].priority;
|
||||
chosenSfx[j].entryIndex = chosenSfx[j - 1].entryIndex;
|
||||
}
|
||||
|
||||
chosenSfx[i].priority = entry->priority;
|
||||
chosenSfx[i].entryIndex = entryIndex;
|
||||
i = numChannels; // make this the last pass through the loop, here equivalent to "break"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
k = entryIndex;
|
||||
}
|
||||
|
||||
entryIndex = gSfxBanks[bankId][k].next;
|
||||
}
|
||||
|
||||
// If a sfx is chosen, update its state
|
||||
for (i = 0; i < numChosenSfx; i++) {
|
||||
entry = &gSfxBanks[bankId][chosenSfx[i].entryIndex];
|
||||
|
||||
if (entry->state == SFX_STATE_QUEUED) {
|
||||
// sfx is a new entry
|
||||
entry->state = SFX_STATE_READY;
|
||||
} else if (entry->state == SFX_STATE_PLAYING) {
|
||||
// sfx is already playing
|
||||
entry->state = SFX_STATE_PLAYING_REFRESH;
|
||||
}
|
||||
}
|
||||
|
||||
// Apply the chosenSfx to the activeSfx in each channel
|
||||
numChannels = gChannelsPerBank[gSfxChannelLayout][bankId];
|
||||
for (i = 0; i < numChannels; i++) {
|
||||
needNewSfx = false;
|
||||
activeSfx = &gActiveSfx[bankId][i];
|
||||
|
||||
// Check if a sfx is already in the channel
|
||||
if (activeSfx->entryIndex == 0xFF) {
|
||||
// No sfx playing in the channel
|
||||
// Available for use
|
||||
needNewSfx = true;
|
||||
} else {
|
||||
// The channel is already playing a sfx
|
||||
// Get the entry of the sfx playing
|
||||
entry = &gSfxBanks[bankId][activeSfx[0].entryIndex];
|
||||
|
||||
// Check the state of the sfx playing
|
||||
if (entry->state == SFX_STATE_PLAYING) {
|
||||
if (entry->sfxId & SFX_FLAG_MASK) {
|
||||
// For "all-frames" sfx, remove the entry
|
||||
AudioSfx_RemoveBankEntry(bankId, activeSfx->entryIndex);
|
||||
} else {
|
||||
// For "one-frame" sfx, reset the state to queued
|
||||
entry->state = SFX_STATE_QUEUED;
|
||||
entry->freshness = 0x80;
|
||||
}
|
||||
needNewSfx = true;
|
||||
} else if (entry->state == SFX_STATE_EMPTY) {
|
||||
// The sfx already in the channel is empty
|
||||
// Can replace the sfx
|
||||
activeSfx->entryIndex = 0xFF;
|
||||
needNewSfx = true;
|
||||
} else {
|
||||
// Sfx is already playing as it should, nothing to do.
|
||||
for (j = 0; j < numChannels; j++) {
|
||||
if (activeSfx->entryIndex == chosenSfx[j].entryIndex) {
|
||||
chosenSfx[j].entryIndex = 0xFF;
|
||||
j = numChannels;
|
||||
}
|
||||
}
|
||||
|
||||
numChosenSfx--;
|
||||
}
|
||||
}
|
||||
|
||||
// enter the new sfx into the activeSfx
|
||||
if (needNewSfx == true) {
|
||||
for (j = 0; j < numChannels; j++) {
|
||||
chosenEntryIndex = chosenSfx[j].entryIndex;
|
||||
if ((chosenEntryIndex != 0xFF) &&
|
||||
(gSfxBanks[bankId][chosenEntryIndex].state != SFX_STATE_PLAYING_REFRESH)) {
|
||||
for (k = 0; k < numChannels; k++) {
|
||||
if (chosenEntryIndex == gActiveSfx[bankId][k].entryIndex) {
|
||||
needNewSfx = false;
|
||||
k = numChannels; // "break; i.e. force for-loop to end"
|
||||
}
|
||||
}
|
||||
|
||||
if (needNewSfx == true) {
|
||||
activeSfx->entryIndex = chosenEntryIndex;
|
||||
chosenSfx[j].entryIndex = 0xFF;
|
||||
j = numChannels + 1;
|
||||
numChosenSfx--;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (j == numChannels) {
|
||||
// nothing found
|
||||
activeSfx->entryIndex = 0xFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AudioSfx_PlayActiveSfx(u8 bankId) {
|
||||
u8 entryIndex;
|
||||
SequenceChannel* channel;
|
||||
SfxBankEntry* entry;
|
||||
u8 i;
|
||||
u8 ioPort5Data;
|
||||
|
||||
for (i = 0; i < gChannelsPerBank[gSfxChannelLayout][bankId]; i++) {
|
||||
entryIndex = gActiveSfx[bankId][i].entryIndex;
|
||||
// If entry is not empty
|
||||
if (entryIndex != 0xFF) {
|
||||
entry = &gSfxBanks[bankId][entryIndex];
|
||||
channel = gAudioContext.seqPlayers[SEQ_PLAYER_SFX].channels[sCurSfxPlayerChannelIndex];
|
||||
|
||||
if (entry->state == SFX_STATE_READY) {
|
||||
// Initialize a sfx (new sfx request)
|
||||
entry->channelIndex = sCurSfxPlayerChannelIndex;
|
||||
if (entry->sfxParams & SFX_FLAG_LOWER_VOLUME_BGM) {
|
||||
AudioSfx_LowerBgmVolume(sCurSfxPlayerChannelIndex);
|
||||
}
|
||||
|
||||
// Add noise that will offset the frequency of the sfx
|
||||
if ((entry->sfxParams & SFX_PARAM_RAND_FREQ_RAISE_MASK) != (0 << SFX_PARAM_RAND_FREQ_RAISE_SHIFT)) {
|
||||
switch (entry->sfxParams & SFX_PARAM_RAND_FREQ_RAISE_MASK) {
|
||||
case (1 << SFX_PARAM_RAND_FREQ_RAISE_SHIFT):
|
||||
entry->randFreq = AudioThread_NextRandom() & 0xF;
|
||||
break;
|
||||
|
||||
case (2 << SFX_PARAM_RAND_FREQ_RAISE_SHIFT):
|
||||
entry->randFreq = AudioThread_NextRandom() & 0x1F;
|
||||
break;
|
||||
|
||||
case (3 << SFX_PARAM_RAND_FREQ_RAISE_SHIFT):
|
||||
entry->randFreq = AudioThread_NextRandom() & 0x3F;
|
||||
break;
|
||||
|
||||
default:
|
||||
entry->randFreq = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate all the properties of sfx
|
||||
AudioSfx_SetProperties(bankId, entryIndex, sCurSfxPlayerChannelIndex);
|
||||
|
||||
// CHAN_UPD_SCRIPT_IO (ioPort 0, enable the sfx to play in seq 0)
|
||||
AudioThread_QueueCmdS8((0x6 << 24) | (SEQ_PLAYER_SFX << 16) | ((sCurSfxPlayerChannelIndex & 0xFF) << 8),
|
||||
1);
|
||||
|
||||
// CHAN_UPD_SCRIPT_IO (ioPort 4, write the lower bits sfx index to seq 0 so it can find the right code
|
||||
// to execute)
|
||||
AudioThread_QueueCmdS8((0x6 << 24) | (SEQ_PLAYER_SFX << 16) |
|
||||
((sCurSfxPlayerChannelIndex & 0xFF) << 8) | 4,
|
||||
entry->sfxId & 0xFF);
|
||||
|
||||
// If the sfx bank has more than 255 entries (greater than a u8 can store),
|
||||
// then store the Id in upper and lower bits
|
||||
if (gIsLargeSfxBank[bankId]) {
|
||||
// Store upper bits
|
||||
ioPort5Data = ((u8)((entry->sfxId & 0x300) >> 7) + (u8)((entry->sfxId & 0xFF) >> 7));
|
||||
} else {
|
||||
ioPort5Data = 0;
|
||||
}
|
||||
|
||||
if ((entry->sfxParams & SFX_FLAG_8) && (entry->freshness == 0x80)) {
|
||||
ioPort5Data += 0x80;
|
||||
}
|
||||
|
||||
if (D_801D6608[bankId]) {
|
||||
// CHAN_UPD_SCRIPT_IO (ioPort 5, write the upper bits sfx index and a flag to seq 0, for banks with
|
||||
// > 0xFF entries)
|
||||
AudioThread_QueueCmdS8((0x6 << 24) | (SEQ_PLAYER_SFX << 16) |
|
||||
((sCurSfxPlayerChannelIndex & 0xFF) << 8) | 5,
|
||||
ioPort5Data);
|
||||
}
|
||||
|
||||
// Update playing state
|
||||
if (entry->sfxId & SFX_FLAG_MASK) {
|
||||
// "all-frames" sfx
|
||||
entry->state = SFX_STATE_PLAYING;
|
||||
} else {
|
||||
// "one-frame" sfx
|
||||
entry->state = SFX_STATE_PLAYING_ONE_FRAME;
|
||||
}
|
||||
} else if ((u8)channel->soundScriptIO[1] == 0xFF) {
|
||||
// Signal from seq 0 that the sfx is finished playing. Remove entry
|
||||
AudioSfx_RemoveBankEntry(bankId, entryIndex);
|
||||
} else if (entry->state == SFX_STATE_PLAYING_REFRESH) {
|
||||
// Sfx is playing but a refresh is requested
|
||||
AudioSfx_SetProperties(bankId, entryIndex, sCurSfxPlayerChannelIndex);
|
||||
|
||||
// Update playing state
|
||||
if (entry->sfxId & SFX_FLAG_MASK) {
|
||||
// "all-frames" sfx
|
||||
entry->state = SFX_STATE_PLAYING;
|
||||
} else {
|
||||
// "one-frame" sfx
|
||||
entry->state = SFX_STATE_PLAYING_ONE_FRAME;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sCurSfxPlayerChannelIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
void AudioSfx_StopByBank(u8 bankId) {
|
||||
SfxBankEntry* entry;
|
||||
s32 pad;
|
||||
SfxBankEntry entryToRemove;
|
||||
u8 entryIndex = gSfxBanks[bankId][0].next;
|
||||
|
||||
while (entryIndex != 0xFF) {
|
||||
entry = &gSfxBanks[bankId][entryIndex];
|
||||
if (entry->state >= SFX_STATE_PLAYING_REFRESH) {
|
||||
AudioThread_QueueCmdS8((0x6 << 24) | (SEQ_PLAYER_SFX << 16) | ((entry->channelIndex & 0xFF) << 8), 0);
|
||||
}
|
||||
|
||||
if (entry->state != SFX_STATE_EMPTY) {
|
||||
AudioSfx_RemoveBankEntry(bankId, entryIndex);
|
||||
}
|
||||
entryIndex = gSfxBanks[bankId][0].next;
|
||||
}
|
||||
|
||||
entryToRemove.sfxId = bankId << 12;
|
||||
AudioSfx_RemoveMatchingRequests(SFX_RM_REQ_BY_BANK, &entryToRemove);
|
||||
}
|
||||
|
||||
void AudioSfx_StopByPosAndBankImpl(u8 bankId, Vec3f* pos) {
|
||||
SfxBankEntry* entry;
|
||||
u8 entryIndex = gSfxBanks[bankId][0].next;
|
||||
u8 prevEntryIndex = 0;
|
||||
|
||||
while (entryIndex != 0xFF) {
|
||||
entry = &gSfxBanks[bankId][entryIndex];
|
||||
if (entry->posX == &pos->x) {
|
||||
if (entry->state >= SFX_STATE_PLAYING_REFRESH) {
|
||||
AudioThread_QueueCmdS8((0x6 << 24) | (SEQ_PLAYER_SFX << 16) | ((entry->channelIndex & 0xFF) << 8), 0);
|
||||
}
|
||||
|
||||
if (entry->state != SFX_STATE_EMPTY) {
|
||||
AudioSfx_RemoveBankEntry(bankId, entryIndex);
|
||||
}
|
||||
} else {
|
||||
prevEntryIndex = entryIndex;
|
||||
}
|
||||
|
||||
entryIndex = gSfxBanks[bankId][prevEntryIndex].next;
|
||||
}
|
||||
}
|
||||
|
||||
void AudioSfx_StopByPosAndBank(u8 bankId, Vec3f* pos) {
|
||||
SfxBankEntry entryToRemove;
|
||||
|
||||
AudioSfx_StopByPosAndBankImpl(bankId, pos);
|
||||
entryToRemove.sfxId = bankId << 12;
|
||||
entryToRemove.posX = &pos->x;
|
||||
AudioSfx_RemoveMatchingRequests(SFX_RM_REQ_BY_POS_AND_BANK, &entryToRemove);
|
||||
}
|
||||
|
||||
void AudioSfx_StopByPos(Vec3f* pos) {
|
||||
u8 bankId;
|
||||
SfxBankEntry entryToRemove;
|
||||
|
||||
for (bankId = 0; bankId < ARRAY_COUNT(gSfxBanks); bankId++) {
|
||||
AudioSfx_StopByPosAndBankImpl(bankId, pos);
|
||||
}
|
||||
|
||||
entryToRemove.posX = &pos->x;
|
||||
AudioSfx_RemoveMatchingRequests(SFX_RM_REQ_BY_POS, &entryToRemove);
|
||||
}
|
||||
|
||||
void AudioSfx_StopByPosAndId(Vec3f* pos, u16 sfxId) {
|
||||
SfxBankEntry* entry;
|
||||
u8 entryIndex = gSfxBanks[SFX_BANK(sfxId)][0].next;
|
||||
u8 prevEntryIndex = 0;
|
||||
SfxBankEntry entryToRemove;
|
||||
|
||||
while (entryIndex != 0xFF) {
|
||||
entry = &gSfxBanks[SFX_BANK(sfxId)][entryIndex];
|
||||
if ((entry->posX == &pos->x) && (entry->sfxId == sfxId)) {
|
||||
if (entry->state >= SFX_STATE_PLAYING_REFRESH) {
|
||||
AudioThread_QueueCmdS8((0x6 << 24) | (SEQ_PLAYER_SFX << 16) | ((entry->channelIndex & 0xFF) << 8), 0);
|
||||
}
|
||||
|
||||
if (entry->state != SFX_STATE_EMPTY) {
|
||||
AudioSfx_RemoveBankEntry(SFX_BANK(sfxId), entryIndex);
|
||||
}
|
||||
entryIndex = 0xFF;
|
||||
} else {
|
||||
prevEntryIndex = entryIndex;
|
||||
}
|
||||
|
||||
if (entryIndex != 0xFF) {
|
||||
entryIndex = gSfxBanks[SFX_BANK(sfxId)][prevEntryIndex].next;
|
||||
}
|
||||
}
|
||||
|
||||
entryToRemove.posX = &pos->x;
|
||||
entryToRemove.sfxId = sfxId;
|
||||
AudioSfx_RemoveMatchingRequests(SFX_RM_REQ_BY_POS_AND_ID, &entryToRemove);
|
||||
}
|
||||
|
||||
void AudioSfx_StopByTokenAndId(u8 token, u16 sfxId) {
|
||||
SfxBankEntry* entry;
|
||||
u8 entryIndex = gSfxBanks[SFX_BANK(sfxId)][0].next;
|
||||
u8 prevEntryIndex = 0;
|
||||
SfxBankEntry entryToRemove;
|
||||
|
||||
while (entryIndex != 0xFF) {
|
||||
entry = &gSfxBanks[SFX_BANK(sfxId)][entryIndex];
|
||||
if ((entry->token == token) && (entry->sfxId == sfxId)) {
|
||||
if (entry->state >= SFX_STATE_PLAYING_REFRESH) {
|
||||
AudioThread_QueueCmdS8((0x6 << 24) | (SEQ_PLAYER_SFX << 16) | ((entry->channelIndex & 0xFF) << 8), 0);
|
||||
}
|
||||
|
||||
if (entry->state != SFX_STATE_EMPTY) {
|
||||
AudioSfx_RemoveBankEntry(SFX_BANK(sfxId), entryIndex);
|
||||
}
|
||||
} else {
|
||||
prevEntryIndex = entryIndex;
|
||||
}
|
||||
|
||||
if (entryIndex != 0xFF) {
|
||||
entryIndex = gSfxBanks[SFX_BANK(sfxId)][prevEntryIndex].next;
|
||||
}
|
||||
}
|
||||
|
||||
entryToRemove.token = token;
|
||||
entryToRemove.sfxId = sfxId;
|
||||
AudioSfx_RemoveMatchingRequests(SFX_RM_REQ_BY_TOKEN_AND_ID, &entryToRemove);
|
||||
}
|
||||
|
||||
void AudioSfx_StopById(u32 sfxId) {
|
||||
SfxBankEntry* entry;
|
||||
u8 entryIndex = gSfxBanks[SFX_BANK(sfxId)][0].next;
|
||||
u8 prevEntryIndex = 0;
|
||||
SfxBankEntry entryToRemove;
|
||||
|
||||
while (entryIndex != 0xFF) {
|
||||
entry = &gSfxBanks[SFX_BANK(sfxId)][entryIndex];
|
||||
if (entry->sfxId == sfxId) {
|
||||
if (entry->state >= SFX_STATE_PLAYING_REFRESH) {
|
||||
AudioThread_QueueCmdS8((0x6 << 24) | (SEQ_PLAYER_SFX << 16) | ((entry->channelIndex & 0xFF) << 8), 0);
|
||||
}
|
||||
if (entry->state != SFX_STATE_EMPTY) {
|
||||
AudioSfx_RemoveBankEntry(SFX_BANK(sfxId), entryIndex);
|
||||
}
|
||||
} else {
|
||||
prevEntryIndex = entryIndex;
|
||||
}
|
||||
|
||||
entryIndex = gSfxBanks[SFX_BANK(sfxId)][prevEntryIndex].next;
|
||||
}
|
||||
|
||||
entryToRemove.sfxId = sfxId;
|
||||
AudioSfx_RemoveMatchingRequests(SFX_RM_REQ_BY_ID, &entryToRemove);
|
||||
}
|
||||
|
||||
void AudioSfx_ProcessRequests(void) {
|
||||
if (gAudioContext.seqPlayers[SEQ_PLAYER_SFX].enabled) {
|
||||
while (sSfxRequestWriteIndex != sSfxRequestReadIndex) {
|
||||
AudioSfx_ProcessRequest();
|
||||
sSfxRequestReadIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unused
|
||||
*/
|
||||
void AudioSfx_SetBankLerp(u8 bankId, u8 target, u16 delay) {
|
||||
if (delay == 0) {
|
||||
delay++;
|
||||
}
|
||||
|
||||
sSfxBankLerp[bankId].target = target / 127.0f;
|
||||
sSfxBankLerp[bankId].remainingFrames = delay;
|
||||
sSfxBankLerp[bankId].step = ((sSfxBankLerp[bankId].value - sSfxBankLerp[bankId].target) / delay);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unused
|
||||
*/
|
||||
void AudioSfx_StepBankLerp(u8 bankId) {
|
||||
if (sSfxBankLerp[bankId].remainingFrames != 0) {
|
||||
sSfxBankLerp[bankId].remainingFrames--;
|
||||
|
||||
if (sSfxBankLerp[bankId].remainingFrames != 0) {
|
||||
sSfxBankLerp[bankId].value -= sSfxBankLerp[bankId].step;
|
||||
} else {
|
||||
sSfxBankLerp[bankId].value = sSfxBankLerp[bankId].target;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AudioSfx_ProcessActiveSfx(void) {
|
||||
u8 bankId;
|
||||
|
||||
if (gAudioContext.seqPlayers[SEQ_PLAYER_SFX].enabled) {
|
||||
sCurSfxPlayerChannelIndex = 0;
|
||||
|
||||
for (bankId = 0; bankId < ARRAY_COUNT(gSfxBanks); bankId++) {
|
||||
AudioSfx_ChooseActiveSfx(bankId);
|
||||
AudioSfx_PlayActiveSfx(bankId);
|
||||
AudioSfx_StepBankLerp(bankId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
u8 AudioSfx_IsPlaying(u32 sfxId) {
|
||||
SfxBankEntry* entry;
|
||||
u8 entryIndex = gSfxBanks[SFX_BANK(sfxId)][0].next;
|
||||
|
||||
while (entryIndex != 0xFF) {
|
||||
entry = &gSfxBanks[SFX_BANK(sfxId)][entryIndex];
|
||||
if (entry->sfxId == sfxId) {
|
||||
return true;
|
||||
}
|
||||
entryIndex = entry->next;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void AudioSfx_Reset(void) {
|
||||
u8 bankId;
|
||||
u8 i;
|
||||
u8 entryIndex;
|
||||
|
||||
sSfxRequestWriteIndex = 0;
|
||||
sSfxRequestReadIndex = 0;
|
||||
sSfxChannelLowVolumeFlag = 0;
|
||||
|
||||
for (bankId = 0; bankId < ARRAY_COUNT(gSfxBanks); bankId++) {
|
||||
sSfxBankListEnd[bankId] = 0;
|
||||
sSfxBankFreeListStart[bankId] = 1;
|
||||
sSfxBankUnused[bankId] = 0;
|
||||
gSfxBankMuted[bankId] = false;
|
||||
sSfxBankLerp[bankId].value = 1.0f;
|
||||
sSfxBankLerp[bankId].remainingFrames = 0;
|
||||
}
|
||||
|
||||
for (bankId = 0; bankId < ARRAY_COUNT(gSfxBanks); bankId++) {
|
||||
for (i = 0; i < MAX_CHANNELS_PER_BANK; i++) {
|
||||
gActiveSfx[bankId][i].entryIndex = 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
for (bankId = 0; bankId < ARRAY_COUNT(gSfxBanks); bankId++) {
|
||||
gSfxBanks[bankId][0].prev = 0xFF;
|
||||
gSfxBanks[bankId][0].next = 0xFF;
|
||||
|
||||
for (i = 1; i < sSfxBankSizes[bankId] - 1; i++) {
|
||||
gSfxBanks[bankId][i].prev = i - 1;
|
||||
gSfxBanks[bankId][i].next = i + 1;
|
||||
}
|
||||
|
||||
gSfxBanks[bankId][i].prev = i - 1;
|
||||
gSfxBanks[bankId][i].next = 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "global.h"
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_801A7B10/func_801A7B10.s")
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_801A7B10/Audio_StartSequence.s")
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_801A7B10/func_801A7D04.s")
|
||||
|
||||
|
||||
+1
-1
@@ -78,7 +78,7 @@ void AudioMgr_ThreadEntry(void* arg) {
|
||||
s16* msg = NULL;
|
||||
s32 exit;
|
||||
|
||||
func_801A4C30();
|
||||
Audio_Init();
|
||||
AudioLoad_SetDmaHandler(DmaMgr_DmaHandler);
|
||||
func_801A4D00();
|
||||
osSendMesg(&audioMgr->lockMsgQ, NULL, OS_MESG_BLOCK);
|
||||
|
||||
@@ -9,7 +9,7 @@ void AudioMgr_StopAllSfxExceptSystem(void) {
|
||||
|
||||
for (bankIdPtr = sSfxBankIds; bankIdPtr < (sSfxBankIds + ARRAY_COUNT(sSfxBankIds)); bankIdPtr++) {
|
||||
if (*bankIdPtr != BANK_SYSTEM) {
|
||||
func_801A7084(*bankIdPtr);
|
||||
AudioSfx_StopByBank(*bankIdPtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+5
-3
@@ -2127,7 +2127,8 @@ void func_800B8E58(Player* player, u16 sfxId) {
|
||||
if (player->currentMask == PLAYER_MASK_GIANT) {
|
||||
func_8019F170(&player->actor.projectedPos, sfxId);
|
||||
} else {
|
||||
Audio_PlaySfxGeneral(sfxId, &player->actor.projectedPos, 4, &D_801DB4B0, &D_801DB4B0, &gSfxDefaultReverb);
|
||||
AudioSfx_PlaySfx(sfxId, &player->actor.projectedPos, 4, &gSfxDefaultFreqAndVolScale,
|
||||
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2567,7 +2568,8 @@ void func_800B9D1C(Actor* actor) {
|
||||
|
||||
if (sfxId != 0) {
|
||||
if (actor->audioFlags & 2) {
|
||||
Audio_PlaySfxGeneral(sfxId, &actor->projectedPos, 4, &D_801DB4B0, &D_801DB4B0, &gSfxDefaultReverb);
|
||||
AudioSfx_PlaySfx(sfxId, &actor->projectedPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
|
||||
&gSfxDefaultReverb);
|
||||
} else if (actor->audioFlags & 4) {
|
||||
play_sound(sfxId);
|
||||
} else if (actor->audioFlags & 8) {
|
||||
@@ -3338,7 +3340,7 @@ Actor* Actor_Delete(ActorContext* actorCtx, Actor* actor, PlayState* play) {
|
||||
actorCtx->targetContext.bgmEnemy = NULL;
|
||||
}
|
||||
|
||||
Audio_StopSfxByPos(&actor->projectedPos);
|
||||
AudioSfx_StopByPos(&actor->projectedPos);
|
||||
Actor_Destroy(actor, play);
|
||||
|
||||
newHead = Actor_RemoveFromCategory(play, actorCtx, actor);
|
||||
|
||||
@@ -59,11 +59,11 @@ EffectSs* EffectSS_GetTable() {
|
||||
|
||||
void EffectSS_Delete(EffectSs* effectSs) {
|
||||
if (effectSs->flags & 2) {
|
||||
Audio_StopSfxByPos(&effectSs->pos);
|
||||
AudioSfx_StopByPos(&effectSs->pos);
|
||||
}
|
||||
|
||||
if (effectSs->flags & 4) {
|
||||
Audio_StopSfxByPos(&effectSs->vec);
|
||||
AudioSfx_StopByPos(&effectSs->vec);
|
||||
}
|
||||
|
||||
EffectSS_ResetEntry(effectSs);
|
||||
|
||||
@@ -16,7 +16,7 @@ void SoundSource_UpdateAll(PlayState* play) {
|
||||
for (i = 0; i < ARRAY_COUNT(play->soundSources); i++) {
|
||||
if (source->countdown != 0) {
|
||||
if (DECR(source->countdown) == 0) {
|
||||
Audio_StopSfxByPos(&source->projectedPos);
|
||||
AudioSfx_StopByPos(&source->projectedPos);
|
||||
} else {
|
||||
SkinMatrix_Vec3fMtxFMultXYZ(&play->viewProjectionMtxF, &source->worldPos, &source->projectedPos);
|
||||
if (source->playSfxEachFrame) {
|
||||
@@ -54,7 +54,7 @@ void SoundSource_Add(PlayState* play, Vec3f* worldPos, u32 duration, u16 sfxId,
|
||||
// If no sound source is available, replace the sound source with the smallest remaining countdown
|
||||
if (i >= ARRAY_COUNT(play->soundSources)) {
|
||||
source = backupSource;
|
||||
Audio_StopSfxByPos(&source->projectedPos);
|
||||
AudioSfx_StopByPos(&source->projectedPos);
|
||||
}
|
||||
|
||||
source->worldPos = *worldPos;
|
||||
|
||||
Reference in New Issue
Block a user