diff --git a/src/audio_core/dsp_interface.cpp b/src/audio_core/dsp_interface.cpp index dcb902582d..626a9d04d1 100644 --- a/src/audio_core/dsp_interface.cpp +++ b/src/audio_core/dsp_interface.cpp @@ -7,6 +7,7 @@ #include "audio_core/sink.h" #include "audio_core/sink_details.h" #include "common/assert.h" +#include "core/settings.h" namespace AudioCore { @@ -39,10 +40,17 @@ void DspInterface::EnableStretching(bool enable) { perform_time_stretching = enable; } -void DspInterface::OutputFrame(const StereoFrame16& frame) { +void DspInterface::OutputFrame(StereoFrame16& frame) { if (!sink) return; + // Implementation of the hardware volume slider with a dynamic range of 60 dB + float volume_scale_factor = std::exp(6.90775 * Settings::values.volume) * 0.001; + for (size_t i = 0; i < frame.size(); i++) { + frame[i][0] = static_cast(frame[i][0] * volume_scale_factor); + frame[i][1] = static_cast(frame[i][1] * volume_scale_factor); + } + if (perform_time_stretching) { time_stretcher.AddSamples(&frame[0][0], frame.size()); std::vector stretched_samples = time_stretcher.Process(sink->SamplesInQueue()); diff --git a/src/audio_core/dsp_interface.h b/src/audio_core/dsp_interface.h index fa62ba6913..4126c03ed5 100644 --- a/src/audio_core/dsp_interface.h +++ b/src/audio_core/dsp_interface.h @@ -68,7 +68,7 @@ public: void EnableStretching(bool enable); protected: - void OutputFrame(const StereoFrame16& frame); + void OutputFrame(StereoFrame16& frame); private: void FlushResidualStretcherAudio(); diff --git a/src/citra/config.cpp b/src/citra/config.cpp index 75f5071692..553e72d932 100644 --- a/src/citra/config.cpp +++ b/src/citra/config.cpp @@ -143,6 +143,7 @@ void Config::ReadValues() { Settings::values.enable_audio_stretching = sdl2_config->GetBoolean("Audio", "enable_audio_stretching", true); Settings::values.audio_device_id = sdl2_config->Get("Audio", "output_device", "auto"); + Settings::values.volume = sdl2_config->GetReal("Audio", "volume", 1); // Data Storage Settings::values.use_virtual_sd = diff --git a/src/citra/default_ini.h b/src/citra/default_ini.h index c501a6de7e..909950350b 100644 --- a/src/citra/default_ini.h +++ b/src/citra/default_ini.h @@ -164,6 +164,10 @@ enable_audio_stretching = # auto (default): Auto-select output_device = +# Output volume. +# 1.0 (default): 100%, 0.0; mute +volume = + [Data Storage] # Whether to create a virtual SD card. # 1 (default): Yes, 0: No diff --git a/src/citra_qt/configuration/config.cpp b/src/citra_qt/configuration/config.cpp index 8d95613536..9bc1ddc4ed 100644 --- a/src/citra_qt/configuration/config.cpp +++ b/src/citra_qt/configuration/config.cpp @@ -122,6 +122,7 @@ void Config::ReadValues() { qt_config->value("enable_audio_stretching", true).toBool(); Settings::values.audio_device_id = qt_config->value("output_device", "auto").toString().toStdString(); + Settings::values.volume = qt_config->value("volume", 1).toFloat(); qt_config->endGroup(); using namespace Service::CAM; @@ -344,6 +345,7 @@ void Config::SaveValues() { qt_config->setValue("output_engine", QString::fromStdString(Settings::values.sink_id)); qt_config->setValue("enable_audio_stretching", Settings::values.enable_audio_stretching); qt_config->setValue("output_device", QString::fromStdString(Settings::values.audio_device_id)); + qt_config->setValue("volume", Settings::values.volume); qt_config->endGroup(); using namespace Service::CAM; diff --git a/src/citra_qt/configuration/configure_audio.cpp b/src/citra_qt/configuration/configure_audio.cpp index d0064ca78e..0aee1cb5e3 100644 --- a/src/citra_qt/configuration/configure_audio.cpp +++ b/src/citra_qt/configuration/configure_audio.cpp @@ -19,6 +19,10 @@ ConfigureAudio::ConfigureAudio(QWidget* parent) ui->output_sink_combo_box->addItem(sink_detail.id); } + connect(ui->volume_slider, &QSlider::valueChanged, [this] { + ui->volume_indicator->setText(tr("%1 %").arg(ui->volume_slider->sliderPosition())); + }); + this->setConfiguration(); connect(ui->output_sink_combo_box, static_cast(&QComboBox::currentIndexChanged), this, @@ -51,6 +55,9 @@ void ConfigureAudio::setConfiguration() { } } ui->audio_device_combo_box->setCurrentIndex(new_device_index); + + ui->volume_slider->setValue(Settings::values.volume * ui->volume_slider->maximum()); + ui->volume_indicator->setText(tr("%1 %").arg(ui->volume_slider->sliderPosition())); } void ConfigureAudio::applyConfiguration() { @@ -61,6 +68,8 @@ void ConfigureAudio::applyConfiguration() { Settings::values.audio_device_id = ui->audio_device_combo_box->itemText(ui->audio_device_combo_box->currentIndex()) .toStdString(); + Settings::values.volume = + static_cast(ui->volume_slider->sliderPosition()) / ui->volume_slider->maximum(); } void ConfigureAudio::updateAudioDevices(int sink_index) { diff --git a/src/citra_qt/configuration/configure_audio.ui b/src/citra_qt/configuration/configure_audio.ui index dd870eb619..83915622c2 100644 --- a/src/citra_qt/configuration/configure_audio.ui +++ b/src/citra_qt/configuration/configure_audio.ui @@ -1,11 +1,18 @@ - - + ConfigureAudio + + + 0 + 0 + 188 + 246 + + - + Audio @@ -13,39 +20,99 @@ - + Output Engine: - - + - - Enable audio stretching - This post-processing effect adjusts audio speed to match emulation speed and helps prevent audio stutter. This however increases audio latency. + + Enable audio stretching + - + Audio Device: - + + + + + + + + 0 + + + + + Volume: + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + 100 + + + 10 + + + Qt::Horizontal + + + + + + + + 32 + 0 + + + + 0 % + + + Qt::AlignCenter + @@ -60,14 +127,14 @@ - 20 - 40 + 167 + 55 - - + + diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index f436568a8b..0adbabeeb9 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -345,13 +345,11 @@ void Module::Interface::GetGyroscopeLowCalibrateParam(Kernel::HLERequestContext& void Module::Interface::GetSoundVolume(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx, 0x17, 0, 0}; - const u8 volume = 0x3F; // TODO(purpasmart): Find out if this is the max value for the volume + const u8 volume = static_cast(0x3F * Settings::values.volume); IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); rb.Push(RESULT_SUCCESS); rb.Push(volume); - - LOG_WARNING(Service_HID, "(STUBBED) called"); } Module::Interface::Interface(std::shared_ptr hid, const char* name, u32 max_session) diff --git a/src/core/settings.h b/src/core/settings.h index af56e55994..0efbeb6d2c 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -139,6 +139,7 @@ struct Values { std::string sink_id; bool enable_audio_stretching; std::string audio_device_id; + float volume; // Camera std::array camera_name;