summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar bunnei2016-04-30 03:49:11 -0400
committerGravatar bunnei2016-04-30 03:49:11 -0400
commitc1f0044a4b10bdff45464e5957f7950a6059d0c9 (patch)
treed9b4673f92da936ce763148f70b82bc7401dd968
parentMerge pull request #1650 from JamePeng/update-the-ndm-code (diff)
parentAudio: Add sink selection to configuration files (diff)
downloadyuzu-c1f0044a4b10bdff45464e5957f7950a6059d0c9.tar.gz
yuzu-c1f0044a4b10bdff45464e5957f7950a6059d0c9.tar.xz
yuzu-c1f0044a4b10bdff45464e5957f7950a6059d0c9.zip
Merge pull request #1729 from MerryMage/null-sink
Audio Config: Implement null sink and implement sink configuration
Diffstat (limited to '')
-rw-r--r--src/audio_core/CMakeLists.txt3
-rw-r--r--src/audio_core/audio_core.cpp33
-rw-r--r--src/audio_core/audio_core.h5
-rw-r--r--src/audio_core/hle/dsp.cpp9
-rw-r--r--src/audio_core/hle/dsp.h11
-rw-r--r--src/audio_core/null_sink.h29
-rw-r--r--src/audio_core/sink_details.cpp18
-rw-r--r--src/audio_core/sink_details.h27
-rw-r--r--src/citra/config.cpp3
-rw-r--r--src/citra/default_ini.h5
-rw-r--r--src/citra_qt/config.cpp8
-rw-r--r--src/core/settings.cpp5
-rw-r--r--src/core/settings.h3
13 files changed, 155 insertions, 4 deletions
diff --git a/src/audio_core/CMakeLists.txt b/src/audio_core/CMakeLists.txt
index a965af291..5a2747e78 100644
--- a/src/audio_core/CMakeLists.txt
+++ b/src/audio_core/CMakeLists.txt
@@ -5,6 +5,7 @@ set(SRCS
5 hle/filter.cpp 5 hle/filter.cpp
6 hle/pipe.cpp 6 hle/pipe.cpp
7 interpolate.cpp 7 interpolate.cpp
8 sink_details.cpp
8 ) 9 )
9 10
10set(HEADERS 11set(HEADERS
@@ -15,7 +16,9 @@ set(HEADERS
15 hle/filter.h 16 hle/filter.h
16 hle/pipe.h 17 hle/pipe.h
17 interpolate.h 18 interpolate.h
19 null_sink.h
18 sink.h 20 sink.h
21 sink_details.h
19 ) 22 )
20 23
21include_directories(../../externals/soundtouch/include) 24include_directories(../../externals/soundtouch/include)
diff --git a/src/audio_core/audio_core.cpp b/src/audio_core/audio_core.cpp
index cbe869a04..d42249ebd 100644
--- a/src/audio_core/audio_core.cpp
+++ b/src/audio_core/audio_core.cpp
@@ -2,9 +2,15 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <memory>
6#include <string>
7
5#include "audio_core/audio_core.h" 8#include "audio_core/audio_core.h"
6#include "audio_core/hle/dsp.h" 9#include "audio_core/hle/dsp.h"
7#include "audio_core/hle/pipe.h" 10#include "audio_core/hle/pipe.h"
11#include "audio_core/null_sink.h"
12#include "audio_core/sink.h"
13#include "audio_core/sink_details.h"
8 14
9#include "core/core_timing.h" 15#include "core/core_timing.h"
10#include "core/hle/kernel/vm_manager.h" 16#include "core/hle/kernel/vm_manager.h"
@@ -28,7 +34,6 @@ static void AudioTickCallback(u64 /*userdata*/, int cycles_late) {
28 CoreTiming::ScheduleEvent(audio_frame_ticks - cycles_late, tick_event); 34 CoreTiming::ScheduleEvent(audio_frame_ticks - cycles_late, tick_event);
29} 35}
30 36
31/// Initialise Audio
32void Init() { 37void Init() {
33 DSP::HLE::Init(); 38 DSP::HLE::Init();
34 39
@@ -36,7 +41,6 @@ void Init() {
36 CoreTiming::ScheduleEvent(audio_frame_ticks, tick_event); 41 CoreTiming::ScheduleEvent(audio_frame_ticks, tick_event);
37} 42}
38 43
39/// Add DSP address spaces to Process's address space.
40void AddAddressSpace(Kernel::VMManager& address_space) { 44void AddAddressSpace(Kernel::VMManager& address_space) {
41 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(); 45 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();
42 address_space.Reprotect(r0_vma, Kernel::VMAPermission::ReadWrite); 46 address_space.Reprotect(r0_vma, Kernel::VMAPermission::ReadWrite);
@@ -45,10 +49,31 @@ void AddAddressSpace(Kernel::VMManager& address_space) {
45 address_space.Reprotect(r1_vma, Kernel::VMAPermission::ReadWrite); 49 address_space.Reprotect(r1_vma, Kernel::VMAPermission::ReadWrite);
46} 50}
47 51
48/// Shutdown Audio 52void SelectSink(std::string sink_id) {
53 if (sink_id == "auto") {
54 // Auto-select.
55 // g_sink_details is ordered in terms of desirability, with the best choice at the front.
56 const auto& sink_detail = g_sink_details.front();
57 DSP::HLE::SetSink(sink_detail.factory());
58 return;
59 }
60
61 auto iter = std::find_if(g_sink_details.begin(), g_sink_details.end(), [sink_id](const auto& sink_detail) {
62 return sink_detail.id == sink_id;
63 });
64
65 if (iter == g_sink_details.end()) {
66 LOG_ERROR(Audio, "AudioCore::SelectSink given invalid sink_id");
67 DSP::HLE::SetSink(std::make_unique<NullSink>());
68 return;
69 }
70
71 DSP::HLE::SetSink(iter->factory());
72}
73
49void Shutdown() { 74void Shutdown() {
50 CoreTiming::UnscheduleEvent(tick_event, 0); 75 CoreTiming::UnscheduleEvent(tick_event, 0);
51 DSP::HLE::Shutdown(); 76 DSP::HLE::Shutdown();
52} 77}
53 78
54} //namespace 79} // namespace AudioCore
diff --git a/src/audio_core/audio_core.h b/src/audio_core/audio_core.h
index b349895ea..f618361f3 100644
--- a/src/audio_core/audio_core.h
+++ b/src/audio_core/audio_core.h
@@ -4,6 +4,8 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <string>
8
7namespace Kernel { 9namespace Kernel {
8class VMManager; 10class VMManager;
9} 11}
@@ -18,6 +20,9 @@ void Init();
18/// Add DSP address spaces to a Process. 20/// Add DSP address spaces to a Process.
19void AddAddressSpace(Kernel::VMManager& vm_manager); 21void AddAddressSpace(Kernel::VMManager& vm_manager);
20 22
23/// Select the sink to use based on sink id.
24void SelectSink(std::string sink_id);
25
21/// Shutdown Audio Core 26/// Shutdown Audio Core
22void Shutdown(); 27void Shutdown();
23 28
diff --git a/src/audio_core/hle/dsp.cpp b/src/audio_core/hle/dsp.cpp
index 5759a5b9e..4d44bd2d9 100644
--- a/src/audio_core/hle/dsp.cpp
+++ b/src/audio_core/hle/dsp.cpp
@@ -2,8 +2,11 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <memory>
6
5#include "audio_core/hle/dsp.h" 7#include "audio_core/hle/dsp.h"
6#include "audio_core/hle/pipe.h" 8#include "audio_core/hle/pipe.h"
9#include "audio_core/sink.h"
7 10
8namespace DSP { 11namespace DSP {
9namespace HLE { 12namespace HLE {
@@ -35,6 +38,8 @@ static SharedMemory& WriteRegion() {
35 return g_regions[1 - CurrentRegionIndex()]; 38 return g_regions[1 - CurrentRegionIndex()];
36} 39}
37 40
41static std::unique_ptr<AudioCore::Sink> sink;
42
38void Init() { 43void Init() {
39 DSP::HLE::ResetPipes(); 44 DSP::HLE::ResetPipes();
40} 45}
@@ -46,5 +51,9 @@ bool Tick() {
46 return true; 51 return true;
47} 52}
48 53
54void SetSink(std::unique_ptr<AudioCore::Sink> sink_) {
55 sink = std::move(sink_);
56}
57
49} // namespace HLE 58} // namespace HLE
50} // namespace DSP 59} // namespace DSP
diff --git a/src/audio_core/hle/dsp.h b/src/audio_core/hle/dsp.h
index f0f125284..4f2410c27 100644
--- a/src/audio_core/hle/dsp.h
+++ b/src/audio_core/hle/dsp.h
@@ -6,6 +6,7 @@
6 6
7#include <array> 7#include <array>
8#include <cstddef> 8#include <cstddef>
9#include <memory>
9#include <type_traits> 10#include <type_traits>
10 11
11#include "audio_core/hle/common.h" 12#include "audio_core/hle/common.h"
@@ -15,6 +16,10 @@
15#include "common/common_types.h" 16#include "common/common_types.h"
16#include "common/swap.h" 17#include "common/swap.h"
17 18
19namespace AudioCore {
20class Sink;
21}
22
18namespace DSP { 23namespace DSP {
19namespace HLE { 24namespace HLE {
20 25
@@ -535,5 +540,11 @@ void Shutdown();
535 */ 540 */
536bool Tick(); 541bool Tick();
537 542
543/**
544 * Set the output sink. This must be called before calling Tick().
545 * @param sink The sink to which audio will be output to.
546 */
547void SetSink(std::unique_ptr<AudioCore::Sink> sink);
548
538} // namespace HLE 549} // namespace HLE
539} // namespace DSP 550} // namespace DSP
diff --git a/src/audio_core/null_sink.h b/src/audio_core/null_sink.h
new file mode 100644
index 000000000..faf0ee4e1
--- /dev/null
+++ b/src/audio_core/null_sink.h
@@ -0,0 +1,29 @@
1// Copyright 2016 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <cstddef>
8
9#include "audio_core/audio_core.h"
10#include "audio_core/sink.h"
11
12namespace AudioCore {
13
14class NullSink final : public Sink {
15public:
16 ~NullSink() override = default;
17
18 unsigned int GetNativeSampleRate() const override {
19 return native_sample_rate;
20 }
21
22 void EnqueueSamples(const std::vector<s16>&) override {}
23
24 size_t SamplesInQueue() const override {
25 return 0;
26 }
27};
28
29} // namespace AudioCore
diff --git a/src/audio_core/sink_details.cpp b/src/audio_core/sink_details.cpp
new file mode 100644
index 000000000..d2cc74103
--- /dev/null
+++ b/src/audio_core/sink_details.cpp
@@ -0,0 +1,18 @@
1// Copyright 2016 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <memory>
6#include <vector>
7
8#include "audio_core/null_sink.h"
9#include "audio_core/sink_details.h"
10
11namespace AudioCore {
12
13// g_sink_details is ordered in terms of desirability, with the best choice at the top.
14const std::vector<SinkDetails> g_sink_details = {
15 { "null", []() { return std::make_unique<NullSink>(); } },
16};
17
18} // namespace AudioCore
diff --git a/src/audio_core/sink_details.h b/src/audio_core/sink_details.h
new file mode 100644
index 000000000..4b30cf835
--- /dev/null
+++ b/src/audio_core/sink_details.h
@@ -0,0 +1,27 @@
1// Copyright 2016 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <functional>
8#include <memory>
9#include <vector>
10
11namespace AudioCore {
12
13class Sink;
14
15struct SinkDetails {
16 SinkDetails(const char* id_, std::function<std::unique_ptr<Sink>()> factory_)
17 : id(id_), factory(factory_) {}
18
19 /// Name for this sink.
20 const char* id;
21 /// A method to call to construct an instance of this type of sink.
22 std::function<std::unique_ptr<Sink>()> factory;
23};
24
25extern const std::vector<SinkDetails> g_sink_details;
26
27} // namespace AudioCore
diff --git a/src/citra/config.cpp b/src/citra/config.cpp
index 9e2ecd307..0d17c80bf 100644
--- a/src/citra/config.cpp
+++ b/src/citra/config.cpp
@@ -71,6 +71,9 @@ void Config::ReadValues() {
71 Settings::values.bg_green = (float)sdl2_config->GetReal("Renderer", "bg_green", 1.0); 71 Settings::values.bg_green = (float)sdl2_config->GetReal("Renderer", "bg_green", 1.0);
72 Settings::values.bg_blue = (float)sdl2_config->GetReal("Renderer", "bg_blue", 1.0); 72 Settings::values.bg_blue = (float)sdl2_config->GetReal("Renderer", "bg_blue", 1.0);
73 73
74 // Audio
75 Settings::values.sink_id = sdl2_config->Get("Audio", "output_engine", "auto");
76
74 // Data Storage 77 // Data Storage
75 Settings::values.use_virtual_sd = sdl2_config->GetBoolean("Data Storage", "use_virtual_sd", true); 78 Settings::values.use_virtual_sd = sdl2_config->GetBoolean("Data Storage", "use_virtual_sd", true);
76 79
diff --git a/src/citra/default_ini.h b/src/citra/default_ini.h
index 1f1aa716b..0e6171736 100644
--- a/src/citra/default_ini.h
+++ b/src/citra/default_ini.h
@@ -56,6 +56,11 @@ bg_red =
56bg_blue = 56bg_blue =
57bg_green = 57bg_green =
58 58
59[Audio]
60# Which audio output engine to use.
61# auto (default): Auto-select, null: No audio output
62output_engine =
63
59[Data Storage] 64[Data Storage]
60# Whether to create a virtual SD card. 65# Whether to create a virtual SD card.
61# 1 (default): Yes, 0: No 66# 1 (default): Yes, 0: No
diff --git a/src/citra_qt/config.cpp b/src/citra_qt/config.cpp
index 7dc61fe40..b5bb75537 100644
--- a/src/citra_qt/config.cpp
+++ b/src/citra_qt/config.cpp
@@ -52,6 +52,10 @@ void Config::ReadValues() {
52 Settings::values.bg_blue = qt_config->value("bg_blue", 1.0).toFloat(); 52 Settings::values.bg_blue = qt_config->value("bg_blue", 1.0).toFloat();
53 qt_config->endGroup(); 53 qt_config->endGroup();
54 54
55 qt_config->beginGroup("Audio");
56 Settings::values.sink_id = qt_config->value("output_engine", "auto").toString().toStdString();
57 qt_config->endGroup();
58
55 qt_config->beginGroup("Data Storage"); 59 qt_config->beginGroup("Data Storage");
56 Settings::values.use_virtual_sd = qt_config->value("use_virtual_sd", true).toBool(); 60 Settings::values.use_virtual_sd = qt_config->value("use_virtual_sd", true).toBool();
57 qt_config->endGroup(); 61 qt_config->endGroup();
@@ -138,6 +142,10 @@ void Config::SaveValues() {
138 qt_config->setValue("bg_blue", (double)Settings::values.bg_blue); 142 qt_config->setValue("bg_blue", (double)Settings::values.bg_blue);
139 qt_config->endGroup(); 143 qt_config->endGroup();
140 144
145 qt_config->beginGroup("Audio");
146 qt_config->setValue("output_engine", QString::fromStdString(Settings::values.sink_id));
147 qt_config->endGroup();
148
141 qt_config->beginGroup("Data Storage"); 149 qt_config->beginGroup("Data Storage");
142 qt_config->setValue("use_virtual_sd", Settings::values.use_virtual_sd); 150 qt_config->setValue("use_virtual_sd", Settings::values.use_virtual_sd);
143 qt_config->endGroup(); 151 qt_config->endGroup();
diff --git a/src/core/settings.cpp b/src/core/settings.cpp
index eaf5c8461..77261eafe 100644
--- a/src/core/settings.cpp
+++ b/src/core/settings.cpp
@@ -4,6 +4,8 @@
4 4
5#include "settings.h" 5#include "settings.h"
6 6
7#include "audio_core/audio_core.h"
8
7#include "core/gdbstub/gdbstub.h" 9#include "core/gdbstub/gdbstub.h"
8 10
9#include "video_core/video_core.h" 11#include "video_core/video_core.h"
@@ -20,6 +22,9 @@ void Apply() {
20 VideoCore::g_hw_renderer_enabled = values.use_hw_renderer; 22 VideoCore::g_hw_renderer_enabled = values.use_hw_renderer;
21 VideoCore::g_shader_jit_enabled = values.use_shader_jit; 23 VideoCore::g_shader_jit_enabled = values.use_shader_jit;
22 VideoCore::g_scaled_resolution_enabled = values.use_scaled_resolution; 24 VideoCore::g_scaled_resolution_enabled = values.use_scaled_resolution;
25
26 AudioCore::SelectSink(values.sink_id);
27
23} 28}
24 29
25} // namespace 30} // namespace
diff --git a/src/core/settings.h b/src/core/settings.h
index d620d8461..04c0a47f9 100644
--- a/src/core/settings.h
+++ b/src/core/settings.h
@@ -63,6 +63,9 @@ struct Values {
63 63
64 std::string log_filter; 64 std::string log_filter;
65 65
66 // Audio
67 std::string sink_id;
68
66 // Debugging 69 // Debugging
67 bool use_gdbstub; 70 bool use_gdbstub;
68 u16 gdbstub_port; 71 u16 gdbstub_port;