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