OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #include "webrtc/modules/audio_processing/high_pass_filter_impl.h" | 11 #include "webrtc/modules/audio_processing/high_pass_filter_impl.h" |
12 | 12 |
13 #include <assert.h> | |
14 | |
15 #include "webrtc/common_audio/signal_processing/include/signal_processing_librar y.h" | 13 #include "webrtc/common_audio/signal_processing/include/signal_processing_librar y.h" |
16 #include "webrtc/modules/audio_processing/audio_buffer.h" | 14 #include "webrtc/modules/audio_processing/audio_buffer.h" |
17 #include "webrtc/system_wrappers/include/critical_section_wrapper.h" | 15 #include "webrtc/system_wrappers/include/critical_section_wrapper.h" |
18 #include "webrtc/typedefs.h" | |
19 | |
20 | 16 |
21 namespace webrtc { | 17 namespace webrtc { |
22 namespace { | 18 namespace { |
23 const int16_t kFilterCoefficients8kHz[5] = | 19 const int16_t kFilterCoefficients8kHz[5] = {3798, -7596, 3798, 7807, -3733}; |
24 {3798, -7596, 3798, 7807, -3733}; | 20 const int16_t kFilterCoefficients[5] = {4012, -8024, 4012, 8002, -3913}; |
21 } // namespace | |
25 | 22 |
26 const int16_t kFilterCoefficients[5] = | 23 class HighPassFilterImpl::MonoFilter { |
27 {4012, -8024, 4012, 8002, -3913}; | 24 public: |
25 explicit MonoFilter(int sample_rate_hz) { | |
hlundin-webrtc
2015/12/04 12:30:09
If you initialize ba_ as
explicit MonoFilter(int s
the sun
2015/12/04 14:53:31
Done.
| |
26 if (sample_rate_hz == AudioProcessing::kSampleRate8kHz) { | |
27 ba_ = kFilterCoefficients8kHz; | |
28 } else { | |
29 ba_ = kFilterCoefficients; | |
30 } | |
31 std::memset(x_, 0, sizeof(x_)); | |
32 std::memset(y_, 0, sizeof(y_)); | |
33 } | |
28 | 34 |
29 struct FilterState { | 35 void Filter(int16_t* data, size_t length) { |
30 int16_t y[4]; | 36 const int16_t* ba = ba_; |
hlundin-webrtc
2015/12/04 12:30:09
Why these local variables? ba, x, and y. (I guess
the sun
2015/12/04 14:53:31
I've tried not to touch the actual implementation
hlundin-webrtc
2015/12/04 15:11:09
Acknowledged.
| |
31 int16_t x[2]; | 37 int16_t* x = x_; |
32 const int16_t* ba; | 38 int16_t* y = y_; |
39 int32_t tmp_int32 = 0; | |
40 | |
41 for (size_t i = 0; i < length; i++) { | |
42 // y[i] = b[0] * x[i] + b[1] * x[i-1] + b[2] * x[i-2] | |
43 // + -a[1] * y[i-1] + -a[2] * y[i-2]; | |
44 | |
45 tmp_int32 = y[1] * ba[3]; // -a[1] * y[i-1] (low part) | |
hlundin-webrtc
2015/12/04 12:30:09
Did you git cl format this? I was expecting the co
the sun
2015/12/04 14:53:30
Done.
| |
46 tmp_int32 += y[3] * ba[4]; // -a[2] * y[i-2] (low part) | |
47 tmp_int32 = (tmp_int32 >> 15); | |
48 tmp_int32 += y[0] * ba[3]; // -a[1] * y[i-1] (high part) | |
49 tmp_int32 += y[2] * ba[4]; // -a[2] * y[i-2] (high part) | |
50 tmp_int32 = (tmp_int32 << 1); | |
51 | |
52 tmp_int32 += data[i] * ba[0]; // b[0]*x[0] | |
53 tmp_int32 += x[0] * ba[1]; // b[1]*x[i-1] | |
54 tmp_int32 += x[1] * ba[2]; // b[2]*x[i-2] | |
55 | |
56 // Update state (input part) | |
57 x[1] = x[0]; | |
58 x[0] = data[i]; | |
59 | |
60 // Update state (filtered part) | |
61 y[2] = y[0]; | |
62 y[3] = y[1]; | |
63 y[0] = static_cast<int16_t>(tmp_int32 >> 13); | |
64 y[1] = static_cast<int16_t>( | |
65 (tmp_int32 - (static_cast<int32_t>(y[0]) << 13)) << 2); | |
66 | |
67 // Rounding in Q12, i.e. add 2^11 | |
hlundin-webrtc
2015/12/04 12:30:09
End with .
the sun
2015/12/04 14:53:30
Done.
| |
68 tmp_int32 += 2048; | |
69 | |
70 // Saturate (to 2^27) so that the HP filtered signal does not overflow | |
hlundin-webrtc
2015/12/04 12:30:09
End with .
the sun
2015/12/04 14:53:31
Done.
| |
71 tmp_int32 = WEBRTC_SPL_SAT(static_cast<int32_t>(134217727), | |
72 tmp_int32, | |
73 static_cast<int32_t>(-134217728)); | |
74 | |
75 // Convert back to Q0 and use rounding. | |
76 data[i] = static_cast<int16_t>(tmp_int32 >> 12); | |
77 } | |
78 } | |
79 | |
80 private: | |
81 const int16_t* ba_ = nullptr; | |
82 int16_t x_[2]; | |
83 int16_t y_[4]; | |
33 }; | 84 }; |
34 | 85 |
35 int InitializeFilter(FilterState* hpf, int sample_rate_hz) { | 86 HighPassFilterImpl::HighPassFilterImpl(rtc::CriticalSection* crit) |
36 assert(hpf != NULL); | 87 : crit_(crit) { |
37 | 88 RTC_DCHECK(crit_); |
38 if (sample_rate_hz == AudioProcessing::kSampleRate8kHz) { | |
39 hpf->ba = kFilterCoefficients8kHz; | |
40 } else { | |
41 hpf->ba = kFilterCoefficients; | |
42 } | |
43 | |
44 WebRtcSpl_MemSetW16(hpf->x, 0, 2); | |
45 WebRtcSpl_MemSetW16(hpf->y, 0, 4); | |
46 | |
47 return AudioProcessing::kNoError; | |
48 } | |
49 | |
50 int Filter(FilterState* hpf, int16_t* data, size_t length) { | |
51 assert(hpf != NULL); | |
52 | |
53 int32_t tmp_int32 = 0; | |
54 int16_t* y = hpf->y; | |
55 int16_t* x = hpf->x; | |
56 const int16_t* ba = hpf->ba; | |
57 | |
58 for (size_t i = 0; i < length; i++) { | |
59 // y[i] = b[0] * x[i] + b[1] * x[i-1] + b[2] * x[i-2] | |
60 // + -a[1] * y[i-1] + -a[2] * y[i-2]; | |
61 | |
62 tmp_int32 = y[1] * ba[3]; // -a[1] * y[i-1] (low part) | |
63 tmp_int32 += y[3] * ba[4]; // -a[2] * y[i-2] (low part) | |
64 tmp_int32 = (tmp_int32 >> 15); | |
65 tmp_int32 += y[0] * ba[3]; // -a[1] * y[i-1] (high part) | |
66 tmp_int32 += y[2] * ba[4]; // -a[2] * y[i-2] (high part) | |
67 tmp_int32 = (tmp_int32 << 1); | |
68 | |
69 tmp_int32 += data[i] * ba[0]; // b[0]*x[0] | |
70 tmp_int32 += x[0] * ba[1]; // b[1]*x[i-1] | |
71 tmp_int32 += x[1] * ba[2]; // b[2]*x[i-2] | |
72 | |
73 // Update state (input part) | |
74 x[1] = x[0]; | |
75 x[0] = data[i]; | |
76 | |
77 // Update state (filtered part) | |
78 y[2] = y[0]; | |
79 y[3] = y[1]; | |
80 y[0] = static_cast<int16_t>(tmp_int32 >> 13); | |
81 y[1] = static_cast<int16_t>( | |
82 (tmp_int32 - (static_cast<int32_t>(y[0]) << 13)) << 2); | |
83 | |
84 // Rounding in Q12, i.e. add 2^11 | |
85 tmp_int32 += 2048; | |
86 | |
87 // Saturate (to 2^27) so that the HP filtered signal does not overflow | |
88 tmp_int32 = WEBRTC_SPL_SAT(static_cast<int32_t>(134217727), | |
89 tmp_int32, | |
90 static_cast<int32_t>(-134217728)); | |
91 | |
92 // Convert back to Q0 and use rounding. | |
93 data[i] = (int16_t)(tmp_int32 >> 12); | |
94 } | |
95 | |
96 return AudioProcessing::kNoError; | |
97 } | |
98 } // namespace | |
99 | |
100 typedef FilterState Handle; | |
101 | |
102 HighPassFilterImpl::HighPassFilterImpl(const AudioProcessing* apm, | |
103 rtc::CriticalSection* crit) | |
104 : ProcessingComponent(), apm_(apm), crit_(crit) { | |
105 RTC_DCHECK(apm); | |
106 RTC_DCHECK(crit); | |
107 } | 89 } |
108 | 90 |
109 HighPassFilterImpl::~HighPassFilterImpl() {} | 91 HighPassFilterImpl::~HighPassFilterImpl() {} |
110 | 92 |
111 int HighPassFilterImpl::ProcessCaptureAudio(AudioBuffer* audio) { | 93 void HighPassFilterImpl::Initialize(int channels, int sample_rate_hz) { |
112 rtc::CritScope cs(crit_); | 94 rtc::CritScope cs(crit_); |
113 int err = AudioProcessing::kNoError; | 95 std::vector<rtc::scoped_ptr<MonoFilter>> new_filters(channels); |
96 for (int i = 0; i < channels; i++) { | |
97 new_filters[i].reset(new MonoFilter(sample_rate_hz)); | |
98 } | |
99 filters_.swap(new_filters); | |
100 } | |
114 | 101 |
115 if (!is_component_enabled()) { | 102 void HighPassFilterImpl::ProcessCaptureAudio(AudioBuffer* audio) { |
116 return AudioProcessing::kNoError; | 103 rtc::CritScope cs(crit_); |
104 if (!enabled_) { | |
105 return; | |
117 } | 106 } |
118 | 107 |
119 assert(audio->num_frames_per_band() <= 160); | 108 RTC_DCHECK_LE(audio->num_frames_per_band(), 160u); |
120 | 109 for (size_t i = 0; i < filters_.size(); i++) { |
121 for (int i = 0; i < num_handles(); i++) { | 110 filters_[i]->Filter(audio->split_bands(i)[kBand0To8kHz], |
122 Handle* my_handle = static_cast<Handle*>(handle(i)); | 111 audio->num_frames_per_band()); |
123 err = Filter(my_handle, | |
124 audio->split_bands(i)[kBand0To8kHz], | |
125 audio->num_frames_per_band()); | |
126 | |
127 if (err != AudioProcessing::kNoError) { | |
128 return GetHandleError(my_handle); | |
129 } | |
130 } | 112 } |
131 | |
132 return AudioProcessing::kNoError; | |
133 } | 113 } |
134 | 114 |
135 int HighPassFilterImpl::Enable(bool enable) { | 115 int HighPassFilterImpl::Enable(bool enable) { |
136 rtc::CritScope cs(crit_); | 116 rtc::CritScope cs(crit_); |
137 return EnableComponent(enable); | 117 enabled_ = enable; |
118 return AudioProcessing::kNoError; | |
138 } | 119 } |
139 | 120 |
140 bool HighPassFilterImpl::is_enabled() const { | 121 bool HighPassFilterImpl::is_enabled() const { |
141 rtc::CritScope cs(crit_); | 122 rtc::CritScope cs(crit_); |
142 return is_component_enabled(); | 123 return enabled_; |
143 } | |
144 | |
145 void* HighPassFilterImpl::CreateHandle() const { | |
146 return new FilterState; | |
147 } | |
148 | |
149 void HighPassFilterImpl::DestroyHandle(void* handle) const { | |
150 delete static_cast<Handle*>(handle); | |
151 } | |
152 | |
153 int HighPassFilterImpl::InitializeHandle(void* handle) const { | |
154 // TODO(peah): Remove dependency on apm for the | |
155 // capture side sample rate. | |
156 rtc::CritScope cs(crit_); | |
157 return InitializeFilter(static_cast<Handle*>(handle), | |
158 apm_->proc_sample_rate_hz()); | |
159 } | |
160 | |
161 int HighPassFilterImpl::ConfigureHandle(void* /*handle*/) const { | |
162 return AudioProcessing::kNoError; // Not configurable. | |
163 } | |
164 | |
165 int HighPassFilterImpl::num_handles_required() const { | |
166 return apm_->num_output_channels(); | |
167 } | |
168 | |
169 int HighPassFilterImpl::GetHandleError(void* handle) const { | |
170 // The component has no detailed errors. | |
171 assert(handle != NULL); | |
172 return AudioProcessing::kUnspecifiedError; | |
173 } | 124 } |
174 } // namespace webrtc | 125 } // namespace webrtc |
OLD | NEW |