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