/* * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "webrtc/modules/audio_processing/vad/pole_zero_filter.h" #include #include #include namespace webrtc { PoleZeroFilter* PoleZeroFilter::Create(const float* numerator_coefficients, size_t order_numerator, const float* denominator_coefficients, size_t order_denominator) { if (order_numerator > kMaxFilterOrder || order_denominator > kMaxFilterOrder || denominator_coefficients[0] == 0 || numerator_coefficients == NULL || denominator_coefficients == NULL) return NULL; return new PoleZeroFilter(numerator_coefficients, order_numerator, denominator_coefficients, order_denominator); } PoleZeroFilter::PoleZeroFilter(const float* numerator_coefficients, size_t order_numerator, const float* denominator_coefficients, size_t order_denominator) : past_input_(), past_output_(), numerator_coefficients_(), denominator_coefficients_(), order_numerator_(order_numerator), order_denominator_(order_denominator), highest_order_(std::max(order_denominator, order_numerator)) { memcpy(numerator_coefficients_, numerator_coefficients, sizeof(numerator_coefficients_[0]) * (order_numerator_ + 1)); memcpy(denominator_coefficients_, denominator_coefficients, sizeof(denominator_coefficients_[0]) * (order_denominator_ + 1)); if (denominator_coefficients_[0] != 1) { for (size_t n = 0; n <= order_numerator_; n++) numerator_coefficients_[n] /= denominator_coefficients_[0]; for (size_t n = 0; n <= order_denominator_; n++) denominator_coefficients_[n] /= denominator_coefficients_[0]; } } template static float FilterArPast(const T* past, size_t order, const float* coefficients) { float sum = 0.0f; size_t past_index = order - 1; for (size_t k = 1; k <= order; k++, past_index--) sum += coefficients[k] * past[past_index]; return sum; } int PoleZeroFilter::Filter(const int16_t* in, size_t num_input_samples, float* output) { if (in == NULL || output == NULL) return -1; // This is the typical case, just a memcpy. const size_t k = std::min(num_input_samples, highest_order_); size_t n; for (n = 0; n < k; n++) { output[n] = in[n] * numerator_coefficients_[0]; output[n] += FilterArPast(&past_input_[n], order_numerator_, numerator_coefficients_); output[n] -= FilterArPast(&past_output_[n], order_denominator_, denominator_coefficients_); past_input_[n + order_numerator_] = in[n]; past_output_[n + order_denominator_] = output[n]; } if (highest_order_ < num_input_samples) { for (size_t m = 0; n < num_input_samples; n++, m++) { output[n] = in[n] * numerator_coefficients_[0]; output[n] += FilterArPast(&in[m], order_numerator_, numerator_coefficients_); output[n] -= FilterArPast(&output[m], order_denominator_, denominator_coefficients_); } // Record into the past signal. memcpy(past_input_, &in[num_input_samples - order_numerator_], sizeof(in[0]) * order_numerator_); memcpy(past_output_, &output[num_input_samples - order_denominator_], sizeof(output[0]) * order_denominator_); } else { // Odd case that the length of the input is shorter that filter order. memmove(past_input_, &past_input_[num_input_samples], order_numerator_ * sizeof(past_input_[0])); memmove(past_output_, &past_output_[num_input_samples], order_denominator_ * sizeof(past_output_[0])); } return 0; } } // namespace webrtc