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