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