Home | History | Annotate | Download | only in vad
      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/vad/pole_zero_filter.h"
     12 
     13 #include <stdlib.h>
     14 #include <string.h>
     15 #include <algorithm>
     16 
     17 namespace webrtc {
     18 
     19 PoleZeroFilter* PoleZeroFilter::Create(const float* numerator_coefficients,
     20                                        size_t order_numerator,
     21                                        const float* denominator_coefficients,
     22                                        size_t order_denominator) {
     23   if (order_numerator > kMaxFilterOrder ||
     24       order_denominator > kMaxFilterOrder || denominator_coefficients[0] == 0 ||
     25       numerator_coefficients == NULL || denominator_coefficients == NULL)
     26     return NULL;
     27   return new PoleZeroFilter(numerator_coefficients, order_numerator,
     28                             denominator_coefficients, order_denominator);
     29 }
     30 
     31 PoleZeroFilter::PoleZeroFilter(const float* numerator_coefficients,
     32                                size_t order_numerator,
     33                                const float* denominator_coefficients,
     34                                size_t order_denominator)
     35     : past_input_(),
     36       past_output_(),
     37       numerator_coefficients_(),
     38       denominator_coefficients_(),
     39       order_numerator_(order_numerator),
     40       order_denominator_(order_denominator),
     41       highest_order_(std::max(order_denominator, order_numerator)) {
     42   memcpy(numerator_coefficients_, numerator_coefficients,
     43          sizeof(numerator_coefficients_[0]) * (order_numerator_ + 1));
     44   memcpy(denominator_coefficients_, denominator_coefficients,
     45          sizeof(denominator_coefficients_[0]) * (order_denominator_ + 1));
     46 
     47   if (denominator_coefficients_[0] != 1) {
     48     for (size_t n = 0; n <= order_numerator_; n++)
     49       numerator_coefficients_[n] /= denominator_coefficients_[0];
     50     for (size_t n = 0; n <= order_denominator_; n++)
     51       denominator_coefficients_[n] /= denominator_coefficients_[0];
     52   }
     53 }
     54 
     55 template <typename T>
     56 static float FilterArPast(const T* past, size_t order,
     57                           const float* coefficients) {
     58   float sum = 0.0f;
     59   size_t past_index = order - 1;
     60   for (size_t k = 1; k <= order; k++, past_index--)
     61     sum += coefficients[k] * past[past_index];
     62   return sum;
     63 }
     64 
     65 int PoleZeroFilter::Filter(const int16_t* in,
     66                            size_t num_input_samples,
     67                            float* output) {
     68   if (in == NULL || output == NULL)
     69     return -1;
     70   // This is the typical case, just a memcpy.
     71   const size_t k = std::min(num_input_samples, highest_order_);
     72   size_t n;
     73   for (n = 0; n < k; n++) {
     74     output[n] = in[n] * numerator_coefficients_[0];
     75     output[n] += FilterArPast(&past_input_[n], order_numerator_,
     76                               numerator_coefficients_);
     77     output[n] -= FilterArPast(&past_output_[n], order_denominator_,
     78                               denominator_coefficients_);
     79 
     80     past_input_[n + order_numerator_] = in[n];
     81     past_output_[n + order_denominator_] = output[n];
     82   }
     83   if (highest_order_ < num_input_samples) {
     84     for (size_t m = 0; n < num_input_samples; n++, m++) {
     85       output[n] = in[n] * numerator_coefficients_[0];
     86       output[n] +=
     87           FilterArPast(&in[m], order_numerator_, numerator_coefficients_);
     88       output[n] -= FilterArPast(&output[m], order_denominator_,
     89                                 denominator_coefficients_);
     90     }
     91     // Record into the past signal.
     92     memcpy(past_input_, &in[num_input_samples - order_numerator_],
     93            sizeof(in[0]) * order_numerator_);
     94     memcpy(past_output_, &output[num_input_samples - order_denominator_],
     95            sizeof(output[0]) * order_denominator_);
     96   } else {
     97     // Odd case that the length of the input is shorter that filter order.
     98     memmove(past_input_, &past_input_[num_input_samples],
     99             order_numerator_ * sizeof(past_input_[0]));
    100     memmove(past_output_, &past_output_[num_input_samples],
    101             order_denominator_ * sizeof(past_output_[0]));
    102   }
    103   return 0;
    104 }
    105 
    106 }  // namespace webrtc
    107