Merge pull request #1729 from MerryMage/null-sink
Audio Config: Implement null sink and implement sink configuration
This commit is contained in:
		| @@ -5,6 +5,7 @@ set(SRCS | ||||
|             hle/filter.cpp | ||||
|             hle/pipe.cpp | ||||
|             interpolate.cpp | ||||
|             sink_details.cpp | ||||
|             ) | ||||
|  | ||||
| set(HEADERS | ||||
| @@ -15,7 +16,9 @@ set(HEADERS | ||||
|             hle/filter.h | ||||
|             hle/pipe.h | ||||
|             interpolate.h | ||||
|             null_sink.h | ||||
|             sink.h | ||||
|             sink_details.h | ||||
|             ) | ||||
|  | ||||
| include_directories(../../externals/soundtouch/include) | ||||
|   | ||||
| @@ -2,9 +2,15 @@ | ||||
| // Licensed under GPLv2 or any later version | ||||
| // Refer to the license.txt file included. | ||||
|  | ||||
| #include <memory> | ||||
| #include <string> | ||||
|  | ||||
| #include "audio_core/audio_core.h" | ||||
| #include "audio_core/hle/dsp.h" | ||||
| #include "audio_core/hle/pipe.h" | ||||
| #include "audio_core/null_sink.h" | ||||
| #include "audio_core/sink.h" | ||||
| #include "audio_core/sink_details.h" | ||||
|  | ||||
| #include "core/core_timing.h" | ||||
| #include "core/hle/kernel/vm_manager.h" | ||||
| @@ -28,7 +34,6 @@ static void AudioTickCallback(u64 /*userdata*/, int cycles_late) { | ||||
|     CoreTiming::ScheduleEvent(audio_frame_ticks - cycles_late, tick_event); | ||||
| } | ||||
|  | ||||
| /// Initialise Audio | ||||
| void Init() { | ||||
|     DSP::HLE::Init(); | ||||
|  | ||||
| @@ -36,7 +41,6 @@ void Init() { | ||||
|     CoreTiming::ScheduleEvent(audio_frame_ticks, tick_event); | ||||
| } | ||||
|  | ||||
| /// Add DSP address spaces to Process's address space. | ||||
| void AddAddressSpace(Kernel::VMManager& address_space) { | ||||
|     auto r0_vma = address_space.MapBackingMemory(DSP::HLE::region0_base, reinterpret_cast<u8*>(&DSP::HLE::g_regions[0]), sizeof(DSP::HLE::SharedMemory), Kernel::MemoryState::IO).MoveFrom(); | ||||
|     address_space.Reprotect(r0_vma, Kernel::VMAPermission::ReadWrite); | ||||
| @@ -45,10 +49,31 @@ void AddAddressSpace(Kernel::VMManager& address_space) { | ||||
|     address_space.Reprotect(r1_vma, Kernel::VMAPermission::ReadWrite); | ||||
| } | ||||
|  | ||||
| /// Shutdown Audio | ||||
| void SelectSink(std::string sink_id) { | ||||
|     if (sink_id == "auto") { | ||||
|         // Auto-select. | ||||
|         // g_sink_details is ordered in terms of desirability, with the best choice at the front. | ||||
|         const auto& sink_detail = g_sink_details.front(); | ||||
|         DSP::HLE::SetSink(sink_detail.factory()); | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     auto iter = std::find_if(g_sink_details.begin(), g_sink_details.end(), [sink_id](const auto& sink_detail) { | ||||
|         return sink_detail.id == sink_id; | ||||
|     }); | ||||
|  | ||||
|     if (iter == g_sink_details.end()) { | ||||
|         LOG_ERROR(Audio, "AudioCore::SelectSink given invalid sink_id"); | ||||
|         DSP::HLE::SetSink(std::make_unique<NullSink>()); | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     DSP::HLE::SetSink(iter->factory()); | ||||
| } | ||||
|  | ||||
| void Shutdown() { | ||||
|     CoreTiming::UnscheduleEvent(tick_event, 0); | ||||
|     DSP::HLE::Shutdown(); | ||||
| } | ||||
|  | ||||
| } //namespace | ||||
| } // namespace AudioCore | ||||
|   | ||||
| @@ -4,6 +4,8 @@ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <string> | ||||
|  | ||||
| namespace Kernel { | ||||
| class VMManager; | ||||
| } | ||||
| @@ -18,6 +20,9 @@ void Init(); | ||||
| /// Add DSP address spaces to a Process. | ||||
| void AddAddressSpace(Kernel::VMManager& vm_manager); | ||||
|  | ||||
| /// Select the sink to use based on sink id. | ||||
| void SelectSink(std::string sink_id); | ||||
|  | ||||
| /// Shutdown Audio Core | ||||
| void Shutdown(); | ||||
|  | ||||
|   | ||||
| @@ -2,8 +2,11 @@ | ||||
| // Licensed under GPLv2 or any later version | ||||
| // Refer to the license.txt file included. | ||||
|  | ||||
| #include <memory> | ||||
|  | ||||
| #include "audio_core/hle/dsp.h" | ||||
| #include "audio_core/hle/pipe.h" | ||||
| #include "audio_core/sink.h" | ||||
|  | ||||
| namespace DSP { | ||||
| namespace HLE { | ||||
| @@ -35,6 +38,8 @@ static SharedMemory& WriteRegion() { | ||||
|     return g_regions[1 - CurrentRegionIndex()]; | ||||
| } | ||||
|  | ||||
| static std::unique_ptr<AudioCore::Sink> sink; | ||||
|  | ||||
| void Init() { | ||||
|     DSP::HLE::ResetPipes(); | ||||
| } | ||||
| @@ -46,5 +51,9 @@ bool Tick() { | ||||
|     return true; | ||||
| } | ||||
|  | ||||
| void SetSink(std::unique_ptr<AudioCore::Sink> sink_) { | ||||
|     sink = std::move(sink_); | ||||
| } | ||||
|  | ||||
| } // namespace HLE | ||||
| } // namespace DSP | ||||
|   | ||||
| @@ -6,6 +6,7 @@ | ||||
|  | ||||
| #include <array> | ||||
| #include <cstddef> | ||||
| #include <memory> | ||||
| #include <type_traits> | ||||
|  | ||||
| #include "audio_core/hle/common.h" | ||||
| @@ -15,6 +16,10 @@ | ||||
| #include "common/common_types.h" | ||||
| #include "common/swap.h" | ||||
|  | ||||
| namespace AudioCore { | ||||
| class Sink; | ||||
| } | ||||
|  | ||||
| namespace DSP { | ||||
| namespace HLE { | ||||
|  | ||||
| @@ -535,5 +540,11 @@ void Shutdown(); | ||||
|  */ | ||||
| bool Tick(); | ||||
|  | ||||
| /** | ||||
|  * Set the output sink. This must be called before calling Tick(). | ||||
|  * @param sink The sink to which audio will be output to. | ||||
|  */ | ||||
| void SetSink(std::unique_ptr<AudioCore::Sink> sink); | ||||
|  | ||||
| } // namespace HLE | ||||
| } // namespace DSP | ||||
|   | ||||
							
								
								
									
										29
									
								
								src/audio_core/null_sink.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/audio_core/null_sink.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| // Copyright 2016 Citra Emulator Project | ||||
| // Licensed under GPLv2 or any later version | ||||
| // Refer to the license.txt file included. | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <cstddef> | ||||
|  | ||||
| #include "audio_core/audio_core.h" | ||||
| #include "audio_core/sink.h" | ||||
|  | ||||
| namespace AudioCore { | ||||
|  | ||||
| class NullSink final : public Sink { | ||||
| public: | ||||
|     ~NullSink() override = default; | ||||
|  | ||||
|     unsigned int GetNativeSampleRate() const override { | ||||
|         return native_sample_rate; | ||||
|     } | ||||
|  | ||||
|     void EnqueueSamples(const std::vector<s16>&) override {} | ||||
|  | ||||
|     size_t SamplesInQueue() const override { | ||||
|         return 0; | ||||
|     } | ||||
| }; | ||||
|  | ||||
| } // namespace AudioCore | ||||
							
								
								
									
										18
									
								
								src/audio_core/sink_details.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								src/audio_core/sink_details.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| // Copyright 2016 Citra Emulator Project | ||||
| // Licensed under GPLv2 or any later version | ||||
| // Refer to the license.txt file included. | ||||
|  | ||||
| #include <memory> | ||||
| #include <vector> | ||||
|  | ||||
| #include "audio_core/null_sink.h" | ||||
| #include "audio_core/sink_details.h" | ||||
|  | ||||
| namespace AudioCore { | ||||
|  | ||||
| // g_sink_details is ordered in terms of desirability, with the best choice at the top. | ||||
| const std::vector<SinkDetails> g_sink_details = { | ||||
|     { "null", []() { return std::make_unique<NullSink>(); } }, | ||||
| }; | ||||
|  | ||||
| } // namespace AudioCore | ||||
							
								
								
									
										27
									
								
								src/audio_core/sink_details.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								src/audio_core/sink_details.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | ||||
| // Copyright 2016 Citra Emulator Project | ||||
| // Licensed under GPLv2 or any later version | ||||
| // Refer to the license.txt file included. | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <functional> | ||||
| #include <memory> | ||||
| #include <vector> | ||||
|  | ||||
| namespace AudioCore { | ||||
|  | ||||
| class Sink; | ||||
|  | ||||
| struct SinkDetails { | ||||
|     SinkDetails(const char* id_, std::function<std::unique_ptr<Sink>()> factory_) | ||||
|         : id(id_), factory(factory_) {} | ||||
|  | ||||
|     /// Name for this sink. | ||||
|     const char* id; | ||||
|     /// A method to call to construct an instance of this type of sink. | ||||
|     std::function<std::unique_ptr<Sink>()> factory; | ||||
| }; | ||||
|  | ||||
| extern const std::vector<SinkDetails> g_sink_details; | ||||
|  | ||||
| } // namespace AudioCore | ||||
| @@ -71,6 +71,9 @@ void Config::ReadValues() { | ||||
|     Settings::values.bg_green = (float)sdl2_config->GetReal("Renderer", "bg_green", 1.0); | ||||
|     Settings::values.bg_blue  = (float)sdl2_config->GetReal("Renderer", "bg_blue",  1.0); | ||||
|  | ||||
|     // Audio | ||||
|     Settings::values.sink_id = sdl2_config->Get("Audio", "output_engine", "auto"); | ||||
|  | ||||
|     // Data Storage | ||||
|     Settings::values.use_virtual_sd = sdl2_config->GetBoolean("Data Storage", "use_virtual_sd", true); | ||||
|  | ||||
|   | ||||
| @@ -56,6 +56,11 @@ bg_red = | ||||
| bg_blue = | ||||
| bg_green = | ||||
|  | ||||
| [Audio] | ||||
| # Which audio output engine to use. | ||||
| # auto (default): Auto-select, null: No audio output | ||||
| output_engine = | ||||
|  | ||||
| [Data Storage] | ||||
| # Whether to create a virtual SD card. | ||||
| # 1 (default): Yes, 0: No | ||||
|   | ||||
| @@ -52,6 +52,10 @@ void Config::ReadValues() { | ||||
|     Settings::values.bg_blue  = qt_config->value("bg_blue",  1.0).toFloat(); | ||||
|     qt_config->endGroup(); | ||||
|  | ||||
|     qt_config->beginGroup("Audio"); | ||||
|     Settings::values.sink_id = qt_config->value("output_engine", "auto").toString().toStdString(); | ||||
|     qt_config->endGroup(); | ||||
|  | ||||
|     qt_config->beginGroup("Data Storage"); | ||||
|     Settings::values.use_virtual_sd = qt_config->value("use_virtual_sd", true).toBool(); | ||||
|     qt_config->endGroup(); | ||||
| @@ -138,6 +142,10 @@ void Config::SaveValues() { | ||||
|     qt_config->setValue("bg_blue",  (double)Settings::values.bg_blue); | ||||
|     qt_config->endGroup(); | ||||
|  | ||||
|     qt_config->beginGroup("Audio"); | ||||
|     qt_config->setValue("output_engine", QString::fromStdString(Settings::values.sink_id)); | ||||
|     qt_config->endGroup(); | ||||
|  | ||||
|     qt_config->beginGroup("Data Storage"); | ||||
|     qt_config->setValue("use_virtual_sd", Settings::values.use_virtual_sd); | ||||
|     qt_config->endGroup(); | ||||
|   | ||||
| @@ -4,6 +4,8 @@ | ||||
|  | ||||
| #include "settings.h" | ||||
|  | ||||
| #include "audio_core/audio_core.h" | ||||
|  | ||||
| #include "core/gdbstub/gdbstub.h" | ||||
|  | ||||
| #include "video_core/video_core.h" | ||||
| @@ -20,6 +22,9 @@ void Apply() { | ||||
|     VideoCore::g_hw_renderer_enabled = values.use_hw_renderer; | ||||
|     VideoCore::g_shader_jit_enabled = values.use_shader_jit; | ||||
|     VideoCore::g_scaled_resolution_enabled = values.use_scaled_resolution; | ||||
|  | ||||
|     AudioCore::SelectSink(values.sink_id); | ||||
|  | ||||
| } | ||||
|  | ||||
| } // namespace | ||||
|   | ||||
| @@ -63,6 +63,9 @@ struct Values { | ||||
|  | ||||
|     std::string log_filter; | ||||
|  | ||||
|     // Audio | ||||
|     std::string sink_id; | ||||
|  | ||||
|     // Debugging | ||||
|     bool use_gdbstub; | ||||
|     u16 gdbstub_port; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 bunnei
					bunnei