mm/src/audio/code_8019AF00.c

6486 lines
224 KiB
C

#include "global.h"
#include "z64voice.h"
typedef struct {
/* 0x0 */ s8 x;
/* 0x1 */ s8 y;
} OcarinaControlStick; // size = 0x2
typedef struct {
/* 0x0 */ Vec3f* pos;
/* 0x4 */ f32 freqScale;
/* 0x8 */ s8 reverbAdd;
} SfxSettings; // size = 0xC
typedef struct {
/* 0x0 */ f32 volume;
/* 0x4 */ f32 freqScale;
/* 0x8 */ s8 reverb;
/* 0x9 */ s8 panSigned;
/* 0xA */ s8 stereoBits;
/* 0xB */ u8 filter;
/* 0xC */ u8 combFilterGain;
/* 0xD */ u8 zVolume;
} SfxChannelState; // size = 0x10
typedef enum {
/* 0x0 */ SFX_CHANNEL_PLAYER0, // SfxPlayerBank
/* 0x1 */ SFX_CHANNEL_PLAYER1,
/* 0x2 */ SFX_CHANNEL_PLAYER2,
/* 0x3 */ SFX_CHANNEL_ITEM0, // SfxItemBank
/* 0x4 */ SFX_CHANNEL_ITEM1,
/* 0x5 */ SFX_CHANNEL_ENV0, // SfxEnvironmentBank
/* 0x6 */ SFX_CHANNEL_ENV1,
/* 0x7 */ SFX_CHANNEL_ENV2,
/* 0x8 */ SFX_CHANNEL_ENEMY0, // SfxEnemyBank
/* 0x9 */ SFX_CHANNEL_ENEMY1,
/* 0xA */ SFX_CHANNEL_ENEMY2,
/* 0xB */ SFX_CHANNEL_SYSTEM0, // SfxSystemBank
/* 0xC */ SFX_CHANNEL_SYSTEM1,
/* 0xD */ SFX_CHANNEL_OCARINA, // SfxOcarinaBank
/* 0xE */ SFX_CHANNEL_VOICE0, // SfxVoiceBank
/* 0xF */ SFX_CHANNEL_VOICE1
} SfxChannelIndex; // seqPlayerIndex = 2
// Global IO ports for sequences, 8 global ports per seqPlayer
typedef enum {
/* 0x0 */ SEQ_PLAYER_IO_PORT_0,
/* 0x1 */ SEQ_PLAYER_IO_PORT_1,
/* 0x2 */ SEQ_PLAYER_IO_PORT_2,
/* 0x3 */ SEQ_PLAYER_IO_PORT_3,
/* 0x4 */ SEQ_PLAYER_IO_PORT_4,
/* 0x5 */ SEQ_PLAYER_IO_PORT_5,
/* 0x6 */ SEQ_PLAYER_IO_PORT_6,
/* 0x7 */ SEQ_PLAYER_IO_PORT_7
} SeqPlayerIOPort;
typedef struct {
/* 0x0 */ f32 value;
/* 0x4 */ f32 target;
/* 0x8 */ f32 step;
/* 0xC */ s32 remainingFrames;
} FreqLerp; // size = 0x10
s32 AudioOcarina_MemoryGameNextNote(void);
void AudioSfx_ProcessSfxSettings(void);
void Audio_UpdateSfxVolumeTransition(void);
void Audio_StepFreqLerp(FreqLerp* lerp);
s32 Audio_SetGanonsTowerBgmVolume(u8 targetVolume);
void Audio_StartMorningSceneSequence(u16 seqId);
void Audio_StartSceneSequence(u16 seqId);
void Audio_PlaySequenceWithSeqPlayerIO(s8 seqPlayerIndex, u16 seqId, u8 fadeInDuration, s8 ioPort, u8 ioData);
void Audio_SetSfxReverbIndexExceptOcarinaBank(u8 reverbIndex);
void Audio_MuteBgmPlayersForFanfare(void);
void Audio_PlayAmbience(u8 ambienceId);
void Audio_SetSfxVolumeExceptSystemAndOcarinaBanks(u8 volume);
void Audio_UpdateRiverSoundVolumes(void);
void Audio_UpdateObjSoundProperties(void);
void Audio_UpdateObjSoundFanfare(void);
void Audio_UpdateSubBgmAtPos(void);
void Audio_UpdateSequenceAtPos(void);
void Audio_UpdateSceneSequenceResumePoint(void);
void Audio_UpdateFanfare(void);
void Audio_UpdatePauseState(void);
void Audio_ResetRequestedSceneSeqId(void);
// Sfx bss
SfxSettings sSfxSettings[8];
u8 sSfxSettingsFlags;
f32 sTwoSemitonesLoweredFreq;
s8 sSfxIncreasedReverb;
f32 sSfxSyncedVolume;
f32 sSfxSyncedVolumeForMetalEffects;
f32 sSfxSyncedFreq;
FreqLerp sRiverFreqScaleLerp;
FreqLerp sWaterfallFreqScaleLerp;
f32 sSfxAdjustedFreq;
s8 sSfxCustomReverb;
u8 sRiverSoundMainBgmVol;
u8 sRiverSoundMainBgmCurrentVol;
u8 sRiverSoundMainBgmLower;
u8 sRiverSoundMainBgmRestore;
u8 sGanonsTowerVol;
f32* sSfxVolumeCur;
f32 sSfxVolumeTarget;
f32 sSfxVolumeRate;
u16 sRequestedSceneSeqId;
SfxChannelState sSfxChannelState[SEQ_NUM_CHANNELS];
// Sequence bss
u8 sRomaniSingingTimer;
u8 sRomaniSingingDisabled;
u8 sRiverSoundBgmTimer;
u8 sFanfareState;
u16 sFanfareSeqId;
u8 sMuteOnlySfxAndAmbienceSeq;
u8 sAllPlayersMutedExceptSystemAndOcarina;
typedef enum {
/* 0 */ AUDIO_PAUSE_STATE_CLOSED,
/* 1 */ AUDIO_PAUSE_STATE_CLOSING,
/* 2 */ AUDIO_PAUSE_STATE_OPEN
} AudioPauseState;
u8 sAudioPauseState;
u8 sSpatialSeqIsActive[4];
u8 sSequenceFilter[8 * 4];
u8 sIsFinalHoursOrSoaring;
u8 sObjSoundFanfareSeqId;
u8 sObjSoundFanfareRequested;
Vec3f sObjSoundFanfarePos;
u8 sObjSoundPlayerIndex;
Vec3f sObjSoundPos;
s16 sObjSoundFlags;
f32 sObjSoundMinDist;
f32 sObjSoundMaxDist;
f32 sObjSoundMaxVol;
f32 sObjSoundMinVol;
Vec3f sSpatialSeqNoFilterPos;
Vec3f sSpatialSeqFilterPos;
f32 sSpatialSeqMaxDist;
u8 sSpatialSeqSeqId;
u8 sSpatialSeqFlags;
u8 D_801FD432;
u8 sSpatialSubBgmFadeTimer;
u8 D_801FD434;
u8 sSpatialSeqPlayerIndex;
u8 sSpatialSeqFadeTimer;
u16 sPrevAmbienceSeqId;
// AudioOcarina bss
OcarinaStaff sPlayingStaff;
OcarinaStaff sPlaybackStaff;
OcarinaStaff sRecordingStaff;
u32 sOcarinaUpdateTaskStart;
OcarinaControlStick sOcarinaInputStickRel;
u32 sOcarinaInputButtonCur;
u32 sOcarinaInputButtonStart;
u32 sOcarinaInputButtonPrev;
s32 sOcarinaInputButtonPress;
u8 sOcarinaDisableTimer;
u8 sOcarinaUnused;
u8 sOcarinaHasStartedSong;
u8 sFirstOcarinaSongIndex;
u8 sLastOcarinaSongIndex;
u32 sOcarinaAvailableSongFlags;
u8 sOcarinaStaffPlayingPos;
u16 sMusicStaffPos[OCARINA_SONG_MAX];
u16 sMusicStaffCurHeldLength[OCARINA_SONG_MAX];
u16 sMusicStaffExpectedLength[OCARINA_SONG_MAX];
u8 sMusicStaffExpectedPitch[OCARINA_SONG_MAX]; // Next required pitch in song playback
u8 D_801FD518[OCARINA_SONG_MAX];
u32 D_801FD530[OCARINA_SONG_MAX];
OcarinaNote sScarecrowsLongSongSecondNote;
u16 sCustomSequencePc;
// Sfx Data
// 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[] = {
true, true, true, true, true, false, true,
};
u8 gChannelsPerBank[4][7] = {
{ 3, 2, 3, 3, 2, 1, 2 },
{ 3, 2, 2, 2, 2, 2, 2 },
{ 3, 2, 2, 2, 2, 2, 2 },
{ 4, 1, 0, 0, 2, 2, 2 },
};
u8 gUsedChannelsPerBank[4][7] = {
{ 3, 2, 3, 2, 2, 1, 1 },
{ 3, 1, 1, 1, 2, 1, 1 },
{ 3, 1, 1, 1, 2, 1, 1 },
{ 2, 1, 0, 0, 1, 1, 1 },
};
f32 sGiantsMaskFreq = 0.89167805f; // Around 2 semitones down in pitch
s8 sGiantsMaskReverbAdd = 0x40;
f32 sWaterWheelVolume = 0.65f;
f32 gSfxVolume = 1.0f;
s8 sSfxTimer = 20;
s8 sSfxTimerLerpRange2 = 30;
s8 sSfxTimerLerpRange1 = 20;
f32 sBehindScreenZ[2] = { -15.0f, -65.0f }; // Unused Remnant of OoT
u8 sAudioIncreasingTranspose = 0; // Remnant of OoT, only unsed in unused functions
u8 gMorphaTransposeTable[16] = { 0, 0, 0, 1, 1, 2, 4, 6, 8, 8, 8, 8, 8, 8, 8, 8 }; // Unused Remnant of OoT
u8 sPrevChargeLevel = 0;
f32 sChargeLevelsSfxFreq[] = { 1.0f, 1.12246f, 1.33484f, 1.33484f };
f32 sCurChargeLevelSfxFreq = 1.0f;
u8 sGanonsTowerLevelsVol[] = {
127, 80, 75, 73, 70, 68, 65, 60 // volumes
};
u8 sEnterGanonsTowerTimer = 0;
u16 sSfxVolumeDuration = 0;
// System Data
s8 sSoundMode = SOUNDMODE_STEREO;
s8 sAudioPauseMenuOpenOrClose = SFX_PAUSE_MENU_CLOSE;
s8 sAudioCutsceneFlag = false;
s8 sSpecReverb = 0;
s8 sAudioEnvReverb = 0;
s8 sAudioCodeReverb = 0;
// Sequence Data
u8 sPrevSeqMode = 0;
f32 sBgmEnemyDist = 0.0f;
s8 sBgmEnemyVolume = 127;
u16 sPrevMainBgmSeqId = NA_BGM_DISABLED;
#define SEQ_RESUME_POINT_NONE 0xC0
u8 sSeqResumePoint = 0;
u8 sPrevSceneSeqId = NA_BGM_GENERAL_SFX;
u32 sNumFramesStill = 0;
u32 sNumFramesMoving = 0;
u8 sAudioBaseFilter = 0;
u8 sAudioExtraFilter = 0;
u8 sAudioBaseFilter2 = 0;
u8 sAudioExtraFilter2 = 0;
s8 gUnderwaterSfxReverbAdd = 0;
Vec3f* sRiverSoundBgmPos = NULL;
f32 sRiverSoundXZDistToPlayer = 2000.0f;
u8 sObjSoundMainBgmSeqId = NA_BGM_GENERAL_SFX;
// Weights distance strongest by depth (z), weaker by left/right screen (x), and weakest by top/bottom screen (y)
#define SEQ_SCREEN_WEIGHTED_DIST(projectedPos) \
(sqrtf(SQ((projectedPos)->z) + ((SQ((projectedPos)->x) / 4.0f) + (SQ((projectedPos)->y) / 6.0f))))
// Allows enemy bgm
#define SEQ_FLAG_ENEMY (1 << 0)
#define SEQ_FLAG_FANFARE (1 << 1)
#define SEQ_FLAG_FANFARE_KAMARO (1 << 2)
// required for Audio_RestorePrevBgm to restore a sequence after Audio_PlayBgm_StorePrevBgm
#define SEQ_FLAG_RESTORE (1 << 3)
/**
* These two sequence flags work together to implement a “resume playing from where you left off” system for scene
* sequences when leaving and returning to a scene. For a scene to resume playing from the point where it left off, it
* must have `SEQ_FLAG_RESUME` attached to it. Then, if the scene changes and the new scene sequence contain
* `SEQ_FLAG_RESUME_PREV`, the point from the previous scene sequence will be stored. Then, when returning to the
* scene with the sequence `SEQ_FLAG_RESUME`, then the sequence will resume playing from where it left off.
*
* TODO: Confirm which sequences properly implement this system after sequence extraction
*/
#define SEQ_FLAG_RESUME (1 << 4)
#define SEQ_FLAG_RESUME_PREV (1 << 5)
/**
* Will write a value of 1 to ioPort 7 when called through the scene. How it's used depends on the sequence:
* NA_BGM_FILE_SELECT - ioPort 7 skips the harp intro when a value of 1 is written to it.
*/
#define SEQ_FLAG_SKIP_HARP_INTRO (1 << 6)
// Unused, repurposed for SubBgm
#define SEQ_FLAG_NO_AMBIENCE (1 << 7)
u8 sSeqFlags[] = {
SEQ_FLAG_FANFARE | SEQ_FLAG_ENEMY, // NA_BGM_GENERAL_SFX
SEQ_FLAG_ENEMY, // NA_BGM_AMBIENCE
SEQ_FLAG_ENEMY, // NA_BGM_TERMINA_FIELD
SEQ_FLAG_RESTORE, // NA_BGM_CHASE
0, // NA_BGM_MAJORAS_THEME
0, // NA_BGM_CLOCK_TOWER
SEQ_FLAG_ENEMY, // NA_BGM_STONE_TOWER_TEMPLE
SEQ_FLAG_ENEMY, // NA_BGM_INV_STONE_TOWER_TEMPLE
SEQ_FLAG_FANFARE, // NA_BGM_FAILURE_0
SEQ_FLAG_FANFARE, // NA_BGM_FAILURE_1
0, // NA_BGM_HAPPY_MASK_SALESMAN
0, // NA_BGM_SONG_OF_HEALING
SEQ_FLAG_ENEMY, // NA_BGM_SWAMP_REGION
0, // NA_BGM_ALIEN_INVASION
SEQ_FLAG_FANFARE, // NA_BGM_SWAMP_CRUISE
0, // NA_BGM_SHARPS_CURSE
SEQ_FLAG_ENEMY, // NA_BGM_GREAT_BAY_REGION
SEQ_FLAG_ENEMY, // NA_BGM_IKANA_REGION
0, // NA_BGM_DEKU_PALACE
SEQ_FLAG_ENEMY, // NA_BGM_MOUNTAIN_REGION
0, // NA_BGM_PIRATES_FORTRESS
0, // NA_BGM_CLOCK_TOWN_DAY_1
0, // NA_BGM_CLOCK_TOWN_DAY_2
0, // NA_BGM_CLOCK_TOWN_DAY_3
SEQ_FLAG_SKIP_HARP_INTRO, // NA_BGM_FILE_SELECT
SEQ_FLAG_RESUME, // NA_BGM_CLEAR_EVENT
0, // NA_BGM_ENEMY
SEQ_FLAG_RESTORE, // NA_BGM_BOSS
SEQ_FLAG_ENEMY, // NA_BGM_WOODFALL_TEMPLE
0, // NA_BGM_CLOCK_TOWN_MAIN_SEQUENCE
0, // NA_BGM_OPENING
SEQ_FLAG_RESUME_PREV, // NA_BGM_INSIDE_A_HOUSE
SEQ_FLAG_FANFARE, // NA_BGM_GAME_OVER
0, // NA_BGM_CLEAR_BOSS
SEQ_FLAG_FANFARE, // NA_BGM_GET_ITEM
SEQ_FLAG_FANFARE, // NA_BGM_CLOCK_TOWN_DAY_2_PTR
SEQ_FLAG_FANFARE, // NA_BGM_GET_HEART
SEQ_FLAG_RESTORE, // NA_BGM_TIMED_MINI_GAME
0, // NA_BGM_GORON_RACE
0, // NA_BGM_MUSIC_BOX_HOUSE
0, // NA_BGM_FAIRY_FOUNTAIN
0, // NA_BGM_ZELDAS_LULLABY
0, // NA_BGM_ROSA_SISTERS
SEQ_FLAG_FANFARE, // NA_BGM_OPEN_CHEST
0, // NA_BGM_MARINE_RESEARCH_LAB
SEQ_FLAG_SKIP_HARP_INTRO, // NA_BGM_GIANTS_THEME
0, // NA_BGM_SONG_OF_STORMS
0, // NA_BGM_ROMANI_RANCH
0, // NA_BGM_GORON_VILLAGE
0, // NA_BGM_MAYORS_OFFICE
SEQ_FLAG_FANFARE, // NA_BGM_OCARINA_EPONA
SEQ_FLAG_FANFARE, // NA_BGM_OCARINA_SUNS
SEQ_FLAG_FANFARE, // NA_BGM_OCARINA_TIME
SEQ_FLAG_FANFARE, // NA_BGM_OCARINA_STORM
SEQ_FLAG_RESUME, // NA_BGM_ZORA_HALL
SEQ_FLAG_FANFARE, // NA_BGM_GET_NEW_MASK
SEQ_FLAG_RESTORE, // NA_BGM_MINI_BOSS
SEQ_FLAG_FANFARE, // NA_BGM_GET_SMALL_ITEM
0, // NA_BGM_ASTRAL_OBSERVATORY
SEQ_FLAG_ENEMY, // NA_BGM_CAVERN
SEQ_FLAG_RESUME | SEQ_FLAG_ENEMY, // NA_BGM_MILK_BAR
SEQ_FLAG_FANFARE, // NA_BGM_ZELDA_APPEAR
0, // NA_BGM_SARIAS_SONG
0, // NA_BGM_GORON_GOAL
0, // NA_BGM_HORSE
0, // NA_BGM_HORSE_GOAL
0, // NA_BGM_INGO
0, // NA_BGM_KOTAKE_POTION_SHOP
SEQ_FLAG_RESUME_PREV, // NA_BGM_SHOP
SEQ_FLAG_FANFARE, // NA_BGM_OWL
SEQ_FLAG_RESUME_PREV, // NA_BGM_SHOOTING_GALLERY
SEQ_FLAG_FANFARE, // NA_BGM_OCARINA_SOARING
SEQ_FLAG_FANFARE, // NA_BGM_OCARINA_HEALING
SEQ_FLAG_FANFARE, // NA_BGM_INVERTED_SONG_OF_TIME
SEQ_FLAG_FANFARE, // NA_BGM_SONG_OF_DOUBLE_TIME
SEQ_FLAG_FANFARE, // NA_BGM_SONATA_OF_AWAKENING
SEQ_FLAG_FANFARE, // NA_BGM_GORON_LULLABY
SEQ_FLAG_FANFARE, // NA_BGM_NEW_WAVE_BOSSA_NOVA
SEQ_FLAG_FANFARE, // NA_BGM_ELEGY_OF_EMPTINESS
SEQ_FLAG_FANFARE, // NA_BGM_OATH_TO_ORDER
0, // NA_BGM_SWORD_TRAINING_HALL
SEQ_FLAG_FANFARE, // NA_BGM_OCARINA_LULLABY_INTRO
SEQ_FLAG_FANFARE, // NA_BGM_LEARNED_NEW_SONG
SEQ_FLAG_FANFARE, // NA_BGM_BREMEN_MARCH
SEQ_FLAG_FANFARE, // NA_BGM_BALLAD_OF_THE_WIND_FISH
SEQ_FLAG_RESTORE, // NA_BGM_SONG_OF_SOARING
0, // NA_BGM_MILK_BAR_DUPLICATE
0, // NA_BGM_FINAL_HOURS
SEQ_FLAG_FANFARE, // NA_BGM_MIKAU_RIFF
SEQ_FLAG_FANFARE, // NA_BGM_MIKAU_FINALE
0, // NA_BGM_FROG_SONG
SEQ_FLAG_FANFARE, // NA_BGM_OCARINA_SONATA
SEQ_FLAG_FANFARE, // NA_BGM_OCARINA_LULLABY
SEQ_FLAG_FANFARE, // NA_BGM_OCARINA_NEW_WAVE
SEQ_FLAG_FANFARE, // NA_BGM_OCARINA_ELEGY
SEQ_FLAG_FANFARE, // NA_BGM_OCARINA_OATH
0, // NA_BGM_MAJORAS_LAIR
SEQ_FLAG_FANFARE, // NA_BGM_OCARINA_LULLABY_INTRO_PTR
SEQ_FLAG_FANFARE, // NA_BGM_OCARINA_GUITAR_BASS_SESSION
SEQ_FLAG_FANFARE, // NA_BGM_PIANO_SESSION
SEQ_FLAG_FANFARE, // NA_BGM_INDIGO_GO_SESSION
SEQ_FLAG_ENEMY, // NA_BGM_SNOWHEAD_TEMPLE
SEQ_FLAG_ENEMY, // NA_BGM_GREAT_BAY_TEMPLE
SEQ_FLAG_FANFARE, // NA_BGM_NEW_WAVE_SAXOPHONE
SEQ_FLAG_FANFARE, // NA_BGM_NEW_WAVE_VOCAL
0, // NA_BGM_MAJORAS_WRATH
0, // NA_BGM_MAJORAS_INCARNATION
0, // NA_BGM_MAJORAS_MASK
SEQ_FLAG_FANFARE, // NA_BGM_BASS_PLAY
SEQ_FLAG_FANFARE, // NA_BGM_DRUMS_PLAY
SEQ_FLAG_FANFARE, // NA_BGM_PIANO_PLAY
SEQ_FLAG_ENEMY, // NA_BGM_IKANA_CASTLE
0, // NA_BGM_GATHERING_GIANTS
SEQ_FLAG_FANFARE_KAMARO, // NA_BGM_KAMARO_DANCE
0, // NA_BGM_CREMIA_CARRIAGE
SEQ_FLAG_FANFARE, // NA_BGM_KEATON_QUIZ
0, // NA_BGM_END_CREDITS_1
0, // NA_BGM_OPENING_LOOP
0, // NA_BGM_TITLE_THEME
SEQ_FLAG_FANFARE, // NA_BGM_DUNGEON_APPEAR
SEQ_FLAG_FANFARE, // NA_BGM_WOODFALL_CLEAR
SEQ_FLAG_FANFARE, // NA_BGM_SNOWHEAD_CLEAR
0, //
0, // NA_BGM_INTO_THE_MOON
0, // NA_BGM_GOODBYE_GIANT
0, // NA_BGM_TATL_AND_TAEL
0, // NA_BGM_MOONS_DESTRUCTION
0, // NA_BGM_END_CREDITS_SECOND_HALF
};
s8 sSpecReverbs[] = {
0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
#define AMBIENCE_CHANNEL_PROPERTIES_ENTRIES_MAX 33
typedef struct {
/* 0x0 */ u16 initChannelMask; // bitwise flag for 16 channels, channels to initialize
/* 0x2 */ u16 initMuteChannelMask; // bitwise flag for 16 channels, channels to mute upon initialization
/* 0x4 */ u8 channelProperties[3 * AMBIENCE_CHANNEL_PROPERTIES_ENTRIES_MAX + 1];
} AmbienceDataIO; // size = 0x68
AmbienceDataIO sAmbienceData[20] = {
// AMBIENCE_ID_00
{
// Init channel mask
((1 << AMBIENCE_CHANNEL_STREAM_0) | (1 << AMBIENCE_CHANNEL_CRITTER_0) | (1 << AMBIENCE_CHANNEL_CRITTER_1) |
(1 << AMBIENCE_CHANNEL_CRITTER_2) | (1 << AMBIENCE_CHANNEL_CRITTER_3) | (1 << AMBIENCE_CHANNEL_CRITTER_4) |
(1 << AMBIENCE_CHANNEL_CRITTER_5) | (1 << AMBIENCE_CHANNEL_CRITTER_6) | (1 << AMBIENCE_CHANNEL_RAIN) |
(1 << AMBIENCE_CHANNEL_LIGHTNING)),
// Init mute channel mask
((1 << AMBIENCE_CHANNEL_CRITTER_0) | (1 << AMBIENCE_CHANNEL_CRITTER_1) | (1 << AMBIENCE_CHANNEL_CRITTER_2) |
(1 << AMBIENCE_CHANNEL_CRITTER_3) | (1 << AMBIENCE_CHANNEL_CRITTER_4) | (1 << AMBIENCE_CHANNEL_CRITTER_5) |
(1 << AMBIENCE_CHANNEL_CRITTER_6) | (1 << AMBIENCE_CHANNEL_RAIN) | (1 << AMBIENCE_CHANNEL_LIGHTNING)),
{
// Channel 0
AMBIENCE_IO_STREAM_0_TYPE(AMBIENCE_STREAM_0),
AMBIENCE_IO_STREAM_0_PORT3(0),
// Channel 1
AMBIENCE_IO_CRITTER_0_TYPE(AMBIENCE_CRITTER_09),
AMBIENCE_IO_CRITTER_0_BEND_PITCH(64),
AMBIENCE_IO_CRITTER_0_NUM_LAYERS(0),
AMBIENCE_IO_CRITTER_0_PORT5(32),
// Channel 2
AMBIENCE_IO_CRITTER_1_TYPE(AMBIENCE_CRITTER_04),
AMBIENCE_IO_CRITTER_1_BEND_PITCH(0),
AMBIENCE_IO_CRITTER_1_NUM_LAYERS(1),
AMBIENCE_IO_CRITTER_1_PORT5(16),
// Channel 3
AMBIENCE_IO_CRITTER_2_TYPE(AMBIENCE_CRITTER_10),
AMBIENCE_IO_CRITTER_2_BEND_PITCH(112),
AMBIENCE_IO_CRITTER_2_NUM_LAYERS(1),
AMBIENCE_IO_CRITTER_2_PORT5(48),
// Channel 4
AMBIENCE_IO_CRITTER_3_TYPE(AMBIENCE_CRITTER_03),
AMBIENCE_IO_CRITTER_3_BEND_PITCH(127),
AMBIENCE_IO_CRITTER_3_NUM_LAYERS(0),
AMBIENCE_IO_CRITTER_3_PORT5(16),
// Channel 5
AMBIENCE_IO_CRITTER_4_TYPE(AMBIENCE_CRITTER_00),
AMBIENCE_IO_CRITTER_4_BEND_PITCH(127),
AMBIENCE_IO_CRITTER_4_NUM_LAYERS(1),
AMBIENCE_IO_CRITTER_4_PORT5(16),
// Channel 6
AMBIENCE_IO_CRITTER_5_TYPE(AMBIENCE_CRITTER_01),
AMBIENCE_IO_CRITTER_5_BEND_PITCH(127),
AMBIENCE_IO_CRITTER_5_NUM_LAYERS(3),
AMBIENCE_IO_CRITTER_5_PORT5(16),
// End
AMBIENCE_IO_ENTRIES_END,
},
},
// AMBIENCE_ID_01
{
// Init channel mask
((1 << AMBIENCE_CHANNEL_STREAM_0) | (1 << AMBIENCE_CHANNEL_CRITTER_0) | (1 << AMBIENCE_CHANNEL_CRITTER_1) |
(1 << AMBIENCE_CHANNEL_CRITTER_2) | (1 << AMBIENCE_CHANNEL_CRITTER_3) | (1 << AMBIENCE_CHANNEL_CRITTER_4) |
(1 << AMBIENCE_CHANNEL_CRITTER_5) | (1 << AMBIENCE_CHANNEL_CRITTER_6) | (1 << AMBIENCE_CHANNEL_RAIN) |
(1 << AMBIENCE_CHANNEL_LIGHTNING)),
// Init mute channel mask
((1 << AMBIENCE_CHANNEL_CRITTER_0) | (1 << AMBIENCE_CHANNEL_CRITTER_1) | (1 << AMBIENCE_CHANNEL_CRITTER_2) |
(1 << AMBIENCE_CHANNEL_CRITTER_3) | (1 << AMBIENCE_CHANNEL_CRITTER_4) | (1 << AMBIENCE_CHANNEL_CRITTER_5) |
(1 << AMBIENCE_CHANNEL_CRITTER_6) | (1 << AMBIENCE_CHANNEL_RAIN) | (1 << AMBIENCE_CHANNEL_LIGHTNING)),
{
// Channel 0
AMBIENCE_IO_STREAM_0_TYPE(AMBIENCE_STREAM_0),
AMBIENCE_IO_STREAM_0_PORT3(0),
// Channel 1
AMBIENCE_IO_CRITTER_0_TYPE(AMBIENCE_CRITTER_04),
AMBIENCE_IO_CRITTER_0_BEND_PITCH(64),
AMBIENCE_IO_CRITTER_0_NUM_LAYERS(0),
AMBIENCE_IO_CRITTER_0_PORT5(32),
// Channel 2
AMBIENCE_IO_CRITTER_1_TYPE(AMBIENCE_CRITTER_16),
AMBIENCE_IO_CRITTER_1_BEND_PITCH(0),
AMBIENCE_IO_CRITTER_1_NUM_LAYERS(1),
AMBIENCE_IO_CRITTER_1_PORT5(16),
// Channel 3
AMBIENCE_IO_CRITTER_2_TYPE(AMBIENCE_CRITTER_12),
AMBIENCE_IO_CRITTER_2_BEND_PITCH(112),
AMBIENCE_IO_CRITTER_2_NUM_LAYERS(0),
AMBIENCE_IO_CRITTER_2_PORT5(48),
// Channel 4
AMBIENCE_IO_CRITTER_3_TYPE(AMBIENCE_CRITTER_15),
AMBIENCE_IO_CRITTER_3_BEND_PITCH(127),
AMBIENCE_IO_CRITTER_3_NUM_LAYERS(1),
AMBIENCE_IO_CRITTER_3_PORT5(16),
// Channel 5
AMBIENCE_IO_CRITTER_4_TYPE(AMBIENCE_CRITTER_06),
AMBIENCE_IO_CRITTER_4_BEND_PITCH(127),
AMBIENCE_IO_CRITTER_4_NUM_LAYERS(1),
AMBIENCE_IO_CRITTER_4_PORT5(16),
// Channel 6
AMBIENCE_IO_CRITTER_5_TYPE(AMBIENCE_CRITTER_01),
AMBIENCE_IO_CRITTER_5_BEND_PITCH(127),
AMBIENCE_IO_CRITTER_5_NUM_LAYERS(3),
AMBIENCE_IO_CRITTER_5_PORT5(16),
// End
AMBIENCE_IO_ENTRIES_END,
},
},
// AMBIENCE_ID_02
{
// Init channel mask
((1 << AMBIENCE_CHANNEL_STREAM_0) | (1 << AMBIENCE_CHANNEL_CRITTER_0) | (1 << AMBIENCE_CHANNEL_CRITTER_1) |
(1 << AMBIENCE_CHANNEL_CRITTER_2) | (1 << AMBIENCE_CHANNEL_CRITTER_3) | (1 << AMBIENCE_CHANNEL_CRITTER_4) |
(1 << AMBIENCE_CHANNEL_CRITTER_5) | (1 << AMBIENCE_CHANNEL_CRITTER_6) | (1 << AMBIENCE_CHANNEL_RAIN) |
(1 << AMBIENCE_CHANNEL_LIGHTNING)),
// Init mute channel mask
((1 << AMBIENCE_CHANNEL_CRITTER_0) | (1 << AMBIENCE_CHANNEL_CRITTER_1) | (1 << AMBIENCE_CHANNEL_CRITTER_2) |
(1 << AMBIENCE_CHANNEL_CRITTER_3) | (1 << AMBIENCE_CHANNEL_CRITTER_4) | (1 << AMBIENCE_CHANNEL_CRITTER_5) |
(1 << AMBIENCE_CHANNEL_CRITTER_6) | (1 << AMBIENCE_CHANNEL_RAIN) | (1 << AMBIENCE_CHANNEL_LIGHTNING)),
{
// Channel 0
AMBIENCE_IO_STREAM_0_TYPE(AMBIENCE_STREAM_0),
AMBIENCE_IO_STREAM_0_PORT3(0),
// Channel 1
AMBIENCE_IO_CRITTER_0_TYPE(AMBIENCE_CRITTER_04),
AMBIENCE_IO_CRITTER_0_BEND_PITCH(64),
AMBIENCE_IO_CRITTER_0_NUM_LAYERS(0),
AMBIENCE_IO_CRITTER_0_PORT5(48),
// Channel 2
AMBIENCE_IO_CRITTER_1_TYPE(AMBIENCE_CRITTER_10),
AMBIENCE_IO_CRITTER_1_BEND_PITCH(0),
AMBIENCE_IO_CRITTER_1_NUM_LAYERS(1),
AMBIENCE_IO_CRITTER_1_PORT5(16),
// Channel 3
AMBIENCE_IO_CRITTER_2_TYPE(AMBIENCE_CRITTER_04),
AMBIENCE_IO_CRITTER_2_BEND_PITCH(48),
AMBIENCE_IO_CRITTER_2_NUM_LAYERS(1),
AMBIENCE_IO_CRITTER_2_PORT5(32),
// Channel 4
AMBIENCE_IO_CRITTER_3_TYPE(AMBIENCE_CRITTER_03),
AMBIENCE_IO_CRITTER_3_BEND_PITCH(127),
AMBIENCE_IO_CRITTER_3_NUM_LAYERS(0),
AMBIENCE_IO_CRITTER_3_PORT5(16),
// Channel 5
AMBIENCE_IO_CRITTER_4_TYPE(AMBIENCE_CRITTER_01),
AMBIENCE_IO_CRITTER_4_BEND_PITCH(64),
AMBIENCE_IO_CRITTER_4_NUM_LAYERS(1),
AMBIENCE_IO_CRITTER_4_PORT5(0),
// Channel 6
AMBIENCE_IO_CRITTER_5_TYPE(AMBIENCE_CRITTER_04),
AMBIENCE_IO_CRITTER_5_BEND_PITCH(127),
AMBIENCE_IO_CRITTER_5_NUM_LAYERS(0),
AMBIENCE_IO_CRITTER_5_PORT5(63),
// End
AMBIENCE_IO_ENTRIES_END,
},
},
// AMBIENCE_ID_03
{
// Init channel mask
((1 << AMBIENCE_CHANNEL_STREAM_0) | (1 << AMBIENCE_CHANNEL_CRITTER_0) | (1 << AMBIENCE_CHANNEL_CRITTER_1) |
(1 << AMBIENCE_CHANNEL_CRITTER_2) | (1 << AMBIENCE_CHANNEL_CRITTER_3) | (1 << AMBIENCE_CHANNEL_CRITTER_4) |
(1 << AMBIENCE_CHANNEL_CRITTER_5) | (1 << AMBIENCE_CHANNEL_CRITTER_6) | (1 << AMBIENCE_CHANNEL_RAIN) |
(1 << AMBIENCE_CHANNEL_LIGHTNING)),
// Init mute channel mask
((1 << AMBIENCE_CHANNEL_CRITTER_0) | (1 << AMBIENCE_CHANNEL_CRITTER_1) | (1 << AMBIENCE_CHANNEL_CRITTER_2) |
(1 << AMBIENCE_CHANNEL_CRITTER_3) | (1 << AMBIENCE_CHANNEL_CRITTER_4) | (1 << AMBIENCE_CHANNEL_CRITTER_5) |
(1 << AMBIENCE_CHANNEL_CRITTER_6) | (1 << AMBIENCE_CHANNEL_RAIN) | (1 << AMBIENCE_CHANNEL_LIGHTNING)),
{
// Channel 0
AMBIENCE_IO_STREAM_0_TYPE(AMBIENCE_STREAM_0),
AMBIENCE_IO_STREAM_0_PORT3(0),
// Channel 1
AMBIENCE_IO_CRITTER_0_TYPE(AMBIENCE_CRITTER_09),
AMBIENCE_IO_CRITTER_0_BEND_PITCH(64),
AMBIENCE_IO_CRITTER_0_NUM_LAYERS(0),
AMBIENCE_IO_CRITTER_0_PORT5(32),
// Channel 2
AMBIENCE_IO_CRITTER_1_TYPE(AMBIENCE_CRITTER_04),
AMBIENCE_IO_CRITTER_1_BEND_PITCH(64),
AMBIENCE_IO_CRITTER_1_NUM_LAYERS(0),
AMBIENCE_IO_CRITTER_1_PORT5(48),
// Channel 3
AMBIENCE_IO_CRITTER_2_TYPE(AMBIENCE_CRITTER_10),
AMBIENCE_IO_CRITTER_2_BEND_PITCH(32),
AMBIENCE_IO_CRITTER_2_NUM_LAYERS(1),
AMBIENCE_IO_CRITTER_2_PORT5(32),
// Channel 4
AMBIENCE_IO_CRITTER_3_TYPE(AMBIENCE_CRITTER_14),
AMBIENCE_IO_CRITTER_3_BEND_PITCH(64),
AMBIENCE_IO_CRITTER_3_NUM_LAYERS(1),
AMBIENCE_IO_CRITTER_3_PORT5(16),
// Channel 5
AMBIENCE_IO_CRITTER_4_TYPE(AMBIENCE_CRITTER_00),
AMBIENCE_IO_CRITTER_4_BEND_PITCH(127),
AMBIENCE_IO_CRITTER_4_NUM_LAYERS(1),
AMBIENCE_IO_CRITTER_4_PORT5(16),
// Channel 6
AMBIENCE_IO_CRITTER_5_TYPE(AMBIENCE_CRITTER_01),
AMBIENCE_IO_CRITTER_5_BEND_PITCH(127),
AMBIENCE_IO_CRITTER_5_NUM_LAYERS(3),
AMBIENCE_IO_CRITTER_5_PORT5(16),
// End
AMBIENCE_IO_ENTRIES_END,
},
},
// AMBIENCE_ID_04
{
// Init channel mask
((1 << AMBIENCE_CHANNEL_STREAM_0) | (1 << AMBIENCE_CHANNEL_CRITTER_0) | (1 << AMBIENCE_CHANNEL_CRITTER_1) |
(1 << AMBIENCE_CHANNEL_CRITTER_2) | (1 << AMBIENCE_CHANNEL_CRITTER_3) | (1 << AMBIENCE_CHANNEL_CRITTER_4) |
(1 << AMBIENCE_CHANNEL_CRITTER_5) | (1 << AMBIENCE_CHANNEL_CRITTER_6) | (1 << AMBIENCE_CHANNEL_RAIN) |
(1 << AMBIENCE_CHANNEL_LIGHTNING)),
// Init mute channel mask
((1 << AMBIENCE_CHANNEL_CRITTER_0) | (1 << AMBIENCE_CHANNEL_CRITTER_1) | (1 << AMBIENCE_CHANNEL_CRITTER_2) |
(1 << AMBIENCE_CHANNEL_CRITTER_3) | (1 << AMBIENCE_CHANNEL_CRITTER_4) | (1 << AMBIENCE_CHANNEL_CRITTER_5) |
(1 << AMBIENCE_CHANNEL_CRITTER_6) | (1 << AMBIENCE_CHANNEL_RAIN) | (1 << AMBIENCE_CHANNEL_LIGHTNING)),
{
// Channel 0
AMBIENCE_IO_STREAM_0_TYPE(0),
AMBIENCE_IO_STREAM_0_PORT3(0),
// Channel 1
AMBIENCE_IO_CRITTER_0_TYPE(AMBIENCE_CRITTER_04),
AMBIENCE_IO_CRITTER_0_BEND_PITCH(64),
AMBIENCE_IO_CRITTER_0_NUM_LAYERS(0),
AMBIENCE_IO_CRITTER_0_PORT5(32),
// Channel 2
AMBIENCE_IO_CRITTER_1_TYPE(AMBIENCE_CRITTER_02),
AMBIENCE_IO_CRITTER_1_BEND_PITCH(64),
AMBIENCE_IO_CRITTER_1_NUM_LAYERS(1),
AMBIENCE_IO_CRITTER_1_PORT5(16),
// Channel 3
AMBIENCE_IO_CRITTER_2_TYPE(AMBIENCE_CRITTER_12),
AMBIENCE_IO_CRITTER_2_BEND_PITCH(112),
AMBIENCE_IO_CRITTER_2_NUM_LAYERS(1),
AMBIENCE_IO_CRITTER_2_PORT5(48),
// Channel 4
AMBIENCE_IO_CRITTER_3_TYPE(AMBIENCE_CRITTER_13),
AMBIENCE_IO_CRITTER_3_BEND_PITCH(64),
AMBIENCE_IO_CRITTER_3_NUM_LAYERS(1),
AMBIENCE_IO_CRITTER_3_PORT5(16),
// Channel 5
AMBIENCE_IO_CRITTER_4_TYPE(AMBIENCE_CRITTER_01),
AMBIENCE_IO_CRITTER_4_BEND_PITCH(64),
AMBIENCE_IO_CRITTER_4_NUM_LAYERS(1),
AMBIENCE_IO_CRITTER_4_PORT5(16),
// Channel 6
AMBIENCE_IO_CRITTER_5_TYPE(AMBIENCE_CRITTER_02),
AMBIENCE_IO_CRITTER_5_BEND_PITCH(112),
AMBIENCE_IO_CRITTER_5_NUM_LAYERS(0),
AMBIENCE_IO_CRITTER_5_PORT5(48),
// Channel 14
AMBIENCE_IO_RAIN_PORT4(63),
// End
AMBIENCE_IO_ENTRIES_END,
},
},
// AMBIENCE_ID_05
{
// Init channel mask
((1 << AMBIENCE_CHANNEL_STREAM_0) | (1 << AMBIENCE_CHANNEL_CRITTER_0) | (1 << AMBIENCE_CHANNEL_CRITTER_1) |
(1 << AMBIENCE_CHANNEL_CRITTER_2) | (1 << AMBIENCE_CHANNEL_CRITTER_3) | (1 << AMBIENCE_CHANNEL_CRITTER_4) |
(1 << AMBIENCE_CHANNEL_CRITTER_5) | (1 << AMBIENCE_CHANNEL_CRITTER_6) | (1 << AMBIENCE_CHANNEL_RAIN) |
(1 << AMBIENCE_CHANNEL_LIGHTNING)),
// Init mute channel mask
((1 << AMBIENCE_CHANNEL_CRITTER_0) | (1 << AMBIENCE_CHANNEL_CRITTER_1) | (1 << AMBIENCE_CHANNEL_CRITTER_2) |
(1 << AMBIENCE_CHANNEL_CRITTER_3) | (1 << AMBIENCE_CHANNEL_CRITTER_4) | (1 << AMBIENCE_CHANNEL_CRITTER_5) |
(1 << AMBIENCE_CHANNEL_CRITTER_6) | (1 << AMBIENCE_CHANNEL_RAIN) | (1 << AMBIENCE_CHANNEL_LIGHTNING)),
{
// Channel 0
AMBIENCE_IO_STREAM_0_TYPE(AMBIENCE_STREAM_0),
AMBIENCE_IO_STREAM_0_PORT3(0),
// Channel 1
AMBIENCE_IO_CRITTER_0_TYPE(AMBIENCE_CRITTER_09),
AMBIENCE_IO_CRITTER_0_BEND_PITCH(64),
AMBIENCE_IO_CRITTER_0_NUM_LAYERS(0),
AMBIENCE_IO_CRITTER_0_PORT5(32),
// Channel 2
AMBIENCE_IO_CRITTER_1_TYPE(AMBIENCE_CRITTER_04),
AMBIENCE_IO_CRITTER_1_BEND_PITCH(0),
AMBIENCE_IO_CRITTER_1_NUM_LAYERS(1),
AMBIENCE_IO_CRITTER_1_PORT5(16),
// Channel 3
AMBIENCE_IO_CRITTER_2_TYPE(AMBIENCE_CRITTER_10),
AMBIENCE_IO_CRITTER_2_BEND_PITCH(112),
AMBIENCE_IO_CRITTER_2_NUM_LAYERS(1),
AMBIENCE_IO_CRITTER_2_PORT5(48),
// Channel 4
AMBIENCE_IO_CRITTER_3_TYPE(AMBIENCE_CRITTER_13),
AMBIENCE_IO_CRITTER_3_BEND_PITCH(127),
AMBIENCE_IO_CRITTER_3_NUM_LAYERS(0),
AMBIENCE_IO_CRITTER_3_PORT5(63),
// Channel 5
AMBIENCE_IO_CRITTER_4_TYPE(AMBIENCE_CRITTER_00),
AMBIENCE_IO_CRITTER_4_BEND_PITCH(127),
AMBIENCE_IO_CRITTER_4_NUM_LAYERS(1),
AMBIENCE_IO_CRITTER_4_PORT5(16),
// Channel 6
AMBIENCE_IO_CRITTER_5_TYPE(AMBIENCE_CRITTER_01),
AMBIENCE_IO_CRITTER_5_BEND_PITCH(127),
AMBIENCE_IO_CRITTER_5_NUM_LAYERS(3),
AMBIENCE_IO_CRITTER_5_PORT5(16),
// End
AMBIENCE_IO_ENTRIES_END,
},
},
// AMBIENCE_ID_06
{
// Init channel mask
((1 << AMBIENCE_CHANNEL_STREAM_0) | (1 << AMBIENCE_CHANNEL_CRITTER_0) | (1 << AMBIENCE_CHANNEL_CRITTER_1) |
(1 << AMBIENCE_CHANNEL_CRITTER_2) | (1 << AMBIENCE_CHANNEL_CRITTER_3) | (1 << AMBIENCE_CHANNEL_CRITTER_4) |
(1 << AMBIENCE_CHANNEL_CRITTER_5) | (1 << AMBIENCE_CHANNEL_CRITTER_6) | (1 << AMBIENCE_CHANNEL_RAIN) |
(1 << AMBIENCE_CHANNEL_LIGHTNING)),
// Init mute channel mask
((1 << AMBIENCE_CHANNEL_CRITTER_0) | (1 << AMBIENCE_CHANNEL_CRITTER_1) | (1 << AMBIENCE_CHANNEL_CRITTER_2) |
(1 << AMBIENCE_CHANNEL_CRITTER_3) | (1 << AMBIENCE_CHANNEL_CRITTER_4) | (1 << AMBIENCE_CHANNEL_CRITTER_5) |
(1 << AMBIENCE_CHANNEL_CRITTER_6) | (1 << AMBIENCE_CHANNEL_RAIN) | (1 << AMBIENCE_CHANNEL_LIGHTNING)),
{
// Channel 0
AMBIENCE_IO_STREAM_0_TYPE(AMBIENCE_STREAM_0),
AMBIENCE_IO_STREAM_0_PORT3(0),
// Channel 1
AMBIENCE_IO_CRITTER_0_TYPE(AMBIENCE_CRITTER_11),
AMBIENCE_IO_CRITTER_0_BEND_PITCH(112),
AMBIENCE_IO_CRITTER_0_NUM_LAYERS(0),
AMBIENCE_IO_CRITTER_0_PORT5(48),
// Channel 2
AMBIENCE_IO_CRITTER_1_TYPE(AMBIENCE_CRITTER_15),
AMBIENCE_IO_CRITTER_1_BEND_PITCH(112),
AMBIENCE_IO_CRITTER_1_NUM_LAYERS(0),
AMBIENCE_IO_CRITTER_1_PORT5(63),
// Channel 3
AMBIENCE_IO_CRITTER_2_TYPE(AMBIENCE_CRITTER_11),
AMBIENCE_IO_CRITTER_2_BEND_PITCH(48),
AMBIENCE_IO_CRITTER_2_NUM_LAYERS(1),
AMBIENCE_IO_CRITTER_2_PORT5(16),
// Channel 4
AMBIENCE_IO_CRITTER_3_TYPE(AMBIENCE_CRITTER_14),
AMBIENCE_IO_CRITTER_3_BEND_PITCH(48),
AMBIENCE_IO_CRITTER_3_NUM_LAYERS(1),
AMBIENCE_IO_CRITTER_3_PORT5(16),
// Channel 5
AMBIENCE_IO_CRITTER_4_TYPE(AMBIENCE_CRITTER_11),
AMBIENCE_IO_CRITTER_4_BEND_PITCH(127),
AMBIENCE_IO_CRITTER_4_NUM_LAYERS(0),
AMBIENCE_IO_CRITTER_4_PORT5(32),
// Channel 6
AMBIENCE_IO_CRITTER_5_TYPE(AMBIENCE_CRITTER_02),
AMBIENCE_IO_CRITTER_5_BEND_PITCH(127),
AMBIENCE_IO_CRITTER_5_NUM_LAYERS(0),
AMBIENCE_IO_CRITTER_5_PORT5(48),
// End
AMBIENCE_IO_ENTRIES_END,
},
},
// AMBIENCE_ID_07
{
// Init channel mask
((1 << AMBIENCE_CHANNEL_STREAM_0) | (1 << AMBIENCE_CHANNEL_RAIN) | (1 << AMBIENCE_CHANNEL_LIGHTNING)),
// Init mute channel mask
((1 << AMBIENCE_CHANNEL_RAIN) | (1 << AMBIENCE_CHANNEL_LIGHTNING)),
{
// Channel 0
AMBIENCE_IO_STREAM_0_TYPE(AMBIENCE_STREAM_0),
AMBIENCE_IO_STREAM_0_PORT3(0),
// End
AMBIENCE_IO_ENTRIES_END,
},
},
// AMBIENCE_ID_08
{
// Init channel mask
((1 << AMBIENCE_CHANNEL_STREAM_0) | (1 << AMBIENCE_CHANNEL_CRITTER_0) | (1 << AMBIENCE_CHANNEL_RAIN) |
(1 << AMBIENCE_CHANNEL_LIGHTNING)),
// Init mute channel mask
((1 << AMBIENCE_CHANNEL_RAIN) | (1 << AMBIENCE_CHANNEL_LIGHTNING)),
{
// Channel 0
AMBIENCE_IO_STREAM_0_TYPE(AMBIENCE_STREAM_0),
AMBIENCE_IO_STREAM_0_PORT3(0),
// Channel 1
AMBIENCE_IO_CRITTER_0_TYPE(AMBIENCE_CRITTER_01),
AMBIENCE_IO_CRITTER_0_BEND_PITCH(127),
AMBIENCE_IO_CRITTER_0_NUM_LAYERS(3),
AMBIENCE_IO_CRITTER_0_PORT5(16),
// End
AMBIENCE_IO_ENTRIES_END,
},
},
// AMBIENCE_ID_09
{
// Init channel mask
((1 << AMBIENCE_CHANNEL_STREAM_0) | (1 << AMBIENCE_CHANNEL_CRITTER_0) | (1 << AMBIENCE_CHANNEL_CRITTER_1) |
(1 << AMBIENCE_CHANNEL_CRITTER_2) | (1 << AMBIENCE_CHANNEL_RAIN) | (1 << AMBIENCE_CHANNEL_LIGHTNING)),
// Init mute channel mask
((1 << AMBIENCE_CHANNEL_RAIN) | (1 << AMBIENCE_CHANNEL_LIGHTNING)),
{
// Channel 0
AMBIENCE_IO_STREAM_0_TYPE(AMBIENCE_STREAM_0),
AMBIENCE_IO_STREAM_0_PORT3(0),
// Channel 1
AMBIENCE_IO_CRITTER_0_TYPE(AMBIENCE_CRITTER_16),
AMBIENCE_IO_CRITTER_0_BEND_PITCH(0),
AMBIENCE_IO_CRITTER_0_NUM_LAYERS(2),
AMBIENCE_IO_CRITTER_0_PORT5(16),
// Channel 2
AMBIENCE_IO_CRITTER_1_TYPE(AMBIENCE_CRITTER_12),
AMBIENCE_IO_CRITTER_1_BEND_PITCH(112),
AMBIENCE_IO_CRITTER_1_NUM_LAYERS(0),
AMBIENCE_IO_CRITTER_1_PORT5(48),
// Channel 3
AMBIENCE_IO_CRITTER_2_TYPE(AMBIENCE_CRITTER_15),
AMBIENCE_IO_CRITTER_2_BEND_PITCH(127),
AMBIENCE_IO_CRITTER_2_NUM_LAYERS(1),
AMBIENCE_IO_CRITTER_2_PORT5(16),
// End
AMBIENCE_IO_ENTRIES_END,
},
},
// AMBIENCE_ID_0A
{
// Init channel mask
((1 << AMBIENCE_CHANNEL_STREAM_0) | (1 << AMBIENCE_CHANNEL_CRITTER_6) | (1 << AMBIENCE_CHANNEL_RAIN) |
(1 << AMBIENCE_CHANNEL_LIGHTNING)),
// Init mute channel mask
((1 << AMBIENCE_CHANNEL_RAIN) | (1 << AMBIENCE_CHANNEL_LIGHTNING)),
{
// Channel 0
AMBIENCE_IO_STREAM_0_TYPE(AMBIENCE_STREAM_1),
AMBIENCE_IO_STREAM_0_PORT3(8),
// Channel 7
AMBIENCE_IO_CRITTER_6_TYPE(AMBIENCE_CRITTER_11),
AMBIENCE_IO_CRITTER_6_BEND_PITCH(112),
AMBIENCE_IO_CRITTER_6_NUM_LAYERS(2),
AMBIENCE_IO_CRITTER_6_PORT5(32),
// End
AMBIENCE_IO_ENTRIES_END,
},
},
// AMBIENCE_ID_0B
{
// Init channel mask
((1 << AMBIENCE_CHANNEL_STREAM_0) | (1 << AMBIENCE_CHANNEL_CRITTER_0) | (1 << AMBIENCE_CHANNEL_CRITTER_1) |
(1 << AMBIENCE_CHANNEL_CRITTER_2) | (1 << AMBIENCE_CHANNEL_RAIN) | (1 << AMBIENCE_CHANNEL_LIGHTNING)),
// Init mute channel mask
((1 << AMBIENCE_CHANNEL_RAIN) | (1 << AMBIENCE_CHANNEL_LIGHTNING)),
{
// Channel 0
AMBIENCE_IO_STREAM_0_TYPE(AMBIENCE_STREAM_3),
AMBIENCE_IO_STREAM_0_PORT3(8),
// Channel 1
AMBIENCE_IO_CRITTER_0_TYPE(AMBIENCE_CRITTER_01),
AMBIENCE_IO_CRITTER_0_BEND_PITCH(127),
AMBIENCE_IO_CRITTER_0_NUM_LAYERS(3),
AMBIENCE_IO_CRITTER_0_PORT5(16),
// Channel 2
AMBIENCE_IO_CRITTER_1_TYPE(AMBIENCE_CRITTER_00),
AMBIENCE_IO_CRITTER_1_BEND_PITCH(127),
AMBIENCE_IO_CRITTER_1_NUM_LAYERS(2),
AMBIENCE_IO_CRITTER_1_PORT5(16),
// Channel 3
AMBIENCE_IO_CRITTER_2_TYPE(AMBIENCE_CRITTER_06),
AMBIENCE_IO_CRITTER_2_BEND_PITCH(127),
AMBIENCE_IO_CRITTER_2_NUM_LAYERS(1),
AMBIENCE_IO_CRITTER_2_PORT5(16),
// End
AMBIENCE_IO_ENTRIES_END,
},
},
// AMBIENCE_ID_0C
{
// Init channel mask
((1 << AMBIENCE_CHANNEL_STREAM_0) | (1 << AMBIENCE_CHANNEL_CRITTER_0) | (1 << AMBIENCE_CHANNEL_CRITTER_1) |
(1 << AMBIENCE_CHANNEL_RAIN) | (1 << AMBIENCE_CHANNEL_LIGHTNING)),
// Init mute channel mask
((1 << AMBIENCE_CHANNEL_RAIN) | (1 << AMBIENCE_CHANNEL_LIGHTNING)),
{
// Channel 0
AMBIENCE_IO_STREAM_0_TYPE(AMBIENCE_STREAM_0),
// Channel 1
AMBIENCE_IO_CRITTER_0_TYPE(AMBIENCE_CRITTER_00),
AMBIENCE_IO_CRITTER_0_BEND_PITCH(127),
AMBIENCE_IO_CRITTER_0_NUM_LAYERS(1),
AMBIENCE_IO_CRITTER_0_PORT5(16),
// Channel 2
AMBIENCE_IO_CRITTER_1_TYPE(AMBIENCE_CRITTER_01),
AMBIENCE_IO_CRITTER_1_BEND_PITCH(127),
AMBIENCE_IO_CRITTER_1_NUM_LAYERS(3),
AMBIENCE_IO_CRITTER_1_PORT5(16),
// End
AMBIENCE_IO_ENTRIES_END,
},
},
// AMBIENCE_ID_0D
{
// Init channel mask
((1 << AMBIENCE_CHANNEL_STREAM_0) | (1 << AMBIENCE_CHANNEL_CRITTER_0) | (1 << AMBIENCE_CHANNEL_RAIN) |
(1 << AMBIENCE_CHANNEL_LIGHTNING)),
// Init mute channel mask
((1 << AMBIENCE_CHANNEL_RAIN) | (1 << AMBIENCE_CHANNEL_LIGHTNING)),
{
// Channel 0
AMBIENCE_IO_STREAM_0_TYPE(AMBIENCE_STREAM_0),
AMBIENCE_IO_STREAM_0_PORT3(0),
// Channel 1
AMBIENCE_IO_CRITTER_0_TYPE(AMBIENCE_CRITTER_04),
AMBIENCE_IO_CRITTER_0_BEND_PITCH(0),
AMBIENCE_IO_CRITTER_0_NUM_LAYERS(1),
AMBIENCE_IO_CRITTER_0_PORT5(16),
// End
AMBIENCE_IO_ENTRIES_END,
},
},
// AMBIENCE_ID_0E
{
// Init channel mask
((1 << AMBIENCE_CHANNEL_STREAM_0) | (1 << AMBIENCE_CHANNEL_CRITTER_0) | (1 << AMBIENCE_CHANNEL_RAIN) |
(1 << AMBIENCE_CHANNEL_LIGHTNING)),
// Init mute channel mask
((1 << AMBIENCE_CHANNEL_RAIN) | (1 << AMBIENCE_CHANNEL_LIGHTNING)),
{
// Channel 0
AMBIENCE_IO_STREAM_0_TYPE(AMBIENCE_STREAM_0),
AMBIENCE_IO_STREAM_0_PORT3(0),
// Channel 1
AMBIENCE_IO_CRITTER_0_TYPE(AMBIENCE_CRITTER_04),
AMBIENCE_IO_CRITTER_0_BEND_PITCH(0),
AMBIENCE_IO_CRITTER_0_NUM_LAYERS(1),
AMBIENCE_IO_CRITTER_0_PORT5(16),
// End
AMBIENCE_IO_ENTRIES_END,
},
},
// AMBIENCE_ID_0F
{
// Init channel mask
((1 << AMBIENCE_CHANNEL_STREAM_0) | (1 << AMBIENCE_CHANNEL_CRITTER_0) | (1 << AMBIENCE_CHANNEL_RAIN) |
(1 << AMBIENCE_CHANNEL_LIGHTNING)),
// Init mute channel mask
((1 << AMBIENCE_CHANNEL_RAIN) | (1 << AMBIENCE_CHANNEL_LIGHTNING)),
{
// Channel 0
AMBIENCE_IO_STREAM_0_TYPE(AMBIENCE_STREAM_0),
AMBIENCE_IO_STREAM_0_PORT3(0),
// Channel 1
AMBIENCE_IO_CRITTER_0_TYPE(AMBIENCE_CRITTER_04),
AMBIENCE_IO_CRITTER_0_BEND_PITCH(0),
AMBIENCE_IO_CRITTER_0_NUM_LAYERS(1),
AMBIENCE_IO_CRITTER_0_PORT5(16),
// End
AMBIENCE_IO_ENTRIES_END,
},
},
// AMBIENCE_ID_10
{
// Init channel mask
((1 << AMBIENCE_CHANNEL_STREAM_0) | (1 << AMBIENCE_CHANNEL_CRITTER_0) | (1 << AMBIENCE_CHANNEL_RAIN) |
(1 << AMBIENCE_CHANNEL_LIGHTNING)),
// Init mute channel mask
((1 << AMBIENCE_CHANNEL_RAIN) | (1 << AMBIENCE_CHANNEL_LIGHTNING)),
{
// Channel 0
AMBIENCE_IO_STREAM_0_TYPE(AMBIENCE_STREAM_0),
AMBIENCE_IO_STREAM_0_PORT3(0),
// Channel 1
AMBIENCE_IO_CRITTER_0_TYPE(AMBIENCE_CRITTER_04),
AMBIENCE_IO_CRITTER_0_BEND_PITCH(0),
AMBIENCE_IO_CRITTER_0_NUM_LAYERS(1),
AMBIENCE_IO_CRITTER_0_PORT5(16),
// End
AMBIENCE_IO_ENTRIES_END,
},
},
// AMBIENCE_ID_11
{
// Init channel mask
((1 << AMBIENCE_CHANNEL_STREAM_0) | (1 << AMBIENCE_CHANNEL_CRITTER_0) | (1 << AMBIENCE_CHANNEL_RAIN) |
(1 << AMBIENCE_CHANNEL_LIGHTNING)),
// Init mute channel mask
((1 << AMBIENCE_CHANNEL_RAIN) | (1 << AMBIENCE_CHANNEL_LIGHTNING)),
{
// Channel 0
AMBIENCE_IO_STREAM_0_TYPE(AMBIENCE_STREAM_0),
AMBIENCE_IO_STREAM_0_PORT3(0),
// Channel 1
AMBIENCE_IO_CRITTER_0_TYPE(AMBIENCE_CRITTER_04),
AMBIENCE_IO_CRITTER_0_BEND_PITCH(0),
AMBIENCE_IO_CRITTER_0_NUM_LAYERS(1),
AMBIENCE_IO_CRITTER_0_PORT5(16),
// End
AMBIENCE_IO_ENTRIES_END,
},
},
// AMBIENCE_ID_12
{
// Init channel mask
((1 << AMBIENCE_CHANNEL_RAIN) | (1 << AMBIENCE_CHANNEL_LIGHTNING)),
// Init mute channel mask
((1 << AMBIENCE_CHANNEL_RAIN) | (1 << AMBIENCE_CHANNEL_LIGHTNING)),
{
// Channel 0
AMBIENCE_IO_STREAM_0_TYPE(AMBIENCE_STREAM_0),
// End
AMBIENCE_IO_ENTRIES_END,
},
},
// AMBIENCE_ID_13
{
// Init channel mask
((1 << AMBIENCE_CHANNEL_STREAM_0) | (1 << AMBIENCE_CHANNEL_CRITTER_0) | (1 << AMBIENCE_CHANNEL_RAIN) |
(1 << AMBIENCE_CHANNEL_LIGHTNING)),
// Init mute channel mask
((1 << AMBIENCE_CHANNEL_RAIN) | (1 << AMBIENCE_CHANNEL_LIGHTNING)),
{
AMBIENCE_IO_STREAM_0_TYPE(AMBIENCE_STREAM_0),
AMBIENCE_IO_STREAM_0_PORT3(0),
// Channel 1
AMBIENCE_IO_CRITTER_0_TYPE(AMBIENCE_CRITTER_04),
AMBIENCE_IO_CRITTER_0_BEND_PITCH(0),
AMBIENCE_IO_CRITTER_0_NUM_LAYERS(1),
AMBIENCE_IO_CRITTER_0_PORT5(16),
// End
AMBIENCE_IO_ENTRIES_END,
},
},
};
// AudioOcarina Data
u8 sIsOcarinaInputEnabled = false;
s8 sOcarinaInstrumentId = OCARINA_INSTRUMENT_OFF;
u8 sCurOcarinaPitch = OCARINA_PITCH_NONE;
u8 sPrevOcarinaPitch = OCARINA_PITCH_C4;
u8 sCurOcarinaButtonIndex = OCARINA_BTN_A;
u8 sMusicStaffPrevPitch = OCARINA_PITCH_C4;
f32 sCurOcarinaBendFreq = 1.0f;
f32 sDefaultOcarinaVolume = 87.0f / 127.0f;
s8 sCurOcarinaBendIndex = 0;
s8 sCurOcarinaVolume = 87;
s8 sCurOcarinaVibrato = 0;
u8 sPlaybackState = 0;
u8 sPlaybackStaffStopPos = 0xFF;
u8 sPlaybackStaffStartPos = 0xFF;
u32 sOcarinaFlags = 0;
s32 sPlaybackNoteTimer = 0;
u16 sPlaybackNotePos = 0;
u16 sPlaybackStaffPos = 0;
u32 sPrevOcarinaWithMusicStaffFlags = 0; // Stores sOcarinaFlags but never used
u8 sPlaybackPitch = OCARINA_PITCH_NONE; // Pitch + PitchFlags
u8 sNotePlaybackVolume = 0;
u8 sNotePlaybackVibrato = 0;
s8 sNotePlaybackBend = 0;
f32 sRelativeNotePlaybackBend = 1.0f;
f32 sRelativeNotePlaybackVolume = 1.0f;
u32 sOcarinaPlaybackTaskStart = 0;
u32 sOcarinaWallCounter = 0;
u8 sCurOcarinaSongWithoutMusicStaff[8] = {
OCARINA_PITCH_C4, OCARINA_PITCH_C4, OCARINA_PITCH_C4, OCARINA_PITCH_C4,
OCARINA_PITCH_C4, OCARINA_PITCH_C4, OCARINA_PITCH_C4, OCARINA_PITCH_C4,
};
u8 sOcarinaWithoutMusicStaffPos = 0;
u8 sOcarinaSongStartingPos = 0;
u8 sButtonToPitchMap[5] = {
OCARINA_PITCH_D4, // OCARINA_BTN_A
OCARINA_PITCH_F4, // OCARINA_BTN_C_DOWN
OCARINA_PITCH_A4, // OCARINA_BTN_C_RIGHT
OCARINA_PITCH_B4, // OCARINA_BTN_C_LEFT
OCARINA_PITCH_D5, // OCARINA_BTN_C_UP
};
u8 sOcarinaMemoryGameAppendPos = 0;
u8 sOcarinaMemoryGameEndPos = 0;
u8 sOcarinaMemoryGameNumNotes[] = { 5, 6, 8 };
OcarinaNote sOcarinaSongNotes[OCARINA_SONG_MAX][20] = {
// OCARINA_SONG_SONATA
{
{ OCARINA_PITCH_D5, 19, 92, 0, 0, 0 },
{ OCARINA_PITCH_B4, 19, 90, 0, 0, 0 },
{ OCARINA_PITCH_D5, 19, 90, 0, 0, 0 },
{ OCARINA_PITCH_B4, 38, 90, 0, 0, 0 },
{ OCARINA_PITCH_D4, 39, 92, 0, 0, 0 },
{ OCARINA_PITCH_A4, 76, 89, 0, 0, 0 },
{ OCARINA_PITCH_D4, 77, 82, 0, 0, 0 },
{ OCARINA_PITCH_NONE, 0, 86, 0, 0, 0 },
},
// OCARINA_SONG_GORON_LULLABY
{
{ OCARINA_PITCH_D4, 41, 80, 0, 0, 0 },
{ OCARINA_PITCH_A4, 40, 72, 0, 0, 0 },
{ OCARINA_PITCH_B4, 39, 84, 0, 0, 0 },
{ OCARINA_PITCH_D4, 42, 76, 0, 0, 0 },
{ OCARINA_PITCH_A4, 40, 84, 0, 0, 0 },
{ OCARINA_PITCH_B4, 39, 76, 0, 0, 0 },
{ OCARINA_PITCH_A4, 41, 84, 0, 0, 0 },
{ OCARINA_PITCH_D4, 80, 76, 0, 0, 0 },
{ OCARINA_PITCH_NONE, 40, 76, 0, 0, 0 },
{ OCARINA_PITCH_NONE, 0, 66, 0, 0, 0 },
},
// OCARINA_SONG_NEW_WAVE
{
{ OCARINA_PITCH_B4, 64, 74, 0, 0, 0 },
{ OCARINA_PITCH_D5, 13, 88, 0, 0, 0 },
{ OCARINA_PITCH_B4, 12, 90, 0, 0, 0 },
{ OCARINA_PITCH_A4, 78, 88, 0, 0, 0 },
{ OCARINA_PITCH_F4, 12, 76, 0, 0, 0 },
{ OCARINA_PITCH_B4, 13, 76, 0, 0, 0 },
{ OCARINA_PITCH_A4, 114, 76, 6, 0, 0 },
{ OCARINA_PITCH_NONE, 0, 90, 0, 0, 0 },
},
// OCARINA_SONG_ELEGY
{
{ OCARINA_PITCH_A4, 85, 93, 0, 0, 0 },
{ OCARINA_PITCH_B4, 43, 91, 0, 0, 0 },
{ OCARINA_PITCH_A4, 43, 93, 0, 0, 0 },
{ OCARINA_PITCH_F4, 21, 88, 0, 0, 0 },
{ OCARINA_PITCH_A4, 21, 88, 0, 0, 0 },
{ OCARINA_PITCH_D5, 43, 101, 0, 0, 0 },
{ OCARINA_PITCH_B4, 85, 95, 0, 0, 0 },
{ OCARINA_PITCH_NONE, 0, 94, 0, 0, 0 },
},
// OCARINA_SONG_OATH
{
{ OCARINA_PITCH_A4, 97, 104, 0, 0, 0 },
{ OCARINA_PITCH_F4, 48, 88, 0, 0, 0 },
{ OCARINA_PITCH_D4, 49, 78, 0, 0, 0 },
{ OCARINA_PITCH_F4, 49, 78, 0, 0, 0 },
{ OCARINA_PITCH_A4, 48, 94, 0, 0, 0 },
{ OCARINA_PITCH_D5, 97, 100, 0, 0, 0 },
{ OCARINA_PITCH_NONE, 0, 96, 0, 0, 0 },
},
// OCARINA_SONG_SARIAS
{
{ OCARINA_PITCH_F4, 17, 84, 0, 0, 0 },
{ OCARINA_PITCH_A4, 17, 88, 0, 0, 0 },
{ OCARINA_PITCH_B4, 34, 80, 0, 0, 0 },
{ OCARINA_PITCH_F4, 17, 84, 0, 0, 0 },
{ OCARINA_PITCH_A4, 17, 88, 0, 0, 0 },
{ OCARINA_PITCH_B4, 136, 80, 0, 0, 0 },
{ OCARINA_PITCH_NONE, 0, 90, 0, 0, 0 },
},
// OCARINA_SONG_TIME
{
{ OCARINA_PITCH_A4, 32, 84, 0, 0, 0 },
{ OCARINA_PITCH_D4, 65, 88, 0, 0, 0 },
{ OCARINA_PITCH_F4, 33, 80, 0, 0, 0 },
{ OCARINA_PITCH_A4, 32, 84, 0, 0, 0 },
{ OCARINA_PITCH_D4, 65, 88, 0, 0, 0 },
{ OCARINA_PITCH_F4, 99, 80, 0, 0, 0 },
{ OCARINA_PITCH_NONE, 0, 90, 0, 0, 0 },
},
// OCARINA_SONG_HEALING
{
{ OCARINA_PITCH_B4, 32, 88, 0, 0, 0 },
{ OCARINA_PITCH_A4, 33, 88, 0, 0, 0 },
{ OCARINA_PITCH_F4, 33, 69, 0, 0, 0 },
{ OCARINA_PITCH_B4, 32, 94, 0, 0, 0 },
{ OCARINA_PITCH_A4, 33, 88, 0, 0, 0 },
{ OCARINA_PITCH_F4, 121, 86, 2, 0, 0 },
{ OCARINA_PITCH_NONE, 10, 84, 0, 0, 0 },
{ OCARINA_PITCH_NONE, 0, 90, 0, 0, 0 },
},
// OCARINA_SONG_EPONAS
{
{ OCARINA_PITCH_D5, 18, 84, 0, 0, 0 },
{ OCARINA_PITCH_B4, 18, 88, 0, 0, 0 },
{ OCARINA_PITCH_A4, 72, 80, 0, 0, 0 },
{ OCARINA_PITCH_D5, 18, 84, 0, 0, 0 },
{ OCARINA_PITCH_B4, 18, 88, 0, 0, 0 },
{ OCARINA_PITCH_A4, 144, 80, 0, 0, 0 },
{ OCARINA_PITCH_NONE, 0, 90, 0, 0, 0 },
},
// OCARINA_SONG_SOARING
{
{ OCARINA_PITCH_F4, 18, 84, 0, 0, 0 },
{ OCARINA_PITCH_B4, 18, 80, 0, 0, 0 },
{ OCARINA_PITCH_D5, 36, 94, 0, 0, 0 },
{ OCARINA_PITCH_F4, 18, 73, 0, 0, 0 },
{ OCARINA_PITCH_B4, 18, 76, 0, 0, 0 },
{ OCARINA_PITCH_D5, 108, 96, 2, 0, 0 },
{ OCARINA_PITCH_NONE, 0, 90, 0, 0, 0 },
},
// OCARINA_SONG_STORMS
{
{ OCARINA_PITCH_D4, 11, 84, 0, 0, 0 },
{ OCARINA_PITCH_F4, 11, 88, 0, 0, 0 },
{ OCARINA_PITCH_D5, 45, 80, 0, 0, 0 },
{ OCARINA_PITCH_D4, 11, 84, 0, 0, 0 },
{ OCARINA_PITCH_F4, 11, 88, 0, 0, 0 },
{ OCARINA_PITCH_D5, 90, 80, 0, 0, 0 },
{ OCARINA_PITCH_NONE, 0, 90, 0, 0, 0 },
},
// OCARINA_SONG_SUNS
{
{ OCARINA_PITCH_A4, 12, 84, 0, 0, 0 },
{ OCARINA_PITCH_F4, 13, 88, 0, 0, 0 },
{ OCARINA_PITCH_D5, 29, 80, 2, 0, 0 },
{ OCARINA_PITCH_NONE, 9, 84, 0, 0, 0 },
{ OCARINA_PITCH_A4, 12, 84, 0, 0, 0 },
{ OCARINA_PITCH_F4, 13, 88, 0, 0, 0 },
{ OCARINA_PITCH_D5, 120, 80, 3, 0, 0 },
{ OCARINA_PITCH_NONE, 0, 90, 0, 0, 0 },
},
// OCARINA_SONG_INVERTED_TIME
{
{ OCARINA_PITCH_F4, 32, 84, 0, 0, 0 },
{ OCARINA_PITCH_D4, 65, 88, 0, 0, 0 },
{ OCARINA_PITCH_A4, 33, 80, 0, 0, 0 },
{ OCARINA_PITCH_F4, 32, 84, 0, 0, 0 },
{ OCARINA_PITCH_D4, 65, 88, 0, 0, 0 },
{ OCARINA_PITCH_A4, 99, 80, 0, 0, 0 },
{ OCARINA_PITCH_NONE, 0, 90, 0, 0, 0 },
},
// OCARINA_SONG_DOUBLE_TIME
{
{ OCARINA_PITCH_A4, 29, 84, 0, 0, 0 },
{ OCARINA_PITCH_NONE, 3, 84, 0, 0, 0 },
{ OCARINA_PITCH_A4, 30, 84, 0, 0, 0 },
{ OCARINA_PITCH_NONE, 3, 84, 0, 0, 0 },
{ OCARINA_PITCH_D4, 29, 84, 0, 0, 0 },
{ OCARINA_PITCH_NONE, 3, 84, 0, 0, 0 },
{ OCARINA_PITCH_D4, 30, 84, 0, 0, 0 },
{ OCARINA_PITCH_NONE, 3, 84, 0, 0, 0 },
{ OCARINA_PITCH_F4, 29, 84, 0, 0, 0 },
{ OCARINA_PITCH_NONE, 3, 84, 0, 0, 0 },
{ OCARINA_PITCH_F4, 99, 84, 0, 0, 0 },
{ OCARINA_PITCH_NONE, 0, 0, 0, 0, 0 },
},
// OCARINA_SONG_GORON_LULLABY_INTRO
{
{ OCARINA_PITCH_D4, 32, 78, 0, 0, 0 },
{ OCARINA_PITCH_A4, 33, 90, 0, 0, 0 },
{ OCARINA_PITCH_B4, 33, 87, 0, 0, 0 },
{ OCARINA_PITCH_D4, 32, 92, 0, 0, 0 },
{ OCARINA_PITCH_A4, 33, 86, 0, 0, 0 },
{ OCARINA_PITCH_B4, 130, 80, 0, 0, 0 },
{ OCARINA_PITCH_NONE, 0, 66, 0, 0, 0 },
},
// OCARINA_SONG_WIND_FISH_HUMAN
{
{ OCARINA_PITCH_D5, 89, 80, 0, 0, 0 },
{ OCARINA_PITCH_A4, 41, 72, 0, 0, 0 },
{ OCARINA_PITCH_B4, 22, 84, 0, 0, 0 },
{ OCARINA_PITCH_A4, 91, 76, 0, 0, 0 },
{ OCARINA_PITCH_NONE, 30, 66, 0, 0, 0 },
{ OCARINA_PITCH_NONE, 0, 66, 0, 0, 0 },
},
// OCARINA_SONG_WIND_FISH_GORON
{
{ OCARINA_PITCH_D4, 52, 80, 0, 0, 0 },
{ OCARINA_PITCH_NONE, 3, 66, 0, 0, 0 },
{ OCARINA_PITCH_D4, 8, 72, 0, 0, 0 },
{ OCARINA_PITCH_NONE, 3, 66, 0, 0, 0 },
{ OCARINA_PITCH_D4, 30, 84, 0, 0, 0 },
{ OCARINA_PITCH_NONE, 3, 66, 0, 0, 0 },
{ OCARINA_PITCH_F4, 34, 76, 0, 0, 0 },
{ OCARINA_PITCH_D4, 52, 80, 0, 0, 0 },
{ OCARINA_PITCH_NONE, 3, 66, 0, 0, 0 },
{ OCARINA_PITCH_D4, 8, 72, 0, 0, 0 },
{ OCARINA_PITCH_NONE, 3, 66, 0, 0, 0 },
{ OCARINA_PITCH_D4, 30, 84, 0, 0, 0 },
{ OCARINA_PITCH_NONE, 3, 66, 0, 0, 0 },
{ OCARINA_PITCH_A4, 34, 76, 0, 0, 0 },
{ OCARINA_PITCH_NONE, 0, 66, 0, 0, 0 },
},
// OCARINA_SONG_WIND_FISH_ZORA
{
{ OCARINA_PITCH_D5, 11, 80, 0, 0, 0 },
{ OCARINA_PITCH_A4, 11, 72, 0, 0, 0 },
{ OCARINA_PITCH_F4, 11, 84, 0, 0, 0 },
{ OCARINA_PITCH_D4, 100, 76, 0, 0, 0 },
{ OCARINA_PITCH_D5, 11, 84, 0, 0, 0 },
{ OCARINA_PITCH_B4, 11, 76, 0, 0, 0 },
{ OCARINA_PITCH_A4, 11, 72, 0, 0, 0 },
{ OCARINA_PITCH_F4, 100, 84, 0, 0, 0 },
{ OCARINA_PITCH_NONE, 0, 66, 0, 0, 0 },
},
// OCARINA_SONG_WIND_FISH_DEKU
{
{ OCARINA_PITCH_A4, 54, 80, 0, 0, 0 },
{ OCARINA_PITCH_D4, 77, 72, 0, 0, 0 },
{ OCARINA_PITCH_F4, 19, 84, 0, 0, 0 },
{ OCARINA_PITCH_B4, 20, 76, 0, 0, 0 },
{ OCARINA_PITCH_A4, 78, 84, 0, 0, 0 },
{ OCARINA_PITCH_NONE, 0, 66, 0, 0, 0 },
},
// OCARINA_SONG_EVAN_PART1
{
{ OCARINA_PITCH_A4, 33, 100, 0, 0, 0 },
{ OCARINA_PITCH_NONE, 3, 92, 0, 0, 0 },
{ OCARINA_PITCH_A4, 37, 104, 0, 0, 0 },
{ OCARINA_PITCH_F4, 24, 100, 0, 0, 0 },
{ OCARINA_PITCH_D4, 70, 97, 0, 0, 0 },
{ OCARINA_PITCH_NONE, 3, 96, 0, 0, 0 },
{ OCARINA_PITCH_D4, 12, 93, 0, 0, 0 },
{ OCARINA_PITCH_F4, 12, 100, 0, 0, 0 },
{ OCARINA_PITCH_A4, 12, 62, 0, 0, 0 },
{ OCARINA_PITCH_D4, 170, 91, 0, 0, 0 },
{ OCARINA_PITCH_NONE, 0, 66, 0, 0, 0 },
},
// OCARINA_SONG_EVAN_PART2
{
{ OCARINA_PITCH_B4, 33, 107, 0, 0, 0 },
{ OCARINA_PITCH_NONE, 3, 100, 0, 0, 0 },
{ OCARINA_PITCH_B4, 37, 104, 0, 0, 0 },
{ OCARINA_PITCH_A4, 24, 97, 0, 0, 0 },
{ OCARINA_PITCH_F4, 70, 104, 0, 0, 0 },
{ OCARINA_PITCH_NONE, 3, 104, 0, 0, 0 },
{ OCARINA_PITCH_F4, 12, 90, 0, 0, 0 },
{ OCARINA_PITCH_A4, 12, 96, 0, 0, 0 },
{ OCARINA_PITCH_B4, 12, 81, 0, 0, 0 },
{ OCARINA_PITCH_F4, 170, 66, 0, 0, 0 },
{ OCARINA_PITCH_NONE, 0, 66, 0, 0, 0 },
},
// OCARINA_SONG_ZELDAS_LULLABY
{
{ OCARINA_PITCH_B4, 51, 84, 0, 0, 0 },
{ OCARINA_PITCH_D5, 25, 88, 0, 0, 0 },
{ OCARINA_PITCH_A4, 78, 80, 0, 0, 0 },
{ OCARINA_PITCH_B4, 51, 84, 0, 0, 0 },
{ OCARINA_PITCH_D5, 25, 88, 0, 0, 0 },
{ OCARINA_PITCH_A4, 100, 80, 0, 0, 0 },
{ OCARINA_PITCH_NONE, 0, 90, 0, 0, 0 },
},
// OCARINA_SONG_SCARECROW_SPAWN
{
{ OCARINA_PITCH_D4, 3, 0, 0, 0, 0 },
{ OCARINA_PITCH_NONE, 0, 255, 0, 0, 0 },
},
// OCARINA_SONG_TERMINA_WALL
{
{ OCARINA_PITCH_D4, 3, 0, 0, 0, 0 },
{ OCARINA_PITCH_NONE, 0, 255, 0, 0, 0 },
},
};
OcarinaNote sOoTOcarinaSongNotes[9][20] = {
// Minuet
{
{ OCARINA_PITCH_D4, 18, 86, 0, 0, 0 },
{ OCARINA_PITCH_D5, 18, 92, 0, 0, 0 },
{ OCARINA_PITCH_B4, 72, 86, 0, 0, 0 },
{ OCARINA_PITCH_A4, 18, 80, 0, 0, 0 },
{ OCARINA_PITCH_B4, 18, 88, 0, 0, 0 },
{ OCARINA_PITCH_A4, 144, 86, 0, 0, 0 },
{ OCARINA_PITCH_NONE, 0, 86, 0, 0, 0 },
},
// Bolero
{
{ OCARINA_PITCH_F4, 15, 80, 0, 0, 0 },
{ OCARINA_PITCH_D4, 15, 72, 0, 0, 0 },
{ OCARINA_PITCH_F4, 15, 84, 0, 0, 0 },
{ OCARINA_PITCH_D4, 15, 76, 0, 0, 0 },
{ OCARINA_PITCH_A4, 15, 84, 0, 0, 0 },
{ OCARINA_PITCH_F4, 15, 74, 0, 0, 0 },
{ OCARINA_PITCH_A4, 15, 78, 0, 0, 0 },
{ OCARINA_PITCH_F4, 135, 66, 0, 0, 0 },
{ OCARINA_PITCH_NONE, 0, 66, 0, 0, 0 },
},
// Serenade
{
{ OCARINA_PITCH_D4, 36, 60, 0, 0, 0 },
{ OCARINA_PITCH_F4, 36, 78, 0, 0, 0 },
{ OCARINA_PITCH_A4, 33, 82, 0, 0, 0 },
{ OCARINA_PITCH_NONE, 3, 82, 0, 0, 0 },
{ OCARINA_PITCH_A4, 36, 84, 0, 0, 0 },
{ OCARINA_PITCH_B4, 144, 90, 0, 0, 0 },
{ OCARINA_PITCH_NONE, 0, 90, 0, 0, 0 },
},
// Requiem
{
{ OCARINA_PITCH_D4, 45, 88, 0, 0, 0 },
{ OCARINA_PITCH_F4, 23, 86, 0, 0, 0 },
{ OCARINA_PITCH_D4, 22, 84, 0, 0, 0 },
{ OCARINA_PITCH_A4, 45, 86, 0, 0, 0 },
{ OCARINA_PITCH_F4, 45, 94, 0, 0, 0 },
{ OCARINA_PITCH_D4, 180, 94, 0, 0, 0 },
{ OCARINA_PITCH_NONE, 0, 94, 0, 0, 0 },
},
// Nocturne
{
{ OCARINA_PITCH_B4, 36, 88, 0, 0, 0 },
{ OCARINA_PITCH_A4, 33, 84, 0, 0, 0 },
{ OCARINA_PITCH_NONE, 3, 84, 0, 0, 0 },
{ OCARINA_PITCH_A4, 18, 82, 0, 0, 0 },
{ OCARINA_PITCH_D4, 18, 60, 0, 0, 0 },
{ OCARINA_PITCH_B4, 18, 90, 0, 0, 0 },
{ OCARINA_PITCH_A4, 18, 88, 0, 0, 0 },
{ OCARINA_PITCH_F4, 144, 96, 0, 0, 0 },
{ OCARINA_PITCH_NONE, 0, 96, 0, 0, 0 },
},
// Prelude
{
{ OCARINA_PITCH_D5, 15, 84, 0, 0, 0 },
{ OCARINA_PITCH_A4, 45, 88, 0, 0, 0 },
{ OCARINA_PITCH_D5, 15, 88, 0, 0, 0 },
{ OCARINA_PITCH_A4, 15, 82, 0, 0, 0 },
{ OCARINA_PITCH_B4, 15, 86, 0, 0, 0 },
{ OCARINA_PITCH_D5, 60, 90, 0, 0, 0 },
{ OCARINA_PITCH_NONE, 75, 90, 0, 0, 0 },
{ OCARINA_PITCH_NONE, 0, 90, 0, 0, 0 },
},
// Sarias
{
{ OCARINA_PITCH_F4, 17, 84, 0, 0, 0 },
{ OCARINA_PITCH_A4, 17, 88, 0, 0, 0 },
{ OCARINA_PITCH_B4, 34, 80, 0, 0, 0 },
{ OCARINA_PITCH_F4, 17, 84, 0, 0, 0 },
{ OCARINA_PITCH_A4, 17, 88, 0, 0, 0 },
{ OCARINA_PITCH_B4, 136, 80, 0, 0, 0 },
{ OCARINA_PITCH_NONE, 0, 90, 0, 0, 0 },
},
// Zeldas Lullaby
{
{ OCARINA_PITCH_B4, 51, 84, 0, 0, 0 },
{ OCARINA_PITCH_D5, 25, 88, 0, 0, 0 },
{ OCARINA_PITCH_A4, 78, 80, 0, 0, 0 },
{ OCARINA_PITCH_B4, 51, 84, 0, 0, 0 },
{ OCARINA_PITCH_D5, 25, 88, 0, 0, 0 },
{ OCARINA_PITCH_A4, 100, 80, 0, 0, 0 },
{ OCARINA_PITCH_NONE, 0, 90, 0, 0, 0 },
},
// Suns Song
{
{ OCARINA_PITCH_A4, 12, 84, 0, 0, 0 },
{ OCARINA_PITCH_F4, 13, 88, 0, 0, 0 },
{ OCARINA_PITCH_D5, 29, 80, 2, 0, 0 },
{ OCARINA_PITCH_NONE, 9, 84, 0, 0, 0 },
{ OCARINA_PITCH_A4, 12, 84, 0, 0, 0 },
{ OCARINA_PITCH_F4, 13, 88, 0, 0, 0 },
{ OCARINA_PITCH_D5, 120, 80, 3, 0, 0 },
{ OCARINA_PITCH_NONE, 0, 90, 0, 0, 0 },
},
};
u8 sOoTOcarinaSongsNumNotes[] = {
6, // Minuet
8, // Bolero
5, // Serenade
6, // Requiem
7, // Nocturne
6, // Prelude
6, // Sarias
6, // Zeldas Lullaby
6, // Suns Song
};
OcarinaNote* sPlaybackSong = sOcarinaSongNotes[0];
u8 sFrogsSongNotes[14] = {
OCARINA_BTN_A, OCARINA_BTN_C_LEFT, OCARINA_BTN_C_RIGHT, OCARINA_BTN_C_DOWN, OCARINA_BTN_C_LEFT,
OCARINA_BTN_C_RIGHT, OCARINA_BTN_C_DOWN, OCARINA_BTN_A, OCARINA_BTN_C_DOWN, OCARINA_BTN_A,
OCARINA_BTN_C_DOWN, OCARINA_BTN_C_RIGHT, OCARINA_BTN_C_LEFT, OCARINA_BTN_A,
};
u8* gFrogsSongPtr = sFrogsSongNotes;
u8 sRecordingState = OCARINA_RECORD_OFF;
u8 sRecordSongPos = 0;
u32 sOcarinaRecordTaskStart = 0;
u8 sRecordOcarinaPitch = 0;
u8 sRecordOcarinaVolume = 0;
u8 sRecordOcarinaVibrato = 0;
s8 sRecordOcarinaBendIndex = 0;
u8 sRecordOcarinaButtonIndex = 0;
u8 sPlayedOcarinaSongIndexPlusOne = 0;
u8 sMusicStaffNumNotesPerTest = 0;
u8 D_801D8530 = false;
u32 D_801D8534 = 0;
u8 sOcarinaDropInputTimer = 0;
OcarinaNote sScarecrowsLongSongNotes[108] = {
{ OCARINA_PITCH_NONE, 0, 0, 0, 0, 0 },
{ OCARINA_PITCH_NONE, 0, 0, 0, 0, 0 },
};
OcarinaNote* gScarecrowLongSongPtr = sScarecrowsLongSongNotes;
u8* gScarecrowSpawnSongPtr = (u8*)&sOcarinaSongNotes[OCARINA_SONG_SCARECROW_SPAWN];
OcarinaNote* sTerminaWallSongPtr = sOcarinaSongNotes[OCARINA_SONG_TERMINA_WALL];
u8 sPitchToButtonMap[16] = {
OCARINA_BTN_A, // OCARINA_PITCH_C4
OCARINA_BTN_A, // OCARINA_PITCH_DFLAT4
OCARINA_BTN_A, // OCARINA_PITCH_D4
OCARINA_BTN_A, // OCARINA_PITCH_EFLAT4
OCARINA_BTN_C_DOWN, // OCARINA_PITCH_E4
OCARINA_BTN_C_DOWN, // OCARINA_PITCH_F4
OCARINA_BTN_C_DOWN, // OCARINA_PITCH_GFLAT4
OCARINA_BTN_C_RIGHT, // OCARINA_PITCH_G4
OCARINA_BTN_C_RIGHT, // OCARINA_PITCH_AFLAT4
OCARINA_BTN_C_RIGHT, // OCARINA_PITCH_A4
OCARINA_BTN_C_RIGHT_OR_C_LEFT, // OCARINA_PITCH_BFLAT4: Interface/Overlap between C_RIGHT and C_LEFT
OCARINA_BTN_C_LEFT, // OCARINA_PITCH_B4
OCARINA_BTN_C_LEFT, // OCARINA_PITCH_C5
OCARINA_BTN_C_UP, // OCARINA_PITCH_DFLAT5
OCARINA_BTN_C_UP, // OCARINA_PITCH_D5
OCARINA_BTN_C_UP, // OCARINA_PITCH_EFLAT5
};
// seqData written in the music macro language
// Only used in unused functions
// clang-format off
u8 sCustomSequenceScript[400] = {
/* 0 */ 0xFE, // delay1
/* 1 */ 0xFE, // delay1
/* 2 */ 0xD3, 0x20, // mutebhv 0x20
/* 4 */ 0xD7, 0x00, 0x01, // initchan 0x0001
/* 7 */ 0xCC, 0x00, // ldi 0
/* 9 */ 0x70, // stio 0
/* 10 */ 0x90, 0x00, 22, // ldchan 0, chan0
/* 13 */ 0xDB, 100, // vol 100
/* 15 */ 0xDD, 120, // tempo 120
// .sequence seq_loop
/* 17 */ 0xFE, // delay1
/* 18 */ 0x00, // testchan 0
/* 19 */ 0xF3, -4, // rbeqz seq_loop
/* 21 */ 0xFF, // end
// .channel chan0
/* 22 */ 0xC3, // short
/* 23 */ 0x88, 0x00, 41, // ldlayer 0, layer0
/* 26 */ 0x89, 0x00, 43, // ldlayer 1, layer1
/* 29 */ 0xDF, 127, // vol 127
/* 31 */ 0xE9, 0x0F, // notepri 0x0F
/* 33 */ 0xDD, 55, // pan 55
/* 35 */ 0xD4, 64, // reverb 64
/* 37 */ 0xC1, 82, // instr 82
// .channel chan_loop
/* 39 */ 0xFE, // delay1
/* 40 */ 0x80, // testlayer 0
// (no end or loop; channel script seems to run into the note layers?)
// .layer layer0
/* 41 */ 0xF3, -4, // rbeqz chan_loop
// .layer layer1
/* 43 */ 0xFF, // end
// .layer layer2?
/* 44 */ 0xC2, -5, // transpose -5
/* 46 */ 0xC0, 0, // ldelay 0
/* 48 */ 0xC1, 87, // shortvel 87
/* 50 */ 0xC9, 0, // shortgate 0
/* 52 */ 0, // empty until the end
};
// clang-format on
OcarinaSongButtons gOcarinaSongButtons[OCARINA_SONG_MAX] = {
// OCARINA_SONG_SONATA
{
7,
{
OCARINA_BTN_C_UP,
OCARINA_BTN_C_LEFT,
OCARINA_BTN_C_UP,
OCARINA_BTN_C_LEFT,
OCARINA_BTN_A,
OCARINA_BTN_C_RIGHT,
OCARINA_BTN_A,
},
},
// OCARINA_SONG_GORON_LULLABY
{
8,
{
OCARINA_BTN_A,
OCARINA_BTN_C_RIGHT,
OCARINA_BTN_C_LEFT,
OCARINA_BTN_A,
OCARINA_BTN_C_RIGHT,
OCARINA_BTN_C_LEFT,
OCARINA_BTN_C_RIGHT,
OCARINA_BTN_A,
},
},
// OCARINA_SONG_NEW_WAVE
{
7,
{
OCARINA_BTN_C_LEFT,
OCARINA_BTN_C_UP,
OCARINA_BTN_C_LEFT,
OCARINA_BTN_C_RIGHT,
OCARINA_BTN_C_DOWN,
OCARINA_BTN_C_LEFT,
OCARINA_BTN_C_RIGHT,
},
},
// OCARINA_SONG_ELEGY
{
7,
{
OCARINA_BTN_C_RIGHT,
OCARINA_BTN_C_LEFT,
OCARINA_BTN_C_RIGHT,
OCARINA_BTN_C_DOWN,
OCARINA_BTN_C_RIGHT,
OCARINA_BTN_C_UP,
OCARINA_BTN_C_LEFT,
},
},
// OCARINA_SONG_OATH
{
6,
{
OCARINA_BTN_C_RIGHT,
OCARINA_BTN_C_DOWN,
OCARINA_BTN_A,
OCARINA_BTN_C_DOWN,
OCARINA_BTN_C_RIGHT,
OCARINA_BTN_C_UP,
},
},
// OCARINA_SONG_SARIAS
{
6,
{
OCARINA_BTN_C_DOWN,
OCARINA_BTN_C_RIGHT,
OCARINA_BTN_C_LEFT,
OCARINA_BTN_C_DOWN,
OCARINA_BTN_C_RIGHT,
OCARINA_BTN_C_LEFT,
},
},
// OCARINA_SONG_TIME
{
6,
{
OCARINA_BTN_C_RIGHT,
OCARINA_BTN_A,
OCARINA_BTN_C_DOWN,
OCARINA_BTN_C_RIGHT,
OCARINA_BTN_A,
OCARINA_BTN_C_DOWN,
},
},
// OCARINA_SONG_HEALING
{
6,
{
OCARINA_BTN_C_LEFT,
OCARINA_BTN_C_RIGHT,
OCARINA_BTN_C_DOWN,
OCARINA_BTN_C_LEFT,
OCARINA_BTN_C_RIGHT,
OCARINA_BTN_C_DOWN,
},
},
// OCARINA_SONG_EPONAS
{
6,
{
OCARINA_BTN_C_UP,
OCARINA_BTN_C_LEFT,
OCARINA_BTN_C_RIGHT,
OCARINA_BTN_C_UP,
OCARINA_BTN_C_LEFT,
OCARINA_BTN_C_RIGHT,
},
},
// OCARINA_SONG_SOARING
{
6,
{
OCARINA_BTN_C_DOWN,
OCARINA_BTN_C_LEFT,
OCARINA_BTN_C_UP,
OCARINA_BTN_C_DOWN,
OCARINA_BTN_C_LEFT,
OCARINA_BTN_C_UP,
},
},
// OCARINA_SONG_STORMS
{
6,
{
OCARINA_BTN_A,
OCARINA_BTN_C_DOWN,
OCARINA_BTN_C_UP,
OCARINA_BTN_A,
OCARINA_BTN_C_DOWN,
OCARINA_BTN_C_UP,
},
},
// OCARINA_SONG_SUNS
{
6,
{
OCARINA_BTN_C_RIGHT,
OCARINA_BTN_C_DOWN,
OCARINA_BTN_C_UP,
OCARINA_BTN_C_RIGHT,
OCARINA_BTN_C_DOWN,
OCARINA_BTN_C_UP,
},
},
// OCARINA_SONG_INVERTED_TIME
{
6,
{
OCARINA_BTN_C_DOWN,
OCARINA_BTN_A,
OCARINA_BTN_C_RIGHT,
OCARINA_BTN_C_DOWN,
OCARINA_BTN_A,
OCARINA_BTN_C_RIGHT,
},
},
// OCARINA_SONG_DOUBLE_TIME
{
6,
{
OCARINA_BTN_C_RIGHT,
OCARINA_BTN_C_RIGHT,
OCARINA_BTN_A,
OCARINA_BTN_A,
OCARINA_BTN_C_DOWN,
OCARINA_BTN_C_DOWN,
},
},
// OCARINA_SONG_GORON_LULLABY_INTRO
{
6,
{
OCARINA_BTN_A,
OCARINA_BTN_C_RIGHT,
OCARINA_BTN_C_LEFT,
OCARINA_BTN_A,
OCARINA_BTN_C_RIGHT,
OCARINA_BTN_C_LEFT,
},
},
// OCARINA_SONG_WIND_FISH_HUMAN
{
4,
{
OCARINA_BTN_C_UP,
OCARINA_BTN_C_RIGHT,
OCARINA_BTN_C_LEFT,
OCARINA_BTN_C_RIGHT,
},
},
// OCARINA_SONG_WIND_FISH_GORON
{
8,
{
OCARINA_BTN_A,
OCARINA_BTN_A,
OCARINA_BTN_A,
OCARINA_BTN_C_DOWN,
OCARINA_BTN_A,
OCARINA_BTN_A,
OCARINA_BTN_A,
OCARINA_BTN_C_RIGHT,
},
},
// OCARINA_SONG_WIND_FISH_ZORA
{
8,
{
OCARINA_BTN_C_UP,
OCARINA_BTN_C_RIGHT,
OCARINA_BTN_C_DOWN,
OCARINA_BTN_A,
OCARINA_BTN_C_UP,
OCARINA_BTN_C_LEFT,
OCARINA_BTN_C_RIGHT,
OCARINA_BTN_C_DOWN,
},
},
// OCARINA_SONG_WIND_FISH_DEKU
{
5,
{
OCARINA_BTN_C_RIGHT,
OCARINA_BTN_A,
OCARINA_BTN_C_DOWN,
OCARINA_BTN_C_LEFT,
OCARINA_BTN_C_RIGHT,
},
},
// OCARINA_SONG_EVAN_PART1
{
8,
{
OCARINA_BTN_C_RIGHT,
OCARINA_BTN_C_RIGHT,
OCARINA_BTN_C_DOWN,
OCARINA_BTN_A,
OCARINA_BTN_A,
OCARINA_BTN_C_DOWN,
OCARINA_BTN_C_RIGHT,
OCARINA_BTN_A,
},
},
// OCARINA_SONG_EVAN_PART2
{
8,
{
OCARINA_BTN_C_LEFT,
OCARINA_BTN_C_LEFT,
OCARINA_BTN_C_RIGHT,
OCARINA_BTN_C_DOWN,
OCARINA_BTN_C_DOWN,
OCARINA_BTN_C_RIGHT,
OCARINA_BTN_C_LEFT,
OCARINA_BTN_C_DOWN,
},
},
// OCARINA_SONG_ZELDAS_LULLABY
{
6,
{
OCARINA_BTN_C_LEFT,
OCARINA_BTN_C_UP,
OCARINA_BTN_C_RIGHT,
OCARINA_BTN_C_LEFT,
OCARINA_BTN_C_UP,
OCARINA_BTN_C_RIGHT,
},
},
// OCARINA_SONG_SCARECROW_SPAWN
{
8,
{
OCARINA_BTN_A,
OCARINA_BTN_A,
OCARINA_BTN_A,
OCARINA_BTN_A,
OCARINA_BTN_A,
OCARINA_BTN_A,
OCARINA_BTN_A,
OCARINA_BTN_A,
},
},
// OCARINA_SONG_TERMINA_WALL
{
8,
{
OCARINA_BTN_A,
OCARINA_BTN_C_DOWN,
OCARINA_BTN_C_RIGHT,
OCARINA_BTN_C_LEFT,
OCARINA_BTN_C_UP,
OCARINA_BTN_C_LEFT,
OCARINA_BTN_C_RIGHT,
OCARINA_BTN_C_DOWN,
},
},
};
const u16 gAudioEnvironmentalSfx[] = {
NA_SE_EV_RIVER_STREAM - SFX_FLAG, NA_SE_EV_WAVE - SFX_FLAG,
NA_SE_EV_WATER_WALL_BIG - SFX_FLAG, NA_SE_EV_WATER_WALL - SFX_FLAG,
NA_SE_EV_MAGMA_LEVEL - SFX_FLAG, NA_SE_EV_MAGMA_LEVEL_M - SFX_FLAG,
NA_SE_EV_MAGMA_LEVEL_L - SFX_FLAG, NA_SE_EV_TORCH - SFX_FLAG,
NA_SE_EV_FOUNTAIN - SFX_FLAG, NA_SE_EV_DRAIN - SFX_FLAG,
NA_SE_EV_CROWD - SFX_FLAG, NA_SE_EV_WATER_CONVECTION - SFX_FLAG,
NA_SE_EV_GORON_CHEER - SFX_FLAG, NA_SE_EV_WATER_WALL_BIG_SILENT - SFX_FLAG,
NA_SE_EV_WATER_BUBBLE - SFX_FLAG, NA_SE_EV_COW_CRY_LV - SFX_FLAG,
NA_SE_EV_MAKE_TURRET - SFX_FLAG, NA_SE_EV_BOILED_WATER_S - SFX_FLAG,
NA_SE_EV_BOILED_WATER_L - SFX_FLAG, NA_SE_EV_WAVE_S - SFX_FLAG,
NA_SE_EV_WAVE_S - SFX_FLAG, NA_SE_EV_WAVE_S - SFX_FLAG,
};
const u8 sIsOcarinaSongReserved[OCARINA_SONG_MAX] = {
true, // OCARINA_SONG_SONATA
true, // OCARINA_SONG_GORON_LULLABY
true, // OCARINA_SONG_NEW_WAVE
true, // OCARINA_SONG_ELEGY
true, // OCARINA_SONG_OATH
false, // OCARINA_SONG_SARIAS
true, // OCARINA_SONG_TIME
true, // OCARINA_SONG_HEALING
true, // OCARINA_SONG_EPONAS
true, // OCARINA_SONG_SOARING
true, // OCARINA_SONG_STORMS
false, // OCARINA_SONG_SUNS
true, // OCARINA_SONG_INVERTED_TIME
true, // OCARINA_SONG_DOUBLE_TIME
true, // OCARINA_SONG_GORON_LULLABY_INTRO
false, // OCARINA_SONG_WIND_FISH_HUMAN
false, // OCARINA_SONG_WIND_FISH_GORON
false, // OCARINA_SONG_WIND_FISH_ZORA
false, // OCARINA_SONG_WIND_FISH_DEKU
true, // OCARINA_SONG_EVAN_PART1
true, // OCARINA_SONG_EVAN_PART2
false, // OCARINA_SONG_ZELDAS_LULLABY
true, // OCARINA_SONG_SCARECROW_SPAWN
false, // OCARINA_SONG_TERMINA_WALL
};
const char sAudioOcarinaUnusedText0[] = "key step is too long !!! %d:%d>%d\n";
const char sAudioOcarinaUnusedText1[] = "You played %d Melody !!! (last step:%d)\n";
const char sAudioOcarinaUnusedText2[] = "pass 0\n";
const char sAudioOcarinaUnusedText3[] = "pass 1\n";
const char sAudioOcarinaUnusedText4[] = "pass 2\n";
const char sAudioOcarinaUnusedText5[] = "last key is bad !!! %d %d %02X %02X\n";
const char sAudioOcarinaUnusedText6[] = "last key step is too short !!! %d:%d %d<%d\n";
const char sAudioOcarinaUnusedText7[] = "check is over!!! %d %d %d\n";
void AudioOcarina_ReadControllerInput(void) {
Input inputs[MAXCONTROLLERS];
Input* input = &inputs[0];
u32 ocarinaInputButtonPrev = sOcarinaInputButtonCur;
PadMgr_GetInput2(inputs, false);
sOcarinaInputButtonCur = input->cur.button;
sOcarinaInputButtonPrev = ocarinaInputButtonPrev;
sOcarinaInputStickRel.x = input->rel.stick_x;
sOcarinaInputStickRel.y = input->rel.stick_y;
}
/**
* Looks up the frequency to bend the pitch by.
* The pitch will bend up to a maximum of 2 semitones
* in each direction giving a total range of 4 semitones
*/
f32 AudioOcarina_BendPitchTwoSemitones(s8 bendIndex) {
s8 adjBendIndex;
f32 bendFreq;
if (bendIndex > 64) {
adjBendIndex = 127;
} else if (bendIndex < -64) {
adjBendIndex = -128;
} else if (bendIndex >= 0) {
adjBendIndex = (bendIndex * 127) / 64;
} else {
adjBendIndex = (bendIndex * 128) / 64;
}
/**
* index 128 is in the middle of the table and
* contains the value 1.0f i.e. no bend
* absolute indices above 128 will bend the pitch 2 semitones upwards
* absolute indices below 128 will bend the pitch 2 semitones downwards
*/
bendFreq = gBendPitchTwoSemitonesFrequencies[adjBendIndex + 128];
return bendFreq;
}
/**
* If an available song has been played, then return that song index
* If the ocarina is on, but no song has been played then return 0xFE
* If the ocarina is off, return 0xFF
*/
u8 AudioOcarina_GetPlayingState(void) {
u8 playedOcarinaSongIndex;
if (sPlayedOcarinaSongIndexPlusOne != 0) {
playedOcarinaSongIndex = sPlayedOcarinaSongIndexPlusOne - 1;
sPlayedOcarinaSongIndexPlusOne = 0;
} else if (sOcarinaFlags != 0) {
playedOcarinaSongIndex = 0xFE;
} else {
playedOcarinaSongIndex = 0xFF;
}
return playedOcarinaSongIndex;
}
u8 AudioOcarina_MapPitchToButton(u8 pitchAndBFlatFlag) {
u8 buttonIndex = sPitchToButtonMap[pitchAndBFlatFlag & 0x3F];
/**
* Special case for bFlat4:
* CRIGHT and CLEFT are the only two pitches that are 2 semitones apart
* which are pitches A4 and B4 respectively
* bFlat4 is in the middle of those two and is the only pitch that can not
* be resolved between the two buttons without external information.
* That information is stored as flags in pitch with the mask:
* (pitchAndBFlatFlag & 0xC0)
*/
if (buttonIndex == OCARINA_BTN_C_RIGHT_OR_C_LEFT) {
if (pitchAndBFlatFlag & OCARINA_BUTTON_FLAG_BFLAT_RAISE) {
return OCARINA_BTN_C_RIGHT;
}
// OCARINA_BUTTON_FLAG_BFLAT_LOWER
return OCARINA_BTN_C_LEFT;
}
return buttonIndex;
}
void AudioOcarina_MapSongFromPitchToButton(u8 noteSongIndex, u8 buttonSongIndex, u8 numButtons) {
u8 buttonSongPos = 0;
u8 noteSongPos = 0;
u8 pitch;
while ((buttonSongPos < numButtons) && (noteSongPos < 16)) {
pitch = sOcarinaSongNotes[noteSongIndex][noteSongPos++].pitch;
if (pitch != OCARINA_PITCH_NONE) {
gOcarinaSongButtons[buttonSongIndex].buttonIndex[buttonSongPos++] = sPitchToButtonMap[pitch];
}
}
gOcarinaSongButtons[buttonSongIndex].numButtons = numButtons;
}
/**
* Ocarina flags:
* bitmask 0x3FFF:
* - Ocarina song id
* bitmask 0xC000:
* - 0x0000: Limits the notes to 8 notes at a time. Not playing a correct song after 8 notes will cause an ocarina
* error
* - 0x4000: (Identical to 0xC000)
* - 0x8000: Limits the notes to 1 note at a time. A single incorrect note will cause an ocarina error
* - 0xC000: Free-play, no limitations to the number of notes to play
* bitmask 0x7FFF0000:
* - ocarina action (only used to make flags != 0)
* bitmask 0x80000000:
* - unused (only used to make flags != 0)
*/
// The ocarina songs that can be performed at any time = 0x3FFF
#define OCARINA_SONGS_PLAYABLE_FLAGS \
((1 << OCARINA_SONG_SONATA) | (1 << OCARINA_SONG_GORON_LULLABY) | (1 << OCARINA_SONG_NEW_WAVE) | \
(1 << OCARINA_SONG_ELEGY) | (1 << OCARINA_SONG_OATH) | (1 << OCARINA_SONG_SARIAS) | (1 << OCARINA_SONG_TIME) | \
(1 << OCARINA_SONG_HEALING) | (1 << OCARINA_SONG_EPONAS) | (1 << OCARINA_SONG_SOARING) | \
(1 << OCARINA_SONG_STORMS) | (1 << OCARINA_SONG_SUNS) | (1 << OCARINA_SONG_INVERTED_TIME) | \
(1 << OCARINA_SONG_DOUBLE_TIME))
void AudioOcarina_Start(u32 ocarinaFlags) {
u8 songIndex;
if ((sOcarinaSongNotes[OCARINA_SONG_SCARECROW_SPAWN][1].volume != 0xFF) &&
((ocarinaFlags & OCARINA_SONGS_PLAYABLE_FLAGS) == OCARINA_SONGS_PLAYABLE_FLAGS)) {
ocarinaFlags |= (1 << OCARINA_SONG_SCARECROW_SPAWN);
}
if ((ocarinaFlags == (0xC0000000 | OCARINA_SONGS_PLAYABLE_FLAGS)) &&
(sOcarinaSongNotes[OCARINA_SONG_SCARECROW_SPAWN][1].volume != 0xFF)) {
ocarinaFlags = (0xC0000000 | OCARINA_SONGS_PLAYABLE_FLAGS);
}
if ((ocarinaFlags == OCARINA_SONGS_PLAYABLE_FLAGS) &&
(sOcarinaSongNotes[OCARINA_SONG_SCARECROW_SPAWN][1].volume != 0xFF)) {
ocarinaFlags = OCARINA_SONGS_PLAYABLE_FLAGS;
}
if (ocarinaFlags != 0xFFFF) {
sOcarinaFlags = 0x80000000 + ocarinaFlags;
sFirstOcarinaSongIndex = 0;
sLastOcarinaSongIndex = OCARINA_SONG_MAX;
sOcarinaAvailableSongFlags = ocarinaFlags & 0xFFFFFF;
sMusicStaffNumNotesPerTest = 8; // Ocarina Check
sOcarinaHasStartedSong = false;
sPlayedOcarinaSongIndexPlusOne = 0;
sOcarinaStaffPlayingPos = 0;
sPlayingStaff.state = AudioOcarina_GetPlayingState();
sIsOcarinaInputEnabled = true;
sPrevOcarinaWithMusicStaffFlags = 0;
// Reset music staff song check
for (songIndex = OCARINA_SONG_SONATA; songIndex <= OCARINA_SONG_EVAN_PART2; songIndex++) {
for (sMusicStaffPos[songIndex] = 0;
sOcarinaSongNotes[songIndex][sMusicStaffPos[songIndex]].pitch == OCARINA_PITCH_NONE;) {
sMusicStaffPos[songIndex]++;
}
sMusicStaffCurHeldLength[songIndex] = 0;
sMusicStaffExpectedLength[songIndex] = 0;
sMusicStaffExpectedPitch[songIndex] = 0;
if (D_801D8530) {
if ((1 << songIndex) & ocarinaFlags) {
D_801FD518[songIndex] = 0;
} else {
D_801FD518[songIndex] = 0xFF;
}
}
}
if (ocarinaFlags & 0x80000000) {
sMusicStaffNumNotesPerTest = 0; // Ocarina Playback
}
if (ocarinaFlags & 0x40000000) {
sOcarinaWithoutMusicStaffPos = 0;
}
if (ocarinaFlags & 0xC0400000) {
AudioOcarina_MapSongFromPitchToButton(OCARINA_SONG_SCARECROW_SPAWN, OCARINA_SONG_SCARECROW_SPAWN, 8);
}
} else {
sOcarinaFlags = 0;
sIsOcarinaInputEnabled = false;
}
}
#undef OCARINA_SONGS_PLAYABLE_FLAGS
void AudioOcarina_SetSongStartingPos(void) {
sOcarinaSongStartingPos = sOcarinaWithoutMusicStaffPos;
}
void AudioOcarina_StartAtSongStartingPos(u32 ocarinaFlags) {
D_801D8530 = false;
AudioOcarina_Start(ocarinaFlags);
if (sOcarinaSongStartingPos != 0) {
sOcarinaWithoutMusicStaffPos = sOcarinaSongStartingPos;
sOcarinaSongStartingPos = 0;
}
}
void AudioOcarina_StartForSongCheck(u32 ocarinaFlags, u8 ocarinaStaffPlayingPosStart) {
u8 songIndex;
u8 j;
AudioOcarina_Start(ocarinaFlags);
sMusicStaffNumNotesPerTest = 8;
sOcarinaStaffPlayingPos = ocarinaStaffPlayingPosStart;
for (songIndex = 0; songIndex <= OCARINA_SONG_EVAN_PART2; songIndex++) {
for (j = 0; j < ocarinaStaffPlayingPosStart;) {
if (sOcarinaSongNotes[songIndex][sMusicStaffPos[songIndex]].pitch != OCARINA_PITCH_NONE) {
j++;
}
sMusicStaffPos[songIndex]++;
}
if (sOcarinaSongNotes[songIndex][sMusicStaffPos[songIndex]].pitch == OCARINA_PITCH_NONE) {
sMusicStaffPos[songIndex]++;
}
}
}
void AudioOcarina_StartWithSongNoteLengths(u32 ocarinaFlags) {
u8 songIndex;
for (songIndex = 0; songIndex < OCARINA_SONG_MAX; songIndex++) {
if ((1 << songIndex) & ocarinaFlags) {
D_801FD530[songIndex] = 0;
} else {
D_801FD530[songIndex] = 0xFF;
}
}
D_801D8530 = true;
D_801D8534 = ocarinaFlags;
AudioOcarina_Start(ocarinaFlags);
}
void AudioOcarina_StartDefault(u32 ocarinaFlags) {
D_801D8530 = false;
AudioOcarina_Start(ocarinaFlags);
}
u8 func_8019B568(void) {
u32 temp_v0 = D_801D8534;
u8 songIndex;
for (songIndex = OCARINA_SONG_SONATA; !((temp_v0 >> songIndex) & 1) && (songIndex < OCARINA_SONG_MAX);
songIndex++) {}
return songIndex;
}
u8 func_8019B5AC(void) {
u8 songIndex = func_8019B568();
if (songIndex < OCARINA_SONG_MAX) {
return D_801FD518[songIndex];
}
return 0xFF;
}
u8 func_8019B5EC(void) {
return D_801FD530[func_8019B568()];
}
void AudioOcarina_CheckIfStartedSong(void) {
if ((sCurOcarinaPitch != OCARINA_PITCH_NONE) && !sOcarinaHasStartedSong) {
sOcarinaHasStartedSong = true;
sMusicStaffPrevPitch = OCARINA_PITCH_NONE;
}
}
void AudioOcarina_UpdateCurOcarinaSong(void) {
u8 i;
if (sOcarinaWithoutMusicStaffPos == 8) {
for (i = 0; i < ARRAY_COUNT(sCurOcarinaSongWithoutMusicStaff) - 1; i++) {
sCurOcarinaSongWithoutMusicStaff[i] = sCurOcarinaSongWithoutMusicStaff[i + 1];
}
} else {
sOcarinaWithoutMusicStaffPos++;
}
}
/**
* Checks for ocarina songs from user input with a music staff prompt
* Type 1) Playback: tests note-by-note (ocarinaFlag & 0xC000 == 0x8000) eg:
* - learning a new song
* - playing the ocarina memory game
* Type 2) Check: tests in 8-note chunks (ocarinaFlag & 0xC000 == 0x0000) eg:
* - validating scarecrow spawn song as adult
* - ocarina prompt for zelda's lullaby, saria's song, Storms, Song of Time, etc...
*/
void AudioOcarina_CheckSongsWithMusicStaff(void) {
u32 curOcarinaSongFlag;
s32 pad;
u8 noNewValidInput = false;
s16 pad2;
s8 staffOcarinaPlayingPosOffset = 0;
u8 songIndex;
OcarinaNote* curNote;
OcarinaNote* nextNote;
AudioOcarina_CheckIfStartedSong();
if (!sOcarinaHasStartedSong) {
return;
}
if (ABS_ALT(sCurOcarinaBendIndex) > 20) {
sOcarinaFlags = 0;
for (songIndex = OCARINA_SONG_SONATA; songIndex < OCARINA_SONG_MAX; songIndex++) {
D_801FD518[songIndex] = 4;
}
sIsOcarinaInputEnabled = false;
return;
}
if ((sPrevOcarinaPitch == sCurOcarinaPitch) || (sCurOcarinaPitch == OCARINA_PITCH_NONE)) {
noNewValidInput = true;
} else {
AudioOcarina_UpdateCurOcarinaSong();
sCurOcarinaSongWithoutMusicStaff[sOcarinaWithoutMusicStaffPos - 1] = sCurOcarinaPitch;
}
for (songIndex = sFirstOcarinaSongIndex; songIndex < sLastOcarinaSongIndex; songIndex++) {
curOcarinaSongFlag = 1 << songIndex;
if (sOcarinaAvailableSongFlags & curOcarinaSongFlag) {
if (D_801D8530) {
sMusicStaffCurHeldLength[songIndex] += sOcarinaUpdateTaskStart - sOcarinaPlaybackTaskStart;
} else {
sMusicStaffCurHeldLength[songIndex] = sMusicStaffExpectedLength[songIndex] + 9;
}
if (noNewValidInput) {
if ((sMusicStaffCurHeldLength[songIndex] > 8) &&
(sMusicStaffPrevPitch != sMusicStaffExpectedPitch[songIndex])) {
sOcarinaAvailableSongFlags ^= curOcarinaSongFlag;
if (D_801D8530) {
D_801FD518[songIndex] = 1;
}
}
if (D_801D8530 && ((sMusicStaffExpectedLength[songIndex] + 9) < sMusicStaffCurHeldLength[songIndex])) {
sOcarinaAvailableSongFlags ^= curOcarinaSongFlag;
D_801FD518[songIndex] = 3;
} else if ((sMusicStaffCurHeldLength[songIndex] >= (sMusicStaffExpectedLength[songIndex] - 9)) &&
(sMusicStaffCurHeldLength[songIndex] >= sMusicStaffExpectedLength[songIndex]) &&
(sOcarinaSongNotes[songIndex][sMusicStaffPos[songIndex]].length == 0) &&
(sMusicStaffPrevPitch == sMusicStaffExpectedPitch[songIndex])) {
// This case is taken if the song is finished and successfully played
// (i.e. .length == 0 indicates that the song is at the end)
sPlayedOcarinaSongIndexPlusOne = songIndex + 1;
sIsOcarinaInputEnabled = false;
sOcarinaFlags = 0;
if (D_801D8530) {
D_801FD518[songIndex] = 5;
}
}
} else if (sMusicStaffCurHeldLength[songIndex] >= (sMusicStaffExpectedLength[songIndex] - 9)) {
// This else-if statement always holds true, taken if a new note is played
if (sMusicStaffPrevPitch != OCARINA_PITCH_NONE) {
// New note is played
if (sMusicStaffPrevPitch == sMusicStaffExpectedPitch[songIndex]) {
// Note is part of expected song
if (D_801D8530) {
D_801FD530[songIndex] +=
ABS_ALT(sMusicStaffExpectedLength[songIndex] - sMusicStaffCurHeldLength[songIndex]);
}
sMusicStaffCurHeldLength[songIndex] = 0;
} else {
// Note is not part of expected song, so this song is no longer available as an option in this
// playback
sOcarinaAvailableSongFlags ^= curOcarinaSongFlag;
if (D_801D8530) {
D_801FD518[songIndex] = 1;
}
}
}
curNote = &sOcarinaSongNotes[songIndex][sMusicStaffPos[songIndex]];
nextNote = &sOcarinaSongNotes[songIndex][++sMusicStaffPos[songIndex]];
sMusicStaffExpectedLength[songIndex] = curNote->length;
sMusicStaffExpectedPitch[songIndex] = curNote->pitch;
while ((curNote->pitch == nextNote->pitch) ||
((nextNote->pitch == OCARINA_PITCH_NONE) && (nextNote->length != 0))) {
sMusicStaffExpectedLength[songIndex] += nextNote->length;
curNote = &sOcarinaSongNotes[songIndex][sMusicStaffPos[songIndex]];
nextNote = &sOcarinaSongNotes[songIndex][sMusicStaffPos[songIndex] + 1];
sMusicStaffPos[songIndex]++;
}
} else if (sMusicStaffCurHeldLength[songIndex] < 9) {
// case never taken
staffOcarinaPlayingPosOffset = -1;
sMusicStaffCurHeldLength[songIndex] = 0;
sMusicStaffPrevPitch = sCurOcarinaPitch;
} else {
// case never taken
if (sOcarinaSongNotes[songIndex][sMusicStaffPos[songIndex]].length == 0) {
D_801FD518[songIndex] = 1;
} else if (D_801D8530) {
D_801FD518[songIndex] = 2;
}
sOcarinaAvailableSongFlags ^= curOcarinaSongFlag;
}
}
// if a note is played that doesn't match a song, the song bit in sAvailOcarinaSongFlags is turned off
// if there are no more songs remaining that it could be and the maximum position has been exceeded, then
if ((sOcarinaAvailableSongFlags == 0) && (sOcarinaStaffPlayingPos >= sMusicStaffNumNotesPerTest)) {
sIsOcarinaInputEnabled = false;
if (!D_801D8530) {
if ((sOcarinaFlags & 0x40000000) && (sCurOcarinaPitch == sOcarinaSongNotes[songIndex][0].pitch)) {
// case never taken, this function is not called if (sOcarinaFlags & 0x40000000) is set
sPrevOcarinaWithMusicStaffFlags = sOcarinaFlags;
}
}
sOcarinaFlags = 0;
return;
}
}
if (!noNewValidInput) {
sMusicStaffPrevPitch = sCurOcarinaPitch;
sOcarinaStaffPlayingPos += staffOcarinaPlayingPosOffset + 1;
}
}
/**
* Checks for ocarina songs from user input with no music staff prompt.
* Includes ocarina actions such as free play, no warp
*/
void AudioOcarina_CheckSongsWithoutMusicStaff(void) {
u32 pitch;
u8 ocarinaStaffPlayingPosStart;
u8 songIndex;
u8 j;
u8 k;
if (CHECK_BTN_ANY(sOcarinaInputButtonCur, BTN_L) &&
CHECK_BTN_ANY(sOcarinaInputButtonCur, BTN_A | BTN_CRIGHT | BTN_CLEFT | BTN_CDOWN | BTN_CUP)) {
AudioOcarina_StartDefault(sOcarinaFlags);
return;
}
AudioOcarina_CheckIfStartedSong();
if (!sOcarinaHasStartedSong) {
return;
}
ocarinaStaffPlayingPosStart = sOcarinaStaffPlayingPos;
if ((sPrevOcarinaPitch != sCurOcarinaPitch) && (sCurOcarinaPitch != OCARINA_PITCH_NONE)) {
sOcarinaStaffPlayingPos++;
if (sOcarinaStaffPlayingPos > ARRAY_COUNT(sCurOcarinaSongWithoutMusicStaff)) {
sOcarinaStaffPlayingPos = 1;
}
AudioOcarina_UpdateCurOcarinaSong();
if ((ABS_ALT(sCurOcarinaBendIndex) > 20) && (ocarinaStaffPlayingPosStart != sOcarinaStaffPlayingPos)) {
sCurOcarinaSongWithoutMusicStaff[sOcarinaWithoutMusicStaffPos - 1] = OCARINA_PITCH_NONE;
} else {
sCurOcarinaSongWithoutMusicStaff[sOcarinaWithoutMusicStaffPos - 1] = sCurOcarinaPitch;
}
// This nested for-loop tests to see if the notes from the ocarina are identical
// to any of the songIndex from sFirstOcarinaSongIndex to sLastOcarinaSongIndex
// Loop through each of the songs
for (songIndex = sFirstOcarinaSongIndex; songIndex < sLastOcarinaSongIndex; songIndex++) {
// Checks to see if the song is available to be played
if ((u32)sOcarinaAvailableSongFlags & (1 << songIndex)) {
// Loops through all possible starting indices?
// Loops through the notes of the song?
for (j = 0, k = 0; (j < gOcarinaSongButtons[songIndex].numButtons) && (k == 0) &&
(sOcarinaWithoutMusicStaffPos >= gOcarinaSongButtons[songIndex].numButtons);) {
pitch = sCurOcarinaSongWithoutMusicStaff[(sOcarinaWithoutMusicStaffPos -
gOcarinaSongButtons[songIndex].numButtons) +
j];
if (pitch == sButtonToPitchMap[gOcarinaSongButtons[songIndex].buttonIndex[j]]) {
j++;
} else {
k++;
}
}
// This conditional is true if songIndex = i is detected
if (j == gOcarinaSongButtons[songIndex].numButtons) {
sPlayedOcarinaSongIndexPlusOne = songIndex + 1;
sIsOcarinaInputEnabled = false;
sOcarinaFlags = 0;
}
}
}
}
}
void AudioOcarina_PlayControllerInput(u8 isOcarinaSfxSuppressedWhenCancelled) {
u32 ocarinaBtnsHeld;
// Prevents two different ocarina notes from being played on two consecutive frames
if ((sOcarinaFlags != 0) && (sOcarinaDropInputTimer != 0)) {
sOcarinaDropInputTimer--;
return;
}
// Ensures the button pressed to start the ocarina does not also play an ocarina note
if ((sOcarinaInputButtonStart == 0) ||
((sOcarinaInputButtonStart & (BTN_A | BTN_CRIGHT | BTN_CLEFT | BTN_CDOWN | BTN_CUP)) !=
(sOcarinaInputButtonCur & (BTN_A | BTN_CRIGHT | BTN_CLEFT | BTN_CDOWN | BTN_CUP)))) {
sOcarinaInputButtonStart = 0;
if (1) {}
sCurOcarinaPitch = OCARINA_PITCH_NONE;
sCurOcarinaButtonIndex = OCARINA_BTN_INVALID;
ocarinaBtnsHeld = (sOcarinaInputButtonCur & (BTN_A | BTN_CRIGHT | BTN_CLEFT | BTN_CDOWN | BTN_CUP)) &
(sOcarinaInputButtonPrev & (BTN_A | BTN_CRIGHT | BTN_CLEFT | BTN_CDOWN | BTN_CUP));
if (!(sOcarinaInputButtonPress & ocarinaBtnsHeld) && (sOcarinaInputButtonCur != 0)) {
sOcarinaInputButtonPress = sOcarinaInputButtonCur;
} else {
sOcarinaInputButtonPress &= ocarinaBtnsHeld;
}
// Interprets and transforms controller input into ocarina buttons and notes
if (CHECK_BTN_ANY(sOcarinaInputButtonPress, BTN_A)) {
sCurOcarinaPitch = OCARINA_PITCH_D4;
sCurOcarinaButtonIndex = OCARINA_BTN_A;
} else if (CHECK_BTN_ANY(sOcarinaInputButtonPress, BTN_CDOWN)) {
sCurOcarinaPitch = OCARINA_PITCH_F4;
sCurOcarinaButtonIndex = OCARINA_BTN_C_DOWN;
} else if (CHECK_BTN_ANY(sOcarinaInputButtonPress, BTN_CRIGHT)) {
sCurOcarinaPitch = OCARINA_PITCH_A4;
sCurOcarinaButtonIndex = OCARINA_BTN_C_RIGHT;
} else if (CHECK_BTN_ANY(sOcarinaInputButtonPress, BTN_CLEFT)) {
sCurOcarinaPitch = OCARINA_PITCH_B4;
sCurOcarinaButtonIndex = OCARINA_BTN_C_LEFT;
} else if (CHECK_BTN_ANY(sOcarinaInputButtonPress, BTN_CUP)) {
sCurOcarinaPitch = OCARINA_PITCH_D5;
sCurOcarinaButtonIndex = OCARINA_BTN_C_UP;
}
if (sOcarinaInputButtonCur) {}
// Pressing the R Button will raise the pitch by 1 semitone
if ((sCurOcarinaPitch != OCARINA_PITCH_NONE) && CHECK_BTN_ANY(sOcarinaInputButtonCur, BTN_R) &&
(sRecordingState != OCARINA_RECORD_SCARECROW_SPAWN)) {
sCurOcarinaButtonIndex += OCARINA_BUTTON_FLAG_BFLAT_RAISE; // Flag to resolve B Flat 4
sCurOcarinaPitch++; // Raise the pitch by 1 semitone
}
// Pressing the Z Button will lower the pitch by 1 semitone
if ((sCurOcarinaPitch != OCARINA_PITCH_NONE) && CHECK_BTN_ANY(sOcarinaInputButtonCur, BTN_Z) &&
(sRecordingState != OCARINA_RECORD_SCARECROW_SPAWN)) {
sCurOcarinaButtonIndex += OCARINA_BUTTON_FLAG_BFLAT_LOWER; // Flag to resolve B Flat 4
sCurOcarinaPitch--; // Lower the pitch by 1 semitone
}
if (sRecordingState != OCARINA_RECORD_SCARECROW_SPAWN) {
// Bend the pitch of the note based on y control stick
sCurOcarinaBendIndex = sOcarinaInputStickRel.y;
sCurOcarinaBendFreq = AudioOcarina_BendPitchTwoSemitones(sCurOcarinaBendIndex);
// Add vibrato of the ocarina note based on the x control stick
sCurOcarinaVibrato = ABS_ALT(sOcarinaInputStickRel.x) >> 2;
// Sets vibrato to io port 6
AUDIOCMD_CHANNEL_SET_IO(SEQ_PLAYER_SFX, SFX_CHANNEL_OCARINA, 6, sCurOcarinaVibrato);
} else {
// no bending or vibrato for recording state OCARINA_RECORD_SCARECROW_SPAWN
sCurOcarinaBendIndex = 0;
sCurOcarinaVibrato = 0;
sCurOcarinaBendFreq = 1.0f; // No bend
}
// Processes new and valid notes
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
AUDIOCMD_CHANNEL_SET_IO(SEQ_PLAYER_SFX, SFX_CHANNEL_OCARINA, 7, sOcarinaInstrumentId - 1);
// Sets pitch to io port 5
AUDIOCMD_CHANNEL_SET_IO(SEQ_PLAYER_SFX, SFX_CHANNEL_OCARINA, 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
AudioSfx_StopById(NA_SE_OC_OCARINA);
}
}
}
/**
* Directly enable the ocarina to receive input without
* properly resetting it based on an ocarina instrument id
* Unused.
*/
void AudioOcarina_EnableInput(u8 inputEnabled) {
sIsOcarinaInputEnabled = inputEnabled;
}
/**
* Resets ocarina properties
*/
void AudioOcarina_ResetAndMute(void) {
sOcarinaInputButtonCur = 0;
sOcarinaInputButtonPrev = 0;
sOcarinaInputButtonPress = 0;
sOcarinaInputButtonStart = 0xFFFF;
AudioOcarina_PlayControllerInput(false);
AudioSfx_StopById(NA_SE_OC_OCARINA);
if (gAudioSpecId != 12) {
AudioSfx_MuteBanks(0);
}
sPlaybackState = 0;
sPlaybackStaffPos = 0;
sIsOcarinaInputEnabled = false;
sOcarinaFlags = 0;
// return to full volume for both bgm players after ocarina is finished
AudioSfx_RestoreBgmVolume(SFX_CHANNEL_OCARINA);
// return to full volume for all sfx channels except system & ocarina banks
Audio_SetSfxVolumeExceptSystemAndOcarinaBanks(0x7F);
}
void AudioOcarina_ResetAndReadInput(void) {
sOcarinaInputButtonCur = 0;
sOcarinaInputButtonPrev = 0;
sOcarinaInputButtonPress = 0;
sOcarinaInputButtonStart = 0xFFFF;
AudioOcarina_PlayControllerInput(true);
sPlaybackState = 0;
sPlaybackStaffPos = 0;
sIsOcarinaInputEnabled = false;
sOcarinaFlags = 0;
sOcarinaInputButtonCur = 0;
AudioOcarina_ReadControllerInput();
sOcarinaInputButtonStart = sOcarinaInputButtonCur;
}
/**
* Set a timer that will disable the ocarina once the timer reaches 0
*/
void AudioOcarina_SetOcarinaDisableTimer(u8 unused, u8 timer) {
sOcarinaDisableTimer = timer;
sOcarinaUnused = unused;
}
void AudioOcarina_SetInstrument(u8 ocarinaInstrumentId) {
if ((sOcarinaInstrumentId != ocarinaInstrumentId) || (ocarinaInstrumentId == OCARINA_INSTRUMENT_DEFAULT)) {
SEQCMD_SET_CHANNEL_IO(SEQ_PLAYER_SFX, SFX_CHANNEL_OCARINA, 1, ocarinaInstrumentId);
sOcarinaInstrumentId = ocarinaInstrumentId;
if (ocarinaInstrumentId == OCARINA_INSTRUMENT_OFF) {
AudioOcarina_ResetAndMute();
} else {
sOcarinaInputButtonCur = 0;
AudioOcarina_ReadControllerInput();
sOcarinaInputButtonStart = sOcarinaInputButtonCur;
// lowers volume of all sfx channels except system & ocarina banks
Audio_SetSfxVolumeExceptSystemAndOcarinaBanks(0x40);
// lowers volume of bgm players while playing ocarina
AudioSfx_LowerBgmVolume(SFX_CHANNEL_OCARINA);
}
}
}
void AudioOcarina_SetPlaybackSong(s8 songIndexPlusOne, u8 playbackState) {
u8 i = 0;
if (songIndexPlusOne == 0) {
sPlaybackState = 0;
AudioSfx_StopById(NA_SE_OC_OCARINA);
return;
}
if (songIndexPlusOne < (OCARINA_SONG_MAX + 1)) {
sPlaybackSong = sOcarinaSongNotes[songIndexPlusOne - 1];
} else {
sPlaybackSong = sScarecrowsLongSongNotes;
}
sPlaybackNotePos = 0;
if (playbackState & 0x80) {
sPlaybackState = 1;
sPlaybackStaffStopPos = playbackState & 0xF;
sPlaybackStaffStartPos = 0xFF;
} else if (playbackState & 0x40) {
sPlaybackState = 1;
sPlaybackStaffStartPos = playbackState & 0xF;
sPlaybackStaffStopPos = 0xFF;
while (i < sPlaybackStaffStartPos) {
if (sOcarinaSongNotes[songIndexPlusOne - 1][sPlaybackNotePos].pitch != OCARINA_PITCH_NONE) {
i++;
}
sPlaybackNotePos++;
}
} else {
sPlaybackState = playbackState;
sPlaybackStaffStopPos = 0xFF;
sPlaybackStaffStartPos = 0xFF;
}
sPlaybackNoteTimer = 0;
sPlaybackPitch = OCARINA_PITCH_NONE;
sPlaybackStaffPos = 0;
if (sPlaybackStaffStartPos == 0xFF) {
while ((sPlaybackSong[sPlaybackNotePos].pitch == OCARINA_PITCH_NONE) &&
(songIndexPlusOne > (OCARINA_SONG_EVAN_PART2 + 1))) {
sPlaybackNotePos++;
}
}
}
/**
* Play a song with the ocarina to the user that is
* based on OcarinaNote data and not user input
*/
void AudioOcarina_PlaybackSong(void) {
s32 noteTimerStep;
s32 nextNoteTimerStep;
if (sPlaybackState == 0) {
return;
}
if (sPlaybackStaffPos == 0) {
noteTimerStep = 3;
} else {
noteTimerStep = sOcarinaUpdateTaskStart - sOcarinaPlaybackTaskStart;
}
if (noteTimerStep < sPlaybackNoteTimer) {
sPlaybackNoteTimer -= noteTimerStep;
} else {
nextNoteTimerStep = noteTimerStep - sPlaybackNoteTimer;
sPlaybackNoteTimer = 0;
}
if (sPlaybackNoteTimer == 0) {
if (sPlaybackStaffPos == sPlaybackStaffStopPos) {
sPlaybackState = 0;
return;
}
sPlaybackNoteTimer = sPlaybackSong[sPlaybackNotePos].length;
if (sPlaybackNotePos == 1) {
sPlaybackNoteTimer++;
}
if (sPlaybackNoteTimer == 0) {
sPlaybackState--;
if (sPlaybackState != 0) {
sPlaybackNotePos = 0;
sPlaybackStaffPos = 0;
sPlaybackPitch = OCARINA_PITCH_NONE;
} else {
AudioSfx_StopById(NA_SE_OC_OCARINA);
}
return;
} else {
sPlaybackNoteTimer -= nextNoteTimerStep;
}
// Update volume
if (sNotePlaybackVolume != sPlaybackSong[sPlaybackNotePos].volume) {
sNotePlaybackVolume = sPlaybackSong[sPlaybackNotePos].volume;
sRelativeNotePlaybackVolume = sNotePlaybackVolume / 127.0f;
}
// Update vibrato
sNotePlaybackVibrato = sPlaybackSong[sPlaybackNotePos].vibrato;
// Sets vibrato to io port 6
AUDIOCMD_CHANNEL_SET_IO(SEQ_PLAYER_SFX, SFX_CHANNEL_OCARINA, 6, sNotePlaybackVibrato);
// Update bend
if (sNotePlaybackBend != sPlaybackSong[sPlaybackNotePos].bend) {
sNotePlaybackBend = sPlaybackSong[sPlaybackNotePos].bend;
sRelativeNotePlaybackBend = AudioOcarina_BendPitchTwoSemitones(sNotePlaybackBend);
}
// No changes in volume, vibrato, or bend between notes
if ((sPlaybackSong[sPlaybackNotePos].volume == sPlaybackSong[sPlaybackNotePos - 1].volume &&
(sPlaybackSong[sPlaybackNotePos].vibrato == sPlaybackSong[sPlaybackNotePos - 1].vibrato) &&
(sPlaybackSong[sPlaybackNotePos].bend == sPlaybackSong[sPlaybackNotePos - 1].bend))) {
sPlaybackPitch = 0xFE;
}
if (sPlaybackPitch != sPlaybackSong[sPlaybackNotePos].pitch) {
u8 pitch = sPlaybackSong[sPlaybackNotePos].pitch;
// As bFlat4 is exactly in the middle of notes B & A, a flag is
// added to the pitch to resolve which button to map Bflat4 to
if (pitch == OCARINA_PITCH_BFLAT4) {
sPlaybackPitch = pitch + sPlaybackSong[sPlaybackNotePos].bFlat4Flag;
} else {
sPlaybackPitch = pitch;
}
if (sPlaybackPitch != OCARINA_PITCH_NONE) {
sPlaybackStaffPos++;
// Sets ocarina instrument Id to io port 7, which is used
// as an index in seq 0 to get the true instrument Id
AUDIOCMD_CHANNEL_SET_IO(SEQ_PLAYER_SFX, SFX_CHANNEL_OCARINA, 7, sOcarinaInstrumentId - 1);
AUDIOCMD_CHANNEL_SET_IO(SEQ_PLAYER_SFX, SFX_CHANNEL_OCARINA, 5,
sPlaybackPitch & OCARINA_BUTTON_MASK_PITCH);
AudioSfx_PlaySfx(NA_SE_OC_OCARINA, &gSfxDefaultPos, 4, &sRelativeNotePlaybackBend,
&sRelativeNotePlaybackVolume, &gSfxDefaultReverb);
} else {
AudioSfx_StopById(NA_SE_OC_OCARINA);
}
}
sPlaybackNotePos++;
}
}
void AudioOcarina_SetRecordingSong(u8 isRecordingComplete) {
u16 i;
u16 i2;
u16 pad;
u8 pitch;
OcarinaNote* note;
u8 j;
u8 k;
s32 t;
OcarinaNote* recordedSong;
if (sRecordingState == OCARINA_RECORD_SCARECROW_LONG) {
recordedSong = gScarecrowLongSongPtr;
} else {
/**
* OCARINA_RECORD_SCARECROW_SPAWN
*
* The notes for scarecrows spawn song are first recorded into the ocarina termina
* wall address to act as a buffer. That way, if a new scarecrow spawn song is
* rejected, the previous scarecrow spawn song is not overwritten. If the scarecrow
* spawn song is accepted, then the notes are copied over to the scarecrow spawn
* song address
*/
recordedSong = sTerminaWallSongPtr;
}
recordedSong[sRecordSongPos].pitch = sRecordOcarinaPitch;
recordedSong[sRecordSongPos].length = sOcarinaUpdateTaskStart - sOcarinaRecordTaskStart;
recordedSong[sRecordSongPos].volume = sRecordOcarinaVolume;
recordedSong[sRecordSongPos].vibrato = sRecordOcarinaVibrato;
recordedSong[sRecordSongPos].bend = sRecordOcarinaBendIndex;
recordedSong[sRecordSongPos].bFlat4Flag = sRecordOcarinaButtonIndex & OCARINA_BUTTON_MASK_FLAG;
sRecordOcarinaPitch = sCurOcarinaPitch;
sRecordOcarinaVolume = sCurOcarinaVolume;
sRecordOcarinaVibrato = sCurOcarinaVibrato;
sRecordOcarinaBendIndex = sCurOcarinaBendIndex;
sRecordOcarinaButtonIndex = sCurOcarinaButtonIndex;
sRecordSongPos++;
if ((sRecordSongPos != (ARRAY_COUNT(sScarecrowsLongSongNotes) - 1)) && !isRecordingComplete) {
// Continue recording
return;
}
// Recording is complete
i = sRecordSongPos;
pitch = OCARINA_PITCH_NONE;
while ((i != 0) && (pitch == OCARINA_PITCH_NONE)) {
i--;
pitch = recordedSong[i].pitch;
}
if (sRecordSongPos != (i + 1)) {
sRecordSongPos = i + 2;
recordedSong[sRecordSongPos - 1].length = 0;
}
recordedSong[sRecordSongPos].length = 0;
if (sRecordingState == OCARINA_RECORD_SCARECROW_SPAWN) {
if (sOcarinaStaffPlayingPos >= 8) {
for (i = 0; i < sRecordSongPos; i++) {
recordedSong[i] = recordedSong[i + 1];
}
// Copies Notes from buffer into scarecrows spawn buttons to be tested for acceptance or rejection
AudioOcarina_MapSongFromPitchToButton(OCARINA_SONG_TERMINA_WALL, OCARINA_SONG_SCARECROW_SPAWN, 8);
// Tests to see if the notes from the scarecrow song contain identical
// notes within its song to any of the reserved songIndex from 0 to 21
// Loop through each of the songs
for (i = 0; i < OCARINA_SONG_SCARECROW_SPAWN; i++) {
// Checks to see if the song is reserved
if (sIsOcarinaSongReserved[i]) {
// Loops through all possible starting indices
for (j = 0; (j < 9 - gOcarinaSongButtons[i].numButtons); j++) {
// Loops through the notes of the song
for (k = 0; (k < gOcarinaSongButtons[i].numButtons) && (k + j < 8) &&
(gOcarinaSongButtons[i].buttonIndex[k] ==
gOcarinaSongButtons[OCARINA_SONG_SCARECROW_SPAWN].buttonIndex[k + j]);
k++) {
;
}
// This conditional is true if the recorded song contains a reserved song
// recorded song is cancelled
if (k == gOcarinaSongButtons[i].numButtons) {
sRecordingState = OCARINA_RECORD_REJECTED;
sOcarinaSongNotes[OCARINA_SONG_SCARECROW_SPAWN][1].volume = 0xFF;
return;
}
}
}
}
// Counts how many times a note is repeated
i = 1;
while (i < 8) {
if (gOcarinaSongButtons[OCARINA_SONG_SCARECROW_SPAWN].buttonIndex[0] !=
gOcarinaSongButtons[OCARINA_SONG_SCARECROW_SPAWN].buttonIndex[i]) {
i = 9; // break
} else {
i++;
}
}
// This condition is true if all 8 notes are the same pitch
if (i == 8) {
sRecordingState = OCARINA_RECORD_REJECTED;
sOcarinaSongNotes[OCARINA_SONG_SCARECROW_SPAWN][1].volume = 0xFF;
return;
}
// The scarecrow spawn song is accepted and copied from the buffer to the scarecrow spawn notes
for (i = 0; i < sRecordSongPos; i++) {
sOcarinaSongNotes[OCARINA_SONG_SCARECROW_SPAWN][i] = sOcarinaSongNotes[OCARINA_SONG_TERMINA_WALL][i];
}
sIsOcarinaInputEnabled = false;
} else {
sOcarinaSongNotes[OCARINA_SONG_SCARECROW_SPAWN][1].volume = 0xFF;
}
}
sRecordingState = OCARINA_RECORD_OFF;
}
/**
* recordingState = OCARINA_RECORD_OFF, end
* recordingState = OCARINA_RECORD_SCARECROW_LONG, start long scarecrows song
* recordingState = OCARINA_RECORD_SCARECROW_SPAWN, start spawn scarecrows song
*/
void AudioOcarina_SetRecordingState(u8 recordingState) {
if ((u32)recordingState == sRecordingState) {
return;
}
if (recordingState != OCARINA_RECORD_OFF) {
sOcarinaRecordTaskStart = sOcarinaUpdateTaskStart;
sRecordOcarinaPitch = OCARINA_PITCH_NONE;
sRecordOcarinaVolume = 0x57;
sRecordOcarinaVibrato = 0;
sRecordOcarinaBendIndex = 0;
sRecordOcarinaButtonIndex = 0;
sRecordSongPos = 0;
sIsOcarinaInputEnabled = true;
sOcarinaStaffPlayingPos = 0;
sScarecrowsLongSongSecondNote = sScarecrowsLongSongNotes[1];
} else {
if (sRecordSongPos == 0) {
sScarecrowsLongSongNotes[1] = sScarecrowsLongSongSecondNote;
} else {
if (sRecordingState == OCARINA_RECORD_SCARECROW_SPAWN) {
sOcarinaStaffPlayingPos = 1;
}
AudioOcarina_SetRecordingSong(true);
}
sIsOcarinaInputEnabled = false;
sOcarinaStaffPlayingPos = 0;
}
sRecordingState = recordingState;
}
void AudioOcarina_UpdateRecordingStaff(void) {
sRecordingStaff.state = sRecordingState;
sRecordingStaff.pos = sOcarinaStaffPlayingPos;
if (sRecordingState == OCARINA_RECORD_REJECTED) {
sRecordingState = OCARINA_RECORD_OFF;
}
}
void AudioOcarina_UpdatePlayingStaff(void) {
if (sCurOcarinaButtonIndex != OCARINA_BTN_INVALID) {
sPlayingStaff.buttonIndex = sCurOcarinaButtonIndex & OCARINA_BUTTON_MASK_PITCH;
}
sPlayingStaff.state = AudioOcarina_GetPlayingState();
sPlayingStaff.pos = sOcarinaStaffPlayingPos;
}
void AudioOcarina_UpdatePlaybackStaff(void) {
if ((sPlaybackPitch & OCARINA_BUTTON_MASK_PITCH) <= OCARINA_PITCH_EFLAT5) {
sPlaybackStaff.buttonIndex = AudioOcarina_MapPitchToButton(sPlaybackPitch);
}
sPlaybackStaff.state = sPlaybackState;
if (sPlaybackSong != sScarecrowsLongSongNotes) {
sPlaybackStaff.pos = sPlaybackStaffPos;
} else if (sPlaybackStaffPos == 0) {
sPlaybackStaff.pos = 0;
} else {
sPlaybackStaff.pos = ((sPlaybackStaffPos - 1) % 8) + 1;
}
}
OcarinaStaff* AudioOcarina_GetRecordingStaff(void) {
return &sRecordingStaff;
}
OcarinaStaff* AudioOcarina_GetPlayingStaff(void) {
if (sPlayingStaff.state < 0xFE) {
sOcarinaFlags = 0;
}
return &sPlayingStaff;
}
OcarinaStaff* AudioOcarina_GetPlaybackStaff(void) {
return &sPlaybackStaff;
}
void AudioOcarina_RecordSong(void) {
s32 noteChanged;
if ((sRecordingState != OCARINA_RECORD_OFF) && ((sOcarinaUpdateTaskStart - sOcarinaRecordTaskStart) >= 3)) {
noteChanged = false;
if (sRecordOcarinaPitch != sCurOcarinaPitch) {
if (sCurOcarinaPitch != OCARINA_PITCH_NONE) {
sRecordingStaff.buttonIndex = sCurOcarinaButtonIndex & OCARINA_BUTTON_MASK_PITCH;
sOcarinaStaffPlayingPos++;
} else if ((sRecordingState == OCARINA_RECORD_SCARECROW_SPAWN) && (sOcarinaStaffPlayingPos == 8)) {
AudioOcarina_SetRecordingSong(true);
return;
}
if (sOcarinaStaffPlayingPos > 8) {
if (sRecordingState == OCARINA_RECORD_SCARECROW_SPAWN) {
// notes played are over 8 and in recording mode.
AudioOcarina_SetRecordingSong(true);
return;
}
sOcarinaStaffPlayingPos = 1;
}
noteChanged = true;
} else if (sRecordOcarinaVolume != sCurOcarinaVolume) {
noteChanged = true;
} else if (sRecordOcarinaVibrato != sCurOcarinaVibrato) {
if (sRecordingState != OCARINA_RECORD_SCARECROW_SPAWN) {
noteChanged = true;
}
} else if ((sRecordOcarinaBendIndex != sCurOcarinaBendIndex) &&
(sRecordingState != OCARINA_RECORD_SCARECROW_SPAWN)) {
noteChanged = true;
}
if (noteChanged) {
AudioOcarina_SetRecordingSong(false);
sOcarinaRecordTaskStart = sOcarinaUpdateTaskStart;
}
}
}
/**
* Tests to see if the notes from songIndex contain identical notes
* within its song to any of the reserved songIndex from 0 up to maxSongIndex
*/
s32 AudioOcarina_TerminaWallValidateNotes(u8 songIndex, u8 maxSongIndex) {
u8 curSongIndex;
u8 j;
u8 k;
// loop through all possible songs up to maxSongIndex
for (curSongIndex = 0; curSongIndex < maxSongIndex; curSongIndex++) {
// check to see if the song is reserved or not
if (sIsOcarinaSongReserved[curSongIndex]) {
// starting index to test the song
for (j = 0; j < (9 - gOcarinaSongButtons[curSongIndex].numButtons); j++) {
// loop through each note in the song
for (k = 0; (k < gOcarinaSongButtons[curSongIndex].numButtons) && ((k + j) < 8) &&
(gOcarinaSongButtons[curSongIndex].buttonIndex[k] ==
gOcarinaSongButtons[songIndex].buttonIndex[(k + j)]);
k++) {
continue;
}
if (k == gOcarinaSongButtons[curSongIndex].numButtons) {
// failure: songIndex is identical to curSongIndex.
return -1;
}
}
}
}
// success: notes are accepted and used
return 0;
}
/**
* Generates the notes displayed on the Termina Field wall of musical notes
* Song generation loop alternates between 8 random notes and a random song from Ocarina of Time (OoT).
* Will check to see that the notes are valid by ensuring no playable song is within the selected notes
* All OoT songs are valid, so the outer loop will run a maxiumum of two times.
* i.e. if random notes fails, then the next set of notes will be from a valid OoT song
*/
void AudioOcarina_TerminaWallGenerateNotes(void) {
OcarinaNote* ocarinaNote;
u8 randomButtonIndex;
u8 i;
u8 j;
do {
i = 0;
if (sOcarinaWallCounter++ % 2) {
j = 0;
for (; i < 8; i++) {
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;
sOcarinaSongNotes[OCARINA_SONG_TERMINA_WALL][j].vibrato = 0;
sOcarinaSongNotes[OCARINA_SONG_TERMINA_WALL][j].bend = 0;
j++;
sOcarinaSongNotes[OCARINA_SONG_TERMINA_WALL][j].pitch = OCARINA_PITCH_NONE;
sOcarinaSongNotes[OCARINA_SONG_TERMINA_WALL][j].length = 3;
sOcarinaSongNotes[OCARINA_SONG_TERMINA_WALL][j].volume = 0;
sOcarinaSongNotes[OCARINA_SONG_TERMINA_WALL][j].vibrato = 0;
sOcarinaSongNotes[OCARINA_SONG_TERMINA_WALL][j].bend = 0;
j++;
}
sOcarinaSongNotes[OCARINA_SONG_TERMINA_WALL][j - 2].length = 90;
sOcarinaSongNotes[OCARINA_SONG_TERMINA_WALL][j - 1].length = 22;
sOcarinaSongNotes[OCARINA_SONG_TERMINA_WALL][j + 1].pitch = OCARINA_PITCH_NONE;
sOcarinaSongNotes[OCARINA_SONG_TERMINA_WALL][j + 1].length = 0;
AudioOcarina_MapSongFromPitchToButton(OCARINA_SONG_TERMINA_WALL, OCARINA_SONG_TERMINA_WALL, 8);
} else {
j = AudioThread_NextRandom() % ARRAY_COUNT(sOoTOcarinaSongNotes);
ocarinaNote = sOoTOcarinaSongNotes[j];
for (; ocarinaNote[i].length != 0; i++) {
sOcarinaSongNotes[OCARINA_SONG_TERMINA_WALL][i] = ocarinaNote[i];
}
sOcarinaSongNotes[OCARINA_SONG_TERMINA_WALL][i].pitch = OCARINA_PITCH_NONE;
sOcarinaSongNotes[OCARINA_SONG_TERMINA_WALL][i].length = 0;
AudioOcarina_MapSongFromPitchToButton(OCARINA_SONG_TERMINA_WALL, OCARINA_SONG_TERMINA_WALL,
sOoTOcarinaSongsNumNotes[j]);
}
} while (AudioOcarina_TerminaWallValidateNotes(OCARINA_SONG_TERMINA_WALL, OCARINA_SONG_TERMINA_WALL) != 0);
}
/**
* Unused remnant of OoT
*/
void AudioOcarina_MemoryGameInit(u8 minigameRound) {
u8 i;
if (minigameRound > 2) {
minigameRound = 2;
}
sOcarinaMemoryGameAppendPos = 0;
sOcarinaMemoryGameEndPos = sOcarinaMemoryGameNumNotes[minigameRound];
for (i = 0; i < 3; i++) {
AudioOcarina_MemoryGameNextNote();
}
}
/**
* Unused remnant of OoT, Id 14 now represent Goron Lullaby Intro instead of the OoT ocarina memory game
* //! @bug calling this function in MM will overwrite Goron Lullaby Intro
*/
#define OCARINA_SONG_MEMORY_GAME 14
s32 AudioOcarina_MemoryGameNextNote(void) {
u32 randomButtonIndex;
u8 randomPitch;
if (sOcarinaMemoryGameAppendPos == sOcarinaMemoryGameEndPos) {
return true;
}
randomButtonIndex = AudioThread_NextRandom();
randomPitch = sButtonToPitchMap[randomButtonIndex % ARRAY_COUNT(sButtonToPitchMap)];
if (sOcarinaSongNotes[OCARINA_SONG_MEMORY_GAME][sOcarinaMemoryGameAppendPos - 1].pitch == randomPitch) {
randomPitch = sButtonToPitchMap[(randomButtonIndex + 1) % ARRAY_COUNT(sButtonToPitchMap)];
}
sOcarinaSongNotes[OCARINA_SONG_MEMORY_GAME][sOcarinaMemoryGameAppendPos].pitch = randomPitch;
sOcarinaSongNotes[OCARINA_SONG_MEMORY_GAME][sOcarinaMemoryGameAppendPos].length = 45;
sOcarinaSongNotes[OCARINA_SONG_MEMORY_GAME][sOcarinaMemoryGameAppendPos].volume = 0x50;
sOcarinaSongNotes[OCARINA_SONG_MEMORY_GAME][sOcarinaMemoryGameAppendPos].vibrato = 0;
sOcarinaSongNotes[OCARINA_SONG_MEMORY_GAME][sOcarinaMemoryGameAppendPos].bend = 0;
sOcarinaMemoryGameAppendPos++;
sOcarinaSongNotes[OCARINA_SONG_MEMORY_GAME][sOcarinaMemoryGameAppendPos].pitch = OCARINA_PITCH_NONE;
sOcarinaSongNotes[OCARINA_SONG_MEMORY_GAME][sOcarinaMemoryGameAppendPos].length = 0;
sOcarinaSongNotes[OCARINA_SONG_MEMORY_GAME][sOcarinaMemoryGameAppendPos + 1].pitch = OCARINA_PITCH_NONE;
sOcarinaSongNotes[OCARINA_SONG_MEMORY_GAME][sOcarinaMemoryGameAppendPos + 1].length = 0;
//! FAKE:
if (1) {}
return false;
}
#undef OCARINA_SONG_MEMORY_GAME
void AudioOcarina_Update(void) {
sOcarinaUpdateTaskStart = gAudioCtx.totalTaskCount;
if (sOcarinaInstrumentId != OCARINA_INSTRUMENT_OFF) {
if (sIsOcarinaInputEnabled == true) {
AudioOcarina_ReadControllerInput();
}
if ((sPlaybackState == 0) && (sIsOcarinaInputEnabled == true)) {
AudioOcarina_PlayControllerInput(false);
}
if (sOcarinaFlags != 0) {
if (sOcarinaFlags & 0x40000000) {
AudioOcarina_CheckSongsWithoutMusicStaff();
} else {
AudioOcarina_CheckSongsWithMusicStaff();
}
}
AudioOcarina_PlaybackSong();
sOcarinaPlaybackTaskStart = sOcarinaUpdateTaskStart;
if (sPlaybackState == 0) {
AudioOcarina_RecordSong();
}
if ((sOcarinaFlags != 0) && (sPrevOcarinaPitch != sCurOcarinaPitch)) {
sOcarinaDropInputTimer = 1; // Drops ocarina input for 1 frame
}
sPrevOcarinaPitch = sCurOcarinaPitch;
if (sOcarinaDisableTimer != 0) {
sOcarinaDisableTimer--;
if (sOcarinaDisableTimer == 0) {
AudioOcarina_SetInstrument(OCARINA_INSTRUMENT_OFF);
}
}
}
AudioOcarina_UpdatePlayingStaff();
AudioOcarina_UpdatePlaybackStaff();
AudioOcarina_UpdateRecordingStaff();
}
#define OCARINA_INSTRUMENT_OOT_MAX 7
void AudioOcarina_PlayLongScarecrowSong(void) {
static u8 sScarecrowAfterCreditsState = 0;
static u8 sScarecrowAfterCreditsIntrumentId = OCARINA_INSTRUMENT_DEFAULT;
static u16 sScarecrowAfterCreditsTimer = 1200;
switch (sScarecrowAfterCreditsState) {
case 0:
if (sScarecrowAfterCreditsTimer-- == 0) {
// OoT originally had 7 Ocarina instruments
// MM has more so this does not go all the way to the max
if (sScarecrowAfterCreditsIntrumentId < OCARINA_INSTRUMENT_OOT_MAX) {
// set next ocarina instrument and restart
sScarecrowAfterCreditsState++;
} else {
// finished
sScarecrowAfterCreditsState = 3;
AudioOcarina_SetInstrument(OCARINA_INSTRUMENT_OFF);
}
sScarecrowAfterCreditsTimer = 1200;
}
break;
case 1:
AudioSfx_MuteBanks(0);
AudioOcarina_SetInstrument(sScarecrowAfterCreditsIntrumentId);
AudioOcarina_SetPlaybackSong(OCARINA_SONG_SCARECROW_LONG + 1, 1);
sScarecrowAfterCreditsIntrumentId++;
sScarecrowAfterCreditsState++;
break;
case 2:
if (AudioOcarina_GetPlaybackStaff()->state == 0) {
sScarecrowAfterCreditsState = 0;
}
break;
}
}
u8 sRequestCustomSequence = false;
void AudioOcarina_SetCustomSequence(void) {
// Never passes true as sRequestCustomSequence is never set true
if (sRequestCustomSequence && gAudioCtx.seqPlayers[SEQ_PLAYER_FANFARE].enabled &&
((u8)gAudioCtx.seqPlayers[SEQ_PLAYER_FANFARE].seqScriptIO[0] == (u8)SEQ_IO_VAL_NONE)) {
gAudioCtx.seqPlayers[SEQ_PLAYER_FANFARE].seqData = sCustomSequenceScript;
sRequestCustomSequence = false;
}
}
// Called by unused function
void AudioOcarina_PlayCustomSequence(void) {
sRequestCustomSequence = true;
SEQCMD_PLAY_SEQUENCE(SEQ_PLAYER_FANFARE, 0, NA_BGM_DUNGEON_APPEAR);
}
// Unused
s32 AudioOcarina_CreateCustomSequence(void) {
OcarinaNote* prevNote;
u16 i;
u16 delay = 0;
u8 absPitch;
s8 adjBendIndex;
u8 prevVibrato = 0;
s8 prevBend = 0;
u8 isLegato = false;
u16 phi_s4 = 0;
u16 temp1; // prevNoteLength, reused temp
u16 temp2;
sCustomSequencePc = 39; // .channel chan_loop
prevNote = &sScarecrowsLongSongNotes[0];
for (i = 1; ((prevNote->pitch == OCARINA_PITCH_NONE) && (prevNote->length != 0)); i++) {
prevNote = &sScarecrowsLongSongNotes[i];
}
for (; (prevNote->length != 0) && (sCustomSequencePc < 394); i++) {
temp1 = ((prevNote->length * 48) / 30);
if (prevVibrato != prevNote->vibrato) {
sCustomSequenceScript[sCustomSequencePc++] = 0xFD; // delay cmd
if (delay >= 0x80) {
// Store as compressed u16
sCustomSequenceScript[sCustomSequencePc++] = (((delay >> 8) & 0xFF) & 0x7F) + 0x80; // delay arg
sCustomSequenceScript[sCustomSequencePc++] = delay & 0xFF; // delay arg
} else {
// Store as u8
sCustomSequenceScript[sCustomSequencePc++] = delay; // delay arg
}
sCustomSequenceScript[sCustomSequencePc++] = 0xD8; // vibdepth cmd
sCustomSequenceScript[sCustomSequencePc++] = prevNote->vibrato; // vibdepth arg
delay = temp1;
prevVibrato = prevNote->vibrato;
} else {
delay += temp1;
}
prevNote = &sScarecrowsLongSongNotes[i];
}
if (delay != 0) {
sCustomSequenceScript[sCustomSequencePc++] = 0xFD; // delay cmd
if (delay >= 0x80) {
// Store as compressed u16
sCustomSequenceScript[sCustomSequencePc++] = (((delay >> 8) & 0xFF) & 0x7F) + 0x80; // delay arg
sCustomSequenceScript[sCustomSequencePc++] = delay & 0xFF; // delay arg
} else {
// Store as u8
sCustomSequenceScript[sCustomSequencePc++] = delay; // delay arg
}
}
sCustomSequenceScript[sCustomSequencePc++] = 0xFF; // end cmd
// ldlayer 0, layer0
sCustomSequenceScript[24] = sCustomSequencePc >> 8;
sCustomSequenceScript[25] = sCustomSequencePc & 0xFF;
// ldlayer 1, layer1
sCustomSequenceScript[27] = (sCustomSequencePc + 4) >> 8;
sCustomSequenceScript[28] = (sCustomSequencePc + 4) & 0xFF;
sCustomSequenceScript[sCustomSequencePc++] = 0xC2; // transpose cmd
sCustomSequenceScript[sCustomSequencePc++] = -5; // transpose arg
sCustomSequenceScript[sCustomSequencePc++] = 0xC0; // ldelay cmd
sCustomSequenceScript[sCustomSequencePc++] = 8; // ldelay arg
sCustomSequenceScript[sCustomSequencePc++] = 0xC1; // shortvel cmd
sCustomSequenceScript[sCustomSequencePc++] = 87; // shortvel arg
sCustomSequenceScript[sCustomSequencePc++] = 0xC9; // shortgate cmd
sCustomSequenceScript[sCustomSequencePc++] = 0; // shortgate arg
prevNote = &sScarecrowsLongSongNotes[0];
for (i = 1; ((prevNote->pitch == OCARINA_PITCH_NONE) && (prevNote->length != 0)); i++) {
prevNote = &sScarecrowsLongSongNotes[i];
}
for (; ((temp1 = prevNote->length) != 0) && (sCustomSequencePc < 394); i++) {
if (prevNote->pitch == sScarecrowsLongSongNotes[i].pitch) {
if ((sScarecrowsLongSongNotes[i].length != 0) && !isLegato) {
sCustomSequenceScript[sCustomSequencePc++] = 0xC4; // legato cmd
isLegato = true;
}
} else if ((isLegato == true) && (sScarecrowsLongSongNotes[i].pitch != OCARINA_PITCH_NONE) &&
(sScarecrowsLongSongNotes[i].pitch != OCARINA_PITCH_C4)) {
sCustomSequenceScript[sCustomSequencePc++] = 0xC5; // nolegato cmd
isLegato = false;
}
if (prevBend != prevNote->bend) {
sCustomSequenceScript[sCustomSequencePc++] = 0xCE; // bendfine cmd
if (ABS_ALT(prevNote->bend) > 64) {
adjBendIndex = 127;
} else if (prevNote->bend < 0) {
adjBendIndex = -prevNote->bend;
} else {
adjBendIndex = ((prevNote->bend * 127) / 64);
}
if (prevNote->bend < 0) {
adjBendIndex *= -1;
}
sCustomSequenceScript[sCustomSequencePc++] = adjBendIndex; // bendfine arg
prevBend = prevNote->bend;
}
absPitch = prevNote->pitch + 39; // convert ocarina pitch to absolute pitch, + PITCH_C4 (Middle C)
if (prevNote->pitch != OCARINA_PITCH_NONE) {
sCustomSequenceScript[sCustomSequencePc++] = absPitch; // shortdvg cmd, shortdvg arg
} else {
sCustomSequenceScript[sCustomSequencePc++] = 0xC0; // ldelay cmd
}
// delay/duration
temp2 = ((temp1 * 48) + phi_s4) / 30;
if (temp2 < 0x80) {
// Store as u8
sCustomSequenceScript[sCustomSequencePc++] = temp2; // shortdvg/ldelay arg
} else {
// Store as compressed u16
sCustomSequenceScript[sCustomSequencePc++] = (((temp2 >> 8) & 0xFF) & 0x7F) + 0x80; // shortdvg/ldelay arg
sCustomSequenceScript[sCustomSequencePc++] = temp2 & 0xFF; // shortdvg/ldelay arg
}
phi_s4 = ((temp1 * 48) + phi_s4) - (temp2 * 30);
prevNote = &sScarecrowsLongSongNotes[i];
}
sCustomSequenceScript[sCustomSequencePc++] = 0xFF; // end cmd
AudioOcarina_PlayCustomSequence();
if (i >= 394) {
return -1;
}
return 0;
}
void AudioOcarina_ResetInstrument(void) {
if (sOcarinaInstrumentId != OCARINA_INSTRUMENT_OFF) {
SEQCMD_SET_CHANNEL_IO(SEQ_PLAYER_SFX, SFX_CHANNEL_OCARINA, 1, 0);
sOcarinaInstrumentId = OCARINA_INSTRUMENT_OFF;
AudioOcarina_ResetAndMute();
}
}
void AudioOcarina_ResetStaffs(void) {
u8 songIndex;
sPlayingStaff.buttonIndex = OCARINA_BTN_INVALID;
sPlayingStaff.state = 0xFF;
sPlayingStaff.pos = 0;
sPlaybackStaff.buttonIndex = OCARINA_BTN_INVALID;
sPlaybackStaff.state = 0;
sPlaybackStaff.pos = 0;
sRecordingStaff.buttonIndex = OCARINA_BTN_INVALID;
sRecordingStaff.state = 0xFF;
sRecordingStaff.pos = 0;
sOcarinaDisableTimer = 0;
sOcarinaDropInputTimer = 0;
for (songIndex = OCARINA_SONG_SONATA; songIndex < OCARINA_SONG_MAX; songIndex++) {
D_801FD518[songIndex] = 0xFF;
D_801FD530[songIndex] = 0;
}
D_801D8534 = 0;
}
void Audio_Noop1(s32 arg0) {
}
void Audio_Noop2(s32 arg0, s32 arg1) {
}
void Audio_Noop3(void) {
}
void Audio_Update(void) {
if ((AudioSeq_UpdateAudioHeapReset() == 0) && !AudioSeq_ResetReverb()) {
AudioOcarina_SetCustomSequence();
AudioOcarina_Update();
AudioVoice_Update();
Audio_StepFreqLerp(&sRiverFreqScaleLerp);
Audio_StepFreqLerp(&sWaterfallFreqScaleLerp);
Audio_UpdateRiverSoundVolumes();
Audio_UpdateSceneSequenceResumePoint();
Audio_UpdateFanfare();
Audio_UpdateSfxVolumeTransition();
Audio_UpdateSubBgmAtPos();
Audio_UpdateObjSoundFanfare();
Audio_UpdateSequenceAtPos();
Audio_UpdatePauseState();
Audio_UpdateObjSoundProperties();
Audio_ResetRequestedSceneSeqId();
AudioSfx_ProcessRequests();
AudioSeq_ProcessSeqCmds();
AudioSfx_ProcessActiveSfx();
AudioSeq_UpdateActiveSequences();
AudioSfx_ProcessSfxSettings();
AudioThread_ScheduleProcessCmds();
}
}
void Audio_Noop4(UNK_TYPE arg0) {
}
void Audio_Noop5(UNK_TYPE arg0, UNK_TYPE arg1) {
}
/**
* Queues a bgm sequence directly to the internal audio queue system.
* Skips the external audio command process
* Unused
*/
void Audio_PlayMainBgm(s8 seqId) {
AUDIOCMD_GLOBAL_INIT_SEQPLAYER(SEQ_PLAYER_BGM_MAIN, (u8)seqId, 1);
}
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];
if (bankEntry->sfxParams & SFX_FLAG_VOLUME_NO_DIST) {
return 1.0f;
}
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;
}
switch (bankEntry->sfxParams & SFX_PARAM_DIST_RANGE_MASK) {
case 0:
baseDist = 500.0f;
break;
case 1:
baseDist = 666.6667f;
break;
case 2:
baseDist = 952.381f;
break;
case 3:
baseDist = 3846.154f;
break;
case 4:
baseDist = 1000.0f;
break;
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(gAudioCtx.seqPlayers[SEQ_PLAYER_SFX].channels[channelIndex])) {
scriptAdd = gAudioCtx.seqPlayers[SEQ_PLAYER_SFX].channels[channelIndex]->seqScriptIO[1];
if (gAudioCtx.seqPlayers[SEQ_PLAYER_SFX].channels[channelIndex]->seqScriptIO[1] <= SEQ_IO_VAL_NONE) {
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 - ((gAudioCtx.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 - ((gAudioCtx.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_EXTERNAL) {
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_EXTERNAL) {
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_EXTERNAL) && !(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) {}
// ioPort 2, sets volume
AUDIOCMD_CHANNEL_SET_IO(SEQ_PLAYER_SFX, channelIndex, 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->stereoData.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;
}
void Audio_PlaySfx(u16 sfxId) {
AudioSfx_PlaySfx(sfxId, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
if (sfxId == NA_SE_OC_TELOP_IMPACT) {
Audio_SetSequenceMode(SEQ_MODE_DEFAULT);
}
}
void Audio_PlaySfx_2(u16 sfxId) {
AudioSfx_PlaySfx(sfxId, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
}
/**
* Bends the pitch of the sfx by a little under two semitones and adds reverb
*/
void Audio_PlaySfx_AtPosWithPresetLowFreqAndHighReverb(Vec3f* pos, u16 sfxId) {
AudioSfx_PlaySfx(sfxId, pos, 4, &sTwoSemitonesLoweredFreq, &gSfxDefaultFreqAndVolScale, &sSfxIncreasedReverb);
}
void Audio_PlaySfx_AtPos(Vec3f* pos, u16 sfxId) {
AudioSfx_PlaySfx(sfxId, pos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
void Audio_PlaySfx_MessageDecide(void) {
Audio_PlaySfx(NA_SE_SY_DECIDE);
AudioSfx_StopById(NA_SE_SY_MESSAGE_PASS);
}
void Audio_PlaySfx_MessageCancel(void) {
Audio_PlaySfx(NA_SE_SY_CANCEL);
AudioSfx_StopById(NA_SE_SY_MESSAGE_PASS);
}
SfxSettings* AudioSfx_AddSfxSetting(Vec3f* pos) {
SfxSettings* sfxSettings;
u8 i = 0;
u8 sfxSettingIndex = 0xFF;
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++;
}
}
}
/**
* Used for Gyorg and Bigslime
*/
void Audio_PlaySfx_Underwater(Vec3f* pos, u16 sfxId) {
if ((sfxId == NA_SE_EN_KONB_JUMP_OLD) || (sfxId == NA_SE_EN_KONB_SINK_OLD)) {
AudioSfx_PlaySfx(sfxId, pos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
} else {
AudioSfx_PlaySfx(sfxId, pos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gUnderwaterSfxReverbAdd);
}
}
/**
* Used only for eating the goron sirloin by the goron with Don Gero's Mask
*/
void Audio_PlaySfx_WithSfxSettingsReverb(Vec3f* pos, u16 sfxId) {
SfxSettings* sfxSettings;
if ((sfxId == NA_SE_EN_KONB_JUMP_OLD) || (sfxId == NA_SE_EN_KONB_SINK_OLD)) {
AudioSfx_PlaySfx(sfxId, pos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
} else {
sfxSettings = AudioSfx_AddSfxSetting(pos);
if (sfxSettings != NULL) {
AudioSfx_PlaySfx(sfxId, pos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&sfxSettings->reverbAdd);
}
}
}
void Audio_SetSfxUnderwaterReverb(s8 isUnderwaterReverbActivated) {
if (isUnderwaterReverbActivated) {
gUnderwaterSfxReverbAdd = -0x80;
} else {
gUnderwaterSfxReverbAdd = 0;
}
}
void AudioSfx_LowerSfxSettingsReverb(Vec3f* pos, s8 isReverbLowered) {
SfxSettings* sfxSettings = AudioSfx_AddSfxSetting(pos);
if (sfxSettings != NULL) {
if (isReverbLowered) {
sfxSettings->reverbAdd = -0x80;
} else {
sfxSettings->reverbAdd = 0;
}
}
}
f32 Audio_SetSyncedSfxFreqAndVolume(f32 freqVolParam) {
f32 ret = 1.0f;
if (freqVolParam > 6.0f) {
sSfxSyncedVolume = 1.0f;
sSfxSyncedFreq = 1.1f;
} else {
ret = freqVolParam / 6.0f;
sSfxSyncedVolume = ret * (1.0f - 0.775f) + 0.775f;
sSfxSyncedFreq = (ret * 0.2f) + 0.9f;
}
return ret;
}
/**
* Adjusts both frequency and volume based on a single parameter "freqVolParam"
* When freqVolParam >= 6.0f, frequency is increased to 1.1f and volume remains fixed at 1.0f
* For every -1.0f taken from freqVolParam (eg. 5.0f, 4.0f, 3.0f...):
* - volume will decrease by 0.0375f
* - frequency will decrease by 0.0333333f
*/
void Audio_PlaySfx_AtPosForMetalEffectsWithSyncedFreqAndVolume(Vec3f* pos, u16 sfxId, f32 freqVolParam) {
f32 sp2C;
f32 phi_f0;
u8 phi_v0;
u16 metalSfxId = NA_SE_NONE;
sp2C = Audio_SetSyncedSfxFreqAndVolume(freqVolParam);
AudioSfx_PlaySfx(sfxId, pos, 4, &sSfxSyncedFreq, &sSfxSyncedVolume, &gSfxDefaultReverb);
if ((sfxId & 0xF0) == 0xB0) {
// Crawlspaces (unused remnant of OoT)
phi_f0 = 0.3f;
phi_v0 = true;
sp2C = 1.0f;
} else {
phi_f0 = 1.1f;
phi_v0 = gAudioCtx.audioRandom & 1;
}
if (phi_f0 < freqVolParam) {
if (phi_v0) {
if ((sfxId & 0x1FF) < 0x80) {
metalSfxId = NA_SE_PL_METALEFFECT_KID;
} else if ((sfxId & 0x1FF) < 0xF0) {
metalSfxId = NA_SE_PL_METALEFFECT_ADULT;
}
if (metalSfxId != NA_SE_NONE) {
sSfxSyncedVolumeForMetalEffects = (sp2C * 0.7) + 0.3;
AudioSfx_PlaySfx(metalSfxId, pos, 4, &sSfxSyncedFreq, &sSfxSyncedVolumeForMetalEffects,
&gSfxDefaultReverb);
}
}
}
}
/**
* Adjusts both frequency and volume based on a single parameter "freqVolParam"
* When freqVolParam >= 6.0f, frequency is increased to 1.1f and volume remains fixed at 1.0f
* For every -1.0f taken from freqVolParam (eg. 5.0f, 4.0f, 3.0f...):
* - volume will decrease by 0.0375f
* - frequency will decrease by 0.0333333f
*/
void Audio_PlaySfx_AtPosWithSyncedFreqAndVolume(Vec3f* pos, u16 sfxId, f32 freqVolParam) {
Audio_SetSyncedSfxFreqAndVolume(freqVolParam);
AudioSfx_PlaySfx(sfxId, pos, 4, &sSfxSyncedFreq, &sSfxSyncedVolume, &gSfxDefaultReverb);
}
void Audio_PlaySfx_GiantsMaskUnused(Vec3f* pos, u16 sfxId) {
AudioSfx_PlaySfx(sfxId | 0xE0, pos, 4, &sGiantsMaskFreq, &gSfxDefaultFreqAndVolScale, &sGiantsMaskReverbAdd);
}
void Audio_PlaySfx_GiantsMask(Vec3f* pos, u16 sfxId) {
AudioSfx_PlaySfx((sfxId & 0x681F) + 0x20, pos, 4, &sGiantsMaskFreq, &gSfxDefaultFreqAndVolScale,
&sGiantsMaskReverbAdd);
}
void Audio_PlaySfx_Randomized(Vec3f* pos, u16 baseSfxId, u8 randLim) {
u8 offset = AudioThread_NextRandom() % randLim;
AudioSfx_PlaySfx(baseSfxId + offset, pos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
}
/**
* Plays increasingly high-pitched sword charging sfx as Player charges up the sword
*/
void Audio_PlaySfx_SwordCharge(Vec3f* pos, u8 chargeLevel) {
chargeLevel %= 4U;
if (chargeLevel != sPrevChargeLevel) {
sCurChargeLevelSfxFreq = sChargeLevelsSfxFreq[chargeLevel];
switch (chargeLevel) {
case 1:
AudioSfx_PlaySfx(NA_SE_PL_SWORD_CHARGE, pos, 4, &sCurChargeLevelSfxFreq, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
break;
case 2:
AudioSfx_PlaySfx(NA_SE_PL_SWORD_CHARGE, pos, 4, &sCurChargeLevelSfxFreq, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
break;
default:
break;
}
sPrevChargeLevel = chargeLevel;
}
if (chargeLevel != 0) {
AudioSfx_PlaySfx(NA_SE_IT_SWORD_CHARGE - SFX_FLAG, pos, 4, &sCurChargeLevelSfxFreq, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
}
}
void Audio_PlaySfx_AtPosWithFreqAndVolume(Vec3f* pos, u16 sfxId, f32 freqScale, f32* volume) {
SfxSettings* sfxSettings = AudioSfx_AddSfxSetting(pos);
f32* freqScaleAdj;
if (sfxSettings != NULL) {
freqScaleAdj = &sfxSettings->freqScale;
if (freqScale < 0.75f) {
*freqScaleAdj = ((freqScale / 0.75f) * 0.25f) + 0.5f;
} else {
*freqScaleAdj = freqScale;
}
if (*freqScaleAdj > 0.5f) {
AudioSfx_PlaySfx(sfxId, pos, 4, freqScaleAdj, volume, &gSfxDefaultReverb);
}
}
}
void Audio_PlaySfx_AtPosWithFreq(Vec3f* pos, u16 sfxId, f32 freqScale) {
Audio_PlaySfx_AtPosWithFreqAndVolume(pos, sfxId, freqScale, &gSfxDefaultFreqAndVolScale);
}
void Audio_PlaySfx_AtPosWithFreqAndChannelIO(Vec3f* pos, u16 sfxId, f32 freqScale, u8 arg3) {
if (freqScale > 1.0f) {
freqScale = 1.0f;
}
AudioSfx_SetChannelIO(pos, sfxId, (arg3 - (u32)(freqScale * arg3)) & 0xFF);
Audio_PlaySfx_AtPosWithFreq(pos, sfxId, freqScale);
}
void Audio_PlaySfx_WaterWheel(Vec3f* pos, u16 sfxId) {
u8 isWaterWheelSfxNotPlaying = false;
switch (sfxId) {
case NA_SE_EV_DUMMY_WATER_WHEEL_LR - SFX_FLAG:
if (!AudioSfx_IsPlaying(NA_SE_EV_BIG_WATER_WHEEL_LR - SFX_FLAG)) {
isWaterWheelSfxNotPlaying = true;
}
break;
case NA_SE_EV_DUMMY_WATER_WHEEL_RR - SFX_FLAG:
if (!AudioSfx_IsPlaying(NA_SE_EV_BIG_WATER_WHEEL_RR - SFX_FLAG)) {
isWaterWheelSfxNotPlaying = true;
}
break;
default:
break;
}
if (isWaterWheelSfxNotPlaying) {
AudioSfx_SetChannelIO(pos, sfxId, 0);
Audio_PlaySfx_AtPosWithFreqAndVolume(pos, sfxId, 1.0f, &sWaterWheelVolume);
}
}
/**
* at timerShiftedLerp == 1: use sSfxTimerLerpRange1
* at timerShiftedLerp == 2: use sSfxTimerLerpRange2
*
* sSfxAdjustedFreq was modified in OoT, but remains 1.0f in MM
*
* Used for "NA_SE_IT_DEKUNUTS_FLOWER_ROLL" and "NA_SE_IT_FISHING_REEL_SLOW"
*/
void Audio_PlaySfx_AtPosWithTimer(Vec3f* pos, u16 sfxId, f32 timerShiftedLerp) {
sSfxTimer--;
if (sSfxTimer == 0) {
AudioSfx_PlaySfx(sfxId, pos, 4, &sSfxAdjustedFreq, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
if (timerShiftedLerp > 2.0f) {
timerShiftedLerp = 2.0f;
}
// Linear interpolation between "sSfxTimerLerpRange1" and "sSfxTimerLerpRange2" from lerp factor
// (timerShiftedLerp - 1.0f)
sSfxTimer = (s8)((sSfxTimerLerpRange1 - sSfxTimerLerpRange2) * (1.0f - timerShiftedLerp)) + sSfxTimerLerpRange1;
}
}
void Audio_SetSfxTimerLerpInterval(s8 timerLerpRange1, s8 timerLerpRange2) {
sSfxTimer = 1;
sSfxTimerLerpRange2 = timerLerpRange2;
sSfxTimerLerpRange1 = timerLerpRange1;
}
void Audio_PlaySfx_AtPosWithReverb(Vec3f* pos, u16 sfxId, s8 reverbAdd) {
sSfxCustomReverb = reverbAdd;
AudioSfx_PlaySfx(sfxId, pos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &sSfxCustomReverb);
}
void Audio_PlaySfx_AtPosWithVolume(Vec3f* pos, u16 sfxId, f32 volume) {
gSfxVolume = volume;
AudioSfx_PlaySfx(sfxId, pos, 4, &gSfxDefaultFreqAndVolScale, &gSfxVolume, &gSfxDefaultReverb);
}
void Audio_SetSfxVolumeTransition(f32* volume, f32 volumeTarget, u16 duration) {
sSfxVolumeCur = volume;
sSfxVolumeTarget = volumeTarget;
sSfxVolumeDuration = duration;
sSfxVolumeRate = (*sSfxVolumeCur - sSfxVolumeTarget) / sSfxVolumeDuration;
}
// Part of audio update (runs every frame)
void Audio_UpdateSfxVolumeTransition(void) {
if (sSfxVolumeDuration != 0) {
sSfxVolumeDuration--;
if (sSfxVolumeDuration == 0) {
*sSfxVolumeCur = sSfxVolumeTarget;
} else {
*sSfxVolumeCur -= sSfxVolumeRate;
}
}
}
void Audio_PlaySfx_FishingReel(f32 timerShiftedLerp) {
Audio_PlaySfx_AtPosWithTimer(&gSfxDefaultPos, NA_SE_IT_FISHING_REEL_SLOW - SFX_FLAG, timerShiftedLerp);
Audio_PlaySfx_AtPosWithFreq(&gSfxDefaultPos, 0, (0.15f * timerShiftedLerp) + 1.4f);
}
/**
* Used for EnRiverSound
*/
void Audio_PlaySfx_River(Vec3f* pos, f32 freqScale) {
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;
}
AudioSfx_PlaySfx(NA_SE_EV_RIVER_STREAM - SFX_FLAG, pos, 4, &sRiverFreqScaleLerp.value, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
}
/**
* Unused remnant of OoT's EnRiverSound
* Used for Zora's River Waterfall
*/
void Audio_PlaySfx_Waterfall(Vec3f* pos, f32 freqScale) {
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;
}
AudioSfx_PlaySfx(NA_SE_EV_WATER_WALL_BIG - SFX_FLAG, pos, 4, &sWaterfallFreqScaleLerp.value,
&sWaterfallFreqScaleLerp.value, &gSfxDefaultReverb);
}
/**
* Used for EnRiverSound variables
*/
void Audio_StepFreqLerp(FreqLerp* lerp) {
if (lerp->remainingFrames != 0) {
lerp->remainingFrames--;
if (lerp->remainingFrames != 0) {
lerp->value += lerp->step;
} else {
lerp->value = lerp->target;
}
}
}
f32 sBigBellsVolume[] = {
1.0f, 0.9f, 0.8f, 0.7f, 0.6f, 0.5f, 0.4f, 0.3f,
};
void Audio_PlaySfx_BigBells(Vec3f* pos, u8 volumeIndex) {
AudioSfx_PlaySfx(NA_SE_EV_SIGNAL_BIGBELL, pos, 4, &gSfxDefaultFreqAndVolScale, &sBigBellsVolume[volumeIndex & 7],
&gSfxDefaultReverb);
}
void Audio_SetBgmVolumeOff(void) {
AudioSeq_SetVolumeScale(SEQ_PLAYER_BGM_MAIN, VOL_SCALE_INDEX_FANFARE, 0, 10);
AudioSeq_SetVolumeScale(SEQ_PLAYER_BGM_SUB, VOL_SCALE_INDEX_FANFARE, 0, 10);
}
void Audio_SetBgmVolumeOn(void) {
AudioSeq_SetVolumeScale(SEQ_PLAYER_BGM_MAIN, VOL_SCALE_INDEX_FANFARE, 0x7F, 3);
AudioSeq_SetVolumeScale(SEQ_PLAYER_BGM_SUB, VOL_SCALE_INDEX_FANFARE, 0x7F, 3);
}
void func_801A0204(s8 seqId) {
AUDIOCMD_SEQPLAYER_SET_IO(SEQ_PLAYER_BGM_MAIN, 2, (u8)seqId);
}
void Audio_SetMainBgmVolume(u8 targetVolume, u8 volumeFadeTimer) {
AudioSeq_SetVolumeScale(SEQ_PLAYER_BGM_MAIN, VOL_SCALE_INDEX_BGM_MAIN, targetVolume, volumeFadeTimer);
}
/**
* Unused remnant from OoT's EnRiverSound
* Was designed to incrementally increase volume of NA_BGM_GANON_TOWER for each new room during the climb of Ganon's
* Tower
*/
void Audio_SetGanonsTowerBgmVolumeLevel(u8 ganonsTowerLevel) {
u8 channelIndex;
s8 panChannelWeight = 0;
// Ganondorfs's Lair
if (ganonsTowerLevel == 0) {
// Pan comes entirely from the SequenceChannel
panChannelWeight = 0x7F;
}
for (channelIndex = 0; channelIndex < SEQ_NUM_CHANNELS; channelIndex++) {
AUDIOCMD_CHANNEL_SET_PAN_WEIGHT(SEQ_PLAYER_BGM_MAIN, channelIndex, panChannelWeight);
}
// Lowest room in Ganon's Tower (Entrance Room)
if (ganonsTowerLevel == 7) {
// Adds a delay to setting the volume in the first room
sEnterGanonsTowerTimer = 2;
} else {
Audio_SetGanonsTowerBgmVolume(sGanonsTowerLevelsVol[ganonsTowerLevel % ARRAY_COUNTU(sGanonsTowerLevelsVol)]);
}
}
/**
* Unused remnant from OoT's EnRiverSound
* If a new volume is requested for ganon's tower, update the volume and
* calculate a new low-pass filter cutoff and reverb based on the new volume
*/
s32 Audio_SetGanonsTowerBgmVolume(u8 targetVolume) {
u8 lowPassFilterCutoff;
u8 channelIndex;
u16 reverb;
if (sGanonsTowerVol != targetVolume) {
// Sets the volume
AudioSeq_SetVolumeScale(SEQ_PLAYER_BGM_MAIN, VOL_SCALE_INDEX_BGM_MAIN, targetVolume, 2);
// Sets the filter cutoff of the form (lowPassFilterCutoff << 4) | (highPassFilter & 0xF). highPassFilter is
// always set to 0
if (targetVolume < 0x40) {
// Only the first room
lowPassFilterCutoff = 0x10;
} else {
// Higher volume leads to a higher cut-off frequency in the low-pass filtering
lowPassFilterCutoff = (((targetVolume - 0x40) >> 2) + 1) << 4;
}
SEQCMD_SET_CHANNEL_IO(SEQ_PLAYER_BGM_MAIN, 15, 4, lowPassFilterCutoff);
// Sets the reverb
for (channelIndex = 0; channelIndex < ARRAY_COUNT(gAudioCtx.seqPlayers[SEQ_PLAYER_BGM_MAIN].channels);
channelIndex++) {
if (&gAudioCtx.sequenceChannelNone != gAudioCtx.seqPlayers[SEQ_PLAYER_BGM_MAIN].channels[channelIndex]) {
// seqScriptIO[5] was originally set to 0x40 in channels 0, 1, and 4 by OoT's Ganon's Tower BGM,
// which was removed in MM
if ((u8)gAudioCtx.seqPlayers[SEQ_PLAYER_BGM_MAIN].channels[channelIndex]->seqScriptIO[5] !=
(u8)SEQ_IO_VAL_NONE) {
// Higher volume leads to lower reverb
reverb = (((u16)gAudioCtx.seqPlayers[SEQ_PLAYER_BGM_MAIN].channels[channelIndex]->seqScriptIO[5] -
targetVolume) +
0x7F);
if (reverb > 0x7F) {
reverb = 0x7F;
}
AUDIOCMD_CHANNEL_SET_REVERB_VOLUME(SEQ_PLAYER_BGM_MAIN, channelIndex, (u8)reverb);
}
}
}
sGanonsTowerVol = targetVolume;
}
return -1;
}
/**
* Unused remnant from OoT's EnRiverSound
* Responsible for lowering market bgm in Child Market Entrance and Child Market Back Alley
* Only lowers volume for 1 frame, so must be called every frame to maintain lower volume
*/
void Audio_LowerMainBgmVolume(u8 volume) {
sRiverSoundMainBgmVol = volume;
sRiverSoundMainBgmLower = true;
}
/**
* Unused remnant from OoT's EnRiverSound
* Still called by Audio_Update every frame, but none of these processes get initialized
*/
void Audio_UpdateRiverSoundVolumes(void) {
// Updates Main Bgm Volume (RiverSound of type RS_LOWER_MAIN_BGM_VOLUME)
if (sRiverSoundMainBgmLower == true) {
if (sRiverSoundMainBgmCurrentVol != sRiverSoundMainBgmVol) {
// lowers the volume for 1 frame
AudioSeq_SetVolumeScale(SEQ_PLAYER_BGM_MAIN, VOL_SCALE_INDEX_BGM_MAIN, sRiverSoundMainBgmVol, 10);
sRiverSoundMainBgmCurrentVol = sRiverSoundMainBgmVol;
sRiverSoundMainBgmRestore = true;
}
sRiverSoundMainBgmLower = false;
} else if ((sRiverSoundMainBgmRestore == true) && (sAudioPauseMenuOpenOrClose == SFX_PAUSE_MENU_CLOSE)) {
// restores the volume every frame
AudioSeq_SetVolumeScale(SEQ_PLAYER_BGM_MAIN, VOL_SCALE_INDEX_BGM_MAIN, 0x7F, 10);
sRiverSoundMainBgmCurrentVol = 0x7F;
sRiverSoundMainBgmRestore = false;
}
// Update Ganon's Tower Volume (RiverSound of type RS_GANON_TOWER_7)
if (sEnterGanonsTowerTimer != 0) {
sEnterGanonsTowerTimer--;
if (sEnterGanonsTowerTimer == 0) {
Audio_SetGanonsTowerBgmVolume(sGanonsTowerLevelsVol[7]);
}
}
}
// Unused remnant of OoT
void Audio_PlaySfx_IncreasinglyTransposed(Vec3f* pos, s16 sfxId, u8* semitones) {
AudioSfx_PlaySfx(sfxId, pos, 4, &gPitchFrequencies[semitones[sAudioIncreasingTranspose] + 39],
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
if (sAudioIncreasingTranspose < 15) {
sAudioIncreasingTranspose++;
}
}
// Unused remnant of OoT
void Audio_ResetIncreasingTranspose(void) {
sAudioIncreasingTranspose = 0;
}
// Unused remnant of OoT
void Audio_PlaySfx_Transposed(Vec3f* pos, u16 sfxId, s8 semitone) {
AudioSfx_PlaySfx(sfxId, pos, 4, &gPitchFrequencies[semitone + 39], &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
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)) {
AUDIOCMD_CHANNEL_SET_IO(SEQ_PLAYER_SFX, channelIndex, 6, ioData);
}
}
channelIndex++;
}
}
/**
* Plays sfx and sets ioData to io port 6 if the sfx is active
*/
void Audio_PlaySfx_AtPosWithChannelIO(Vec3f* pos, u16 sfxId, u8 ioData) {
AudioSfx_SetChannelIO(pos, sfxId, ioData);
AudioSfx_PlaySfx(sfxId, pos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
/**
* Plays sfx and sets ioData to io port 6
*/
void Audio_PlaySfx_AtPosWithAllChannelsIO(Vec3f* pos, u16 sfxId, u8 ioData) {
u8 channelIndex = 0;
u8 i;
u8 bankId = SFX_BANK_SHIFT(sfxId);
for (i = 0; i < bankId; i++) {
channelIndex += gChannelsPerBank[gSfxChannelLayout][i];
}
for (i = 0; i < gChannelsPerBank[gSfxChannelLayout][bankId]; i++) {
AUDIOCMD_CHANNEL_SET_IO(SEQ_PLAYER_SFX, channelIndex++, 6, ioData);
}
AudioSfx_PlaySfx(sfxId, pos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
/**
* Unused remnant of OoT's EnRiverSound (func_800F4E30)
*/
void func_801A09D4(Vec3f* pos, f32 xzDistToPlayer) {
f32 volumeRel;
s8 pan;
u8 channelIndex;
if (sRiverSoundBgmPos == NULL) {
sRiverSoundBgmPos = pos;
sRiverSoundXZDistToPlayer = xzDistToPlayer;
} else if (sRiverSoundBgmPos != pos) {
if (sRiverSoundXZDistToPlayer > xzDistToPlayer) {
sRiverSoundBgmPos = pos;
sRiverSoundXZDistToPlayer = xzDistToPlayer;
}
} else {
sRiverSoundXZDistToPlayer = xzDistToPlayer;
}
if (sRiverSoundBgmPos->x > 100.0f) {
pan = 0x7F;
} else if (sRiverSoundBgmPos->x < -100.0f) {
pan = 0;
} else {
pan = ((sRiverSoundBgmPos->x / 100.0f) * 64.0f) + 64.0f;
}
if (sRiverSoundXZDistToPlayer > 400.0f) {
volumeRel = 0.1f;
} else if (sRiverSoundXZDistToPlayer < 120.0f) {
volumeRel = 1.0f;
} else {
volumeRel = ((1.0f - ((sRiverSoundXZDistToPlayer - 120.0f) / 280.0f)) * 0.9f) + 0.1f;
}
for (channelIndex = 0; channelIndex < SEQ_NUM_CHANNELS; channelIndex++) {
if (channelIndex != 9) {
SEQCMD_SET_CHANNEL_VOLUME(SEQ_PLAYER_BGM_MAIN, channelIndex, 2, (u8)(127.0f * volumeRel));
AUDIOCMD_CHANNEL_SET_PAN(SEQ_PLAYER_BGM_MAIN, channelIndex, pan);
}
}
}
/**
* Unused remnant of OoT's EnRiverSound
*/
void Audio_ClearSariaBgm(void) {
if (sRiverSoundBgmPos != NULL) {
sRiverSoundBgmPos = NULL;
}
}
/**
* Unused remnant of OoT's EnRiverSound
*/
void Audio_ClearSariaBgmAtPos(Vec3f* pos) {
if (sRiverSoundBgmPos == pos) {
sRiverSoundBgmPos = NULL;
}
}
/**
* Turns on and off channels from both bgm players in a way that splits
* equally between the two bgm channels. Split based on note priority
*/
void Audio_SplitBgmChannels(s8 volumeSplit) {
u8 volume;
u8 notePriority;
u16 channelBits;
u8 sBgmPlayers[2] = { SEQ_PLAYER_BGM_MAIN, SEQ_PLAYER_BGM_SUB };
u8 i;
u8 channelIndex;
if ((AudioSeq_GetActiveSeqId(SEQ_PLAYER_FANFARE) == NA_BGM_DISABLED) &&
(AudioSeq_GetActiveSeqId(SEQ_PLAYER_BGM_SUB) != NA_BGM_ROMANI_RANCH)) {
for (i = 0; i < ARRAY_COUNT(sBgmPlayers); i++) {
if (i == 0) {
// Main Bgm SeqPlayer
volume = volumeSplit;
} else {
// Sub Bgm SeqPlayer
volume = 0x7F - volumeSplit;
}
if (volume > 100) {
notePriority = 11;
} else if (volume < 20) {
notePriority = 2;
} else {
notePriority = ((volume - 20) / 10) + 2;
}
channelBits = 0;
for (channelIndex = 0; channelIndex < SEQ_NUM_CHANNELS; channelIndex++) {
if (gAudioCtx.seqPlayers[sBgmPlayers[i]].channels[channelIndex]->notePriority < notePriority) {
// If the note currently playing in the channel is a high enough priority,
// then keep the channel on by setting a channelBit
// If this condition fails, then the channel will be shut off
channelBits += (1 << channelIndex);
}
}
SEQCMD_SET_CHANNEL_DISABLE_MASK(sBgmPlayers[i], channelBits);
}
}
}
void Audio_SetSequenceProperties(u8 seqPlayerIndex, Vec3f* projectedPos, s16 flags, f32 minDist, f32 maxDist,
f32 maxVolume, f32 minVolume) {
f32 dist;
f32 volume;
s8 surroundEffectIndex;
s8 pan;
s32 pad;
// calculating surround sound effect from screen depth
if (projectedPos->z > 0.0f) {
if (projectedPos->z > 100.0f) {
surroundEffectIndex = 0;
} else {
surroundEffectIndex = ((100.0f - projectedPos->z) / 100.0f) * 64.0f;
}
} else {
if (projectedPos->z < -100.0f) {
surroundEffectIndex = 0x7F;
} else {
surroundEffectIndex = (s8)((-projectedPos->z / 100.0f) * 64.0f) + 0x3F;
}
}
// calculating pan from left-right screen position
if (projectedPos->x > 0.0f) {
if (projectedPos->x > 200.0f) {
pan = 0x6C;
} else {
pan = (s8)((projectedPos->x / 200.0f) * 45.0f) + 0x3F;
}
} else {
if (projectedPos->x < -200.0f) {
pan = 0x14;
} else {
pan = (s8)(((projectedPos->x + 200.0f) / 200.0f) * 44.0f) + 0x14;
}
}
// Calculate weighted volume
dist = SEQ_SCREEN_WEIGHTED_DIST(projectedPos);
if (dist > maxDist) {
volume = minVolume;
} else if (dist < minDist) {
volume = 1.0f;
} else {
volume = (((maxDist - dist) / (maxDist - minDist)) * (1.0f - minVolume)) + minVolume;
}
AUDIOCMD_GLOBAL_SET_CHANNEL_MASK(seqPlayerIndex, 0xFFFF);
if (flags & 1) {
AUDIOCMD_CHANNEL_SET_SURROUND_EFFECT_INDEX(seqPlayerIndex, AUDIOCMD_ALL_CHANNELS, surroundEffectIndex);
}
if (flags & 2) {
AUDIOCMD_CHANNEL_SET_PAN(seqPlayerIndex, AUDIOCMD_ALL_CHANNELS, pan);
}
if (flags & 4) {
AUDIOCMD_CHANNEL_SET_PAN_WEIGHT(seqPlayerIndex, AUDIOCMD_ALL_CHANNELS, 0x7F);
}
// applies filter, stores result in sSequenceFilter
if (flags & 8) {
// Uses new filter gBandPassFilterData
AUDIOCMD_CHANNEL_SET_FILTER(seqPlayerIndex, AUDIOCMD_ALL_CHANNELS, 0x54,
((u32)&sSequenceFilter[0] & ~0xF) + 0x10);
} else {
// Identity Filter
AUDIOCMD_CHANNEL_SET_FILTER(seqPlayerIndex, AUDIOCMD_ALL_CHANNELS, 0, ((u32)&sSequenceFilter[0] & ~0xF) + 0x10);
}
if (flags & 0x10) {
AUDIOCMD_CHANNEL_SET_GAIN(seqPlayerIndex, AUDIOCMD_ALL_CHANNELS, 0x7F);
} else {
AUDIOCMD_CHANNEL_SET_GAIN(seqPlayerIndex, AUDIOCMD_ALL_CHANNELS, 0);
}
if (flags & 0x20) {
AUDIOCMD_CHANNEL_SET_VOL_SCALE(seqPlayerIndex, AUDIOCMD_ALL_CHANNELS, maxVolume * volume);
}
if (flags & 0x40) {
AUDIOCMD_CHANNEL_SET_PAN_WEIGHT(seqPlayerIndex, AUDIOCMD_ALL_CHANNELS, 0x40);
}
if (flags & 0x80) {
AUDIOCMD_CHANNEL_SET_REVERB_INDEX(seqPlayerIndex, AUDIOCMD_ALL_CHANNELS, 1);
}
if (flags & 0x100) {
AUDIOCMD_CHANNEL_SET_REVERB_VOLUME(seqPlayerIndex, AUDIOCMD_ALL_CHANNELS, 55);
}
}
// ======== BEGIN Z_OBJ_SOUND FUNCTIONS ========
/**
* Used for Main Bgm and Fanfares
*/
void Audio_UpdateObjSoundProperties(void) {
if (sObjSoundPlayerIndex != SEQ_PLAYER_INVALID) {
if ((AudioSeq_GetActiveSeqId(sObjSoundPlayerIndex) != NA_BGM_FINAL_HOURS) &&
AudioSeq_IsSeqCmdNotQueued((sObjSoundPlayerIndex << 24) + NA_BGM_FINAL_HOURS,
SEQCMD_OP_MASK | SEQCMD_ASYNC_ACTIVE | SEQCMD_SEQPLAYER_MASK |
SEQCMD_SEQID_MASK) &&
!sIsFinalHoursOrSoaring) {
Audio_SetSequenceProperties(sObjSoundPlayerIndex, &sObjSoundPos, sObjSoundFlags, sObjSoundMinDist,
sObjSoundMaxDist, sObjSoundMaxVol, sObjSoundMinVol);
}
sObjSoundPlayerIndex = SEQ_PLAYER_INVALID;
}
}
/**
* Used for Main Bgm and Fanfares
*/
void Audio_SetObjSoundProperties(u8 seqPlayerIndex, Vec3f* pos, s16 flags, f32 minDist, f32 maxDist, f32 maxVolume,
f32 minVolume) {
sObjSoundPlayerIndex = seqPlayerIndex;
sObjSoundPos.x = pos->x;
sObjSoundPos.y = pos->y;
sObjSoundPos.z = pos->z;
sObjSoundFlags = flags;
sObjSoundMinDist = minDist;
sObjSoundMaxDist = maxDist;
sObjSoundMaxVol = maxVolume;
sObjSoundMinVol = minVolume;
}
void Audio_StartObjSoundFanfare(u8 seqPlayerIndex, Vec3f* pos, s8 seqId, u16 seqIdOffset) {
s32 pad[3];
u32 mask;
if ((AudioSeq_GetActiveSeqId(seqPlayerIndex) == NA_BGM_FINAL_HOURS) ||
!AudioSeq_IsSeqCmdNotQueued((seqPlayerIndex << 0x18) + NA_BGM_FINAL_HOURS,
SEQCMD_OP_MASK | SEQCMD_ASYNC_ACTIVE | SEQCMD_SEQPLAYER_MASK | SEQCMD_SEQID_MASK) ||
sIsFinalHoursOrSoaring) {
sIsFinalHoursOrSoaring = true;
} else if (pos != NULL) {
if ((seqId != (s8)(AudioSeq_GetActiveSeqId(seqPlayerIndex) & 0xFFFF)) &&
!gAudioCtx.seqPlayers[seqPlayerIndex].enabled && (sObjSoundMainBgmSeqId == NA_BGM_GENERAL_SFX)) {
mask = 0xFFFF;
SEQCMD_PLAY_SEQUENCE(seqPlayerIndex, ((((AudioThread_NextRandom() % 30) & 0xFF) + 1)),
((seqId & mask) + seqIdOffset));
sObjSoundMainBgmSeqId = seqId;
}
Audio_SetObjSoundProperties(seqPlayerIndex, pos, 0x7F, 320.0f, 1280.0f, 1.0f, 0.0f);
} else {
SEQCMD_STOP_SEQUENCE(seqPlayerIndex, 5);
}
}
void Audio_PlayObjSoundBgm(Vec3f* pos, s8 seqId) {
s32 pad[2];
u16 sp36;
s32 sp2C;
u16 seqId0 = AudioSeq_GetActiveSeqId(SEQ_PLAYER_BGM_MAIN);
u32 temp_a0;
if ((seqId0 == NA_BGM_FINAL_HOURS) ||
!AudioSeq_IsSeqCmdNotQueued(NA_BGM_FINAL_HOURS,
SEQCMD_OP_MASK | SEQCMD_ASYNC_ACTIVE | SEQCMD_SEQPLAYER_MASK | SEQCMD_SEQID_MASK) ||
sIsFinalHoursOrSoaring) {
sIsFinalHoursOrSoaring = true;
return;
}
if (seqId0 == NA_BGM_SONG_OF_SOARING) {
sIsFinalHoursOrSoaring = true;
}
if (pos != NULL) {
if (seqId == NA_BGM_ASTRAL_OBSERVATORY) {
if ((seqId != (u8)(seqId0 & 0xFF)) && !sAllPlayersMutedExceptSystemAndOcarina) {
SEQCMD_PLAY_SEQUENCE(SEQ_PLAYER_BGM_MAIN, 0, (u16)seqId);
sObjSoundMainBgmSeqId = seqId;
} else if ((seqId == (u8)(seqId0 & 0xFF)) && (sObjSoundMainBgmSeqId == NA_BGM_GENERAL_SFX)) {
sObjSoundMainBgmSeqId = seqId;
}
Audio_SetObjSoundProperties(SEQ_PLAYER_BGM_MAIN, pos, 0x20, 100.0f, 1500.0f, 0.9f, 0.0f);
} else {
if (sObjSoundMainBgmSeqId == NA_BGM_GENERAL_SFX) {
temp_a0 = ((((AudioThread_NextRandom() % 30) & 0xFF) + 1) << 0x10) | ((u16)seqId + 0x7F00);
SEQCMD_PLAY_SEQUENCE(SEQ_PLAYER_BGM_MAIN, 0, temp_a0);
sObjSoundMainBgmSeqId = seqId;
}
if (seqId == NA_BGM_MILK_BAR_DUPLICATE) {
Audio_SetObjSoundProperties(SEQ_PLAYER_BGM_MAIN, pos, 0x1E3, 0.0f, 600.0f, 0.9f, 0.55f);
} else if (seqId == NA_BGM_MILK_BAR) {
Audio_SetObjSoundProperties(SEQ_PLAYER_BGM_MAIN, pos, 0x1FF, 0.0f, 600.0f, 0.9f, 0.55f);
} else {
Audio_SetObjSoundProperties(SEQ_PLAYER_BGM_MAIN, pos, 0x3F, 0.0f, 600.0f, 0.9f, 0.55f);
}
}
} else {
if (sObjSoundMainBgmSeqId == NA_BGM_ASTRAL_OBSERVATORY) {
AUDIOCMD_GLOBAL_SET_CHANNEL_MASK(SEQ_PLAYER_BGM_MAIN, 0xFFFF);
AUDIOCMD_CHANNEL_SET_VOL_SCALE(SEQ_PLAYER_BGM_MAIN, AUDIOCMD_ALL_CHANNELS, 1.0f);
SEQCMD_PLAY_SEQUENCE(SEQ_PLAYER_BGM_MAIN, 10, NA_BGM_CAVERN);
} else {
SEQCMD_STOP_SEQUENCE(SEQ_PLAYER_BGM_MAIN, 5);
}
sObjSoundMainBgmSeqId = NA_BGM_GENERAL_SFX;
}
}
void Audio_PlayObjSoundFanfare(Vec3f* pos, s8 seqId) {
s32 requestFanfare = false;
s32 pad;
if (sObjSoundFanfareSeqId == NA_BGM_GENERAL_SFX) {
// No spatial fanfare is currently playing
requestFanfare = true;
} else if (SEQ_SCREEN_WEIGHTED_DIST(pos) < SEQ_SCREEN_WEIGHTED_DIST(&sObjSoundFanfarePos)) {
// The spatial fanfare requested is closer than the spatial fanfare currently playing
requestFanfare = true;
}
if (requestFanfare) {
sObjSoundFanfarePos.x = pos->x;
sObjSoundFanfarePos.y = pos->y;
sObjSoundFanfarePos.z = pos->z;
sObjSoundFanfareSeqId = seqId;
sObjSoundFanfareRequested = true;
}
}
void Audio_UpdateObjSoundFanfare(void) {
if (sObjSoundFanfareRequested && (sAudioPauseState == AUDIO_PAUSE_STATE_CLOSED)) {
if (sObjSoundFanfareSeqId != NA_BGM_GENERAL_SFX) {
Audio_StartObjSoundFanfare(SEQ_PLAYER_FANFARE, &sObjSoundFanfarePos, sObjSoundFanfareSeqId, 0);
if (AudioSeq_GetActiveSeqId(SEQ_PLAYER_FANFARE) == NA_BGM_DISABLED) {
Audio_MuteBgmPlayersForFanfare();
}
if ((AudioSeq_GetActiveSeqId(SEQ_PLAYER_BGM_MAIN) != NA_BGM_DISABLED) &&
(AudioSeq_GetActiveSeqId(SEQ_PLAYER_AMBIENCE) == NA_BGM_DISABLED)) {
Audio_PlayAmbience(AMBIENCE_ID_09);
}
sAudioCutsceneFlag = true;
} else {
Audio_StartObjSoundFanfare(SEQ_PLAYER_FANFARE, NULL, sObjSoundFanfareSeqId, 0);
if (AudioSeq_GetActiveSeqId(SEQ_PLAYER_BGM_MAIN) != NA_BGM_DISABLED) {
SEQCMD_STOP_SEQUENCE(SEQ_PLAYER_AMBIENCE, 0);
}
sObjSoundFanfareRequested = false;
sObjSoundMainBgmSeqId = NA_BGM_GENERAL_SFX;
sAudioCutsceneFlag = false;
}
sObjSoundFanfareSeqId = NA_BGM_GENERAL_SFX;
}
}
// ======== END Z_OBJ_SOUND FUNCTIONS ========
void Audio_StopSequenceAtPos(u8 seqPlayerIndex, u8 volumeFadeTimer) {
SEQCMD_STOP_SEQUENCE((u32)seqPlayerIndex, 20);
if ((seqPlayerIndex == SEQ_PLAYER_BGM_SUB) && (AudioSeq_GetActiveSeqId(SEQ_PLAYER_BGM_MAIN) != NA_BGM_DISABLED)) {
AudioSeq_SetVolumeScale(SEQ_PLAYER_BGM_MAIN, VOL_SCALE_INDEX_BGM_SUB, 0x7F, volumeFadeTimer);
Audio_SplitBgmChannels(0);
}
}
void Audio_StartSubBgmAtPos(u8 seqPlayerIndex, Vec3f* projectedPos, u8 seqId, u8 flags, f32 minDist, f32 maxDist,
f32 arg6) {
f32 dist = SEQ_SCREEN_WEIGHTED_DIST(projectedPos);
u8 targetVolume;
u16 seqId0 = AudioSeq_GetActiveSeqId(seqPlayerIndex);
f32 relVolume;
s32 pad;
if (dist > maxDist) {
if ((u8)seqId0 == seqId) {
Audio_StopSequenceAtPos(seqPlayerIndex, 10);
sSpatialSeqIsActive[seqPlayerIndex] = false;
}
return;
}
if ((!gAudioCtx.seqPlayers[seqPlayerIndex].enabled && !sAllPlayersMutedExceptSystemAndOcarina) ||
(seqId0 == (NA_BGM_ENEMY | 0x800))) {
if (seqPlayerIndex == SEQ_PLAYER_BGM_SUB) {
AudioSeq_SetVolumeScale(seqPlayerIndex, VOL_SCALE_INDEX_BGM_SUB, 0x7F, 1);
}
SEQCMD_PLAY_SEQUENCE((u32)seqPlayerIndex, 1, seqId);
sSpatialSeqIsActive[seqPlayerIndex] = true;
}
Audio_SetSequenceProperties(seqPlayerIndex, projectedPos, flags, minDist, maxDist, 1.0, 0.05f);
if ((seqPlayerIndex == SEQ_PLAYER_BGM_SUB) && (gAudioCtx.seqPlayers[SEQ_PLAYER_BGM_MAIN].enabled == true)) {
if (dist > maxDist) {
relVolume = 1.0f;
} else if (dist < minDist) {
relVolume = 0.0f;
} else {
relVolume = 1.0f - ((maxDist - dist) / (maxDist - minDist));
}
targetVolume = (u8)(relVolume * 127.0f);
AudioSeq_SetVolumeScale(SEQ_PLAYER_BGM_MAIN, VOL_SCALE_INDEX_BGM_SUB, targetVolume, 10);
Audio_SplitBgmChannels(0x7F - targetVolume);
}
}
/**
* sSpatialSeqNoFilterPos takes priority over sSpatialSeqFilterPos
* Used only by guru guru for song of storms
*/
void Audio_PlaySubBgmAtPos(Vec3f* pos, u8 seqId, f32 maxDist) {
if (gAudioSpecId != 0xC) {
sSpatialSeqNoFilterPos.x = pos->x;
sSpatialSeqNoFilterPos.y = pos->y;
sSpatialSeqNoFilterPos.z = pos->z;
sSpatialSeqSeqId = seqId;
sSpatialSeqMaxDist = maxDist;
sSpatialSeqFlags |= 2; // Only update volume
sSpatialSubBgmFadeTimer = 4;
}
}
// Used only by guru guru for song of storms in stock pot from hallway or neighboring room
void Audio_PlaySubBgmAtPosWithFilter(Vec3f* pos, u8 seqId, f32 maxDist) {
sSpatialSeqFilterPos.x = pos->x;
sSpatialSeqFilterPos.y = pos->y;
sSpatialSeqFilterPos.z = pos->z;
sSpatialSeqSeqId = seqId;
//! @bug Did not set sSpatialSeqMaxDist = maxDist; This will use the previously set value of sSpatialSeqMaxDist
sSpatialSeqFlags |= 1; // Update with volume and filter
sSpatialSubBgmFadeTimer = 4;
}
// Another bgm by pos, less customization
void Audio_UpdateSubBgmAtPos(void) {
if (sSpatialSubBgmFadeTimer != 0) {
if (sSpatialSeqFlags & 2) {
// Affects only volume
Audio_StartSubBgmAtPos(SEQ_PLAYER_BGM_SUB, &sSpatialSeqNoFilterPos, sSpatialSeqSeqId, 0x20, 100.0f,
sSpatialSeqMaxDist, 1.0f);
} else {
// Set volume with band-pass filter
Audio_StartSubBgmAtPos(SEQ_PLAYER_BGM_SUB, &sSpatialSeqFilterPos, sSpatialSeqSeqId, 0x28, 100.0f,
sSpatialSeqMaxDist, 1.0f);
}
sSpatialSubBgmFadeTimer--;
if (sSpatialSubBgmFadeTimer == 0) {
Audio_StopSequenceAtPos(SEQ_PLAYER_BGM_SUB, 10);
}
sSpatialSeqFlags = 0;
}
}
/**
* Play sequence at the default center of the screen. Does not check for final hours or soaring bgms playing
* Used only by minifrog for the frog song
*/
void Audio_PlaySequenceAtDefaultPos(u8 seqPlayerIndex, u16 seqId) {
if (!sAudioCutsceneFlag && (gAudioSpecId != 0xC)) {
sSpatialSeqFilterPos.x = gSfxDefaultPos.x;
sSpatialSeqFilterPos.y = gSfxDefaultPos.y;
sSpatialSeqFilterPos.z = gSfxDefaultPos.z;
sSpatialSeqMaxDist = 10000.0f;
sSpatialSeqFadeTimer = 128;
sSpatialSeqSeqId = seqId;
sSpatialSeqPlayerIndex = seqPlayerIndex;
}
}
// Used only by minifrog
void Audio_StopSequenceAtDefaultPos(void) {
if (gAudioSpecId != 0xC) {
sSpatialSeqFadeTimer = 1;
sSpatialSeqSeqId = NA_BGM_GENERAL_SFX;
}
}
/**
* Play the requested sequence at a position. Valid for sequences on players 0 - 3
*/
void Audio_PlaySequenceAtPos(u8 seqPlayerIndex, Vec3f* pos, u16 seqId, f32 maxDist) {
if ((!sAudioCutsceneFlag) && ((AudioSeq_GetActiveSeqId(SEQ_PLAYER_BGM_MAIN) & 0xFF) != NA_BGM_SONG_OF_SOARING) &&
(gAudioSpecId != 0xC) && (pos != NULL) &&
((sSpatialSeqPlayerIndex != SEQ_PLAYER_BGM_MAIN) ||
(AudioSeq_GetActiveSeqId(SEQ_PLAYER_BGM_MAIN) != NA_BGM_FINAL_HOURS))) {
sSpatialSeqFilterPos.x = pos->x;
sSpatialSeqFilterPos.y = pos->y;
sSpatialSeqFilterPos.z = pos->z;
sSpatialSeqMaxDist = maxDist;
sSpatialSeqFadeTimer = 2;
sSpatialSeqSeqId = seqId & 0xFF;
sSpatialSeqPlayerIndex = seqPlayerIndex;
}
}
void Audio_UpdateSequenceAtPos(void) {
u16 mainBgmSeqId = AudioSeq_GetActiveSeqId(SEQ_PLAYER_BGM_MAIN);
u8 volumeFadeTimer;
if ((sSpatialSeqFadeTimer != 0) && (sAudioPauseState == AUDIO_PAUSE_STATE_CLOSED)) {
if ((sSpatialSeqSeqId == NA_BGM_GENERAL_SFX) || (mainBgmSeqId == NA_BGM_SONG_OF_SOARING)) {
volumeFadeTimer = 10;
if (mainBgmSeqId == NA_BGM_SONG_OF_SOARING) {
sSpatialSeqFadeTimer = 0;
volumeFadeTimer = 1;
} else if (sSpatialSeqFadeTimer < 128) {
sSpatialSeqFadeTimer--;
}
if (sSpatialSeqFadeTimer == 0) {
Audio_StopSequenceAtPos(sSpatialSeqPlayerIndex, volumeFadeTimer);
sSpatialSeqIsActive[sSpatialSeqPlayerIndex] = false;
}
} else {
if ((sSpatialSeqPlayerIndex == SEQ_PLAYER_BGM_MAIN) && (mainBgmSeqId == NA_BGM_FINAL_HOURS)) {
Audio_StopSequenceAtPos(sSpatialSeqPlayerIndex, 10);
sSpatialSeqIsActive[sSpatialSeqPlayerIndex] = false;
return;
}
Audio_StartSubBgmAtPos(sSpatialSeqPlayerIndex, &sSpatialSeqFilterPos, sSpatialSeqSeqId, 0x20, 200.0f,
sSpatialSeqMaxDist, 1.0f);
if (!sSpatialSeqIsActive[sSpatialSeqPlayerIndex]) {
sSpatialSeqFadeTimer = 0;
}
}
if (sSpatialSeqFadeTimer < 128) {
sSpatialSeqSeqId = NA_BGM_GENERAL_SFX;
}
}
}
/**
* Unused remnant of OoT's EnRiverSound
*/
void Audio_PlaySariaBgm(Vec3f* pos, u16 seqId, u16 distMax) {
f32 absY;
f32 dist;
u8 targetVolume;
f32 prevDist;
if (sRiverSoundBgmTimer != 0) {
sRiverSoundBgmTimer--;
return;
}
dist = sqrtf(SQ(pos->z) + (SQ(pos->x) + SQ(pos->y)));
if (sRiverSoundBgmPos == NULL) {
sRiverSoundBgmPos = pos;
Audio_PlaySequenceWithSeqPlayerIO(SEQ_PLAYER_BGM_SUB, seqId, 0, 7, 2);
} else {
prevDist = sqrtf(SQ(sRiverSoundBgmPos->z) + SQ(sRiverSoundBgmPos->x));
if (dist < prevDist) {
sRiverSoundBgmPos = pos;
} else {
dist = prevDist;
}
}
absY = ABS_ALT(pos->y);
if ((distMax / 15.0f) < absY) {
targetVolume = 0;
} else if (dist < distMax) {
targetVolume = (1.0f - (dist / distMax)) * 127.0f;
} else {
targetVolume = 0;
}
if (seqId != NA_BGM_FAIRY_FOUNTAIN) {
Audio_SplitBgmChannels(targetVolume);
}
AudioSeq_SetVolumeScale(SEQ_PLAYER_BGM_SUB, VOL_SCALE_INDEX_BGM_SUB, targetVolume, 0);
AudioSeq_SetVolumeScale(SEQ_PLAYER_BGM_MAIN, VOL_SCALE_INDEX_BGM_SUB, 0x7F - targetVolume, 0);
}
/**
* Unused remnant of OoT's EnRiverSound
*/
void Audio_ClearSariaBgm2(void) {
sRiverSoundBgmPos = NULL;
}
void func_801A246C(u8 seqPlayerIndex, u8 type) {
u16 seqId;
u8 targetVolume;
s32 channelMask = 0;
targetVolume = 0;
switch (type) {
case 0:
targetVolume = 0x7F;
break;
case 1:
channelMask = 0xFFFF;
break;
case 2:
targetVolume = 0xFF;
break;
default:
break;
}
if (targetVolume != 0xFF) {
SEQCMD_SET_CHANNEL_DISABLE_MASK(seqPlayerIndex, channelMask);
AudioSeq_SetVolumeScale(SEQ_PLAYER_BGM_MAIN, VOL_SCALE_INDEX_BGM_SUB, targetVolume, 1);
} else {
AudioSeq_SetVolumeScale(SEQ_PLAYER_BGM_MAIN, VOL_SCALE_INDEX_BGM_SUB, 0x7F, 0);
seqId = AudioSeq_GetActiveSeqId(seqPlayerIndex);
if (seqId != NA_BGM_DISABLED) {
SEQCMD_PLAY_SEQUENCE(seqPlayerIndex, 0, seqId);
}
}
}
void Audio_PlayMorningSceneSequence(u16 seqId, u8 dayMinusOne) {
Audio_StartMorningSceneSequence(seqId);
SEQCMD_SET_SEQPLAYER_IO(SEQ_PLAYER_BGM_MAIN, 4, dayMinusOne);
}
void Audio_StartMorningSceneSequence(u16 seqId) {
if (seqId != NA_BGM_AMBIENCE) {
SEQCMD_STOP_SEQUENCE(SEQ_PLAYER_AMBIENCE, 0);
Audio_StartSceneSequence(seqId);
Audio_PlaySequenceWithSeqPlayerIO(SEQ_PLAYER_BGM_MAIN, seqId, 0, 0, 1);
} else {
Audio_PlayAmbience(AMBIENCE_ID_08);
}
}
void Audio_PlaySceneSequence(u16 seqId, u8 dayMinusOne) {
if (sRequestedSceneSeqId != seqId) {
if (seqId == NA_BGM_AMBIENCE) {
Audio_PlayAmbience(AMBIENCE_ID_08);
} else if ((seqId != NA_BGM_FINAL_HOURS) || (sPrevMainBgmSeqId == NA_BGM_DISABLED)) {
Audio_StartSceneSequence(seqId);
SEQCMD_SET_SEQPLAYER_IO(SEQ_PLAYER_BGM_MAIN, 4, dayMinusOne);
}
sRequestedSceneSeqId = seqId;
}
}
void Audio_StartSceneSequence(u16 seqId) {
u8 fadeInDuration = 0;
u8 skipHarpIntro;
if ((sSeqFlags[sPrevSceneSeqId] & SEQ_FLAG_RESUME_PREV) && (sSeqFlags[seqId & 0xFF & 0xFF] & SEQ_FLAG_RESUME)) {
// Resume the sequence from the point where it left off last time it was played in the scene
if ((sSeqResumePoint & 0x3F) != 0) {
fadeInDuration = 30;
}
// Write the sequence resumePoint to resume from into ioPort 7
Audio_PlaySequenceWithSeqPlayerIO(SEQ_PLAYER_BGM_MAIN, seqId, fadeInDuration, 7, sSeqResumePoint);
sSeqResumePoint = 0;
} else {
// Start the sequence from the beginning
// Writes to ioPort 7. See `SEQ_FLAG_SKIP_HARP_INTRO` for writing a value of 1 to ioPort 7.
if (sSeqFlags[seqId & 0xFF & 0xFF] & SEQ_FLAG_SKIP_HARP_INTRO) {
skipHarpIntro = 1;
} else {
skipHarpIntro = (u8)SEQ_IO_VAL_NONE;
}
Audio_PlaySequenceWithSeqPlayerIO(SEQ_PLAYER_BGM_MAIN, seqId, 0, 7, skipHarpIntro);
if (!(sSeqFlags[seqId] & SEQ_FLAG_RESUME_PREV)) {
// Reset the sequence resumePoint
sSeqResumePoint = SEQ_RESUME_POINT_NONE;
}
}
sPrevSceneSeqId = seqId & 0xFF;
}
void Audio_UpdateSceneSequenceResumePoint(void) {
u16 seqId = AudioSeq_GetActiveSeqId(SEQ_PLAYER_BGM_MAIN);
if ((seqId != NA_BGM_DISABLED) && (sSeqFlags[seqId & 0xFF & 0xFF] & SEQ_FLAG_RESUME)) {
if (sSeqResumePoint != SEQ_RESUME_POINT_NONE) {
// Get the current point to resume from
sSeqResumePoint = gAudioCtx.seqPlayers[SEQ_PLAYER_BGM_MAIN].seqScriptIO[3];
} else {
// Initialize the point to resume from to the start of the sequence
sSeqResumePoint = 0;
}
}
}
// Unused
void Audio_PlayBgmForSongOfStorms(void) {
if (AudioSeq_GetActiveSeqId(SEQ_PLAYER_BGM_MAIN) != NA_BGM_SONG_OF_STORMS) {
SEQCMD_PLAY_SEQUENCE(SEQ_PLAYER_BGM_MAIN, 0, NA_BGM_SONG_OF_STORMS | SEQ_FLAG_ASYNC);
}
}
/**
* Specifically for SEQ_PLAYER_BGM_MAIN
*/
void Audio_ScaleTempoAndFreqForMainBgm(f32 freqTempoScale, u8 duration) {
if (freqTempoScale == 1.0f) {
SEQCMD_RESET_TEMPO(SEQ_PLAYER_BGM_MAIN, duration);
} else {
SEQCMD_SCALE_TEMPO(SEQ_PLAYER_BGM_MAIN, duration, freqTempoScale * 100.0f);
}
SEQCMD_SET_SEQPLAYER_FREQ(SEQ_PLAYER_BGM_MAIN, duration, freqTempoScale * 1000.0f);
}
void Audio_SetSeqTempoAndFreq(u8 seqPlayerIndex, f32 freqTempoScale, u8 duration) {
if (freqTempoScale == 1.0f) {
SEQCMD_RESET_TEMPO(seqPlayerIndex, duration);
} else {
SEQCMD_SCALE_TEMPO(seqPlayerIndex, duration, freqTempoScale * 100.0f);
}
SEQCMD_SET_SEQPLAYER_FREQ(seqPlayerIndex, duration, freqTempoScale * 1000.0f);
}
void Audio_PlaySubBgm(u16 seqId) {
AudioSeq_SetVolumeScale(SEQ_PLAYER_BGM_SUB, VOL_SCALE_INDEX_BGM_SUB, 0x7F, 0);
SEQCMD_PLAY_SEQUENCE(SEQ_PLAYER_BGM_SUB, 0, seqId);
AudioSeq_SetVolumeScale(SEQ_PLAYER_BGM_MAIN, VOL_SCALE_INDEX_BGM_SUB, 0, 5);
SEQCMD_SETUP_RESTORE_SEQPLAYER_VOLUME_WITH_SCALE_INDEX(SEQ_PLAYER_BGM_SUB, SEQ_PLAYER_BGM_MAIN, 3, 10);
SEQCMD_SETUP_SET_CHANNEL_DISABLE_MASK(SEQ_PLAYER_BGM_SUB, SEQ_PLAYER_BGM_MAIN, 0);
}
void Audio_StopSubBgm(void) {
SEQCMD_STOP_SEQUENCE(SEQ_PLAYER_BGM_SUB, 0);
}
// Unused remnant of OoT
void Audio_IncreaseTempoForTimedMinigame(void) {
if ((AudioSeq_GetActiveSeqId(SEQ_PLAYER_BGM_MAIN) == NA_BGM_TIMED_MINI_GAME) &&
AudioSeq_IsSeqCmdNotQueued(SEQCMD_OP_PLAY_SEQUENCE << 28, SEQCMD_OP_MASK)) {
// Set tempo to be higher than the default tempo for th timed mini-game sequence
SEQCMD_SET_TEMPO(SEQ_PLAYER_BGM_MAIN, 5, 210);
}
}
void Audio_PlaySequenceInCutscene(u16 seqId) {
if (sSeqFlags[seqId & 0xFF & 0xFF] & SEQ_FLAG_FANFARE) {
Audio_PlayFanfare(seqId);
} else if (sSeqFlags[seqId & 0xFF & 0xFF] & SEQ_FLAG_FANFARE_KAMARO) {
SEQCMD_PLAY_SEQUENCE(SEQ_PLAYER_FANFARE, 0, seqId);
} else if (sSeqFlags[seqId & 0xFF & 0xFF] & SEQ_FLAG_NO_AMBIENCE) {
SEQCMD_PLAY_SEQUENCE(SEQ_PLAYER_BGM_SUB, 0, seqId);
} else {
Audio_PlaySequenceWithSeqPlayerIO(SEQ_PLAYER_BGM_MAIN, seqId, 0, 7, SEQ_IO_VAL_NONE);
AudioSeq_SetVolumeScale(SEQ_PLAYER_BGM_MAIN, VOL_SCALE_INDEX_FANFARE, 0x7F, 0);
AudioSeq_SetVolumeScale(SEQ_PLAYER_BGM_MAIN, VOL_SCALE_INDEX_BGM_SUB, 0x7F, 0);
SEQCMD_STOP_SEQUENCE(SEQ_PLAYER_FANFARE, 0);
}
}
void Audio_StopSequenceInCutscene(u16 seqId) {
if (sSeqFlags[seqId & 0xFF & 0xFF] & SEQ_FLAG_FANFARE) {
SEQCMD_STOP_SEQUENCE(SEQ_PLAYER_FANFARE, 0);
} else if (sSeqFlags[seqId & 0xFF & 0xFF] & SEQ_FLAG_FANFARE_KAMARO) {
SEQCMD_STOP_SEQUENCE(SEQ_PLAYER_FANFARE, 0);
} else if (sSeqFlags[seqId & 0xFF & 0xFF] & SEQ_FLAG_NO_AMBIENCE) {
SEQCMD_STOP_SEQUENCE(SEQ_PLAYER_BGM_SUB, 0);
} else {
SEQCMD_STOP_SEQUENCE(SEQ_PLAYER_BGM_MAIN, 0);
}
}
s32 Audio_IsSequencePlaying(u8 seqId) {
u8 seqPlayerIndex = SEQ_PLAYER_BGM_MAIN;
if (sSeqFlags[seqId & 0xFF] & SEQ_FLAG_FANFARE) {
seqPlayerIndex = SEQ_PLAYER_FANFARE;
} else if (sSeqFlags[seqId & 0xFF] & SEQ_FLAG_FANFARE_KAMARO) {
seqPlayerIndex = SEQ_PLAYER_FANFARE;
}
if (seqId == (AudioSeq_GetActiveSeqId(seqPlayerIndex) & 0xFF)) {
return true;
} else {
return false;
}
}
void Audio_PlayBgm_StorePrevBgm(u16 seqId) {
u16 curSeqId = AudioSeq_GetActiveSeqId(SEQ_PLAYER_BGM_MAIN);
if (curSeqId == NA_BGM_DISABLED) {
curSeqId = NA_BGM_GENERAL_SFX;
}
if (curSeqId != seqId) {
Audio_SetSequenceMode(SEQ_MODE_IGNORE);
// Ensure the sequence about to be stored isn't also storing a separate sequence
if (!(sSeqFlags[curSeqId] & SEQ_FLAG_RESTORE)) {
sPrevMainBgmSeqId = curSeqId;
}
SEQCMD_PLAY_SEQUENCE(SEQ_PLAYER_BGM_MAIN, 0, seqId + SEQ_FLAG_ASYNC);
}
}
/**
* To be used in conjunction with Audio_PlayBgm_StorePrevBgm
*/
void Audio_RestorePrevBgm(void) {
if ((AudioSeq_GetActiveSeqId(SEQ_PLAYER_BGM_MAIN) != NA_BGM_DISABLED) &&
(sSeqFlags[AudioSeq_GetActiveSeqId(SEQ_PLAYER_BGM_MAIN) & 0xFF] & SEQ_FLAG_RESTORE)) {
if ((sPrevMainBgmSeqId == NA_BGM_DISABLED) || (sPrevMainBgmSeqId == NA_BGM_GENERAL_SFX)) {
SEQCMD_STOP_SEQUENCE(SEQ_PLAYER_BGM_MAIN, 0);
} else {
if (sPrevMainBgmSeqId == NA_BGM_AMBIENCE) {
sPrevMainBgmSeqId = sPrevAmbienceSeqId;
}
SEQCMD_PLAY_SEQUENCE(SEQ_PLAYER_BGM_MAIN, 0, sPrevMainBgmSeqId + SEQ_FLAG_ASYNC);
}
sPrevMainBgmSeqId = NA_BGM_DISABLED;
}
}
// Unused
void Audio_PlayAmbience_StorePrevBgm(u8 ambienceId) {
u16 seqId = AudioSeq_GetActiveSeqId(SEQ_PLAYER_BGM_MAIN);
if (seqId != NA_BGM_AMBIENCE) {
sPrevMainBgmSeqId = seqId;
}
Audio_PlayAmbience(ambienceId);
}
// Unused
void Audio_ForceRestorePreviousBgm(void) {
if (sPrevMainBgmSeqId != NA_BGM_DISABLED) {
SEQCMD_PLAY_SEQUENCE(SEQ_PLAYER_BGM_MAIN, 0, sPrevMainBgmSeqId + SEQ_FLAG_ASYNC);
}
sPrevMainBgmSeqId = NA_BGM_DISABLED;
}
void Audio_PlayFanfareWithPlayerIOPort7(u16 seqId, u8 ioData) {
Audio_PlayFanfare(seqId);
SEQCMD_SET_SEQPLAYER_IO(SEQ_PLAYER_FANFARE, 7, ioData);
}
void Audio_MuteBgmPlayersForFanfare(void) {
AudioSeq_SetVolumeScale(SEQ_PLAYER_BGM_MAIN, VOL_SCALE_INDEX_FANFARE, 0, 5);
AudioSeq_SetVolumeScale(SEQ_PLAYER_BGM_SUB, VOL_SCALE_INDEX_FANFARE, 0, 5);
SEQCMD_SETUP_RESTORE_SEQPLAYER_VOLUME_WITH_SCALE_INDEX(SEQ_PLAYER_FANFARE, SEQ_PLAYER_BGM_MAIN, 1, 10);
SEQCMD_SETUP_RESTORE_SEQPLAYER_VOLUME_WITH_SCALE_INDEX(SEQ_PLAYER_FANFARE, SEQ_PLAYER_BGM_SUB, 1, 10);
SEQCMD_SETUP_SET_CHANNEL_DISABLE_MASK(SEQ_PLAYER_FANFARE, SEQ_PLAYER_BGM_MAIN, 0);
}
/**
* Sets up seqId to play on seqPlayerIndex 1
*/
void Audio_PlayFanfare(u16 seqId) {
u16 prevSeqId = AudioSeq_GetActiveSeqId(SEQ_PLAYER_FANFARE);
u32 outNumFonts;
u8* prevFontId = AudioThread_GetFontsForSequence(prevSeqId & 0xFF, &outNumFonts);
u8* fontId = AudioThread_GetFontsForSequence(seqId & 0xFF, &outNumFonts);
if ((prevSeqId == NA_BGM_DISABLED) || (*prevFontId == *fontId)) {
sFanfareState = 1;
} else {
sFanfareState = 5;
SEQCMD_STOP_SEQUENCE(SEQ_PLAYER_FANFARE, 0);
}
sFanfareSeqId = seqId;
}
void Audio_UpdateFanfare(void) {
if (sFanfareState != 0) {
if ((sFanfareState != 5) &&
!AudioSeq_IsSeqCmdNotQueued((SEQCMD_OP_STOP_SEQUENCE << 28) | (SEQ_PLAYER_FANFARE << 24),
SEQCMD_OP_MASK | SEQCMD_ASYNC_ACTIVE | SEQCMD_SEQPLAYER_MASK)) {
sFanfareState = 0;
} else {
sFanfareState--;
if (sFanfareState == 0) {
AUDIOCMD_GLOBAL_POP_PERSISTENT_CACHE(SEQUENCE_TABLE);
AUDIOCMD_GLOBAL_POP_PERSISTENT_CACHE(FONT_TABLE);
AudioSeq_GetActiveSeqId(SEQ_PLAYER_BGM_MAIN);
if (AudioSeq_GetActiveSeqId(SEQ_PLAYER_FANFARE) == NA_BGM_DISABLED) {
Audio_MuteBgmPlayersForFanfare();
}
SEQCMD_PLAY_SEQUENCE(SEQ_PLAYER_FANFARE, 0, sFanfareSeqId);
SEQCMD_SET_CHANNEL_DISABLE_MASK(SEQ_PLAYER_BGM_MAIN, 0xFFFF);
}
}
}
}
void Audio_PlayFanfareWithPlayerIOCustomPort(u16 seqId, s8 ioPort, u8 ioData) {
SEQCMD_SET_SEQPLAYER_IO(SEQ_PLAYER_FANFARE, ioPort, ioData);
Audio_PlayFanfare(seqId);
}
void Audio_PlaySequenceWithSeqPlayerIO(s8 seqPlayerIndex, u16 seqId, u8 fadeInDuration, s8 ioPort, u8 ioData) {
u16 flaggedSeqId;
SEQCMD_SET_SEQPLAYER_IO(seqPlayerIndex, ioPort, ioData);
if ((seqId & 0xFF) < 2) {
flaggedSeqId = seqId;
} else {
flaggedSeqId = seqId | 0x8000;
}
SEQCMD_PLAY_SEQUENCE((u32)seqPlayerIndex, fadeInDuration, flaggedSeqId);
}
void Audio_SetSequenceMode(u8 seqMode) {
s32 volumeFadeInTimer;
u16 seqId;
u8 volumeFadeOutTimer;
if ((sPrevMainBgmSeqId == NA_BGM_DISABLED) && (sPrevMainBgmSeqId == NA_BGM_DISABLED)) {
// clang-format off
if (sAudioCutsceneFlag || sSpatialSeqIsActive[SEQ_PLAYER_BGM_SUB]) { \
seqMode = SEQ_MODE_IGNORE;
}
// clang-format on
seqId = gActiveSeqs[SEQ_PLAYER_BGM_MAIN].seqId;
if ((seqId == NA_BGM_DISABLED) || (sSeqFlags[(u8)(seqId & 0xFF)] & SEQ_FLAG_ENEMY) ||
((sPrevSeqMode & 0x7F) == SEQ_MODE_ENEMY)) {
if (seqMode != (sPrevSeqMode & 0x7F)) {
if (seqMode == SEQ_MODE_ENEMY) {
// If only seqMode = SEQ_MODE_ENEMY (Start)
volumeFadeInTimer = ABS_ALT(gActiveSeqs[SEQ_PLAYER_BGM_SUB].volScales[1] - sBgmEnemyVolume);
AudioSeq_SetVolumeScale(SEQ_PLAYER_BGM_SUB, VOL_SCALE_INDEX_BGM_SUB, sBgmEnemyVolume,
volumeFadeInTimer);
SEQCMD_PLAY_SEQUENCE(SEQ_PLAYER_BGM_SUB, 10, NA_BGM_ENEMY | 0x800);
if (seqId >= NA_BGM_TERMINA_FIELD) {
AudioSeq_SetVolumeScale(SEQ_PLAYER_BGM_MAIN, VOL_SCALE_INDEX_BGM_SUB, 0x7F - sBgmEnemyVolume,
10);
Audio_SplitBgmChannels(sBgmEnemyVolume);
}
} else if ((sPrevSeqMode & 0x7F) == SEQ_MODE_ENEMY) {
// If only sPrevSeqMode = SEQ_MODE_ENEMY (End)
SEQCMD_STOP_SEQUENCE(SEQ_PLAYER_BGM_SUB, 10);
if (seqMode == SEQ_MODE_IGNORE) {
volumeFadeOutTimer = 0;
} else {
volumeFadeOutTimer = 10;
}
AudioSeq_SetVolumeScale(SEQ_PLAYER_BGM_MAIN, VOL_SCALE_INDEX_BGM_SUB, 0x7F, volumeFadeOutTimer);
Audio_SplitBgmChannels(0);
}
sPrevSeqMode = seqMode + 0x80;
} else {
if (seqMode == SEQ_MODE_ENEMY) {
// If both seqMode = sPrevSeqMode = SEQ_MODE_ENEMY
if ((AudioSeq_GetActiveSeqId(SEQ_PLAYER_BGM_SUB) == NA_BGM_DISABLED) &&
(seqId != NA_BGM_DISABLED) && (sSeqFlags[seqId & 0xFF & 0xFF] & SEQ_FLAG_ENEMY)) {
SEQCMD_PLAY_SEQUENCE(SEQ_PLAYER_BGM_SUB, 10, NA_BGM_ENEMY | 0x800);
sPrevSeqMode = seqMode + 0x80;
}
}
}
} else {
// Remnant of OoT's Hyrule Field Sequence
if (seqMode == SEQ_MODE_DEFAULT) {
if (sPrevSeqMode == SEQ_MODE_STILL) {
sNumFramesMoving = 0;
}
sNumFramesStill = 0;
sNumFramesMoving++;
} else {
sNumFramesStill++;
}
if ((seqMode == SEQ_MODE_STILL) && (sNumFramesStill < 30) && (sNumFramesMoving > 20)) {
seqMode = SEQ_MODE_DEFAULT;
}
sPrevSeqMode = seqMode;
SEQCMD_SET_SEQPLAYER_IO(SEQ_PLAYER_BGM_MAIN, 2, seqMode);
}
}
}
void Audio_UpdateEnemyBgmVolume(f32 dist) {
f32 adjDist;
u16 seqId = gActiveSeqs[SEQ_PLAYER_BGM_MAIN].seqId;
if (sPrevSeqMode == (SEQ_MODE_ENEMY | 0x80)) {
if (dist != sBgmEnemyDist) {
// clamp (dist - 150.0f) between 0 and 350
if (dist < 150.0f) {
adjDist = 0.0f;
} else if (dist > 500.0f) {
adjDist = 350.0f;
} else {
adjDist = dist - 150.0f;
}
sBgmEnemyVolume = ((350.0f - adjDist) * 127.0f) / 350.0f;
AudioSeq_SetVolumeScale(SEQ_PLAYER_BGM_SUB, VOL_SCALE_INDEX_BGM_SUB, sBgmEnemyVolume, 10);
if ((seqId >= NA_BGM_TERMINA_FIELD) && !(sSeqFlags[seqId & 0xFF & 0xFF] & SEQ_FLAG_FANFARE_KAMARO)) {
AudioSeq_SetVolumeScale(SEQ_PLAYER_BGM_MAIN, VOL_SCALE_INDEX_BGM_SUB, (0x7F - sBgmEnemyVolume), 10);
}
}
Audio_SplitBgmChannels(sBgmEnemyVolume);
}
sBgmEnemyDist = dist;
}
void Audio_UpdateRomaniSinging(f32 dist, u16 seqId) {
s8 pad;
s8 melodyVolume;
s16 curSeqId;
if (sRomaniSingingDisabled) {
return;
}
curSeqId = (s8)(AudioSeq_GetActiveSeqId(SEQ_PLAYER_BGM_MAIN) & 0xFF);
if (curSeqId == (seqId & 0xFF)) {
if ((seqId & 0xFF) == NA_BGM_ROMANI_RANCH) {
// Romani is singing along with the Romani Ranch Sequence
if (dist > 2000.0f) {
melodyVolume = 127;
} else if (dist < 200.0f) {
melodyVolume = 0;
} else {
melodyVolume = (s8)(((dist - 200.0f) * 127.0f) / 1800.0f);
}
// Update volume for channels 0 & 1, which contains Romani's singing
SEQCMD_SET_CHANNEL_VOLUME(SEQ_PLAYER_BGM_MAIN, 0, 3, 127 - melodyVolume);
SEQCMD_SET_CHANNEL_VOLUME(SEQ_PLAYER_BGM_MAIN, 1, 3, 127 - melodyVolume);
// Update volume for channel 13, which contains the melody line for Romani's Ranch Sequence
SEQCMD_SET_CHANNEL_VOLUME(SEQ_PLAYER_BGM_MAIN, 13, 3, melodyVolume);
if (sRomaniSingingTimer == 0) {
sRomaniSingingTimer++;
}
}
} else if ((curSeqId == NA_BGM_AMBIENCE) && ((seqId & 0xFF) == NA_BGM_ROMANI_RANCH)) {
// Romani is singing along with ambience
curSeqId = (s8)(AudioSeq_GetActiveSeqId(SEQ_PLAYER_BGM_SUB) & 0xFF);
if ((curSeqId != (seqId & 0xFF)) && (sRomaniSingingTimer < 10)) {
// Disable all channels between 2-15.
// Only allow the two channels with Romani's singing to play, and surpress the full Romani Ranch sequence.
Audio_PlaySequenceWithSeqPlayerIO(SEQ_PLAYER_BGM_SUB, NA_BGM_ROMANI_RANCH, 0, 0, 0);
SEQCMD_SET_CHANNEL_DISABLE_MASK(SEQ_PLAYER_BGM_SUB, 0xFFFC);
sRomaniSingingTimer = 10;
}
if (dist > 2000.0f) {
melodyVolume = 127;
} else if (dist < 200.0f) {
melodyVolume = 0;
} else {
melodyVolume = (s8)(((dist - 200.0f) * 127.0f) / 1800.0f);
}
// Update volume for channels 0 & 1, which contains Romani's singing
SEQCMD_SET_CHANNEL_VOLUME(SEQ_PLAYER_BGM_SUB, 0, 3, 127 - melodyVolume);
SEQCMD_SET_CHANNEL_VOLUME(SEQ_PLAYER_BGM_SUB, 1, 3, 127 - melodyVolume);
}
if (sRomaniSingingTimer < 10) {
sRomaniSingingTimer++;
}
}
u8 func_801A3950(u8 seqPlayerIndex, u8 resetChannelIO) {
u8 ret = SEQ_IO_VAL_NONE;
SequenceChannel* channel = gAudioCtx.seqPlayers[seqPlayerIndex].channels[15];
if (gAudioCtx.seqPlayers[seqPlayerIndex].enabled && channel->enabled) {
if (channel->seqScriptIO[0] != SEQ_IO_VAL_NONE) {
ret = channel->seqScriptIO[0];
if (resetChannelIO == true) {
SEQCMD_SET_CHANNEL_IO(seqPlayerIndex, 15, 0, (u8)SEQ_IO_VAL_NONE);
}
}
}
return ret;
}
// Used only by minifrog
u8 func_801A39F8(void) {
u8 frogIndex = 0xFF;
s32 pad;
SequenceChannel* channel = gAudioCtx.seqPlayers[SEQ_PLAYER_BGM_SUB].channels[15];
if (gAudioCtx.seqPlayers[SEQ_PLAYER_BGM_SUB].enabled) {
if ((AudioSeq_GetActiveSeqId(SEQ_PLAYER_BGM_SUB) == NA_BGM_FROG_SONG) && channel->enabled) {
if (channel->seqScriptIO[0] != -1) {
frogIndex = channel->seqScriptIO[0];
AUDIOCMD_CHANNEL_SET_IO(SEQ_PLAYER_BGM_SUB, 15, 0, SEQ_IO_VAL_NONE);
}
}
}
return frogIndex;
}
void Audio_SetPauseState(u8 isPauseMenuOpen) {
if ((isPauseMenuOpen == false) && (sAudioPauseState != AUDIO_PAUSE_STATE_CLOSED)) {
sAudioPauseState = AUDIO_PAUSE_STATE_CLOSING;
} else {
sAudioPauseState = isPauseMenuOpen << 1; // Set to AUDIO_PAUSE_STATE_OPEN
}
}
void Audio_UpdatePauseState(void) {
if ((sAudioPauseState != AUDIO_PAUSE_STATE_CLOSED) && (sAudioPauseState != AUDIO_PAUSE_STATE_OPEN)) {
sAudioPauseState--; // Set to AUDIO_PAUSE_STATE_CLOSED
}
}
void Audio_PlaySfx_PauseMenuOpenOrClose(u8 pauseMenuOpenOrClose) {
sAudioPauseMenuOpenOrClose = pauseMenuOpenOrClose;
if (pauseMenuOpenOrClose != SFX_PAUSE_MENU_CLOSE) {
Audio_PlaySfx(NA_SE_SY_WIN_OPEN);
AUDIOCMD_GLOBAL_MUTE(AUDIOCMD_ALL_SEQPLAYERS);
} else {
Audio_PlaySfx(NA_SE_SY_WIN_CLOSE);
AUDIOCMD_GLOBAL_UNMUTE(AUDIOCMD_ALL_SEQPLAYERS, false);
}
}
// Only used by guru guru
void Audio_MuteSeqPlayerBgmSub(u8 isMuted) {
if (isMuted == true) {
AUDIOCMD_GLOBAL_MUTE(SEQ_PLAYER_BGM_SUB);
} else {
AUDIOCMD_GLOBAL_UNMUTE(SEQ_PLAYER_BGM_SUB, false);
}
}
/**
* Enable or disable Romani's singing
*
* @param romaniSingingDisabled true to disable, false to enable
*/
void Audio_ToggleRomaniSinging(u8 romaniSingingDisabled) {
u8 seqPlayerIndex;
u16 channelMaskDisable;
sRomaniSingingDisabled = romaniSingingDisabled;
if ((AudioSeq_GetActiveSeqId(SEQ_PLAYER_BGM_MAIN) & 0xFF) == NA_BGM_ROMANI_RANCH) {
// Romani is singing along with the Romani Ranch Sequence
seqPlayerIndex = SEQ_PLAYER_BGM_MAIN;
// Do not disable any channel.
// Allow the full Romani Ranch sequence to play in addition to Romani's singing.
channelMaskDisable = 0;
} else if ((AudioSeq_GetActiveSeqId(SEQ_PLAYER_BGM_SUB) & 0xFF) == NA_BGM_ROMANI_RANCH) {
seqPlayerIndex = SEQ_PLAYER_BGM_SUB;
// Disable all channels between 2-15.
// Only allow the two channels with Romani's singing to play, and surpress the full Romani sequence.
channelMaskDisable = 0xFFFC;
} else {
return;
}
if (romaniSingingDisabled) {
// Turn volume off for channels 0 & 1, which contains Romani's singing
SEQCMD_SET_CHANNEL_VOLUME(seqPlayerIndex, 0, 1, 0);
SEQCMD_SET_CHANNEL_VOLUME(seqPlayerIndex, 1, 1, 0);
if (seqPlayerIndex == SEQ_PLAYER_BGM_SUB) {
// When singing along with ambience, disable all 16 channels
SEQCMD_SET_CHANNEL_DISABLE_MASK(seqPlayerIndex, channelMaskDisable | 3);
}
} else {
if (seqPlayerIndex == SEQ_PLAYER_BGM_SUB) {
// When singing along with ambience, start the sequence
Audio_PlaySequenceWithSeqPlayerIO(SEQ_PLAYER_BGM_SUB, NA_BGM_ROMANI_RANCH, 0, 0, 0);
}
// Turn volume on for only channels 0 & 1, which contains Romani's singing
SEQCMD_SET_CHANNEL_VOLUME(seqPlayerIndex, 0, 1, 0x7F);
SEQCMD_SET_CHANNEL_VOLUME(seqPlayerIndex, 1, 1, 0x7F);
if (seqPlayerIndex == SEQ_PLAYER_BGM_SUB) {
// When singing along with ambience, disable channels 2-15
SEQCMD_SET_CHANNEL_DISABLE_MASK(seqPlayerIndex, channelMaskDisable);
}
}
}
void Audio_SetEnvReverb(s8 reverb) {
sAudioEnvReverb = reverb & 0x7F;
}
void Audio_SetCodeReverb(s8 reverb) {
u8 reverbIndex;
if (reverb != 0) {
if ((reverb & 0x40) != (sAudioCodeReverb & 0x40)) {
reverbIndex = (reverb >> 6) + 1;
Audio_SetSfxReverbIndexExceptOcarinaBank(reverbIndex);
}
sAudioCodeReverb = reverb & 0x7F;
}
}
/**
* Possibly a test for surround sound
* Unused
*/
void Audio_PlaySfx_SurroundSoundTest(void) {
s32 val = 0;
if (sSoundMode == SOUNDMODE_SURROUND_EXTERNAL) {
val = 2;
}
Audio_PlaySfx_AtPosWithAllChannelsIO(&gSfxDefaultPos, NA_SE_SY_SOUT_DEMO, val);
}
void Audio_SetFileSelectSettings(s8 audioSetting) {
s8 soundMode;
switch (audioSetting) {
case SAVE_AUDIO_STEREO:
soundMode = SOUNDMODE_STEREO;
sSoundMode = SOUNDMODE_STEREO;
break;
case SAVE_AUDIO_MONO:
soundMode = SOUNDMODE_MONO;
sSoundMode = SOUNDMODE_MONO;
break;
case SAVE_AUDIO_HEADSET:
soundMode = SOUNDMODE_HEADSET;
sSoundMode = SOUNDMODE_HEADSET;
break;
case SAVE_AUDIO_SURROUND:
soundMode = SOUNDMODE_SURROUND;
sSoundMode = SOUNDMODE_SURROUND_EXTERNAL;
break;
default:
break;
}
SEQCMD_SET_SOUND_MODE(soundMode);
}
void Audio_SetBaseFilter(u8 filter) {
if (sAudioBaseFilter != filter) {
if (filter == 0) {
AudioSfx_StopById(NA_SE_PL_IN_BUBBLE);
} else if (sAudioBaseFilter == 0) {
AudioSfx_PlaySfx(NA_SE_PL_IN_BUBBLE, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
}
sAudioBaseFilter = filter;
sAudioBaseFilter2 = filter;
}
void Audio_SetExtraFilter(u8 filter) {
u8 channelIndex;
sAudioExtraFilter2 = filter;
sAudioExtraFilter = filter;
if (gActiveSeqs[SEQ_PLAYER_AMBIENCE].seqId == NA_BGM_AMBIENCE) {
for (channelIndex = 0; channelIndex < SEQ_NUM_CHANNELS; channelIndex++) {
// seq player 4, all channels, slot 6
AUDIOCMD_CHANNEL_SET_IO(SEQ_PLAYER_AMBIENCE, channelIndex, 6, filter);
}
}
}
void Audio_SetCutsceneFlag(s8 flag) {
sAudioCutsceneFlag = flag;
}
void Audio_PlaySfx_IfNotInCutsceneImpl(u16 sfxId, Vec3f* pos, u8 token, f32* freqScale, f32* volume, s8* reverbAdd) {
if (!sAudioCutsceneFlag) {
AudioSfx_PlaySfx(sfxId, pos, token, freqScale, volume, reverbAdd);
}
}
void Audio_PlaySfx_IfNotInCutscene(u16 sfxId) {
Audio_PlaySfx_IfNotInCutsceneImpl(sfxId, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
}
// Unused
void Audio_MuteSfxAndAmbienceSeqExceptSystemAndOcarina(u8 muteOnlySfxAndAmbienceSeq) {
sMuteOnlySfxAndAmbienceSeq = muteOnlySfxAndAmbienceSeq;
}
void Audio_SetSpec(u8 specId) {
if (!sMuteOnlySfxAndAmbienceSeq) {
SEQCMD_RESET_AUDIO_HEAP(0, 0, specId);
} else {
SEQCMD_RESET_AUDIO_HEAP(2, 0, specId);
}
}
void Audio_MuteAllSeqExceptSystemAndOcarina(u16 duration) {
s32 skip;
u8 channelIndex;
if (!sMuteOnlySfxAndAmbienceSeq) {
sAllPlayersMutedExceptSystemAndOcarina = true;
SEQCMD_STOP_SEQUENCE(SEQ_PLAYER_BGM_MAIN, (duration * 3) / 2);
SEQCMD_STOP_SEQUENCE(SEQ_PLAYER_FANFARE, (duration * 3) / 2);
SEQCMD_STOP_SEQUENCE(SEQ_PLAYER_BGM_SUB, (duration * 3) / 2);
}
SEQCMD_STOP_SEQUENCE(SEQ_PLAYER_AMBIENCE, (duration * 3) / 2);
for (channelIndex = 0; channelIndex < SEQ_NUM_CHANNELS; channelIndex++) {
skip = false;
switch (channelIndex) {
case SFX_CHANNEL_SYSTEM0:
case SFX_CHANNEL_SYSTEM1:
if (gAudioSpecId == 10) {} // Remnant of OoT
if (gAudioSpecId == 11) {}
skip = true;
break;
case SFX_CHANNEL_OCARINA:
skip = true;
break;
}
if (!skip) {
SEQCMD_SET_CHANNEL_VOLUME(SEQ_PLAYER_SFX, channelIndex, (u8)(duration >> 1), 0);
}
}
}
void Audio_MuteSfxAndAmbienceSeqExceptSysAndOca(u16 duration) {
sMuteOnlySfxAndAmbienceSeq = true;
Audio_MuteAllSeqExceptSystemAndOcarina(duration);
}
void Audio_StopFanfare(u16 duration) {
SEQCMD_STOP_SEQUENCE(SEQ_PLAYER_BGM_MAIN, duration);
if (AudioSeq_GetActiveSeqId(SEQ_PLAYER_FANFARE) != NA_BGM_DISABLED) {
SEQCMD_STOP_SEQUENCE(SEQ_PLAYER_FANFARE, duration);
}
SEQCMD_STOP_SEQUENCE(SEQ_PLAYER_BGM_SUB, duration);
SEQCMD_STOP_SEQUENCE(SEQ_PLAYER_AMBIENCE, duration);
AudioSeq_SetVolumeScale(SEQ_PLAYER_BGM_MAIN, VOL_SCALE_INDEX_BGM_SUB, 0x7F, 0);
AudioSeq_SetVolumeScale(SEQ_PLAYER_BGM_MAIN, VOL_SCALE_INDEX_FANFARE, 0x7F, 0);
}
/**
* The flag 0xFF makes the sequence process SkipTicks and SkipForwardSequence
* Unused
*/
void Audio_StartSfxPlayer(void) {
AudioSeq_StartSequence(SEQ_PLAYER_SFX, NA_BGM_GENERAL_SFX, 0xFF, 5);
}
void Audio_DisableAllSeq(void) {
AUDIOCMD_GLOBAL_DISABLE_SEQPLAYER(SEQ_PLAYER_BGM_MAIN, 0);
AUDIOCMD_GLOBAL_DISABLE_SEQPLAYER(SEQ_PLAYER_FANFARE, 0);
AUDIOCMD_GLOBAL_DISABLE_SEQPLAYER(SEQ_PLAYER_SFX, 0);
AUDIOCMD_GLOBAL_DISABLE_SEQPLAYER(SEQ_PLAYER_BGM_SUB, 0);
AUDIOCMD_GLOBAL_DISABLE_SEQPLAYER(SEQ_PLAYER_AMBIENCE, 0);
AudioThread_ScheduleProcessCmds();
}
s8 Audio_GetEnabledNotesCount(void) {
return AudioThread_GetEnabledNotesCount();
}
// Unused
void func_801A4348(void) {
Audio_DisableAllSeq();
AudioThread_ScheduleProcessCmds();
// Wait for all notes to be finished
while (true) {
if (Audio_GetEnabledNotesCount() == 0) {
break;
}
}
}
void Audio_SetSfxVolumeExceptSystemAndOcarinaBanks(u8 volume) {
u8 channelIndex;
if (!sAllPlayersMutedExceptSystemAndOcarina) {
for (channelIndex = 0; channelIndex < SEQ_NUM_CHANNELS; channelIndex++) {
switch (channelIndex) {
case SFX_CHANNEL_SYSTEM0:
case SFX_CHANNEL_SYSTEM1:
case SFX_CHANNEL_OCARINA:
break;
default:
SEQCMD_SET_CHANNEL_VOLUME(SEQ_PLAYER_SFX, channelIndex, 10, volume);
break;
}
}
}
}
void Audio_SetSfxReverbIndexExceptOcarinaBank(u8 reverbIndex) {
u8 channelIndex;
for (channelIndex = 0; channelIndex < SEQ_NUM_CHANNELS; channelIndex++) {
if (channelIndex != SFX_CHANNEL_OCARINA) {
AUDIOCMD_CHANNEL_SET_REVERB_INDEX(SEQ_PLAYER_SFX, channelIndex, reverbIndex);
}
}
}
void Audio_PreNMI(void) {
AudioThread_PreNMIInternal();
}
void Audio_ResetRequestedSceneSeqId(void) {
sRequestedSceneSeqId = NA_BGM_DISABLED;
}
void Audio_ResetData(void) {
u8 i;
for (i = 0; i < ARRAY_COUNT(sSfxSettings); i++) {
sSfxSettings[i].pos = NULL;
sSfxSettings[i].freqScale = 1.0;
sSfxSettings[i].reverbAdd = 0;
}
sSfxSettingsFlags = 0;
sTwoSemitonesLoweredFreq = 0.9f;
sSfxIncreasedReverb = 20;
sSfxVolumeDuration = 0;
sPrevSeqMode = 0;
sSfxSyncedVolume = 1.0f;
sSfxSyncedFreq = 1.0f;
sAudioBaseFilter = 0;
sAudioExtraFilter = 0;
sAudioBaseFilter2 = 0;
sAudioExtraFilter2 = 0;
AudioOcarina_ResetInstrument();
sRiverFreqScaleLerp.remainingFrames = 0;
sWaterfallFreqScaleLerp.remainingFrames = 0;
sRiverFreqScaleLerp.value = 1;
sWaterfallFreqScaleLerp.value = 1;
sSfxAdjustedFreq = 1;
sRiverSoundMainBgmVol = 0x7F;
sRiverSoundMainBgmCurrentVol = 0x7F;
sRiverSoundMainBgmLower = false;
sRiverSoundMainBgmRestore = false;
sGanonsTowerVol = 0xFF;
sRomaniSingingTimer = 0;
sObjSoundFanfareRequested = false;
sSpecReverb = sSpecReverbs[gAudioSpecId];
sAudioPauseMenuOpenOrClose = SFX_PAUSE_MENU_CLOSE;
sPrevMainBgmSeqId = NA_BGM_DISABLED;
AUDIOCMD_SEQPLAYER_SET_IO(SEQ_PLAYER_BGM_MAIN, 0, SEQ_IO_VAL_NONE);
sRiverSoundBgmPos = NULL;
sFanfareState = 0;
sRiverSoundBgmTimer = 1;
sRomaniSingingDisabled = false;
sObjSoundMainBgmSeqId = NA_BGM_GENERAL_SFX;
sPrevAmbienceSeqId = NA_BGM_DISABLED;
sSpatialSeqFlags = 0;
D_801FD432 = 0;
sSpatialSeqSeqId = NA_BGM_GENERAL_SFX;
sSpatialSubBgmFadeTimer = 0;
D_801FD434 = 0;
sSpatialSeqFadeTimer = 0;
sAllPlayersMutedExceptSystemAndOcarina = false;
sAudioPauseState = AUDIO_PAUSE_STATE_CLOSED;
sObjSoundPlayerIndex = SEQ_PLAYER_INVALID;
sIsFinalHoursOrSoaring = false;
for (i = SEQ_PLAYER_BGM_MAIN; i <= SEQ_PLAYER_BGM_SUB; i++) {
sSpatialSeqIsActive[i] = false;
}
}
s32 func_801A46F8(void) {
switch (func_801A3950(SEQ_PLAYER_FANFARE, true)) {
case 0:
case 0x8:
case 0x10:
case 0x18:
case 0x20:
return true;
default:
return false;
}
}
// used for z_obj_sound and z_en_gk
void Audio_PlaySfx_AtFixedPos(Vec3f* pos, u16 sfxId) {
static Vec3f sSfxOriginalPos[] = { 0.0f, 0.0f, 0.0f };
s32 i;
f32* dstPos = (f32*)&sSfxOriginalPos;
f32* srcPos = (f32*)pos;
// Vec3f copy
for (i = 0; i < 3; i++) {
dstPos[i] = srcPos[i];
}
Audio_PlaySfx_AtPos(sSfxOriginalPos, sfxId);
}
void Audio_PlaySfx_AtPosWithVolumeTransition(Vec3f* pos, u16 sfxId, u16 duration) {
Audio_PlaySfx_AtPosWithVolume(pos, sfxId, 0.0f);
Audio_SetSfxVolumeTransition(&gSfxVolume, 1.0f, duration);
}
void Audio_SetAmbienceChannelIO(u8 channelIndexRange, u8 ioPort, u8 ioData) {
u8 firstChannelIndex;
u8 lastChannelIndex;
u8 channelIndex;
if ((gActiveSeqs[SEQ_PLAYER_AMBIENCE].seqId != NA_BGM_AMBIENCE) &&
AudioSeq_IsSeqCmdNotQueued((SEQCMD_OP_PLAY_SEQUENCE << 28) | NA_BGM_AMBIENCE,
SEQCMD_OP_MASK | SEQCMD_SEQID_MASK)) {
return;
}
// channelIndexRange = 01 on ioPort 1
if ((((channelIndexRange << 8) + (u32)ioPort) == ((1 << 8) | (u32)1)) &&
(AudioSeq_GetActiveSeqId(SEQ_PLAYER_BGM_SUB) != NA_BGM_ROMANI_RANCH)) {
sRomaniSingingTimer = 0;
}
firstChannelIndex = channelIndexRange >> 4;
lastChannelIndex = channelIndexRange & 0xF;
if (firstChannelIndex == 0) {
firstChannelIndex = channelIndexRange & 0xF;
}
for (channelIndex = firstChannelIndex; channelIndex <= lastChannelIndex; channelIndex++) {
SEQCMD_SET_CHANNEL_IO(SEQ_PLAYER_AMBIENCE, channelIndex, ioPort, ioData);
}
}
void Audio_StartAmbience(u16 initChannelMask, u16 initMuteChannelMask) {
u8 channelIndex;
SEQCMD_SET_SEQPLAYER_IO(SEQ_PLAYER_AMBIENCE, SEQ_PLAYER_IO_PORT_0, 1);
SEQCMD_SET_SEQPLAYER_IO(SEQ_PLAYER_AMBIENCE, SEQ_PLAYER_IO_PORT_4, (u8)(initChannelMask >> 8));
SEQCMD_SET_SEQPLAYER_IO(SEQ_PLAYER_AMBIENCE, SEQ_PLAYER_IO_PORT_5, (u8)(initChannelMask & 0xFF));
AudioSeq_SetVolumeScale(SEQ_PLAYER_BGM_MAIN, VOL_SCALE_INDEX_BGM_MAIN, 0x7F, 1);
if ((AudioSeq_GetActiveSeqId(SEQ_PLAYER_AMBIENCE) != NA_BGM_DISABLED) &&
(AudioSeq_GetActiveSeqId(SEQ_PLAYER_AMBIENCE) != NA_BGM_AMBIENCE)) {
AudioSeq_StopSequence(SEQ_PLAYER_AMBIENCE, 0);
AUDIOCMD_GLOBAL_STOP_AUDIOCMDS();
}
if (AudioSeq_GetActiveSeqId(SEQ_PLAYER_BGM_SUB) == (NA_BGM_ENEMY | 0x800)) {
AudioSeq_SetVolumeScale(SEQ_PLAYER_BGM_MAIN, VOL_SCALE_INDEX_BGM_SUB, 0x7F, 1);
}
SEQCMD_PLAY_SEQUENCE(SEQ_PLAYER_AMBIENCE, 0, NA_BGM_AMBIENCE);
for (channelIndex = 0; channelIndex < SEQ_NUM_CHANNELS; channelIndex++) {
if (!(initMuteChannelMask & (1 << channelIndex)) && (initChannelMask & (1 << channelIndex))) {
SEQCMD_SET_CHANNEL_IO(SEQ_PLAYER_AMBIENCE, channelIndex, CHANNEL_IO_PORT_1, 1);
}
}
}
void Audio_PlayAmbience(u8 ambienceId) {
u8 i = 0;
u8 channelIndex;
u8 ioPort;
u8 ioData;
if (!((gActiveSeqs[SEQ_PLAYER_AMBIENCE].seqId != NA_BGM_DISABLED) &&
(sSeqFlags[gActiveSeqs[SEQ_PLAYER_AMBIENCE].seqId & 0xFF & 0xFF] & SEQ_FLAG_NO_AMBIENCE))) {
if (gActiveSeqs[SEQ_PLAYER_AMBIENCE].seqId != NA_BGM_AMBIENCE) {
sPrevAmbienceSeqId = gActiveSeqs[SEQ_PLAYER_AMBIENCE].seqId;
}
Audio_StartAmbience(sAmbienceData[ambienceId].initChannelMask, sAmbienceData[ambienceId].initMuteChannelMask);
while ((sAmbienceData[ambienceId].channelProperties[i] != 0xFF) &&
(i < ARRAY_COUNT(sAmbienceData[ambienceId].channelProperties))) {
channelIndex = sAmbienceData[ambienceId].channelProperties[i++];
ioPort = sAmbienceData[ambienceId].channelProperties[i++];
ioData = sAmbienceData[ambienceId].channelProperties[i++];
SEQCMD_SET_CHANNEL_IO(SEQ_PLAYER_AMBIENCE, channelIndex, ioPort, ioData);
}
SEQCMD_SET_CHANNEL_IO(SEQ_PLAYER_AMBIENCE, AMBIENCE_CHANNEL_SOUND_MODE, CHANNEL_IO_PORT_7, sSoundMode);
}
}
u32 Audio_SetAmbienceRandomBend(u8 seqScriptValIn, SequenceChannel* channel) {
u32 seqScriptValOut = seqScriptValIn;
gAudioCtx.seqPlayers[SEQ_PLAYER_AMBIENCE].applyBend = true;
if ((seqScriptValIn == 0) || (seqScriptValIn == 0xFF)) {
gAudioCtx.seqPlayers[SEQ_PLAYER_AMBIENCE].bend = 1.0f;
} else {
seqScriptValOut = AudioThread_NextRandom();
gAudioCtx.seqPlayers[SEQ_PLAYER_AMBIENCE].bend = 1.0293 - ((gAudioCtx.audioRandom & 0xF) / 144.0f);
return seqScriptValOut;
}
#ifdef AVOID_UB
return seqScriptValOut;
#endif
}
void Audio_Init(void) {
AudioLoad_Init(NULL, 0);
}
void AudioSfx_Init(u16 fadeTimer) {
u8 channelIndex;
AudioThread_ScheduleProcessCmds();
AudioSeq_StartSequence(SEQ_PLAYER_SFX, NA_BGM_GENERAL_SFX, 0x70, fadeTimer);
for (channelIndex = 0; channelIndex < ARRAY_COUNT(sSfxChannelState); channelIndex++) {
AUDIOCMD_CHANNEL_SET_SFX_STATE(SEQ_PLAYER_SFX, channelIndex, &sSfxChannelState[channelIndex]);
}
AUDIOCMD_GLOBAL_SET_CUSTOM_FUNCTION(AUDIO_CUSTOM_FUNCTION_SEQ_0, AudioSfx_SetFreqAndStereoBits);
AUDIOCMD_GLOBAL_SET_CUSTOM_FUNCTION(AUDIO_CUSTOM_FUNCTION_SEQ_1, Audio_SetAmbienceRandomBend);
}
void Audio_InitSound(void) {
Audio_ResetData();
AudioOcarina_ResetStaffs();
AudioSfx_ResetSfxChannelState();
AudioSeq_ResetActiveSequencesAndVolume();
AudioSfx_Reset();
AudioVoice_ResetData();
AudioSfx_Init(10);
}
void Audio_ResetForAudioHeapStep3(void) {
AudioSfx_Init(1);
AUDIOCMD_GLOBAL_UNMUTE(AUDIOCMD_ALL_SEQPLAYERS, true);
AudioThread_ScheduleProcessCmds();
AUDIOCMD_GLOBAL_STOP_AUDIOCMDS();
sIsFinalHoursOrSoaring = false;
sObjSoundMainBgmSeqId = NA_BGM_GENERAL_SFX;
sMuteOnlySfxAndAmbienceSeq = false;
}
void Audio_ResetForAudioHeapStep2(void) {
Audio_ResetForAudioHeapStep3();
if (gAudioSpecId < ARRAY_COUNT(gReverbSettingsTable)) {
AUDIOCMD_GLOBAL_SET_REVERB_DATA(1, REVERB_DATA_TYPE_SETTINGS, &gReverbSettingsTable[gAudioSpecId][1]);
}
}
void Audio_ResetForAudioHeapStep1(s32 specId) {
gAudioHeapResetState = AUDIO_HEAP_RESET_STATE_RESETTING;
Audio_ResetData();
AudioOcarina_ResetStaffs();
AudioSfx_ResetSfxChannelState();
AudioSeq_ResetActiveSequences();
AudioSfx_Reset();
AudioVoice_ResetWord();
if (gAudioSpecId == 0xB) {
AudioSfx_MuteBanks((1 << BANK_PLAYER) | (1 << BANK_ITEM) | (1 << BANK_ENV) | (1 << BANK_ENEMY) |
(1 << BANK_OCARINA) | (1 << BANK_VOICE));
}
}
void Audio_UnusedReset(void) {
AudioSeq_ResetActiveSequences();
AUDIOCMD_GLOBAL_UNMUTE(AUDIOCMD_ALL_SEQPLAYERS, true);
Audio_ResetData();
AudioSfx_ResetSfxChannelState();
AudioSfx_Init(1);
AudioVoice_ResetWord();
}