diff --git a/src/audio_core/audio_core.cpp b/src/audio_core/audio_core.cpp index d42249ebd..76839cdf8 100644 --- a/src/audio_core/audio_core.cpp +++ b/src/audio_core/audio_core.cpp @@ -71,6 +71,13 @@ void SelectSink(std::string sink_id) { DSP::HLE::SetSink(iter->factory()); } +void SelectDevice(std::string device_id){ + if (device_id == "") { + LOG_ERROR(Audio, "AudioCore::SelectDevice given invalid device_id"); + return; + } +} + void Shutdown() { CoreTiming::UnscheduleEvent(tick_event, 0); DSP::HLE::Shutdown(); diff --git a/src/audio_core/audio_core.h b/src/audio_core/audio_core.h index f618361f3..bd8622411 100644 --- a/src/audio_core/audio_core.h +++ b/src/audio_core/audio_core.h @@ -23,6 +23,9 @@ void AddAddressSpace(Kernel::VMManager& vm_manager); /// Select the sink to use based on sink id. void SelectSink(std::string sink_id); +/// Select the device to use based on device id. +void SelectDevice(std::string device_id); + /// Shutdown Audio Core void Shutdown(); diff --git a/src/audio_core/null_sink.h b/src/audio_core/null_sink.h index faf0ee4e1..619302d37 100644 --- a/src/audio_core/null_sink.h +++ b/src/audio_core/null_sink.h @@ -5,6 +5,7 @@ #pragma once #include +#include #include "audio_core/audio_core.h" #include "audio_core/sink.h" @@ -24,6 +25,12 @@ public: size_t SamplesInQueue() const override { return 0; } + + void SetDevice(int device_id) override {} + + std::map* GetDeviceMap() override { + return nullptr; + } }; } // namespace AudioCore diff --git a/src/audio_core/sdl2_sink.cpp b/src/audio_core/sdl2_sink.cpp index dc75c04ee..74bb1f212 100644 --- a/src/audio_core/sdl2_sink.cpp +++ b/src/audio_core/sdl2_sink.cpp @@ -10,6 +10,8 @@ #include "audio_core/audio_core.h" #include "audio_core/sdl2_sink.h" +#include "core/settings.h" + #include "common/assert.h" #include "common/logging/log.h" #include @@ -45,10 +47,28 @@ SDL2Sink::SDL2Sink() : impl(std::make_unique()) { SDL_AudioSpec obtained_audiospec; SDL_zero(obtained_audiospec); - impl->audio_device_id = SDL_OpenAudioDevice(nullptr, false, &desired_audiospec, &obtained_audiospec, 0); - if (impl->audio_device_id <= 0) { - LOG_CRITICAL(Audio_Sink, "SDL_OpenAudioDevice failed"); - return; + int device_count = SDL_GetNumAudioDevices(0); + device_map.clear(); + for (int i = 0; i < device_count; ++i) { + device_map[i] = SDL_GetAudioDeviceName(i, 0); + } + + if (device_count < 1 || + Settings::values.audio_device_id == "auto" || + Settings::values.audio_device_id == "") { + impl->audio_device_id = SDL_OpenAudioDevice(nullptr, false, &desired_audiospec, &obtained_audiospec, 0); + if (impl->audio_device_id <= 0) { + LOG_CRITICAL(Audio_Sink, "SDL_OpenAudioDevice failed"); + return; + } + } + else + { + impl->audio_device_id = SDL_OpenAudioDevice(device_map[device_id].c_str(), false, &desired_audiospec, &obtained_audiospec, 0); + if (impl->audio_device_id <= 0) { + LOG_CRITICAL(Audio_Sink, "SDL_OpenAudioDevice failed"); + return; + } } impl->sample_rate = obtained_audiospec.freq; @@ -99,6 +119,14 @@ size_t SDL2Sink::SamplesInQueue() const { return total_size; } +void SDL2Sink::SetDevice(int _device_id) { + this->device_id = _device_id; +} + +std::map* SDL2Sink::GetDeviceMap() { + return &device_map; +} + void SDL2Sink::Impl::Callback(void* impl_, u8* buffer, int buffer_size_in_bytes) { Impl* impl = reinterpret_cast(impl_); diff --git a/src/audio_core/sdl2_sink.h b/src/audio_core/sdl2_sink.h index 0f296b673..5199529fe 100644 --- a/src/audio_core/sdl2_sink.h +++ b/src/audio_core/sdl2_sink.h @@ -6,6 +6,7 @@ #include #include +#include #include "audio_core/sink.h" @@ -22,9 +23,16 @@ public: size_t SamplesInQueue() const override; + std::map* GetDeviceMap(); + void SetDevice(int _device_id); + private: struct Impl; std::unique_ptr impl; + int device_id; + std::map device_map; }; +extern const std::map g_device_map; + } // namespace AudioCore diff --git a/src/audio_core/sink.h b/src/audio_core/sink.h index 1c881c3d2..23f621193 100644 --- a/src/audio_core/sink.h +++ b/src/audio_core/sink.h @@ -5,6 +5,7 @@ #pragma once #include +#include #include "common/common_types.h" @@ -29,6 +30,9 @@ public: /// Samples enqueued that have not been played yet. virtual std::size_t SamplesInQueue() const = 0; + + virtual void SetDevice(int device_id) = 0; + virtual std::map* GetDeviceMap() = 0; }; } // namespace diff --git a/src/citra_qt/configure_audio.cpp b/src/citra_qt/configure_audio.cpp index cedfa2f2a..25e13a051 100644 --- a/src/citra_qt/configure_audio.cpp +++ b/src/citra_qt/configure_audio.cpp @@ -21,6 +21,12 @@ ConfigureAudio::ConfigureAudio(QWidget* parent) : ui->output_sink_combo_box->addItem(sink_detail.id); } + ui->audio_device_combo_box->clear(); + ui->audio_device_combo_box->addItem("auto"); + //for (const auto& device : AudioCore:) { + // ui->audio_device_combo_box->addItem(device.second.c_str()); + //} + this->setConfiguration(); } @@ -36,9 +42,20 @@ void ConfigureAudio::setConfiguration() { } } ui->output_sink_combo_box->setCurrentIndex(new_sink_index); + + + int new_device_index = -1; + for (int index = 0; index < ui->audio_device_combo_box->count(); index++) { + if (ui->audio_device_combo_box->itemText(index).toStdString() == Settings::values.audio_device_id) { + new_device_index = index; + break; + } + } + ui->audio_device_combo_box->setCurrentIndex(new_sink_index); } void ConfigureAudio::applyConfiguration() { Settings::values.sink_id = ui->output_sink_combo_box->itemText(ui->output_sink_combo_box->currentIndex()).toStdString(); + Settings::values.audio_device_id = ui->audio_device_combo_box->itemText(ui->audio_device_combo_box->currentIndex()).toStdString(); Settings::Apply(); } diff --git a/src/citra_qt/configure_audio.ui b/src/citra_qt/configure_audio.ui index d7f6946ca..bccaa1db5 100644 --- a/src/citra_qt/configure_audio.ui +++ b/src/citra_qt/configure_audio.ui @@ -25,6 +25,21 @@ + + + + + + Audio Device: + + + + + + + + + diff --git a/src/core/settings.cpp b/src/core/settings.cpp index 77261eafe..f4ee129ee 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp @@ -24,7 +24,7 @@ void Apply() { VideoCore::g_scaled_resolution_enabled = values.use_scaled_resolution; AudioCore::SelectSink(values.sink_id); - + AudioCore::SelectDevice(values.audio_device_id); } } // namespace diff --git a/src/core/settings.h b/src/core/settings.h index f95e62390..3ae14f008 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -6,6 +6,7 @@ #include #include +#include #include "common/common_types.h" @@ -81,6 +82,7 @@ struct Values { // Audio std::string sink_id; + std::string audio_device_id; // Debugging bool use_gdbstub;