15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/* 25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2010, Google Inc. All rights reserved. 35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without 55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions 65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * are met: 75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 1. Redistributions of source code must retain the above copyright 85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * notice, this list of conditions and the following disclaimer. 95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 2. Redistributions in binary form must reproduce the above copyright 105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * notice, this list of conditions and the following disclaimer in the 115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * documentation and/or other materials provided with the distribution. 125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY 145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY 175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */ 245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h" 265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#if ENABLE(WEB_AUDIO) 285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "modules/webaudio/AudioBufferSourceNode.h" 3053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 31197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "bindings/core/v8/ExceptionState.h" 3219cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)#include "core/dom/ExceptionCode.h" 331e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/audio/AudioUtilities.h" 3453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "modules/webaudio/AudioContext.h" 3553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "modules/webaudio/AudioNodeOutput.h" 361e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/FloatConversion.h" 3753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "wtf/MainThread.h" 3853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "wtf/MathExtras.h" 391e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include <algorithm> 405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 41c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink { 425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)const double DefaultGrainDuration = 0.020; // 20ms 445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Arbitrary upper limit on playback rate. 465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Higher than expected rates can be useful when playing back oversampled buffers 475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// to minimize linear interpolation aliasing. 485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)const double MaxRate = 1024; 495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 509e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)AudioBufferSourceNode* AudioBufferSourceNode::create(AudioContext* context, float sampleRate) 515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 529e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) return adoptRefCountedGarbageCollectedWillBeNoop(new AudioBufferSourceNode(context, sampleRate)); 535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)AudioBufferSourceNode::AudioBufferSourceNode(AudioContext* context, float sampleRate) 565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) : AudioScheduledSourceNode(context, sampleRate) 57d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) , m_buffer(nullptr) 585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_isLooping(false) 595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_loopStart(0) 605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_loopEnd(0) 615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_virtualReadIndex(0) 625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_isGrain(false) 635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_grainOffset(0.0) 645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_grainDuration(DefaultGrainDuration) 655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) setNodeType(NodeTypeAudioBufferSource); 675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 68c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) m_playbackRate = AudioParam::create(context, 1.0); 69926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 70197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // Default to mono. A call to setBuffer() will set the number of output 71197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // channels to that of the buffer. 72197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch addOutput(AudioNodeOutput::create(this, 1)); 735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) initialize(); 755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)AudioBufferSourceNode::~AudioBufferSourceNode() 785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 79c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) ASSERT(!isInitialized()); 80c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} 81c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 82c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void AudioBufferSourceNode::dispose() 83c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles){ 845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) clearPannerNode(); 855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) uninitialize(); 86c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) AudioScheduledSourceNode::dispose(); 875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void AudioBufferSourceNode::process(size_t framesToProcess) 905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) AudioBus* outputBus = output(0)->bus(); 925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!isInitialized()) { 945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) outputBus->zero(); 955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // The audio thread can't block on this lock, so we call tryLock() instead. 995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) MutexTryLocker tryLocker(m_processLock); 1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (tryLocker.locked()) { 1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!buffer()) { 1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) outputBus->zero(); 1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 106926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // After calling setBuffer() with a buffer having a different number of channels, there can in rare cases be a slight delay 107926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // before the output bus is updated to the new number of channels because of use of tryLocks() in the context's updating system. 108926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // In this case, if the the buffer has just been changed and we're not quite ready yet, then just output silence. 109926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (numberOfChannels() != buffer()->numberOfChannels()) { 110926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) outputBus->zero(); 111926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return; 112926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 113926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) size_t quantumFrameOffset; 1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) size_t bufferFramesToProcess; 1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) updateSchedulingInfo(framesToProcess, 1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) outputBus, 1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) quantumFrameOffset, 1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bufferFramesToProcess); 12102772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!bufferFramesToProcess) { 1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) outputBus->zero(); 1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (unsigned i = 0; i < outputBus->numberOfChannels(); ++i) 1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_destinationChannels[i] = outputBus->channel(i)->mutableData(); 1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Render by reading directly from the buffer. 1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!renderFromBuffer(outputBus, quantumFrameOffset, bufferFramesToProcess)) { 1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) outputBus->zero(); 1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) outputBus->clearSilentFlag(); 1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Too bad - the tryLock() failed. We must be in the middle of changing buffers and were already outputting silence anyway. 1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) outputBus->zero(); 1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Returns true if we're finished. 1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool AudioBufferSourceNode::renderSilenceAndFinishIfNotLooping(AudioBus*, unsigned index, size_t framesToProcess) 1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!loop()) { 1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // If we're not looping, then stop playing when we get to the end. 1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (framesToProcess > 0) { 1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // We're not looping and we've reached the end of the sample data, but we still need to provide more output, 1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // so generate silence for the remaining. 15202772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch for (unsigned i = 0; i < numberOfChannels(); ++i) 1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) memset(m_destinationChannels[i] + index, 0, sizeof(float) * framesToProcess); 1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) finish(); 1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool AudioBufferSourceNode::renderFromBuffer(AudioBus* bus, unsigned destinationFrameOffset, size_t numberOfFrames) 1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(context()->isAudioThread()); 165926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Basic sanity checking 1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(bus); 1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(buffer()); 1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!bus || !buffer()) 1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unsigned numberOfChannels = this->numberOfChannels(); 1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unsigned busNumberOfChannels = bus->numberOfChannels(); 1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool channelCountGood = numberOfChannels && numberOfChannels == busNumberOfChannels; 1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(channelCountGood); 1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!channelCountGood) 1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Sanity check destinationFrameOffset, numberOfFrames. 1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) size_t destinationLength = bus->length(); 1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool isLengthGood = destinationLength <= 4096 && numberOfFrames <= 4096; 1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(isLengthGood); 1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!isLengthGood) 1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool isOffsetGood = destinationFrameOffset <= destinationLength && destinationFrameOffset + numberOfFrames <= destinationLength; 1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(isOffsetGood); 1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!isOffsetGood) 1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Potentially zero out initial frames leading up to the offset. 1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (destinationFrameOffset) { 19502772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch for (unsigned i = 0; i < numberOfChannels; ++i) 1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) memset(m_destinationChannels[i], 0, sizeof(float) * destinationFrameOffset); 1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Offset the pointers to the correct offset frame. 2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unsigned writeIndex = destinationFrameOffset; 2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) size_t bufferLength = buffer()->length(); 2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) double bufferSampleRate = buffer()->sampleRate(); 2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Avoid converting from time to sample-frames twice by computing 2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // the grain end time first before computing the sample frame. 2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unsigned endFrame = m_isGrain ? AudioUtilities::timeToSampleFrame(m_grainOffset + m_grainDuration, bufferSampleRate) : bufferLength; 20802772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // This is a HACK to allow for HRTF tail-time - avoids glitch at end. 2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // FIXME: implement tailTime for each AudioNode for a more general solution to this problem. 2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // https://bugs.webkit.org/show_bug.cgi?id=77224 2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_isGrain) 2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) endFrame += 512; 2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Do some sanity checking. 2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (endFrame > bufferLength) 2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) endFrame = bufferLength; 2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_virtualReadIndex >= endFrame) 2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_virtualReadIndex = 0; // reset to start 2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // If the .loop attribute is true, then values of m_loopStart == 0 && m_loopEnd == 0 implies 2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // that we should use the entire buffer as the loop, otherwise use the loop values in m_loopStart and m_loopEnd. 2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) double virtualEndFrame = endFrame; 2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) double virtualDeltaFrames = endFrame; 2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (loop() && (m_loopStart || m_loopEnd) && m_loopStart >= 0 && m_loopEnd > 0 && m_loopStart < m_loopEnd) { 2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Convert from seconds to sample-frames. 2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) double loopStartFrame = m_loopStart * buffer()->sampleRate(); 2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) double loopEndFrame = m_loopEnd * buffer()->sampleRate(); 2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 231197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch virtualEndFrame = std::min(loopEndFrame, virtualEndFrame); 2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) virtualDeltaFrames = virtualEndFrame - loopStartFrame; 2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) double pitchRate = totalPitchRate(); 2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Sanity check that our playback rate isn't larger than the loop size. 2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (pitchRate >= virtualDeltaFrames) 2405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Get local copy. 2435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) double virtualReadIndex = m_virtualReadIndex; 2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Render loop - reading from the source buffer to the destination using linear interpolation. 2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int framesToProcess = numberOfFrames; 2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const float** sourceChannels = m_sourceChannels.get(); 2495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float** destinationChannels = m_destinationChannels.get(); 2505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Optimize for the very common case of playing back with pitchRate == 1. 2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // We can avoid the linear interpolation. 2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (pitchRate == 1 && virtualReadIndex == floor(virtualReadIndex) 2545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) && virtualDeltaFrames == floor(virtualDeltaFrames) 2555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) && virtualEndFrame == floor(virtualEndFrame)) { 2565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unsigned readIndex = static_cast<unsigned>(virtualReadIndex); 2575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unsigned deltaFrames = static_cast<unsigned>(virtualDeltaFrames); 2585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) endFrame = static_cast<unsigned>(virtualEndFrame); 2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while (framesToProcess > 0) { 2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int framesToEnd = endFrame - readIndex; 261197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch int framesThisTime = std::min(framesToProcess, framesToEnd); 262197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch framesThisTime = std::max(0, framesThisTime); 2635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 26402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch for (unsigned i = 0; i < numberOfChannels; ++i) 2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) memcpy(destinationChannels[i] + writeIndex, sourceChannels[i] + readIndex, sizeof(float) * framesThisTime); 2665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) writeIndex += framesThisTime; 2685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) readIndex += framesThisTime; 2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) framesToProcess -= framesThisTime; 2705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Wrap-around. 2725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (readIndex >= endFrame) { 2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) readIndex -= deltaFrames; 2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (renderSilenceAndFinishIfNotLooping(bus, writeIndex, framesToProcess)) 2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) virtualReadIndex = readIndex; 2795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 2805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while (framesToProcess--) { 2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unsigned readIndex = static_cast<unsigned>(virtualReadIndex); 2825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) double interpolationFactor = virtualReadIndex - readIndex; 2835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // For linear interpolation we need the next sample-frame too. 2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unsigned readIndex2 = readIndex + 1; 2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (readIndex2 >= bufferLength) { 2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (loop()) { 2885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Make sure to wrap around at the end of the buffer. 2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) readIndex2 = static_cast<unsigned>(virtualReadIndex + 1 - virtualDeltaFrames); 2905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else 2915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) readIndex2 = readIndex; 2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Final sanity check on buffer access. 2955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // FIXME: as an optimization, try to get rid of this inner-loop check and put assertions and guards before the loop. 2965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (readIndex >= bufferLength || readIndex2 >= bufferLength) 2975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 2985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Linear interpolation. 3005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (unsigned i = 0; i < numberOfChannels; ++i) { 3015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float* destination = destinationChannels[i]; 3025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const float* source = sourceChannels[i]; 3035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) double sample1 = source[readIndex]; 3055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) double sample2 = source[readIndex2]; 3065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) double sample = (1.0 - interpolationFactor) * sample1 + interpolationFactor * sample2; 3075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) destination[writeIndex] = narrowPrecisionToFloat(sample); 3095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) writeIndex++; 3115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) virtualReadIndex += pitchRate; 3135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Wrap-around, retaining sub-sample position since virtualReadIndex is floating-point. 3155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (virtualReadIndex >= virtualEndFrame) { 3165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) virtualReadIndex -= virtualDeltaFrames; 3175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (renderSilenceAndFinishIfNotLooping(bus, writeIndex, framesToProcess)) 3185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 3195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bus->clearSilentFlag(); 3245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_virtualReadIndex = virtualReadIndex; 3265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 3285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 33151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)void AudioBufferSourceNode::setBuffer(AudioBuffer* buffer, ExceptionState& exceptionState) 3325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 3335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(isMainThread()); 33402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 3355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // The context must be locked since changing the buffer can re-configure the number of channels that are output. 3365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) AudioContext::AutoLocker contextLocker(context()); 33702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 3385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // This synchronizes with process(). 3395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) MutexLocker processLocker(m_processLock); 34002772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 3415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (buffer) { 3425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Do any necesssary re-configuration to the buffer's number of channels. 3435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unsigned numberOfChannels = buffer->numberOfChannels(); 3445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3451e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) if (numberOfChannels > AudioContext::maxNumberOfChannels()) { 34651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) exceptionState.throwTypeError("number of input channels (" + String::number(numberOfChannels) 3471e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) + ") exceeds maximum (" 3481e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) + String::number(AudioContext::maxNumberOfChannels()) + ")."); 3491e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) return; 3501e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) } 3515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) output(0)->setNumberOfChannels(numberOfChannels); 3535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_sourceChannels = adoptArrayPtr(new const float* [numberOfChannels]); 3555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_destinationChannels = adoptArrayPtr(new float* [numberOfChannels]); 3565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 35702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch for (unsigned i = 0; i < numberOfChannels; ++i) 3585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_sourceChannels[i] = buffer->getChannelData(i)->data(); 3595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_virtualReadIndex = 0; 3625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_buffer = buffer; 3635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)unsigned AudioBufferSourceNode::numberOfChannels() 3665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 3675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return output(0)->numberOfChannels(); 3685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 37051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)void AudioBufferSourceNode::start(double when, ExceptionState& exceptionState) 371f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles){ 372d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) AudioScheduledSourceNode::start(when, exceptionState); 373f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)} 374f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) 37551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)void AudioBufferSourceNode::start(double when, double grainOffset, ExceptionState& exceptionState) 376f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles){ 377d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) start(when, grainOffset, buffer() ? buffer()->duration() : 0, exceptionState); 378f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)} 379f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) 38051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)void AudioBufferSourceNode::start(double when, double grainOffset, double grainDuration, ExceptionState& exceptionState) 38119cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles){ 3825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(isMainThread()); 3835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 38419cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) if (m_playbackState != UNSCHEDULED_STATE) { 38551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) exceptionState.throwDOMException( 38619cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) InvalidStateError, 387a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) "cannot call start more than once."); 3885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 38919cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) } 3905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3917242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci if (!std::isfinite(when) || (when < 0)) { 3927242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci exceptionState.throwDOMException( 3937242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci InvalidStateError, 3947242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci "Start time must be a finite non-negative number: " + String::number(when)); 3957242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci return; 3967242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci } 3977242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 3987242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci if (!std::isfinite(grainOffset) || (grainOffset < 0)) { 3997242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci exceptionState.throwDOMException( 4007242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci InvalidStateError, 4017242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci "Offset must be a finite non-negative number: " + String::number(grainOffset)); 4027242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci return; 4037242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci } 4047242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 4057242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci if (!std::isfinite(grainDuration) || (grainDuration < 0)) { 4067242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci exceptionState.throwDOMException( 4077242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci InvalidStateError, 4087242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci "Duration must be a finite non-negative number: " + String::number(grainDuration)); 4097242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci return; 4107242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci } 4117242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 4125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!buffer()) 4135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 41402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 415d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) // Do sanity checking of grain parameters versus buffer size. 416d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) double bufferDuration = buffer()->duration(); 4175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 418197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch grainOffset = std::max(0.0, grainOffset); 419197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch grainOffset = std::min(bufferDuration, grainOffset); 420d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) m_grainOffset = grainOffset; 4215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 422d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) double maxDuration = bufferDuration - grainOffset; 4235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 424197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch grainDuration = std::max(0.0, grainDuration); 425197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch grainDuration = std::min(maxDuration, grainDuration); 426d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) m_grainDuration = grainDuration; 427f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) 428d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) m_isGrain = true; 4295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_startTime = when; 43002772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 4315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // We call timeToSampleFrame here since at playbackRate == 1 we don't want to go through linear interpolation 4325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // at a sub-sample position since it will degrade the quality. 4335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // When aligned to the sample-frame the playback will be identical to the PCM data stored in the buffer. 4345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Since playbackRate == 1 is very common, it's worth considering quality. 4355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_virtualReadIndex = AudioUtilities::timeToSampleFrame(m_grainOffset, buffer()->sampleRate()); 43602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 4375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_playbackState = SCHEDULED_STATE; 4385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 4395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)double AudioBufferSourceNode::totalPitchRate() 4415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 4425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) double dopplerRate = 1.0; 4435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_pannerNode) 4445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) dopplerRate = m_pannerNode->dopplerRate(); 44502772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 4465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Incorporate buffer's sample-rate versus AudioContext's sample-rate. 4475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Normally it's not an issue because buffers are loaded at the AudioContext's sample-rate, but we can handle it in any case. 4485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) double sampleRateFactor = 1.0; 4495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (buffer()) 4505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) sampleRateFactor = buffer()->sampleRate() / sampleRate(); 45102772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 4525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) double basePitchRate = playbackRate()->value(); 4535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) double totalRate = dopplerRate * sampleRateFactor * basePitchRate; 4555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Sanity check the total rate. It's very important that the resampler not get any bad rate values. 457197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch totalRate = std::max(0.0, totalRate); 4585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!totalRate) 4595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) totalRate = 1; // zero rate is considered illegal 460197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch totalRate = std::min(MaxRate, totalRate); 46102772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 462926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) bool isTotalRateValid = !std::isnan(totalRate) && !std::isinf(totalRate); 4635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(isTotalRateValid); 4645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!isTotalRateValid) 4655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) totalRate = 1.0; 4665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return totalRate; 4685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 4695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool AudioBufferSourceNode::propagatesSilence() const 4715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 4725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return !isPlayingOrScheduled() || hasFinished() || !m_buffer; 4735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 4745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void AudioBufferSourceNode::setPannerNode(PannerNode* pannerNode) 4765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 4775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_pannerNode != pannerNode && !hasFinished()) { 4789e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) PannerNode* oldPannerNode(m_pannerNode.release()); 4795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_pannerNode = pannerNode; 480197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch if (pannerNode) 481197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch pannerNode->makeConnection(); 482197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch if (oldPannerNode) 483197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch oldPannerNode->breakConnection(); 4845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 4855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 4865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void AudioBufferSourceNode::clearPannerNode() 4885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 4895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_pannerNode) { 490197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch m_pannerNode->breakConnection(); 491197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch m_pannerNode.clear(); 4925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 4935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 4945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void AudioBufferSourceNode::finish() 4965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 4975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) clearPannerNode(); 4985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(!m_pannerNode); 4995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) AudioScheduledSourceNode::finish(); 5005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 5015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 502323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)void AudioBufferSourceNode::trace(Visitor* visitor) 503323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles){ 504323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) visitor->trace(m_buffer); 505323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) visitor->trace(m_playbackRate); 506c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) visitor->trace(m_pannerNode); 507323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) AudioScheduledSourceNode::trace(visitor); 508323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)} 509323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) 510c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} // namespace blink 5115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif // ENABLE(WEB_AUDIO) 513