| 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 * | 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 |
| 11 * notice, this list of conditions and the following disclaimer in the | 11 * notice, this list of conditions and the following disclaimer in the |
| 12 * documentation and/or other materials provided with the distribution. | 12 * documentation and/or other materials provided with the distribution. |
| 13 * | 13 * |
| 14 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY | 14 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY |
| 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| 16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | 16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| 17 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY | 17 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY |
| 18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | 18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| 19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | 19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| 20 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | 20 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| 21 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 21 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
| 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 24 */ | 24 */ |
| 25 | 25 |
| 26 #include "modules/webaudio/AudioParam.h" | 26 #include "modules/webaudio/AudioParam.h" |
| 27 #include "modules/webaudio/AudioNode.h" | 27 #include "modules/webaudio/AudioNode.h" |
| 28 #include "modules/webaudio/AudioNodeOutput.h" | 28 #include "modules/webaudio/AudioNodeOutput.h" |
| 29 #include "platform/FloatConversion.h" | 29 #include "platform/FloatConversion.h" |
| 30 #include "platform/Histogram.h" |
| 30 #include "platform/audio/AudioUtilities.h" | 31 #include "platform/audio/AudioUtilities.h" |
| 31 #include "wtf/MathExtras.h" | 32 #include "wtf/MathExtras.h" |
| 32 | 33 |
| 33 namespace blink { | 34 namespace blink { |
| 34 | 35 |
| 35 const double AudioParamHandler::DefaultSmoothingConstant = 0.05; | 36 const double AudioParamHandler::DefaultSmoothingConstant = 0.05; |
| 36 const double AudioParamHandler::SnapThreshold = 0.001; | 37 const double AudioParamHandler::SnapThreshold = 0.001; |
| 37 | 38 |
| 38 AudioParamHandler::AudioParamHandler(AbstractAudioContext& context, AudioParamTy
pe paramType, double defaultValue) | 39 AudioParamHandler::AudioParamHandler(AbstractAudioContext& context, AudioParamTy
pe paramType, double defaultValue) |
| 39 : AudioSummingJunction(context.deferredTaskHandler()) | 40 : AudioSummingJunction(context.deferredTaskHandler()) |
| 40 , m_paramType(paramType) | 41 , m_paramType(paramType) |
| 41 , m_intrinsicValue(defaultValue) | 42 , m_intrinsicValue(defaultValue) |
| 42 , m_defaultValue(defaultValue) | 43 , m_defaultValue(defaultValue) |
| 43 , m_smoothedValue(defaultValue) | 44 , m_smoothedValue(defaultValue) |
| 44 { | 45 { |
| 45 // The destination MUST exist because we need the destination handler for th
e AudioParam. | 46 // The destination MUST exist because we need the destination handler for th
e AudioParam. |
| 46 RELEASE_ASSERT(context.destination()); | 47 RELEASE_ASSERT(context.destination()); |
| 47 | 48 |
| 48 m_destinationHandler = &context.destination()->audioDestinationHandler(); | 49 m_destinationHandler = &context.destination()->audioDestinationHandler(); |
| 49 } | 50 } |
| 50 | 51 |
| 51 AudioDestinationHandler& AudioParamHandler::destinationHandler() const | 52 AudioDestinationHandler& AudioParamHandler::destinationHandler() const |
| 52 { | 53 { |
| 53 return *m_destinationHandler; | 54 return *m_destinationHandler; |
| 54 } | 55 } |
| 55 | 56 |
| 57 void AudioParamHandler::setParamType(AudioParamType paramType) |
| 58 { |
| 59 m_paramType = paramType; |
| 60 } |
| 61 |
| 56 String AudioParamHandler::getParamName() const | 62 String AudioParamHandler::getParamName() const |
| 57 { | 63 { |
| 58 // The returned string should be the name of the node and the name of the Au
dioParam for | 64 // The returned string should be the name of the node and the name of the Au
dioParam for |
| 59 // that node. | 65 // that node. |
| 60 switch (m_paramType) { | 66 switch (m_paramType) { |
| 61 case ParamTypeAudioBufferSourcePlaybackRate: | 67 case ParamTypeAudioBufferSourcePlaybackRate: |
| 62 return "AudioBufferSource.playbackRate"; | 68 return "AudioBufferSource.playbackRate"; |
| 63 case ParamTypeAudioBufferSourceDetune: | 69 case ParamTypeAudioBufferSourceDetune: |
| 64 return "AudioBufferSource.detune"; | 70 return "AudioBufferSource.detune"; |
| 65 case ParamTypeBiquadFilterFrequency: | 71 case ParamTypeBiquadFilterFrequency: |
| 66 return "BiquadFilter.frequency"; | 72 return "BiquadFilter.frequency"; |
| 67 case ParamTypeBiquadFilterQ: | 73 case ParamTypeBiquadFilterQ: |
| 74 case ParamTypeBiquadFilterQLowpass: |
| 75 case ParamTypeBiquadFilterQHighpass: |
| 76 // We don't really need separate names for the Q parameter for lowpass a
nd highpass filters. |
| 77 // The difference is only for the histograms. |
| 68 return "BiquadFilter.Q"; | 78 return "BiquadFilter.Q"; |
| 69 case ParamTypeBiquadFilterGain: | 79 case ParamTypeBiquadFilterGain: |
| 70 return "BiquadFilter.gain"; | 80 return "BiquadFilter.gain"; |
| 71 case ParamTypeBiquadFilterDetune: | 81 case ParamTypeBiquadFilterDetune: |
| 72 return "BiquadFilter.detune"; | 82 return "BiquadFilter.detune"; |
| 73 case ParamTypeDelayDelayTime: | 83 case ParamTypeDelayDelayTime: |
| 74 return "Delay.delayTime"; | 84 return "Delay.delayTime"; |
| 75 case ParamTypeDynamicsCompressorThreshold: | 85 case ParamTypeDynamicsCompressorThreshold: |
| 76 return "DynamicsCompressor.threshold"; | 86 return "DynamicsCompressor.threshold"; |
| 77 case ParamTypeDynamicsCompressorKnee: | 87 case ParamTypeDynamicsCompressorKnee: |
| (...skipping 30 matching lines...) Expand all Loading... |
| 108 v = timelineValue; | 118 v = timelineValue; |
| 109 } | 119 } |
| 110 | 120 |
| 111 setIntrinsicValue(v); | 121 setIntrinsicValue(v); |
| 112 return v; | 122 return v; |
| 113 } | 123 } |
| 114 | 124 |
| 115 void AudioParamHandler::setValue(float value) | 125 void AudioParamHandler::setValue(float value) |
| 116 { | 126 { |
| 117 setIntrinsicValue(value); | 127 setIntrinsicValue(value); |
| 128 updateHistograms(value); |
| 118 } | 129 } |
| 119 | 130 |
| 120 float AudioParamHandler::smoothedValue() | 131 float AudioParamHandler::smoothedValue() |
| 121 { | 132 { |
| 122 return m_smoothedValue; | 133 return m_smoothedValue; |
| 123 } | 134 } |
| 124 | 135 |
| 125 bool AudioParamHandler::smooth() | 136 bool AudioParamHandler::smooth() |
| 126 { | 137 { |
| 127 // If values have been explicitly scheduled on the timeline, then use the ex
act value. | 138 // If values have been explicitly scheduled on the timeline, then use the ex
act value. |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 240 { | 251 { |
| 241 ASSERT(deferredTaskHandler().isGraphOwner()); | 252 ASSERT(deferredTaskHandler().isGraphOwner()); |
| 242 | 253 |
| 243 if (m_outputs.contains(&output)) { | 254 if (m_outputs.contains(&output)) { |
| 244 m_outputs.remove(&output); | 255 m_outputs.remove(&output); |
| 245 changedOutputs(); | 256 changedOutputs(); |
| 246 output.removeParam(*this); | 257 output.removeParam(*this); |
| 247 } | 258 } |
| 248 } | 259 } |
| 249 | 260 |
| 261 int AudioParamHandler::computeQHistogramValue(float newValue) const |
| 262 { |
| 263 // For the Q value, assume a useful range is [0, 25] and that 0.25 dB resolu
tion is good enough. |
| 264 // Then, we can map the floating point Q value (in dB) to an integer just by
multipling by 4 and |
| 265 // rounding. |
| 266 newValue = clampTo(newValue, 0.0, 25.0); |
| 267 return static_cast<int>(4 * newValue + 0.5); |
| 268 } |
| 269 |
| 270 void AudioParamHandler::updateHistograms(float newValue) |
| 271 { |
| 272 switch (m_paramType) { |
| 273 case ParamTypeBiquadFilterQLowpass: |
| 274 { |
| 275 // The histogram for the Q value for a lowpass biquad filter. |
| 276 DEFINE_STATIC_LOCAL(SparseHistogram, lowpassQHistogram, ("WebAudio.B
iquadFilter.Q.Lowpass")); |
| 277 |
| 278 lowpassQHistogram.sample(computeQHistogramValue(newValue)); |
| 279 } |
| 280 break; |
| 281 case ParamTypeBiquadFilterQHighpass: |
| 282 { |
| 283 // The histogram for the Q value for a highpass biquad filter. |
| 284 DEFINE_STATIC_LOCAL(SparseHistogram, highpassQHistogram, ("WebAudio.
BiquadFilter.Q.Highpass")); |
| 285 |
| 286 highpassQHistogram.sample(computeQHistogramValue(newValue)); |
| 287 } |
| 288 break; |
| 289 default: |
| 290 // Nothing to do for all other types. |
| 291 break; |
| 292 } |
| 293 } |
| 294 |
| 250 // ---------------------------------------------------------------- | 295 // ---------------------------------------------------------------- |
| 251 | 296 |
| 252 AudioParam::AudioParam(AbstractAudioContext& context, AudioParamType paramType,
double defaultValue) | 297 AudioParam::AudioParam(AbstractAudioContext& context, AudioParamType paramType,
double defaultValue) |
| 253 : m_handler(AudioParamHandler::create(context, paramType, defaultValue)) | 298 : m_handler(AudioParamHandler::create(context, paramType, defaultValue)) |
| 254 , m_context(context) | 299 , m_context(context) |
| 255 { | 300 { |
| 256 } | 301 } |
| 257 | 302 |
| 258 AudioParam* AudioParam::create(AbstractAudioContext& context, AudioParamType par
amType, double defaultValue) | 303 AudioParam* AudioParam::create(AbstractAudioContext& context, AudioParamType par
amType, double defaultValue) |
| 259 { | 304 { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 273 void AudioParam::setValue(float value) | 318 void AudioParam::setValue(float value) |
| 274 { | 319 { |
| 275 handler().setValue(value); | 320 handler().setValue(value); |
| 276 } | 321 } |
| 277 | 322 |
| 278 float AudioParam::defaultValue() const | 323 float AudioParam::defaultValue() const |
| 279 { | 324 { |
| 280 return handler().defaultValue(); | 325 return handler().defaultValue(); |
| 281 } | 326 } |
| 282 | 327 |
| 328 void AudioParam::setParamType(AudioParamType paramType) |
| 329 { |
| 330 handler().setParamType(paramType); |
| 331 } |
| 332 |
| 283 AudioParam* AudioParam::setValueAtTime(float value, double time, ExceptionState&
exceptionState) | 333 AudioParam* AudioParam::setValueAtTime(float value, double time, ExceptionState&
exceptionState) |
| 284 { | 334 { |
| 285 handler().timeline().setValueAtTime(value, time, exceptionState); | 335 handler().timeline().setValueAtTime(value, time, exceptionState); |
| 336 handler().updateHistograms(value); |
| 286 return this; | 337 return this; |
| 287 } | 338 } |
| 288 | 339 |
| 289 AudioParam* AudioParam::linearRampToValueAtTime(float value, double time, Except
ionState& exceptionState) | 340 AudioParam* AudioParam::linearRampToValueAtTime(float value, double time, Except
ionState& exceptionState) |
| 290 { | 341 { |
| 291 handler().timeline().linearRampToValueAtTime( | 342 handler().timeline().linearRampToValueAtTime( |
| 292 value, time, handler().intrinsicValue(), context()->currentTime(), excep
tionState); | 343 value, time, handler().intrinsicValue(), context()->currentTime(), excep
tionState); |
| 344 |
| 345 // This is probably the best we can do for the histogram. We don't want to
run the automation |
| 346 // to get all the values and use them to update the histogram. |
| 347 handler().updateHistograms(value); |
| 348 |
| 293 return this; | 349 return this; |
| 294 } | 350 } |
| 295 | 351 |
| 296 AudioParam* AudioParam::exponentialRampToValueAtTime(float value, double time, E
xceptionState& exceptionState) | 352 AudioParam* AudioParam::exponentialRampToValueAtTime(float value, double time, E
xceptionState& exceptionState) |
| 297 { | 353 { |
| 298 handler().timeline().exponentialRampToValueAtTime(value, time, handler().int
rinsicValue(), context()->currentTime(), exceptionState); | 354 handler().timeline().exponentialRampToValueAtTime(value, time, handler().int
rinsicValue(), context()->currentTime(), exceptionState); |
| 355 |
| 356 // This is probably the best we can do for the histogram. We don't want to
run the automation |
| 357 // to get all the values and use them to update the histogram. |
| 358 handler().updateHistograms(value); |
| 359 |
| 299 return this; | 360 return this; |
| 300 } | 361 } |
| 301 | 362 |
| 302 AudioParam* AudioParam::setTargetAtTime(float target, double time, double timeCo
nstant, ExceptionState& exceptionState) | 363 AudioParam* AudioParam::setTargetAtTime(float target, double time, double timeCo
nstant, ExceptionState& exceptionState) |
| 303 { | 364 { |
| 304 handler().timeline().setTargetAtTime(target, time, timeConstant, exceptionSt
ate); | 365 handler().timeline().setTargetAtTime(target, time, timeConstant, exceptionSt
ate); |
| 366 |
| 367 // Don't update the histogram here. It's not clear in normal usage if the p
arameter value will |
| 368 // actually reach |target|. |
| 305 return this; | 369 return this; |
| 306 } | 370 } |
| 307 | 371 |
| 308 AudioParam* AudioParam::setValueCurveAtTime(DOMFloat32Array* curve, double time,
double duration, ExceptionState& exceptionState) | 372 AudioParam* AudioParam::setValueCurveAtTime(DOMFloat32Array* curve, double time,
double duration, ExceptionState& exceptionState) |
| 309 { | 373 { |
| 310 handler().timeline().setValueCurveAtTime(curve, time, duration, exceptionSta
te); | 374 handler().timeline().setValueCurveAtTime(curve, time, duration, exceptionSta
te); |
| 375 |
| 376 // We could update the histogram with every value in the curve, due to inter
polation, we'll |
| 377 // probably be missing many values. So we don't update the histogram. setV
alueCurveAtTime is |
| 378 // probably a fairly rare method anyway. |
| 311 return this; | 379 return this; |
| 312 } | 380 } |
| 313 | 381 |
| 314 AudioParam* AudioParam::cancelScheduledValues(double startTime, ExceptionState&
exceptionState) | 382 AudioParam* AudioParam::cancelScheduledValues(double startTime, ExceptionState&
exceptionState) |
| 315 { | 383 { |
| 316 handler().timeline().cancelScheduledValues(startTime, exceptionState); | 384 handler().timeline().cancelScheduledValues(startTime, exceptionState); |
| 317 return this; | 385 return this; |
| 318 } | 386 } |
| 319 | 387 |
| 320 } // namespace blink | 388 } // namespace blink |
| 321 | 389 |
| OLD | NEW |