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