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 <limits.h> | 27 #include <limits.h> |
28 #include "platform/audio/AudioUtilities.h" | 28 #include "platform/audio/AudioUtilities.h" |
29 #include "platform/wtf/MathExtras.h" | 29 #include "platform/wtf/MathExtras.h" |
30 #include "platform/wtf/Vector.h" | 30 #include "platform/wtf/Vector.h" |
31 | 31 |
32 namespace blink { | 32 namespace blink { |
33 | 33 |
| 34 // FIXME: As a recursive linear filter, depending on its parameters, a biquad |
| 35 // filter can have an infinite tailTime. In practice, Biquad filters do not |
| 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 |
| 38 // settings of the Biquad. |
| 39 static const double kMaxBiquadDelayTime = 0.2; |
| 40 |
34 void BiquadDSPKernel::UpdateCoefficientsIfNecessary(int frames_to_process) { | 41 void BiquadDSPKernel::UpdateCoefficientsIfNecessary(int frames_to_process) { |
35 if (GetBiquadProcessor()->FilterCoefficientsDirty()) { | 42 if (GetBiquadProcessor()->FilterCoefficientsDirty()) { |
36 float cutoff_frequency[AudioUtilities::kRenderQuantumFrames]; | 43 float cutoff_frequency[AudioUtilities::kRenderQuantumFrames]; |
37 float q[AudioUtilities::kRenderQuantumFrames]; | 44 float q[AudioUtilities::kRenderQuantumFrames]; |
38 float gain[AudioUtilities::kRenderQuantumFrames]; | 45 float gain[AudioUtilities::kRenderQuantumFrames]; |
39 float detune[AudioUtilities::kRenderQuantumFrames]; // in Cents | 46 float detune[AudioUtilities::kRenderQuantumFrames]; // in Cents |
40 | 47 |
41 SECURITY_CHECK(static_cast<unsigned>(frames_to_process) <= | 48 SECURITY_CHECK(static_cast<unsigned>(frames_to_process) <= |
42 AudioUtilities::kRenderQuantumFrames); | 49 AudioUtilities::kRenderQuantumFrames); |
43 | 50 |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
107 | 114 |
108 case BiquadProcessor::kNotch: | 115 case BiquadProcessor::kNotch: |
109 biquad_.SetNotchParams(k, normalized_frequency, q[k]); | 116 biquad_.SetNotchParams(k, normalized_frequency, q[k]); |
110 break; | 117 break; |
111 | 118 |
112 case BiquadProcessor::kAllpass: | 119 case BiquadProcessor::kAllpass: |
113 biquad_.SetAllpassParams(k, normalized_frequency, q[k]); | 120 biquad_.SetAllpassParams(k, normalized_frequency, q[k]); |
114 break; | 121 break; |
115 } | 122 } |
116 } | 123 } |
117 | |
118 UpdateTailTime(number_of_frames - 1); | |
119 } | |
120 | |
121 void BiquadDSPKernel::UpdateTailTime(int coef_index) { | |
122 // A reasonable upper limit for the tail time. While it's easy to | |
123 // create biquad filters whose tail time can be much larger than | |
124 // this, limit the maximum to this value so that we don't keep such | |
125 // nodes alive "forever". | |
126 // TODO: What is a reasonable upper limit? | |
127 const double kMaxTailTime = 30; | |
128 | |
129 double sample_rate = SampleRate(); | |
130 double tail = | |
131 biquad_.TailFrame(coef_index, kMaxTailTime * sample_rate) / sample_rate; | |
132 | |
133 tail_time_ = clampTo(tail, 0.0, kMaxTailTime); | |
134 } | 124 } |
135 | 125 |
136 void BiquadDSPKernel::Process(const float* source, | 126 void BiquadDSPKernel::Process(const float* source, |
137 float* destination, | 127 float* destination, |
138 size_t frames_to_process) { | 128 size_t frames_to_process) { |
139 DCHECK(source); | 129 DCHECK(source); |
140 DCHECK(destination); | 130 DCHECK(destination); |
141 DCHECK(GetBiquadProcessor()); | 131 DCHECK(GetBiquadProcessor()); |
142 | 132 |
143 // Recompute filter coefficients if any of the parameters have changed. | 133 // Recompute filter coefficients if any of the parameters have changed. |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
202 detune = GetBiquadProcessor()->Parameter4().Value(); | 192 detune = GetBiquadProcessor()->Parameter4().Value(); |
203 } | 193 } |
204 | 194 |
205 UpdateCoefficients(1, &cutoff_frequency, &q, &gain, &detune); | 195 UpdateCoefficients(1, &cutoff_frequency, &q, &gain, &detune); |
206 | 196 |
207 biquad_.GetFrequencyResponse(n_frequencies, frequency.data(), mag_response, | 197 biquad_.GetFrequencyResponse(n_frequencies, frequency.data(), mag_response, |
208 phase_response); | 198 phase_response); |
209 } | 199 } |
210 | 200 |
211 double BiquadDSPKernel::TailTime() const { | 201 double BiquadDSPKernel::TailTime() const { |
212 return tail_time_; | 202 return kMaxBiquadDelayTime; |
213 } | 203 } |
214 | 204 |
215 double BiquadDSPKernel::LatencyTime() const { | 205 double BiquadDSPKernel::LatencyTime() const { |
216 return 0; | 206 return 0; |
217 } | 207 } |
218 | 208 |
219 } // namespace blink | 209 } // namespace blink |
OLD | NEW |