Home | History | Annotate | Download | only in common_audio
      1 /*
      2  *  Copyright (c) 2014 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 #include "webrtc/common_audio/fir_filter.h"
     12 
     13 #include <assert.h>
     14 #include <string.h>
     15 
     16 #include "webrtc/base/scoped_ptr.h"
     17 #include "webrtc/common_audio/fir_filter_neon.h"
     18 #include "webrtc/common_audio/fir_filter_sse.h"
     19 #include "webrtc/system_wrappers/include/cpu_features_wrapper.h"
     20 
     21 namespace webrtc {
     22 
     23 class FIRFilterC : public FIRFilter {
     24  public:
     25   FIRFilterC(const float* coefficients,
     26              size_t coefficients_length);
     27 
     28   void Filter(const float* in, size_t length, float* out) override;
     29 
     30  private:
     31   size_t coefficients_length_;
     32   size_t state_length_;
     33   rtc::scoped_ptr<float[]> coefficients_;
     34   rtc::scoped_ptr<float[]> state_;
     35 };
     36 
     37 FIRFilter* FIRFilter::Create(const float* coefficients,
     38                              size_t coefficients_length,
     39                              size_t max_input_length) {
     40   if (!coefficients || coefficients_length <= 0 || max_input_length <= 0) {
     41     assert(false);
     42     return NULL;
     43   }
     44 
     45   FIRFilter* filter = NULL;
     46 // If we know the minimum architecture at compile time, avoid CPU detection.
     47 #if defined(WEBRTC_ARCH_X86_FAMILY)
     48 #if defined(__SSE2__)
     49   filter =
     50       new FIRFilterSSE2(coefficients, coefficients_length, max_input_length);
     51 #else
     52   // x86 CPU detection required.
     53   if (WebRtc_GetCPUInfo(kSSE2)) {
     54     filter =
     55         new FIRFilterSSE2(coefficients, coefficients_length, max_input_length);
     56   } else {
     57     filter = new FIRFilterC(coefficients, coefficients_length);
     58   }
     59 #endif
     60 #elif defined(WEBRTC_HAS_NEON)
     61   filter =
     62       new FIRFilterNEON(coefficients, coefficients_length, max_input_length);
     63 #elif defined(WEBRTC_DETECT_NEON)
     64   if (WebRtc_GetCPUFeaturesARM() & kCPUFeatureNEON) {
     65     filter =
     66         new FIRFilterNEON(coefficients, coefficients_length, max_input_length);
     67   } else {
     68     filter = new FIRFilterC(coefficients, coefficients_length);
     69   }
     70 #else
     71   filter = new FIRFilterC(coefficients, coefficients_length);
     72 #endif
     73 
     74   return filter;
     75 }
     76 
     77 FIRFilterC::FIRFilterC(const float* coefficients, size_t coefficients_length)
     78     : coefficients_length_(coefficients_length),
     79       state_length_(coefficients_length - 1),
     80       coefficients_(new float[coefficients_length_]),
     81       state_(new float[state_length_]) {
     82   for (size_t i = 0; i < coefficients_length_; ++i) {
     83     coefficients_[i] = coefficients[coefficients_length_ - i - 1];
     84   }
     85   memset(state_.get(), 0, state_length_ * sizeof(state_[0]));
     86 }
     87 
     88 void FIRFilterC::Filter(const float* in, size_t length, float* out) {
     89   assert(length > 0);
     90 
     91   // Convolves the input signal |in| with the filter kernel |coefficients_|
     92   // taking into account the previous state.
     93   for (size_t i = 0; i < length; ++i) {
     94     out[i] = 0.f;
     95     size_t j;
     96     for (j = 0; state_length_ > i && j < state_length_ - i; ++j) {
     97       out[i] += state_[i + j] * coefficients_[j];
     98     }
     99     for (; j < coefficients_length_; ++j) {
    100       out[i] += in[j + i - state_length_] * coefficients_[j];
    101     }
    102   }
    103 
    104   // Update current state.
    105   if (length >= state_length_) {
    106     memcpy(
    107         state_.get(), &in[length - state_length_], state_length_ * sizeof(*in));
    108   } else {
    109     memmove(state_.get(),
    110             &state_[length],
    111             (state_length_ - length) * sizeof(state_[0]));
    112     memcpy(&state_[state_length_ - length], in, length * sizeof(*in));
    113   }
    114 }
    115 
    116 }  // namespace webrtc
    117