diff options
Diffstat (limited to 'webrtc/modules/audio_processing/agc/pole_zero_filter.cc')
-rw-r--r-- | webrtc/modules/audio_processing/agc/pole_zero_filter.cc | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/webrtc/modules/audio_processing/agc/pole_zero_filter.cc b/webrtc/modules/audio_processing/agc/pole_zero_filter.cc new file mode 100644 index 0000000000..3c41e33dd6 --- /dev/null +++ b/webrtc/modules/audio_processing/agc/pole_zero_filter.cc @@ -0,0 +1,111 @@ +/* + * 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/agc/pole_zero_filter.h" + +#include <stdlib.h> +#include <string.h> +#include <algorithm> + +namespace webrtc { + +PoleZeroFilter* PoleZeroFilter::Create(const float* numerator_coefficients, + int order_numerator, + const float* denominator_coefficients, + int order_denominator) { + if (order_numerator < 0 || + order_denominator < 0 || + 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, + int order_numerator, + const float* denominator_coefficients, + int 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 (int n = 0; n <= order_numerator_; n++) + numerator_coefficients_[n] /= denominator_coefficients_[0]; + for (int n = 0; n <= order_denominator_; n++) + denominator_coefficients_[n] /= denominator_coefficients_[0]; + } +} + +template <typename T> +static float FilterArPast(const T* past, int order, + const float* coefficients) { + float sum = 0.0f; + int past_index = order - 1; + for (int k = 1; k <= order; k++, past_index--) + sum += coefficients[k] * past[past_index]; + return sum; +} + +int PoleZeroFilter::Filter(const int16_t* in, + int num_input_samples, + float* output) { + if (in == NULL || num_input_samples < 0 || output == NULL) + return -1; + // This is the typical case, just a memcpy. + const int k = std::min(num_input_samples, highest_order_); + int 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 (int 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 + |