forked from suyu/suyu
audio_core: Add interfaces for Sink and SinkStream.
This commit is contained in:
parent
0e8a2c7222
commit
9ef227e09d
6 changed files with 163 additions and 0 deletions
|
@ -2,8 +2,13 @@ add_library(audio_core STATIC
|
||||||
audio_out.cpp
|
audio_out.cpp
|
||||||
audio_out.h
|
audio_out.h
|
||||||
buffer.h
|
buffer.h
|
||||||
|
null_sink.h
|
||||||
stream.cpp
|
stream.cpp
|
||||||
stream.h
|
stream.h
|
||||||
|
sink.h
|
||||||
|
sink_details.cpp
|
||||||
|
sink_details.h
|
||||||
|
sink_stream.h
|
||||||
)
|
)
|
||||||
|
|
||||||
create_target_directory_groups(audio_core)
|
create_target_directory_groups(audio_core)
|
||||||
|
|
27
src/audio_core/null_sink.h
Normal file
27
src/audio_core/null_sink.h
Normal file
|
@ -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
|
29
src/audio_core/sink.h
Normal file
29
src/audio_core/sink.h
Normal file
|
@ -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
|
38
src/audio_core/sink_details.cpp
Normal file
38
src/audio_core/sink_details.cpp
Normal file
|
@ -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
|
32
src/audio_core/sink_details.h
Normal file
32
src/audio_core/sink_details.h
Normal file
|
@ -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
|
32
src/audio_core/sink_stream.h
Normal file
32
src/audio_core/sink_stream.h
Normal file
|
@ -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
|
Loading…
Reference in a new issue