| 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::BiquadFilter { |
| 27 {4012, -8024, 4012, 8002, -3913}; | 24 public: |
| 25 explicit BiquadFilter(int sample_rate_hz) : |
| 26 ba_(sample_rate_hz == AudioProcessing::kSampleRate8kHz ? |
| 27 kFilterCoefficients8kHz : kFilterCoefficients) |
| 28 { |
| 29 std::memset(x_, 0, sizeof(x_)); |
| 30 std::memset(y_, 0, sizeof(y_)); |
| 31 } |
| 28 | 32 |
| 29 struct FilterState { | 33 void Process(int16_t* data, size_t length) { |
| 30 int16_t y[4]; | 34 const int16_t* const ba = ba_; |
| 31 int16_t x[2]; | 35 int16_t* x = x_; |
| 32 const int16_t* ba; | 36 int16_t* y = y_; |
| 37 int32_t tmp_int32 = 0; |
| 38 |
| 39 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 tmp_int32 = y[1] * ba[3]; // -a[1] * y[i-1] (low part) |
| 44 tmp_int32 += y[3] * ba[4]; // -a[2] * y[i-2] (low part) |
| 45 tmp_int32 = (tmp_int32 >> 15); |
| 46 tmp_int32 += y[0] * ba[3]; // -a[1] * y[i-1] (high part) |
| 47 tmp_int32 += y[2] * ba[4]; // -a[2] * y[i-2] (high part) |
| 48 tmp_int32 = (tmp_int32 << 1); |
| 49 |
| 50 tmp_int32 += data[i] * ba[0]; // b[0] * x[0] |
| 51 tmp_int32 += x[0] * ba[1]; // b[1] * x[i-1] |
| 52 tmp_int32 += x[1] * ba[2]; // b[2] * x[i-2] |
| 53 |
| 54 // Update state (input part). |
| 55 x[1] = x[0]; |
| 56 x[0] = data[i]; |
| 57 |
| 58 // Update state (filtered part). |
| 59 y[2] = y[0]; |
| 60 y[3] = y[1]; |
| 61 y[0] = static_cast<int16_t>(tmp_int32 >> 13); |
| 62 y[1] = static_cast<int16_t>( |
| 63 (tmp_int32 - (static_cast<int32_t>(y[0]) << 13)) << 2); |
| 64 |
| 65 // Rounding in Q12, i.e. add 2^11. |
| 66 tmp_int32 += 2048; |
| 67 |
| 68 // Saturate (to 2^27) so that the HP filtered signal does not overflow. |
| 69 tmp_int32 = WEBRTC_SPL_SAT(static_cast<int32_t>(134217727), |
| 70 tmp_int32, |
| 71 static_cast<int32_t>(-134217728)); |
| 72 |
| 73 // Convert back to Q0 and use rounding. |
| 74 data[i] = static_cast<int16_t>(tmp_int32 >> 12); |
| 75 } |
| 76 } |
| 77 |
| 78 private: |
| 79 const int16_t* const ba_ = nullptr; |
| 80 int16_t x_[2]; |
| 81 int16_t y_[4]; |
| 33 }; | 82 }; |
| 34 | 83 |
| 35 int InitializeFilter(FilterState* hpf, int sample_rate_hz) { | 84 HighPassFilterImpl::HighPassFilterImpl(rtc::CriticalSection* crit) |
| 36 assert(hpf != NULL); | 85 : crit_(crit) { |
| 37 | 86 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 } | 87 } |
| 108 | 88 |
| 109 HighPassFilterImpl::~HighPassFilterImpl() {} | 89 HighPassFilterImpl::~HighPassFilterImpl() {} |
| 110 | 90 |
| 111 int HighPassFilterImpl::ProcessCaptureAudio(AudioBuffer* audio) { | 91 void HighPassFilterImpl::Initialize(int channels, int sample_rate_hz) { |
| 92 std::vector<rtc::scoped_ptr<BiquadFilter>> new_filters(channels); |
| 93 for (int i = 0; i < channels; i++) { |
| 94 new_filters[i].reset(new BiquadFilter(sample_rate_hz)); |
| 95 } |
| 112 rtc::CritScope cs(crit_); | 96 rtc::CritScope cs(crit_); |
| 113 int err = AudioProcessing::kNoError; | 97 filters_.swap(new_filters); |
| 98 } |
| 114 | 99 |
| 115 if (!is_component_enabled()) { | 100 void HighPassFilterImpl::ProcessCaptureAudio(AudioBuffer* audio) { |
| 116 return AudioProcessing::kNoError; | 101 rtc::CritScope cs(crit_); |
| 102 if (!enabled_) { |
| 103 return; |
| 117 } | 104 } |
| 118 | 105 |
| 119 assert(audio->num_frames_per_band() <= 160); | 106 RTC_DCHECK_GE(160u, audio->num_frames_per_band()); |
| 120 | 107 RTC_DCHECK_EQ(filters_.size(), static_cast<size_t>(audio->num_channels())); |
| 121 for (int i = 0; i < num_handles(); i++) { | 108 for (size_t i = 0; i < filters_.size(); i++) { |
| 122 Handle* my_handle = static_cast<Handle*>(handle(i)); | 109 filters_[i]->Process(audio->split_bands(i)[kBand0To8kHz], |
| 123 err = Filter(my_handle, | 110 audio->num_frames_per_band()); |
| 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 } | 111 } |
| 131 | |
| 132 return AudioProcessing::kNoError; | |
| 133 } | 112 } |
| 134 | 113 |
| 135 int HighPassFilterImpl::Enable(bool enable) { | 114 int HighPassFilterImpl::Enable(bool enable) { |
| 136 rtc::CritScope cs(crit_); | 115 rtc::CritScope cs(crit_); |
| 137 return EnableComponent(enable); | 116 enabled_ = enable; |
| 117 return AudioProcessing::kNoError; |
| 138 } | 118 } |
| 139 | 119 |
| 140 bool HighPassFilterImpl::is_enabled() const { | 120 bool HighPassFilterImpl::is_enabled() const { |
| 141 rtc::CritScope cs(crit_); | 121 rtc::CritScope cs(crit_); |
| 142 return is_component_enabled(); | 122 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 } | 123 } |
| 174 } // namespace webrtc | 124 } // namespace webrtc |
| OLD | NEW |