summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbunnei <bunneidev@gmail.com>2018-07-28 19:40:50 +0200
committerbunnei <bunneidev@gmail.com>2018-07-31 03:45:24 +0200
commit9ef227e09d6e374008d9536935d01c11a6ca06bd (patch)
tree55a0169ab36ff521770a94a59b857063caf65f8b
parentaudio_core: Misc. improvements to stream/buffer/audio_out. (diff)
downloadyuzu-9ef227e09d6e374008d9536935d01c11a6ca06bd.tar
yuzu-9ef227e09d6e374008d9536935d01c11a6ca06bd.tar.gz
yuzu-9ef227e09d6e374008d9536935d01c11a6ca06bd.tar.bz2
yuzu-9ef227e09d6e374008d9536935d01c11a6ca06bd.tar.lz
yuzu-9ef227e09d6e374008d9536935d01c11a6ca06bd.tar.xz
yuzu-9ef227e09d6e374008d9536935d01c11a6ca06bd.tar.zst
yuzu-9ef227e09d6e374008d9536935d01c11a6ca06bd.zip
-rw-r--r--src/audio_core/CMakeLists.txt5
-rw-r--r--src/audio_core/null_sink.h27
-rw-r--r--src/audio_core/sink.h29
-rw-r--r--src/audio_core/sink_details.cpp38
-rw-r--r--src/audio_core/sink_details.h32
-rw-r--r--src/audio_core/sink_stream.h32
6 files changed, 163 insertions, 0 deletions
diff --git a/src/audio_core/CMakeLists.txt b/src/audio_core/CMakeLists.txt
index f00a55994..6bc8f586a 100644
--- a/src/audio_core/CMakeLists.txt
+++ b/src/audio_core/CMakeLists.txt
@@ -2,8 +2,13 @@ add_library(audio_core STATIC
audio_out.cpp
audio_out.h
buffer.h
+ null_sink.h
stream.cpp
stream.h
+ sink.h
+ sink_details.cpp
+ sink_details.h
+ sink_stream.h
)
create_target_directory_groups(audio_core)
diff --git a/src/audio_core/null_sink.h b/src/audio_core/null_sink.h
new file mode 100644
index 000000000..2e04438f7
--- /dev/null
+++ b/src/audio_core/null_sink.h
@@ -0,0 +1,27 @@
+// Copyright 2018 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "audio_core/sink.h"
+
+namespace AudioCore {
+
+class NullSink final : public Sink {
+public:
+ explicit NullSink(std::string){};
+ ~NullSink() override = default;
+
+ SinkStream& AcquireSinkStream(u32 /*sample_rate*/, u32 /*num_channels*/) override {
+ return null_sink_stream;
+ }
+
+private:
+ struct NullSinkStreamImpl final : SinkStream {
+ void EnqueueSamples(u32 /*num_channels*/, const s16* /*samples*/,
+ size_t /*sample_count*/) override {}
+ } null_sink_stream;
+};
+
+} // namespace AudioCore
diff --git a/src/audio_core/sink.h b/src/audio_core/sink.h
new file mode 100644
index 000000000..d1bb98c3d
--- /dev/null
+++ b/src/audio_core/sink.h
@@ -0,0 +1,29 @@
+// Copyright 2018 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <memory>
+
+#include "audio_core/sink_stream.h"
+#include "common/common_types.h"
+
+namespace AudioCore {
+
+constexpr char auto_device_name[] = "auto";
+
+/**
+ * This class is an interface for an audio sink. An audio sink accepts samples in stereo signed
+ * PCM16 format to be output. Sinks *do not* handle resampling and expect the correct sample rate.
+ * They are dumb outputs.
+ */
+class Sink {
+public:
+ virtual ~Sink() = default;
+ virtual SinkStream& AcquireSinkStream(u32 sample_rate, u32 num_channels) = 0;
+};
+
+using SinkPtr = std::unique_ptr<Sink>;
+
+} // namespace AudioCore
diff --git a/src/audio_core/sink_details.cpp b/src/audio_core/sink_details.cpp
new file mode 100644
index 000000000..6396d8065
--- /dev/null
+++ b/src/audio_core/sink_details.cpp
@@ -0,0 +1,38 @@
+// Copyright 2018 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <algorithm>
+#include <memory>
+#include <string>
+#include <vector>
+#include "audio_core/null_sink.h"
+#include "audio_core/sink_details.h"
+#include "common/logging/log.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 = {
+ SinkDetails{"null", &std::make_unique<NullSink, std::string>,
+ [] { return std::vector<std::string>{"null"}; }},
+};
+
+const SinkDetails& GetSinkDetails(std::string sink_id) {
+ 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 (sink_id == "auto" || iter == g_sink_details.end()) {
+ if (sink_id != "auto") {
+ LOG_ERROR(Audio, "AudioCore::SelectSink given invalid sink_id {}", sink_id);
+ }
+ // Auto-select.
+ // g_sink_details is ordered in terms of desirability, with the best choice at the front.
+ iter = g_sink_details.begin();
+ }
+
+ return *iter;
+}
+
+} // namespace AudioCore
diff --git a/src/audio_core/sink_details.h b/src/audio_core/sink_details.h
new file mode 100644
index 000000000..aa8aae1a9
--- /dev/null
+++ b/src/audio_core/sink_details.h
@@ -0,0 +1,32 @@
+// Copyright 2018 yuzu 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>(std::string)> factory_,
+ std::function<std::vector<std::string>()> list_devices_)
+ : id(id_), factory(factory_), list_devices(list_devices_) {}
+
+ /// 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>(std::string device_id)> factory;
+ /// A method to call to list available devices.
+ std::function<std::vector<std::string>()> list_devices;
+};
+
+extern const std::vector<SinkDetails> g_sink_details;
+
+const SinkDetails& GetSinkDetails(std::string sink_id);
+
+} // namespace AudioCore
diff --git a/src/audio_core/sink_stream.h b/src/audio_core/sink_stream.h
new file mode 100644
index 000000000..e7a3f01b0
--- /dev/null
+++ b/src/audio_core/sink_stream.h
@@ -0,0 +1,32 @@
+// Copyright 2018 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <memory>
+
+#include "common/common_types.h"
+
+namespace AudioCore {
+
+/**
+ * Accepts samples in stereo signed PCM16 format to be output. Sinks *do not* handle resampling and
+ * expect the correct sample rate. They are dumb outputs.
+ */
+class SinkStream {
+public:
+ virtual ~SinkStream() = default;
+
+ /**
+ * Feed stereo samples to sink.
+ * @param num_channels Number of channels used.
+ * @param samples Samples in interleaved stereo PCM16 format.
+ * @param sample_count Number of samples.
+ */
+ virtual void EnqueueSamples(u32 num_channels, const s16* samples, size_t sample_count) = 0;
+};
+
+using SinkStreamPtr = std::unique_ptr<SinkStream>;
+
+} // namespace AudioCore