/* * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ // Modified from the Chromium original: // src/media/base/sinc_resampler.cc // Initial input buffer layout, dividing into regions r0_ to r4_ (note: r0_, r3_ // and r4_ will move after the first load): // // |----------------|-----------------------------------------|----------------| // // request_frames_ // <---------------------------------------------------------> // r0_ (during first load) // // kKernelSize / 2 kKernelSize / 2 kKernelSize / 2 kKernelSize / 2 // <---------------> <---------------> <---------------> <---------------> // r1_ r2_ r3_ r4_ // // block_size_ == r4_ - r2_ // <---------------------------------------> // // request_frames_ // <------------------ ... -----------------> // r0_ (during second load) // // On the second request r0_ slides to the right by kKernelSize / 2 and r3_, r4_ // and block_size_ are reinitialized via step (3) in the algorithm below. // // These new regions remain constant until a Flush() occurs. While complicated, // this allows us to reduce jitter by always requesting the same amount from the // provided callback. // // The algorithm: // // 1) Allocate input_buffer of size: request_frames_ + kKernelSize; this ensures // there's enough room to read request_frames_ from the callback into region // r0_ (which will move between the first and subsequent passes). // // 2) Let r1_, r2_ each represent half the kernel centered around r0_: // // r0_ = input_buffer_ + kKernelSize / 2 // r1_ = input_buffer_ // r2_ = r0_ // // r0_ is always request_frames_ in size. r1_, r2_ are kKernelSize / 2 in // size. r1_ must be zero initialized to avoid convolution with garbage (see // step (5) for why). // // 3) Let r3_, r4_ each represent half the kernel right aligned with the end of // r0_ and choose block_size_ as the distance in frames between r4_ and r2_: // // r3_ = r0_ + request_frames_ - kKernelSize // r4_ = r0_ + request_frames_ - kKernelSize / 2 // block_size_ = r4_ - r2_ = request_frames_ - kKernelSize / 2 // // 4) Consume request_frames_ frames into r0_. // // 5) Position kernel centered at start of r2_ and generate output frames until // the kernel is centered at the start of r4_ or we've finished generating // all the output frames. // // 6) Wrap left over data from the r3_ to r1_ and r4_ to r2_. // // 7) If we're on the second load, in order to avoid overwriting the frames we // just wrapped from r4_ we need to slide r0_ to the right by the size of // r4_, which is kKernelSize / 2: // // r0_ = r0_ + kKernelSize / 2 = input_buffer_ + kKernelSize // // r3_, r4_, and block_size_ then need to be reinitialized, so goto (3). // // 8) Else, if we're not on the second load, goto (4). // // Note: we're glossing over how the sub-sample handling works with // `virtual_source_idx_`, etc. // MSVC++ requires this to be set before any other includes to get M_PI. #define _USE_MATH_DEFINES #include "common_audio/resampler/sinc_resampler.h" #include <math.h> #include <stdint.h> #include <string.h> #include <limits> #include "rtc_base/checks.h" #include "rtc_base/system/arch.h" #include "system_wrappers/include/cpu_features_wrapper.h" // kSSE2, WebRtc_G... namespace webrtc { namespace { double SincScaleFactor(double io_ratio) { … } } // namespace const size_t SincResampler::kKernelSize; // If we know the minimum architecture at compile time, avoid CPU detection. void SincResampler::InitializeCPUSpecificFeatures() { … } SincResampler::SincResampler(double io_sample_rate_ratio, size_t request_frames, SincResamplerCallback* read_cb) : … { … } SincResampler::~SincResampler() { … } void SincResampler::UpdateRegions(bool second_load) { … } void SincResampler::InitializeKernel() { … } void SincResampler::SetRatio(double io_sample_rate_ratio) { … } void SincResampler::Resample(size_t frames, float* destination) { … } #undef CONVOLVE_FUNC size_t SincResampler::ChunkSize() const { … } void SincResampler::Flush() { … } float SincResampler::Convolve_C(const float* input_ptr, const float* k1, const float* k2, double kernel_interpolation_factor) { … } } // namespace webrtc