1 /* 2 * Copyright (C) 2010, Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY 17 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 */ 24 25 #include "config.h" 26 27 #if ENABLE(WEB_AUDIO) 28 29 #include "modules/webaudio/AudioBufferSourceNode.h" 30 31 #include "bindings/core/v8/ExceptionState.h" 32 #include "core/dom/ExceptionCode.h" 33 #include "platform/audio/AudioUtilities.h" 34 #include "modules/webaudio/AudioContext.h" 35 #include "modules/webaudio/AudioNodeOutput.h" 36 #include "platform/FloatConversion.h" 37 #include "wtf/MainThread.h" 38 #include "wtf/MathExtras.h" 39 #include <algorithm> 40 41 namespace blink { 42 43 const double DefaultGrainDuration = 0.020; // 20ms 44 45 // Arbitrary upper limit on playback rate. 46 // Higher than expected rates can be useful when playing back oversampled buffers 47 // to minimize linear interpolation aliasing. 48 const double MaxRate = 1024; 49 50 AudioBufferSourceNode* AudioBufferSourceNode::create(AudioContext* context, float sampleRate) 51 { 52 return adoptRefCountedGarbageCollectedWillBeNoop(new AudioBufferSourceNode(context, sampleRate)); 53 } 54 55 AudioBufferSourceNode::AudioBufferSourceNode(AudioContext* context, float sampleRate) 56 : AudioScheduledSourceNode(context, sampleRate) 57 , m_buffer(nullptr) 58 , m_isLooping(false) 59 , m_loopStart(0) 60 , m_loopEnd(0) 61 , m_virtualReadIndex(0) 62 , m_isGrain(false) 63 , m_grainOffset(0.0) 64 , m_grainDuration(DefaultGrainDuration) 65 { 66 setNodeType(NodeTypeAudioBufferSource); 67 68 m_playbackRate = AudioParam::create(context, 1.0); 69 70 // Default to mono. A call to setBuffer() will set the number of output 71 // channels to that of the buffer. 72 addOutput(AudioNodeOutput::create(this, 1)); 73 74 initialize(); 75 } 76 77 AudioBufferSourceNode::~AudioBufferSourceNode() 78 { 79 ASSERT(!isInitialized()); 80 } 81 82 void AudioBufferSourceNode::dispose() 83 { 84 clearPannerNode(); 85 uninitialize(); 86 AudioScheduledSourceNode::dispose(); 87 } 88 89 void AudioBufferSourceNode::process(size_t framesToProcess) 90 { 91 AudioBus* outputBus = output(0)->bus(); 92 93 if (!isInitialized()) { 94 outputBus->zero(); 95 return; 96 } 97 98 // The audio thread can't block on this lock, so we call tryLock() instead. 99 MutexTryLocker tryLocker(m_processLock); 100 if (tryLocker.locked()) { 101 if (!buffer()) { 102 outputBus->zero(); 103 return; 104 } 105 106 // After calling setBuffer() with a buffer having a different number of channels, there can in rare cases be a slight delay 107 // before the output bus is updated to the new number of channels because of use of tryLocks() in the context's updating system. 108 // In this case, if the the buffer has just been changed and we're not quite ready yet, then just output silence. 109 if (numberOfChannels() != buffer()->numberOfChannels()) { 110 outputBus->zero(); 111 return; 112 } 113 114 size_t quantumFrameOffset; 115 size_t bufferFramesToProcess; 116 117 updateSchedulingInfo(framesToProcess, 118 outputBus, 119 quantumFrameOffset, 120 bufferFramesToProcess); 121 122 if (!bufferFramesToProcess) { 123 outputBus->zero(); 124 return; 125 } 126 127 for (unsigned i = 0; i < outputBus->numberOfChannels(); ++i) 128 m_destinationChannels[i] = outputBus->channel(i)->mutableData(); 129 130 // Render by reading directly from the buffer. 131 if (!renderFromBuffer(outputBus, quantumFrameOffset, bufferFramesToProcess)) { 132 outputBus->zero(); 133 return; 134 } 135 136 outputBus->clearSilentFlag(); 137 } else { 138 // Too bad - the tryLock() failed. We must be in the middle of changing buffers and were already outputting silence anyway. 139 outputBus->zero(); 140 } 141 } 142 143 // Returns true if we're finished. 144 bool AudioBufferSourceNode::renderSilenceAndFinishIfNotLooping(AudioBus*, unsigned index, size_t framesToProcess) 145 { 146 if (!loop()) { 147 // If we're not looping, then stop playing when we get to the end. 148 149 if (framesToProcess > 0) { 150 // We're not looping and we've reached the end of the sample data, but we still need to provide more output, 151 // so generate silence for the remaining. 152 for (unsigned i = 0; i < numberOfChannels(); ++i) 153 memset(m_destinationChannels[i] + index, 0, sizeof(float) * framesToProcess); 154 } 155 156 finish(); 157 return true; 158 } 159 return false; 160 } 161 162 bool AudioBufferSourceNode::renderFromBuffer(AudioBus* bus, unsigned destinationFrameOffset, size_t numberOfFrames) 163 { 164 ASSERT(context()->isAudioThread()); 165 166 // Basic sanity checking 167 ASSERT(bus); 168 ASSERT(buffer()); 169 if (!bus || !buffer()) 170 return false; 171 172 unsigned numberOfChannels = this->numberOfChannels(); 173 unsigned busNumberOfChannels = bus->numberOfChannels(); 174 175 bool channelCountGood = numberOfChannels && numberOfChannels == busNumberOfChannels; 176 ASSERT(channelCountGood); 177 if (!channelCountGood) 178 return false; 179 180 // Sanity check destinationFrameOffset, numberOfFrames. 181 size_t destinationLength = bus->length(); 182 183 bool isLengthGood = destinationLength <= 4096 && numberOfFrames <= 4096; 184 ASSERT(isLengthGood); 185 if (!isLengthGood) 186 return false; 187 188 bool isOffsetGood = destinationFrameOffset <= destinationLength && destinationFrameOffset + numberOfFrames <= destinationLength; 189 ASSERT(isOffsetGood); 190 if (!isOffsetGood) 191 return false; 192 193 // Potentially zero out initial frames leading up to the offset. 194 if (destinationFrameOffset) { 195 for (unsigned i = 0; i < numberOfChannels; ++i) 196 memset(m_destinationChannels[i], 0, sizeof(float) * destinationFrameOffset); 197 } 198 199 // Offset the pointers to the correct offset frame. 200 unsigned writeIndex = destinationFrameOffset; 201 202 size_t bufferLength = buffer()->length(); 203 double bufferSampleRate = buffer()->sampleRate(); 204 205 // Avoid converting from time to sample-frames twice by computing 206 // the grain end time first before computing the sample frame. 207 unsigned endFrame = m_isGrain ? AudioUtilities::timeToSampleFrame(m_grainOffset + m_grainDuration, bufferSampleRate) : bufferLength; 208 209 // This is a HACK to allow for HRTF tail-time - avoids glitch at end. 210 // FIXME: implement tailTime for each AudioNode for a more general solution to this problem. 211 // https://bugs.webkit.org/show_bug.cgi?id=77224 212 if (m_isGrain) 213 endFrame += 512; 214 215 // Do some sanity checking. 216 if (endFrame > bufferLength) 217 endFrame = bufferLength; 218 if (m_virtualReadIndex >= endFrame) 219 m_virtualReadIndex = 0; // reset to start 220 221 // If the .loop attribute is true, then values of m_loopStart == 0 && m_loopEnd == 0 implies 222 // that we should use the entire buffer as the loop, otherwise use the loop values in m_loopStart and m_loopEnd. 223 double virtualEndFrame = endFrame; 224 double virtualDeltaFrames = endFrame; 225 226 if (loop() && (m_loopStart || m_loopEnd) && m_loopStart >= 0 && m_loopEnd > 0 && m_loopStart < m_loopEnd) { 227 // Convert from seconds to sample-frames. 228 double loopStartFrame = m_loopStart * buffer()->sampleRate(); 229 double loopEndFrame = m_loopEnd * buffer()->sampleRate(); 230 231 virtualEndFrame = std::min(loopEndFrame, virtualEndFrame); 232 virtualDeltaFrames = virtualEndFrame - loopStartFrame; 233 } 234 235 236 double pitchRate = totalPitchRate(); 237 238 // Sanity check that our playback rate isn't larger than the loop size. 239 if (pitchRate >= virtualDeltaFrames) 240 return false; 241 242 // Get local copy. 243 double virtualReadIndex = m_virtualReadIndex; 244 245 // Render loop - reading from the source buffer to the destination using linear interpolation. 246 int framesToProcess = numberOfFrames; 247 248 const float** sourceChannels = m_sourceChannels.get(); 249 float** destinationChannels = m_destinationChannels.get(); 250 251 // Optimize for the very common case of playing back with pitchRate == 1. 252 // We can avoid the linear interpolation. 253 if (pitchRate == 1 && virtualReadIndex == floor(virtualReadIndex) 254 && virtualDeltaFrames == floor(virtualDeltaFrames) 255 && virtualEndFrame == floor(virtualEndFrame)) { 256 unsigned readIndex = static_cast<unsigned>(virtualReadIndex); 257 unsigned deltaFrames = static_cast<unsigned>(virtualDeltaFrames); 258 endFrame = static_cast<unsigned>(virtualEndFrame); 259 while (framesToProcess > 0) { 260 int framesToEnd = endFrame - readIndex; 261 int framesThisTime = std::min(framesToProcess, framesToEnd); 262 framesThisTime = std::max(0, framesThisTime); 263 264 for (unsigned i = 0; i < numberOfChannels; ++i) 265 memcpy(destinationChannels[i] + writeIndex, sourceChannels[i] + readIndex, sizeof(float) * framesThisTime); 266 267 writeIndex += framesThisTime; 268 readIndex += framesThisTime; 269 framesToProcess -= framesThisTime; 270 271 // Wrap-around. 272 if (readIndex >= endFrame) { 273 readIndex -= deltaFrames; 274 if (renderSilenceAndFinishIfNotLooping(bus, writeIndex, framesToProcess)) 275 break; 276 } 277 } 278 virtualReadIndex = readIndex; 279 } else { 280 while (framesToProcess--) { 281 unsigned readIndex = static_cast<unsigned>(virtualReadIndex); 282 double interpolationFactor = virtualReadIndex - readIndex; 283 284 // For linear interpolation we need the next sample-frame too. 285 unsigned readIndex2 = readIndex + 1; 286 if (readIndex2 >= bufferLength) { 287 if (loop()) { 288 // Make sure to wrap around at the end of the buffer. 289 readIndex2 = static_cast<unsigned>(virtualReadIndex + 1 - virtualDeltaFrames); 290 } else 291 readIndex2 = readIndex; 292 } 293 294 // Final sanity check on buffer access. 295 // FIXME: as an optimization, try to get rid of this inner-loop check and put assertions and guards before the loop. 296 if (readIndex >= bufferLength || readIndex2 >= bufferLength) 297 break; 298 299 // Linear interpolation. 300 for (unsigned i = 0; i < numberOfChannels; ++i) { 301 float* destination = destinationChannels[i]; 302 const float* source = sourceChannels[i]; 303 304 double sample1 = source[readIndex]; 305 double sample2 = source[readIndex2]; 306 double sample = (1.0 - interpolationFactor) * sample1 + interpolationFactor * sample2; 307 308 destination[writeIndex] = narrowPrecisionToFloat(sample); 309 } 310 writeIndex++; 311 312 virtualReadIndex += pitchRate; 313 314 // Wrap-around, retaining sub-sample position since virtualReadIndex is floating-point. 315 if (virtualReadIndex >= virtualEndFrame) { 316 virtualReadIndex -= virtualDeltaFrames; 317 if (renderSilenceAndFinishIfNotLooping(bus, writeIndex, framesToProcess)) 318 break; 319 } 320 } 321 } 322 323 bus->clearSilentFlag(); 324 325 m_virtualReadIndex = virtualReadIndex; 326 327 return true; 328 } 329 330 331 void AudioBufferSourceNode::setBuffer(AudioBuffer* buffer, ExceptionState& exceptionState) 332 { 333 ASSERT(isMainThread()); 334 335 // The context must be locked since changing the buffer can re-configure the number of channels that are output. 336 AudioContext::AutoLocker contextLocker(context()); 337 338 // This synchronizes with process(). 339 MutexLocker processLocker(m_processLock); 340 341 if (buffer) { 342 // Do any necesssary re-configuration to the buffer's number of channels. 343 unsigned numberOfChannels = buffer->numberOfChannels(); 344 345 if (numberOfChannels > AudioContext::maxNumberOfChannels()) { 346 exceptionState.throwTypeError("number of input channels (" + String::number(numberOfChannels) 347 + ") exceeds maximum (" 348 + String::number(AudioContext::maxNumberOfChannels()) + ")."); 349 return; 350 } 351 352 output(0)->setNumberOfChannels(numberOfChannels); 353 354 m_sourceChannels = adoptArrayPtr(new const float* [numberOfChannels]); 355 m_destinationChannels = adoptArrayPtr(new float* [numberOfChannels]); 356 357 for (unsigned i = 0; i < numberOfChannels; ++i) 358 m_sourceChannels[i] = buffer->getChannelData(i)->data(); 359 } 360 361 m_virtualReadIndex = 0; 362 m_buffer = buffer; 363 } 364 365 unsigned AudioBufferSourceNode::numberOfChannels() 366 { 367 return output(0)->numberOfChannels(); 368 } 369 370 void AudioBufferSourceNode::start(double when, ExceptionState& exceptionState) 371 { 372 AudioScheduledSourceNode::start(when, exceptionState); 373 } 374 375 void AudioBufferSourceNode::start(double when, double grainOffset, ExceptionState& exceptionState) 376 { 377 start(when, grainOffset, buffer() ? buffer()->duration() : 0, exceptionState); 378 } 379 380 void AudioBufferSourceNode::start(double when, double grainOffset, double grainDuration, ExceptionState& exceptionState) 381 { 382 ASSERT(isMainThread()); 383 384 if (m_playbackState != UNSCHEDULED_STATE) { 385 exceptionState.throwDOMException( 386 InvalidStateError, 387 "cannot call start more than once."); 388 return; 389 } 390 391 if (!std::isfinite(when) || (when < 0)) { 392 exceptionState.throwDOMException( 393 InvalidStateError, 394 "Start time must be a finite non-negative number: " + String::number(when)); 395 return; 396 } 397 398 if (!std::isfinite(grainOffset) || (grainOffset < 0)) { 399 exceptionState.throwDOMException( 400 InvalidStateError, 401 "Offset must be a finite non-negative number: " + String::number(grainOffset)); 402 return; 403 } 404 405 if (!std::isfinite(grainDuration) || (grainDuration < 0)) { 406 exceptionState.throwDOMException( 407 InvalidStateError, 408 "Duration must be a finite non-negative number: " + String::number(grainDuration)); 409 return; 410 } 411 412 if (!buffer()) 413 return; 414 415 // Do sanity checking of grain parameters versus buffer size. 416 double bufferDuration = buffer()->duration(); 417 418 grainOffset = std::max(0.0, grainOffset); 419 grainOffset = std::min(bufferDuration, grainOffset); 420 m_grainOffset = grainOffset; 421 422 double maxDuration = bufferDuration - grainOffset; 423 424 grainDuration = std::max(0.0, grainDuration); 425 grainDuration = std::min(maxDuration, grainDuration); 426 m_grainDuration = grainDuration; 427 428 m_isGrain = true; 429 m_startTime = when; 430 431 // We call timeToSampleFrame here since at playbackRate == 1 we don't want to go through linear interpolation 432 // at a sub-sample position since it will degrade the quality. 433 // When aligned to the sample-frame the playback will be identical to the PCM data stored in the buffer. 434 // Since playbackRate == 1 is very common, it's worth considering quality. 435 m_virtualReadIndex = AudioUtilities::timeToSampleFrame(m_grainOffset, buffer()->sampleRate()); 436 437 m_playbackState = SCHEDULED_STATE; 438 } 439 440 double AudioBufferSourceNode::totalPitchRate() 441 { 442 double dopplerRate = 1.0; 443 if (m_pannerNode) 444 dopplerRate = m_pannerNode->dopplerRate(); 445 446 // Incorporate buffer's sample-rate versus AudioContext's sample-rate. 447 // Normally it's not an issue because buffers are loaded at the AudioContext's sample-rate, but we can handle it in any case. 448 double sampleRateFactor = 1.0; 449 if (buffer()) 450 sampleRateFactor = buffer()->sampleRate() / sampleRate(); 451 452 double basePitchRate = playbackRate()->value(); 453 454 double totalRate = dopplerRate * sampleRateFactor * basePitchRate; 455 456 // Sanity check the total rate. It's very important that the resampler not get any bad rate values. 457 totalRate = std::max(0.0, totalRate); 458 if (!totalRate) 459 totalRate = 1; // zero rate is considered illegal 460 totalRate = std::min(MaxRate, totalRate); 461 462 bool isTotalRateValid = !std::isnan(totalRate) && !std::isinf(totalRate); 463 ASSERT(isTotalRateValid); 464 if (!isTotalRateValid) 465 totalRate = 1.0; 466 467 return totalRate; 468 } 469 470 bool AudioBufferSourceNode::propagatesSilence() const 471 { 472 return !isPlayingOrScheduled() || hasFinished() || !m_buffer; 473 } 474 475 void AudioBufferSourceNode::setPannerNode(PannerNode* pannerNode) 476 { 477 if (m_pannerNode != pannerNode && !hasFinished()) { 478 PannerNode* oldPannerNode(m_pannerNode.release()); 479 m_pannerNode = pannerNode; 480 if (pannerNode) 481 pannerNode->makeConnection(); 482 if (oldPannerNode) 483 oldPannerNode->breakConnection(); 484 } 485 } 486 487 void AudioBufferSourceNode::clearPannerNode() 488 { 489 if (m_pannerNode) { 490 m_pannerNode->breakConnection(); 491 m_pannerNode.clear(); 492 } 493 } 494 495 void AudioBufferSourceNode::finish() 496 { 497 clearPannerNode(); 498 ASSERT(!m_pannerNode); 499 AudioScheduledSourceNode::finish(); 500 } 501 502 void AudioBufferSourceNode::trace(Visitor* visitor) 503 { 504 visitor->trace(m_buffer); 505 visitor->trace(m_playbackRate); 506 visitor->trace(m_pannerNode); 507 AudioScheduledSourceNode::trace(visitor); 508 } 509 510 } // namespace blink 511 512 #endif // ENABLE(WEB_AUDIO) 513