From 6d9dd1dc6dacbba9907e7c4e92e2d9d111ef44f4 Mon Sep 17 00:00:00 2001 From: MerryMage Date: Sat, 8 Sep 2018 14:55:11 +0100 Subject: [PATCH] cubeb_sink: Use RingBuffer --- src/audio_core/cubeb_sink.cpp | 66 ++++++++++++++--------------------- 1 file changed, 26 insertions(+), 40 deletions(-) diff --git a/src/audio_core/cubeb_sink.cpp b/src/audio_core/cubeb_sink.cpp index 0f77fd1628..552bcd051d 100644 --- a/src/audio_core/cubeb_sink.cpp +++ b/src/audio_core/cubeb_sink.cpp @@ -4,18 +4,17 @@ #include #include -#include - #include "audio_core/cubeb_sink.h" #include "audio_core/stream.h" #include "common/logging/log.h" +#include "common/ring_buffer.h" namespace AudioCore { -class SinkStreamImpl final : public SinkStream { +class CubebSinkStream final : public SinkStream { public: - SinkStreamImpl(cubeb* ctx, u32 sample_rate, u32 num_channels_, cubeb_devid output_device, - const std::string& name) + CubebSinkStream(cubeb* ctx, u32 sample_rate, u32 num_channels_, cubeb_devid output_device, + const std::string& name) : ctx{ctx}, num_channels{num_channels_} { if (num_channels == 6) { @@ -38,7 +37,7 @@ public: if (cubeb_stream_init(ctx, &stream_backend, name.c_str(), nullptr, nullptr, output_device, ¶ms, std::max(512u, minimum_latency), - &SinkStreamImpl::DataCallback, &SinkStreamImpl::StateCallback, + &CubebSinkStream::DataCallback, &CubebSinkStream::StateCallback, this) != CUBEB_OK) { LOG_CRITICAL(Audio_Sink, "Error initializing cubeb stream"); return; @@ -50,7 +49,7 @@ public: } } - ~SinkStreamImpl() { + ~CubebSinkStream() { if (!ctx) { return; } @@ -63,33 +62,27 @@ public: } void EnqueueSamples(u32 num_channels, const std::vector& samples) override { - if (!ctx) { - return; - } - - std::lock_guard lock{queue_mutex}; - - queue.reserve(queue.size() + samples.size() * GetNumChannels()); - if (is_6_channel) { // Downsample 6 channels to 2 const size_t sample_count_copy_size = samples.size() * 2; - queue.reserve(sample_count_copy_size); + std::vector buf; + buf.reserve(sample_count_copy_size); for (size_t i = 0; i < samples.size(); i += num_channels) { - queue.push_back(samples[i]); - queue.push_back(samples[i + 1]); + buf.push_back(samples[i]); + buf.push_back(samples[i + 1]); } - } else { - // Copy as-is - std::copy(samples.begin(), samples.end(), std::back_inserter(queue)); + queue.Push(buf); + return; } + + queue.Push(samples); } - size_t SamplesInQueue(u32 num_channels) const { + size_t SamplesInQueue(u32 num_channels) const override { if (!ctx) return 0; - return queue.size() / num_channels; + return queue.Size() / num_channels; } u32 GetNumChannels() const { @@ -104,8 +97,7 @@ private: u32 num_channels{}; bool is_6_channel{}; - std::mutex queue_mutex; - std::vector queue; + Common::RingBuffer queue; static long DataCallback(cubeb_stream* stream, void* user_data, const void* input_buffer, void* output_buffer, long num_frames); @@ -151,38 +143,32 @@ CubebSink::~CubebSink() { SinkStream& CubebSink::AcquireSinkStream(u32 sample_rate, u32 num_channels, const std::string& name) { sink_streams.push_back( - std::make_unique(ctx, sample_rate, num_channels, output_device, name)); + std::make_unique(ctx, sample_rate, num_channels, output_device, name)); return *sink_streams.back(); } -long SinkStreamImpl::DataCallback(cubeb_stream* stream, void* user_data, const void* input_buffer, +long CubebSinkStream::DataCallback(cubeb_stream* stream, void* user_data, const void* input_buffer, void* output_buffer, long num_frames) { - SinkStreamImpl* impl = static_cast(user_data); + CubebSinkStream* impl = static_cast(user_data); u8* buffer = reinterpret_cast(output_buffer); if (!impl) { return {}; } - std::lock_guard lock{impl->queue_mutex}; + const size_t max_samples_to_write = impl->GetNumChannels() * num_frames; + const size_t samples_written = impl->queue.Pop(buffer, max_samples_to_write); - const size_t frames_to_write{ - std::min(impl->queue.size() / impl->GetNumChannels(), static_cast(num_frames))}; - - memcpy(buffer, impl->queue.data(), frames_to_write * sizeof(s16) * impl->GetNumChannels()); - impl->queue.erase(impl->queue.begin(), - impl->queue.begin() + frames_to_write * impl->GetNumChannels()); - - if (frames_to_write < num_frames) { + if (samples_written < max_samples_to_write) { // Fill the rest of the frames with silence - memset(buffer + frames_to_write * sizeof(s16) * impl->GetNumChannels(), 0, - (num_frames - frames_to_write) * sizeof(s16) * impl->GetNumChannels()); + std::memset(buffer + samples_written * sizeof(s16), 0, + (max_samples_to_write - samples_written) * sizeof(s16)); } return num_frames; } -void SinkStreamImpl::StateCallback(cubeb_stream* stream, void* user_data, cubeb_state state) {} +void CubebSinkStream::StateCallback(cubeb_stream* stream, void* user_data, cubeb_state state) {} std::vector ListCubebSinkDevices() { std::vector device_list;