Chromium Code Reviews| 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 AudioDestinationHandler& AudioParamHandler::destinationHandler() const | 39 AudioDestinationHandler& AudioParamHandler::destinationHandler() const |
| 39 { | 40 { |
| 40 return *m_destinationHandler; | 41 return *m_destinationHandler; |
| 41 } | 42 } |
| 42 | 43 |
| 44 void AudioParamHandler::setParamType(AudioParamType paramType) | |
| 45 { | |
| 46 m_paramType = paramType; | |
| 47 } | |
| 48 | |
| 43 String AudioParamHandler::getParamName() const | 49 String AudioParamHandler::getParamName() const |
| 44 { | 50 { |
| 45 // The returned string should be the name of the node and the name of the Au dioParam for | 51 // The returned string should be the name of the node and the name of the Au dioParam for |
| 46 // that node. | 52 // that node. |
| 47 switch (m_paramType) { | 53 switch (m_paramType) { |
| 48 case ParamTypeAudioBufferSourcePlaybackRate: | 54 case ParamTypeAudioBufferSourcePlaybackRate: |
| 49 return "AudioBufferSource.playbackRate"; | 55 return "AudioBufferSource.playbackRate"; |
| 50 case ParamTypeAudioBufferSourceDetune: | 56 case ParamTypeAudioBufferSourceDetune: |
| 51 return "AudioBufferSource.detune"; | 57 return "AudioBufferSource.detune"; |
| 52 case ParamTypeBiquadFilterFrequency: | 58 case ParamTypeBiquadFilterFrequency: |
| 53 return "BiquadFilter.frequency"; | 59 return "BiquadFilter.frequency"; |
| 54 case ParamTypeBiquadFilterQ: | 60 case ParamTypeBiquadFilterQ: |
| 61 case ParamTypeBiquadFilterQLowpass: | |
| 62 case ParamTypeBiquadFilterQHighpass: | |
| 63 // We don't really need separate names for the Q parameter for lowpass a nd highpass filters. | |
| 64 // The difference is only for the histograms. | |
| 55 return "BiquadFilter.Q"; | 65 return "BiquadFilter.Q"; |
| 56 case ParamTypeBiquadFilterGain: | 66 case ParamTypeBiquadFilterGain: |
| 57 return "BiquadFilter.gain"; | 67 return "BiquadFilter.gain"; |
| 58 case ParamTypeBiquadFilterDetune: | 68 case ParamTypeBiquadFilterDetune: |
| 59 return "BiquadFilter.detune"; | 69 return "BiquadFilter.detune"; |
| 60 case ParamTypeDelayDelayTime: | 70 case ParamTypeDelayDelayTime: |
| 61 return "Delay.delayTime"; | 71 return "Delay.delayTime"; |
| 62 case ParamTypeDynamicsCompressorThreshold: | 72 case ParamTypeDynamicsCompressorThreshold: |
| 63 return "DynamicsCompressor.threshold"; | 73 return "DynamicsCompressor.threshold"; |
| 64 case ParamTypeDynamicsCompressorKnee: | 74 case ParamTypeDynamicsCompressorKnee: |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 95 v = timelineValue; | 105 v = timelineValue; |
| 96 } | 106 } |
| 97 | 107 |
| 98 setIntrinsicValue(v); | 108 setIntrinsicValue(v); |
| 99 return v; | 109 return v; |
| 100 } | 110 } |
| 101 | 111 |
| 102 void AudioParamHandler::setValue(float value) | 112 void AudioParamHandler::setValue(float value) |
| 103 { | 113 { |
| 104 setIntrinsicValue(value); | 114 setIntrinsicValue(value); |
| 115 updateHistograms(value); | |
| 105 } | 116 } |
| 106 | 117 |
| 107 float AudioParamHandler::smoothedValue() | 118 float AudioParamHandler::smoothedValue() |
| 108 { | 119 { |
| 109 return m_smoothedValue; | 120 return m_smoothedValue; |
| 110 } | 121 } |
| 111 | 122 |
| 112 bool AudioParamHandler::smooth() | 123 bool AudioParamHandler::smooth() |
| 113 { | 124 { |
| 114 // If values have been explicitly scheduled on the timeline, then use the ex act value. | 125 // 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... | |
| 227 { | 238 { |
| 228 ASSERT(deferredTaskHandler().isGraphOwner()); | 239 ASSERT(deferredTaskHandler().isGraphOwner()); |
| 229 | 240 |
| 230 if (m_outputs.contains(&output)) { | 241 if (m_outputs.contains(&output)) { |
| 231 m_outputs.remove(&output); | 242 m_outputs.remove(&output); |
| 232 changedOutputs(); | 243 changedOutputs(); |
| 233 output.removeParam(*this); | 244 output.removeParam(*this); |
| 234 } | 245 } |
| 235 } | 246 } |
| 236 | 247 |
| 248 void AudioParamHandler::updateHistograms(float newValue) | |
| 249 { | |
| 250 switch (m_paramType) { | |
| 251 case ParamTypeBiquadFilterQLowpass: | |
| 252 { | |
| 253 // The Q parameter of a lowpass and highpass BiquadFilter is in dB. Let's assume a | |
| 254 // useful range is [0, 50]. And also assume 0.01 dB resolution is g ood enough. Then, | |
| 255 // we can map the floating point Q value to an integer just by multi pling by 100. So | |
| 256 // the max value is 5000. | |
| 257 DEFINE_STATIC_LOCAL( | |
| 258 EnumerationHistogram, lowpassQHistogram, | |
| 259 ("WebAudio.BiquadFilter.Q.Lowpass", 5000)); | |
|
Raymond Toy
2016/05/06 17:07:34
Should the limit here be 5000 or 5001?
Is Enumera
Mark P
2016/05/06 23:58:34
Probably neither, see below.
Raymond Toy
2016/05/09 17:17:09
Rounding Q to an int is probably ok. Perhaps I'll
| |
| 260 newValue = clampTo(newValue, 0, 50); | |
| 261 int histogramValue = static_cast<int>(100 * newValue); | |
| 262 lowpassQHistogram.count(histogramValue); | |
| 263 } | |
| 264 break; | |
| 265 case ParamTypeBiquadFilterQHighpass: | |
| 266 { | |
| 267 // The histogram for the highpass filter has the same constraints as for the lowpass | |
| 268 // filter above. | |
| 269 DEFINE_STATIC_LOCAL( | |
| 270 EnumerationHistogram, highpassQHistogram, | |
| 271 ("WebAudio.BiquadFilter.Q.Highpass", 5000)); | |
| 272 newValue = clampTo(newValue, 0, 50); | |
| 273 int histogramValue = static_cast<int>(100 * newValue); | |
| 274 highpassQHistogram.count(histogramValue); | |
| 275 } | |
| 276 break; | |
| 277 default: | |
| 278 // Nothing to do for all other types. | |
| 279 break; | |
| 280 } | |
| 281 } | |
| 282 | |
| 237 // ---------------------------------------------------------------- | 283 // ---------------------------------------------------------------- |
| 238 | 284 |
| 239 AudioParam::AudioParam(AbstractAudioContext& context, AudioParamType paramType, double defaultValue) | 285 AudioParam::AudioParam(AbstractAudioContext& context, AudioParamType paramType, double defaultValue) |
| 240 : m_handler(AudioParamHandler::create(context, paramType, defaultValue)) | 286 : m_handler(AudioParamHandler::create(context, paramType, defaultValue)) |
| 241 , m_context(context) | 287 , m_context(context) |
| 242 { | 288 { |
| 243 } | 289 } |
| 244 | 290 |
| 245 AudioParam* AudioParam::create(AbstractAudioContext& context, AudioParamType par amType, double defaultValue) | 291 AudioParam* AudioParam::create(AbstractAudioContext& context, AudioParamType par amType, double defaultValue) |
| 246 { | 292 { |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 260 void AudioParam::setValue(float value) | 306 void AudioParam::setValue(float value) |
| 261 { | 307 { |
| 262 handler().setValue(value); | 308 handler().setValue(value); |
| 263 } | 309 } |
| 264 | 310 |
| 265 float AudioParam::defaultValue() const | 311 float AudioParam::defaultValue() const |
| 266 { | 312 { |
| 267 return handler().defaultValue(); | 313 return handler().defaultValue(); |
| 268 } | 314 } |
| 269 | 315 |
| 316 void AudioParam::setParamType(AudioParamType paramType) | |
| 317 { | |
| 318 handler().setParamType(paramType); | |
| 319 } | |
| 320 | |
| 270 AudioParam* AudioParam::setValueAtTime(float value, double time, ExceptionState& exceptionState) | 321 AudioParam* AudioParam::setValueAtTime(float value, double time, ExceptionState& exceptionState) |
| 271 { | 322 { |
| 272 handler().timeline().setValueAtTime(value, time, exceptionState); | 323 handler().timeline().setValueAtTime(value, time, exceptionState); |
| 324 handler().updateHistograms(value); | |
| 273 return this; | 325 return this; |
| 274 } | 326 } |
| 275 | 327 |
| 276 AudioParam* AudioParam::linearRampToValueAtTime(float value, double time, Except ionState& exceptionState) | 328 AudioParam* AudioParam::linearRampToValueAtTime(float value, double time, Except ionState& exceptionState) |
| 277 { | 329 { |
| 278 handler().timeline().linearRampToValueAtTime( | 330 handler().timeline().linearRampToValueAtTime( |
| 279 value, time, handler().intrinsicValue(), context()->currentTime(), excep tionState); | 331 value, time, handler().intrinsicValue(), context()->currentTime(), excep tionState); |
| 332 | |
| 333 // This is probably the best we can do for the histogram. We don't want to run the automation | |
| 334 // to get all the values and use them to update the histogram. | |
| 335 handler().updateHistograms(value); | |
| 336 | |
| 280 return this; | 337 return this; |
| 281 } | 338 } |
| 282 | 339 |
| 283 AudioParam* AudioParam::exponentialRampToValueAtTime(float value, double time, E xceptionState& exceptionState) | 340 AudioParam* AudioParam::exponentialRampToValueAtTime(float value, double time, E xceptionState& exceptionState) |
| 284 { | 341 { |
| 285 handler().timeline().exponentialRampToValueAtTime(value, time, handler().int rinsicValue(), context()->currentTime(), exceptionState); | 342 handler().timeline().exponentialRampToValueAtTime(value, time, handler().int rinsicValue(), context()->currentTime(), exceptionState); |
| 343 | |
| 344 // This is probably the best we can do for the histogram. We don't want to run the automation | |
| 345 // to get all the values and use them to update the histogram. | |
| 346 handler().updateHistograms(value); | |
| 347 | |
| 286 return this; | 348 return this; |
| 287 } | 349 } |
| 288 | 350 |
| 289 AudioParam* AudioParam::setTargetAtTime(float target, double time, double timeCo nstant, ExceptionState& exceptionState) | 351 AudioParam* AudioParam::setTargetAtTime(float target, double time, double timeCo nstant, ExceptionState& exceptionState) |
| 290 { | 352 { |
| 291 handler().timeline().setTargetAtTime(target, time, timeConstant, exceptionSt ate); | 353 handler().timeline().setTargetAtTime(target, time, timeConstant, exceptionSt ate); |
| 354 | |
| 355 // Don't update the histogram here. It's not clear in normal usage if the p arameter value will | |
| 356 // actually reach |target|. | |
| 292 return this; | 357 return this; |
| 293 } | 358 } |
| 294 | 359 |
| 295 AudioParam* AudioParam::setValueCurveAtTime(DOMFloat32Array* curve, double time, double duration, ExceptionState& exceptionState) | 360 AudioParam* AudioParam::setValueCurveAtTime(DOMFloat32Array* curve, double time, double duration, ExceptionState& exceptionState) |
| 296 { | 361 { |
| 297 handler().timeline().setValueCurveAtTime(curve, time, duration, exceptionSta te); | 362 handler().timeline().setValueCurveAtTime(curve, time, duration, exceptionSta te); |
| 363 | |
| 364 // We could update the histogram with every value in the curve, due to inter polation, we'll | |
| 365 // probably be missing many values. So we don't update the histogram. setV alueCurveAtTime is | |
| 366 // probably a fairly rare method anyway. | |
| 298 return this; | 367 return this; |
| 299 } | 368 } |
| 300 | 369 |
| 301 AudioParam* AudioParam::cancelScheduledValues(double startTime, ExceptionState& exceptionState) | 370 AudioParam* AudioParam::cancelScheduledValues(double startTime, ExceptionState& exceptionState) |
| 302 { | 371 { |
| 303 handler().timeline().cancelScheduledValues(startTime, exceptionState); | 372 handler().timeline().cancelScheduledValues(startTime, exceptionState); |
| 304 return this; | 373 return this; |
| 305 } | 374 } |
| 306 | 375 |
| 307 } // namespace blink | 376 } // namespace blink |
| 308 | 377 |
| OLD | NEW |