From ac123c4cab1411b4dc1d54d736dc45b44095ad55 Mon Sep 17 00:00:00 2001 From: Tortuga Veloz Date: Tue, 10 Feb 2026 09:46:09 +0100 Subject: [PATCH] update audio options to select among 4 opts. --- assets/config_menu/sound.rml | 48 +++++++++++++++++++++++++++--------- include/zelda_config.h | 19 ++++++++++++++ include/zelda_sound.h | 6 +++-- patches/sound_patches.c | 14 +++++++---- src/game/config.cpp | 4 +-- src/game/recomp_api.cpp | 4 +-- src/main/main.cpp | 6 ----- src/ui/ui_config.cpp | 35 +++++++++++++------------- 8 files changed, 90 insertions(+), 46 deletions(-) diff --git a/assets/config_menu/sound.rml b/assets/config_menu/sound.rml index 30fa2c7..d95f8a0 100644 --- a/assets/config_menu/sound.rml +++ b/assets/config_menu/sound.rml @@ -71,31 +71,55 @@
- +
- + - + + + + + + +
@@ -111,7 +135,7 @@ Toggles whether or not the low-health beeping sound plays.

- Enables 5.1 surround sound output using matrix decoding. Requires a surround sound system or virtual surround headphones. + Sets the audio output mode. Stereo outputs standard stereo audio. Mono outputs mono audio. Headphones optimizes audio for headphone listening. Surround enables 5.1 surround sound output using matrix decoding.

