1470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/* 20c6f931420f1e8b697e31810c0b821bbd3d50585bjornv@webrtc.org * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * 4470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * Use of this source code is governed by a BSD-style license 5470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * that can be found in the LICENSE file in the root of the source 6470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * tree. An additional intellectual property rights grant can be found 7470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * in the file PATENTS. All contributing project authors may 8470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * be found in the AUTHORS file in the root of the source tree. 9470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com */ 10470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 117fad4b8c9f1e9a6e3de9962fb74d4953b4f1bb03pbos@webrtc.org#include "webrtc/modules/audio_processing/high_pass_filter_impl.h" 12470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 137fad4b8c9f1e9a6e3de9962fb74d4953b4f1bb03pbos@webrtc.org#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h" 1456e4a05053d6addc7dbbe2b4d07271305fdbea75andrew@webrtc.org#include "webrtc/modules/audio_processing/audio_buffer.h" 1598f53510b222f71fdd8b799b2f33737ceeb28c61Henrik Kjellander#include "webrtc/system_wrappers/include/critical_section_wrapper.h" 16470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 17470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comnamespace webrtc { 18470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comnamespace { 1970f9903e570931831a027ba6f91c164efc604a85solenbergconst int16_t kFilterCoefficients8kHz[5] = {3798, -7596, 3798, 7807, -3733}; 2070f9903e570931831a027ba6f91c164efc604a85solenbergconst int16_t kFilterCoefficients[5] = {4012, -8024, 4012, 8002, -3913}; 2170f9903e570931831a027ba6f91c164efc604a85solenberg} // namespace 22470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2370f9903e570931831a027ba6f91c164efc604a85solenbergclass HighPassFilterImpl::BiquadFilter { 2470f9903e570931831a027ba6f91c164efc604a85solenberg public: 2570f9903e570931831a027ba6f91c164efc604a85solenberg explicit BiquadFilter(int sample_rate_hz) : 2670f9903e570931831a027ba6f91c164efc604a85solenberg ba_(sample_rate_hz == AudioProcessing::kSampleRate8kHz ? 2770f9903e570931831a027ba6f91c164efc604a85solenberg kFilterCoefficients8kHz : kFilterCoefficients) 2870f9903e570931831a027ba6f91c164efc604a85solenberg { 29c1316a1e51231b717e335f2c4c5ed3bf860a42b3solenberg Reset(); 30c1316a1e51231b717e335f2c4c5ed3bf860a42b3solenberg } 31c1316a1e51231b717e335f2c4c5ed3bf860a42b3solenberg 32c1316a1e51231b717e335f2c4c5ed3bf860a42b3solenberg void Reset() { 3370f9903e570931831a027ba6f91c164efc604a85solenberg std::memset(x_, 0, sizeof(x_)); 3470f9903e570931831a027ba6f91c164efc604a85solenberg std::memset(y_, 0, sizeof(y_)); 35470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 36470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3770f9903e570931831a027ba6f91c164efc604a85solenberg void Process(int16_t* data, size_t length) { 3870f9903e570931831a027ba6f91c164efc604a85solenberg const int16_t* const ba = ba_; 3970f9903e570931831a027ba6f91c164efc604a85solenberg int16_t* x = x_; 4070f9903e570931831a027ba6f91c164efc604a85solenberg int16_t* y = y_; 4170f9903e570931831a027ba6f91c164efc604a85solenberg int32_t tmp_int32 = 0; 4270f9903e570931831a027ba6f91c164efc604a85solenberg 4370f9903e570931831a027ba6f91c164efc604a85solenberg for (size_t i = 0; i < length; i++) { 4470f9903e570931831a027ba6f91c164efc604a85solenberg // y[i] = b[0] * x[i] + b[1] * x[i-1] + b[2] * x[i-2] 4570f9903e570931831a027ba6f91c164efc604a85solenberg // + -a[1] * y[i-1] + -a[2] * y[i-2]; 4670f9903e570931831a027ba6f91c164efc604a85solenberg 4770f9903e570931831a027ba6f91c164efc604a85solenberg tmp_int32 = y[1] * ba[3]; // -a[1] * y[i-1] (low part) 4870f9903e570931831a027ba6f91c164efc604a85solenberg tmp_int32 += y[3] * ba[4]; // -a[2] * y[i-2] (low part) 4970f9903e570931831a027ba6f91c164efc604a85solenberg tmp_int32 = (tmp_int32 >> 15); 5070f9903e570931831a027ba6f91c164efc604a85solenberg tmp_int32 += y[0] * ba[3]; // -a[1] * y[i-1] (high part) 5170f9903e570931831a027ba6f91c164efc604a85solenberg tmp_int32 += y[2] * ba[4]; // -a[2] * y[i-2] (high part) 5270f9903e570931831a027ba6f91c164efc604a85solenberg tmp_int32 = (tmp_int32 << 1); 5370f9903e570931831a027ba6f91c164efc604a85solenberg 5470f9903e570931831a027ba6f91c164efc604a85solenberg tmp_int32 += data[i] * ba[0]; // b[0] * x[0] 5570f9903e570931831a027ba6f91c164efc604a85solenberg tmp_int32 += x[0] * ba[1]; // b[1] * x[i-1] 5670f9903e570931831a027ba6f91c164efc604a85solenberg tmp_int32 += x[1] * ba[2]; // b[2] * x[i-2] 5770f9903e570931831a027ba6f91c164efc604a85solenberg 5870f9903e570931831a027ba6f91c164efc604a85solenberg // Update state (input part). 5970f9903e570931831a027ba6f91c164efc604a85solenberg x[1] = x[0]; 6070f9903e570931831a027ba6f91c164efc604a85solenberg x[0] = data[i]; 6170f9903e570931831a027ba6f91c164efc604a85solenberg 6270f9903e570931831a027ba6f91c164efc604a85solenberg // Update state (filtered part). 6370f9903e570931831a027ba6f91c164efc604a85solenberg y[2] = y[0]; 6470f9903e570931831a027ba6f91c164efc604a85solenberg y[3] = y[1]; 6570f9903e570931831a027ba6f91c164efc604a85solenberg y[0] = static_cast<int16_t>(tmp_int32 >> 13); 6670f9903e570931831a027ba6f91c164efc604a85solenberg y[1] = static_cast<int16_t>( 6770f9903e570931831a027ba6f91c164efc604a85solenberg (tmp_int32 - (static_cast<int32_t>(y[0]) << 13)) << 2); 6870f9903e570931831a027ba6f91c164efc604a85solenberg 6970f9903e570931831a027ba6f91c164efc604a85solenberg // Rounding in Q12, i.e. add 2^11. 7070f9903e570931831a027ba6f91c164efc604a85solenberg tmp_int32 += 2048; 7170f9903e570931831a027ba6f91c164efc604a85solenberg 7270f9903e570931831a027ba6f91c164efc604a85solenberg // Saturate (to 2^27) so that the HP filtered signal does not overflow. 7370f9903e570931831a027ba6f91c164efc604a85solenberg tmp_int32 = WEBRTC_SPL_SAT(static_cast<int32_t>(134217727), 7470f9903e570931831a027ba6f91c164efc604a85solenberg tmp_int32, 7570f9903e570931831a027ba6f91c164efc604a85solenberg static_cast<int32_t>(-134217728)); 7670f9903e570931831a027ba6f91c164efc604a85solenberg 7770f9903e570931831a027ba6f91c164efc604a85solenberg // Convert back to Q0 and use rounding. 7870f9903e570931831a027ba6f91c164efc604a85solenberg data[i] = static_cast<int16_t>(tmp_int32 >> 12); 7970f9903e570931831a027ba6f91c164efc604a85solenberg } 80470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 81470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 8270f9903e570931831a027ba6f91c164efc604a85solenberg private: 8370f9903e570931831a027ba6f91c164efc604a85solenberg const int16_t* const ba_ = nullptr; 8470f9903e570931831a027ba6f91c164efc604a85solenberg int16_t x_[2]; 8570f9903e570931831a027ba6f91c164efc604a85solenberg int16_t y_[4]; 8670f9903e570931831a027ba6f91c164efc604a85solenberg}; 87470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 8870f9903e570931831a027ba6f91c164efc604a85solenbergHighPassFilterImpl::HighPassFilterImpl(rtc::CriticalSection* crit) 8970f9903e570931831a027ba6f91c164efc604a85solenberg : crit_(crit) { 9070f9903e570931831a027ba6f91c164efc604a85solenberg RTC_DCHECK(crit_); 91df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah} 92470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 93470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comHighPassFilterImpl::~HighPassFilterImpl() {} 94470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 956955870806624479723addfae6dcf5d13968796cPeter Kastingvoid HighPassFilterImpl::Initialize(size_t channels, int sample_rate_hz) { 9670f9903e570931831a027ba6f91c164efc604a85solenberg std::vector<rtc::scoped_ptr<BiquadFilter>> new_filters(channels); 976955870806624479723addfae6dcf5d13968796cPeter Kasting for (size_t i = 0; i < channels; i++) { 9870f9903e570931831a027ba6f91c164efc604a85solenberg new_filters[i].reset(new BiquadFilter(sample_rate_hz)); 9970f9903e570931831a027ba6f91c164efc604a85solenberg } 100df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah rtc::CritScope cs(crit_); 10170f9903e570931831a027ba6f91c164efc604a85solenberg filters_.swap(new_filters); 10270f9903e570931831a027ba6f91c164efc604a85solenberg} 103470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 10470f9903e570931831a027ba6f91c164efc604a85solenbergvoid HighPassFilterImpl::ProcessCaptureAudio(AudioBuffer* audio) { 1055e465c33cac54ed5265f18413f7afc44aae2dfcasolenberg RTC_DCHECK(audio); 10670f9903e570931831a027ba6f91c164efc604a85solenberg rtc::CritScope cs(crit_); 10770f9903e570931831a027ba6f91c164efc604a85solenberg if (!enabled_) { 10870f9903e570931831a027ba6f91c164efc604a85solenberg return; 109470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 110470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 11170f9903e570931831a027ba6f91c164efc604a85solenberg RTC_DCHECK_GE(160u, audio->num_frames_per_band()); 1126955870806624479723addfae6dcf5d13968796cPeter Kasting RTC_DCHECK_EQ(filters_.size(), audio->num_channels()); 11370f9903e570931831a027ba6f91c164efc604a85solenberg for (size_t i = 0; i < filters_.size(); i++) { 11470f9903e570931831a027ba6f91c164efc604a85solenberg filters_[i]->Process(audio->split_bands(i)[kBand0To8kHz], 11570f9903e570931831a027ba6f91c164efc604a85solenberg audio->num_frames_per_band()); 116470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 117470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 118470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 119470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint HighPassFilterImpl::Enable(bool enable) { 120df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah rtc::CritScope cs(crit_); 121c1316a1e51231b717e335f2c4c5ed3bf860a42b3solenberg if (!enabled_ && enable) { 122c1316a1e51231b717e335f2c4c5ed3bf860a42b3solenberg for (auto& filter : filters_) { 123c1316a1e51231b717e335f2c4c5ed3bf860a42b3solenberg filter->Reset(); 124c1316a1e51231b717e335f2c4c5ed3bf860a42b3solenberg } 125c1316a1e51231b717e335f2c4c5ed3bf860a42b3solenberg } 12670f9903e570931831a027ba6f91c164efc604a85solenberg enabled_ = enable; 12770f9903e570931831a027ba6f91c164efc604a85solenberg return AudioProcessing::kNoError; 128470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 129470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 130470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.combool HighPassFilterImpl::is_enabled() const { 131df3efa8c079294857a8b8e0a02634d06a6d6b6d6peah rtc::CritScope cs(crit_); 13270f9903e570931831a027ba6f91c164efc604a85solenberg return enabled_; 133470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 134470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} // namespace webrtc 135