mirror of https://github.com/pmret/papermario.git
bgm update units
This commit is contained in:
parent
c3416b5cb2
commit
b37fa6a05b
|
|
@ -648,7 +648,7 @@ typedef struct MusicProximityTrigger {
|
|||
/* 0x00 */ VecXZf pos;
|
||||
/* 0x08 */ f32 innerDist;
|
||||
/* 0x0C */ f32 outerDist;
|
||||
/* 0x10 */ s32 unk;
|
||||
/* 0x10 */ s32 mix; /// which branch value to switch to
|
||||
/* 0x14 */ s32 manualActivationFlag;
|
||||
} MusicProximityTrigger; // size = 0x18
|
||||
|
||||
|
|
|
|||
|
|
@ -1028,6 +1028,12 @@ API_CALLABLE(RegisterMusicEvents);
|
|||
API_CALLABLE(FadeOutMusic);
|
||||
|
||||
/// @evtapi
|
||||
/// Start playing a song.
|
||||
///
|
||||
/// @param playerID MusicPlayer to use, should almost always be 0 (MUSIC_PLAYER_MAIN).
|
||||
/// @param song Song from SongIDs.
|
||||
/// @param variation
|
||||
/// @param volumeLevel Perceptual loudness from VOL_LEVEL_MUTE to VOL_LEVEL_FULL.
|
||||
API_CALLABLE(SetMusic);
|
||||
|
||||
/// @evtapi
|
||||
|
|
|
|||
45
src/audio.h
45
src/audio.h
|
|
@ -66,13 +66,35 @@ typedef u8* WaveData;
|
|||
#define AU_PAN_MID 64
|
||||
#define AU_PAN_MAX 127
|
||||
|
||||
// only valid for vol != 0
|
||||
// converts an 8-bit volume to a 16-bit volume. only valid for vol != 0.
|
||||
#define AU_VOL_8_TO_16(vol) (((vol) << 8) | 0xFF)
|
||||
// only valid for vol != 0
|
||||
// converts an 8-bit volume to a 32-bit volume. only valid for vol != 0.
|
||||
#define AU_VOL_8_TO_32(vol) (((vol) << 0x18) | 0xFFFFFF)
|
||||
|
||||
#define BGM_SAMPLE_RATE 156250
|
||||
#define BGM_DEFAULT_TEMPO 15600
|
||||
#define BGM_DEFAULT_TICKS_PER_BEAT 48
|
||||
|
||||
// fixed scale for update counter to avoid precision loss of fractional frames; 1 unit = 0.001 audio frame
|
||||
// (ie, prevent truncation when updating tick every 1.5 frames)
|
||||
#define BGM_UPDATE_SCALE (1000)
|
||||
// 1 unit = 0.01 BPM
|
||||
#define BGM_TEMPO_SCALE (100)
|
||||
|
||||
// number of audio frames per minute x BGM_UPDATE_SCALE --> units = milli-frames per minute
|
||||
#define BGM_MFRAMES_PER_MINUTE (BGM_UPDATE_SCALE * (60 * HARDWARE_OUTPUT_RATE) / AUDIO_SAMPLES)
|
||||
|
||||
// default BPM for BGMPlayer
|
||||
#define BGM_DEFAULT_BPM 156
|
||||
// default masterTempo for BGMPlayer, derived from BGM_DEFAULT_BPM
|
||||
#define BGM_DEFAULT_TEMPO (BGM_DEFAULT_BPM * BGM_TEMPO_SCALE)
|
||||
|
||||
// just over 100x the default tempo, seemingly chosen for to make each tick = 256 audio samples
|
||||
// solves (AUDIO_SAMPLES * BGM_MFRAMES_PER_MINUTE) / (BGM_DEFAULT_TICKS_PER_BEAT * x) = 256
|
||||
// --> (184 * 10434782) / (48 * x) = 256
|
||||
// --> x = (184 * 10434782) / (48 * 256)
|
||||
#define BGM_DEFAULT_UPDATE_STEP 156250
|
||||
|
||||
// converts a 'tempo' value from BGM command to units suitable for the player update counter
|
||||
#define BGM_TEMPO_TO_UPDATE_UNITS(tempo) (BGM_UPDATE_SCALE * (u32)(tempo) / BGM_TEMPO_SCALE)
|
||||
|
||||
#define SND_MIN_DURATION 250
|
||||
#define SND_MAX_DURATION 10000
|
||||
|
|
@ -135,6 +157,11 @@ typedef enum AuEffectType {
|
|||
AU_FX_OTHER_BIGROOM = 10,
|
||||
} AuEffectType;
|
||||
|
||||
typedef enum MusicPlayer {
|
||||
MUSIC_PLAYER_MAIN = 0,
|
||||
MUSIC_PLAYER_AUX = 1,
|
||||
} MusicPlayer;
|
||||
|
||||
typedef enum MusicState {
|
||||
MUSIC_STATE_IDLE = 0,
|
||||
MUSIC_STATE_STOP_CURRENT = 1,
|
||||
|
|
@ -192,7 +219,7 @@ typedef enum BGMSpecialSubops {
|
|||
BGM_SPECIAL_WRITE_CUSTOM_ENV = 3, // write custom envelope data
|
||||
BGM_SPECIAL_USE_CUSTOM_ENV = 4, // select which custom envelope to use
|
||||
BGM_SPECIAL_TRIGGER_SOUND = 5,
|
||||
BGM_SPECIAL_PROX_MIX_OVERRIDE = 6,
|
||||
BGM_SPECIAL_PROX_MIX_OVERRIDE = 6,
|
||||
} BGMSpecialSubops;
|
||||
|
||||
typedef enum FxBus {
|
||||
|
|
@ -1103,10 +1130,10 @@ typedef struct SeqNote {
|
|||
typedef struct BGMPlayer {
|
||||
/* 0x000 */ AuGlobals* globals;
|
||||
/* 0x004 */ SoundManager* soundManager;
|
||||
/* 0x008 */ s32 nextUpdateStep;
|
||||
/* 0x00C */ s32 nextUpdateInterval;
|
||||
/* 0x010 */ s32 nextUpdateCounter;
|
||||
/* 0x014 */ s32 updateCounter;
|
||||
/* 0x008 */ s32 nextUpdateStep; /// update counter amount to add per audio frame
|
||||
/* 0x00C */ s32 tickUpdateInterval; /// update counter threshold for a single tick
|
||||
/* 0x010 */ s32 nextUpdateCounter; /// current update counter value
|
||||
/* 0x014 */ s32 frameCounter; /// video frames (60 fps)
|
||||
/* 0x018 */ s32 songPlayingCounter;
|
||||
/* 0x01C */ s32 songName;
|
||||
/* 0x020 */ s32 pushSongName;
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ void au_bgm_begin_video_frame(BGMPlayer* player) {
|
|||
|
||||
compID = 0;
|
||||
unkType = -1;
|
||||
player->updateCounter++;
|
||||
player->frameCounter++;
|
||||
|
||||
if (player->cmdBufPending != 0) {
|
||||
if (player->cmdBufPending < ARRAY_COUNT(player->cmdBufData)) {
|
||||
|
|
@ -68,7 +68,7 @@ void au_bgm_begin_video_frame(BGMPlayer* player) {
|
|||
player->unk_58 = unkType & 0xFF;
|
||||
player->unk_5A = unkType & 0xFF;
|
||||
player->masterState = BGM_PLAY_STATE_INIT;
|
||||
player->nextUpdateStep = BGM_SAMPLE_RATE;
|
||||
player->nextUpdateStep = BGM_DEFAULT_UPDATE_STEP;
|
||||
if (unkType == 2) {
|
||||
bgmFile = player->globals->dataBGM[1];
|
||||
} else {
|
||||
|
|
@ -76,7 +76,7 @@ void au_bgm_begin_video_frame(BGMPlayer* player) {
|
|||
}
|
||||
player->bgmFile = bgmFile;
|
||||
bgmData = &bgmFile->info;
|
||||
au_bgm_set_tick_resolution(player, BGM_SAMPLE_RATE, BgmTicksRates[*(player->tickRatePtr) & 7]);
|
||||
au_bgm_set_tick_resolution(player, BGM_DEFAULT_UPDATE_STEP, BgmTicksRates[*(player->tickRatePtr) & 7]);
|
||||
|
||||
compOffset = bgmData->compositions[compID];
|
||||
if (compOffset == 0) {
|
||||
|
|
@ -179,7 +179,7 @@ AuResult au_bgm_process_init_song(SongStartRequest* request) {
|
|||
au_fade_init(&player->fadeInfo, duration, volume0, volume1);
|
||||
player->fadeInfo.envelopeTarget = AU_MAX_VOLUME_16;
|
||||
player->fadeInfo.envelopeTicks = 1;
|
||||
au_bgm_set_tick_resolution(player, BGM_SAMPLE_RATE, BgmTicksRates[fileInfo->timingPreset & 7]);
|
||||
au_bgm_set_tick_resolution(player, BGM_DEFAULT_UPDATE_STEP, BgmTicksRates[fileInfo->timingPreset & 7]);
|
||||
|
||||
if (variation < BGM_VARIATION_0 || variation > BGM_VARIATION_3 || fileInfo->compositions[variation] == 0) {
|
||||
variation = BGM_VARIATION_0;
|
||||
|
|
@ -524,11 +524,11 @@ void au_bgm_player_init(BGMPlayer* player, s32 priority, s32 busID, AuGlobals* g
|
|||
s16 i;
|
||||
|
||||
player->globals = globals;
|
||||
au_bgm_set_tick_resolution(player, BGM_SAMPLE_RATE, 48);
|
||||
au_bgm_set_tick_resolution(player, BGM_DEFAULT_UPDATE_STEP, BGM_DEFAULT_TICKS_PER_BEAT);
|
||||
player->busVolume = AU_MAX_BUS_VOLUME;
|
||||
player->masterTempo = BGM_DEFAULT_TEMPO;
|
||||
player->masterVolume = AU_MAX_VOLUME_8 << 24;
|
||||
player->updateCounter = 0;
|
||||
player->frameCounter = 0;
|
||||
player->songPlayingCounter = 0;
|
||||
player->songName = 0;
|
||||
player->pushSongName = 0;
|
||||
|
|
@ -663,8 +663,8 @@ s32 au_bgm_player_audio_frame_update(BGMPlayer* player) {
|
|||
s32 retVal = FALSE;
|
||||
|
||||
// update pseudorandom numbers with fast 'good enough' method
|
||||
player->randomValue1 = (player->randomValue1 & 0xFFFF) + (player->songPlayingCounter & 0xFFFF) + (player->updateCounter & 0xFFFF);
|
||||
player->randomValue2 = (player->randomValue2 & 0xFFFF) + ((player->songPlayingCounter << 4) & 0xFFFF) + ((player->updateCounter >> 4) & 0xFFFF);
|
||||
player->randomValue1 = (player->randomValue1 & 0xFFFF) + (player->songPlayingCounter & 0xFFFF) + (player->frameCounter & 0xFFFF);
|
||||
player->randomValue2 = (player->randomValue2 & 0xFFFF) + ((player->songPlayingCounter << 4) & 0xFFFF) + ((player->frameCounter >> 4) & 0xFFFF);
|
||||
do {
|
||||
switch (player->masterState) {
|
||||
case BGM_PLAY_STATE_IDLE:
|
||||
|
|
@ -757,7 +757,7 @@ void au_bgm_player_initialize(BGMPlayer* player) {
|
|||
au_bgm_reset_all_voices(player);
|
||||
player->playbackRate = 128.0f; // set to 1.0 later om...
|
||||
player->masterTempo = BGM_DEFAULT_TEMPO;
|
||||
player->masterTempoBPM = BGM_DEFAULT_TEMPO / 100;
|
||||
player->masterTempoBPM = player->masterTempo / 100;
|
||||
player->unused_21E = 0x80;
|
||||
player->masterVolume = AU_MAX_VOLUME_8 << 24;
|
||||
player->pushSongName = 0;
|
||||
|
|
@ -824,27 +824,35 @@ void au_bgm_clear_custom_note_press(BGMPlayer* player, s32 index) {
|
|||
}
|
||||
}
|
||||
|
||||
void au_bgm_set_tick_resolution(BGMPlayer* player, s32 sampleRate, s32 resolution) {
|
||||
u32 samplesPerTick;
|
||||
|
||||
samplesPerTick = 10434782 / (u32)resolution;
|
||||
void au_bgm_set_tick_resolution(BGMPlayer* player, s32 mBeatsPerMinute, u32 ticksPerBeat) {
|
||||
// compute how many audio frames before the next tick
|
||||
u32 mFramesPerTick = BGM_MFRAMES_PER_MINUTE / ticksPerBeat;
|
||||
|
||||
// Clamp samples per tick to stay in a valid range
|
||||
if (samplesPerTick > 500000) {
|
||||
samplesPerTick = 500000;
|
||||
} else if (samplesPerTick < 80000) {
|
||||
samplesPerTick = 80000;
|
||||
if (mFramesPerTick > 500000) {
|
||||
mFramesPerTick = 500000;
|
||||
} else if (mFramesPerTick < 80000) {
|
||||
mFramesPerTick = 80000;
|
||||
}
|
||||
|
||||
// Clamp to sample rate
|
||||
if (samplesPerTick < sampleRate) {
|
||||
sampleRate = samplesPerTick;
|
||||
if (mFramesPerTick < mBeatsPerMinute) {
|
||||
mBeatsPerMinute = mFramesPerTick;
|
||||
}
|
||||
|
||||
player->nextUpdateStep = sampleRate;
|
||||
player->nextUpdateInterval = samplesPerTick;
|
||||
player->nextUpdateCounter = samplesPerTick;
|
||||
player->maxTempo = samplesPerTick / 1000;
|
||||
// breakdown of units:
|
||||
//
|
||||
// tickUpdateInterval / nextUpdateStep = framesPerTick
|
||||
//
|
||||
// 1000 x frames beat min frames
|
||||
// ------------- x ------ x --------------- = ------
|
||||
// min tick 1000 x beat tick
|
||||
|
||||
player->nextUpdateStep = mBeatsPerMinute;
|
||||
player->tickUpdateInterval = mFramesPerTick;
|
||||
player->nextUpdateCounter = mFramesPerTick;
|
||||
|
||||
player->maxTempo = mFramesPerTick / BGM_UPDATE_SCALE;
|
||||
}
|
||||
|
||||
// runs whenever a new composition begins playing
|
||||
|
|
@ -1004,7 +1012,7 @@ void au_bgm_player_update_stop(BGMPlayer* player) {
|
|||
}
|
||||
au_bgm_reset_all_voices(player);
|
||||
player->masterState = BGM_PLAY_STATE_IDLE;
|
||||
player->nextUpdateStep = BGM_SAMPLE_RATE;
|
||||
player->nextUpdateStep = BGM_DEFAULT_UPDATE_STEP;
|
||||
}
|
||||
|
||||
#define POST_BGM_READ() \
|
||||
|
|
@ -1048,7 +1056,7 @@ void au_bgm_player_update_playing(BGMPlayer *player) {
|
|||
} else {
|
||||
player->masterTempo += player->masterTempoStep;
|
||||
}
|
||||
player->nextUpdateStep = player->masterTempo * 10;
|
||||
player->nextUpdateStep = BGM_TEMPO_TO_UPDATE_UNITS(player->masterTempo);
|
||||
}
|
||||
if (player->masterVolumeTicks != 0) {
|
||||
player->masterVolumeTicks--;
|
||||
|
|
@ -1504,7 +1512,7 @@ void au_BGMCmd_E0_MasterTempo(BGMPlayer* player, BGMPlayerTrack* track) {
|
|||
player->masterTempoBPM = bpm;
|
||||
tempo = au_bgm_bpm_to_tempo(player, bpm);
|
||||
player->masterTempo = tempo;
|
||||
player->nextUpdateStep = tempo * 10;
|
||||
player->nextUpdateStep = BGM_TEMPO_TO_UPDATE_UNITS(tempo);
|
||||
player->masterTempoTicks = 0;
|
||||
player->masterTempoTarget = 0;
|
||||
player->masterTempoStep = 0;
|
||||
|
|
@ -1999,7 +2007,7 @@ void au_bgm_set_playback_rate(BGMPlayer* player, f32 rate) {
|
|||
|
||||
player->playbackRate = rate;
|
||||
player->masterTempo = au_bgm_bpm_to_tempo(player, player->masterTempoBPM);
|
||||
player->nextUpdateStep = player->masterTempo * 10;
|
||||
player->nextUpdateStep = BGM_TEMPO_TO_UPDATE_UNITS(player->masterTempo);
|
||||
player->masterTempoTicks = 0;
|
||||
player->masterTempoTarget = 0;
|
||||
player->masterTempoStep = 0;
|
||||
|
|
|
|||
|
|
@ -247,7 +247,7 @@ void au_update_clients_for_audio_frame(void) {
|
|||
|
||||
bgmPlayer->nextUpdateCounter -= bgmPlayer->nextUpdateStep;
|
||||
if (bgmPlayer->nextUpdateCounter <= 0) {
|
||||
bgmPlayer->nextUpdateCounter += bgmPlayer->nextUpdateInterval;
|
||||
bgmPlayer->nextUpdateCounter += bgmPlayer->tickUpdateInterval;
|
||||
bgmPlayer->prevUpdateResult = au_bgm_player_audio_frame_update(bgmPlayer);
|
||||
}
|
||||
}
|
||||
|
|
@ -274,7 +274,7 @@ void au_update_clients_for_audio_frame(void) {
|
|||
|
||||
bgmPlayer->nextUpdateCounter -= bgmPlayer->nextUpdateStep;
|
||||
if (bgmPlayer->nextUpdateCounter <= 0) {
|
||||
bgmPlayer->nextUpdateCounter += bgmPlayer->nextUpdateInterval;
|
||||
bgmPlayer->nextUpdateCounter += bgmPlayer->tickUpdateInterval;
|
||||
bgmPlayer->prevUpdateResult = au_bgm_player_audio_frame_update(bgmPlayer);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ void au_bgm_update_bus_volumes(BGMPlayer* arg0);
|
|||
s32 au_bgm_player_audio_frame_update(BGMPlayer* player);
|
||||
void au_bgm_player_initialize(BGMPlayer* player);
|
||||
void au_bgm_clear_custom_note_press(BGMPlayer* player, s32 arg1);
|
||||
void au_bgm_set_tick_resolution(BGMPlayer* player, s32 sampleRate, s32 divisor);
|
||||
void au_bgm_set_tick_resolution(BGMPlayer* player, s32 sampleRate, u32 resolution);
|
||||
void au_bgm_player_read_composition(BGMPlayer* player);
|
||||
void au_bgm_end_composition_loop(BGMPlayer* player, u32 cmd);
|
||||
void au_bgm_load_phrase(BGMPlayer* player, u32 cmd);
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ MusicProximityTrigger N(MusicMixTrigger1) = {
|
|||
.pos = { 15.0f, -400.0f },
|
||||
.innerDist = 90.0f,
|
||||
.outerDist = 120.0f,
|
||||
.unk = 7,
|
||||
.mix = 7,
|
||||
.manualActivationFlag = MF_MusicMixTrigger1,
|
||||
};
|
||||
|
||||
|
|
@ -14,7 +14,7 @@ MusicProximityTrigger N(MusicMixTrigger2) = {
|
|||
.pos = { 445.0f, -307.0f },
|
||||
.innerDist = 90.0f,
|
||||
.outerDist = 110.0f,
|
||||
.unk = 3,
|
||||
.mix = 3,
|
||||
.manualActivationFlag = MF_MusicMixTrigger2,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ MusicProximityTrigger N(MusicMixTrigger1) = {
|
|||
.pos = { -190.0f, -210.0f },
|
||||
.innerDist = 100.0f,
|
||||
.outerDist = 120.0f,
|
||||
.unk = 2,
|
||||
.mix = 2,
|
||||
.manualActivationFlag = MF_MusicMixTrigger1,
|
||||
};
|
||||
|
||||
|
|
@ -14,7 +14,7 @@ MusicProximityTrigger N(MusicMixTrigger2) = {
|
|||
.pos = { -150.0f, 330.0f },
|
||||
.innerDist = 110.0f,
|
||||
.outerDist = 130.0f,
|
||||
.unk = 8,
|
||||
.mix = 8,
|
||||
.manualActivationFlag = MF_MusicMixTrigger2,
|
||||
};
|
||||
|
||||
|
|
@ -22,7 +22,7 @@ MusicProximityTrigger N(MusicMixTrigger3) = {
|
|||
.pos = { 266.0f, 370.0f },
|
||||
.innerDist = 200.0f,
|
||||
.outerDist = 220.0f,
|
||||
.unk = 5,
|
||||
.mix = 5,
|
||||
.manualActivationFlag = MF_MusicMixTrigger3,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ MusicProximityTrigger N(MusicMixTrigger1) = {
|
|||
.pos = { -150.0f, -205.0f },
|
||||
.innerDist = 120.0f,
|
||||
.outerDist = 150.0f,
|
||||
.unk = 1,
|
||||
.mix = 1,
|
||||
.manualActivationFlag = MF_MusicMixTrigger1,
|
||||
};
|
||||
|
||||
|
|
@ -14,7 +14,7 @@ MusicProximityTrigger N(MusicMixTrigger2) = {
|
|||
.pos = { -400.0f, 250.0f },
|
||||
.innerDist = 110.0f,
|
||||
.outerDist = 130.0f,
|
||||
.unk = 4,
|
||||
.mix = 4,
|
||||
.manualActivationFlag = MF_MusicMixTrigger2,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ MusicProximityTrigger N(MusicMixTrigger) = {
|
|||
.pos = { -480.0f, 220.0f },
|
||||
.innerDist = 100.0f,
|
||||
.outerDist = 120.0f,
|
||||
.unk = 9,
|
||||
.mix = 9,
|
||||
.manualActivationFlag = MF_MusicMixTrigger,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ API_CALLABLE(N(MonitorMusicProximityTrigger)) {
|
|||
}
|
||||
|
||||
if (cond) {
|
||||
bgm_adjust_proximity(0, trigger->unk, script->functionTemp[1]);
|
||||
bgm_adjust_proximity(0, trigger->mix, script->functionTemp[1]);
|
||||
}
|
||||
|
||||
return ApiStatus_BLOCK;
|
||||
|
|
|
|||
Loading…
Reference in New Issue