16b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner/*
26b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner * Copyright (C) 2010, Google Inc. All rights reserved.
36b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner *
46b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner * Redistribution and use in source and binary forms, with or without
56b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner * modification, are permitted provided that the following conditions
66b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner * are met:
76b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner * 1.  Redistributions of source code must retain the above copyright
86b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner *    notice, this list of conditions and the following disclaimer.
96b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner * 2.  Redistributions in binary form must reproduce the above copyright
106b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner *    notice, this list of conditions and the following disclaimer in the
116b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner *    documentation and/or other materials provided with the distribution.
126b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner *
136b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
146b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
156b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
166b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
176b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
186b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
196b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
206b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
216b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
226b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
236b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner */
246b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
256b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#include "config.h"
266b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
276b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#if ENABLE(WEB_AUDIO)
286b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
296b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#include "JavaScriptAudioNode.h"
306b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
316b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#include "AudioBuffer.h"
326b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#include "AudioBus.h"
336b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#include "AudioContext.h"
346b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#include "AudioNodeInput.h"
356b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#include "AudioNodeOutput.h"
366b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#include "AudioProcessingEvent.h"
376b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#include "Document.h"
386b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#include "Float32Array.h"
396b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#include <wtf/MainThread.h>
406b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
416b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennernamespace WebCore {
426b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
436b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennerconst size_t DefaultBufferSize = 4096;
446b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
456b70adc33054f8aee8c54d0f460458a9df11b8a5Russell BrennerPassRefPtr<JavaScriptAudioNode> JavaScriptAudioNode::create(AudioContext* context, double sampleRate, size_t bufferSize, unsigned numberOfInputs, unsigned numberOfOutputs)
466b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner{
476b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    return adoptRef(new JavaScriptAudioNode(context, sampleRate, bufferSize, numberOfInputs, numberOfOutputs));
486b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner}
496b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
506b70adc33054f8aee8c54d0f460458a9df11b8a5Russell BrennerJavaScriptAudioNode::JavaScriptAudioNode(AudioContext* context, double sampleRate, size_t bufferSize, unsigned numberOfInputs, unsigned numberOfOutputs)
516b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    : AudioNode(context, sampleRate)
526b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    , m_doubleBufferIndex(0)
536b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    , m_doubleBufferIndexForEvent(0)
546b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    , m_bufferSize(bufferSize)
556b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    , m_bufferReadWriteIndex(0)
566b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    , m_isRequestOutstanding(false)
576b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner{
586b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    // Check for valid buffer size.
596b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    switch (bufferSize) {
606b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    case 256:
616b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    case 512:
626b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    case 1024:
636b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    case 2048:
646b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    case 4096:
656b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    case 8192:
666b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    case 16384:
676b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        m_bufferSize = bufferSize;
686b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        break;
696b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    default:
706b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        m_bufferSize = DefaultBufferSize;
716b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    }
726b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
736b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    // Regardless of the allowed buffer sizes above, we still need to process at the granularity of the AudioNode.
746b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    if (m_bufferSize < AudioNode::ProcessingSizeInFrames)
756b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        m_bufferSize = AudioNode::ProcessingSizeInFrames;
766b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
776b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    // FIXME: Right now we're hardcoded to single input and single output.
786b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    // Although the specification says this is OK for a simple implementation, multiple inputs and outputs would be good.
796b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    ASSERT_UNUSED(numberOfInputs, numberOfInputs == 1);
806b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    ASSERT_UNUSED(numberOfOutputs, numberOfOutputs == 1);
816b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    addInput(adoptPtr(new AudioNodeInput(this)));
826b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    addOutput(adoptPtr(new AudioNodeOutput(this, 2)));
836b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
846b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    setType(NodeTypeJavaScript);
856b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
866b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    initialize();
876b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner}
886b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
896b70adc33054f8aee8c54d0f460458a9df11b8a5Russell BrennerJavaScriptAudioNode::~JavaScriptAudioNode()
906b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner{
916b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    uninitialize();
926b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner}
936b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
946b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid JavaScriptAudioNode::initialize()
956b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner{
966b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    if (isInitialized())
976b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        return;
986b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
996b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    double sampleRate = context()->sampleRate();
1006b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
1016b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    // Create double buffers on both the input and output sides.
1026b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    // These AudioBuffers will be directly accessed in the main thread by JavaScript.
1036b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    for (unsigned i = 0; i < 2; ++i) {
1046b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        m_inputBuffers.append(AudioBuffer::create(2, bufferSize(), sampleRate));
1056b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        m_outputBuffers.append(AudioBuffer::create(2, bufferSize(), sampleRate));
1066b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    }
1076b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
1086b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    AudioNode::initialize();
1096b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner}
1106b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
1116b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid JavaScriptAudioNode::uninitialize()
1126b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner{
1136b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    if (!isInitialized())
1146b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        return;
1156b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
1166b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    m_inputBuffers.clear();
1176b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    m_outputBuffers.clear();
1186b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
1196b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    AudioNode::uninitialize();
1206b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner}
1216b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
1226b70adc33054f8aee8c54d0f460458a9df11b8a5Russell BrennerJavaScriptAudioNode* JavaScriptAudioNode::toJavaScriptAudioNode()
1236b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner{
1246b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    return this;
1256b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner}
1266b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
1276b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid JavaScriptAudioNode::process(size_t framesToProcess)
1286b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner{
1296b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    // Discussion about inputs and outputs:
1306b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    // As in other AudioNodes, JavaScriptAudioNode uses an AudioBus for its input and output (see inputBus and outputBus below).
1316b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    // Additionally, there is a double-buffering for input and output which is exposed directly to JavaScript (see inputBuffer and outputBuffer below).
1326b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    // This node is the producer for inputBuffer and the consumer for outputBuffer.
1336b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    // The JavaScript code is the consumer of inputBuffer and the producer for outputBuffer.
1346b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
1356b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    // Get input and output busses.
1366b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    AudioBus* inputBus = this->input(0)->bus();
1376b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    AudioBus* outputBus = this->output(0)->bus();
1386b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
1396b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    // Get input and output buffers.  We double-buffer both the input and output sides.
1406b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    unsigned doubleBufferIndex = this->doubleBufferIndex();
1416b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    bool isDoubleBufferIndexGood = doubleBufferIndex < 2 && doubleBufferIndex < m_inputBuffers.size() && doubleBufferIndex < m_outputBuffers.size();
1426b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    ASSERT(isDoubleBufferIndexGood);
1436b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    if (!isDoubleBufferIndexGood)
1446b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        return;
1456b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
1466b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    AudioBuffer* inputBuffer = m_inputBuffers[doubleBufferIndex].get();
1476b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    AudioBuffer* outputBuffer = m_outputBuffers[doubleBufferIndex].get();
1486b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
1496b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    // Check the consistency of input and output buffers.
1506b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    bool buffersAreGood = inputBuffer && outputBuffer && bufferSize() == inputBuffer->length() && bufferSize() == outputBuffer->length()
1516b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        && m_bufferReadWriteIndex + framesToProcess <= bufferSize();
1526b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    ASSERT(buffersAreGood);
1536b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    if (!buffersAreGood)
1546b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        return;
1556b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
1566b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    // We assume that bufferSize() is evenly divisible by framesToProcess - should always be true, but we should still check.
1576b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    bool isFramesToProcessGood = framesToProcess && bufferSize() >= framesToProcess && !(bufferSize() % framesToProcess);
1586b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    ASSERT(isFramesToProcessGood);
1596b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    if (!isFramesToProcessGood)
1606b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        return;
1616b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
1626b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    unsigned numberOfInputChannels = inputBus->numberOfChannels();
1636b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
1646b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    bool channelsAreGood = (numberOfInputChannels == 1 || numberOfInputChannels == 2) && outputBus->numberOfChannels() == 2;
1656b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    ASSERT(channelsAreGood);
1666b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    if (!channelsAreGood)
1676b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        return;
1686b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
1696b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    float* sourceL = inputBus->channel(0)->data();
1706b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    float* sourceR = numberOfInputChannels > 1 ? inputBus->channel(1)->data() : 0;
1716b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    float* destinationL = outputBus->channel(0)->data();
1726b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    float* destinationR = outputBus->channel(1)->data();
1736b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
1746b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    // Copy from the input to the input buffer.  See "buffersAreGood" check above for safety.
1756b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    size_t bytesToCopy = sizeof(float) * framesToProcess;
1766b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    memcpy(inputBuffer->getChannelData(0)->data() + m_bufferReadWriteIndex, sourceL, bytesToCopy);
1776b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
1786b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    if (numberOfInputChannels == 2)
1796b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        memcpy(inputBuffer->getChannelData(1)->data() + m_bufferReadWriteIndex, sourceR, bytesToCopy);
1806b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    else if (numberOfInputChannels == 1) {
1816b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        // If the input is mono, then also copy the mono input to the right channel of the AudioBuffer which the AudioProcessingEvent uses.
1826b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        // FIXME: it is likely the audio API will evolve to present an AudioBuffer with the same number of channels as our input.
1836b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        memcpy(inputBuffer->getChannelData(1)->data() + m_bufferReadWriteIndex, sourceL, bytesToCopy);
1846b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    }
1856b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
1866b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    // Copy from the output buffer to the output.  See "buffersAreGood" check above for safety.
1876b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    memcpy(destinationL, outputBuffer->getChannelData(0)->data() + m_bufferReadWriteIndex, bytesToCopy);
1886b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    memcpy(destinationR, outputBuffer->getChannelData(1)->data() + m_bufferReadWriteIndex, bytesToCopy);
1896b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
1906b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    // Update the buffering index.
1916b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    m_bufferReadWriteIndex = (m_bufferReadWriteIndex + framesToProcess) % bufferSize();
1926b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
1936b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    // m_bufferReadWriteIndex will wrap back around to 0 when the current input and output buffers are full.
1946b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    // When this happens, fire an event and swap buffers.
1956b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    if (!m_bufferReadWriteIndex) {
1966b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        // Avoid building up requests on the main thread to fire process events when they're not being handled.
1976b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        // This could be a problem if the main thread is very busy doing other things and is being held up handling previous requests.
1986b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        if (m_isRequestOutstanding) {
1996b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner            // We're late in handling the previous request.  The main thread must be very busy.
2006b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner            // The best we can do is clear out the buffer ourself here.
2016b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner            outputBuffer->zero();
2026b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        } else {
2036b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner            // Reference ourself so we don't accidentally get deleted before fireProcessEvent() gets called.
2046b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner            ref();
2056b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
2066b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner            // Fire the event on the main thread, not this one (which is the realtime audio thread).
2076b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner            m_doubleBufferIndexForEvent = m_doubleBufferIndex;
2086b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner            m_isRequestOutstanding = true;
20981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            callOnMainThread(fireProcessEventDispatch, this);
2106b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        }
2116b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
2126b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        swapBuffers();
2136b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    }
2146b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner}
2156b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
2166b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid JavaScriptAudioNode::fireProcessEventDispatch(void* userData)
2176b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner{
2186b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    JavaScriptAudioNode* jsAudioNode = static_cast<JavaScriptAudioNode*>(userData);
2196b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    ASSERT(jsAudioNode);
2206b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    if (!jsAudioNode)
2216b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        return;
2226b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
2236b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    jsAudioNode->fireProcessEvent();
2246b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
2256b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    // De-reference to match the ref() call in process().
2266b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    jsAudioNode->deref();
2276b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner}
2286b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
2296b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid JavaScriptAudioNode::fireProcessEvent()
2306b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner{
2316b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    ASSERT(isMainThread() && m_isRequestOutstanding);
2326b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
2336b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    bool isIndexGood = m_doubleBufferIndexForEvent < 2;
2346b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    ASSERT(isIndexGood);
2356b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    if (!isIndexGood)
2366b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        return;
2376b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
2386b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    AudioBuffer* inputBuffer = m_inputBuffers[m_doubleBufferIndexForEvent].get();
2396b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    AudioBuffer* outputBuffer = m_outputBuffers[m_doubleBufferIndexForEvent].get();
2406b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    ASSERT(inputBuffer && outputBuffer);
2416b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    if (!inputBuffer || !outputBuffer)
2426b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        return;
2436b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
2446b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    // Avoid firing the event if the document has already gone away.
2456b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    if (context()->hasDocument()) {
2466b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        // Let the audio thread know we've gotten to the point where it's OK for it to make another request.
2476b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        m_isRequestOutstanding = false;
2486b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
2496b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        // Call the JavaScript event handler which will do the audio processing.
2506b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        dispatchEvent(AudioProcessingEvent::create(inputBuffer, outputBuffer));
2516b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    }
2526b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner}
2536b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
2546b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid JavaScriptAudioNode::reset()
2556b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner{
2566b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    m_bufferReadWriteIndex = 0;
2576b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    m_doubleBufferIndex = 0;
2586b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
2596b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    for (unsigned i = 0; i < 2; ++i) {
2606b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        m_inputBuffers[i]->zero();
2616b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        m_outputBuffers[i]->zero();
2626b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    }
2636b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner}
2646b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
2656b70adc33054f8aee8c54d0f460458a9df11b8a5Russell BrennerScriptExecutionContext* JavaScriptAudioNode::scriptExecutionContext() const
2666b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner{
2676b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    return const_cast<JavaScriptAudioNode*>(this)->context()->document();
2686b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner}
2696b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
2706b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner} // namespace WebCore
2716b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
2726b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#endif // ENABLE(WEB_AUDIO)
273