diff --git a/include/zelda_config.h b/include/zelda_config.h index 59b41f0..4b1e727 100644 --- a/include/zelda_config.h +++ b/include/zelda_config.h @@ -87,6 +87,25 @@ namespace zelda64 { AnalogCamMode get_analog_cam_mode(); void set_analog_cam_mode(AnalogCamMode mode); + // Audio mode setting - mirrors the game's AudioOption enum + enum class AudioMode { + Stereo, + Mono, + Headphones, + Surround, + OptionCount + }; + + NLOHMANN_JSON_SERIALIZE_ENUM(zelda64::AudioMode, { + {zelda64::AudioMode::Stereo, "Stereo"}, + {zelda64::AudioMode::Mono, "Mono"}, + {zelda64::AudioMode::Headphones, "Headphones"}, + {zelda64::AudioMode::Surround, "Surround"} + }); + + AudioMode get_audio_mode(); + void set_audio_mode(AudioMode mode); + void open_quit_game_prompt(); }; diff --git a/include/zelda_sound.h b/include/zelda_sound.h index fb1a652..c296035 100644 --- a/include/zelda_sound.h +++ b/include/zelda_sound.h @@ -1,6 +1,8 @@ #ifndef __ZELDA_SOUND_H__ #define __ZELDA_SOUND_H__ +#include "zelda_config.h" + namespace zelda64 { void reset_sound_settings(); void set_main_volume(int volume); @@ -9,8 +11,8 @@ namespace zelda64 { int get_bgm_volume(); void set_low_health_beeps_enabled(bool enabled); bool get_low_health_beeps_enabled(); - void set_surround_sound_enabled(bool enabled); - bool get_surround_sound_enabled(); + AudioMode get_audio_mode(); + void set_audio_mode(AudioMode mode); } #endif diff --git a/patches/sound_patches.c b/patches/sound_patches.c index 453df4c..b33ace2 100644 --- a/patches/sound_patches.c +++ b/patches/sound_patches.c @@ -369,9 +369,7 @@ RECOMP_PATCH void LifeMeter_UpdateSizeAndBeep(PlayState* play) { } extern s8 sSoundMode; -// @recomp Surround sound output is now controlled by the recomp's config menu -// (Sound -> Surround Sound 5.1), not by the in-game audio setting. -// This function still controls the game's internal sound processing mode. +// @recomp Patched to sync audio channels with the game's audio setting RECOMP_PATCH void Audio_SetFileSelectSettings(s8 audioSetting) { s8 soundMode; @@ -379,23 +377,29 @@ RECOMP_PATCH void Audio_SetFileSelectSettings(s8 audioSetting) { case SAVE_AUDIO_STEREO: soundMode = SOUNDMODE_STEREO; sSoundMode = SOUNDMODE_STEREO; + // @recomp Sync audio output to stereo + recomp_set_audio_channels(AUDIO_CHANNELS_STEREO); break; case SAVE_AUDIO_MONO: soundMode = SOUNDMODE_MONO; sSoundMode = SOUNDMODE_MONO; + // @recomp Sync audio output to stereo (mono is handled by the game's audio engine) + recomp_set_audio_channels(AUDIO_CHANNELS_STEREO); break; case SAVE_AUDIO_HEADSET: soundMode = SOUNDMODE_HEADSET; sSoundMode = SOUNDMODE_HEADSET; + // @recomp Sync audio output to stereo (headset mode is handled by the game's audio engine) + recomp_set_audio_channels(AUDIO_CHANNELS_STEREO); break; case SAVE_AUDIO_SURROUND: soundMode = SOUNDMODE_SURROUND; - // @recomp Use external surround mode - the actual 5.1 output is handled - // by the matrix decoder when enabled in the recomp's config menu sSoundMode = SOUNDMODE_SURROUND_EXTERNAL; + // @recomp Enable 5.1 matrix surround output when game's surround option is selected + recomp_set_audio_channels(AUDIO_CHANNELS_MATRIX_51); break; default: diff --git a/src/game/config.cpp b/src/game/config.cpp index f00bc09..063aa6b 100644 --- a/src/game/config.cpp +++ b/src/game/config.cpp @@ -460,7 +460,7 @@ bool save_sound_config(const std::filesystem::path& path) { config_json["main_volume"] = zelda64::get_main_volume(); config_json["bgm_volume"] = zelda64::get_bgm_volume(); config_json["low_health_beeps"] = zelda64::get_low_health_beeps_enabled(); - config_json["surround_sound"] = zelda64::get_surround_sound_enabled(); + config_json["audio_mode"] = zelda64::get_audio_mode(); return save_json_with_backups(path, config_json); } @@ -475,7 +475,7 @@ bool load_sound_config(const std::filesystem::path& path) { call_if_key_exists(zelda64::set_main_volume, config_json, "main_volume"); call_if_key_exists(zelda64::set_bgm_volume, config_json, "bgm_volume"); call_if_key_exists(zelda64::set_low_health_beeps_enabled, config_json, "low_health_beeps"); - call_if_key_exists(zelda64::set_surround_sound_enabled, config_json, "surround_sound"); + call_if_key_exists(zelda64::set_audio_mode, config_json, "audio_mode"); return true; } diff --git a/src/game/recomp_api.cpp b/src/game/recomp_api.cpp index 222f7e1..4567789 100644 --- a/src/game/recomp_api.cpp +++ b/src/game/recomp_api.cpp @@ -183,11 +183,11 @@ extern "C" void recomp_set_right_analog_suppressed(uint8_t* rdram, recomp_contex recomp::set_right_analog_suppressed(suppressed); } -// Surround sound support +// Surround sound support - called by the game when audio settings change extern "C" void recomp_set_audio_channels(uint8_t* rdram, recomp_context* ctx) { s32 channels = _arg<0, s32>(rdram, ctx); - // Validate input + // Validate input and update the audio backend if (channels >= 0 && channels < audioMax) { set_audio_channels(static_cast(channels)); } diff --git a/src/main/main.cpp b/src/main/main.cpp index d7a3e6d..3e85458 100644 --- a/src/main/main.cpp +++ b/src/main/main.cpp @@ -257,12 +257,6 @@ void queue_samples(int16_t* audio_data, size_t sample_count) { // Handle surround sound matrix decoding if (audio_channel_setting == audioMatrix51 && sound_matrix_decoder) { - static int surround_frame_count = 0; - if (surround_frame_count < 5) { - printf("Audio: Processing surround frame %d: %zu stereo frames, offset=%u, resampled=%zu\n", - ++surround_frame_count, frames_after_discard, - input_channels * discarded_output_frames / 2, resampled_stereo_frames); - } // Process stereo through the matrix decoder to get 5.1 surround auto [surround_samples, surround_sample_count] = sound_matrix_decoder->Process(stereo_samples, frames_after_discard); diff --git a/src/ui/ui_config.cpp b/src/ui/ui_config.cpp index 80c35cf..5ea4c0e 100644 --- a/src/ui/ui_config.cpp +++ b/src/ui/ui_config.cpp @@ -365,12 +365,12 @@ struct SoundOptionsContext { std::atomic main_volume; // Option to control the volume of all sound std::atomic bgm_volume; std::atomic low_health_beeps_enabled; // RmlUi doesn't seem to like "true"/"false" strings for setting variants so an int is used here instead. - std::atomic surround_sound_enabled; // Enable 5.1 surround sound matrix decoding + zelda64::AudioMode audio_mode; // Audio output mode (Stereo, Mono, Headphones, Surround) void reset() { bgm_volume = 100; main_volume = 100; low_health_beeps_enabled = (int)true; - surround_sound_enabled = (int)false; + audio_mode = zelda64::AudioMode::Stereo; } SoundOptionsContext() { reset(); @@ -422,18 +422,18 @@ bool zelda64::get_low_health_beeps_enabled() { // Forward declaration from main.cpp void set_audio_channels(AudioChannelsSetting channels); -void zelda64::set_surround_sound_enabled(bool enabled) { - printf("UI: Setting surround sound to %s\n", enabled ? "enabled" : "disabled"); - sound_options_context.surround_sound_enabled.store((int)enabled); +void zelda64::set_audio_mode(zelda64::AudioMode mode) { + printf("UI: Setting audio mode to %d\n", (int)mode); + sound_options_context.audio_mode = mode; if (sound_options_model_handle) { - sound_options_model_handle.DirtyVariable("surround_sound_enabled"); + sound_options_model_handle.DirtyVariable("audio_mode"); } - // Update audio backend - set_audio_channels(enabled ? audioMatrix51 : audioStereo); + // Update audio backend - only Surround mode uses 5.1 matrix decoding + set_audio_channels(mode == zelda64::AudioMode::Surround ? audioMatrix51 : audioStereo); } -bool zelda64::get_surround_sound_enabled() { - return (bool)sound_options_context.surround_sound_enabled.load(); +zelda64::AudioMode zelda64::get_audio_mode() { + return sound_options_context.audio_mode; } struct DebugContext { @@ -960,14 +960,15 @@ public: bind_atomic(constructor, sound_options_model_handle, "bgm_volume", &sound_options_context.bgm_volume); bind_atomic(constructor, sound_options_model_handle, "low_health_beeps_enabled", &sound_options_context.low_health_beeps_enabled); - // Custom binding for surround sound that calls the setter to update audio channels - constructor.BindFunc("surround_sound_enabled", - [](Rml::Variant& out) { - out = sound_options_context.surround_sound_enabled.load(); - }, + // Custom binding for audio mode that calls the setter to update audio channels + constructor.BindFunc("audio_mode", + [](Rml::Variant& out) { get_option(sound_options_context.audio_mode, out); }, [](const Rml::Variant& in) { - bool enabled = in.Get() != 0; - zelda64::set_surround_sound_enabled(enabled); + zelda64::AudioMode mode = zelda64::AudioMode::OptionCount; + from_json(in.Get(), mode); + if (mode != zelda64::AudioMode::OptionCount) { + zelda64::set_audio_mode(mode); + } } ); }