Index: Source/modules/webaudio/BiquadDSPKernel.cpp |
diff --git a/Source/modules/webaudio/BiquadDSPKernel.cpp b/Source/modules/webaudio/BiquadDSPKernel.cpp |
index 5136ae118cd3e5b1ebea5b4bdcc70be50c3d3332..45b663be10b57ee611b3cfce05911b1983ef99a7 100644 |
--- a/Source/modules/webaudio/BiquadDSPKernel.cpp |
+++ b/Source/modules/webaudio/BiquadDSPKernel.cpp |
@@ -40,73 +40,73 @@ namespace WebCore { |
// settings of the Biquad. |
static const double MaxBiquadDelayTime = 0.2; |
-void BiquadDSPKernel::updateCoefficientsIfNecessary(bool useSmoothing, bool forceUpdate) |
+void BiquadDSPKernel::updateCoefficientsIfNecessary() |
{ |
- if (forceUpdate || biquadProcessor()->filterCoefficientsDirty()) { |
- double value1; |
- double value2; |
+ if (biquadProcessor()->filterCoefficientsDirty()) { |
+ double cutoffFrequency; |
+ double Q; |
double gain; |
double detune; // in Cents |
if (biquadProcessor()->hasSampleAccurateValues()) { |
- value1 = biquadProcessor()->parameter1()->finalValue(); |
- value2 = biquadProcessor()->parameter2()->finalValue(); |
+ cutoffFrequency = biquadProcessor()->parameter1()->finalValue(); |
+ Q = biquadProcessor()->parameter2()->finalValue(); |
gain = biquadProcessor()->parameter3()->finalValue(); |
detune = biquadProcessor()->parameter4()->finalValue(); |
- } else if (useSmoothing) { |
- value1 = biquadProcessor()->parameter1()->smoothedValue(); |
- value2 = biquadProcessor()->parameter2()->smoothedValue(); |
+ } else { |
+ cutoffFrequency = biquadProcessor()->parameter1()->smoothedValue(); |
+ Q = biquadProcessor()->parameter2()->smoothedValue(); |
gain = biquadProcessor()->parameter3()->smoothedValue(); |
detune = biquadProcessor()->parameter4()->smoothedValue(); |
- } else { |
- value1 = biquadProcessor()->parameter1()->value(); |
- value2 = biquadProcessor()->parameter2()->value(); |
- gain = biquadProcessor()->parameter3()->value(); |
- detune = biquadProcessor()->parameter4()->value(); |
} |
- // Convert from Hertz to normalized frequency 0 -> 1. |
- double nyquist = this->nyquist(); |
- double normalizedFrequency = value1 / nyquist; |
+ updateCoefficients(cutoffFrequency, Q, gain, detune); |
+ } |
+} |
- // Offset frequency by detune. |
- if (detune) |
- normalizedFrequency *= pow(2, detune / 1200); |
+void BiquadDSPKernel::updateCoefficients(double cutoffFrequency, double Q, double gain, double detune) |
+{ |
+ // Convert from Hertz to normalized frequency 0 -> 1. |
+ double nyquist = this->nyquist(); |
+ double normalizedFrequency = cutoffFrequency / nyquist; |
- // Configure the biquad with the new filter parameters for the appropriate type of filter. |
- switch (biquadProcessor()->type()) { |
- case BiquadProcessor::LowPass: |
- m_biquad.setLowpassParams(normalizedFrequency, value2); |
- break; |
+ // Offset frequency by detune. |
+ if (detune) |
+ normalizedFrequency *= pow(2, detune / 1200); |
- case BiquadProcessor::HighPass: |
- m_biquad.setHighpassParams(normalizedFrequency, value2); |
- break; |
+ // Configure the biquad with the new filter parameters for the appropriate type of filter. |
+ switch (biquadProcessor()->type()) { |
+ case BiquadProcessor::LowPass: |
+ m_biquad.setLowpassParams(normalizedFrequency, Q); |
+ break; |
- case BiquadProcessor::BandPass: |
- m_biquad.setBandpassParams(normalizedFrequency, value2); |
- break; |
+ case BiquadProcessor::HighPass: |
+ m_biquad.setHighpassParams(normalizedFrequency, Q); |
+ break; |
- case BiquadProcessor::LowShelf: |
- m_biquad.setLowShelfParams(normalizedFrequency, gain); |
- break; |
+ case BiquadProcessor::BandPass: |
+ m_biquad.setBandpassParams(normalizedFrequency, Q); |
+ break; |
- case BiquadProcessor::HighShelf: |
- m_biquad.setHighShelfParams(normalizedFrequency, gain); |
- break; |
+ case BiquadProcessor::LowShelf: |
+ m_biquad.setLowShelfParams(normalizedFrequency, gain); |
+ break; |
- case BiquadProcessor::Peaking: |
- m_biquad.setPeakingParams(normalizedFrequency, value2, gain); |
- break; |
+ case BiquadProcessor::HighShelf: |
+ m_biquad.setHighShelfParams(normalizedFrequency, gain); |
+ break; |
- case BiquadProcessor::Notch: |
- m_biquad.setNotchParams(normalizedFrequency, value2); |
- break; |
+ case BiquadProcessor::Peaking: |
+ m_biquad.setPeakingParams(normalizedFrequency, Q, gain); |
+ break; |
- case BiquadProcessor::Allpass: |
- m_biquad.setAllpassParams(normalizedFrequency, value2); |
- break; |
- } |
+ case BiquadProcessor::Notch: |
+ m_biquad.setNotchParams(normalizedFrequency, Q); |
+ break; |
+ |
+ case BiquadProcessor::Allpass: |
+ m_biquad.setAllpassParams(normalizedFrequency, Q); |
+ break; |
} |
} |
@@ -118,7 +118,14 @@ void BiquadDSPKernel::process(const float* source, float* destination, size_t fr |
// FIXME: as an optimization, implement a way that a Biquad object can simply copy its internal filter coefficients from another Biquad object. |
// Then re-factor this code to only run for the first BiquadDSPKernel of each BiquadProcessor. |
- updateCoefficientsIfNecessary(true, false); |
+ |
+ // The audio thread can't block on this lock; skip updating the coefficients for this block if |
+ // necessary. We'll get them the next time around. |
+ { |
+ MutexTryLocker tryLocker(m_processLock); |
+ if (tryLocker.locked()) |
+ updateCoefficientsIfNecessary(); |
+ } |
m_biquad.process(source, destination, framesToProcess); |
} |
@@ -142,12 +149,33 @@ void BiquadDSPKernel::getFrequencyResponse(int nFrequencies, |
for (int k = 0; k < nFrequencies; ++k) |
frequency[k] = narrowPrecisionToFloat(frequencyHz[k] / nyquist); |
- // We want to get the final values of the coefficients and compute |
- // the response from that instead of some intermediate smoothed |
- // set. Forcefully update the coefficients even if they are not |
- // dirty. |
+ double cutoffFrequency; |
+ double Q; |
+ double gain; |
+ double detune; // in Cents |
+ |
+ { |
+ // Get a copy of the current biquad filter coefficients so we can update the biquad with |
+ // these values. We need to synchronize with process() to prevent process() from updating |
+ // the filter coefficients while we're trying to access them. The process will update it |
+ // next time around. |
+ // |
+ // The BiquadDSPKernel object here (along with it's Biquad object) is for querying the |
+ // frequency response and is NOT the same as the one in process() which is used for |
+ // performing the actual filtering. This one is is created in |
+ // BiquadProcessor::getFrequencyResponse for this purpose. Both, however, point to the same |
+ // BiquadProcessor object. |
+ // |
+ // FIXME: Simplify this: crbug.com/390266 |
+ MutexLocker processLocker(m_processLock); |
+ |
+ cutoffFrequency = biquadProcessor()->parameter1()->value(); |
+ Q = biquadProcessor()->parameter2()->value(); |
+ gain = biquadProcessor()->parameter3()->value(); |
+ detune = biquadProcessor()->parameter4()->value(); |
+ } |
- updateCoefficientsIfNecessary(false, true); |
+ updateCoefficients(cutoffFrequency, Q, gain, detune); |
m_biquad.getFrequencyResponse(nFrequencies, frequency.data(), magResponse, phaseResponse); |
} |