You've already forked Microtransactions64
mirror of
https://github.com/Print-and-Panic/Microtransactions64.git
synced 2026-01-21 10:17:19 -08:00
Add SET_ECHO level script command + minor BETTER_REVERB refactoring (#591)
* Add SET_ECHO level script command + minor BETTER_REVERB refactoring * Add Puppyprint debug page for trying out different BETTER_REVERB presets and configurations Also fix a missing Puppyprint enum that was causing issues * Modify Puppyprint BETTER_REVERB page + other minor improvements * Swap order of RSP commands to allow reverb downsampling to sound more similar to that of without downsampling
This commit is contained in:
113
src/audio/data.c
113
src/audio/data.c
@@ -43,7 +43,7 @@ struct AudioSessionSettingsEU gAudioSessionPresets[] = {
|
||||
|
||||
#ifdef BETTER_REVERB
|
||||
// Each entry represents an array of variable audio buffer sizes / delays for each respective filter.
|
||||
u32 delaysArr[][NUM_ALLPASS] = {
|
||||
u32 sReverbDelaysArr[][NUM_ALLPASS] = {
|
||||
{ /* 0 */
|
||||
4, 4, 4,
|
||||
4, 4, 4,
|
||||
@@ -65,7 +65,7 @@ u32 delaysArr[][NUM_ALLPASS] = {
|
||||
};
|
||||
|
||||
// Each entry represents an array of multipliers applied to the final output of each group of 3 filters.
|
||||
u8 reverbMultsArr[][NUM_ALLPASS / 3] = {
|
||||
u8 sReverbMultsArr[][NUM_ALLPASS / 3] = {
|
||||
/* 0 */ {0x00, 0x00, 0x00, 0x00},
|
||||
/* 1 */ {0xD7, 0x6F, 0x36, 0x22},
|
||||
/* 2 */ {0xCF, 0x73, 0x38, 0x1F},
|
||||
@@ -74,11 +74,11 @@ u8 reverbMultsArr[][NUM_ALLPASS / 3] = {
|
||||
/**
|
||||
* Format:
|
||||
* - useLightweightSettings (Reduce some runtime configurability options in favor of a slight speed boost during processing; Light configurability settings are found in synthesis.h)
|
||||
* - downsampleRate (Higher values exponentially reduce the number of input samples to process, improving perfomance at cost of quality)
|
||||
* - downsampleRate (Higher values exponentially reduce the number of input samples to process, improving perfomance at cost of quality; number <= 0 signifies use of vanilla reverb)
|
||||
* - isMono (Only process reverb on the left channel and share it with the right channel, improving performance at cost of quality)
|
||||
* - filterCount (Number of filters to process data with; in general, more filters means higher quality at the cost of performance demand; always 3 with light settings)
|
||||
*
|
||||
* - windowSize (Size of circular reverb buffer; higher values work better for a more open soundscape, lower is better for a more compact sound)
|
||||
* - windowSize (Size of circular reverb buffer; higher values work better for a more open soundscape, lower is better for a more compact sound; value of 0 disables all reverb)
|
||||
* - gain (Amount of audio retransmitted into the circular reverb buffer, emulating decay; higher values represent a lengthier decay period)
|
||||
* - gainIndex (Advanced parameter; used to tune the outputs of every first two of three filters; overridden when using light settings)
|
||||
* - reverbIndex (Advanced parameter; used to tune the incoming output of every third filter; overridden when using light settings)
|
||||
@@ -93,36 +93,36 @@ u8 reverbMultsArr[][NUM_ALLPASS / 3] = {
|
||||
*/
|
||||
struct BetterReverbSettings gBetterReverbSettings[] = {
|
||||
{ /* Preset 0 - Vanilla Reverb [Default Preset] */
|
||||
.useLightweightSettings = FALSE, // Ignored with vanilla reverb
|
||||
.downsampleRate = -1, // Signifies use of vanilla reverb
|
||||
.isMono = FALSE, // Ignored with vanilla reverb
|
||||
.filterCount = NUM_ALLPASS, // Ignored with vanilla reverb
|
||||
.useLightweightSettings = FALSE, // Ignored with vanilla reverb
|
||||
.downsampleRate = -1, // Signifies use of vanilla reverb
|
||||
.isMono = FALSE, // Ignored with vanilla reverb
|
||||
.filterCount = NUM_ALLPASS, // Ignored with vanilla reverb
|
||||
|
||||
.windowSize = -1, // Use vanilla preset window size
|
||||
.gain = -1, // Use vanilla preset gain value
|
||||
.gainIndex = 0x00, // Ignored with vanilla reverb
|
||||
.reverbIndex = 0x00, // Ignored with vanilla reverb
|
||||
.windowSize = -1, // Use vanilla preset window size
|
||||
.gain = -1, // Use vanilla preset gain value
|
||||
.gainIndex = 0x00, // Ignored with vanilla reverb
|
||||
.reverbIndex = 0x00, // Ignored with vanilla reverb
|
||||
|
||||
.delaysL = delaysArr[0], // Ignored with vanilla reverb
|
||||
.delaysR = delaysArr[0], // Ignored with vanilla reverb
|
||||
.reverbMultsL = reverbMultsArr[0], // Ignored with vanilla reverb
|
||||
.reverbMultsR = reverbMultsArr[0], // Ignored with vanilla reverb
|
||||
.delaysL = sReverbDelaysArr[0], // Ignored with vanilla reverb
|
||||
.delaysR = sReverbDelaysArr[0], // Ignored with vanilla reverb
|
||||
.reverbMultsL = sReverbMultsArr[0], // Ignored with vanilla reverb
|
||||
.reverbMultsR = sReverbMultsArr[0], // Ignored with vanilla reverb
|
||||
},
|
||||
{ /* Preset 1 - Sample Console Configuration */
|
||||
.useLightweightSettings = TRUE,
|
||||
.downsampleRate = 2,
|
||||
.isMono = FALSE,
|
||||
.filterCount = (NUM_ALLPASS - 9), // Ignored with lightweight settings
|
||||
.filterCount = (NUM_ALLPASS - 9), // Ignored with lightweight settings
|
||||
|
||||
.windowSize = 0x0E00,
|
||||
.gain = 0x43FF,
|
||||
.gainIndex = 0xA0, // Ignored with lightweight settings
|
||||
.reverbIndex = 0x30, // Ignored with lightweight settings
|
||||
.gain = 0x2FFF,
|
||||
.gainIndex = 0xA0, // Ignored with lightweight settings
|
||||
.reverbIndex = 0x30, // Ignored with lightweight settings
|
||||
|
||||
.delaysL = delaysArr[1],
|
||||
.delaysR = delaysArr[2],
|
||||
.reverbMultsL = reverbMultsArr[1], // Ignored with lightweight settings
|
||||
.reverbMultsR = reverbMultsArr[2], // Ignored with lightweight settings
|
||||
.delaysL = sReverbDelaysArr[1],
|
||||
.delaysR = sReverbDelaysArr[2],
|
||||
.reverbMultsL = sReverbMultsArr[1], // Ignored with lightweight settings
|
||||
.reverbMultsR = sReverbMultsArr[2], // Ignored with lightweight settings
|
||||
},
|
||||
{ /* Preset 2 - Sample Emulator Configuration (RCVI Hack or Emulator CPU Overclocking Required!) */
|
||||
.useLightweightSettings = FALSE,
|
||||
@@ -131,17 +131,60 @@ struct BetterReverbSettings gBetterReverbSettings[] = {
|
||||
.filterCount = NUM_ALLPASS,
|
||||
|
||||
.windowSize = 0x0E00,
|
||||
.gain = 0x28FF,
|
||||
.gain = 0x2AFF,
|
||||
.gainIndex = 0xA0,
|
||||
.reverbIndex = 0x60,
|
||||
.reverbIndex = 0x40,
|
||||
|
||||
.delaysL = delaysArr[1],
|
||||
.delaysR = delaysArr[2],
|
||||
.reverbMultsL = reverbMultsArr[1],
|
||||
.reverbMultsR = reverbMultsArr[2],
|
||||
.delaysL = sReverbDelaysArr[1],
|
||||
.delaysR = sReverbDelaysArr[2],
|
||||
.reverbMultsL = sReverbMultsArr[1],
|
||||
.reverbMultsR = sReverbMultsArr[2],
|
||||
},
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef PUPPYPRINT_DEBUG
|
||||
// Used for A/B comparisons and preset configuration debugging alongside Puppyprint Debug
|
||||
struct BetterReverbSettings gDebugBetterReverbSettings[2] = {
|
||||
{ /* Preset A */
|
||||
.useLightweightSettings = FALSE,
|
||||
.downsampleRate = 2,
|
||||
.isMono = FALSE,
|
||||
.filterCount = (NUM_ALLPASS - 9),
|
||||
|
||||
.windowSize = 0x0E00,
|
||||
.gain = 0x2FFF,
|
||||
.gainIndex = 0xA0,
|
||||
.reverbIndex = 0x30,
|
||||
|
||||
.delaysL = sReverbDelaysArr[1],
|
||||
.delaysR = sReverbDelaysArr[2],
|
||||
.reverbMultsL = sReverbMultsArr[1],
|
||||
.reverbMultsR = sReverbMultsArr[2],
|
||||
},
|
||||
{ /* Preset B */
|
||||
.useLightweightSettings = FALSE,
|
||||
.downsampleRate = 2,
|
||||
.isMono = FALSE,
|
||||
.filterCount = (NUM_ALLPASS - 9),
|
||||
|
||||
.windowSize = 0x0E00,
|
||||
.gain = 0x2FFF,
|
||||
.gainIndex = 0xA0,
|
||||
.reverbIndex = 0x30,
|
||||
|
||||
.delaysL = sReverbDelaysArr[1],
|
||||
.delaysR = sReverbDelaysArr[2],
|
||||
.reverbMultsL = sReverbMultsArr[1],
|
||||
.reverbMultsR = sReverbMultsArr[2],
|
||||
},
|
||||
};
|
||||
#endif // PUPPYPRINT_DEBUG
|
||||
|
||||
STATIC_ASSERT(ARRAY_COUNT(gBetterReverbSettings) > 0, "gBetterReverbSettings must contain presets!");
|
||||
STATIC_ASSERT(ARRAY_COUNT(sReverbDelaysArr) > 0, "sReverbDelaysArr must not be empty!");
|
||||
STATIC_ASSERT(ARRAY_COUNT(sReverbMultsArr) > 0, "sReverbMultsArr must not be empty!");
|
||||
|
||||
#endif // BETTER_REVERB
|
||||
|
||||
// Format:
|
||||
// - frequency
|
||||
@@ -913,6 +956,14 @@ s16 gAiBufferLengths[NUMAIBUFFERS];
|
||||
|
||||
u32 gAudioRandom;
|
||||
|
||||
#ifdef BETTER_REVERB
|
||||
u8 gBetterReverbPresetCount = ARRAY_COUNT(gBetterReverbSettings);
|
||||
#ifdef PUPPYPRINT_DEBUG
|
||||
u8 gReverbDelaysArrCount = ARRAY_COUNT(sReverbDelaysArr);
|
||||
u8 gReverbMultsArrCount = ARRAY_COUNT(sReverbMultsArr);
|
||||
#endif // PUPPYPRINT_DEBUG
|
||||
#endif // BETTER_REVERB
|
||||
|
||||
#if defined(VERSION_EU) || defined(VERSION_SH)
|
||||
s32 gAudioErrorFlags;
|
||||
#endif
|
||||
|
||||
@@ -54,8 +54,16 @@ extern struct AudioSessionSettings gAudioSessionSettings;
|
||||
extern struct ReverbSettingsUS gReverbSettings[18];
|
||||
#endif
|
||||
#ifdef BETTER_REVERB
|
||||
extern u8 gBetterReverbPresetCount;
|
||||
extern struct BetterReverbSettings gBetterReverbSettings[];
|
||||
#endif
|
||||
#ifdef PUPPYPRINT_DEBUG
|
||||
extern struct BetterReverbSettings gDebugBetterReverbSettings[2];
|
||||
extern u32 sReverbDelaysArr[][NUM_ALLPASS];
|
||||
extern u8 sReverbMultsArr[][NUM_ALLPASS / 3];
|
||||
extern u8 gReverbDelaysArrCount;
|
||||
extern u8 gReverbMultsArrCount;
|
||||
#endif // PUPPYPRINT_DEBUG
|
||||
#endif // BETTER_REVERB
|
||||
|
||||
#if defined(VERSION_EU) || defined(VERSION_SH)
|
||||
extern f32 gPitchBendFrequencyScale[256];
|
||||
|
||||
@@ -232,7 +232,7 @@ struct MusicDynamic sMusicDynamics[8] = {
|
||||
#define STUB_LEVEL(_0, _1, _2, _3, echo1, echo2, echo3, _7, _8) { echo1, echo2, echo3 },
|
||||
#define DEFINE_LEVEL(_0, _1, _2, _3, _4, _5, echo1, echo2, echo3, _9, _10) { echo1, echo2, echo3 },
|
||||
|
||||
u8 sLevelAreaReverbs[LEVEL_COUNT][3] = {
|
||||
s8 sLevelAreaReverbs[LEVEL_COUNT][3] = {
|
||||
{ 0x00, 0x00, 0x00 }, // LEVEL_NONE
|
||||
#include "levels/level_defines.h"
|
||||
};
|
||||
@@ -1138,7 +1138,8 @@ static f32 get_sound_freq_scale(u8 bank, u8 item) {
|
||||
static u32 get_sound_reverb(UNUSED u8 bank, UNUSED u8 soundIndex, u8 channelIndex) {
|
||||
u8 area;
|
||||
u8 level;
|
||||
u8 reverb;
|
||||
s8 areaEcho;
|
||||
s16 reverb;
|
||||
|
||||
// Disable level reverb if NO_ECHO is set
|
||||
if (sSoundBanks[bank][soundIndex].soundBits & SOUND_NO_ECHO) {
|
||||
@@ -1152,18 +1153,27 @@ static u32 get_sound_reverb(UNUSED u8 bank, UNUSED u8 soundIndex, u8 channelInde
|
||||
}
|
||||
}
|
||||
|
||||
// reverb = reverb adjustment + level reverb + a volume-dependent value
|
||||
areaEcho = sLevelAreaReverbs[level][area];
|
||||
|
||||
if (gAreaData[gCurrAreaIndex].useEchoOverride && !(sSoundBanks[bank][soundIndex].soundBits & SOUND_NO_ECHO)) {
|
||||
areaEcho = gAreaData[gCurrAreaIndex].echoOverride;
|
||||
}
|
||||
|
||||
// reverb = reverb adjustment + level reverb (or level script override value) + a volume-dependent value
|
||||
// The volume-dependent value is 0 when volume is at maximum, and raises to
|
||||
// LOW_VOLUME_REVERB when the volume is 0
|
||||
reverb = (u8)(u8) gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->soundScriptIO[5]
|
||||
+ sLevelAreaReverbs[level][area]
|
||||
+ ((1.0f - gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->volume)
|
||||
* LOW_VOLUME_REVERB);
|
||||
reverb = (s16) ((u8) gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->soundScriptIO[5]) + areaEcho;
|
||||
|
||||
if (reverb > 0x7f) {
|
||||
// NOTE: In some cases, it may be better to apply this after ensuring reverb is non-negative so the result doesn't end up sounding way too dry.
|
||||
// This has been left as-is however because in most cases where negative reverb is even used, this is probably desirable anyway.
|
||||
reverb += (s16) ((1.0f - gSequencePlayers[SEQ_PLAYER_SFX].channels[channelIndex]->volume) * LOW_VOLUME_REVERB);
|
||||
|
||||
if (reverb < 0 || areaEcho <= -0x80) {
|
||||
reverb = 0;
|
||||
} else if (reverb > 0x7f) {
|
||||
reverb = 0x7f;
|
||||
}
|
||||
return reverb;
|
||||
return (u8) reverb;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <PR/ultratypes.h>
|
||||
|
||||
#include "types.h"
|
||||
#include "level_table.h"
|
||||
|
||||
// Sequence arguments, passed to seq_player_play_sequence. seqId may be bit-OR'ed with
|
||||
// SEQ_VARIATION; this will load the same sequence, but set a variation
|
||||
@@ -34,6 +35,8 @@ extern f32 gGlobalSoundSource[3];
|
||||
// defined in data.c, used by the game
|
||||
extern u32 gAudioRandom;
|
||||
|
||||
extern s8 sLevelAreaReverbs[LEVEL_COUNT][3];
|
||||
|
||||
struct SPTask *create_next_audio_frame_task(void);
|
||||
void play_sound(s32 soundBits, f32 *pos);
|
||||
void audio_signal_game_loop_tick(void);
|
||||
|
||||
@@ -1048,8 +1048,20 @@ void init_reverb_us(s32 presetId) {
|
||||
s32 reverbWindowSize = gReverbSettings[presetId].windowSize;
|
||||
gReverbDownsampleRate = gReverbSettings[presetId].downsampleRate;
|
||||
#ifdef BETTER_REVERB
|
||||
// This will likely crash if given an invalid preset value. Adding a safety check here isn't worth the usability interference.
|
||||
struct BetterReverbSettings *betterReverbPreset = &gBetterReverbSettings[gBetterReverbPreset];
|
||||
struct BetterReverbSettings *betterReverbPreset = &gBetterReverbSettings[gBetterReverbPresetValue];
|
||||
|
||||
#ifdef PUPPYPRINT_DEBUG
|
||||
if ((s8) gBetterReverbPresetValue < 0 && (s8) gBetterReverbPresetValue >= -ARRAY_COUNT(gDebugBetterReverbSettings)) {
|
||||
betterReverbPreset = &gDebugBetterReverbSettings[ARRAY_COUNT(gDebugBetterReverbSettings) + (s8) gBetterReverbPresetValue];
|
||||
} else if (gBetterReverbPresetValue >= gBetterReverbPresetCount) {
|
||||
#else
|
||||
if (gBetterReverbPresetValue >= gBetterReverbPresetCount) {
|
||||
#endif
|
||||
aggress(gBetterReverbPresetCount > 0, "No BETTER_REVERB presets exist!");
|
||||
|
||||
assert(gBetterReverbPresetValue < gBetterReverbPresetCount, "BETTER_REVERB preset value exceeds total number of available presets!");
|
||||
betterReverbPreset = &gBetterReverbSettings[0];
|
||||
}
|
||||
|
||||
betterReverbLightweight = betterReverbPreset->useLightweightSettings;
|
||||
betterReverbDownsampleRate = betterReverbPreset->downsampleRate;
|
||||
@@ -1071,9 +1083,10 @@ void init_reverb_us(s32 presetId) {
|
||||
|
||||
if (betterReverbWindowsSize >= 0) {
|
||||
reverbWindowSize = betterReverbWindowsSize;
|
||||
if (reverbWindowSize < (DEFAULT_LEN_2CH * 2) && betterReverbWindowsSize != 0) // Minimum window size to not overflow
|
||||
reverbWindowSize = (DEFAULT_LEN_2CH * 2);
|
||||
reverbWindowSize /= gReverbDownsampleRate;
|
||||
if (reverbWindowSize < DEFAULT_LEN_2CH && betterReverbWindowsSize != 0) // Minimum window size to not overflow
|
||||
reverbWindowSize = DEFAULT_LEN_2CH;
|
||||
reverbWindowSize = ALIGN16(reverbWindowSize);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1138,7 +1151,7 @@ void init_reverb_us(s32 presetId) {
|
||||
if (!gSynthesisReverb.useReverb)
|
||||
toggleBetterReverb = FALSE;
|
||||
|
||||
if (betterReverbPreset->gain > 0)
|
||||
if (betterReverbPreset->gain >= 0)
|
||||
gSynthesisReverb.reverbGain = (u16) betterReverbPreset->gain;
|
||||
|
||||
if (!sAudioIsInitialized)
|
||||
|
||||
@@ -140,9 +140,11 @@ void *alloc_bank_or_seq(struct SoundMultiPool *arg0, s32 arg1, s32 size, s32 arg
|
||||
void *get_bank_or_seq(struct SoundMultiPool *arg0, s32 arg1, s32 id);
|
||||
#endif
|
||||
#if defined(VERSION_EU) || defined(VERSION_SH)
|
||||
void init_reverb_eu(void);
|
||||
s32 audio_shut_down_and_reset_step(void);
|
||||
void audio_reset_session(void);
|
||||
#else
|
||||
void init_reverb_us(s32 presetId);
|
||||
void audio_reset_session(s32 reverbPresetId);
|
||||
#endif
|
||||
void discard_bank(s32 bankId);
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
|
||||
#ifdef BETTER_REVERB
|
||||
// Do not touch these values manually, unless you want potential for problems.
|
||||
u8 gBetterReverbPreset = 0;
|
||||
u8 gBetterReverbPresetValue = 0;
|
||||
u8 toggleBetterReverb = FALSE;
|
||||
u8 betterReverbLightweight = FALSE;
|
||||
u8 monoReverb;
|
||||
@@ -768,9 +768,9 @@ u64 *synthesis_do_one_audio_update(s16 *aiBuf, s32 bufLen, u64 *cmd, s32 updateI
|
||||
aResample(cmd++, gSynthesisReverb.resampleFlags, (u16) gSynthesisReverb.resampleRate, VIRTUAL_TO_PHYSICAL2(gSynthesisReverb.resampleStateLeft));
|
||||
aSetBuffer(cmd++, 0, t4 + DMEM_ADDR_WET_RIGHT_CH, DMEM_ADDR_RIGHT_CH, bufLen << 1);
|
||||
aResample(cmd++, gSynthesisReverb.resampleFlags, (u16) gSynthesisReverb.resampleRate, VIRTUAL_TO_PHYSICAL2(gSynthesisReverb.resampleStateRight));
|
||||
aSetBuffer(cmd++, 0, 0, 0, DEFAULT_LEN_2CH);
|
||||
aMix(cmd++, 0, /*gain*/ 0x8000 + gSynthesisReverb.reverbGain, /*in*/ DMEM_ADDR_LEFT_CH, /*out*/ DMEM_ADDR_LEFT_CH);
|
||||
aDMEMMove(cmd++, DMEM_ADDR_LEFT_CH, DMEM_ADDR_WET_LEFT_CH, DEFAULT_LEN_2CH);
|
||||
aSetBuffer(cmd++, 0, 0, 0, DEFAULT_LEN_2CH);
|
||||
aMix(cmd++, 0, /*gain*/ 0x8000 + gSynthesisReverb.reverbGain, /*in*/ DMEM_ADDR_WET_LEFT_CH, /*out*/ DMEM_ADDR_WET_LEFT_CH);
|
||||
}
|
||||
|
||||
AUDIO_PROFILER_SWITCH(PROFILER_TIME_SUB_AUDIO_SYNTHESIS_ENVELOPE_REVERB, PROFILER_TIME_SUB_AUDIO_SYNTHESIS_PROCESSING);
|
||||
|
||||
@@ -54,7 +54,7 @@ enum ChannelIndexes {
|
||||
/* ------------ BETTER REVERB EXTERNED VARIABLES ------------ */
|
||||
|
||||
extern u8 toggleBetterReverb;
|
||||
extern u8 gBetterReverbPreset;
|
||||
extern u8 gBetterReverbPresetValue;
|
||||
extern u8 betterReverbLightweight;
|
||||
extern s8 betterReverbDownsampleRate;
|
||||
extern u8 monoReverb;
|
||||
|
||||
Reference in New Issue
Block a user