| 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 |