sinc_resampler.h 7.0 KB

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