OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
142 convolve_proc_ = WebRtc_GetCPUFeaturesARM() & kCPUFeatureNEON ? | 142 convolve_proc_ = WebRtc_GetCPUFeaturesARM() & kCPUFeatureNEON ? |
143 Convolve_NEON : Convolve_C; | 143 Convolve_NEON : Convolve_C; |
144 } | 144 } |
145 #else | 145 #else |
146 // Unknown architecture. | 146 // Unknown architecture. |
147 #define CONVOLVE_FUNC Convolve_C | 147 #define CONVOLVE_FUNC Convolve_C |
148 void SincResampler::InitializeCPUSpecificFeatures() {} | 148 void SincResampler::InitializeCPUSpecificFeatures() {} |
149 #endif | 149 #endif |
150 | 150 |
151 SincResampler::SincResampler(double io_sample_rate_ratio, | 151 SincResampler::SincResampler(double io_sample_rate_ratio, |
152 int request_frames, | 152 size_t request_frames, |
153 SincResamplerCallback* read_cb) | 153 SincResamplerCallback* read_cb) |
154 : io_sample_rate_ratio_(io_sample_rate_ratio), | 154 : io_sample_rate_ratio_(io_sample_rate_ratio), |
155 read_cb_(read_cb), | 155 read_cb_(read_cb), |
156 request_frames_(request_frames), | 156 request_frames_(request_frames), |
157 input_buffer_size_(request_frames_ + kKernelSize), | 157 input_buffer_size_(request_frames_ + kKernelSize), |
158 // Create input buffers with a 16-byte alignment for SSE optimizations. | 158 // Create input buffers with a 16-byte alignment for SSE optimizations. |
159 kernel_storage_(static_cast<float*>( | 159 kernel_storage_(static_cast<float*>( |
160 AlignedMalloc(sizeof(float) * kKernelStorageSize, 16))), | 160 AlignedMalloc(sizeof(float) * kKernelStorageSize, 16))), |
161 kernel_pre_sinc_storage_(static_cast<float*>( | 161 kernel_pre_sinc_storage_(static_cast<float*>( |
162 AlignedMalloc(sizeof(float) * kKernelStorageSize, 16))), | 162 AlignedMalloc(sizeof(float) * kKernelStorageSize, 16))), |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
208 void SincResampler::InitializeKernel() { | 208 void SincResampler::InitializeKernel() { |
209 // Blackman window parameters. | 209 // Blackman window parameters. |
210 static const double kAlpha = 0.16; | 210 static const double kAlpha = 0.16; |
211 static const double kA0 = 0.5 * (1.0 - kAlpha); | 211 static const double kA0 = 0.5 * (1.0 - kAlpha); |
212 static const double kA1 = 0.5; | 212 static const double kA1 = 0.5; |
213 static const double kA2 = 0.5 * kAlpha; | 213 static const double kA2 = 0.5 * kAlpha; |
214 | 214 |
215 // Generates a set of windowed sinc() kernels. | 215 // Generates a set of windowed sinc() kernels. |
216 // We generate a range of sub-sample offsets from 0.0 to 1.0. | 216 // We generate a range of sub-sample offsets from 0.0 to 1.0. |
217 const double sinc_scale_factor = SincScaleFactor(io_sample_rate_ratio_); | 217 const double sinc_scale_factor = SincScaleFactor(io_sample_rate_ratio_); |
218 for (int offset_idx = 0; offset_idx <= kKernelOffsetCount; ++offset_idx) { | 218 for (size_t offset_idx = 0; offset_idx <= kKernelOffsetCount; ++offset_idx) { |
219 const float subsample_offset = | 219 const float subsample_offset = |
220 static_cast<float>(offset_idx) / kKernelOffsetCount; | 220 static_cast<float>(offset_idx) / kKernelOffsetCount; |
221 | 221 |
222 for (int i = 0; i < kKernelSize; ++i) { | 222 for (size_t i = 0; i < kKernelSize; ++i) { |
223 const int idx = i + offset_idx * kKernelSize; | 223 const size_t idx = i + offset_idx * kKernelSize; |
224 const float pre_sinc = | 224 const float pre_sinc = static_cast<float>(M_PI * |
225 static_cast<float>(M_PI * (i - kKernelSize / 2 - subsample_offset)); | 225 (static_cast<int>(i) - static_cast<int>(kKernelSize / 2) - |
| 226 subsample_offset)); |
226 kernel_pre_sinc_storage_[idx] = pre_sinc; | 227 kernel_pre_sinc_storage_[idx] = pre_sinc; |
227 | 228 |
228 // Compute Blackman window, matching the offset of the sinc(). | 229 // Compute Blackman window, matching the offset of the sinc(). |
229 const float x = (i - subsample_offset) / kKernelSize; | 230 const float x = (i - subsample_offset) / kKernelSize; |
230 const float window = static_cast<float>(kA0 - kA1 * cos(2.0 * M_PI * x) + | 231 const float window = static_cast<float>(kA0 - kA1 * cos(2.0 * M_PI * x) + |
231 kA2 * cos(4.0 * M_PI * x)); | 232 kA2 * cos(4.0 * M_PI * x)); |
232 kernel_window_storage_[idx] = window; | 233 kernel_window_storage_[idx] = window; |
233 | 234 |
234 // Compute the sinc with offset, then window the sinc() function and store | 235 // Compute the sinc with offset, then window the sinc() function and store |
235 // at the correct offset. | 236 // at the correct offset. |
236 kernel_storage_[idx] = static_cast<float>(window * | 237 kernel_storage_[idx] = static_cast<float>(window * |
237 ((pre_sinc == 0) ? | 238 ((pre_sinc == 0) ? |
238 sinc_scale_factor : | 239 sinc_scale_factor : |
239 (sin(sinc_scale_factor * pre_sinc) / pre_sinc))); | 240 (sin(sinc_scale_factor * pre_sinc) / pre_sinc))); |
240 } | 241 } |
241 } | 242 } |
242 } | 243 } |
243 | 244 |
244 void SincResampler::SetRatio(double io_sample_rate_ratio) { | 245 void SincResampler::SetRatio(double io_sample_rate_ratio) { |
245 if (fabs(io_sample_rate_ratio_ - io_sample_rate_ratio) < | 246 if (fabs(io_sample_rate_ratio_ - io_sample_rate_ratio) < |
246 std::numeric_limits<double>::epsilon()) { | 247 std::numeric_limits<double>::epsilon()) { |
247 return; | 248 return; |
248 } | 249 } |
249 | 250 |
250 io_sample_rate_ratio_ = io_sample_rate_ratio; | 251 io_sample_rate_ratio_ = io_sample_rate_ratio; |
251 | 252 |
252 // Optimize reinitialization by reusing values which are independent of | 253 // Optimize reinitialization by reusing values which are independent of |
253 // |sinc_scale_factor|. Provides a 3x speedup. | 254 // |sinc_scale_factor|. Provides a 3x speedup. |
254 const double sinc_scale_factor = SincScaleFactor(io_sample_rate_ratio_); | 255 const double sinc_scale_factor = SincScaleFactor(io_sample_rate_ratio_); |
255 for (int offset_idx = 0; offset_idx <= kKernelOffsetCount; ++offset_idx) { | 256 for (size_t offset_idx = 0; offset_idx <= kKernelOffsetCount; ++offset_idx) { |
256 for (int i = 0; i < kKernelSize; ++i) { | 257 for (size_t i = 0; i < kKernelSize; ++i) { |
257 const int idx = i + offset_idx * kKernelSize; | 258 const size_t idx = i + offset_idx * kKernelSize; |
258 const float window = kernel_window_storage_[idx]; | 259 const float window = kernel_window_storage_[idx]; |
259 const float pre_sinc = kernel_pre_sinc_storage_[idx]; | 260 const float pre_sinc = kernel_pre_sinc_storage_[idx]; |
260 | 261 |
261 kernel_storage_[idx] = static_cast<float>(window * | 262 kernel_storage_[idx] = static_cast<float>(window * |
262 ((pre_sinc == 0) ? | 263 ((pre_sinc == 0) ? |
263 sinc_scale_factor : | 264 sinc_scale_factor : |
264 (sin(sinc_scale_factor * pre_sinc) / pre_sinc))); | 265 (sin(sinc_scale_factor * pre_sinc) / pre_sinc))); |
265 } | 266 } |
266 } | 267 } |
267 } | 268 } |
268 | 269 |
269 void SincResampler::Resample(int frames, float* destination) { | 270 void SincResampler::Resample(size_t frames, float* destination) { |
270 int remaining_frames = frames; | 271 size_t remaining_frames = frames; |
271 | 272 |
272 // Step (1) -- Prime the input buffer at the start of the input stream. | 273 // Step (1) -- Prime the input buffer at the start of the input stream. |
273 if (!buffer_primed_ && remaining_frames) { | 274 if (!buffer_primed_ && remaining_frames) { |
274 read_cb_->Run(request_frames_, r0_); | 275 read_cb_->Run(request_frames_, r0_); |
275 buffer_primed_ = true; | 276 buffer_primed_ = true; |
276 } | 277 } |
277 | 278 |
278 // Step (2) -- Resample! const what we can outside of the loop for speed. It | 279 // Step (2) -- Resample! const what we can outside of the loop for speed. It |
279 // actually has an impact on ARM performance. See inner loop comment below. | 280 // actually has an impact on ARM performance. See inner loop comment below. |
280 const double current_io_ratio = io_sample_rate_ratio_; | 281 const double current_io_ratio = io_sample_rate_ratio_; |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
336 if (r0_ == r2_) | 337 if (r0_ == r2_) |
337 UpdateRegions(true); | 338 UpdateRegions(true); |
338 | 339 |
339 // Step (5) -- Refresh the buffer with more input. | 340 // Step (5) -- Refresh the buffer with more input. |
340 read_cb_->Run(request_frames_, r0_); | 341 read_cb_->Run(request_frames_, r0_); |
341 } | 342 } |
342 } | 343 } |
343 | 344 |
344 #undef CONVOLVE_FUNC | 345 #undef CONVOLVE_FUNC |
345 | 346 |
346 int SincResampler::ChunkSize() const { | 347 size_t SincResampler::ChunkSize() const { |
347 return static_cast<int>(block_size_ / io_sample_rate_ratio_); | 348 return static_cast<size_t>(block_size_ / io_sample_rate_ratio_); |
348 } | 349 } |
349 | 350 |
350 void SincResampler::Flush() { | 351 void SincResampler::Flush() { |
351 virtual_source_idx_ = 0; | 352 virtual_source_idx_ = 0; |
352 buffer_primed_ = false; | 353 buffer_primed_ = false; |
353 memset(input_buffer_.get(), 0, | 354 memset(input_buffer_.get(), 0, |
354 sizeof(*input_buffer_.get()) * input_buffer_size_); | 355 sizeof(*input_buffer_.get()) * input_buffer_size_); |
355 UpdateRegions(false); | 356 UpdateRegions(false); |
356 } | 357 } |
357 | 358 |
358 float SincResampler::Convolve_C(const float* input_ptr, const float* k1, | 359 float SincResampler::Convolve_C(const float* input_ptr, const float* k1, |
359 const float* k2, | 360 const float* k2, |
360 double kernel_interpolation_factor) { | 361 double kernel_interpolation_factor) { |
361 float sum1 = 0; | 362 float sum1 = 0; |
362 float sum2 = 0; | 363 float sum2 = 0; |
363 | 364 |
364 // Generate a single output sample. Unrolling this loop hurt performance in | 365 // Generate a single output sample. Unrolling this loop hurt performance in |
365 // local testing. | 366 // local testing. |
366 int n = kKernelSize; | 367 size_t n = kKernelSize; |
367 while (n--) { | 368 while (n--) { |
368 sum1 += *input_ptr * *k1++; | 369 sum1 += *input_ptr * *k1++; |
369 sum2 += *input_ptr++ * *k2++; | 370 sum2 += *input_ptr++ * *k2++; |
370 } | 371 } |
371 | 372 |
372 // Linearly interpolate the two "convolutions". | 373 // Linearly interpolate the two "convolutions". |
373 return static_cast<float>((1.0 - kernel_interpolation_factor) * sum1 + | 374 return static_cast<float>((1.0 - kernel_interpolation_factor) * sum1 + |
374 kernel_interpolation_factor * sum2); | 375 kernel_interpolation_factor * sum2); |
375 } | 376 } |
376 | 377 |
377 } // namespace webrtc | 378 } // namespace webrtc |
OLD | NEW |