OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2010, Google Inc. All rights reserved. | 2 * Copyright (C) 2010, Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
(...skipping 13 matching lines...) Expand all Loading... |
24 */ | 24 */ |
25 | 25 |
26 #include "modules/webaudio/BiquadDSPKernel.h" | 26 #include "modules/webaudio/BiquadDSPKernel.h" |
27 #include "platform/audio/AudioUtilities.h" | 27 #include "platform/audio/AudioUtilities.h" |
28 #include "wtf/MathExtras.h" | 28 #include "wtf/MathExtras.h" |
29 #include "wtf/Vector.h" | 29 #include "wtf/Vector.h" |
30 #include <limits.h> | 30 #include <limits.h> |
31 | 31 |
32 namespace blink { | 32 namespace blink { |
33 | 33 |
34 // FIXME: As a recursive linear filter, depending on its parameters, a biquad fi
lter can have | 34 // FIXME: As a recursive linear filter, depending on its parameters, a biquad |
35 // an infinite tailTime. In practice, Biquad filters do not usually (except for
very high resonance values) | 35 // filter can have an infinite tailTime. In practice, Biquad filters do not |
36 // have a tailTime of longer than approx. 200ms. This value could possibly be ca
lculated based on the | 36 // usually (except for very high resonance values) have a tailTime of longer |
| 37 // than approx. 200ms. This value could possibly be calculated based on the |
37 // settings of the Biquad. | 38 // settings of the Biquad. |
38 static const double MaxBiquadDelayTime = 0.2; | 39 static const double MaxBiquadDelayTime = 0.2; |
39 | 40 |
40 void BiquadDSPKernel::updateCoefficientsIfNecessary(int framesToProcess) { | 41 void BiquadDSPKernel::updateCoefficientsIfNecessary(int framesToProcess) { |
41 if (getBiquadProcessor()->filterCoefficientsDirty()) { | 42 if (getBiquadProcessor()->filterCoefficientsDirty()) { |
42 float cutoffFrequency[AudioUtilities::kRenderQuantumFrames]; | 43 float cutoffFrequency[AudioUtilities::kRenderQuantumFrames]; |
43 float Q[AudioUtilities::kRenderQuantumFrames]; | 44 float Q[AudioUtilities::kRenderQuantumFrames]; |
44 float gain[AudioUtilities::kRenderQuantumFrames]; | 45 float gain[AudioUtilities::kRenderQuantumFrames]; |
45 float detune[AudioUtilities::kRenderQuantumFrames]; // in Cents | 46 float detune[AudioUtilities::kRenderQuantumFrames]; // in Cents |
46 | 47 |
(...skipping 30 matching lines...) Expand all Loading... |
77 | 78 |
78 m_biquad.setHasSampleAccurateValues(numberOfFrames > 1); | 79 m_biquad.setHasSampleAccurateValues(numberOfFrames > 1); |
79 | 80 |
80 for (int k = 0; k < numberOfFrames; ++k) { | 81 for (int k = 0; k < numberOfFrames; ++k) { |
81 double normalizedFrequency = cutoffFrequency[k] / nyquist; | 82 double normalizedFrequency = cutoffFrequency[k] / nyquist; |
82 | 83 |
83 // Offset frequency by detune. | 84 // Offset frequency by detune. |
84 if (detune[k]) | 85 if (detune[k]) |
85 normalizedFrequency *= pow(2, detune[k] / 1200); | 86 normalizedFrequency *= pow(2, detune[k] / 1200); |
86 | 87 |
87 // Configure the biquad with the new filter parameters for the appropriate t
ype of filter. | 88 // Configure the biquad with the new filter parameters for the appropriate |
| 89 // type of filter. |
88 switch (getBiquadProcessor()->type()) { | 90 switch (getBiquadProcessor()->type()) { |
89 case BiquadProcessor::LowPass: | 91 case BiquadProcessor::LowPass: |
90 m_biquad.setLowpassParams(k, normalizedFrequency, Q[k]); | 92 m_biquad.setLowpassParams(k, normalizedFrequency, Q[k]); |
91 break; | 93 break; |
92 | 94 |
93 case BiquadProcessor::HighPass: | 95 case BiquadProcessor::HighPass: |
94 m_biquad.setHighpassParams(k, normalizedFrequency, Q[k]); | 96 m_biquad.setHighpassParams(k, normalizedFrequency, Q[k]); |
95 break; | 97 break; |
96 | 98 |
97 case BiquadProcessor::BandPass: | 99 case BiquadProcessor::BandPass: |
(...skipping 24 matching lines...) Expand all Loading... |
122 } | 124 } |
123 | 125 |
124 void BiquadDSPKernel::process(const float* source, | 126 void BiquadDSPKernel::process(const float* source, |
125 float* destination, | 127 float* destination, |
126 size_t framesToProcess) { | 128 size_t framesToProcess) { |
127 DCHECK(source); | 129 DCHECK(source); |
128 DCHECK(destination); | 130 DCHECK(destination); |
129 DCHECK(getBiquadProcessor()); | 131 DCHECK(getBiquadProcessor()); |
130 | 132 |
131 // Recompute filter coefficients if any of the parameters have changed. | 133 // Recompute filter coefficients if any of the parameters have changed. |
132 // FIXME: as an optimization, implement a way that a Biquad object can simply
copy its internal filter coefficients from another Biquad object. | 134 // FIXME: as an optimization, implement a way that a Biquad object can simply |
133 // Then re-factor this code to only run for the first BiquadDSPKernel of each
BiquadProcessor. | 135 // copy its internal filter coefficients from another Biquad object. Then |
| 136 // re-factor this code to only run for the first BiquadDSPKernel of each |
| 137 // BiquadProcessor. |
134 | 138 |
135 // The audio thread can't block on this lock; skip updating the coefficients f
or this block if | 139 // The audio thread can't block on this lock; skip updating the coefficients |
136 // necessary. We'll get them the next time around. | 140 // for this block if necessary. We'll get them the next time around. |
137 { | 141 { |
138 MutexTryLocker tryLocker(m_processLock); | 142 MutexTryLocker tryLocker(m_processLock); |
139 if (tryLocker.locked()) | 143 if (tryLocker.locked()) |
140 updateCoefficientsIfNecessary(framesToProcess); | 144 updateCoefficientsIfNecessary(framesToProcess); |
141 } | 145 } |
142 | 146 |
143 m_biquad.process(source, destination, framesToProcess); | 147 m_biquad.process(source, destination, framesToProcess); |
144 } | 148 } |
145 | 149 |
146 void BiquadDSPKernel::getFrequencyResponse(int nFrequencies, | 150 void BiquadDSPKernel::getFrequencyResponse(int nFrequencies, |
(...skipping 13 matching lines...) Expand all Loading... |
160 // with 1 equal to the Nyquist frequency. | 164 // with 1 equal to the Nyquist frequency. |
161 for (int k = 0; k < nFrequencies; ++k) | 165 for (int k = 0; k < nFrequencies; ++k) |
162 frequency[k] = clampTo<float>(frequencyHz[k] / nyquist); | 166 frequency[k] = clampTo<float>(frequencyHz[k] / nyquist); |
163 | 167 |
164 float cutoffFrequency; | 168 float cutoffFrequency; |
165 float Q; | 169 float Q; |
166 float gain; | 170 float gain; |
167 float detune; // in Cents | 171 float detune; // in Cents |
168 | 172 |
169 { | 173 { |
170 // Get a copy of the current biquad filter coefficients so we can update the
biquad with | 174 // Get a copy of the current biquad filter coefficients so we can update the |
171 // these values. We need to synchronize with process() to prevent process()
from updating | 175 // biquad with these values. We need to synchronize with process() to |
172 // the filter coefficients while we're trying to access them. The process wi
ll update it | 176 // prevent process() from updating the filter coefficients while we're |
173 // next time around. | 177 // trying to access them. The process will update it next time around. |
174 // | 178 // |
175 // The BiquadDSPKernel object here (along with it's Biquad object) is for qu
erying the | 179 // The BiquadDSPKernel object here (along with it's Biquad object) is for |
176 // frequency response and is NOT the same as the one in process() which is u
sed for | 180 // querying the frequency response and is NOT the same as the one in |
177 // performing the actual filtering. This one is is created in | 181 // process() which is used for performing the actual filtering. This one is |
178 // BiquadProcessor::getFrequencyResponse for this purpose. Both, however, po
int to the same | 182 // is created in BiquadProcessor::getFrequencyResponse for this purpose. |
179 // BiquadProcessor object. | 183 // Both, however, point to the same BiquadProcessor object. |
180 // | 184 // |
181 // FIXME: Simplify this: crbug.com/390266 | 185 // FIXME: Simplify this: crbug.com/390266 |
182 MutexLocker processLocker(m_processLock); | 186 MutexLocker processLocker(m_processLock); |
183 | 187 |
184 cutoffFrequency = getBiquadProcessor()->parameter1().value(); | 188 cutoffFrequency = getBiquadProcessor()->parameter1().value(); |
185 Q = getBiquadProcessor()->parameter2().value(); | 189 Q = getBiquadProcessor()->parameter2().value(); |
186 gain = getBiquadProcessor()->parameter3().value(); | 190 gain = getBiquadProcessor()->parameter3().value(); |
187 detune = getBiquadProcessor()->parameter4().value(); | 191 detune = getBiquadProcessor()->parameter4().value(); |
188 } | 192 } |
189 | 193 |
190 updateCoefficients(1, &cutoffFrequency, &Q, &gain, &detune); | 194 updateCoefficients(1, &cutoffFrequency, &Q, &gain, &detune); |
191 | 195 |
192 m_biquad.getFrequencyResponse(nFrequencies, frequency.data(), magResponse, | 196 m_biquad.getFrequencyResponse(nFrequencies, frequency.data(), magResponse, |
193 phaseResponse); | 197 phaseResponse); |
194 } | 198 } |
195 | 199 |
196 double BiquadDSPKernel::tailTime() const { | 200 double BiquadDSPKernel::tailTime() const { |
197 return MaxBiquadDelayTime; | 201 return MaxBiquadDelayTime; |
198 } | 202 } |
199 | 203 |
200 double BiquadDSPKernel::latencyTime() const { | 204 double BiquadDSPKernel::latencyTime() const { |
201 return 0; | 205 return 0; |
202 } | 206 } |
203 | 207 |
204 } // namespace blink | 208 } // namespace blink |
OLD | NEW |