Index: media/base/sinc_resampler.cc |
diff --git a/media/base/sinc_resampler.cc b/media/base/sinc_resampler.cc |
index a2918c3f0d2e590c2eedc48ed29aa92a3e015343..b66ed345a3f13d148148ea29075216b9acca771c 100644 |
--- a/media/base/sinc_resampler.cc |
+++ b/media/base/sinc_resampler.cc |
@@ -1,7 +1,16 @@ |
-// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
-// |
+/* |
+ * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. |
+ * |
+ * Use of this source code is governed by a BSD-style license |
+ * that can be found in the LICENSE file in the root of the source |
+ * tree. An additional intellectual property rights grant can be found |
+ * in the file PATENTS. All contributing project authors may |
+ * be found in the AUTHORS file in the root of the source tree. |
+ */ |
+ |
+// Modified from the Chromium original: |
+// src/media/base/sinc_resampler.cc |
+ |
// Initial input buffer layout, dividing into regions r0_ to r4_ (note: r0_, r3_ |
// and r4_ will move after the first load): |
// |
@@ -76,19 +85,16 @@ |
// MSVC++ requires this to be set before any other includes to get M_PI. |
#define _USE_MATH_DEFINES |
-#include "media/base/sinc_resampler.h" |
+#include "webrtc/common_audio/resampler/sinc_resampler.h" |
+#include "webrtc/system_wrappers/interface/compile_assert.h" |
+#include "webrtc/system_wrappers/interface/cpu_features_wrapper.h" |
+#include "webrtc/typedefs.h" |
#include <cmath> |
+#include <cstring> |
#include <limits> |
-#include "base/cpu.h" |
-#include "base/logging.h" |
- |
-#if defined(ARCH_CPU_ARM_FAMILY) && defined(USE_NEON) |
-#include <arm_neon.h> |
-#endif |
- |
-namespace media { |
+namespace webrtc { |
static double SincScaleFactor(double io_ratio) { |
// |sinc_scale_factor| is basically the normalized cutoff frequency of the |
@@ -107,31 +113,36 @@ static double SincScaleFactor(double io_ratio) { |
} |
// If we know the minimum architecture at compile time, avoid CPU detection. |
-// Force NaCl code to use C routines since (at present) nothing there uses these |
-// methods and plumbing the -msse built library is non-trivial. iOS lies |
-// about its architecture, so we also need to exclude it here. |
-#if defined(ARCH_CPU_X86_FAMILY) && !defined(OS_NACL) && !defined(OS_IOS) |
+// iOS lies about its architecture, so we also need to exclude it here. |
+#if defined(WEBRTC_ARCH_X86_FAMILY) && !defined(WEBRTC_IOS) |
#if defined(__SSE__) |
#define CONVOLVE_FUNC Convolve_SSE |
void SincResampler::InitializeCPUSpecificFeatures() {} |
#else |
-// X86 CPU detection required. Functions will be set by |
+// X86 CPU detection required. Function will be set by |
// InitializeCPUSpecificFeatures(). |
// TODO(dalecurtis): Once Chrome moves to an SSE baseline this can be removed. |
-#define CONVOLVE_FUNC g_convolve_proc_ |
- |
-typedef float (*ConvolveProc)(const float*, const float*, const float*, double); |
-static ConvolveProc g_convolve_proc_ = NULL; |
+#define CONVOLVE_FUNC convolve_proc_ |
void SincResampler::InitializeCPUSpecificFeatures() { |
- CHECK(!g_convolve_proc_); |
- g_convolve_proc_ = base::CPU().has_sse() ? Convolve_SSE : Convolve_C; |
+ convolve_proc_ = WebRtc_GetCPUInfo(kSSE2) ? Convolve_SSE : Convolve_C; |
} |
#endif |
-#elif defined(ARCH_CPU_ARM_FAMILY) && defined(USE_NEON) |
+#elif defined(WEBRTC_ARCH_ARM_V7) |
+#if defined(WEBRTC_ARCH_ARM_NEON) |
#define CONVOLVE_FUNC Convolve_NEON |
void SincResampler::InitializeCPUSpecificFeatures() {} |
#else |
+// NEON CPU detection required. Function will be set by |
+// InitializeCPUSpecificFeatures(). |
+#define CONVOLVE_FUNC convolve_proc_ |
+ |
+void SincResampler::InitializeCPUSpecificFeatures() { |
+ convolve_proc_ = WebRtc_GetCPUFeaturesARM() & kCPUFeatureNEON ? |
+ Convolve_NEON : Convolve_C; |
+} |
+#endif |
+#else |
// Unknown architecture. |
#define CONVOLVE_FUNC Convolve_C |
void SincResampler::InitializeCPUSpecificFeatures() {} |
@@ -139,26 +150,32 @@ void SincResampler::InitializeCPUSpecificFeatures() {} |
SincResampler::SincResampler(double io_sample_rate_ratio, |
int request_frames, |
- const ReadCB& read_cb) |
+ SincResamplerCallback* read_cb) |
: io_sample_rate_ratio_(io_sample_rate_ratio), |
read_cb_(read_cb), |
request_frames_(request_frames), |
input_buffer_size_(request_frames_ + kKernelSize), |
// Create input buffers with a 16-byte alignment for SSE optimizations. |
kernel_storage_(static_cast<float*>( |
- base::AlignedAlloc(sizeof(float) * kKernelStorageSize, 16))), |
+ AlignedMalloc(sizeof(float) * kKernelStorageSize, 16))), |
kernel_pre_sinc_storage_(static_cast<float*>( |
- base::AlignedAlloc(sizeof(float) * kKernelStorageSize, 16))), |
+ AlignedMalloc(sizeof(float) * kKernelStorageSize, 16))), |
kernel_window_storage_(static_cast<float*>( |
- base::AlignedAlloc(sizeof(float) * kKernelStorageSize, 16))), |
+ AlignedMalloc(sizeof(float) * kKernelStorageSize, 16))), |
input_buffer_(static_cast<float*>( |
- base::AlignedAlloc(sizeof(float) * input_buffer_size_, 16))), |
+ AlignedMalloc(sizeof(float) * input_buffer_size_, 16))), |
+#if defined(WEBRTC_RESAMPLER_CPU_DETECTION) |
+ convolve_proc_(NULL), |
+#endif |
r1_(input_buffer_.get()), |
r2_(input_buffer_.get() + kKernelSize / 2) { |
- CHECK_GT(request_frames_, 0); |
+#if defined(WEBRTC_RESAMPLER_CPU_DETECTION) |
+ InitializeCPUSpecificFeatures(); |
+ assert(convolve_proc_); |
+#endif |
+ assert(request_frames_ > 0); |
Flush(); |
- CHECK_GT(block_size_, kKernelSize) |
- << "block_size must be greater than kKernelSize!"; |
+ assert(block_size_ > kKernelSize); |
memset(kernel_storage_.get(), 0, |
sizeof(*kernel_storage_.get()) * kKernelStorageSize); |
@@ -181,11 +198,11 @@ void SincResampler::UpdateRegions(bool second_load) { |
block_size_ = r4_ - r2_; |
// r1_ at the beginning of the buffer. |
- CHECK_EQ(r1_, input_buffer_.get()); |
+ assert(r1_ == input_buffer_.get()); |
// r1_ left of r2_, r4_ left of r3_ and size correct. |
- CHECK_EQ(r2_ - r1_, r4_ - r3_); |
+ assert(r2_ - r1_ == r4_ - r3_); |
// r2_ left of r3. |
- CHECK_LT(r2_, r3_); |
+ assert(r2_ < r3_); |
} |
void SincResampler::InitializeKernel() { |
@@ -205,20 +222,20 @@ void SincResampler::InitializeKernel() { |
for (int i = 0; i < kKernelSize; ++i) { |
const int idx = i + offset_idx * kKernelSize; |
const float pre_sinc = M_PI * (i - kKernelSize / 2 - subsample_offset); |
- kernel_pre_sinc_storage_[idx] = pre_sinc; |
+ kernel_pre_sinc_storage_.get()[idx] = pre_sinc; |
// Compute Blackman window, matching the offset of the sinc(). |
const float x = (i - subsample_offset) / kKernelSize; |
const float window = kA0 - kA1 * cos(2.0 * M_PI * x) + kA2 |
* cos(4.0 * M_PI * x); |
- kernel_window_storage_[idx] = window; |
+ kernel_window_storage_.get()[idx] = window; |
// Compute the sinc with offset, then window the sinc() function and store |
// at the correct offset. |
if (pre_sinc == 0) { |
- kernel_storage_[idx] = sinc_scale_factor * window; |
+ kernel_storage_.get()[idx] = sinc_scale_factor * window; |
} else { |
- kernel_storage_[idx] = |
+ kernel_storage_.get()[idx] = |
window * sin(sinc_scale_factor * pre_sinc) / pre_sinc; |
} |
} |
@@ -239,13 +256,13 @@ void SincResampler::SetRatio(double io_sample_rate_ratio) { |
for (int offset_idx = 0; offset_idx <= kKernelOffsetCount; ++offset_idx) { |
for (int i = 0; i < kKernelSize; ++i) { |
const int idx = i + offset_idx * kKernelSize; |
- const float window = kernel_window_storage_[idx]; |
- const float pre_sinc = kernel_pre_sinc_storage_[idx]; |
+ const float window = kernel_window_storage_.get()[idx]; |
+ const float pre_sinc = kernel_pre_sinc_storage_.get()[idx]; |
if (pre_sinc == 0) { |
- kernel_storage_[idx] = sinc_scale_factor * window; |
+ kernel_storage_.get()[idx] = sinc_scale_factor * window; |
} else { |
- kernel_storage_[idx] = |
+ kernel_storage_.get()[idx] = |
window * sin(sinc_scale_factor * pre_sinc) / pre_sinc; |
} |
} |
@@ -257,7 +274,7 @@ void SincResampler::Resample(int frames, float* destination) { |
// Step (1) -- Prime the input buffer at the start of the input stream. |
if (!buffer_primed_ && remaining_frames) { |
- read_cb_.Run(request_frames_, r0_); |
+ read_cb_->Run(request_frames_, r0_); |
buffer_primed_ = true; |
} |
@@ -273,7 +290,7 @@ void SincResampler::Resample(int frames, float* destination) { |
// or when built with clang. See https://codereview.chromium.org/18566009/ |
for (int i = ceil((block_size_ - virtual_source_idx_) / current_io_ratio); |
i > 0; --i) { |
- DCHECK_LT(virtual_source_idx_, block_size_); |
+ assert(virtual_source_idx_ < block_size_); |
// |virtual_source_idx_| lies in between two kernel offsets so figure out |
// what they are. |
@@ -291,8 +308,8 @@ void SincResampler::Resample(int frames, float* destination) { |
// Ensure |k1|, |k2| are 16-byte aligned for SIMD usage. Should always be |
// true so long as kKernelSize is a multiple of 16. |
- DCHECK_EQ(0u, reinterpret_cast<uintptr_t>(k1) & 0x0F); |
- DCHECK_EQ(0u, reinterpret_cast<uintptr_t>(k2) & 0x0F); |
+ assert(0u == (reinterpret_cast<uintptr_t>(k1) & 0x0F)); |
+ assert(0u == (reinterpret_cast<uintptr_t>(k2) & 0x0F)); |
// Initialize input pointer based on quantized |virtual_source_idx_|. |
const float* const input_ptr = r1_ + source_idx; |
@@ -322,7 +339,7 @@ void SincResampler::Resample(int frames, float* destination) { |
UpdateRegions(true); |
// Step (5) -- Refresh the buffer with more input. |
- read_cb_.Run(request_frames_, r0_); |
+ read_cb_->Run(request_frames_, r0_); |
} |
} |
@@ -359,33 +376,4 @@ float SincResampler::Convolve_C(const float* input_ptr, const float* k1, |
+ kernel_interpolation_factor * sum2; |
} |
-#if defined(ARCH_CPU_ARM_FAMILY) && defined(USE_NEON) |
-float SincResampler::Convolve_NEON(const float* input_ptr, const float* k1, |
- const float* k2, |
- double kernel_interpolation_factor) { |
- float32x4_t m_input; |
- float32x4_t m_sums1 = vmovq_n_f32(0); |
- float32x4_t m_sums2 = vmovq_n_f32(0); |
- |
- const float* upper = input_ptr + kKernelSize; |
- for (; input_ptr < upper; ) { |
- m_input = vld1q_f32(input_ptr); |
- input_ptr += 4; |
- m_sums1 = vmlaq_f32(m_sums1, m_input, vld1q_f32(k1)); |
- k1 += 4; |
- m_sums2 = vmlaq_f32(m_sums2, m_input, vld1q_f32(k2)); |
- k2 += 4; |
- } |
- |
- // Linearly interpolate the two "convolutions". |
- m_sums1 = vmlaq_f32( |
- vmulq_f32(m_sums1, vmovq_n_f32(1.0 - kernel_interpolation_factor)), |
- m_sums2, vmovq_n_f32(kernel_interpolation_factor)); |
- |
- // Sum components together. |
- float32x2_t m_half = vadd_f32(vget_high_f32(m_sums1), vget_low_f32(m_sums1)); |
- return vget_lane_f32(vpadd_f32(m_half, m_half), 0); |
-} |
-#endif |
- |
-} // namespace media |
+} // namespace webrtc |