audio_core: Flush stream when not playing anything
This commit is contained in:
parent
55af5bda55
commit
957ddab679
6 changed files with 23 additions and 0 deletions
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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>;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue