static int flush(struct SwrContext *s){ s->delayed_samples_fixup = soxr_delay((soxr_t)s->resample); soxr_process((soxr_t)s->resample, NULL, 0, NULL, NULL, 0, NULL); { float f; size_t idone, odone; soxr_process((soxr_t)s->resample, &f, 0, &idone, &f, 0, &odone); s->delayed_samples_fixup -= soxr_delay((soxr_t)s->resample); } return 0; }
static int64_t get_out_samples(struct SwrContext *s, int in_samples){ double out_samples = (double)s->out_sample_rate / s->in_sample_rate * in_samples; double delayed_samples = soxr_delay((soxr_t)s->resample); if (s->flushed) delayed_samples += s->delayed_samples_fixup; return (int64_t)(out_samples + delayed_samples + 1 + .5); }
static int64_t get_delay(struct SwrContext *s, int64_t base){ double delayed_samples = soxr_delay((soxr_t)s->resample); double delay_s; if (s->flushed) delayed_samples += s->delayed_samples_fixup; delay_s = delayed_samples / s->out_sample_rate; return (int64_t)(delay_s * base + .5); }
static int64_t get_delay(struct SwrContext *s, int64_t base){ double delay_s = soxr_delay((soxr_t)s->resample) / s->out_sample_rate; return (int64_t)(delay_s * base + .5); }
double Resampler::GetDelayedSamples() { if(m_soxr == NULL) return 0.0; return soxr_delay(m_soxr); }
void DspRate::FinishStateTransition(DspChunk& processedChunk, DspChunk& unprocessedChunk, bool eos) { if (m_inStateTransition) { assert(m_state == State::Variable); DspChunk::ToFloat(processedChunk); DspChunk::ToFloat(unprocessedChunk); auto& first = m_transitionChunks.first; auto& second = m_transitionChunks.second; DspChunk::MergeChunks(first, processedChunk); assert(processedChunk.IsEmpty()); if (m_soxrc) { // Transitioning from constant rate conversion to variable. if (!m_transitionCorrelation.first) m_transitionCorrelation = {true, (size_t)std::round(soxr_delay(m_soxrc))}; if (m_transitionCorrelation.second > 0) { DspChunk::MergeChunks(second, eos ? ProcessEosChunk(m_soxrc, unprocessedChunk) : ProcessChunk(m_soxrc, unprocessedChunk)); } else { // Nothing to flush from constant rate conversion buffer. m_inStateTransition = false; } } else { // Transitioning from pass-through to variable rate conversion. m_transitionCorrelation = {}; DspChunk::MergeChunks(second, unprocessedChunk); } // Cross-fade. if (m_inStateTransition) { const size_t transitionFrames = m_outputRate / 1000; // 1ms if (first.GetFrameCount() >= transitionFrames && second.GetFrameCount() >= m_transitionCorrelation.second + transitionFrames) { second.ShrinkHead(second.GetFrameCount() - m_transitionCorrelation.second); Crossfade(first, second, transitionFrames); processedChunk = std::move(first); m_inStateTransition = false; } else if (eos) { processedChunk = std::move(second); m_inStateTransition = false; } } if (!m_inStateTransition) { m_transitionCorrelation = {}; m_transitionChunks = {}; DestroyBackend(m_soxrc); } } unprocessedChunk = {}; }