update audio options to select among 4 opts.

This commit is contained in:
Tortuga Veloz 2026-02-10 09:46:09 +01:00
parent 98da5553ff
commit ac123c4cab
8 changed files with 90 additions and 46 deletions

View file

@ -71,31 +71,55 @@
</div>
<div class="config-option" data-event-mouseover="set_cur_config_index(3)">
<label class="config-option__title">Surround Sound (5.1)</label>
<label class="config-option__title">Audio Mode</label>
<div class="config-option__list">
<input
type="radio"
data-event-blur="set_cur_config_index(-1)"
data-event-focus="set_cur_config_index(3)"
name="surround"
data-checked="surround_sound_enabled"
value="1"
id="surround_on"
name="audio_mode"
data-checked="audio_mode"
value="Stereo"
id="audio_stereo"
style="nav-up: #lhb_on"
/>
<label class="config-option__tab-label" for="surround_on">On</label>
<label class="config-option__tab-label" for="audio_stereo">Stereo</label>
<input
type="radio"
data-event-blur="set_cur_config_index(-1)"
data-event-focus="set_cur_config_index(3)"
name="surround"
data-checked="surround_sound_enabled"
value="0"
id="surround_off"
name="audio_mode"
data-checked="audio_mode"
value="Mono"
id="audio_mono"
style="nav-up: #lhb_on"
/>
<label class="config-option__tab-label" for="surround_off">Off</label>
<label class="config-option__tab-label" for="audio_mono">Mono</label>
<input
type="radio"
data-event-blur="set_cur_config_index(-1)"
data-event-focus="set_cur_config_index(3)"
name="audio_mode"
data-checked="audio_mode"
value="Headphones"
id="audio_headphones"
style="nav-up: #lhb_on"
/>
<label class="config-option__tab-label" for="audio_headphones">Headphones</label>
<input
type="radio"
data-event-blur="set_cur_config_index(-1)"
data-event-focus="set_cur_config_index(3)"
name="audio_mode"
data-checked="audio_mode"
value="Surround"
id="audio_surround"
style="nav-up: #lhb_on"
/>
<label class="config-option__tab-label" for="audio_surround">Surround</label>
</div>
</div>
</div>
@ -111,7 +135,7 @@
Toggles whether or not the low-health beeping sound plays.
</p>
<p data-if="cur_config_index == 3">
Enables 5.1 surround sound output using matrix decoding. Requires a surround sound system or virtual surround headphones.
Sets the audio output mode. <b>Stereo</b> outputs standard stereo audio. <b>Mono</b> outputs mono audio. <b>Headphones</b> optimizes audio for headphone listening. <b>Surround</b> enables 5.1 surround sound output using matrix decoding.
</p>
</div>
</div>

View file

@ -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();
};

View file

@ -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

View file

@ -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:

View file

@ -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;
}

View file

@ -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<AudioChannelsSetting>(channels));
}

View file

@ -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);

View file

@ -365,12 +365,12 @@ struct SoundOptionsContext {
std::atomic<int> main_volume; // Option to control the volume of all sound
std::atomic<int> bgm_volume;
std::atomic<int> 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<int> 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<int>() != 0;
zelda64::set_surround_sound_enabled(enabled);
zelda64::AudioMode mode = zelda64::AudioMode::OptionCount;
from_json(in.Get<std::string>(), mode);
if (mode != zelda64::AudioMode::OptionCount) {
zelda64::set_audio_mode(mode);
}
}
);
}