| 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 |