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) *
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 1.  Redistributions of source code must retain the above copyright
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     notice, this list of conditions and the following disclaimer.
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 2.  Redistributions in binary form must reproduce the above copyright
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     notice, this list of conditions and the following disclaimer in the
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     documentation and/or other materials provided with the distribution.
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     its contributors may be used to endorse or promote products derived
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     from this software without specific prior written permission.
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h"
305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#if ENABLE(WEB_AUDIO)
325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
331e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/audio/ReverbConvolver.h"
345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)#include "platform/Task.h"
361e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/audio/AudioBus.h"
371e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/audio/VectorMath.h"
3851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)#include "public/platform/Platform.h"
3951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)#include "public/platform/WebThread.h"
405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
41c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink {
425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)using namespace VectorMath;
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)const int InputBufferSize = 8 * 16384;
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// We only process the leading portion of the impulse response in the real-time thread.  We don't exceed this length.
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// It turns out then, that the background thread has about 278msec of scheduling slop.
495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Empirically, this has been found to be a good compromise between giving enough time for scheduling slop,
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// while still minimizing the amount of processing done in the primary (high-priority) thread.
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// This was found to be a good value on Mac OS X, and may work well on other platforms as well, assuming
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// the very rough scheduling latencies are similar on these time-scales.  Of course, this code may need to be
535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// tuned for individual platforms if this assumption is found to be incorrect.
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)const size_t RealtimeFrameLimit = 8192  + 4096; // ~278msec @ 44.1KHz
555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)const size_t MinFFTSize = 128;
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)const size_t MaxRealtimeFFTSize = 2048;
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)ReverbConvolver::ReverbConvolver(AudioChannel* impulseResponse, size_t renderSliceSize, size_t maxFFTSize, size_t convolverRenderPhase, bool useBackgroundThreads)
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    : m_impulseResponseLength(impulseResponse->length())
615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_accumulationBuffer(impulseResponse->length() + renderSliceSize)
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_inputBuffer(InputBufferSize)
635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_minFFTSize(MinFFTSize) // First stage will have this size - successive stages will double in size each time
645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_maxFFTSize(maxFFTSize) // until we hit m_maxFFTSize
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // If we are using background threads then don't exceed this FFT size for the
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // stages which run in the real-time thread.  This avoids having only one or two
685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // large stages (size 16384 or so) at the end which take a lot of time every several
695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // processing slices.  This way we amortize the cost over more processing slices.
705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_maxRealtimeFFTSize = MaxRealtimeFFTSize;
715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // For the moment, a good way to know if we have real-time constraint is to check if we're using background threads.
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Otherwise, assume we're being run from a command-line tool.
745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool hasRealtimeConstraint = useBackgroundThreads;
755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const float* response = impulseResponse->data();
775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    size_t totalResponseLength = impulseResponse->length();
785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // The total latency is zero because the direct-convolution is used in the leading portion.
805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    size_t reverbTotalLatency = 0;
815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    size_t stageOffset = 0;
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int i = 0;
845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    size_t fftSize = m_minFFTSize;
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (stageOffset < totalResponseLength) {
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        size_t stageSize = fftSize / 2;
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // For the last stage, it's possible that stageOffset is such that we're straddling the end
895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // of the impulse response buffer (if we use stageSize), so reduce the last stage's length...
905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (stageSize + stageOffset > totalResponseLength)
915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            stageSize = totalResponseLength - stageOffset;
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // This "staggers" the time when each FFT happens so they don't all happen at the same time
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        int renderPhase = convolverRenderPhase + i * renderSliceSize;
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        bool useDirectConvolver = !stageOffset;
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        OwnPtr<ReverbConvolverStage> stage = adoptPtr(new ReverbConvolverStage(response, totalResponseLength, reverbTotalLatency, stageOffset, stageSize, fftSize, renderPhase, renderSliceSize, &m_accumulationBuffer, useDirectConvolver));
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        bool isBackgroundStage = false;
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        if (useBackgroundThreads && stageOffset > RealtimeFrameLimit) {
1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            m_backgroundStages.append(stage.release());
1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            isBackgroundStage = true;
1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        } else
1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            m_stages.append(stage.release());
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        stageOffset += stageSize;
1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ++i;
1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!useDirectConvolver) {
1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Figure out next FFT size
1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            fftSize *= 2;
1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (hasRealtimeConstraint && !isBackgroundStage && fftSize > m_maxRealtimeFFTSize)
1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            fftSize = m_maxRealtimeFFTSize;
1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (fftSize > m_maxFFTSize)
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            fftSize = m_maxFFTSize;
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Start up background thread
1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // FIXME: would be better to up the thread priority here.  It doesn't need to be real-time, but higher than the default...
12451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    if (useBackgroundThreads && m_backgroundStages.size() > 0)
125e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)        m_backgroundThread = adoptPtr(Platform::current()->createThread("Reverb convolution background thread"));
1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)ReverbConvolver::~ReverbConvolver()
1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Wait for background thread to stop
13151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    m_backgroundThread.clear();
1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)void ReverbConvolver::processInBackground()
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
13651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    // Process all of the stages until their read indices reach the input buffer's write index
13751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    int writeIndex = m_inputBuffer.writeIndex();
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    // Even though it doesn't seem like every stage needs to maintain its own version of readIndex
14051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    // we do this in case we want to run in more than one background thread.
14151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    int readIndex;
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    while ((readIndex = m_backgroundStages[0]->inputReadIndex()) != writeIndex) { // FIXME: do better to detect buffer overrun...
14451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        // The ReverbConvolverStages need to process in amounts which evenly divide half the FFT size
14551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        const int SliceSize = MinFFTSize / 2;
1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        // Accumulate contributions from each stage
14851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        for (size_t i = 0; i < m_backgroundStages.size(); ++i)
14951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            m_backgroundStages[i]->processInBackground(this, SliceSize);
1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void ReverbConvolver::process(const AudioChannel* sourceChannel, AudioChannel* destinationChannel, size_t framesToProcess)
1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool isSafe = sourceChannel && destinationChannel && sourceChannel->length() >= framesToProcess && destinationChannel->length() >= framesToProcess;
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(isSafe);
1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!isSafe)
1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
15902772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const float* source = sourceChannel->data();
1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    float* destination = destinationChannel->mutableData();
1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool isDataSafe = source && destination;
1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(isDataSafe);
1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!isDataSafe)
1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Feed input buffer (read by all threads)
1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_inputBuffer.write(source, framesToProcess);
1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Accumulate contributions from each stage
1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (size_t i = 0; i < m_stages.size(); ++i)
1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_stages[i]->process(source, framesToProcess);
1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Finally read from accumulation buffer
1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_accumulationBuffer.readAndClear(destination, framesToProcess);
17602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
17751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    // Now that we've buffered more input, post another task to the background thread.
17851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    if (m_backgroundThread)
17951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        m_backgroundThread->postTask(new Task(WTF::bind(&ReverbConvolver::processInBackground, this)));
1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void ReverbConvolver::reset()
1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (size_t i = 0; i < m_stages.size(); ++i)
1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_stages[i]->reset();
1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (size_t i = 0; i < m_backgroundStages.size(); ++i)
1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_backgroundStages[i]->reset();
1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_accumulationBuffer.reset();
1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_inputBuffer.reset();
1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)size_t ReverbConvolver::latencyFrames() const
1955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return 0;
1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
199c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} // namespace blink
2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif // ENABLE(WEB_AUDIO)
202