| Index: third_party/WebKit/Source/platform/audio/IIRFilter.cpp
|
| diff --git a/third_party/WebKit/Source/platform/audio/IIRFilter.cpp b/third_party/WebKit/Source/platform/audio/IIRFilter.cpp
|
| index a98ec4aef12d0599bd8a76a323332927f81f41fa..7ac343fdc87c7eb77abb71af13dffeb2a8c34208 100644
|
| --- a/third_party/WebKit/Source/platform/audio/IIRFilter.cpp
|
| +++ b/third_party/WebKit/Source/platform/audio/IIRFilter.cpp
|
| @@ -5,6 +5,8 @@
|
| #include "platform/audio/IIRFilter.h"
|
|
|
| #include <complex>
|
| +#include "platform/audio/AudioUtilities.h"
|
| +#include "platform/audio/VectorMath.h"
|
| #include "platform/wtf/MathExtras.h"
|
|
|
| namespace blink {
|
| @@ -29,6 +31,7 @@ IIRFilter::~IIRFilter() {}
|
| void IIRFilter::Reset() {
|
| x_buffer_.Zero();
|
| y_buffer_.Zero();
|
| + buffer_index_ = 0;
|
| }
|
|
|
| static std::complex<double> EvaluatePolynomial(const double* coef,
|
| @@ -139,4 +142,73 @@ void IIRFilter::GetFrequencyResponse(int n_frequencies,
|
| }
|
| }
|
|
|
| +double IIRFilter::TailTime(double sample_rate) {
|
| + // The maximum tail time. This is somewhat arbitrary, but we're assuming that
|
| + // no one is going to expect the IIRFilter to produce an output after this
|
| + // much time after the inputs have stopped.
|
| + const double kMaxTailTime = 60;
|
| +
|
| + // If the maximum amplitude of the impulse response is less than this, we
|
| + // assume that we've reached the tail of the response. Currently, this means
|
| + // that the impulse is less than 1 bit of a 16-bit PCM value.
|
| + const float kMaxTailAmplitude = 1 / 32768.0;
|
| +
|
| + // How to compute the tail time? We're going to filter an impulse
|
| + // for |kMaxTailTime| seconds, in blocks of kRenderQuantumFrames at
|
| + // a time. The maximum magnitude of this block is saved. After all
|
| + // of the samples have been computed, find the last block with a
|
| + // maximum magnitude greater than |kMaxTaileAmplitude|. That block
|
| + // index + 1 will be the tail time. We don't need to be
|
| + // super-accurate in computing the tail time since we process on
|
| + // blocks, block accuracy is good enough, and the value just needs
|
| + // to be larger than the "real" tail time, so we don't prematurely
|
| + // zero out the output of the node.
|
| +
|
| + // Number of render quanta needed to reach the max tail time.
|
| + int number_of_blocks = std::ceil(sample_rate * kMaxTailTime /
|
| + AudioUtilities::kRenderQuantumFrames);
|
| +
|
| + // Input and output buffers for filtering.
|
| + AudioFloatArray input(AudioUtilities::kRenderQuantumFrames);
|
| + AudioFloatArray output(AudioUtilities::kRenderQuantumFrames);
|
| +
|
| + // Array to hold the max magnitudes
|
| + AudioFloatArray magnitudes(number_of_blocks);
|
| +
|
| + // Create the impulse input signal.
|
| + input[0] = 1;
|
| +
|
| + // Process the first block and get the max magnitude of the output.
|
| + Process(input.Data(), output.Data(), AudioUtilities::kRenderQuantumFrames);
|
| + VectorMath::Vmaxmgv(output.Data(), 1, &magnitudes[0],
|
| + AudioUtilities::kRenderQuantumFrames);
|
| +
|
| + // Process the rest of the signal, getting the max magnitude of the
|
| + // output for each block.
|
| + input[0] = 0;
|
| +
|
| + for (int k = 1; k < number_of_blocks; ++k) {
|
| + Process(input.Data(), output.Data(), AudioUtilities::kRenderQuantumFrames);
|
| + VectorMath::Vmaxmgv(output.Data(), 1, &magnitudes[k],
|
| + AudioUtilities::kRenderQuantumFrames);
|
| + }
|
| +
|
| + // Done computing the impulse response; reset the state so the actual node
|
| + // starts in the expected initial state.
|
| + Reset();
|
| +
|
| + // Find the last block with amplitude greater than the threshold.
|
| + int index = number_of_blocks - 1;
|
| + for (int k = index; k >= 0; --k) {
|
| + if (magnitudes[k] > kMaxTailAmplitude) {
|
| + index = k;
|
| + break;
|
| + }
|
| + }
|
| +
|
| + // The magnitude first become lower than the threshold at the next block.
|
| + // Compute the corresponding time value value; that's the tail time.
|
| + return (index + 1) * AudioUtilities::kRenderQuantumFrames / sample_rate;
|
| +}
|
| +
|
| } // namespace blink
|
|
|