tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

sinc_resampler.h (7167B)


      1 /*
      2 *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
      3 *
      4 *  Use of this source code is governed by a BSD-style license
      5 *  that can be found in the LICENSE file in the root of the source
      6 *  tree. An additional intellectual property rights grant can be found
      7 *  in the file PATENTS.  All contributing project authors may
      8 *  be found in the AUTHORS file in the root of the source tree.
      9 */
     10 
     11 // Modified from the Chromium original here:
     12 // src/media/base/sinc_resampler.h
     13 
     14 #ifndef COMMON_AUDIO_RESAMPLER_SINC_RESAMPLER_H_
     15 #define COMMON_AUDIO_RESAMPLER_SINC_RESAMPLER_H_
     16 
     17 #include <stddef.h>
     18 
     19 #include <memory>
     20 
     21 #include "rtc_base/gtest_prod_util.h"
     22 #include "rtc_base/memory/aligned_malloc.h"
     23 #include "rtc_base/system/arch.h"
     24 
     25 namespace webrtc {
     26 
     27 // Callback class for providing more data into the resampler.  Expects `frames`
     28 // of data to be rendered into `destination`; zero padded if not enough frames
     29 // are available to satisfy the request.
     30 class SincResamplerCallback {
     31 public:
     32  virtual ~SincResamplerCallback() {}
     33  virtual void Run(size_t frames, float* destination) = 0;
     34 };
     35 
     36 // SincResampler is a high-quality single-channel sample-rate converter.
     37 class SincResampler {
     38 public:
     39  // The kernel size can be adjusted for quality (higher is better) at the
     40  // expense of performance.  Must be a multiple of 32.
     41  // TODO(dalecurtis): Test performance to see if we can jack this up to 64+.
     42  static const size_t kKernelSize = 32;
     43 
     44  // Default request size.  Affects how often and for how much SincResampler
     45  // calls back for input.  Must be greater than kKernelSize.
     46  static const size_t kDefaultRequestSize = 512;
     47 
     48  // The kernel offset count is used for interpolation and is the number of
     49  // sub-sample kernel shifts.  Can be adjusted for quality (higher is better)
     50  // at the expense of allocating more memory.
     51  static const size_t kKernelOffsetCount = 32;
     52  static const size_t kKernelStorageSize =
     53      kKernelSize * (kKernelOffsetCount + 1);
     54 
     55  // Constructs a SincResampler with the specified `read_cb`, which is used to
     56  // acquire audio data for resampling.  `io_sample_rate_ratio` is the ratio
     57  // of input / output sample rates.  `request_frames` controls the size in
     58  // frames of the buffer requested by each `read_cb` call.  The value must be
     59  // greater than kKernelSize.  Specify kDefaultRequestSize if there are no
     60  // request size constraints.
     61  SincResampler(double io_sample_rate_ratio,
     62                size_t request_frames,
     63                SincResamplerCallback* read_cb);
     64  virtual ~SincResampler();
     65 
     66  SincResampler(const SincResampler&) = delete;
     67  SincResampler& operator=(const SincResampler&) = delete;
     68 
     69  // Resample `frames` of data from `read_cb_` into `destination`.
     70  void Resample(size_t frames, float* destination);
     71 
     72  // The maximum size in frames that guarantees Resample() will only make a
     73  // single call to `read_cb_` for more data.
     74  size_t ChunkSize() const;
     75 
     76  size_t request_frames() const { return request_frames_; }
     77 
     78  // Flush all buffered data and reset internal indices.  Not thread safe, do
     79  // not call while Resample() is in progress.
     80  void Flush();
     81 
     82  // Update `io_sample_rate_ratio_`.  SetRatio() will cause a reconstruction of
     83  // the kernels used for resampling.  Not thread safe, do not call while
     84  // Resample() is in progress.
     85  //
     86  // TODO(ajm): Use this in PushSincResampler rather than reconstructing
     87  // SincResampler.  We would also need a way to update `request_frames_`.
     88  void SetRatio(double io_sample_rate_ratio);
     89 
     90  float* get_kernel_for_testing() { return kernel_storage_.get(); }
     91 
     92 private:
     93  FRIEND_TEST_ALL_PREFIXES(SincResamplerTest, Convolve);
     94  FRIEND_TEST_ALL_PREFIXES(SincResamplerTest, ConvolveBenchmark);
     95 
     96  void InitializeKernel();
     97  void UpdateRegions(bool second_load);
     98 
     99  // Selects runtime specific CPU features like SSE.  Must be called before
    100  // using SincResampler.
    101  // TODO(ajm): Currently managed by the class internally. See the note with
    102  // `convolve_proc_` below.
    103  void InitializeCPUSpecificFeatures();
    104 
    105  // Compute convolution of `k1` and `k2` over `input_ptr`, resultant sums are
    106  // linearly interpolated using `kernel_interpolation_factor`.  On x86 and ARM
    107  // the underlying implementation is chosen at run time.
    108  static float Convolve_C(const float* input_ptr,
    109                          const float* k1,
    110                          const float* k2,
    111                          double kernel_interpolation_factor);
    112 #if defined(WEBRTC_ARCH_X86_FAMILY)
    113  static float Convolve_SSE(const float* input_ptr,
    114                            const float* k1,
    115                            const float* k2,
    116                            double kernel_interpolation_factor);
    117  static float Convolve_AVX2(const float* input_ptr,
    118                             const float* k1,
    119                             const float* k2,
    120                             double kernel_interpolation_factor);
    121 #elif defined(WEBRTC_HAS_NEON)
    122  static float Convolve_NEON(const float* input_ptr,
    123                             const float* k1,
    124                             const float* k2,
    125                             double kernel_interpolation_factor);
    126 #endif
    127 
    128  // The ratio of input / output sample rates.
    129  double io_sample_rate_ratio_;
    130 
    131  // An index on the source input buffer with sub-sample precision.  It must be
    132  // double precision to avoid drift.
    133  double virtual_source_idx_;
    134 
    135  // The buffer is primed once at the very beginning of processing.
    136  bool buffer_primed_;
    137 
    138  // Source of data for resampling.
    139  SincResamplerCallback* read_cb_;
    140 
    141  // The size (in samples) to request from each `read_cb_` execution.
    142  const size_t request_frames_;
    143 
    144  // The number of source frames processed per pass.
    145  size_t block_size_;
    146 
    147  // The size (in samples) of the internal buffer used by the resampler.
    148  const size_t input_buffer_size_;
    149 
    150  // Contains kKernelOffsetCount kernels back-to-back, each of size kKernelSize.
    151  // The kernel offsets are sub-sample shifts of a windowed sinc shifted from
    152  // 0.0 to 1.0 sample.
    153  std::unique_ptr<float[], AlignedFreeDeleter> kernel_storage_;
    154  std::unique_ptr<float[], AlignedFreeDeleter> kernel_pre_sinc_storage_;
    155  std::unique_ptr<float[], AlignedFreeDeleter> kernel_window_storage_;
    156 
    157  // Data from the source is copied into this buffer for each processing pass.
    158  std::unique_ptr<float[], AlignedFreeDeleter> input_buffer_;
    159 
    160  // Stores the runtime selection of which Convolve function to use.
    161  // TODO(ajm): Move to using a global static which must only be initialized
    162  // once by the user. We're not doing this initially, because we don't have
    163  // e.g. a LazyInstance helper in webrtc.
    164  typedef float (*ConvolveProc)(const float*,
    165                                const float*,
    166                                const float*,
    167                                double);
    168  ConvolveProc convolve_proc_;
    169 
    170  // Pointers to the various regions inside `input_buffer_`.  See the diagram at
    171  // the top of the .cc file for more information.
    172  float* r0_;
    173  float* const r1_;
    174  float* const r2_;
    175  float* r3_;
    176  float* r4_;
    177 };
    178 
    179 }  // namespace webrtc
    180 
    181 #endif  // COMMON_AUDIO_RESAMPLER_SINC_RESAMPLER_H_