Line data Source code
1 : /*
2 : * Copyright (c) 2012 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/modules/audio_processing/low_cut_filter.h"
12 :
13 : #include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
14 : #include "webrtc/modules/audio_processing/audio_buffer.h"
15 : #include "webrtc/system_wrappers/include/critical_section_wrapper.h"
16 :
17 : namespace webrtc {
18 : namespace {
19 : const int16_t kFilterCoefficients8kHz[5] = {3798, -7596, 3798, 7807, -3733};
20 : const int16_t kFilterCoefficients[5] = {4012, -8024, 4012, 8002, -3913};
21 : } // namespace
22 :
23 : class LowCutFilter::BiquadFilter {
24 : public:
25 0 : explicit BiquadFilter(int sample_rate_hz)
26 0 : : ba_(sample_rate_hz == AudioProcessing::kSampleRate8kHz
27 : ? kFilterCoefficients8kHz
28 0 : : kFilterCoefficients) {
29 0 : std::memset(x_, 0, sizeof(x_));
30 0 : std::memset(y_, 0, sizeof(y_));
31 0 : }
32 :
33 0 : void Process(int16_t* data, size_t length) {
34 0 : const int16_t* const ba = ba_;
35 0 : int16_t* x = x_;
36 0 : int16_t* y = y_;
37 0 : int32_t tmp_int32 = 0;
38 :
39 0 : for (size_t i = 0; i < length; i++) {
40 : // y[i] = b[0] * x[i] + b[1] * x[i-1] + b[2] * x[i-2]
41 : // + -a[1] * y[i-1] + -a[2] * y[i-2];
42 :
43 0 : tmp_int32 = y[1] * ba[3]; // -a[1] * y[i-1] (low part)
44 0 : tmp_int32 += y[3] * ba[4]; // -a[2] * y[i-2] (low part)
45 0 : tmp_int32 = (tmp_int32 >> 15);
46 0 : tmp_int32 += y[0] * ba[3]; // -a[1] * y[i-1] (high part)
47 0 : tmp_int32 += y[2] * ba[4]; // -a[2] * y[i-2] (high part)
48 0 : tmp_int32 = (tmp_int32 << 1);
49 :
50 0 : tmp_int32 += data[i] * ba[0]; // b[0] * x[0]
51 0 : tmp_int32 += x[0] * ba[1]; // b[1] * x[i-1]
52 0 : tmp_int32 += x[1] * ba[2]; // b[2] * x[i-2]
53 :
54 : // Update state (input part).
55 0 : x[1] = x[0];
56 0 : x[0] = data[i];
57 :
58 : // Update state (filtered part).
59 0 : y[2] = y[0];
60 0 : y[3] = y[1];
61 0 : y[0] = static_cast<int16_t>(tmp_int32 >> 13);
62 0 : y[1] = static_cast<int16_t>(
63 0 : (tmp_int32 - (static_cast<int32_t>(y[0]) << 13)) << 2);
64 :
65 : // Rounding in Q12, i.e. add 2^11.
66 0 : tmp_int32 += 2048;
67 :
68 : // Saturate (to 2^27) so that the HP filtered signal does not overflow.
69 0 : tmp_int32 = WEBRTC_SPL_SAT(static_cast<int32_t>(134217727), tmp_int32,
70 : static_cast<int32_t>(-134217728));
71 :
72 : // Convert back to Q0 and use rounding.
73 0 : data[i] = static_cast<int16_t>(tmp_int32 >> 12);
74 : }
75 0 : }
76 :
77 : private:
78 : const int16_t* const ba_ = nullptr;
79 : int16_t x_[2];
80 : int16_t y_[4];
81 : };
82 :
83 0 : LowCutFilter::LowCutFilter(size_t channels, int sample_rate_hz) {
84 0 : filters_.resize(channels);
85 0 : for (size_t i = 0; i < channels; i++) {
86 0 : filters_[i].reset(new BiquadFilter(sample_rate_hz));
87 : }
88 0 : }
89 :
90 0 : LowCutFilter::~LowCutFilter() {}
91 :
92 0 : void LowCutFilter::Process(AudioBuffer* audio) {
93 0 : RTC_DCHECK(audio);
94 0 : RTC_DCHECK_GE(160, audio->num_frames_per_band());
95 0 : RTC_DCHECK_EQ(filters_.size(), audio->num_channels());
96 0 : for (size_t i = 0; i < filters_.size(); i++) {
97 0 : filters_[i]->Process(audio->split_bands(i)[kBand0To8kHz],
98 0 : audio->num_frames_per_band());
99 : }
100 0 : }
101 :
102 : } // namespace webrtc
|