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