1e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent/* 2e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. 3e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * 4e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * Use of this source code is governed by a BSD-style license 5e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * that can be found in the LICENSE file in the root of the source 6e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * tree. An additional intellectual property rights grant can be found 7e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * in the file PATENTS. All contributing project authors may 8e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * be found in the AUTHORS file in the root of the source tree. 9e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent */ 10e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 11e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "high_pass_filter_impl.h" 12e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 13e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include <cassert> 14e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 15e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "critical_section_wrapper.h" 16e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "typedefs.h" 17e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "signal_processing_library.h" 18e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 19e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "audio_processing_impl.h" 20e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "audio_buffer.h" 21e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 22e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentnamespace webrtc { 23e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentnamespace { 24e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentconst WebRtc_Word16 kFilterCoefficients8kHz[5] = 25e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent {3798, -7596, 3798, 7807, -3733}; 26e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 27e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentconst WebRtc_Word16 kFilterCoefficients[5] = 28e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent {4012, -8024, 4012, 8002, -3913}; 29e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 30e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentstruct FilterState { 31e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_Word16 y[4]; 32e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_Word16 x[2]; 33e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent const WebRtc_Word16* ba; 34e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}; 35e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 36e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint InitializeFilter(FilterState* hpf, int sample_rate_hz) { 37e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent assert(hpf != NULL); 38e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 39e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (sample_rate_hz == AudioProcessingImpl::kSampleRate8kHz) { 40e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent hpf->ba = kFilterCoefficients8kHz; 41e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } else { 42e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent hpf->ba = kFilterCoefficients; 43e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 44e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 45e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtcSpl_MemSetW16(hpf->x, 0, 2); 46e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtcSpl_MemSetW16(hpf->y, 0, 4); 47e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 48e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return AudioProcessing::kNoError; 49e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 50e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 51e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint Filter(FilterState* hpf, WebRtc_Word16* data, int length) { 52e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent assert(hpf != NULL); 53e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 54e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_Word32 tmp_int32 = 0; 55e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_Word16* y = hpf->y; 56e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_Word16* x = hpf->x; 57e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent const WebRtc_Word16* ba = hpf->ba; 58e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 59e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent for (int i = 0; i < length; i++) { 60e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // y[i] = b[0] * x[i] + b[1] * x[i-1] + b[2] * x[i-2] 61e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // + -a[1] * y[i-1] + -a[2] * y[i-2]; 62e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 63e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmp_int32 = 64e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WEBRTC_SPL_MUL_16_16(y[1], ba[3]); // -a[1] * y[i-1] (low part) 65e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmp_int32 += 66e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WEBRTC_SPL_MUL_16_16(y[3], ba[4]); // -a[2] * y[i-2] (low part) 67e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmp_int32 = (tmp_int32 >> 15); 68e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmp_int32 += 69e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WEBRTC_SPL_MUL_16_16(y[0], ba[3]); // -a[1] * y[i-1] (high part) 70e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmp_int32 += 71e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WEBRTC_SPL_MUL_16_16(y[2], ba[4]); // -a[2] * y[i-2] (high part) 72e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmp_int32 = (tmp_int32 << 1); 73e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 74e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmp_int32 += WEBRTC_SPL_MUL_16_16(data[i], ba[0]); // b[0]*x[0] 75e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmp_int32 += WEBRTC_SPL_MUL_16_16(x[0], ba[1]); // b[1]*x[i-1] 76e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmp_int32 += WEBRTC_SPL_MUL_16_16(x[1], ba[2]); // b[2]*x[i-2] 77e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 78e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // Update state (input part) 79e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent x[1] = x[0]; 80e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent x[0] = data[i]; 81e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 82e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // Update state (filtered part) 83e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent y[2] = y[0]; 84e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent y[3] = y[1]; 85e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent y[0] = static_cast<WebRtc_Word16>(tmp_int32 >> 13); 86e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent y[1] = static_cast<WebRtc_Word16>((tmp_int32 - 87e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WEBRTC_SPL_LSHIFT_W32(static_cast<WebRtc_Word32>(y[0]), 13)) << 2); 88e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 89e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // Rounding in Q12, i.e. add 2^11 90e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmp_int32 += 2048; 91e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 92e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // Saturate (to 2^27) so that the HP filtered signal does not overflow 93e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmp_int32 = WEBRTC_SPL_SAT(static_cast<WebRtc_Word32>(134217727), 94e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmp_int32, 95e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent static_cast<WebRtc_Word32>(-134217728)); 96e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 97e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // Convert back to Q0 and use rounding 98e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent data[i] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmp_int32, 12); 99e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 100e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 101e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 102e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return AudioProcessing::kNoError; 103e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 104e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} // namespace 105e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 106e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurenttypedef FilterState Handle; 107e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 108e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric LaurentHighPassFilterImpl::HighPassFilterImpl(const AudioProcessingImpl* apm) 109e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent : ProcessingComponent(apm), 110e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent apm_(apm) {} 111e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 112e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric LaurentHighPassFilterImpl::~HighPassFilterImpl() {} 113e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 114e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint HighPassFilterImpl::ProcessCaptureAudio(AudioBuffer* audio) { 115e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent int err = apm_->kNoError; 116e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 117e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (!is_component_enabled()) { 118e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return apm_->kNoError; 119e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 120e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 121e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent assert(audio->samples_per_split_channel() <= 160); 122e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 123e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent for (int i = 0; i < num_handles(); i++) { 124e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent Handle* my_handle = static_cast<Handle*>(handle(i)); 125e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent err = Filter(my_handle, 126e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent audio->low_pass_split_data(i), 127e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent audio->samples_per_split_channel()); 128e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 129e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (err != apm_->kNoError) { 130e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return GetHandleError(my_handle); 131e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 132e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 133e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 134e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return apm_->kNoError; 135e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 136e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 137e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint HighPassFilterImpl::Enable(bool enable) { 138e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent CriticalSectionScoped crit_scoped(*apm_->crit()); 139e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return EnableComponent(enable); 140e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 141e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 142e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentbool HighPassFilterImpl::is_enabled() const { 143e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return is_component_enabled(); 144e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 145e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 146e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint HighPassFilterImpl::get_version(char* version, 147e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent int version_len_bytes) const { 148e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // An empty string is used to indicate no version information. 149e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent memset(version, 0, version_len_bytes); 150e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return apm_->kNoError; 151e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 152e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 153e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentvoid* HighPassFilterImpl::CreateHandle() const { 154e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return new FilterState; 155e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 156e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 157e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint HighPassFilterImpl::DestroyHandle(void* handle) const { 158e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent delete static_cast<Handle*>(handle); 159e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return apm_->kNoError; 160e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 161e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 162e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint HighPassFilterImpl::InitializeHandle(void* handle) const { 163e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return InitializeFilter(static_cast<Handle*>(handle), 164e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent apm_->sample_rate_hz()); 165e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 166e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 167e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint HighPassFilterImpl::ConfigureHandle(void* /*handle*/) const { 168e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return apm_->kNoError; // Not configurable. 169e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 170e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 171e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint HighPassFilterImpl::num_handles_required() const { 172e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return apm_->num_output_channels(); 173e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 174e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 175e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint HighPassFilterImpl::GetHandleError(void* handle) const { 176e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // The component has no detailed errors. 177e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent assert(handle != NULL); 178e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return apm_->kUnspecifiedError; 179e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 180e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} // namespace webrtc 181