137ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org/* 237ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. 337ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org * 437ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org * Use of this source code is governed by a BSD-style license 537ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org * that can be found in the LICENSE file in the root of the source 637ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org * tree. An additional intellectual property rights grant can be found 737ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org * in the file PATENTS. All contributing project authors may 837ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org * be found in the AUTHORS file in the root of the source tree. 937ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org */ 1037ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org 1137ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org#include "webrtc/common_audio/fir_filter.h" 1237ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org 1337ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org#include <assert.h> 1437ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org#include <string.h> 1537ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org 1600b8f6b3643332cce1ee711715f7fbb824d793cakwiberg@webrtc.org#include "webrtc/base/scoped_ptr.h" 1737ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org#include "webrtc/common_audio/fir_filter_neon.h" 1837ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org#include "webrtc/common_audio/fir_filter_sse.h" 1998f53510b222f71fdd8b799b2f33737ceeb28c61Henrik Kjellander#include "webrtc/system_wrappers/include/cpu_features_wrapper.h" 2037ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org 2137ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.orgnamespace webrtc { 2237ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org 2337ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.orgclass FIRFilterC : public FIRFilter { 2437ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org public: 2537ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org FIRFilterC(const float* coefficients, 2637ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org size_t coefficients_length); 2737ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org 2814665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org void Filter(const float* in, size_t length, float* out) override; 2937ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org 3037ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org private: 3137ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org size_t coefficients_length_; 3237ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org size_t state_length_; 3300b8f6b3643332cce1ee711715f7fbb824d793cakwiberg@webrtc.org rtc::scoped_ptr<float[]> coefficients_; 3400b8f6b3643332cce1ee711715f7fbb824d793cakwiberg@webrtc.org rtc::scoped_ptr<float[]> state_; 3537ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org}; 3637ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org 3737ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.orgFIRFilter* FIRFilter::Create(const float* coefficients, 3837ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org size_t coefficients_length, 3937ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org size_t max_input_length) { 4037ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org if (!coefficients || coefficients_length <= 0 || max_input_length <= 0) { 4137ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org assert(false); 4237ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org return NULL; 4337ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org } 4437ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org 4537ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org FIRFilter* filter = NULL; 4637ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org// If we know the minimum architecture at compile time, avoid CPU detection. 4737ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org#if defined(WEBRTC_ARCH_X86_FAMILY) 4837ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org#if defined(__SSE2__) 4937ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org filter = 5037ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org new FIRFilterSSE2(coefficients, coefficients_length, max_input_length); 5137ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org#else 5237ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org // x86 CPU detection required. 5337ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org if (WebRtc_GetCPUInfo(kSSE2)) { 5437ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org filter = 5537ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org new FIRFilterSSE2(coefficients, coefficients_length, max_input_length); 5637ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org } else { 5737ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org filter = new FIRFilterC(coefficients, coefficients_length); 5837ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org } 5937ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org#endif 60cb7f8ce2df7564546936d3041a96ccc86a90f988Andrew MacDonald#elif defined(WEBRTC_HAS_NEON) 6137ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org filter = 6237ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org new FIRFilterNEON(coefficients, coefficients_length, max_input_length); 63cb7f8ce2df7564546936d3041a96ccc86a90f988Andrew MacDonald#elif defined(WEBRTC_DETECT_NEON) 6437ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org if (WebRtc_GetCPUFeaturesARM() & kCPUFeatureNEON) { 6537ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org filter = 6637ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org new FIRFilterNEON(coefficients, coefficients_length, max_input_length); 6737ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org } else { 6837ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org filter = new FIRFilterC(coefficients, coefficients_length); 6937ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org } 7037ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org#else 7137ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org filter = new FIRFilterC(coefficients, coefficients_length); 7237ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org#endif 7337ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org 7437ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org return filter; 7537ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org} 7637ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org 7737ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.orgFIRFilterC::FIRFilterC(const float* coefficients, size_t coefficients_length) 7837ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org : coefficients_length_(coefficients_length), 7937ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org state_length_(coefficients_length - 1), 8037ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org coefficients_(new float[coefficients_length_]), 8137ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org state_(new float[state_length_]) { 8237ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org for (size_t i = 0; i < coefficients_length_; ++i) { 8337ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org coefficients_[i] = coefficients[coefficients_length_ - i - 1]; 8437ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org } 853cbd6c26c861a63f8f6164b7142d532a599f00e5bjornv@webrtc.org memset(state_.get(), 0, state_length_ * sizeof(state_[0])); 8637ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org} 8737ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org 8837ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.orgvoid FIRFilterC::Filter(const float* in, size_t length, float* out) { 8937ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org assert(length > 0); 9037ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org 9137ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org // Convolves the input signal |in| with the filter kernel |coefficients_| 9237ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org // taking into account the previous state. 9337ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org for (size_t i = 0; i < length; ++i) { 9437ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org out[i] = 0.f; 9537ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org size_t j; 9637ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org for (j = 0; state_length_ > i && j < state_length_ - i; ++j) { 9737ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org out[i] += state_[i + j] * coefficients_[j]; 9837ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org } 9937ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org for (; j < coefficients_length_; ++j) { 10037ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org out[i] += in[j + i - state_length_] * coefficients_[j]; 10137ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org } 10237ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org } 10337ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org 10437ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org // Update current state. 10537ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org if (length >= state_length_) { 10637ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org memcpy( 10737ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org state_.get(), &in[length - state_length_], state_length_ * sizeof(*in)); 10837ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org } else { 10937ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org memmove(state_.get(), 11037ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org &state_[length], 11137ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org (state_length_ - length) * sizeof(state_[0])); 11237ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org memcpy(&state_[state_length_ - length], in, length * sizeof(*in)); 11337ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org } 11437ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org} 11537ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org 11637ca765650adb36d3dd0ab84a507e660f44766c6aluebs@webrtc.org} // namespace webrtc 117