зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1265408 - Avoid complex division in getFrequencyResponse; r=padenot
Using the division operator on std::complex values fails on our linux64 AWS test machines, yielding infinities and NaNs for valid inputs. Presumably this could affect machines in the wild as well. This patch removes the use of the division operator and replaces it with real operations. MozReview-Commit-ID: 4s7xUf9ja0F --HG-- extra : rebase_source : cdfee7070a50eefbf8e50aee3993cf8993cd32b4
This commit is contained in:
Родитель
77a0cbd919
Коммит
2b6abdb28d
|
@ -175,7 +175,7 @@ void Biquad::setHighpassParams(double cutoff, double resonance)
|
|||
void Biquad::setNormalizedCoefficients(double b0, double b1, double b2, double a0, double a1, double a2)
|
||||
{
|
||||
double a0Inverse = 1 / a0;
|
||||
|
||||
|
||||
m_b0 = b0 * a0Inverse;
|
||||
m_b1 = b1 * a0Inverse;
|
||||
m_b2 = b2 * a0Inverse;
|
||||
|
@ -376,7 +376,7 @@ void Biquad::setBandpassParams(double frequency, double Q)
|
|||
if (Q > 0) {
|
||||
double alpha = sin(w0) / (2 * Q);
|
||||
double k = cos(w0);
|
||||
|
||||
|
||||
double b0 = alpha;
|
||||
double b1 = 0;
|
||||
double b2 = -alpha;
|
||||
|
@ -451,13 +451,21 @@ void Biquad::getFrequencyResponse(int nFrequencies,
|
|||
double b2 = m_b2;
|
||||
double a1 = m_a1;
|
||||
double a2 = m_a2;
|
||||
|
||||
|
||||
for (int k = 0; k < nFrequencies; ++k) {
|
||||
double omega = -M_PI * frequency[k];
|
||||
Complex z = Complex(cos(omega), sin(omega));
|
||||
Complex numerator = b0 + (b1 + b2 * z) * z;
|
||||
Complex denominator = Complex(1, 0) + (a1 + a2 * z) * z;
|
||||
Complex response = numerator / denominator;
|
||||
// Strangely enough, using complex division:
|
||||
// e.g. Complex response = numerator / denominator;
|
||||
// fails on our test machines, yielding infinities and NaNs, so we do
|
||||
// things the long way here.
|
||||
double n = norm(denominator);
|
||||
double r = (real(numerator)*real(denominator) + imag(numerator)*imag(denominator)) / n;
|
||||
double i = (imag(numerator)*real(denominator) - real(numerator)*imag(denominator)) / n;
|
||||
std::complex<double> response = std::complex<double>(r, i);
|
||||
|
||||
magResponse[k] = static_cast<float>(abs(response));
|
||||
phaseResponse[k] = static_cast<float>(atan2(imag(response), real(response)));
|
||||
}
|
||||
|
|
|
@ -129,7 +129,15 @@ void IIRFilter::getFrequencyResponse(int nFrequencies, const float* frequency, f
|
|||
|
||||
std::complex<double> numerator = evaluatePolynomial(m_feedforward->Elements(), zRecip, m_feedforward->Length() - 1);
|
||||
std::complex<double> denominator = evaluatePolynomial(m_feedback->Elements(), zRecip, m_feedback->Length() - 1);
|
||||
std::complex<double> response = numerator / denominator;
|
||||
// Strangely enough, using complex division:
|
||||
// e.g. Complex response = numerator / denominator;
|
||||
// fails on our test machines, yielding infinities and NaNs, so we do
|
||||
// things the long way here.
|
||||
double n = norm(denominator);
|
||||
double r = (real(numerator)*real(denominator) + imag(numerator)*imag(denominator)) / n;
|
||||
double i = (imag(numerator)*real(denominator) - real(numerator)*imag(denominator)) / n;
|
||||
std::complex<double> response = std::complex<double>(r, i);
|
||||
|
||||
magResponse[k] = static_cast<float>(abs(response));
|
||||
phaseResponse[k] = static_cast<float>(atan2(imag(response), real(response)));
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче