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 11 matching lines...) Expand all Loading... |
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/AudioParamTimeline.h" | 26 #include "modules/webaudio/AudioParamTimeline.h" |
27 #include "bindings/core/v8/ExceptionState.h" | 27 #include "bindings/core/v8/ExceptionState.h" |
28 #include "core/dom/ExceptionCode.h" | 28 #include "core/dom/ExceptionCode.h" |
29 #include "platform/audio/AudioUtilities.h" | 29 #include "platform/audio/AudioUtilities.h" |
30 #include "wtf/CPU.h" | 30 #include "wtf/CPU.h" |
31 #include "wtf/MathExtras.h" | 31 #include "wtf/MathExtras.h" |
| 32 #include "wtf/PtrUtil.h" |
32 #include <algorithm> | 33 #include <algorithm> |
33 | 34 |
34 #if CPU(X86) || CPU(X86_64) | 35 #if CPU(X86) || CPU(X86_64) |
35 #include <emmintrin.h> | 36 #include <emmintrin.h> |
36 #endif | 37 #endif |
37 | 38 |
38 namespace blink { | 39 namespace blink { |
39 | 40 |
40 // For a SetTarget event, if the relative difference between the current value | 41 // For a SetTarget event, if the relative difference between the current value |
41 // and the target value is less than this, consider them the same and just | 42 // and the target value is less than this, consider them the same and just |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
99 s = "setTargetAtTime"; | 100 s = "setTargetAtTime"; |
100 // This has an extra time constant arg | 101 // This has an extra time constant arg |
101 args = args + ", " + String::number(event.timeConstant(), 16); | 102 args = args + ", " + String::number(event.timeConstant(), 16); |
102 break; | 103 break; |
103 case ParamEvent::SetValueCurve: | 104 case ParamEvent::SetValueCurve: |
104 s = "setValueCurveAtTime"; | 105 s = "setValueCurveAtTime"; |
105 // Replace the default arg, using "..." to denote the curve argument. | 106 // Replace the default arg, using "..." to denote the curve argument. |
106 args = "..., " + String::number(event.time(), 16) + ", " + | 107 args = "..., " + String::number(event.time(), 16) + ", " + |
107 String::number(event.duration(), 16); | 108 String::number(event.duration(), 16); |
108 break; | 109 break; |
| 110 case ParamEvent::CancelValues: |
| 111 // Fall through; we should never have to print out the internal |
| 112 // CancelValues event. |
109 case ParamEvent::LastType: | 113 case ParamEvent::LastType: |
110 ASSERT_NOT_REACHED(); | 114 ASSERT_NOT_REACHED(); |
111 break; | 115 break; |
112 }; | 116 }; |
113 | 117 |
114 return s + "(" + args + ")"; | 118 return s + "(" + args + ")"; |
115 } | 119 } |
116 | 120 |
117 AudioParamTimeline::ParamEvent::ParamEvent(Type type, | 121 // Computes the value of a linear ramp event at time t with the given event |
118 float value, | 122 // parameters. |
119 double time, | 123 float AudioParamTimeline::linearRampAtTime(double t, |
120 double timeConstant, | 124 float value1, |
121 double duration, | 125 double time1, |
122 const DOMFloat32Array* curve, | 126 float value2, |
123 float initialValue, | 127 double time2) { |
124 double callTime) | 128 return value1 + (value2 - value1) * (t - time1) / (time2 - time1); |
125 : m_type(type), | |
126 m_value(value), | |
127 m_time(time), | |
128 m_timeConstant(timeConstant), | |
129 m_duration(duration), | |
130 m_initialValue(initialValue), | |
131 m_callTime(callTime), | |
132 m_needsTimeClampCheck(true) { | |
133 if (curve) { | |
134 // Copy the curve data | |
135 unsigned curveLength = curve->length(); | |
136 m_curve.resize(curveLength); | |
137 memcpy(m_curve.data(), curve->data(), curveLength * sizeof(float)); | |
138 } | |
139 } | 129 } |
140 | 130 |
141 AudioParamTimeline::ParamEvent | 131 // Computes the value of an exponential ramp event at time t with the given |
142 AudioParamTimeline::ParamEvent::createSetValueEvent(float value, double time) { | 132 // event parameters. |
143 return ParamEvent(ParamEvent::SetValue, value, time, 0, 0, nullptr); | 133 float AudioParamTimeline::exponentialRampAtTime(double t, |
| 134 float value1, |
| 135 double time1, |
| 136 float value2, |
| 137 double time2) { |
| 138 return value1 * pow(value2 / value1, (t - time1) / (time2 - time1)); |
144 } | 139 } |
145 | 140 |
146 AudioParamTimeline::ParamEvent | 141 // Compute the value of a set target event at time t with the given event |
| 142 // parameters. |
| 143 float AudioParamTimeline::targetValueAtTime(double t, |
| 144 float value1, |
| 145 double time1, |
| 146 float value2, |
| 147 float timeConstant) { |
| 148 return value2 + (value1 - value2) * exp(-(t - time1) / timeConstant); |
| 149 } |
| 150 |
| 151 // Compute the value of a set curve event at time t with the given event |
| 152 // parameters. |
| 153 float AudioParamTimeline::valueCurveAtTime(double t, |
| 154 double time1, |
| 155 double duration, |
| 156 const float* curveData, |
| 157 unsigned curveLength) { |
| 158 double curveIndex = (curveLength - 1) / duration * (t - time1); |
| 159 unsigned k = std::min(static_cast<unsigned>(curveIndex), curveLength - 1); |
| 160 unsigned k1 = std::min(k + 1, curveLength - 1); |
| 161 float c0 = curveData[k]; |
| 162 float c1 = curveData[k1]; |
| 163 float delta = std::min(curveIndex - k, 1.0); |
| 164 |
| 165 return c0 + (c1 - c0) * delta; |
| 166 } |
| 167 |
| 168 std::unique_ptr<AudioParamTimeline::ParamEvent> |
| 169 AudioParamTimeline::ParamEvent::createSetValueEvent(float value, double time) { |
| 170 return WTF::wrapUnique(new ParamEvent(ParamEvent::SetValue, value, time)); |
| 171 } |
| 172 |
| 173 std::unique_ptr<AudioParamTimeline::ParamEvent> |
147 AudioParamTimeline::ParamEvent::createLinearRampEvent(float value, | 174 AudioParamTimeline::ParamEvent::createLinearRampEvent(float value, |
148 double time, | 175 double time, |
149 float initialValue, | 176 float initialValue, |
150 double callTime) { | 177 double callTime) { |
151 return ParamEvent(ParamEvent::LinearRampToValue, value, time, 0, 0, nullptr, | 178 return WTF::wrapUnique(new ParamEvent(ParamEvent::LinearRampToValue, value, |
152 initialValue, callTime); | 179 time, initialValue, callTime)); |
153 } | 180 } |
154 | 181 |
155 AudioParamTimeline::ParamEvent | 182 std::unique_ptr<AudioParamTimeline::ParamEvent> |
156 AudioParamTimeline::ParamEvent::createExponentialRampEvent(float value, | 183 AudioParamTimeline::ParamEvent::createExponentialRampEvent(float value, |
157 double time, | 184 double time, |
158 float initialValue, | 185 float initialValue, |
159 double callTime) { | 186 double callTime) { |
160 return ParamEvent(ParamEvent::ExponentialRampToValue, value, time, 0, 0, | 187 return WTF::wrapUnique(new ParamEvent(ParamEvent::ExponentialRampToValue, |
161 nullptr, initialValue, callTime); | 188 value, time, initialValue, callTime)); |
162 } | 189 } |
163 | 190 |
164 AudioParamTimeline::ParamEvent | 191 std::unique_ptr<AudioParamTimeline::ParamEvent> |
165 AudioParamTimeline::ParamEvent::createSetTargetEvent(float value, | 192 AudioParamTimeline::ParamEvent::createSetTargetEvent(float value, |
166 double time, | 193 double time, |
167 double timeConstant) { | 194 double timeConstant) { |
168 // The time line code does not expect a timeConstant of 0. (IT | 195 // The time line code does not expect a timeConstant of 0. (IT |
169 // returns NaN or Infinity due to division by zero. The caller | 196 // returns NaN or Infinity due to division by zero. The caller |
170 // should have converted this to a SetValueEvent. | 197 // should have converted this to a SetValueEvent. |
171 DCHECK_NE(timeConstant, 0); | 198 DCHECK_NE(timeConstant, 0); |
172 return ParamEvent(ParamEvent::SetTarget, value, time, timeConstant, 0, | 199 return WTF::wrapUnique( |
173 nullptr); | 200 new ParamEvent(ParamEvent::SetTarget, value, time, timeConstant)); |
174 } | 201 } |
175 | 202 |
176 AudioParamTimeline::ParamEvent | 203 std::unique_ptr<AudioParamTimeline::ParamEvent> |
177 AudioParamTimeline::ParamEvent::createSetValueCurveEvent( | 204 AudioParamTimeline::ParamEvent::createSetValueCurveEvent( |
178 const DOMFloat32Array* curve, | 205 const DOMFloat32Array* curve, |
179 double time, | 206 double time, |
180 double duration) { | 207 double duration) { |
181 return ParamEvent(ParamEvent::SetValueCurve, 0, time, 0, duration, curve); | 208 double curvePoints = (curve->length() - 1) / duration; |
| 209 float endValue = curve->data()[curve->length() - 1]; |
| 210 |
| 211 return WTF::wrapUnique(new ParamEvent( |
| 212 ParamEvent::SetValueCurve, time, duration, curve, curvePoints, endValue)); |
| 213 } |
| 214 |
| 215 std::unique_ptr<AudioParamTimeline::ParamEvent> |
| 216 AudioParamTimeline::ParamEvent::createCancelValuesEvent( |
| 217 double time, |
| 218 std::unique_ptr<ParamEvent> savedEvent) { |
| 219 if (savedEvent) { |
| 220 // The savedEvent can only have certain event types. Verify that. |
| 221 ParamEvent::Type savedType = savedEvent->getType(); |
| 222 |
| 223 DCHECK_NE(savedType, ParamEvent::LastType); |
| 224 DCHECK(savedType == ParamEvent::LinearRampToValue || |
| 225 savedType == ParamEvent::ExponentialRampToValue || |
| 226 savedType == ParamEvent::SetValueCurve); |
| 227 } |
| 228 |
| 229 return WTF::wrapUnique( |
| 230 new ParamEvent(ParamEvent::CancelValues, time, std::move(savedEvent))); |
| 231 } |
| 232 |
| 233 std::unique_ptr<AudioParamTimeline::ParamEvent> |
| 234 AudioParamTimeline::ParamEvent::createGeneralEvent( |
| 235 Type type, |
| 236 float value, |
| 237 double time, |
| 238 float initialValue, |
| 239 double callTime, |
| 240 double timeConstant, |
| 241 double duration, |
| 242 Vector<float>& curve, |
| 243 double curvePointsPerSecond, |
| 244 float curveEndValue, |
| 245 std::unique_ptr<ParamEvent> savedEvent) { |
| 246 return WTF::wrapUnique(new ParamEvent( |
| 247 type, value, time, initialValue, callTime, timeConstant, duration, curve, |
| 248 curvePointsPerSecond, curveEndValue, std::move(savedEvent))); |
| 249 } |
| 250 |
| 251 AudioParamTimeline::ParamEvent* AudioParamTimeline::ParamEvent::savedEvent() |
| 252 const { |
| 253 DCHECK_EQ(getType(), ParamEvent::CancelValues); |
| 254 return m_savedEvent.get(); |
| 255 } |
| 256 |
| 257 bool AudioParamTimeline::ParamEvent::hasDefaultCancelledValue() const { |
| 258 DCHECK_EQ(getType(), ParamEvent::CancelValues); |
| 259 return m_hasDefaultCancelledValue; |
| 260 } |
| 261 |
| 262 void AudioParamTimeline::ParamEvent::setCancelledValue(float value) { |
| 263 DCHECK_EQ(getType(), ParamEvent::CancelValues); |
| 264 m_value = value; |
| 265 m_hasDefaultCancelledValue = true; |
| 266 } |
| 267 |
| 268 // General event |
| 269 AudioParamTimeline::ParamEvent::ParamEvent( |
| 270 ParamEvent::Type type, |
| 271 float value, |
| 272 double time, |
| 273 float initialValue, |
| 274 double callTime, |
| 275 double timeConstant, |
| 276 double duration, |
| 277 Vector<float>& curve, |
| 278 double curvePointsPerSecond, |
| 279 float curveEndValue, |
| 280 std::unique_ptr<ParamEvent> savedEvent) |
| 281 : m_type(type), |
| 282 m_value(value), |
| 283 m_time(time), |
| 284 m_initialValue(initialValue), |
| 285 m_callTime(callTime), |
| 286 m_timeConstant(timeConstant), |
| 287 m_duration(duration), |
| 288 m_curvePointsPerSecond(curvePointsPerSecond), |
| 289 m_curveEndValue(curveEndValue), |
| 290 m_savedEvent(std::move(savedEvent)), |
| 291 m_needsTimeClampCheck(true), |
| 292 m_hasDefaultCancelledValue(false) { |
| 293 m_curve = curve; |
| 294 } |
| 295 |
| 296 // Create simplest event needing just a value and time, like setValueAtTime |
| 297 AudioParamTimeline::ParamEvent::ParamEvent(ParamEvent::Type type, |
| 298 float value, |
| 299 double time) |
| 300 : m_type(type), |
| 301 m_value(value), |
| 302 m_time(time), |
| 303 m_initialValue(0), |
| 304 m_callTime(0), |
| 305 m_timeConstant(0), |
| 306 m_duration(0), |
| 307 m_curvePointsPerSecond(0), |
| 308 m_curveEndValue(0), |
| 309 m_savedEvent(nullptr), |
| 310 m_needsTimeClampCheck(true), |
| 311 m_hasDefaultCancelledValue(false) { |
| 312 DCHECK_EQ(type, ParamEvent::SetValue); |
| 313 } |
| 314 |
| 315 // Create a linear or exponential ramp that requires an initial value and |
| 316 // time in case |
| 317 // there is no actual event that preceeds this event. |
| 318 AudioParamTimeline::ParamEvent::ParamEvent(ParamEvent::Type type, |
| 319 float value, |
| 320 double time, |
| 321 float initialValue, |
| 322 double callTime) |
| 323 : m_type(type), |
| 324 m_value(value), |
| 325 m_time(time), |
| 326 m_initialValue(initialValue), |
| 327 m_callTime(callTime), |
| 328 m_timeConstant(0), |
| 329 m_duration(0), |
| 330 m_curvePointsPerSecond(0), |
| 331 m_curveEndValue(0), |
| 332 m_savedEvent(nullptr), |
| 333 m_needsTimeClampCheck(true), |
| 334 m_hasDefaultCancelledValue(false) { |
| 335 DCHECK(type == ParamEvent::LinearRampToValue || |
| 336 type == ParamEvent::ExponentialRampToValue); |
| 337 } |
| 338 |
| 339 // Create an event needing a time constant (setTargetAtTime) |
| 340 AudioParamTimeline::ParamEvent::ParamEvent(ParamEvent::Type type, |
| 341 float value, |
| 342 double time, |
| 343 double timeConstant) |
| 344 : m_type(type), |
| 345 m_value(value), |
| 346 m_time(time), |
| 347 m_initialValue(0), |
| 348 m_callTime(0), |
| 349 m_timeConstant(timeConstant), |
| 350 m_duration(0), |
| 351 m_curvePointsPerSecond(0), |
| 352 m_curveEndValue(0), |
| 353 m_savedEvent(nullptr), |
| 354 m_needsTimeClampCheck(true), |
| 355 m_hasDefaultCancelledValue(false) { |
| 356 DCHECK_EQ(type, ParamEvent::SetTarget); |
| 357 } |
| 358 |
| 359 // Create a setValueCurve event |
| 360 AudioParamTimeline::ParamEvent::ParamEvent(ParamEvent::Type type, |
| 361 double time, |
| 362 double duration, |
| 363 const DOMFloat32Array* curve, |
| 364 double curvePointsPerSecond, |
| 365 float curveEndValue) |
| 366 : m_type(type), |
| 367 m_value(0), |
| 368 m_time(time), |
| 369 m_initialValue(0), |
| 370 m_callTime(0), |
| 371 m_timeConstant(0), |
| 372 m_duration(duration), |
| 373 m_curvePointsPerSecond(curvePointsPerSecond), |
| 374 m_curveEndValue(curveEndValue), |
| 375 m_savedEvent(nullptr), |
| 376 m_needsTimeClampCheck(true), |
| 377 m_hasDefaultCancelledValue(false) { |
| 378 DCHECK_EQ(type, ParamEvent::SetValueCurve); |
| 379 if (curve) { |
| 380 unsigned curveLength = curve->length(); |
| 381 m_curve.resize(curve->length()); |
| 382 memcpy(m_curve.data(), curve->data(), curveLength * sizeof(float)); |
| 383 } |
| 384 } |
| 385 |
| 386 // Create CancelValues event |
| 387 AudioParamTimeline::ParamEvent::ParamEvent( |
| 388 ParamEvent::Type type, |
| 389 double time, |
| 390 std::unique_ptr<ParamEvent> savedEvent) |
| 391 : m_type(type), |
| 392 m_value(0), |
| 393 m_time(time), |
| 394 m_initialValue(0), |
| 395 m_callTime(0), |
| 396 m_timeConstant(0), |
| 397 m_duration(0), |
| 398 m_curvePointsPerSecond(0), |
| 399 m_curveEndValue(0), |
| 400 m_savedEvent(std::move(savedEvent)), |
| 401 m_needsTimeClampCheck(true), |
| 402 m_hasDefaultCancelledValue(false) { |
| 403 DCHECK_EQ(type, ParamEvent::CancelValues); |
182 } | 404 } |
183 | 405 |
184 void AudioParamTimeline::setValueAtTime(float value, | 406 void AudioParamTimeline::setValueAtTime(float value, |
185 double time, | 407 double time, |
186 ExceptionState& exceptionState) { | 408 ExceptionState& exceptionState) { |
187 DCHECK(isMainThread()); | 409 DCHECK(isMainThread()); |
188 | 410 |
189 if (!isNonNegativeAudioParamTime(time, exceptionState)) | 411 if (!isNonNegativeAudioParamTime(time, exceptionState)) |
190 return; | 412 return; |
191 | 413 |
| 414 MutexLocker locker(m_eventsLock); |
192 insertEvent(ParamEvent::createSetValueEvent(value, time), exceptionState); | 415 insertEvent(ParamEvent::createSetValueEvent(value, time), exceptionState); |
193 } | 416 } |
194 | 417 |
195 void AudioParamTimeline::linearRampToValueAtTime( | 418 void AudioParamTimeline::linearRampToValueAtTime( |
196 float value, | 419 float value, |
197 double time, | 420 double time, |
198 float initialValue, | 421 float initialValue, |
199 double callTime, | 422 double callTime, |
200 ExceptionState& exceptionState) { | 423 ExceptionState& exceptionState) { |
201 DCHECK(isMainThread()); | 424 DCHECK(isMainThread()); |
202 | 425 |
203 if (!isNonNegativeAudioParamTime(time, exceptionState)) | 426 if (!isNonNegativeAudioParamTime(time, exceptionState)) |
204 return; | 427 return; |
205 | 428 |
| 429 MutexLocker locker(m_eventsLock); |
206 insertEvent( | 430 insertEvent( |
207 ParamEvent::createLinearRampEvent(value, time, initialValue, callTime), | 431 ParamEvent::createLinearRampEvent(value, time, initialValue, callTime), |
208 exceptionState); | 432 exceptionState); |
209 } | 433 } |
210 | 434 |
211 void AudioParamTimeline::exponentialRampToValueAtTime( | 435 void AudioParamTimeline::exponentialRampToValueAtTime( |
212 float value, | 436 float value, |
213 double time, | 437 double time, |
214 float initialValue, | 438 float initialValue, |
215 double callTime, | 439 double callTime, |
216 ExceptionState& exceptionState) { | 440 ExceptionState& exceptionState) { |
217 DCHECK(isMainThread()); | 441 DCHECK(isMainThread()); |
218 | 442 |
219 if (!isNonNegativeAudioParamTime(time, exceptionState)) | 443 if (!isNonNegativeAudioParamTime(time, exceptionState)) |
220 return; | 444 return; |
221 | 445 |
222 if (!value) { | 446 if (!value) { |
223 exceptionState.throwDOMException( | 447 exceptionState.throwDOMException( |
224 InvalidAccessError, | 448 InvalidAccessError, |
225 "The float target value provided (" + String::number(value) + | 449 "The float target value provided (" + String::number(value) + |
226 ") should not be in the range (" + | 450 ") should not be in the range (" + |
227 String::number(-std::numeric_limits<float>::denorm_min()) + ", " + | 451 String::number(-std::numeric_limits<float>::denorm_min()) + ", " + |
228 String::number(std::numeric_limits<float>::denorm_min()) + ")."); | 452 String::number(std::numeric_limits<float>::denorm_min()) + ")."); |
229 return; | 453 return; |
230 } | 454 } |
231 | 455 |
| 456 MutexLocker locker(m_eventsLock); |
232 insertEvent(ParamEvent::createExponentialRampEvent(value, time, initialValue, | 457 insertEvent(ParamEvent::createExponentialRampEvent(value, time, initialValue, |
233 callTime), | 458 callTime), |
234 exceptionState); | 459 exceptionState); |
235 } | 460 } |
236 | 461 |
237 void AudioParamTimeline::setTargetAtTime(float target, | 462 void AudioParamTimeline::setTargetAtTime(float target, |
238 double time, | 463 double time, |
239 double timeConstant, | 464 double timeConstant, |
240 ExceptionState& exceptionState) { | 465 ExceptionState& exceptionState) { |
241 DCHECK(isMainThread()); | 466 DCHECK(isMainThread()); |
242 | 467 |
243 if (!isNonNegativeAudioParamTime(time, exceptionState) || | 468 if (!isNonNegativeAudioParamTime(time, exceptionState) || |
244 !isNonNegativeAudioParamTime(timeConstant, exceptionState, | 469 !isNonNegativeAudioParamTime(timeConstant, exceptionState, |
245 "Time constant")) | 470 "Time constant")) |
246 return; | 471 return; |
247 | 472 |
| 473 MutexLocker locker(m_eventsLock); |
| 474 |
248 // If timeConstant = 0, we instantly jump to the target value, so | 475 // If timeConstant = 0, we instantly jump to the target value, so |
249 // insert a SetValueEvent instead of SetTargetEvent. | 476 // insert a SetValueEvent instead of SetTargetEvent. |
250 if (timeConstant == 0) { | 477 if (timeConstant == 0) { |
251 insertEvent(ParamEvent::createSetValueEvent(target, time), exceptionState); | 478 insertEvent(ParamEvent::createSetValueEvent(target, time), exceptionState); |
252 } else { | 479 } else { |
253 insertEvent(ParamEvent::createSetTargetEvent(target, time, timeConstant), | 480 insertEvent(ParamEvent::createSetTargetEvent(target, time, timeConstant), |
254 exceptionState); | 481 exceptionState); |
255 } | 482 } |
256 } | 483 } |
257 | 484 |
258 void AudioParamTimeline::setValueCurveAtTime(DOMFloat32Array* curve, | 485 void AudioParamTimeline::setValueCurveAtTime(DOMFloat32Array* curve, |
259 double time, | 486 double time, |
260 double duration, | 487 double duration, |
261 ExceptionState& exceptionState) { | 488 ExceptionState& exceptionState) { |
262 DCHECK(isMainThread()); | 489 DCHECK(isMainThread()); |
263 DCHECK(curve); | 490 DCHECK(curve); |
264 | 491 |
265 if (!isNonNegativeAudioParamTime(time, exceptionState) || | 492 if (!isNonNegativeAudioParamTime(time, exceptionState) || |
266 !isPositiveAudioParamTime(duration, exceptionState, "Duration")) | 493 !isPositiveAudioParamTime(duration, exceptionState, "Duration")) |
267 return; | 494 return; |
268 | 495 |
269 if (curve->length() < 2) { | 496 if (curve->length() < 2) { |
270 exceptionState.throwDOMException( | 497 exceptionState.throwDOMException( |
271 InvalidStateError, ExceptionMessages::indexExceedsMinimumBound( | 498 InvalidStateError, ExceptionMessages::indexExceedsMinimumBound( |
272 "curve length", curve->length(), 2U)); | 499 "curve length", curve->length(), 2U)); |
273 return; | 500 return; |
274 } | 501 } |
275 | 502 |
| 503 MutexLocker locker(m_eventsLock); |
276 insertEvent(ParamEvent::createSetValueCurveEvent(curve, time, duration), | 504 insertEvent(ParamEvent::createSetValueCurveEvent(curve, time, duration), |
277 exceptionState); | 505 exceptionState); |
278 | 506 |
279 // Insert a setValueAtTime event too to establish an event so that all | 507 // Insert a setValueAtTime event too to establish an event so that all |
280 // following events will process from the end of the curve instead of the | 508 // following events will process from the end of the curve instead of the |
281 // beginning. | 509 // beginning. |
282 insertEvent(ParamEvent::createSetValueEvent( | 510 insertEvent(ParamEvent::createSetValueEvent( |
283 curve->data()[curve->length() - 1], time + duration), | 511 curve->data()[curve->length() - 1], time + duration), |
284 exceptionState); | 512 exceptionState); |
285 } | 513 } |
286 | 514 |
287 void AudioParamTimeline::insertEvent(const ParamEvent& event, | 515 void AudioParamTimeline::insertEvent(std::unique_ptr<ParamEvent> event, |
288 ExceptionState& exceptionState) { | 516 ExceptionState& exceptionState) { |
289 DCHECK(isMainThread()); | 517 DCHECK(isMainThread()); |
290 | 518 |
291 // Sanity check the event. Be super careful we're not getting infected with | 519 // Sanity check the event. Be super careful we're not getting infected with |
292 // NaN or Inf. These should have been handled by the caller. | 520 // NaN or Inf. These should have been handled by the caller. |
293 bool isValid = event.getType() < ParamEvent::LastType && | 521 bool isValid = event->getType() < ParamEvent::LastType && |
294 std::isfinite(event.value()) && std::isfinite(event.time()) && | 522 std::isfinite(event->value()) && |
295 std::isfinite(event.timeConstant()) && | 523 std::isfinite(event->time()) && |
296 std::isfinite(event.duration()) && event.duration() >= 0; | 524 std::isfinite(event->timeConstant()) && |
| 525 std::isfinite(event->duration()) && event->duration() >= 0; |
297 | 526 |
298 DCHECK(isValid); | 527 DCHECK(isValid); |
299 if (!isValid) | 528 if (!isValid) |
300 return; | 529 return; |
301 | 530 |
302 MutexLocker locker(m_eventsLock); | |
303 | |
304 unsigned i = 0; | 531 unsigned i = 0; |
305 double insertTime = event.time(); | 532 double insertTime = event->time(); |
306 | 533 |
307 if (!m_events.size() && | 534 if (!m_events.size() && |
308 (event.getType() == ParamEvent::LinearRampToValue || | 535 (event->getType() == ParamEvent::LinearRampToValue || |
309 event.getType() == ParamEvent::ExponentialRampToValue)) { | 536 event->getType() == ParamEvent::ExponentialRampToValue)) { |
310 // There are no events preceding these ramps. Insert a new setValueAtTime | 537 // There are no events preceding these ramps. Insert a new setValueAtTime |
311 // event to set the starting point for these events. | 538 // event to set the starting point for these events. |
312 m_events.insert(0, AudioParamTimeline::ParamEvent::createSetValueEvent( | 539 m_events.insert(0, AudioParamTimeline::ParamEvent::createSetValueEvent( |
313 event.initialValue(), event.callTime())); | 540 event->initialValue(), event->callTime())); |
314 } | 541 } |
315 | 542 |
316 for (i = 0; i < m_events.size(); ++i) { | 543 for (i = 0; i < m_events.size(); ++i) { |
317 if (event.getType() == ParamEvent::SetValueCurve) { | 544 if (event->getType() == ParamEvent::SetValueCurve) { |
318 // If this event is a SetValueCurve, make sure it doesn't overlap any | 545 // If this event is a SetValueCurve, make sure it doesn't overlap any |
319 // existing event. It's ok if the SetValueCurve starts at the same time as | 546 // existing event. It's ok if the SetValueCurve starts at the same time as |
320 // the end of some other duration. | 547 // the end of some other duration. |
321 double endTime = event.time() + event.duration(); | 548 double endTime = event->time() + event->duration(); |
322 if (m_events[i].time() > event.time() && m_events[i].time() < endTime) { | 549 if (m_events[i]->time() > event->time() && |
| 550 m_events[i]->time() < endTime) { |
323 exceptionState.throwDOMException( | 551 exceptionState.throwDOMException( |
324 NotSupportedError, | 552 NotSupportedError, |
325 eventToString(event) + " overlaps " + eventToString(m_events[i])); | 553 eventToString(*event) + " overlaps " + eventToString(*m_events[i])); |
326 return; | 554 return; |
327 } | 555 } |
328 } else { | 556 } else { |
329 // Otherwise, make sure this event doesn't overlap any existing | 557 // Otherwise, make sure this event doesn't overlap any existing |
330 // SetValueCurve event. | 558 // SetValueCurve event. |
331 if (m_events[i].getType() == ParamEvent::SetValueCurve) { | 559 if (m_events[i]->getType() == ParamEvent::SetValueCurve) { |
332 double endTime = m_events[i].time() + m_events[i].duration(); | 560 double endTime = m_events[i]->time() + m_events[i]->duration(); |
333 if (event.time() >= m_events[i].time() && event.time() < endTime) { | 561 if (event->time() >= m_events[i]->time() && event->time() < endTime) { |
334 exceptionState.throwDOMException( | 562 exceptionState.throwDOMException( |
335 NotSupportedError, | 563 NotSupportedError, eventToString(*event) + " overlaps " + |
336 eventToString(event) + " overlaps " + eventToString(m_events[i])); | 564 eventToString(*m_events[i])); |
337 return; | 565 return; |
338 } | 566 } |
339 } | 567 } |
340 } | 568 } |
341 | 569 |
342 // Overwrite same event type and time. | 570 // Overwrite same event type and time. |
343 if (m_events[i].time() == insertTime && | 571 if (m_events[i]->time() == insertTime && |
344 m_events[i].getType() == event.getType()) { | 572 m_events[i]->getType() == event->getType()) { |
345 m_events[i] = event; | 573 m_events[i] = std::move(event); |
346 return; | 574 return; |
347 } | 575 } |
348 | 576 |
349 if (m_events[i].time() > insertTime) | 577 if (m_events[i]->time() > insertTime) |
350 break; | 578 break; |
351 } | 579 } |
352 | 580 |
353 m_events.insert(i, event); | 581 m_events.insert(i, std::move(event)); |
354 } | 582 } |
355 | 583 |
356 bool AudioParamTimeline::hasValues() const { | 584 bool AudioParamTimeline::hasValues() const { |
357 MutexTryLocker tryLocker(m_eventsLock); | 585 MutexTryLocker tryLocker(m_eventsLock); |
358 | 586 |
359 if (tryLocker.locked()) | 587 if (tryLocker.locked()) |
360 return m_events.size(); | 588 return m_events.size(); |
361 | 589 |
362 // Can't get the lock so that means the main thread is trying to insert an | 590 // Can't get the lock so that means the main thread is trying to insert an |
363 // event. Just return true then. If the main thread releases the lock before | 591 // event. Just return true then. If the main thread releases the lock before |
(...skipping 12 matching lines...) Expand all Loading... |
376 } | 604 } |
377 | 605 |
378 void AudioParamTimeline::cancelScheduledValues(double startTime, | 606 void AudioParamTimeline::cancelScheduledValues(double startTime, |
379 ExceptionState& exceptionState) { | 607 ExceptionState& exceptionState) { |
380 DCHECK(isMainThread()); | 608 DCHECK(isMainThread()); |
381 | 609 |
382 MutexLocker locker(m_eventsLock); | 610 MutexLocker locker(m_eventsLock); |
383 | 611 |
384 // Remove all events starting at startTime. | 612 // Remove all events starting at startTime. |
385 for (unsigned i = 0; i < m_events.size(); ++i) { | 613 for (unsigned i = 0; i < m_events.size(); ++i) { |
386 if (m_events[i].time() >= startTime) { | 614 if (m_events[i]->time() >= startTime) { |
387 m_events.remove(i, m_events.size() - i); | 615 m_events.remove(i, m_events.size() - i); |
388 break; | 616 break; |
389 } | 617 } |
390 } | 618 } |
391 } | 619 } |
392 | 620 |
| 621 void AudioParamTimeline::cancelValuesAndHoldAtTime( |
| 622 double cancelTime, |
| 623 ExceptionState& exceptionState) { |
| 624 DCHECK(isMainThread()); |
| 625 |
| 626 if (!isNonNegativeAudioParamTime(cancelTime, exceptionState)) |
| 627 return; |
| 628 |
| 629 MutexLocker locker(m_eventsLock); |
| 630 |
| 631 unsigned i; |
| 632 // Find the first event at or just past cancelTime. |
| 633 for (i = 0; i < m_events.size(); ++i) { |
| 634 if (m_events[i]->time() > cancelTime) { |
| 635 break; |
| 636 } |
| 637 } |
| 638 |
| 639 // The event that is being cancelled. This is the event just past |
| 640 // cancelTime, if any. |
| 641 unsigned cancelledEventIndex = i; |
| 642 |
| 643 // If the event just before cancelTime is a SetTarget or SetValueCurve |
| 644 // event, we need to handle that event specially instead of the event after. |
| 645 if (i > 0 && ((m_events[i - 1]->getType() == ParamEvent::SetTarget) || |
| 646 (m_events[i - 1]->getType() == ParamEvent::SetValueCurve))) { |
| 647 cancelledEventIndex = i - 1; |
| 648 } else if (i >= m_events.size()) { |
| 649 // If there were no events occurring after |cancelTime| (and the |
| 650 // previous event is not SetTarget or SetValueCurve, we're done. |
| 651 return; |
| 652 } |
| 653 |
| 654 // cancelledEvent is the event that is being cancelled. |
| 655 ParamEvent* cancelledEvent = m_events[cancelledEventIndex].get(); |
| 656 ParamEvent::Type eventType = cancelledEvent->getType(); |
| 657 |
| 658 // New event to be inserted, if any, and a SetValueEvent if needed. |
| 659 std::unique_ptr<ParamEvent> newEvent = nullptr; |
| 660 std::unique_ptr<ParamEvent> newSetValueEvent = nullptr; |
| 661 |
| 662 switch (eventType) { |
| 663 case ParamEvent::LinearRampToValue: |
| 664 case ParamEvent::ExponentialRampToValue: { |
| 665 // For these events we need to remember the parameters of the event |
| 666 // for a CancelValues event so that we can properly cancel the event |
| 667 // and hold the value. |
| 668 std::unique_ptr<ParamEvent> savedEvent = ParamEvent::createGeneralEvent( |
| 669 eventType, cancelledEvent->value(), cancelledEvent->time(), |
| 670 cancelledEvent->initialValue(), cancelledEvent->callTime(), |
| 671 cancelledEvent->timeConstant(), cancelledEvent->duration(), |
| 672 cancelledEvent->curve(), cancelledEvent->curvePointsPerSecond(), |
| 673 cancelledEvent->curveEndValue(), nullptr); |
| 674 |
| 675 newEvent = ParamEvent::createCancelValuesEvent(cancelTime, |
| 676 std::move(savedEvent)); |
| 677 } break; |
| 678 case ParamEvent::SetTarget: { |
| 679 // Don't want to remove the SetTarget event, so bump the index. But |
| 680 // we do want to insert a cancelEvent so that we stop this |
| 681 // automation and hold the value when we get there. |
| 682 ++cancelledEventIndex; |
| 683 |
| 684 newEvent = ParamEvent::createCancelValuesEvent(cancelTime, nullptr); |
| 685 } break; |
| 686 case ParamEvent::SetValueCurve: { |
| 687 double newDuration = cancelTime - cancelledEvent->time(); |
| 688 |
| 689 if (cancelTime > cancelledEvent->time() + cancelledEvent->duration()) { |
| 690 // If the cancellation time is past the end of the curve, |
| 691 // there's nothing to do except remove the following events. |
| 692 ++cancelledEventIndex; |
| 693 } else { |
| 694 // Cancellation time is in the middle of the curve. Therefore, |
| 695 // create a new SetValueCurve event with the appropriate new |
| 696 // parameters to cancel this event properly. Since it's illegal |
| 697 // to insert any event within a SetValueCurve event, we can |
| 698 // compute the new end value now instead of doing when running |
| 699 // the timeline. |
| 700 float endValue = valueCurveAtTime( |
| 701 cancelTime, cancelledEvent->time(), cancelledEvent->duration(), |
| 702 cancelledEvent->curve().data(), cancelledEvent->curve().size()); |
| 703 |
| 704 // Replace the existing SetValueCurve with this new one that is |
| 705 // identical except for the duration. |
| 706 newEvent = ParamEvent::createGeneralEvent( |
| 707 eventType, cancelledEvent->value(), cancelledEvent->time(), |
| 708 cancelledEvent->initialValue(), cancelledEvent->callTime(), |
| 709 cancelledEvent->timeConstant(), newDuration, |
| 710 cancelledEvent->curve(), cancelledEvent->curvePointsPerSecond(), |
| 711 endValue, nullptr); |
| 712 |
| 713 newSetValueEvent = ParamEvent::createSetValueEvent( |
| 714 endValue, cancelledEvent->time() + newDuration); |
| 715 } |
| 716 } break; |
| 717 case ParamEvent::SetValue: |
| 718 case ParamEvent::CancelValues: |
| 719 // Nothing needs to be done for a SetValue or CancelValues event. |
| 720 break; |
| 721 case ParamEvent::LastType: |
| 722 NOTREACHED(); |
| 723 break; |
| 724 } |
| 725 |
| 726 // Now remove all the following events from the timeline. |
| 727 if (cancelledEventIndex < m_events.size()) |
| 728 m_events.remove(cancelledEventIndex, m_events.size() - cancelledEventIndex); |
| 729 |
| 730 // Insert the new event, if any. |
| 731 if (newEvent) { |
| 732 insertEvent(std::move(newEvent), exceptionState); |
| 733 if (newSetValueEvent) |
| 734 insertEvent(std::move(newSetValueEvent), exceptionState); |
| 735 } |
| 736 } |
| 737 |
393 float AudioParamTimeline::valueForContextTime( | 738 float AudioParamTimeline::valueForContextTime( |
394 AudioDestinationHandler& audioDestination, | 739 AudioDestinationHandler& audioDestination, |
395 float defaultValue, | 740 float defaultValue, |
396 bool& hasValue, | 741 bool& hasValue, |
397 float minValue, | 742 float minValue, |
398 float maxValue) { | 743 float maxValue) { |
399 { | 744 { |
400 MutexTryLocker tryLocker(m_eventsLock); | 745 MutexTryLocker tryLocker(m_eventsLock); |
401 if (!tryLocker.locked() || !m_events.size() || | 746 if (!tryLocker.locked() || !m_events.size() || |
402 audioDestination.currentTime() < m_events[0].time()) { | 747 audioDestination.currentTime() < m_events[0]->time()) { |
403 hasValue = false; | 748 hasValue = false; |
404 return defaultValue; | 749 return defaultValue; |
405 } | 750 } |
406 } | 751 } |
407 | 752 |
408 // Ask for just a single value. | 753 // Ask for just a single value. |
409 float value; | 754 float value; |
410 double sampleRate = audioDestination.sampleRate(); | 755 double sampleRate = audioDestination.sampleRate(); |
411 size_t startFrame = audioDestination.currentSampleFrame(); | 756 size_t startFrame = audioDestination.currentSampleFrame(); |
412 // One parameter change per render quantum. | 757 // One parameter change per render quantum. |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
455 unsigned numberOfValues, | 800 unsigned numberOfValues, |
456 double sampleRate, | 801 double sampleRate, |
457 double controlRate) { | 802 double controlRate) { |
458 DCHECK(values); | 803 DCHECK(values); |
459 DCHECK_GE(numberOfValues, 1u); | 804 DCHECK_GE(numberOfValues, 1u); |
460 if (!values || !(numberOfValues >= 1)) | 805 if (!values || !(numberOfValues >= 1)) |
461 return defaultValue; | 806 return defaultValue; |
462 | 807 |
463 // Return default value if there are no events matching the desired time | 808 // Return default value if there are no events matching the desired time |
464 // range. | 809 // range. |
465 if (!m_events.size() || (endFrame / sampleRate <= m_events[0].time())) { | 810 if (!m_events.size() || (endFrame / sampleRate <= m_events[0]->time())) { |
466 for (unsigned i = 0; i < numberOfValues; ++i) | 811 for (unsigned i = 0; i < numberOfValues; ++i) |
467 values[i] = defaultValue; | 812 values[i] = defaultValue; |
468 return defaultValue; | 813 return defaultValue; |
469 } | 814 } |
470 | 815 |
471 int numberOfEvents = m_events.size(); | 816 int numberOfEvents = m_events.size(); |
472 | 817 |
473 if (numberOfEvents > 0) { | 818 if (numberOfEvents > 0) { |
474 bool clampedSomeEventTime = false; | 819 bool clampedSomeEventTime = false; |
475 double currentTime = startFrame / sampleRate; | 820 double currentTime = startFrame / sampleRate; |
476 | 821 |
477 // Look at all the events in the timeline and check to see if any needs | 822 // Look at all the events in the timeline and check to see if any needs |
478 // to clamp the start time to the current time. | 823 // to clamp the start time to the current time. |
479 for (int k = 0; k < numberOfEvents; ++k) { | 824 for (int k = 0; k < numberOfEvents; ++k) { |
480 ParamEvent& event = m_events[k]; | 825 ParamEvent* event = m_events[k].get(); |
481 | 826 |
482 // We're examining the event for the first time and the event time is | 827 // We're examining the event for the first time and the event time is |
483 // in the past so clamp the event time to the current time (start of | 828 // in the past so clamp the event time to the current time (start of |
484 // the rendering quantum). | 829 // the rendering quantum). |
485 if (event.needsTimeClampCheck()) { | 830 if (event->needsTimeClampCheck()) { |
486 if (event.time() < currentTime) { | 831 if (event->time() < currentTime) { |
487 event.setTime(currentTime); | 832 event->setTime(currentTime); |
488 clampedSomeEventTime = true; | 833 clampedSomeEventTime = true; |
489 } | 834 } |
490 | 835 |
491 // In all cases, we can clear the flag because the event is either | 836 // In all cases, we can clear the flag because the event is either |
492 // in the future, or we've already checked it (just now). | 837 // in the future, or we've already checked it (just now). |
493 event.clearTimeClampCheck(); | 838 event->clearTimeClampCheck(); |
494 } | 839 } |
495 } | 840 } |
496 | 841 |
497 if (clampedSomeEventTime) { | 842 if (clampedSomeEventTime) { |
498 // If we clamped some event time to current time, we need to | 843 // If we clamped some event time to current time, we need to |
499 // sort the event list in time order again, but it must be | 844 // sort the event list in time order again, but it must be |
500 // stable! | 845 // stable! |
501 std::stable_sort(m_events.begin(), m_events.end(), | 846 std::stable_sort(m_events.begin(), m_events.end(), |
502 ParamEvent::eventPreceeds); | 847 ParamEvent::eventPreceeds); |
503 } | 848 } |
504 | 849 |
505 // Optimize the case where the last event is in the past. | 850 // Optimize the case where the last event is in the past. |
506 ParamEvent& lastEvent = m_events[m_events.size() - 1]; | 851 ParamEvent* lastEvent = m_events[m_events.size() - 1].get(); |
507 ParamEvent::Type lastEventType = lastEvent.getType(); | 852 ParamEvent::Type lastEventType = lastEvent->getType(); |
508 double lastEventTime = lastEvent.time(); | 853 double lastEventTime = lastEvent->time(); |
509 | 854 |
510 // If the last event is in the past and the event has ended, then we can | 855 // If the last event is in the past and the event has ended, then we can |
511 // just propagate the same value. Except for SetTarget which lasts | 856 // just propagate the same value. Except for SetTarget which lasts |
512 // "forever". SetValueCurve also has an explicit SetValue at the end of | 857 // "forever". SetValueCurve also has an explicit SetValue at the end of |
513 // the curve, so we don't need to worry that SetValueCurve time is a | 858 // the curve, so we don't need to worry that SetValueCurve time is a |
514 // start time, not an end time. | 859 // start time, not an end time. |
515 if (lastEventTime < currentTime && lastEventType != ParamEvent::SetTarget) { | 860 if (lastEventTime < currentTime && lastEventType != ParamEvent::SetTarget) { |
516 // The event has finished, so just copy the default value out. | 861 // The event has finished, so just copy the default value out. |
517 // Since all events are now also in the past, we can just remove all | 862 // Since all events are now also in the past, we can just remove all |
518 // timeline events too because |defaultValue| has the expected | 863 // timeline events too because |defaultValue| has the expected |
519 // value. | 864 // value. |
520 for (unsigned i = 0; i < numberOfValues; ++i) | 865 for (unsigned i = 0; i < numberOfValues; ++i) |
521 values[i] = defaultValue; | 866 values[i] = defaultValue; |
522 m_smoothedValue = defaultValue; | 867 m_smoothedValue = defaultValue; |
523 m_events.clear(); | 868 m_events.clear(); |
524 return defaultValue; | 869 return defaultValue; |
525 } | 870 } |
526 } | 871 } |
527 | 872 |
528 // Maintain a running time (frame) and index for writing the values buffer. | 873 // Maintain a running time (frame) and index for writing the values buffer. |
529 size_t currentFrame = startFrame; | 874 size_t currentFrame = startFrame; |
530 unsigned writeIndex = 0; | 875 unsigned writeIndex = 0; |
531 | 876 |
532 // If first event is after startFrame then fill initial part of values buffer | 877 // If first event is after startFrame then fill initial part of values buffer |
533 // with defaultValue until we reach the first event time. | 878 // with defaultValue until we reach the first event time. |
534 double firstEventTime = m_events[0].time(); | 879 double firstEventTime = m_events[0]->time(); |
535 if (firstEventTime > startFrame / sampleRate) { | 880 if (firstEventTime > startFrame / sampleRate) { |
536 // |fillToFrame| is an exclusive upper bound, so use ceil() to compute the | 881 // |fillToFrame| is an exclusive upper bound, so use ceil() to compute the |
537 // bound from the firstEventTime. | 882 // bound from the firstEventTime. |
538 size_t fillToFrame = endFrame; | 883 size_t fillToFrame = endFrame; |
539 double firstEventFrame = ceil(firstEventTime * sampleRate); | 884 double firstEventFrame = ceil(firstEventTime * sampleRate); |
540 if (endFrame > firstEventFrame) | 885 if (endFrame > firstEventFrame) |
541 fillToFrame = static_cast<size_t>(firstEventFrame); | 886 fillToFrame = static_cast<size_t>(firstEventFrame); |
542 DCHECK_GE(fillToFrame, startFrame); | 887 DCHECK_GE(fillToFrame, startFrame); |
543 | 888 |
544 fillToFrame -= startFrame; | 889 fillToFrame -= startFrame; |
545 fillToFrame = std::min(fillToFrame, static_cast<size_t>(numberOfValues)); | 890 fillToFrame = std::min(fillToFrame, static_cast<size_t>(numberOfValues)); |
546 for (; writeIndex < fillToFrame; ++writeIndex) | 891 for (; writeIndex < fillToFrame; ++writeIndex) |
547 values[writeIndex] = defaultValue; | 892 values[writeIndex] = defaultValue; |
548 | 893 |
549 currentFrame += fillToFrame; | 894 currentFrame += fillToFrame; |
550 } | 895 } |
551 | 896 |
552 float value = defaultValue; | 897 float value = defaultValue; |
553 | 898 |
554 // Go through each event and render the value buffer where the times overlap, | 899 // Go through each event and render the value buffer where the times overlap, |
555 // stopping when we've rendered all the requested values. | 900 // stopping when we've rendered all the requested values. |
556 int lastSkippedEventIndex = 0; | 901 int lastSkippedEventIndex = 0; |
557 for (int i = 0; i < numberOfEvents && writeIndex < numberOfValues; ++i) { | 902 for (int i = 0; i < numberOfEvents && writeIndex < numberOfValues; ++i) { |
558 ParamEvent& event = m_events[i]; | 903 ParamEvent* event = m_events[i].get(); |
559 ParamEvent* nextEvent = i < numberOfEvents - 1 ? &(m_events[i + 1]) : 0; | 904 ParamEvent* nextEvent = i < numberOfEvents - 1 ? m_events[i + 1].get() : 0; |
560 | 905 |
561 // Wait until we get a more recent event. | 906 // Wait until we get a more recent event. |
562 // | 907 // |
563 // WARNING: due to round-off it might happen that nextEvent->time() is | 908 // WARNING: due to round-off it might happen that nextEvent->time() is |
564 // just larger than currentFrame/sampleRate. This means that we will end | 909 // just larger than currentFrame/sampleRate. This means that we will end |
565 // up running the |event| again. The code below had better be prepared | 910 // up running the |event| again. The code below had better be prepared |
566 // for this case! What should happen is the fillToFrame should be 0 so | 911 // for this case! What should happen is the fillToFrame should be 0 so |
567 // that while the event is actually run again, nothing actually gets | 912 // that while the event is actually run again, nothing actually gets |
568 // computed, and we move on to the next event. | 913 // computed, and we move on to the next event. |
569 // | 914 // |
570 // An example of this case is setValueCurveAtTime. The time at which | 915 // An example of this case is setValueCurveAtTime. The time at which |
571 // setValueCurveAtTime ends (and the setValueAtTime begins) might be | 916 // setValueCurveAtTime ends (and the setValueAtTime begins) might be |
572 // just past currentTime/sampleRate. Then setValueCurveAtTime will be | 917 // just past currentTime/sampleRate. Then setValueCurveAtTime will be |
573 // processed again before advancing to setValueAtTime. The number of | 918 // processed again before advancing to setValueAtTime. The number of |
574 // frames to be processed should be zero in this case. | 919 // frames to be processed should be zero in this case. |
575 if (nextEvent && nextEvent->time() < currentFrame / sampleRate) { | 920 if (nextEvent && nextEvent->time() < currentFrame / sampleRate) { |
576 // But if the current event is a SetValue event and the event time is | 921 // But if the current event is a SetValue event and the event time is |
577 // between currentFrame - 1 and curentFrame (in time). we don't want to | 922 // between currentFrame - 1 and curentFrame (in time). we don't want to |
578 // skip it. If we do skip it, the SetValue event is completely skipped | 923 // skip it. If we do skip it, the SetValue event is completely skipped |
579 // and not applied, which is wrong. Other events don't have this problem. | 924 // and not applied, which is wrong. Other events don't have this problem. |
580 // (Because currentFrame is unsigned, we do the time check in this funny, | 925 // (Because currentFrame is unsigned, we do the time check in this funny, |
581 // but equivalent way.) | 926 // but equivalent way.) |
582 double eventFrame = event.time() * sampleRate; | 927 double eventFrame = event->time() * sampleRate; |
583 | 928 |
584 // Condition is currentFrame - 1 < eventFrame <= currentFrame, but | 929 // Condition is currentFrame - 1 < eventFrame <= currentFrame, but |
585 // currentFrame is unsigned and could be 0, so use | 930 // currentFrame is unsigned and could be 0, so use |
586 // currentFrame < eventFrame + 1 instead. | 931 // currentFrame < eventFrame + 1 instead. |
587 if (!((event.getType() == ParamEvent::SetValue && | 932 if (!((event->getType() == ParamEvent::SetValue && |
588 (eventFrame <= currentFrame) && | 933 (eventFrame <= currentFrame) && |
589 (currentFrame < eventFrame + 1)))) { | 934 (currentFrame < eventFrame + 1)))) { |
590 // This is not the special SetValue event case, and nextEvent is | 935 // This is not the special SetValue event case, and nextEvent is |
591 // in the past. We can skip processing of this event since it's | 936 // in the past. We can skip processing of this event since it's |
592 // in past. We keep track of this event in lastSkippedEventIndex | 937 // in past. We keep track of this event in lastSkippedEventIndex |
593 // to note what events we've skipped. | 938 // to note what events we've skipped. |
594 lastSkippedEventIndex = i; | 939 lastSkippedEventIndex = i; |
595 continue; | 940 continue; |
596 } | 941 } |
597 } | 942 } |
598 | 943 |
599 // If there's no next event, set nextEventType to LastType to indicate that. | 944 // If there's no next event, set nextEventType to LastType to indicate that. |
600 ParamEvent::Type nextEventType = | 945 ParamEvent::Type nextEventType = |
601 nextEvent ? static_cast<ParamEvent::Type>(nextEvent->getType()) | 946 nextEvent ? static_cast<ParamEvent::Type>(nextEvent->getType()) |
602 : ParamEvent::LastType; | 947 : ParamEvent::LastType; |
603 | 948 |
604 // If the current event is SetTarget and the next event is a | 949 // If the current event is SetTarget and the next event is a |
605 // LinearRampToValue or ExponentialRampToValue, special handling is needed. | 950 // LinearRampToValue or ExponentialRampToValue, special handling is needed. |
606 // In this case, the linear and exponential ramp should start at wherever | 951 // In this case, the linear and exponential ramp should start at wherever |
607 // the SetTarget processing has reached. | 952 // the SetTarget processing has reached. |
608 if (event.getType() == ParamEvent::SetTarget && | 953 if (event->getType() == ParamEvent::SetTarget && |
609 (nextEventType == ParamEvent::LinearRampToValue || | 954 (nextEventType == ParamEvent::LinearRampToValue || |
610 nextEventType == ParamEvent::ExponentialRampToValue)) { | 955 nextEventType == ParamEvent::ExponentialRampToValue)) { |
611 // Replace the SetTarget with a SetValue to set the starting time and | 956 // Replace the SetTarget with a SetValue to set the starting time and |
612 // value for the ramp using the current frame. We need to update |value| | 957 // value for the ramp using the current frame. We need to update |value| |
613 // appropriately depending on whether the ramp has started or not. | 958 // appropriately depending on whether the ramp has started or not. |
614 // | 959 // |
615 // If SetTarget starts somewhere between currentFrame - 1 and | 960 // If SetTarget starts somewhere between currentFrame - 1 and |
616 // currentFrame, we directly compute the value it would have at | 961 // currentFrame, we directly compute the value it would have at |
617 // currentFrame. If not, we update the value from the value from | 962 // currentFrame. If not, we update the value from the value from |
618 // currentFrame - 1. | 963 // currentFrame - 1. |
619 // | 964 // |
620 // Can't use the condition currentFrame - 1 <= t0 * sampleRate <= | 965 // Can't use the condition currentFrame - 1 <= t0 * sampleRate <= |
621 // currentFrame because currentFrame is unsigned and could be 0. Instead, | 966 // currentFrame because currentFrame is unsigned and could be 0. Instead, |
622 // compute the condition this way, | 967 // compute the condition this way, |
623 // where f = currentFrame and Fs = sampleRate: | 968 // where f = currentFrame and Fs = sampleRate: |
624 // | 969 // |
625 // f - 1 <= t0 * Fs <= f | 970 // f - 1 <= t0 * Fs <= f |
626 // 2 * f - 2 <= 2 * Fs * t0 <= 2 * f | 971 // 2 * f - 2 <= 2 * Fs * t0 <= 2 * f |
627 // -2 <= 2 * Fs * t0 - 2 * f <= 0 | 972 // -2 <= 2 * Fs * t0 - 2 * f <= 0 |
628 // -1 <= 2 * Fs * t0 - 2 * f + 1 <= 1 | 973 // -1 <= 2 * Fs * t0 - 2 * f + 1 <= 1 |
629 // abs(2 * Fs * t0 - 2 * f + 1) <= 1 | 974 // abs(2 * Fs * t0 - 2 * f + 1) <= 1 |
630 if (fabs(2 * sampleRate * event.time() - 2 * currentFrame + 1) <= 1) { | 975 if (fabs(2 * sampleRate * event->time() - 2 * currentFrame + 1) <= 1) { |
631 // SetTarget is starting somewhere between currentFrame - 1 and | 976 // SetTarget is starting somewhere between currentFrame - 1 and |
632 // currentFrame. Compute the value the SetTarget would have at the | 977 // currentFrame. Compute the value the SetTarget would have at the |
633 // currentFrame. | 978 // currentFrame. |
634 value = event.value() + | 979 value = event->value() + |
635 (value - event.value()) * | 980 (value - event->value()) * |
636 exp(-(currentFrame / sampleRate - event.time()) / | 981 exp(-(currentFrame / sampleRate - event->time()) / |
637 event.timeConstant()); | 982 event->timeConstant()); |
638 } else { | 983 } else { |
639 // SetTarget has already started. Update |value| one frame because it's | 984 // SetTarget has already started. Update |value| one frame because it's |
640 // the value from the previous frame. | 985 // the value from the previous frame. |
641 float discreteTimeConstant = static_cast<float>( | 986 float discreteTimeConstant = static_cast<float>( |
642 AudioUtilities::discreteTimeConstantForSampleRate( | 987 AudioUtilities::discreteTimeConstantForSampleRate( |
643 event.timeConstant(), controlRate)); | 988 event->timeConstant(), controlRate)); |
644 value += (event.value() - value) * discreteTimeConstant; | 989 value += (event->value() - value) * discreteTimeConstant; |
645 } | 990 } |
646 | 991 |
647 // Insert a SetValueEvent to mark the starting value and time. | 992 // Insert a SetValueEvent to mark the starting value and time. |
648 // Clear the clamp check because this doesn't need it. | 993 // Clear the clamp check because this doesn't need it. |
649 m_events[i] = | 994 m_events[i] = |
650 ParamEvent::createSetValueEvent(value, currentFrame / sampleRate); | 995 ParamEvent::createSetValueEvent(value, currentFrame / sampleRate); |
651 m_events[i].clearTimeClampCheck(); | 996 m_events[i]->clearTimeClampCheck(); |
| 997 |
| 998 // Update our pointer to the current event because we just changed it. |
| 999 event = m_events[i].get(); |
652 } | 1000 } |
653 | 1001 |
654 float value1 = event.value(); | 1002 float value1 = event->value(); |
655 double time1 = event.time(); | 1003 double time1 = event->time(); |
656 | 1004 |
657 float value2 = nextEvent ? nextEvent->value() : value1; | 1005 float value2 = nextEvent ? nextEvent->value() : value1; |
658 double time2 = nextEvent ? nextEvent->time() : endFrame / sampleRate + 1; | 1006 double time2 = nextEvent ? nextEvent->time() : endFrame / sampleRate + 1; |
659 | 1007 |
| 1008 // Check to see if an event was cancelled. |
| 1009 if (nextEventType == ParamEvent::CancelValues) { |
| 1010 switch (event->getType()) { |
| 1011 case ParamEvent::LinearRampToValue: |
| 1012 case ParamEvent::ExponentialRampToValue: |
| 1013 case ParamEvent::SetValue: { |
| 1014 // These three events potentially establish a starting value for |
| 1015 // the following event, so we need to examine the cancelled |
| 1016 // event to see what to do. |
| 1017 const ParamEvent* savedEvent = nextEvent->savedEvent(); |
| 1018 |
| 1019 // Update the end time and type to pretend that we're running |
| 1020 // this saved event type. |
| 1021 time2 = nextEvent->time(); |
| 1022 nextEventType = savedEvent->getType(); |
| 1023 |
| 1024 if (nextEvent->hasDefaultCancelledValue()) { |
| 1025 // We've already established a value for the cancelled |
| 1026 // event, so just return it. |
| 1027 value2 = nextEvent->value(); |
| 1028 } else { |
| 1029 // If the next event would have been a LinearRamp or |
| 1030 // ExponentialRamp, we need to compute a new end value for |
| 1031 // the event so that the curve works continues as if it were |
| 1032 // not cancelled. |
| 1033 switch (savedEvent->getType()) { |
| 1034 case ParamEvent::LinearRampToValue: |
| 1035 value2 = |
| 1036 linearRampAtTime(nextEvent->time(), value1, time1, |
| 1037 savedEvent->value(), savedEvent->time()); |
| 1038 break; |
| 1039 case ParamEvent::ExponentialRampToValue: |
| 1040 value2 = exponentialRampAtTime(nextEvent->time(), value1, time1, |
| 1041 savedEvent->value(), |
| 1042 savedEvent->time()); |
| 1043 break; |
| 1044 case ParamEvent::SetValueCurve: |
| 1045 case ParamEvent::SetValue: |
| 1046 case ParamEvent::SetTarget: |
| 1047 case ParamEvent::CancelValues: |
| 1048 // These cannot be possible types for the saved event |
| 1049 // because they can't be created. |
| 1050 // createCancelValuesEvent doesn't allow them (SetValue, |
| 1051 // SetTarget, CancelValues) or cancelScheduledValues() |
| 1052 // doesn't create such an event (SetValueCurve). |
| 1053 NOTREACHED(); |
| 1054 break; |
| 1055 case ParamEvent::LastType: |
| 1056 // Illegal event type. |
| 1057 NOTREACHED(); |
| 1058 break; |
| 1059 } |
| 1060 |
| 1061 // Cache the new value so we don't keep computing it over and over. |
| 1062 nextEvent->setCancelledValue(value2); |
| 1063 } |
| 1064 } break; |
| 1065 case ParamEvent::SetValueCurve: |
| 1066 // Everything needed for this was handled when cancelling was |
| 1067 // done. |
| 1068 break; |
| 1069 case ParamEvent::SetTarget: |
| 1070 case ParamEvent::CancelValues: |
| 1071 // Nothing special needs to be done for SetTarget or |
| 1072 // CancelValues followed by CancelValues. |
| 1073 break; |
| 1074 case ParamEvent::LastType: |
| 1075 NOTREACHED(); |
| 1076 break; |
| 1077 } |
| 1078 } |
| 1079 |
660 DCHECK_GE(time2, time1); | 1080 DCHECK_GE(time2, time1); |
661 double deltaTime = time2 - time1; | 1081 double deltaTime = time2 - time1; |
662 float k = deltaTime > 0 ? 1 / deltaTime : 0; | 1082 float k = deltaTime > 0 ? 1 / deltaTime : 0; |
663 | 1083 |
664 // |fillToEndFrame| is the exclusive upper bound of the last frame to be | 1084 // |fillToEndFrame| is the exclusive upper bound of the last frame to be |
665 // computed for this event. It's either the last desired frame (|endFrame|) | 1085 // computed for this event. It's either the last desired frame (|endFrame|) |
666 // or derived from the end time of the next event (time2). We compute | 1086 // or derived from the end time of the next event (time2). We compute |
667 // ceil(time2*sampleRate) because fillToEndFrame is the exclusive upper | 1087 // ceil(time2*sampleRate) because fillToEndFrame is the exclusive upper |
668 // bound. Consider the case where |startFrame| = 128 and time2 = 128.1 | 1088 // bound. Consider the case where |startFrame| = 128 and time2 = 128.1 |
669 // (assuming sampleRate = 1). Since time2 is greater than 128, we want to | 1089 // (assuming sampleRate = 1). Since time2 is greater than 128, we want to |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
781 if (writeIndex >= 1) | 1201 if (writeIndex >= 1) |
782 value /= multiplier; | 1202 value /= multiplier; |
783 | 1203 |
784 // Due to roundoff it's possible that value exceeds value2. Clip value | 1204 // Due to roundoff it's possible that value exceeds value2. Clip value |
785 // to value2 if we are within 1/2 frame of time2. | 1205 // to value2 if we are within 1/2 frame of time2. |
786 if (currentFrame > time2 * sampleRate - 0.5) | 1206 if (currentFrame > time2 * sampleRate - 0.5) |
787 value = value2; | 1207 value = value2; |
788 } | 1208 } |
789 } else { | 1209 } else { |
790 // Handle event types not requiring looking ahead to the next event. | 1210 // Handle event types not requiring looking ahead to the next event. |
791 switch (event.getType()) { | 1211 switch (event->getType()) { |
792 case ParamEvent::SetValue: | 1212 case ParamEvent::SetValue: |
793 case ParamEvent::LinearRampToValue: { | 1213 case ParamEvent::LinearRampToValue: { |
794 currentFrame = fillToEndFrame; | 1214 currentFrame = fillToEndFrame; |
795 | 1215 |
796 // Simply stay at a constant value. | 1216 // Simply stay at a constant value. |
797 value = event.value(); | 1217 value = event->value(); |
798 | 1218 |
799 for (; writeIndex < fillToFrame; ++writeIndex) | 1219 for (; writeIndex < fillToFrame; ++writeIndex) |
800 values[writeIndex] = value; | 1220 values[writeIndex] = value; |
801 | 1221 |
802 break; | 1222 break; |
803 } | 1223 } |
804 | 1224 |
| 1225 case ParamEvent::CancelValues: { |
| 1226 // If the previous event was a SetTarget or ExponentialRamp |
| 1227 // event, the current value is one sample behind. Update |
| 1228 // the sample value by one sample, but only at the start of |
| 1229 // this CancelValues event. |
| 1230 if (event->hasDefaultCancelledValue()) { |
| 1231 value = event->value(); |
| 1232 } else { |
| 1233 double cancelFrame = time1 * sampleRate; |
| 1234 if (i >= 1 && cancelFrame <= currentFrame && |
| 1235 currentFrame < cancelFrame + 1) { |
| 1236 ParamEvent::Type lastEventType = m_events[i - 1]->getType(); |
| 1237 if (lastEventType == ParamEvent::SetTarget) { |
| 1238 float target = m_events[i - 1]->value(); |
| 1239 float timeConstant = m_events[i - 1]->timeConstant(); |
| 1240 float discreteTimeConstant = static_cast<float>( |
| 1241 AudioUtilities::discreteTimeConstantForSampleRate( |
| 1242 timeConstant, controlRate)); |
| 1243 value += (target - value) * discreteTimeConstant; |
| 1244 } |
| 1245 } |
| 1246 } |
| 1247 |
| 1248 // Simply stay at the current value. |
| 1249 for (; writeIndex < fillToFrame; ++writeIndex) |
| 1250 values[writeIndex] = value; |
| 1251 |
| 1252 currentFrame = fillToEndFrame; |
| 1253 break; |
| 1254 } |
| 1255 |
805 case ParamEvent::ExponentialRampToValue: { | 1256 case ParamEvent::ExponentialRampToValue: { |
806 currentFrame = fillToEndFrame; | 1257 currentFrame = fillToEndFrame; |
807 | 1258 |
808 // If we're here, we've reached the end of the ramp. If we can | 1259 // If we're here, we've reached the end of the ramp. If we can |
809 // (because the start and end values have the same sign, and neither | 1260 // (because the start and end values have the same sign, and neither |
810 // is 0), use the actual end value. If not, we have to propagate | 1261 // is 0), use the actual end value. If not, we have to propagate |
811 // whatever we have. | 1262 // whatever we have. |
812 if (i >= 1 && ((m_events[i - 1].value() * event.value()) > 0)) | 1263 if (i >= 1 && ((m_events[i - 1]->value() * event->value()) > 0)) |
813 value = event.value(); | 1264 value = event->value(); |
814 | 1265 |
815 // Simply stay at a constant value from the last time. We don't want | 1266 // Simply stay at a constant value from the last time. We don't want |
816 // to use the value of the event in case value1 * value2 < 0. In this | 1267 // to use the value of the event in case value1 * value2 < 0. In this |
817 // case we should propagate the previous value, which is in |value|. | 1268 // case we should propagate the previous value, which is in |value|. |
818 for (; writeIndex < fillToFrame; ++writeIndex) | 1269 for (; writeIndex < fillToFrame; ++writeIndex) |
819 values[writeIndex] = value; | 1270 values[writeIndex] = value; |
820 | 1271 |
821 break; | 1272 break; |
822 } | 1273 } |
823 | 1274 |
824 case ParamEvent::SetTarget: { | 1275 case ParamEvent::SetTarget: { |
825 // Exponential approach to target value with given time constant. | 1276 // Exponential approach to target value with given time constant. |
826 // | 1277 // |
827 // v(t) = v2 + (v1 - v2)*exp(-(t-t1/tau)) | 1278 // v(t) = v2 + (v1 - v2)*exp(-(t-t1/tau)) |
828 // | 1279 // |
829 | 1280 |
830 float target = event.value(); | 1281 float target = event->value(); |
831 float timeConstant = event.timeConstant(); | 1282 float timeConstant = event->timeConstant(); |
832 float discreteTimeConstant = static_cast<float>( | 1283 float discreteTimeConstant = static_cast<float>( |
833 AudioUtilities::discreteTimeConstantForSampleRate(timeConstant, | 1284 AudioUtilities::discreteTimeConstantForSampleRate(timeConstant, |
834 controlRate)); | 1285 controlRate)); |
835 | 1286 |
836 // Set the starting value correctly. This is only needed when the | 1287 // Set the starting value correctly. This is only needed when the |
837 // current time is "equal" to the start time of this event. This is | 1288 // current time is "equal" to the start time of this event. This is |
838 // to get the sampling correct if the start time of this automation | 1289 // to get the sampling correct if the start time of this automation |
839 // isn't on a frame boundary. Otherwise, we can just continue from | 1290 // isn't on a frame boundary. Otherwise, we can just continue from |
840 // where we left off from the previous rendering quantum. | 1291 // where we left off from the previous rendering quantum. |
841 { | 1292 { |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
910 // The previous loops may have updated |value| one extra time. | 1361 // The previous loops may have updated |value| one extra time. |
911 // Reset it to the last computed value. | 1362 // Reset it to the last computed value. |
912 if (writeIndex >= 1) | 1363 if (writeIndex >= 1) |
913 value = values[writeIndex - 1]; | 1364 value = values[writeIndex - 1]; |
914 currentFrame = fillToEndFrame; | 1365 currentFrame = fillToEndFrame; |
915 } | 1366 } |
916 break; | 1367 break; |
917 } | 1368 } |
918 | 1369 |
919 case ParamEvent::SetValueCurve: { | 1370 case ParamEvent::SetValueCurve: { |
920 Vector<float> curve = event.curve(); | 1371 Vector<float> curve = event->curve(); |
921 float* curveData = curve.data(); | 1372 float* curveData = curve.data(); |
922 unsigned numberOfCurvePoints = curve.size(); | 1373 unsigned numberOfCurvePoints = curve.size(); |
923 | 1374 |
| 1375 float curveEndValue = event->curveEndValue(); |
| 1376 |
924 // Curve events have duration, so don't just use next event time. | 1377 // Curve events have duration, so don't just use next event time. |
925 double duration = event.duration(); | 1378 double duration = event->duration(); |
926 // How much to step the curve index for each frame. This is basically | 1379 // How much to step the curve index for each frame. This is basically |
927 // the term (N - 1)/Td in the specification. | 1380 // the term (N - 1)/Td in the specification. |
928 double curvePointsPerFrame = | 1381 double curvePointsPerFrame = |
929 (numberOfCurvePoints - 1) / duration / sampleRate; | 1382 event->curvePointsPerSecond() / sampleRate; |
930 | 1383 |
931 if (!numberOfCurvePoints || duration <= 0 || sampleRate <= 0) { | 1384 if (!numberOfCurvePoints || duration <= 0 || sampleRate <= 0) { |
932 // Error condition - simply propagate previous value. | 1385 // Error condition - simply propagate previous value. |
933 currentFrame = fillToEndFrame; | 1386 currentFrame = fillToEndFrame; |
934 for (; writeIndex < fillToFrame; ++writeIndex) | 1387 for (; writeIndex < fillToFrame; ++writeIndex) |
935 values[writeIndex] = value; | 1388 values[writeIndex] = value; |
936 break; | 1389 break; |
937 } | 1390 } |
938 | 1391 |
939 // Save old values and recalculate information based on the curve's | 1392 // Save old values and recalculate information based on the curve's |
(...skipping 29 matching lines...) Expand all Loading... |
969 double curveVirtualIndex = 0; | 1422 double curveVirtualIndex = 0; |
970 if (time1 < currentFrame / sampleRate) { | 1423 if (time1 < currentFrame / sampleRate) { |
971 // Index somewhere in the middle of the curve data. | 1424 // Index somewhere in the middle of the curve data. |
972 // Don't use timeToSampleFrame() since we want the exact | 1425 // Don't use timeToSampleFrame() since we want the exact |
973 // floating-point frame. | 1426 // floating-point frame. |
974 double frameOffset = currentFrame - time1 * sampleRate; | 1427 double frameOffset = currentFrame - time1 * sampleRate; |
975 curveVirtualIndex = curvePointsPerFrame * frameOffset; | 1428 curveVirtualIndex = curvePointsPerFrame * frameOffset; |
976 } | 1429 } |
977 | 1430 |
978 // Set the default value in case fillToFrame is 0. | 1431 // Set the default value in case fillToFrame is 0. |
979 value = curveData[numberOfCurvePoints - 1]; | 1432 value = curveEndValue; |
980 | 1433 |
981 // Render the stretched curve data using linear interpolation. | 1434 // Render the stretched curve data using linear interpolation. |
982 // Oversampled curve data can be provided if sharp discontinuities are | 1435 // Oversampled curve data can be provided if sharp discontinuities are |
983 // desired. | 1436 // desired. |
984 unsigned k = 0; | 1437 unsigned k = 0; |
985 #if CPU(X86) || CPU(X86_64) | 1438 #if CPU(X86) || CPU(X86_64) |
986 if (fillToFrame > writeIndex) { | 1439 if (fillToFrame > writeIndex) { |
987 const __m128 vCurveVirtualIndex = _mm_set_ps1(curveVirtualIndex); | 1440 const __m128 vCurveVirtualIndex = _mm_set_ps1(curveVirtualIndex); |
988 const __m128 vCurvePointsPerFrame = | 1441 const __m128 vCurvePointsPerFrame = |
989 _mm_set_ps1(curvePointsPerFrame); | 1442 _mm_set_ps1(curvePointsPerFrame); |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1072 float c1 = curveData[curveIndex1]; | 1525 float c1 = curveData[curveIndex1]; |
1073 double delta = std::min(currentVirtualIndex - curveIndex0, 1.0); | 1526 double delta = std::min(currentVirtualIndex - curveIndex0, 1.0); |
1074 | 1527 |
1075 value = c0 + (c1 - c0) * delta; | 1528 value = c0 + (c1 - c0) * delta; |
1076 | 1529 |
1077 values[writeIndex] = value; | 1530 values[writeIndex] = value; |
1078 } | 1531 } |
1079 | 1532 |
1080 // If there's any time left after the duration of this event and the | 1533 // If there's any time left after the duration of this event and the |
1081 // start of the next, then just propagate the last value of the | 1534 // start of the next, then just propagate the last value of the |
1082 // curveData. | 1535 // curveData. Don't modify |value| unless there is time left. |
1083 if (writeIndex < nextEventFillToFrame) | 1536 if (writeIndex < nextEventFillToFrame) { |
1084 value = curveData[numberOfCurvePoints - 1]; | 1537 value = curveEndValue; |
1085 for (; writeIndex < nextEventFillToFrame; ++writeIndex) | 1538 for (; writeIndex < nextEventFillToFrame; ++writeIndex) |
1086 values[writeIndex] = value; | 1539 values[writeIndex] = value; |
| 1540 } |
1087 | 1541 |
1088 // Re-adjust current time | 1542 // Re-adjust current time |
1089 currentFrame += nextEventFillToFrame; | 1543 currentFrame += nextEventFillToFrame; |
1090 | 1544 |
1091 break; | 1545 break; |
1092 } | 1546 } |
1093 case ParamEvent::LastType: | 1547 case ParamEvent::LastType: |
1094 ASSERT_NOT_REACHED(); | 1548 ASSERT_NOT_REACHED(); |
1095 break; | 1549 break; |
1096 } | 1550 } |
(...skipping 11 matching lines...) Expand all Loading... |
1108 // propagate the last value to the end of the values buffer. | 1562 // propagate the last value to the end of the values buffer. |
1109 for (; writeIndex < numberOfValues; ++writeIndex) | 1563 for (; writeIndex < numberOfValues; ++writeIndex) |
1110 values[writeIndex] = value; | 1564 values[writeIndex] = value; |
1111 | 1565 |
1112 // This value is used to set the .value attribute of the AudioParam. it | 1566 // This value is used to set the .value attribute of the AudioParam. it |
1113 // should be the last computed value. | 1567 // should be the last computed value. |
1114 return values[numberOfValues - 1]; | 1568 return values[numberOfValues - 1]; |
1115 } | 1569 } |
1116 | 1570 |
1117 } // namespace blink | 1571 } // namespace blink |
OLD | NEW |