6 changed files with 163 additions and 0 deletions
-
5src/audio_core/CMakeLists.txt
-
27src/audio_core/null_sink.h
-
29src/audio_core/sink.h
-
38src/audio_core/sink_details.cpp
-
32src/audio_core/sink_details.h
-
32src/audio_core/sink_stream.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 |
||||
@ -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 |
||||
@ -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
|
||||
@ -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 |
||||
@ -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 |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue