launcher: Raise DualSense speaker volume range for SpeakerFX (#1043)

controller: restore speaker midpoint and raise volume ceiling
This commit is contained in:
Pyxellator 2026-10-04 17:48:25 +02:00 committed by GitHub
parent c885da0a3f
commit 719e02574a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 40 additions and 18 deletions

View File

@ -48,7 +48,7 @@ struct ConfigOptions {
int32_t user_id = DEFAULT_USER_ID;
std::string audio_input_device;
std::optional<ControllerColor> controller_color;
uint32_t controller_speaker_volume = 100;
uint32_t controller_speaker_volume = 50;
uint32_t controller_vibration_intensity = 100;
PresentMode present_mode = PresentMode::Mailbox;
int32_t gpu_index = -1;

View File

@ -359,16 +359,16 @@
<layout class="QHBoxLayout" name="controllerVolumeLayout">
<item>
<widget class="QSlider" name="slider_controller_volume">
<property name="toolTip"><string>Scale the DualSense controller speaker over USB and Bluetooth</string></property>
<property name="toolTip"><string>Scale the DualSense speaker over USB and Bluetooth. 50% is the previous default; 100% adds 6 dB of gain.</string></property>
<property name="maximum"><number>100</number></property>
<property name="value"><number>100</number></property>
<property name="value"><number>50</number></property>
<property name="orientation"><enum>Qt::Horizontal</enum></property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_controller_volume_value">
<property name="minimumSize"><size><width>40</width><height>0</height></size></property>
<property name="text"><string>100%</string></property>
<property name="text"><string>50%</string></property>
</widget>
</item>
</layout>

View File

@ -48,7 +48,7 @@ QString EnumToText(T value) {
struct ControllerSettings {
QString color;
int speaker_volume = 100;
int speaker_volume = 50;
int vibration_intensity = 100;
void WriteSettings(QSettings* s) const {
@ -60,13 +60,13 @@ struct ControllerSettings {
void ReadSettings(QSettings* s) {
const QColor saved_color(s->value("controller_color").toString());
color = saved_color.isValid() ? saved_color.name(QColor::HexRgb) : QString {};
const auto read_percent = [s](const char* key) {
const auto read_percent = [s](const char* key, int fallback) {
bool ok = false;
const int value = s->value(key, 100).toInt(&ok);
return ok ? qBound(0, value, 100) : 100;
const int value = s->value(key, fallback).toInt(&ok);
return ok ? qBound(0, value, 100) : fallback;
};
speaker_volume = read_percent("controller_speaker_volume");
vibration_intensity = read_percent("controller_vibration_intensity");
speaker_volume = read_percent("controller_speaker_volume", 50);
vibration_intensity = read_percent("controller_vibration_intensity", 100);
}
};

View File

@ -224,7 +224,9 @@ void GameController::CycleSetting(Setting setting) {
float GameController::GetSettingScale(Setting setting) const {
const auto step = m_setting_steps[static_cast<size_t>(setting)].load(std::memory_order_relaxed);
if (setting == Setting::SpeakerVolume) {
return SPEAKER_VOLUME[step] * (Config::GetControllerSpeakerVolume() / 100.0f);
// The old speaker level matches the PS5 slider's midpoint. Give the upper
// half of the global slider up to 6 dB of extra software gain.
return SPEAKER_VOLUME[step] * (Config::GetControllerSpeakerVolume() / 50.0f);
}
if (setting == Setting::VibrationIntensity) {
return INTENSITY[step] * (Config::GetControllerVibrationIntensity() / 100.0f);

View File

@ -54,7 +54,7 @@ static void PrintUsage() {
Config::DEFAULT_USER_ID);
::printf(" --mic <name> Capture from this microphone; omit for silence.\n");
::printf(" --controller-color <#RRGGBB> Override the controller lightbar color.\n");
::printf(" --controller-volume <0-100> DualSense speaker volume. Default: 100.\n");
::printf(" --controller-volume <0-100> DualSense speaker volume. Default: 50.\n");
::printf(" --controller-vibration <0-100> DualSense vibration intensity. Default: 100.\n");
::printf(
" --present-mode <value> Fifo, Mailbox, or Immediate. Default: Mailbox.\n");

View File

@ -112,7 +112,7 @@ struct Controller {
Initialize();
Connect(1);
Check(GetSettingScale(Setting::SpeakerVolume) ==
Config::GetControllerSpeakerVolume() / 100.0f &&
Config::GetControllerSpeakerVolume() / 50.0f &&
GetSettingScale(Setting::VibrationIntensity) ==
Config::GetControllerVibrationIntensity() / 100.0f &&
GetSettingScale(Setting::TriggerEffectIntensity) == 1.0f,
@ -165,7 +165,7 @@ void TestSettingCycles() {
void TestGlobalControllerLevels() {
Config::ConfigOptions options;
options.controller_speaker_volume = 50;
options.controller_speaker_volume = 25;
options.controller_vibration_intensity = 25;
Config::Load(options);
{
@ -190,6 +190,23 @@ void TestGlobalControllerLevels() {
Check(rumble.back().large == 17 * 257 && rumble.back().small == 8 * 257,
"cycling vibration did not apply the combined intensity to cached rumble");
}
options.controller_speaker_volume = 50;
Config::Load(options);
{
Controller controller;
Check(GetSettingScale(Setting::SpeakerVolume) == 1.0f,
"speaker midpoint did not preserve the previous default level");
}
options.controller_speaker_volume = 100;
Config::Load(options);
{
Controller controller;
Check(GetSettingScale(Setting::SpeakerVolume) == 2.0f,
"speaker maximum did not add 6 dB of gain");
CycleSetting(Setting::SpeakerVolume);
Check(GetSettingScale(Setting::SpeakerVolume) == 0.0f,
"speaker maximum prevented the hotkey from muting");
}
options.controller_speaker_volume = 0;
options.controller_vibration_intensity = 0;
Config::Load(options);

View File

@ -1148,6 +1148,9 @@ void TestAudioSpeakerRouting() {
speaker_scale = 0.5f;
audio.AudioOutOutputs(&output, 1, false);
ExpectPcm({0.25f, 0.25f, 0, 0, 0.25f, 0.25f, 0, 0});
speaker_scale = 2.0f;
audio.AudioOutOutputs(&output, 1, false);
ExpectPcm({1.0f, 1.0f, 0, 0, 1.0f, 1.0f, 0, 0});
speaker_scale = 0.0f;
audio.AudioOutOutputs(&output, 1, false);
ExpectPcm({});
@ -1165,7 +1168,7 @@ void TestAudioFallbackGain() {
Fixture f;
Libs::Audio::Audio audio;
active_controller = 2;
speaker_scale = 0.5f;
speaker_scale = 2.0f;
const std::array<int16_t, 4> integer_pcm {16384, 16384, 16384, 16384};
const auto format = is_float ? Libs::Audio::Audio::Format::FloatStereo
: Libs::Audio::Audio::Format::Signed16bitStereo;
@ -1176,7 +1179,7 @@ void TestAudioFallbackGain() {
audio.AudioOutSetVolume(port, 3, volume.data());
Libs::Audio::Audio::OutputParam output {port, data};
audio.AudioOutOutputs(&output, 1, false);
const float expected = type == 4 ? 0.125f : 0.25f;
const float expected = type == 4 ? 0.5f : 0.25f;
std::array<float, 4> actual {};
if (is_float) {
Check(SDL_GetAudioStreamData(default_stream, actual.data(), sizeof(actual)) ==
@ -1231,14 +1234,14 @@ void TestBluetoothAudioSpeakerRouting() {
const auto port = audio.AudioOutOpen(4, 1024, 48000, Libs::Audio::Audio::Format::FloatStereo);
Check(port.IsValid() && default_stream != nullptr, "Bluetooth pad speaker port did not open");
std::vector<float> sound(2048, 0.25f);
speaker_scale = 0.5f;
speaker_scale = 2.0f;
Libs::Audio::Audio::OutputParam output {port, sound.data()};
Check(audio.AudioOutOutputs(&output, 1, false) == 1024 && hid_opens == 1 &&
SDL_GetAudioStreamQueued(default_stream) == 0,
"Bluetooth pad speaker also played on the host output");
fail_hid_write = true;
auto pending = Libs::Controller::DualSenseBluetooth::Prepare(now * 1000000);
Check(pending.size() == 1 && std::abs(pending[0].audio[200] - 0.125f) < 1e-4f,
Check(pending.size() == 1 && std::abs(pending[0].audio[200] - 0.5f) < 1e-4f,
"Bluetooth speaker did not apply its setting gain");
Libs::Controller::DualSenseBluetooth::Send(pending);
Check(audio.AudioOutOutputs(&output, 1, false) == 1024 &&