audio_core: Flush stream when not playing anything

This commit is contained in:
MerryMage 2018-09-12 18:07:16 +01:00
parent 55af5bda55
commit 957ddab679
6 changed files with 23 additions and 0 deletions

View File

@ -3,6 +3,7 @@
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include <algorithm> #include <algorithm>
#include <atomic>
#include <cstring> #include <cstring>
#include "audio_core/cubeb_sink.h" #include "audio_core/cubeb_sink.h"
#include "audio_core/stream.h" #include "audio_core/stream.h"
@ -81,6 +82,10 @@ public:
return queue.Size() / num_channels; return queue.Size() / num_channels;
} }
void Flush() override {
should_flush = true;
}
u32 GetNumChannels() const { u32 GetNumChannels() const {
return num_channels; return num_channels;
} }
@ -94,6 +99,7 @@ private:
Common::RingBuffer<s16, 0x10000> queue; Common::RingBuffer<s16, 0x10000> queue;
std::array<s16, 2> last_frame; std::array<s16, 2> last_frame;
std::atomic<bool> should_flush{};
TimeStretcher time_stretch; TimeStretcher time_stretch;
static long DataCallback(cubeb_stream* stream, void* user_data, const void* input_buffer, static long DataCallback(cubeb_stream* stream, void* user_data, const void* input_buffer,
@ -163,6 +169,11 @@ long CubebSinkStream::DataCallback(cubeb_stream* stream, void* user_data, const
s16* const out{reinterpret_cast<s16*>(buffer)}; s16* const out{reinterpret_cast<s16*>(buffer)};
const size_t out_frames = impl->time_stretch.Process(in.data(), num_in, out, num_frames); const size_t out_frames = impl->time_stretch.Process(in.data(), num_in, out, num_frames);
samples_written = out_frames * num_channels; samples_written = out_frames * num_channels;
if (impl->should_flush) {
impl->time_stretch.Flush();
impl->should_flush = false;
}
} else { } else {
samples_written = impl->queue.Pop(buffer, samples_to_write); samples_written = impl->queue.Pop(buffer, samples_to_write);
} }

View File

@ -25,6 +25,8 @@ private:
size_t SamplesInQueue(u32 /*num_channels*/) const override { size_t SamplesInQueue(u32 /*num_channels*/) const override {
return 0; return 0;
} }
void Flush() override {}
} null_sink_stream; } null_sink_stream;
}; };

View File

@ -27,6 +27,8 @@ public:
virtual void EnqueueSamples(u32 num_channels, const std::vector<s16>& samples) = 0; virtual void EnqueueSamples(u32 num_channels, const std::vector<s16>& samples) = 0;
virtual std::size_t SamplesInQueue(u32 num_channels) const = 0; virtual std::size_t SamplesInQueue(u32 num_channels) const = 0;
virtual void Flush() = 0;
}; };
using SinkStreamPtr = std::unique_ptr<SinkStream>; using SinkStreamPtr = std::unique_ptr<SinkStream>;

View File

@ -73,6 +73,7 @@ static void VolumeAdjustSamples(std::vector<s16>& samples) {
void Stream::PlayNextBuffer() { void Stream::PlayNextBuffer() {
if (!IsPlaying()) { if (!IsPlaying()) {
// Ensure we are in playing state before playing the next buffer // Ensure we are in playing state before playing the next buffer
sink_stream.Flush();
return; return;
} }
@ -83,6 +84,7 @@ void Stream::PlayNextBuffer() {
if (queued_buffers.empty()) { if (queued_buffers.empty()) {
// No queued buffers - we are effectively paused // No queued buffers - we are effectively paused
sink_stream.Flush();
return; return;
} }

View File

@ -22,6 +22,10 @@ void TimeStretcher::Clear() {
m_sound_touch.clear(); m_sound_touch.clear();
} }
void TimeStretcher::Flush() {
m_sound_touch.flush();
}
size_t TimeStretcher::Process(const s16* in, size_t num_in, s16* out, size_t num_out) { size_t TimeStretcher::Process(const s16* in, size_t num_in, s16* out, size_t num_out) {
const double time_delta = static_cast<double>(num_out) / m_sample_rate; // seconds const double time_delta = static_cast<double>(num_out) / m_sample_rate; // seconds

View File

@ -24,6 +24,8 @@ public:
void Clear(); void Clear();
void Flush();
private: private:
u32 m_sample_rate; u32 m_sample_rate;
u32 m_channel_count; u32 m_channel_count;