OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2011 Google Inc. All rights reserved. | 2 * Copyright (C) 2011 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 * | 7 * |
8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
88 // Linear crossfade (0 -> 1). | 88 // Linear crossfade (0 -> 1). |
89 m_parameters[ParamEffectBlend] = 1; | 89 m_parameters[ParamEffectBlend] = 1; |
90 } | 90 } |
91 | 91 |
92 float DynamicsCompressor::parameterValue(unsigned parameterID) | 92 float DynamicsCompressor::parameterValue(unsigned parameterID) |
93 { | 93 { |
94 ASSERT(parameterID < ParamLast); | 94 ASSERT(parameterID < ParamLast); |
95 return m_parameters[parameterID]; | 95 return m_parameters[parameterID]; |
96 } | 96 } |
97 | 97 |
98 void DynamicsCompressor::setEmphasisStageParameters(unsigned stageIndex, float g
ain, float normalizedFrequency /* 0 -> 1 */) | |
99 { | |
100 float gk = 1 - gain / 20; | |
101 float f1 = normalizedFrequency * gk; | |
102 float f2 = normalizedFrequency / gk; | |
103 float r1 = expf(-f1 * piFloat); | |
104 float r2 = expf(-f2 * piFloat); | |
105 | |
106 ASSERT(m_numberOfChannels == m_preFilterPacks.size()); | |
107 | |
108 for (unsigned i = 0; i < m_numberOfChannels; ++i) { | |
109 // Set pre-filter zero and pole to create an emphasis filter. | |
110 ZeroPole& preFilter = m_preFilterPacks[i]->filters[stageIndex]; | |
111 preFilter.setZero(r1); | |
112 preFilter.setPole(r2); | |
113 | |
114 // Set post-filter with zero and pole reversed to create the de-emphasis
filter. | |
115 // If there were no compressor kernel in between, they would cancel each
other out (allpass filter). | |
116 ZeroPole& postFilter = m_postFilterPacks[i]->filters[stageIndex]; | |
117 postFilter.setZero(r2); | |
118 postFilter.setPole(r1); | |
119 } | |
120 } | |
121 | |
122 void DynamicsCompressor::setEmphasisParameters(float gain, float anchorFreq, flo
at filterStageRatio) | |
123 { | |
124 setEmphasisStageParameters(0, gain, anchorFreq); | |
125 setEmphasisStageParameters(1, gain, anchorFreq / filterStageRatio); | |
126 setEmphasisStageParameters(2, gain, anchorFreq / (filterStageRatio * filterS
tageRatio)); | |
127 setEmphasisStageParameters(3, gain, anchorFreq / (filterStageRatio * filterS
tageRatio * filterStageRatio)); | |
128 } | |
129 | |
130 void DynamicsCompressor::process(const AudioBus* sourceBus, AudioBus* destinatio
nBus, unsigned framesToProcess) | 98 void DynamicsCompressor::process(const AudioBus* sourceBus, AudioBus* destinatio
nBus, unsigned framesToProcess) |
131 { | 99 { |
132 // Though numberOfChannels is retrived from destinationBus, we still name it
numberOfChannels instead of numberOfDestinationChannels. | 100 // Though numberOfChannels is retrived from destinationBus, we still name it
numberOfChannels instead of numberOfDestinationChannels. |
133 // It's because we internally match sourceChannels's size to destinationBus
by channel up/down mix. Thus we need numberOfChannels | 101 // It's because we internally match sourceChannels's size to destinationBus
by channel up/down mix. Thus we need numberOfChannels |
134 // to do the loop work for both m_sourceChannels and m_destinationChannels. | 102 // to do the loop work for both m_sourceChannels and m_destinationChannels. |
135 | 103 |
136 unsigned numberOfChannels = destinationBus->numberOfChannels(); | 104 unsigned numberOfChannels = destinationBus->numberOfChannels(); |
137 unsigned numberOfSourceChannels = sourceBus->numberOfChannels(); | 105 unsigned numberOfSourceChannels = sourceBus->numberOfChannels(); |
138 | 106 |
139 ASSERT(numberOfChannels == m_numberOfChannels && numberOfSourceChannels); | 107 ASSERT(numberOfChannels == m_numberOfChannels && numberOfSourceChannels); |
(...skipping 26 matching lines...) Expand all Loading... |
166 | 134 |
167 float filterStageGain = parameterValue(ParamFilterStageGain); | 135 float filterStageGain = parameterValue(ParamFilterStageGain); |
168 float filterStageRatio = parameterValue(ParamFilterStageRatio); | 136 float filterStageRatio = parameterValue(ParamFilterStageRatio); |
169 float anchor = parameterValue(ParamFilterAnchor); | 137 float anchor = parameterValue(ParamFilterAnchor); |
170 | 138 |
171 if (filterStageGain != m_lastFilterStageGain || filterStageRatio != m_lastFi
lterStageRatio || anchor != m_lastAnchor) { | 139 if (filterStageGain != m_lastFilterStageGain || filterStageRatio != m_lastFi
lterStageRatio || anchor != m_lastAnchor) { |
172 m_lastFilterStageGain = filterStageGain; | 140 m_lastFilterStageGain = filterStageGain; |
173 m_lastFilterStageRatio = filterStageRatio; | 141 m_lastFilterStageRatio = filterStageRatio; |
174 m_lastAnchor = anchor; | 142 m_lastAnchor = anchor; |
175 | 143 |
176 setEmphasisParameters(filterStageGain, anchor, filterStageRatio); | |
177 } | |
178 | |
179 // Apply pre-emphasis filter. | |
180 // Note that the final three stages are computed in-place in the destination
buffer. | |
181 for (unsigned i = 0; i < numberOfChannels; ++i) { | |
182 const float* sourceData = m_sourceChannels[i]; | |
183 float* destinationData = m_destinationChannels[i]; | |
184 ZeroPole* preFilters = m_preFilterPacks[i]->filters; | |
185 | |
186 preFilters[0].process(sourceData, destinationData, framesToProcess); | |
187 preFilters[1].process(destinationData, destinationData, framesToProcess)
; | |
188 preFilters[2].process(destinationData, destinationData, framesToProcess)
; | |
189 preFilters[3].process(destinationData, destinationData, framesToProcess)
; | |
190 } | 144 } |
191 | 145 |
192 float dbThreshold = parameterValue(ParamThreshold); | 146 float dbThreshold = parameterValue(ParamThreshold); |
193 float dbKnee = parameterValue(ParamKnee); | 147 float dbKnee = parameterValue(ParamKnee); |
194 float ratio = parameterValue(ParamRatio); | 148 float ratio = parameterValue(ParamRatio); |
195 float attackTime = parameterValue(ParamAttack); | 149 float attackTime = parameterValue(ParamAttack); |
196 float releaseTime = parameterValue(ParamRelease); | 150 float releaseTime = parameterValue(ParamRelease); |
197 float preDelayTime = parameterValue(ParamPreDelay); | 151 float preDelayTime = parameterValue(ParamPreDelay); |
198 | 152 |
199 // This is effectively a master volume on the compressed signal (pre-blendin
g). | 153 // This is effectively a master volume on the compressed signal (pre-blendin
g). |
200 float dbPostGain = parameterValue(ParamPostGain); | 154 float dbPostGain = parameterValue(ParamPostGain); |
201 | 155 |
202 // Linear blending value from dry to completely processed (0 -> 1) | 156 // Linear blending value from dry to completely processed (0 -> 1) |
203 // 0 means the signal is completely unprocessed. | 157 // 0 means the signal is completely unprocessed. |
204 // 1 mixes in only the compressed signal. | 158 // 1 mixes in only the compressed signal. |
205 float effectBlend = parameterValue(ParamEffectBlend); | 159 float effectBlend = parameterValue(ParamEffectBlend); |
206 | 160 |
207 float releaseZone1 = parameterValue(ParamReleaseZone1); | 161 float releaseZone1 = parameterValue(ParamReleaseZone1); |
208 float releaseZone2 = parameterValue(ParamReleaseZone2); | 162 float releaseZone2 = parameterValue(ParamReleaseZone2); |
209 float releaseZone3 = parameterValue(ParamReleaseZone3); | 163 float releaseZone3 = parameterValue(ParamReleaseZone3); |
210 float releaseZone4 = parameterValue(ParamReleaseZone4); | 164 float releaseZone4 = parameterValue(ParamReleaseZone4); |
211 | 165 |
212 // Apply compression to the pre-filtered signal. | 166 // Apply compression to the source signal. |
213 // The processing is performed in place. | 167 m_compressor.process(m_sourceChannels.get(), |
214 m_compressor.process(m_destinationChannels.get(), | |
215 m_destinationChannels.get(), | 168 m_destinationChannels.get(), |
216 numberOfChannels, | 169 numberOfChannels, |
217 framesToProcess, | 170 framesToProcess, |
218 | 171 |
219 dbThreshold, | 172 dbThreshold, |
220 dbKnee, | 173 dbKnee, |
221 ratio, | 174 ratio, |
222 attackTime, | 175 attackTime, |
223 releaseTime, | 176 releaseTime, |
224 preDelayTime, | 177 preDelayTime, |
225 dbPostGain, | 178 dbPostGain, |
226 effectBlend, | 179 effectBlend, |
227 | 180 |
228 releaseZone1, | 181 releaseZone1, |
229 releaseZone2, | 182 releaseZone2, |
230 releaseZone3, | 183 releaseZone3, |
231 releaseZone4 | 184 releaseZone4 |
232 ); | 185 ); |
233 | 186 |
234 // Update the compression amount. | 187 // Update the compression amount. |
235 setParameterValue(ParamReduction, m_compressor.meteringGain()); | 188 setParameterValue(ParamReduction, m_compressor.meteringGain()); |
236 | 189 |
237 // Apply de-emphasis filter. | |
238 for (unsigned i = 0; i < numberOfChannels; ++i) { | |
239 float* destinationData = m_destinationChannels[i]; | |
240 ZeroPole* postFilters = m_postFilterPacks[i]->filters; | |
241 | |
242 postFilters[0].process(destinationData, destinationData, framesToProcess
); | |
243 postFilters[1].process(destinationData, destinationData, framesToProcess
); | |
244 postFilters[2].process(destinationData, destinationData, framesToProcess
); | |
245 postFilters[3].process(destinationData, destinationData, framesToProcess
); | |
246 } | |
247 } | 190 } |
248 | 191 |
249 void DynamicsCompressor::reset() | 192 void DynamicsCompressor::reset() |
250 { | 193 { |
251 m_lastFilterStageRatio = -1; // for recalc | 194 m_lastFilterStageRatio = -1; // for recalc |
252 m_lastAnchor = -1; | 195 m_lastAnchor = -1; |
253 m_lastFilterStageGain = -1; | 196 m_lastFilterStageGain = -1; |
254 | 197 |
255 for (unsigned channel = 0; channel < m_numberOfChannels; ++channel) { | |
256 for (unsigned stageIndex = 0; stageIndex < 4; ++stageIndex) { | |
257 m_preFilterPacks[channel]->filters[stageIndex].reset(); | |
258 m_postFilterPacks[channel]->filters[stageIndex].reset(); | |
259 } | |
260 } | |
261 | |
262 m_compressor.reset(); | 198 m_compressor.reset(); |
263 } | 199 } |
264 | 200 |
265 void DynamicsCompressor::setNumberOfChannels(unsigned numberOfChannels) | 201 void DynamicsCompressor::setNumberOfChannels(unsigned numberOfChannels) |
266 { | 202 { |
267 if (m_preFilterPacks.size() == numberOfChannels) | |
268 return; | |
269 | |
270 m_preFilterPacks.clear(); | |
271 m_postFilterPacks.clear(); | |
272 for (unsigned i = 0; i < numberOfChannels; ++i) { | |
273 m_preFilterPacks.append(adoptPtr(new ZeroPoleFilterPack4())); | |
274 m_postFilterPacks.append(adoptPtr(new ZeroPoleFilterPack4())); | |
275 } | |
276 | |
277 m_sourceChannels = adoptArrayPtr(new const float* [numberOfChannels]); | 203 m_sourceChannels = adoptArrayPtr(new const float* [numberOfChannels]); |
278 m_destinationChannels = adoptArrayPtr(new float* [numberOfChannels]); | 204 m_destinationChannels = adoptArrayPtr(new float* [numberOfChannels]); |
279 | 205 |
280 m_compressor.setNumberOfChannels(numberOfChannels); | 206 m_compressor.setNumberOfChannels(numberOfChannels); |
281 m_numberOfChannels = numberOfChannels; | 207 m_numberOfChannels = numberOfChannels; |
282 } | 208 } |
283 | 209 |
284 } // namespace WebCore | 210 } // namespace WebCore |
285 | 211 |
286 #endif // ENABLE(WEB_AUDIO) | 212 #endif // ENABLE(WEB_AUDIO) |
OLD | NEW |