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