1 /*
2 * Copyright (c) 2016 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 #include "modules/audio_processing/utility/cascaded_biquad_filter.h"
11
12 #include <algorithm>
13
14 #include "rtc_base/checks.h"
15
16 namespace webrtc {
17
BiQuadParam(std::complex<float> zero,std::complex<float> pole,float gain,bool mirror_zero_along_i_axis)18 CascadedBiQuadFilter::BiQuadParam::BiQuadParam(std::complex<float> zero,
19 std::complex<float> pole,
20 float gain,
21 bool mirror_zero_along_i_axis)
22 : zero(zero),
23 pole(pole),
24 gain(gain),
25 mirror_zero_along_i_axis(mirror_zero_along_i_axis) {}
26
27 CascadedBiQuadFilter::BiQuadParam::BiQuadParam(const BiQuadParam&) = default;
28
BiQuad(const CascadedBiQuadFilter::BiQuadParam & param)29 CascadedBiQuadFilter::BiQuad::BiQuad(
30 const CascadedBiQuadFilter::BiQuadParam& param)
31 : x(), y() {
32 float z_r = std::real(param.zero);
33 float z_i = std::imag(param.zero);
34 float p_r = std::real(param.pole);
35 float p_i = std::imag(param.pole);
36 float gain = param.gain;
37
38 if (param.mirror_zero_along_i_axis) {
39 // Assuming zeroes at z_r and -z_r.
40 RTC_DCHECK(z_i == 0.f);
41 coefficients.b[0] = gain * 1.f;
42 coefficients.b[1] = 0.f;
43 coefficients.b[2] = gain * -(z_r * z_r);
44 } else {
45 // Assuming zeros at (z_r + z_i*i) and (z_r - z_i*i).
46 coefficients.b[0] = gain * 1.f;
47 coefficients.b[1] = gain * -2.f * z_r;
48 coefficients.b[2] = gain * (z_r * z_r + z_i * z_i);
49 }
50
51 // Assuming poles at (p_r + p_i*i) and (p_r - p_i*i).
52 coefficients.a[0] = -2.f * p_r;
53 coefficients.a[1] = p_r * p_r + p_i * p_i;
54 }
55
Reset()56 void CascadedBiQuadFilter::BiQuad::BiQuad::Reset() {
57 x[0] = x[1] = y[0] = y[1] = 0.f;
58 }
59
CascadedBiQuadFilter(const CascadedBiQuadFilter::BiQuadCoefficients & coefficients,size_t num_biquads)60 CascadedBiQuadFilter::CascadedBiQuadFilter(
61 const CascadedBiQuadFilter::BiQuadCoefficients& coefficients,
62 size_t num_biquads)
63 : biquads_(num_biquads, BiQuad(coefficients)) {}
64
CascadedBiQuadFilter(const std::vector<CascadedBiQuadFilter::BiQuadParam> & biquad_params)65 CascadedBiQuadFilter::CascadedBiQuadFilter(
66 const std::vector<CascadedBiQuadFilter::BiQuadParam>& biquad_params) {
67 for (const auto& param : biquad_params) {
68 biquads_.push_back(BiQuad(param));
69 }
70 }
71
72 CascadedBiQuadFilter::~CascadedBiQuadFilter() = default;
73
Process(rtc::ArrayView<const float> x,rtc::ArrayView<float> y)74 void CascadedBiQuadFilter::Process(rtc::ArrayView<const float> x,
75 rtc::ArrayView<float> y) {
76 if (biquads_.size() > 0) {
77 ApplyBiQuad(x, y, &biquads_[0]);
78 for (size_t k = 1; k < biquads_.size(); ++k) {
79 ApplyBiQuad(y, y, &biquads_[k]);
80 }
81 } else {
82 std::copy(x.begin(), x.end(), y.begin());
83 }
84 }
85
Process(rtc::ArrayView<float> y)86 void CascadedBiQuadFilter::Process(rtc::ArrayView<float> y) {
87 for (auto& biquad : biquads_) {
88 ApplyBiQuad(y, y, &biquad);
89 }
90 }
91
Reset()92 void CascadedBiQuadFilter::Reset() {
93 for (auto& biquad : biquads_) {
94 biquad.Reset();
95 }
96 }
97
ApplyBiQuad(rtc::ArrayView<const float> x,rtc::ArrayView<float> y,CascadedBiQuadFilter::BiQuad * biquad)98 void CascadedBiQuadFilter::ApplyBiQuad(rtc::ArrayView<const float> x,
99 rtc::ArrayView<float> y,
100 CascadedBiQuadFilter::BiQuad* biquad) {
101 RTC_DCHECK_EQ(x.size(), y.size());
102 const auto* c_b = biquad->coefficients.b;
103 const auto* c_a = biquad->coefficients.a;
104 auto* m_x = biquad->x;
105 auto* m_y = biquad->y;
106 for (size_t k = 0; k < x.size(); ++k) {
107 const float tmp = x[k];
108 y[k] = c_b[0] * tmp + c_b[1] * m_x[0] + c_b[2] * m_x[1] - c_a[0] * m_y[0] -
109 c_a[1] * m_y[1];
110 m_x[1] = m_x[0];
111 m_x[0] = tmp;
112 m_y[1] = m_y[0];
113 m_y[0] = y[k];
114 }
115 }
116
117 } // namespace webrtc
118