audio_core: Clear time stretcher after flushing to avoid sample bleed. (#7081)
This commit is contained in:
parent
259dbf17dc
commit
45ef11654a
|
@ -66,18 +66,22 @@ void DspInterface::OutputSample(std::array<s16, 2> sample) {
|
|||
}
|
||||
|
||||
void DspInterface::OutputCallback(s16* buffer, std::size_t num_frames) {
|
||||
std::size_t frames_written;
|
||||
std::size_t frames_written = 0;
|
||||
if (perform_time_stretching) {
|
||||
const std::vector<s16> in{fifo.Pop()};
|
||||
const std::size_t num_in{in.size() / 2};
|
||||
frames_written = time_stretcher.Process(in.data(), num_in, buffer, num_frames);
|
||||
} else if (flushing_time_stretcher) {
|
||||
time_stretcher.Flush();
|
||||
frames_written = time_stretcher.Process(nullptr, 0, buffer, num_frames);
|
||||
frames_written += fifo.Pop(buffer, num_frames - frames_written);
|
||||
flushing_time_stretcher = false;
|
||||
} else {
|
||||
frames_written = fifo.Pop(buffer, num_frames);
|
||||
if (flushing_time_stretcher) {
|
||||
time_stretcher.Flush();
|
||||
frames_written = time_stretcher.Process(nullptr, 0, buffer, num_frames);
|
||||
flushing_time_stretcher = false;
|
||||
|
||||
// Make sure any frames that did not fit are cleared from the time stretcher,
|
||||
// so that they do not bleed into the next time the stretcher is enabled.
|
||||
time_stretcher.Clear();
|
||||
}
|
||||
frames_written += fifo.Pop(buffer, num_frames - frames_written);
|
||||
}
|
||||
|
||||
if (frames_written > 0) {
|
||||
|
|
|
@ -18,8 +18,7 @@
|
|||
|
||||
namespace AudioCore {
|
||||
|
||||
TimeStretcher::TimeStretcher()
|
||||
: sample_rate(native_sample_rate), sound_touch(std::make_unique<soundtouch::SoundTouch>()) {
|
||||
TimeStretcher::TimeStretcher() : sound_touch(std::make_unique<soundtouch::SoundTouch>()) {
|
||||
sound_touch->setChannels(2);
|
||||
sound_touch->setSampleRate(native_sample_rate);
|
||||
sound_touch->setPitch(1.0);
|
||||
|
@ -30,16 +29,15 @@ TimeStretcher::~TimeStretcher() = default;
|
|||
|
||||
void TimeStretcher::SetOutputSampleRate(unsigned int sample_rate) {
|
||||
sound_touch->setSampleRate(sample_rate);
|
||||
sample_rate = native_sample_rate;
|
||||
}
|
||||
|
||||
std::size_t TimeStretcher::Process(const s16* in, std::size_t num_in, s16* out,
|
||||
std::size_t num_out) {
|
||||
const double time_delta = static_cast<double>(num_out) / sample_rate; // seconds
|
||||
const double time_delta = static_cast<double>(num_out) / native_sample_rate; // seconds
|
||||
double current_ratio = static_cast<double>(num_in) / static_cast<double>(num_out);
|
||||
|
||||
const double max_latency = 0.25; // seconds
|
||||
const double max_backlog = sample_rate * max_latency;
|
||||
const double max_backlog = native_sample_rate * max_latency;
|
||||
const double backlog_fullness = sound_touch->numSamples() / max_backlog;
|
||||
if (backlog_fullness > 4.0) {
|
||||
// Too many samples in backlog: Don't push anymore on
|
||||
|
|
|
@ -34,7 +34,6 @@ public:
|
|||
void Flush();
|
||||
|
||||
private:
|
||||
unsigned int sample_rate;
|
||||
std::unique_ptr<soundtouch::SoundTouch> sound_touch;
|
||||
double stretch_ratio = 1.0;
|
||||
};
|
||||
|
|
Reference in New Issue