audiosettingswidget.cpp (27320B)
1 // SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com> 2 // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) 3 4 #include "audiosettingswidget.h" 5 #include "qtutils.h" 6 #include "settingswindow.h" 7 #include "settingwidgetbinder.h" 8 #include "ui_audioexpansionsettingsdialog.h" 9 #include "ui_audiostretchsettingsdialog.h" 10 11 #include "core/spu.h" 12 13 #include "util/audio_stream.h" 14 15 #include <bit> 16 #include <cmath> 17 18 AudioSettingsWidget::AudioSettingsWidget(SettingsWindow* dialog, QWidget* parent) : QWidget(parent), m_dialog(dialog) 19 { 20 SettingsInterface* sif = dialog->getSettingsInterface(); 21 22 m_ui.setupUi(this); 23 24 for (u32 i = 0; i < static_cast<u32>(AudioBackend::Count); i++) 25 m_ui.audioBackend->addItem(QString::fromUtf8(AudioStream::GetBackendDisplayName(static_cast<AudioBackend>(i)))); 26 27 for (u32 i = 0; i < static_cast<u32>(AudioExpansionMode::Count); i++) 28 { 29 m_ui.expansionMode->addItem( 30 QString::fromUtf8(AudioStream::GetExpansionModeDisplayName(static_cast<AudioExpansionMode>(i)))); 31 } 32 33 for (u32 i = 0; i < static_cast<u32>(AudioStretchMode::Count); i++) 34 { 35 m_ui.stretchMode->addItem( 36 QString::fromUtf8(AudioStream::GetStretchModeDisplayName(static_cast<AudioStretchMode>(i)))); 37 } 38 39 SettingWidgetBinder::BindWidgetToEnumSetting(sif, m_ui.audioBackend, "Audio", "Backend", 40 &AudioStream::ParseBackendName, &AudioStream::GetBackendName, 41 AudioStream::DEFAULT_BACKEND); 42 SettingWidgetBinder::BindWidgetToEnumSetting(sif, m_ui.expansionMode, "Audio", "ExpansionMode", 43 &AudioStream::ParseExpansionMode, &AudioStream::GetExpansionModeName, 44 AudioStreamParameters::DEFAULT_EXPANSION_MODE); 45 SettingWidgetBinder::BindWidgetToEnumSetting(sif, m_ui.stretchMode, "Audio", "StretchMode", 46 &AudioStream::ParseStretchMode, &AudioStream::GetStretchModeName, 47 AudioStreamParameters::DEFAULT_STRETCH_MODE); 48 SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.bufferMS, "Audio", "BufferMS", 49 AudioStreamParameters::DEFAULT_BUFFER_MS); 50 SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.outputLatencyMS, "Audio", "OutputLatencyMS", 51 AudioStreamParameters::DEFAULT_OUTPUT_LATENCY_MS); 52 SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.outputLatencyMinimal, "Audio", "OutputLatencyMinimal", 53 AudioStreamParameters::DEFAULT_OUTPUT_LATENCY_MINIMAL); 54 SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.muteCDAudio, "CDROM", "MuteCDAudio", false); 55 connect(m_ui.audioBackend, &QComboBox::currentIndexChanged, this, &AudioSettingsWidget::updateDriverNames); 56 connect(m_ui.expansionMode, &QComboBox::currentIndexChanged, this, &AudioSettingsWidget::onExpansionModeChanged); 57 connect(m_ui.expansionSettings, &QToolButton::clicked, this, &AudioSettingsWidget::onExpansionSettingsClicked); 58 connect(m_ui.stretchMode, &QComboBox::currentIndexChanged, this, &AudioSettingsWidget::onStretchModeChanged); 59 connect(m_ui.stretchSettings, &QToolButton::clicked, this, &AudioSettingsWidget::onStretchSettingsClicked); 60 onExpansionModeChanged(); 61 onStretchModeChanged(); 62 updateDriverNames(); 63 64 connect(m_ui.bufferMS, &QSlider::valueChanged, this, &AudioSettingsWidget::updateLatencyLabel); 65 connect(m_ui.outputLatencyMS, &QSlider::valueChanged, this, &AudioSettingsWidget::updateLatencyLabel); 66 connect(m_ui.outputLatencyMinimal, &QCheckBox::checkStateChanged, this, 67 &AudioSettingsWidget::onMinimalOutputLatencyChecked); 68 updateLatencyLabel(); 69 70 // for per-game, just use the normal path, since it needs to re-read/apply 71 if (!dialog->isPerGameSettings()) 72 { 73 m_ui.volume->setValue(m_dialog->getEffectiveIntValue("Audio", "OutputVolume", 100)); 74 m_ui.fastForwardVolume->setValue(m_dialog->getEffectiveIntValue("Audio", "FastForwardVolume", 100)); 75 m_ui.muted->setChecked(m_dialog->getEffectiveBoolValue("Audio", "OutputMuted", false)); 76 connect(m_ui.volume, &QSlider::valueChanged, this, &AudioSettingsWidget::onOutputVolumeChanged); 77 connect(m_ui.fastForwardVolume, &QSlider::valueChanged, this, &AudioSettingsWidget::onFastForwardVolumeChanged); 78 connect(m_ui.muted, &QCheckBox::checkStateChanged, this, &AudioSettingsWidget::onOutputMutedChanged); 79 updateVolumeLabel(); 80 } 81 else 82 { 83 SettingWidgetBinder::BindWidgetAndLabelToIntSetting(sif, m_ui.volume, m_ui.volumeLabel, tr("%"), "Audio", 84 "OutputVolume", 100); 85 SettingWidgetBinder::BindWidgetAndLabelToIntSetting(sif, m_ui.fastForwardVolume, m_ui.fastForwardVolumeLabel, 86 tr("%"), "Audio", "FastForwardVolume", 100); 87 SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.muted, "Audio", "OutputMuted", false); 88 } 89 connect(m_ui.resetVolume, &QToolButton::clicked, this, [this]() { resetVolume(false); }); 90 connect(m_ui.resetFastForwardVolume, &QToolButton::clicked, this, [this]() { resetVolume(true); }); 91 92 dialog->registerWidgetHelp( 93 m_ui.audioBackend, tr("Audio Backend"), QStringLiteral("Cubeb"), 94 tr("The audio backend determines how frames produced by the emulator are submitted to the host. Cubeb provides the " 95 "lowest latency, if you encounter issues, try the SDL backend. The null backend disables all host audio " 96 "output.")); 97 dialog->registerWidgetHelp( 98 m_ui.outputLatencyMS, tr("Output Latency"), tr("%1 ms").arg(AudioStreamParameters::DEFAULT_OUTPUT_LATENCY_MS), 99 tr("The buffer size determines the size of the chunks of audio which will be pulled by the " 100 "host. Smaller values reduce the output latency, but may cause hitches if the emulation " 101 "speed is inconsistent. Note that the Cubeb backend uses smaller chunks regardless of " 102 "this value, so using a low value here may not significantly change latency.")); 103 dialog->registerWidgetHelp(m_ui.volume, tr("Output Volume"), "100%", 104 tr("Controls the volume of the audio played on the host.")); 105 dialog->registerWidgetHelp(m_ui.fastForwardVolume, tr("Fast Forward Volume"), "100%", 106 tr("Controls the volume of the audio played on the host when fast forwarding.")); 107 dialog->registerWidgetHelp(m_ui.muted, tr("Mute All Sound"), tr("Unchecked"), 108 tr("Prevents the emulator from producing any audible sound.")); 109 dialog->registerWidgetHelp(m_ui.muteCDAudio, tr("Mute CD Audio"), tr("Unchecked"), 110 tr("Forcibly mutes both CD-DA and XA audio from the CD-ROM. Can be used to disable " 111 "background music in some games.")); 112 dialog->registerWidgetHelp(m_ui.expansionMode, tr("Expansion Mode"), tr("Disabled (Stereo)"), 113 tr("Determines how audio is expanded from stereo to surround for supported games. This " 114 "includes games that support Dolby Pro Logic/Pro Logic II.")); 115 dialog->registerWidgetHelp(m_ui.expansionSettings, tr("Expansion Settings"), tr("N/A"), 116 tr("These settings fine-tune the behavior of the FreeSurround-based channel expander.")); 117 dialog->registerWidgetHelp( 118 m_ui.stretchMode, tr("Stretch Mode"), tr("Time Stretching"), 119 tr("When running outside of 100% speed, adjusts the tempo on audio instead of dropping frames. Produces " 120 "much nicer fast forward/slowdown audio at a small cost to performance.")); 121 dialog->registerWidgetHelp(m_ui.stretchSettings, tr("Stretch Settings"), tr("N/A"), 122 tr("These settings fine-tune the behavior of the SoundTouch audio time stretcher when " 123 "running outside of 100% speed.")); 124 dialog->registerWidgetHelp(m_ui.resetVolume, tr("Reset Volume"), tr("N/A"), 125 m_dialog->isPerGameSettings() ? tr("Resets volume back to the global/inherited setting.") : 126 tr("Resets volume back to the default, i.e. full.")); 127 dialog->registerWidgetHelp(m_ui.resetFastForwardVolume, tr("Reset Fast Forward Volume"), tr("N/A"), 128 m_dialog->isPerGameSettings() ? tr("Resets volume back to the global/inherited setting.") : 129 tr("Resets volume back to the default, i.e. full.")); 130 } 131 132 AudioSettingsWidget::~AudioSettingsWidget() = default; 133 134 AudioExpansionMode AudioSettingsWidget::getEffectiveExpansionMode() const 135 { 136 return AudioStream::ParseExpansionMode( 137 m_dialog 138 ->getEffectiveStringValue("Audio", "ExpansionMode", 139 AudioStream::GetExpansionModeName(AudioStreamParameters::DEFAULT_EXPANSION_MODE)) 140 .c_str()) 141 .value_or(AudioStreamParameters::DEFAULT_EXPANSION_MODE); 142 } 143 144 u32 AudioSettingsWidget::getEffectiveExpansionBlockSize() const 145 { 146 const AudioExpansionMode expansion_mode = getEffectiveExpansionMode(); 147 if (expansion_mode == AudioExpansionMode::Disabled) 148 return 0; 149 150 const u32 config_block_size = 151 m_dialog->getEffectiveIntValue("Audio", "ExpandBlockSize", AudioStreamParameters::DEFAULT_EXPAND_BLOCK_SIZE); 152 return std::has_single_bit(config_block_size) ? config_block_size : std::bit_ceil(config_block_size); 153 } 154 155 void AudioSettingsWidget::onExpansionModeChanged() 156 { 157 const AudioExpansionMode expansion_mode = getEffectiveExpansionMode(); 158 m_ui.expansionSettings->setEnabled(expansion_mode != AudioExpansionMode::Disabled); 159 updateLatencyLabel(); 160 } 161 162 void AudioSettingsWidget::onStretchModeChanged() 163 { 164 const AudioStretchMode stretch_mode = 165 AudioStream::ParseStretchMode( 166 m_dialog 167 ->getEffectiveStringValue("Audio", "StretchMode", 168 AudioStream::GetStretchModeName(AudioStreamParameters::DEFAULT_STRETCH_MODE)) 169 .c_str()) 170 .value_or(AudioStreamParameters::DEFAULT_STRETCH_MODE); 171 m_ui.stretchSettings->setEnabled(stretch_mode != AudioStretchMode::Off); 172 } 173 174 AudioBackend AudioSettingsWidget::getEffectiveBackend() const 175 { 176 return AudioStream::ParseBackendName( 177 m_dialog 178 ->getEffectiveStringValue("Audio", "Backend", AudioStream::GetBackendName(AudioStream::DEFAULT_BACKEND)) 179 .c_str()) 180 .value_or(AudioStream::DEFAULT_BACKEND); 181 } 182 183 void AudioSettingsWidget::updateDriverNames() 184 { 185 const AudioBackend backend = getEffectiveBackend(); 186 const std::vector<std::pair<std::string, std::string>> names = AudioStream::GetDriverNames(backend); 187 188 m_ui.driver->disconnect(); 189 m_ui.driver->clear(); 190 if (names.empty()) 191 { 192 m_ui.driver->addItem(tr("Default")); 193 m_ui.driver->setEnabled(false); 194 } 195 else 196 { 197 m_ui.driver->setEnabled(true); 198 for (const auto& [name, display_name] : names) 199 m_ui.driver->addItem(QString::fromStdString(display_name), QString::fromStdString(name)); 200 201 SettingWidgetBinder::BindWidgetToStringSetting(m_dialog->getSettingsInterface(), m_ui.driver, "Audio", "Driver", 202 std::move(names.front().first)); 203 connect(m_ui.driver, &QComboBox::currentIndexChanged, this, &AudioSettingsWidget::updateDeviceNames); 204 } 205 206 updateDeviceNames(); 207 } 208 209 void AudioSettingsWidget::updateDeviceNames() 210 { 211 const AudioBackend backend = getEffectiveBackend(); 212 const std::string driver_name = m_dialog->getEffectiveStringValue("Audio", "Driver", ""); 213 const std::string current_device = m_dialog->getEffectiveStringValue("Audio", "Device", ""); 214 const std::vector<AudioStream::DeviceInfo> devices = 215 AudioStream::GetOutputDevices(backend, driver_name.c_str(), SPU::SAMPLE_RATE); 216 217 m_ui.outputDevice->disconnect(); 218 m_ui.outputDevice->clear(); 219 m_output_device_latency = 0; 220 221 if (devices.empty()) 222 { 223 m_ui.outputDevice->addItem(tr("Default")); 224 m_ui.outputDevice->setEnabled(false); 225 } 226 else 227 { 228 m_ui.outputDevice->setEnabled(true); 229 230 bool is_known_device = false; 231 for (const AudioStream::DeviceInfo& di : devices) 232 { 233 m_ui.outputDevice->addItem(QString::fromStdString(di.display_name), QString::fromStdString(di.name)); 234 if (di.name == current_device) 235 { 236 m_output_device_latency = di.minimum_latency_frames; 237 is_known_device = true; 238 } 239 } 240 241 if (!is_known_device) 242 { 243 m_ui.outputDevice->addItem(tr("Unknown Device \"%1\"").arg(QString::fromStdString(current_device)), 244 QString::fromStdString(current_device)); 245 } 246 247 SettingWidgetBinder::BindWidgetToStringSetting(m_dialog->getSettingsInterface(), m_ui.outputDevice, "Audio", 248 "OutputDevice", std::move(devices.front().name)); 249 } 250 251 updateLatencyLabel(); 252 } 253 254 void AudioSettingsWidget::updateLatencyLabel() 255 { 256 const u32 expand_buffer_ms = AudioStream::GetMSForBufferSize(SPU::SAMPLE_RATE, getEffectiveExpansionBlockSize()); 257 const u32 config_buffer_ms = 258 m_dialog->getEffectiveIntValue("Audio", "BufferMS", AudioStreamParameters::DEFAULT_BUFFER_MS); 259 const u32 config_output_latency_ms = 260 m_dialog->getEffectiveIntValue("Audio", "OutputLatencyMS", AudioStreamParameters::DEFAULT_OUTPUT_LATENCY_MS); 261 const bool minimal_output = m_dialog->getEffectiveBoolValue("Audio", "OutputLatencyMinimal", 262 AudioStreamParameters::DEFAULT_OUTPUT_LATENCY_MINIMAL); 263 264 //: Preserve the %1 variable, adapt the latter ms (and/or any possible spaces in between) to your language's ruleset. 265 m_ui.outputLatencyLabel->setText(minimal_output ? tr("N/A") : tr("%1 ms").arg(config_output_latency_ms)); 266 m_ui.bufferMSLabel->setText(tr("%1 ms").arg(config_buffer_ms)); 267 268 const u32 output_latency_ms = minimal_output ? 269 AudioStream::GetMSForBufferSize(SPU::SAMPLE_RATE, m_output_device_latency) : 270 config_output_latency_ms; 271 if (output_latency_ms > 0) 272 { 273 if (expand_buffer_ms > 0) 274 { 275 m_ui.bufferingLabel->setText(tr("Maximum Latency: %1 ms (%2 ms buffer + %3 ms expand + %4 ms output)") 276 .arg(config_buffer_ms + expand_buffer_ms + output_latency_ms) 277 .arg(config_buffer_ms) 278 .arg(expand_buffer_ms) 279 .arg(output_latency_ms)); 280 } 281 else 282 { 283 m_ui.bufferingLabel->setText(tr("Maximum Latency: %1 ms (%2 ms buffer + %3 ms output)") 284 .arg(config_buffer_ms + output_latency_ms) 285 .arg(config_buffer_ms) 286 .arg(output_latency_ms)); 287 } 288 } 289 else 290 { 291 if (expand_buffer_ms > 0) 292 { 293 m_ui.bufferingLabel->setText(tr("Maximum Latency: %1 ms (%2 ms expand, minimum output latency unknown)") 294 .arg(expand_buffer_ms + config_buffer_ms) 295 .arg(expand_buffer_ms)); 296 } 297 else 298 { 299 m_ui.bufferingLabel->setText(tr("Maximum Latency: %1 ms (minimum output latency unknown)").arg(config_buffer_ms)); 300 } 301 } 302 } 303 304 void AudioSettingsWidget::updateVolumeLabel() 305 { 306 m_ui.volumeLabel->setText(tr("%1%").arg(m_ui.volume->value())); 307 m_ui.fastForwardVolumeLabel->setText(tr("%1%").arg(m_ui.fastForwardVolume->value())); 308 } 309 310 void AudioSettingsWidget::onMinimalOutputLatencyChecked(Qt::CheckState state) 311 { 312 const bool minimal = m_dialog->getEffectiveBoolValue("SPU2/Output", "OutputLatencyMinimal", false); 313 m_ui.outputLatencyMS->setEnabled(!minimal); 314 updateLatencyLabel(); 315 } 316 317 void AudioSettingsWidget::onOutputVolumeChanged(int new_value) 318 { 319 // only called for base settings 320 DebugAssert(!m_dialog->isPerGameSettings()); 321 Host::SetBaseIntSettingValue("Audio", "OutputVolume", new_value); 322 Host::CommitBaseSettingChanges(); 323 g_emu_thread->setAudioOutputVolume(new_value, m_ui.fastForwardVolume->value()); 324 325 updateVolumeLabel(); 326 } 327 328 void AudioSettingsWidget::onFastForwardVolumeChanged(int new_value) 329 { 330 // only called for base settings 331 DebugAssert(!m_dialog->isPerGameSettings()); 332 Host::SetBaseIntSettingValue("Audio", "FastForwardVolume", new_value); 333 Host::CommitBaseSettingChanges(); 334 g_emu_thread->setAudioOutputVolume(m_ui.volume->value(), new_value); 335 336 updateVolumeLabel(); 337 } 338 339 void AudioSettingsWidget::onOutputMutedChanged(int new_state) 340 { 341 // only called for base settings 342 DebugAssert(!m_dialog->isPerGameSettings()); 343 344 const bool muted = (new_state != 0); 345 Host::SetBaseBoolSettingValue("Audio", "OutputMuted", muted); 346 Host::CommitBaseSettingChanges(); 347 g_emu_thread->setAudioOutputMuted(muted); 348 } 349 350 void AudioSettingsWidget::onExpansionSettingsClicked() 351 { 352 QDialog dlg(QtUtils::GetRootWidget(this)); 353 Ui::AudioExpansionSettingsDialog dlgui; 354 dlgui.setupUi(&dlg); 355 dlgui.icon->setPixmap(QIcon::fromTheme(QStringLiteral("volume-up-line")).pixmap(32, 32)); 356 357 SettingsInterface* sif = m_dialog->getSettingsInterface(); 358 SettingWidgetBinder::BindWidgetToIntSetting(sif, dlgui.blockSize, "Audio", "ExpandBlockSize", 359 AudioStreamParameters::DEFAULT_EXPAND_BLOCK_SIZE, 0); 360 QtUtils::BindLabelToSlider(dlgui.blockSize, dlgui.blockSizeLabel); 361 SettingWidgetBinder::BindWidgetToFloatSetting(sif, dlgui.circularWrap, "Audio", "ExpandCircularWrap", 362 AudioStreamParameters::DEFAULT_EXPAND_CIRCULAR_WRAP); 363 QtUtils::BindLabelToSlider(dlgui.circularWrap, dlgui.circularWrapLabel); 364 SettingWidgetBinder::BindWidgetToNormalizedSetting(sif, dlgui.shift, "Audio", "ExpandShift", 100.0f, 365 AudioStreamParameters::DEFAULT_EXPAND_SHIFT); 366 QtUtils::BindLabelToSlider(dlgui.shift, dlgui.shiftLabel, 100.0f); 367 SettingWidgetBinder::BindWidgetToNormalizedSetting(sif, dlgui.depth, "Audio", "ExpandDepth", 10.0f, 368 AudioStreamParameters::DEFAULT_EXPAND_DEPTH); 369 QtUtils::BindLabelToSlider(dlgui.depth, dlgui.depthLabel, 10.0f); 370 SettingWidgetBinder::BindWidgetToNormalizedSetting(sif, dlgui.focus, "Audio", "ExpandFocus", 100.0f, 371 AudioStreamParameters::DEFAULT_EXPAND_FOCUS); 372 QtUtils::BindLabelToSlider(dlgui.focus, dlgui.focusLabel, 100.0f); 373 SettingWidgetBinder::BindWidgetToNormalizedSetting(sif, dlgui.centerImage, "Audio", "ExpandCenterImage", 100.0f, 374 AudioStreamParameters::DEFAULT_EXPAND_CENTER_IMAGE); 375 QtUtils::BindLabelToSlider(dlgui.centerImage, dlgui.centerImageLabel, 100.0f); 376 SettingWidgetBinder::BindWidgetToNormalizedSetting(sif, dlgui.frontSeparation, "Audio", "ExpandFrontSeparation", 377 10.0f, AudioStreamParameters::DEFAULT_EXPAND_FRONT_SEPARATION); 378 QtUtils::BindLabelToSlider(dlgui.frontSeparation, dlgui.frontSeparationLabel, 10.0f); 379 SettingWidgetBinder::BindWidgetToNormalizedSetting(sif, dlgui.rearSeparation, "Audio", "ExpandRearSeparation", 10.0f, 380 AudioStreamParameters::DEFAULT_EXPAND_REAR_SEPARATION); 381 QtUtils::BindLabelToSlider(dlgui.rearSeparation, dlgui.rearSeparationLabel, 10.0f); 382 SettingWidgetBinder::BindWidgetToIntSetting(sif, dlgui.lowCutoff, "Audio", "ExpandLowCutoff", 383 AudioStreamParameters::DEFAULT_EXPAND_LOW_CUTOFF); 384 QtUtils::BindLabelToSlider(dlgui.lowCutoff, dlgui.lowCutoffLabel); 385 SettingWidgetBinder::BindWidgetToIntSetting(sif, dlgui.highCutoff, "Audio", "ExpandHighCutoff", 386 AudioStreamParameters::DEFAULT_EXPAND_HIGH_CUTOFF); 387 QtUtils::BindLabelToSlider(dlgui.highCutoff, dlgui.highCutoffLabel); 388 389 connect(dlgui.buttonBox->button(QDialogButtonBox::Close), &QPushButton::clicked, &dlg, &QDialog::accept); 390 connect(dlgui.buttonBox->button(QDialogButtonBox::RestoreDefaults), &QPushButton::clicked, this, [this, &dlg]() { 391 m_dialog->setIntSettingValue("Audio", "ExpandBlockSize", 392 m_dialog->isPerGameSettings() ? 393 std::nullopt : 394 std::optional<int>(AudioStreamParameters::DEFAULT_EXPAND_BLOCK_SIZE)); 395 396 m_dialog->setFloatSettingValue("Audio", "ExpandCircularWrap", 397 m_dialog->isPerGameSettings() ? 398 std::nullopt : 399 std::optional<float>(AudioStreamParameters::DEFAULT_EXPAND_CIRCULAR_WRAP)); 400 m_dialog->setFloatSettingValue( 401 "Audio", "ExpandShift", 402 m_dialog->isPerGameSettings() ? std::nullopt : std::optional<float>(AudioStreamParameters::DEFAULT_EXPAND_SHIFT)); 403 m_dialog->setFloatSettingValue( 404 "Audio", "ExpandDepth", 405 m_dialog->isPerGameSettings() ? std::nullopt : std::optional<float>(AudioStreamParameters::DEFAULT_EXPAND_DEPTH)); 406 m_dialog->setFloatSettingValue( 407 "Audio", "ExpandFocus", 408 m_dialog->isPerGameSettings() ? std::nullopt : std::optional<float>(AudioStreamParameters::DEFAULT_EXPAND_FOCUS)); 409 m_dialog->setFloatSettingValue("Audio", "ExpandCenterImage", 410 m_dialog->isPerGameSettings() ? 411 std::nullopt : 412 std::optional<float>(AudioStreamParameters::DEFAULT_EXPAND_CENTER_IMAGE)); 413 m_dialog->setFloatSettingValue("Audio", "ExpandFrontSeparation", 414 m_dialog->isPerGameSettings() ? 415 std::nullopt : 416 std::optional<float>(AudioStreamParameters::DEFAULT_EXPAND_FRONT_SEPARATION)); 417 m_dialog->setFloatSettingValue("Audio", "ExpandRearSeparation", 418 m_dialog->isPerGameSettings() ? 419 std::nullopt : 420 std::optional<float>(AudioStreamParameters::DEFAULT_EXPAND_REAR_SEPARATION)); 421 m_dialog->setIntSettingValue("Audio", "ExpandLowCutoff", 422 m_dialog->isPerGameSettings() ? 423 std::nullopt : 424 std::optional<int>(AudioStreamParameters::DEFAULT_EXPAND_LOW_CUTOFF)); 425 m_dialog->setIntSettingValue("Audio", "ExpandHighCutoff", 426 m_dialog->isPerGameSettings() ? 427 std::nullopt : 428 std::optional<int>(AudioStreamParameters::DEFAULT_EXPAND_HIGH_CUTOFF)); 429 430 dlg.done(0); 431 432 QMetaObject::invokeMethod(this, &AudioSettingsWidget::onExpansionSettingsClicked, Qt::QueuedConnection); 433 }); 434 435 dlg.exec(); 436 updateLatencyLabel(); 437 } 438 439 void AudioSettingsWidget::onStretchSettingsClicked() 440 { 441 QDialog dlg(QtUtils::GetRootWidget(this)); 442 Ui::AudioStretchSettingsDialog dlgui; 443 dlgui.setupUi(&dlg); 444 dlgui.icon->setPixmap(QIcon::fromTheme(QStringLiteral("volume-up-line")).pixmap(32, 32)); 445 446 SettingsInterface* sif = m_dialog->getSettingsInterface(); 447 SettingWidgetBinder::BindWidgetToIntSetting(sif, dlgui.sequenceLength, "Audio", "StretchSequenceLengthMS", 448 AudioStreamParameters::DEFAULT_STRETCH_SEQUENCE_LENGTH, 0); 449 QtUtils::BindLabelToSlider(dlgui.sequenceLength, dlgui.sequenceLengthLabel); 450 SettingWidgetBinder::BindWidgetToIntSetting(sif, dlgui.seekWindowSize, "Audio", "StretchSeekWindowMS", 451 AudioStreamParameters::DEFAULT_STRETCH_SEEKWINDOW, 0); 452 QtUtils::BindLabelToSlider(dlgui.seekWindowSize, dlgui.seekWindowSizeLabel); 453 SettingWidgetBinder::BindWidgetToIntSetting(sif, dlgui.overlap, "Audio", "StretchOverlapMS", 454 AudioStreamParameters::DEFAULT_STRETCH_OVERLAP, 0); 455 QtUtils::BindLabelToSlider(dlgui.overlap, dlgui.overlapLabel); 456 SettingWidgetBinder::BindWidgetToBoolSetting(sif, dlgui.useQuickSeek, "Audio", "StretchUseQuickSeek", 457 AudioStreamParameters::DEFAULT_STRETCH_USE_QUICKSEEK); 458 SettingWidgetBinder::BindWidgetToBoolSetting(sif, dlgui.useAAFilter, "Audio", "StretchUseAAFilter", 459 AudioStreamParameters::DEFAULT_STRETCH_USE_AA_FILTER); 460 461 connect(dlgui.buttonBox->button(QDialogButtonBox::Close), &QPushButton::clicked, &dlg, &QDialog::accept); 462 connect(dlgui.buttonBox->button(QDialogButtonBox::RestoreDefaults), &QPushButton::clicked, this, [this, &dlg]() { 463 m_dialog->setIntSettingValue("Audio", "StretchSequenceLengthMS", 464 m_dialog->isPerGameSettings() ? 465 std::nullopt : 466 std::optional<int>(AudioStreamParameters::DEFAULT_STRETCH_SEQUENCE_LENGTH)); 467 m_dialog->setIntSettingValue("Audio", "StretchSeekWindowMS", 468 m_dialog->isPerGameSettings() ? 469 std::nullopt : 470 std::optional<int>(AudioStreamParameters::DEFAULT_STRETCH_SEEKWINDOW)); 471 m_dialog->setIntSettingValue("Audio", "StretchOverlapMS", 472 m_dialog->isPerGameSettings() ? 473 std::nullopt : 474 std::optional<int>(AudioStreamParameters::DEFAULT_STRETCH_OVERLAP)); 475 m_dialog->setBoolSettingValue("Audio", "StretchUseQuickSeek", 476 m_dialog->isPerGameSettings() ? 477 std::nullopt : 478 std::optional<bool>(AudioStreamParameters::DEFAULT_STRETCH_USE_QUICKSEEK)); 479 m_dialog->setBoolSettingValue("Audio", "StretchUseAAFilter", 480 m_dialog->isPerGameSettings() ? 481 std::nullopt : 482 std::optional<bool>(AudioStreamParameters::DEFAULT_STRETCH_USE_AA_FILTER)); 483 484 dlg.done(0); 485 486 QMetaObject::invokeMethod(this, &AudioSettingsWidget::onStretchSettingsClicked, Qt::QueuedConnection); 487 }); 488 489 dlg.exec(); 490 } 491 492 void AudioSettingsWidget::resetVolume(bool fast_forward) 493 { 494 const char* key = fast_forward ? "FastForwardVolume" : "OutputVolume"; 495 QSlider* const slider = fast_forward ? m_ui.fastForwardVolume : m_ui.volume; 496 QLabel* const label = fast_forward ? m_ui.fastForwardVolumeLabel : m_ui.volumeLabel; 497 498 if (m_dialog->isPerGameSettings()) 499 { 500 m_dialog->removeSettingValue("Audio", key); 501 502 const int value = m_dialog->getEffectiveIntValue("Audio", key, 100); 503 QSignalBlocker sb(slider); 504 slider->setValue(value); 505 label->setText(QStringLiteral("%1%2").arg(value).arg(tr("%"))); 506 507 // remove bold font if it was previously overridden 508 QFont font(label->font()); 509 font.setBold(false); 510 label->setFont(font); 511 } 512 else 513 { 514 slider->setValue(100); 515 } 516 }