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