diff --git a/libultraship b/libultraship index b2dd85ca39..5c8b975de4 160000 --- a/libultraship +++ b/libultraship @@ -1 +1 @@ -Subproject commit b2dd85ca393225afb0c949035e0eabf87751ff89 +Subproject commit 5c8b975de422c71fd6cda44ada5543c9067f57a2 diff --git a/mm/2s2h/BenPort.cpp b/mm/2s2h/BenPort.cpp index 6f01460945..5c1ed192ec 100644 --- a/mm/2s2h/BenPort.cpp +++ b/mm/2s2h/BenPort.cpp @@ -37,7 +37,7 @@ #endif #include "Extractor/Extract.h" // OTRTODO -//#include +// #include #include "2s2h/Enhancements/FrameInterpolation/FrameInterpolation.h" #ifdef ENABLE_CROWD_CONTROL @@ -211,7 +211,10 @@ OTRGlobals::OTRGlobals() { overlay->LoadFont("Fipps", 32.0f, "fonts/Fipps-Regular.otf"); overlay->SetCurrentFont(CVarGetString(CVAR_GAME_OVERLAY_FONT, "Press Start 2P")); - context->InitAudio({ .SampleRate = 32000, .SampleLength = 1024, .DesiredBuffered = 1680 }); + AudioChannelsSetting channelSetting = + static_cast(CVarGetInteger("gAudioChannelsSetting", audioStereo)); + context->InitAudio( + { .SampleRate = 32000, .SampleLength = 1024, .DesiredBuffered = 1680, .ChannelSetting = channelSetting }); SPDLOG_INFO("Starting 2 Ship 2 Harkinian version {} (Branch: {} | Commit: {})", (char*)gBuildVersion, (char*)gGitBranch, (char*)gGitCommitHash); diff --git a/mm/src/audio/code_8019AF00.c b/mm/src/audio/code_8019AF00.c index f28852bc24..1fd295535a 100644 --- a/mm/src/audio/code_8019AF00.c +++ b/mm/src/audio/code_8019AF00.c @@ -4,6 +4,7 @@ #include "GameInteractor/GameInteractor.h" #include "2s2h/Enhancements/Audio/AudioEditor.h" #include +#include typedef struct { /* 0x0 */ s8 x; @@ -6080,32 +6081,44 @@ void Audio_PlaySfx_SurroundSoundTest(void) { void Audio_SetFileSelectSettings(s8 audioSetting) { s8 soundMode; + AudioChannelsSetting channelsSetting = audioStereo; switch (audioSetting) { case SAVE_AUDIO_STEREO: soundMode = SOUNDMODE_STEREO; sSoundMode = SOUNDMODE_STEREO; + channelsSetting = audioStereo; break; case SAVE_AUDIO_MONO: soundMode = SOUNDMODE_MONO; sSoundMode = SOUNDMODE_MONO; + channelsSetting = audioStereo; break; case SAVE_AUDIO_HEADSET: soundMode = SOUNDMODE_HEADSET; sSoundMode = SOUNDMODE_HEADSET; + channelsSetting = audioStereo; break; case SAVE_AUDIO_SURROUND: soundMode = SOUNDMODE_SURROUND; sSoundMode = SOUNDMODE_SURROUND_EXTERNAL; + channelsSetting = audioMatrix51; break; default: break; } + // Dynamically switch audio backend between stereo and 5.1 surround + SetAudioChannels(channelsSetting); + + // Save audio channel setting so it persists across game launches + CVarSetInteger("gAudioChannelsSetting", channelsSetting); + CVarSave(); + SEQCMD_SET_SOUND_MODE(soundMode); } diff --git a/mm/src/audio/lib/synthesis.c b/mm/src/audio/lib/synthesis.c index c78a043b3d..fca15190a7 100644 --- a/mm/src/audio/lib/synthesis.c +++ b/mm/src/audio/lib/synthesis.c @@ -1484,13 +1484,32 @@ Acmd* AudioSynth_ApplySurroundEffect(Acmd* cmd, NoteSampleState* sampleState, No } else { aLoadBuffer(cmd++, synthState->synthesisBuffers->surroundEffectState, dmem, sizeof(synthState->synthesisBuffers->surroundEffectState)); - aMix(cmd++, (numSamplesPerUpdate * (s32)SAMPLE_SIZE) >> 4, dryGain, dmem, DMEM_LEFT_CH); - aMix(cmd++, (numSamplesPerUpdate * (s32)SAMPLE_SIZE) >> 4, (dryGain ^ 0xFFFF), dmem, DMEM_RIGHT_CH); + + // === Matrix surround encoding: steer surround to RL or RR based on pan === + // Calculate pan position: 0.0 = full left, 0.5 = center, 1.0 = full right + f32 sumVol = sampleState->targetVolLeft + sampleState->targetVolRight; + f32 panPosition = 0.5f; // default: center (mono surround) + if (sumVol > 0.0f) { + panPosition = (f32)sampleState->targetVolRight / sumVol; + } + + // The L/R balance determines RL vs RR steering: + // - L dominant (leftGain > rightGain): surround goes more to Rear Left + // - R dominant (rightGain > leftGain): surround goes more to Rear Right + // - Equal: mono surround to both + s16 leftGain = (s16)(dryGain * (1.0f - panPosition)); + s16 rightGain = (s16)(dryGain * panPosition); + + aMix(cmd++, (numSamplesPerUpdate * (s32)SAMPLE_SIZE) >> 4, leftGain, dmem, DMEM_LEFT_CH); + aMix(cmd++, (numSamplesPerUpdate * (s32)SAMPLE_SIZE) >> 4, (rightGain ^ 0xFFFF), dmem, DMEM_RIGHT_CH); wetGain = (dryGain * synthState->curReverbVol) >> 7; + s16 wetLeftGain = (s16)(wetGain * (1.0f - panPosition)); + s16 wetRightGain = (s16)(wetGain * panPosition); - aMix(cmd++, (numSamplesPerUpdate * (s32)SAMPLE_SIZE) >> 4, wetGain, dmem, DMEM_WET_LEFT_CH); - aMix(cmd++, (numSamplesPerUpdate * (s32)SAMPLE_SIZE) >> 4, (wetGain ^ 0xFFFF), dmem, DMEM_WET_RIGHT_CH); + aMix(cmd++, (numSamplesPerUpdate * (s32)SAMPLE_SIZE) >> 4, wetLeftGain, dmem, DMEM_WET_LEFT_CH); + aMix(cmd++, (numSamplesPerUpdate * (s32)SAMPLE_SIZE) >> 4, (wetRightGain ^ 0xFFFF), dmem, DMEM_WET_RIGHT_CH); + // === End matrix surround encoding === } aSaveBuffer(cmd++, DMEM_SURROUND_TEMP + (numSamplesPerUpdate * SAMPLE_SIZE), diff --git a/mm/src/code/z_common_data.c b/mm/src/code/z_common_data.c index 7ac74db088..b0451fb900 100644 --- a/mm/src/code/z_common_data.c +++ b/mm/src/code/z_common_data.c @@ -6,6 +6,7 @@ #include "z64environment.h" #include "z64transition.h" #include +#include SaveContext gSaveContext ALIGNED(16); @@ -26,6 +27,6 @@ void SaveContext_Init(void) { gSaveContext.prevHudVisibility = HUD_VISIBILITY_ALL; gSaveContext.options.language = LANGUAGE_ENG; - gSaveContext.options.audioSetting = SAVE_AUDIO_STEREO; + gSaveContext.options.audioSetting = (GetAudioChannels() == audioMatrix51) ? SAVE_AUDIO_SURROUND : SAVE_AUDIO_STEREO; gSaveContext.options.zTargetSetting = 0; } diff --git a/mm/src/code/z_sram_NES.c b/mm/src/code/z_sram_NES.c index 03c3c301ee..d7c3a2c202 100644 --- a/mm/src/code/z_sram_NES.c +++ b/mm/src/code/z_sram_NES.c @@ -8,6 +8,7 @@ #include "2s2h/Enhancements/Saving/SavingEnhancements.h" #include "2s2h/GameInteractor/GameInteractor.h" #include +#include void Sram_SyncWriteToFlash(SramContext* sramCtx, s32 curPage, s32 numPages); void func_80147414(SramContext* sramCtx, s32 fileNum, s32 arg2); @@ -1774,10 +1775,14 @@ void func_801457CC(GameState* gameState, SramContext* sramCtx) { gFlashSaveNumPages[sp64 + FLASH_SAVE_BACKUP_OFFSET]); } } else { + // Get default audio setting from config + s8 defaultAudioSetting = + (GetAudioChannels() == audioMatrix51) ? SAVE_AUDIO_SURROUND : SAVE_AUDIO_STEREO; + if (phi_s2) { gSaveContext.options.optionId = 0xA51D; gSaveContext.options.language = LANGUAGE_ENG; - gSaveContext.options.audioSetting = SAVE_AUDIO_STEREO; + gSaveContext.options.audioSetting = defaultAudioSetting; gSaveContext.options.languageSetting = 0; gSaveContext.options.zTargetSetting = 0; } else { @@ -1785,7 +1790,7 @@ void func_801457CC(GameState* gameState, SramContext* sramCtx) { if (gSaveContext.options.optionId != 0xA51D) { gSaveContext.options.optionId = 0xA51D; gSaveContext.options.language = LANGUAGE_ENG; - gSaveContext.options.audioSetting = SAVE_AUDIO_STEREO; + gSaveContext.options.audioSetting = defaultAudioSetting; gSaveContext.options.languageSetting = 0; gSaveContext.options.zTargetSetting = 0; }