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 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
147 } | 147 } |
148 | 148 |
149 finish(); | 149 finish(); |
150 return true; | 150 return true; |
151 } | 151 } |
152 return false; | 152 return false; |
153 } | 153 } |
154 | 154 |
155 bool AudioBufferSourceHandler::renderFromBuffer(AudioBus* bus, unsigned destinat
ionFrameOffset, size_t numberOfFrames) | 155 bool AudioBufferSourceHandler::renderFromBuffer(AudioBus* bus, unsigned destinat
ionFrameOffset, size_t numberOfFrames) |
156 { | 156 { |
157 ASSERT(context()->isAudioThread()); | 157 DCHECK(context()->isAudioThread()); |
158 | 158 |
159 // Basic sanity checking | 159 // Basic sanity checking |
160 ASSERT(bus); | 160 DCHECK(bus); |
161 ASSERT(buffer()); | 161 DCHECK(buffer()); |
162 if (!bus || !buffer()) | 162 if (!bus || !buffer()) |
163 return false; | 163 return false; |
164 | 164 |
165 unsigned numberOfChannels = this->numberOfChannels(); | 165 unsigned numberOfChannels = this->numberOfChannels(); |
166 unsigned busNumberOfChannels = bus->numberOfChannels(); | 166 unsigned busNumberOfChannels = bus->numberOfChannels(); |
167 | 167 |
168 bool channelCountGood = numberOfChannels && numberOfChannels == busNumberOfC
hannels; | 168 bool channelCountGood = numberOfChannels && numberOfChannels == busNumberOfC
hannels; |
169 ASSERT(channelCountGood); | 169 DCHECK(channelCountGood); |
170 if (!channelCountGood) | 170 if (!channelCountGood) |
171 return false; | 171 return false; |
172 | 172 |
173 // Sanity check destinationFrameOffset, numberOfFrames. | 173 // Sanity check destinationFrameOffset, numberOfFrames. |
174 size_t destinationLength = bus->length(); | 174 size_t destinationLength = bus->length(); |
175 | 175 |
176 bool isLengthGood = destinationLength <= AudioUtilities::kRenderQuantumFrame
s | 176 bool isLengthGood = destinationLength <= AudioUtilities::kRenderQuantumFrame
s |
177 && numberOfFrames <= AudioUtilities::kRenderQuantumFrames; | 177 && numberOfFrames <= AudioUtilities::kRenderQuantumFrames; |
178 ASSERT(isLengthGood); | 178 DCHECK(isLengthGood); |
179 if (!isLengthGood) | 179 if (!isLengthGood) |
180 return false; | 180 return false; |
181 | 181 |
182 bool isOffsetGood = destinationFrameOffset <= destinationLength && destinati
onFrameOffset + numberOfFrames <= destinationLength; | 182 bool isOffsetGood = destinationFrameOffset <= destinationLength && destinati
onFrameOffset + numberOfFrames <= destinationLength; |
183 ASSERT(isOffsetGood); | 183 DCHECK(isOffsetGood); |
184 if (!isOffsetGood) | 184 if (!isOffsetGood) |
185 return false; | 185 return false; |
186 | 186 |
187 // Potentially zero out initial frames leading up to the offset. | 187 // Potentially zero out initial frames leading up to the offset. |
188 if (destinationFrameOffset) { | 188 if (destinationFrameOffset) { |
189 for (unsigned i = 0; i < numberOfChannels; ++i) | 189 for (unsigned i = 0; i < numberOfChannels; ++i) |
190 memset(m_destinationChannels[i], 0, sizeof(float) * destinationFrame
Offset); | 190 memset(m_destinationChannels[i], 0, sizeof(float) * destinationFrame
Offset); |
191 } | 191 } |
192 | 192 |
193 // Offset the pointers to the correct offset frame. | 193 // Offset the pointers to the correct offset frame. |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
237 | 237 |
238 // Get local copy. | 238 // Get local copy. |
239 double virtualReadIndex = m_virtualReadIndex; | 239 double virtualReadIndex = m_virtualReadIndex; |
240 | 240 |
241 // Render loop - reading from the source buffer to the destination using lin
ear interpolation. | 241 // Render loop - reading from the source buffer to the destination using lin
ear interpolation. |
242 int framesToProcess = numberOfFrames; | 242 int framesToProcess = numberOfFrames; |
243 | 243 |
244 const float** sourceChannels = m_sourceChannels.get(); | 244 const float** sourceChannels = m_sourceChannels.get(); |
245 float** destinationChannels = m_destinationChannels.get(); | 245 float** destinationChannels = m_destinationChannels.get(); |
246 | 246 |
247 ASSERT(virtualReadIndex >= 0); | 247 DCHECK_GE(virtualReadIndex, 0); |
248 ASSERT(virtualDeltaFrames >= 0); | 248 DCHECK_GE(virtualDeltaFrames, 0); |
249 ASSERT(virtualEndFrame >= 0); | 249 DCHECK_GE(virtualEndFrame, 0); |
250 | 250 |
251 // Optimize for the very common case of playing back with computedPlaybackRa
te == 1. | 251 // Optimize for the very common case of playing back with computedPlaybackRa
te == 1. |
252 // We can avoid the linear interpolation. | 252 // We can avoid the linear interpolation. |
253 if (computedPlaybackRate == 1 && virtualReadIndex == floor(virtualReadIndex) | 253 if (computedPlaybackRate == 1 && virtualReadIndex == floor(virtualReadIndex) |
254 && virtualDeltaFrames == floor(virtualDeltaFrames) | 254 && virtualDeltaFrames == floor(virtualDeltaFrames) |
255 && virtualEndFrame == floor(virtualEndFrame)) { | 255 && virtualEndFrame == floor(virtualEndFrame)) { |
256 unsigned readIndex = static_cast<unsigned>(virtualReadIndex); | 256 unsigned readIndex = static_cast<unsigned>(virtualReadIndex); |
257 unsigned deltaFrames = static_cast<unsigned>(virtualDeltaFrames); | 257 unsigned deltaFrames = static_cast<unsigned>(virtualDeltaFrames); |
258 endFrame = static_cast<unsigned>(virtualEndFrame); | 258 endFrame = static_cast<unsigned>(virtualEndFrame); |
259 while (framesToProcess > 0) { | 259 while (framesToProcess > 0) { |
260 int framesToEnd = endFrame - readIndex; | 260 int framesToEnd = endFrame - readIndex; |
261 int framesThisTime = std::min(framesToProcess, framesToEnd); | 261 int framesThisTime = std::min(framesToProcess, framesToEnd); |
262 framesThisTime = std::max(0, framesThisTime); | 262 framesThisTime = std::max(0, framesThisTime); |
263 | 263 |
264 for (unsigned i = 0; i < numberOfChannels; ++i) | 264 for (unsigned i = 0; i < numberOfChannels; ++i) |
265 memcpy(destinationChannels[i] + writeIndex, sourceChannels[i] +
readIndex, sizeof(float) * framesThisTime); | 265 memcpy(destinationChannels[i] + writeIndex, sourceChannels[i] +
readIndex, sizeof(float) * framesThisTime); |
266 | 266 |
267 writeIndex += framesThisTime; | 267 writeIndex += framesThisTime; |
268 readIndex += framesThisTime; | 268 readIndex += framesThisTime; |
269 framesToProcess -= framesThisTime; | 269 framesToProcess -= framesThisTime; |
270 | 270 |
271 // It can happen that framesThisTime is 0. Assert that we will actua
lly exit the loop in | 271 // It can happen that framesThisTime is 0. DCHECK that we will actua
lly exit the loop in |
272 // this case. framesThisTime is 0 only if readIndex >= endFrame; | 272 // this case. framesThisTime is 0 only if readIndex >= endFrame; |
273 ASSERT(framesThisTime ? true : readIndex >= endFrame); | 273 DCHECK(framesThisTime ? true : readIndex >= endFrame); |
274 | 274 |
275 // Wrap-around. | 275 // Wrap-around. |
276 if (readIndex >= endFrame) { | 276 if (readIndex >= endFrame) { |
277 readIndex -= deltaFrames; | 277 readIndex -= deltaFrames; |
278 if (renderSilenceAndFinishIfNotLooping(bus, writeIndex, framesTo
Process)) | 278 if (renderSilenceAndFinishIfNotLooping(bus, writeIndex, framesTo
Process)) |
279 break; | 279 break; |
280 } | 280 } |
281 } | 281 } |
282 virtualReadIndex = readIndex; | 282 virtualReadIndex = readIndex; |
283 } else { | 283 } else { |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
328 bus->clearSilentFlag(); | 328 bus->clearSilentFlag(); |
329 | 329 |
330 m_virtualReadIndex = virtualReadIndex; | 330 m_virtualReadIndex = virtualReadIndex; |
331 | 331 |
332 return true; | 332 return true; |
333 } | 333 } |
334 | 334 |
335 | 335 |
336 void AudioBufferSourceHandler::setBuffer(AudioBuffer* buffer, ExceptionState& ex
ceptionState) | 336 void AudioBufferSourceHandler::setBuffer(AudioBuffer* buffer, ExceptionState& ex
ceptionState) |
337 { | 337 { |
338 ASSERT(isMainThread()); | 338 DCHECK(isMainThread()); |
339 | 339 |
340 if (m_buffer) { | 340 if (m_buffer) { |
341 exceptionState.throwDOMException( | 341 exceptionState.throwDOMException( |
342 InvalidStateError, | 342 InvalidStateError, |
343 "Cannot set buffer after it has been already been set"); | 343 "Cannot set buffer after it has been already been set"); |
344 return; | 344 return; |
345 } | 345 } |
346 | 346 |
347 // The context must be locked since changing the buffer can re-configure the
number of channels that are output. | 347 // The context must be locked since changing the buffer can re-configure the
number of channels that are output. |
348 BaseAudioContext::AutoLocker contextLocker(context()); | 348 BaseAudioContext::AutoLocker contextLocker(context()); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
387 m_buffer = buffer; | 387 m_buffer = buffer; |
388 } | 388 } |
389 | 389 |
390 unsigned AudioBufferSourceHandler::numberOfChannels() | 390 unsigned AudioBufferSourceHandler::numberOfChannels() |
391 { | 391 { |
392 return output(0).numberOfChannels(); | 392 return output(0).numberOfChannels(); |
393 } | 393 } |
394 | 394 |
395 void AudioBufferSourceHandler::clampGrainParameters(const AudioBuffer* buffer) | 395 void AudioBufferSourceHandler::clampGrainParameters(const AudioBuffer* buffer) |
396 { | 396 { |
397 ASSERT(buffer); | 397 DCHECK(buffer); |
398 | 398 |
399 // We have a buffer so we can clip the offset and duration to lie within the
buffer. | 399 // We have a buffer so we can clip the offset and duration to lie within the
buffer. |
400 double bufferDuration = buffer->duration(); | 400 double bufferDuration = buffer->duration(); |
401 | 401 |
402 m_grainOffset = clampTo(m_grainOffset, 0.0, bufferDuration); | 402 m_grainOffset = clampTo(m_grainOffset, 0.0, bufferDuration); |
403 | 403 |
404 // If the duration was not explicitly given, use the buffer duration to set
the grain | 404 // If the duration was not explicitly given, use the buffer duration to set
the grain |
405 // duration. Otherwise, we want to use the user-specified value, of course. | 405 // duration. Otherwise, we want to use the user-specified value, of course. |
406 if (!m_isDurationGiven) | 406 if (!m_isDurationGiven) |
407 m_grainDuration = bufferDuration - m_grainOffset; | 407 m_grainDuration = bufferDuration - m_grainOffset; |
(...skipping 26 matching lines...) Expand all Loading... |
434 startSource(when, grainOffset, buffer() ? buffer()->duration() : 0, false, e
xceptionState); | 434 startSource(when, grainOffset, buffer() ? buffer()->duration() : 0, false, e
xceptionState); |
435 } | 435 } |
436 | 436 |
437 void AudioBufferSourceHandler::start(double when, double grainOffset, double gra
inDuration, ExceptionState& exceptionState) | 437 void AudioBufferSourceHandler::start(double when, double grainOffset, double gra
inDuration, ExceptionState& exceptionState) |
438 { | 438 { |
439 startSource(when, grainOffset, grainDuration, true, exceptionState); | 439 startSource(when, grainOffset, grainDuration, true, exceptionState); |
440 } | 440 } |
441 | 441 |
442 void AudioBufferSourceHandler::startSource(double when, double grainOffset, doub
le grainDuration, bool isDurationGiven, ExceptionState& exceptionState) | 442 void AudioBufferSourceHandler::startSource(double when, double grainOffset, doub
le grainDuration, bool isDurationGiven, ExceptionState& exceptionState) |
443 { | 443 { |
444 ASSERT(isMainThread()); | 444 DCHECK(isMainThread()); |
445 | 445 |
446 context()->recordUserGestureState(); | 446 context()->recordUserGestureState(); |
447 | 447 |
448 if (playbackState() != UNSCHEDULED_STATE) { | 448 if (playbackState() != UNSCHEDULED_STATE) { |
449 exceptionState.throwDOMException( | 449 exceptionState.throwDOMException( |
450 InvalidStateError, | 450 InvalidStateError, |
451 "cannot call start more than once."); | 451 "cannot call start more than once."); |
452 return; | 452 return; |
453 } | 453 } |
454 | 454 |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
525 double finalPlaybackRate = sampleRateFactor * basePlaybackRate; | 525 double finalPlaybackRate = sampleRateFactor * basePlaybackRate; |
526 | 526 |
527 // Take the detune value into account for the final playback rate. | 527 // Take the detune value into account for the final playback rate. |
528 finalPlaybackRate *= pow(2, m_detune->finalValue() / 1200); | 528 finalPlaybackRate *= pow(2, m_detune->finalValue() / 1200); |
529 | 529 |
530 // Sanity check the total rate. It's very important that the resampler not | 530 // Sanity check the total rate. It's very important that the resampler not |
531 // get any bad rate values. | 531 // get any bad rate values. |
532 finalPlaybackRate = clampTo(finalPlaybackRate, 0.0, MaxRate); | 532 finalPlaybackRate = clampTo(finalPlaybackRate, 0.0, MaxRate); |
533 | 533 |
534 bool isPlaybackRateValid = !std::isnan(finalPlaybackRate) && !std::isinf(fin
alPlaybackRate); | 534 bool isPlaybackRateValid = !std::isnan(finalPlaybackRate) && !std::isinf(fin
alPlaybackRate); |
535 ASSERT(isPlaybackRateValid); | 535 DCHECK(isPlaybackRateValid); |
536 | 536 |
537 if (!isPlaybackRateValid) | 537 if (!isPlaybackRateValid) |
538 finalPlaybackRate = 1.0; | 538 finalPlaybackRate = 1.0; |
539 | 539 |
540 // Record the minimum playback rate for use by handleStoppableSourceNode. | 540 // Record the minimum playback rate for use by handleStoppableSourceNode. |
541 m_minPlaybackRate = std::min(finalPlaybackRate, m_minPlaybackRate); | 541 m_minPlaybackRate = std::min(finalPlaybackRate, m_minPlaybackRate); |
542 | 542 |
543 return finalPlaybackRate; | 543 return finalPlaybackRate; |
544 } | 544 } |
545 | 545 |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
685 { | 685 { |
686 audioBufferSourceHandler().start(when, grainOffset, exceptionState); | 686 audioBufferSourceHandler().start(when, grainOffset, exceptionState); |
687 } | 687 } |
688 | 688 |
689 void AudioBufferSourceNode::start(double when, double grainOffset, double grainD
uration, ExceptionState& exceptionState) | 689 void AudioBufferSourceNode::start(double when, double grainOffset, double grainD
uration, ExceptionState& exceptionState) |
690 { | 690 { |
691 audioBufferSourceHandler().start(when, grainOffset, grainDuration, exception
State); | 691 audioBufferSourceHandler().start(when, grainOffset, grainDuration, exception
State); |
692 } | 692 } |
693 | 693 |
694 } // namespace blink | 694 } // namespace blink |
OLD | NEW |