15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2011 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/SincResampler.h"
345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
351e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/audio/AudioBus.h"
36f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)#include "wtf/CPU.h"
377757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#include "wtf/MathExtras.h"
385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
39f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)#if CPU(X86) || CPU(X86_64)
405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include <emmintrin.h>
415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif
425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Input buffer layout, dividing the total buffer into regions (r0 - r5):
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//
455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// |----------------|----------------------------------------------------------------|----------------|
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//
4702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch//                                              blockSize + kernelSize / 2
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//                   <-------------------------------------------------------------------------------->
495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//                                                  r0
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//
5102772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch//   kernelSize / 2   kernelSize / 2                                 kernelSize / 2     kernelSize / 2
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// <---------------> <--------------->                              <---------------> <--------------->
535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//         r1                r2                                             r3                r4
5402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch//
5502772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch//                                              blockSize
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//                                     <-------------------------------------------------------------->
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//                                                  r5
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// The Algorithm:
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//
615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// 1) Consume input frames into r0 (r1 is zero-initialized).
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// 2) Position kernel centered at start of r0 (r2) and generate output frames until kernel is centered at start of r4.
635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//    or we've finished generating all the output frames.
645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// 3) Copy r3 to r1 and r4 to r2.
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// 4) Consume input frames into r5 (zero-pad if we run out of input).
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// 5) Goto (2) until all of input is consumed.
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//
685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// note: we're glossing over how the sub-sample handling works with m_virtualSourceIndex, etc.
695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
70c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink {
715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)SincResampler::SincResampler(double scaleFactor, unsigned kernelSize, unsigned numberOfKernelOffsets)
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    : m_scaleFactor(scaleFactor)
745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_kernelSize(kernelSize)
755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_numberOfKernelOffsets(numberOfKernelOffsets)
765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_kernelStorage(m_kernelSize * (m_numberOfKernelOffsets + 1))
775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_virtualSourceIndex(0)
785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_blockSize(512)
795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_inputBuffer(m_blockSize + m_kernelSize) // See input buffer layout above.
805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_source(0)
815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_sourceFramesAvailable(0)
825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_sourceProvider(0)
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_isBufferPrimed(false)
845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    initializeKernel();
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SincResampler::initializeKernel()
895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Blackman window parameters.
915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    double alpha = 0.16;
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    double a0 = 0.5 * (1.0 - alpha);
935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    double a1 = 0.5;
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    double a2 = 0.5 * alpha;
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // sincScaleFactor is basically the normalized cutoff frequency of the low-pass filter.
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    double sincScaleFactor = m_scaleFactor > 1.0 ? 1.0 / m_scaleFactor : 1.0;
985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // The sinc function is an idealized brick-wall filter, but since we're windowing it the
1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // transition from pass to stop does not happen right away. So we should adjust the
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // lowpass filter cutoff slightly downward to avoid some aliasing at the very high-end.
1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // FIXME: this value is empirical and to be more exact should vary depending on m_kernelSize.
1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    sincScaleFactor *= 0.9;
1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int n = m_kernelSize;
1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int halfSize = n / 2;
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Generates a set of windowed sinc() kernels.
1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // We generate a range of sub-sample offsets from 0.0 to 1.0.
1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (unsigned offsetIndex = 0; offsetIndex <= m_numberOfKernelOffsets; ++offsetIndex) {
1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        double subsampleOffset = static_cast<double>(offsetIndex) / m_numberOfKernelOffsets;
1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (int i = 0; i < n; ++i) {
1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Compute the sinc() with offset.
1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            double s = sincScaleFactor * piDouble * (i - halfSize - subsampleOffset);
1167242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            double sinc = !s ? 1.0 : std::sin(s) / s;
1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            sinc *= sincScaleFactor;
1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Compute Blackman window, matching the offset of the sinc().
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            double x = (i - subsampleOffset) / n;
1217242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            double window = a0 - a1 * std::cos(twoPiDouble * x) + a2 * std::cos(twoPiDouble * 2.0 * x);
1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Window the sinc() function and store at the correct offset.
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            m_kernelStorage[i + offsetIndex * m_kernelSize] = sinc * window;
1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SincResampler::consumeSource(float* buffer, unsigned numberOfSourceFrames)
1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(m_sourceProvider);
1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!m_sourceProvider)
1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
13402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Wrap the provided buffer by an AudioBus for use by the source provider.
13681a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)    RefPtr<AudioBus> bus = AudioBus::create(1, numberOfSourceFrames, false);
1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // FIXME: Find a way to make the following const-correct:
13981a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)    bus->setChannelMemory(0, buffer, numberOfSourceFrames);
14002772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
14181a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)    m_sourceProvider->provideInput(bus.get(), numberOfSourceFrames);
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace {
1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// BufferSourceProvider is an AudioSourceProvider wrapping an in-memory buffer.
1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)class BufferSourceProvider FINAL : public AudioSourceProvider {
1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)public:
1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    BufferSourceProvider(const float* source, size_t numberOfSourceFrames)
1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        : m_source(source)
1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        , m_sourceFramesAvailable(numberOfSourceFrames)
1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
15502772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Consumes samples from the in-memory buffer.
15709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    virtual void provideInput(AudioBus* bus, size_t framesToProcess) OVERRIDE
1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(m_source && bus);
1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!m_source || !bus)
1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return;
16202772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        float* buffer = bus->channel(0)->mutableData();
1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Clamp to number of frames available and zero-pad.
1667242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        size_t framesToCopy = std::min(m_sourceFramesAvailable, framesToProcess);
1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        memcpy(buffer, m_source, sizeof(float) * framesToCopy);
1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Zero-pad if necessary.
1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (framesToCopy < framesToProcess)
1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            memset(buffer + framesToCopy, 0, sizeof(float) * (framesToProcess - framesToCopy));
1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_sourceFramesAvailable -= framesToCopy;
1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_source += framesToCopy;
1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
17602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)private:
1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const float* m_source;
1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    size_t m_sourceFramesAvailable;
1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} // namespace
1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SincResampler::process(const float* source, float* destination, unsigned numberOfSourceFrames)
1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Resample an in-memory buffer using an AudioSourceProvider.
1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    BufferSourceProvider sourceProvider(source, numberOfSourceFrames);
1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned numberOfDestinationFrames = static_cast<unsigned>(numberOfSourceFrames / m_scaleFactor);
1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned remaining = numberOfDestinationFrames;
19102772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (remaining) {
1937242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        unsigned framesThisTime = std::min(remaining, m_blockSize);
1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        process(&sourceProvider, destination, framesThisTime);
19502772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        destination += framesThisTime;
1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        remaining -= framesThisTime;
1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SincResampler::process(AudioSourceProvider* sourceProvider, float* destination, size_t framesToProcess)
2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool isGood = sourceProvider && m_blockSize > m_kernelSize && m_inputBuffer.size() >= m_blockSize + m_kernelSize && !(m_kernelSize % 2);
2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(isGood);
2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!isGood)
2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
20702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_sourceProvider = sourceProvider;
2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned numberOfDestinationFrames = framesToProcess;
21102772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Setup various region pointers in the buffer (see diagram above).
2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    float* r0 = m_inputBuffer.data() + m_kernelSize / 2;
2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    float* r1 = m_inputBuffer.data();
2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    float* r2 = r0;
2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    float* r3 = r0 + m_blockSize - m_kernelSize / 2;
2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    float* r4 = r0 + m_blockSize;
2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    float* r5 = r0 + m_kernelSize / 2;
2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Step (1)
2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Prime the input buffer at the start of the input stream.
2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!m_isBufferPrimed) {
2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        consumeSource(r0, m_blockSize + m_kernelSize / 2);
2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_isBufferPrimed = true;
2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
22602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Step (2)
2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (numberOfDestinationFrames) {
2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        while (m_virtualSourceIndex < m_blockSize) {
2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // m_virtualSourceIndex lies in between two kernel offsets so figure out what they are.
2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            int sourceIndexI = static_cast<int>(m_virtualSourceIndex);
2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            double subsampleRemainder = m_virtualSourceIndex - sourceIndexI;
2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            double virtualOffsetIndex = subsampleRemainder * m_numberOfKernelOffsets;
2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            int offsetIndex = static_cast<int>(virtualOffsetIndex);
23702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            float* k1 = m_kernelStorage.data() + offsetIndex * m_kernelSize;
2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            float* k2 = k1 + m_kernelSize;
2405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Initialize input pointer based on quantized m_virtualSourceIndex.
2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            float* inputP = r1 + sourceIndexI;
2435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // We'll compute "convolutions" for the two kernels which straddle m_virtualSourceIndex
2455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            float sum1 = 0;
2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            float sum2 = 0;
2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Figure out how much to weight each kernel's "convolution".
2495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            double kernelInterpolationFactor = virtualOffsetIndex - offsetIndex;
2505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
25102772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch            // Generate a single output sample.
2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            int n = m_kernelSize;
2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#define CONVOLVE_ONE_SAMPLE      \
2555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            input = *inputP++;   \
2565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            sum1 += input * *k1; \
2575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            sum2 += input * *k2; \
2585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ++k1;                \
2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ++k2;
2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            {
2625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                float input;
2635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
264f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)#if CPU(X86) || CPU(X86_64)
2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                // If the sourceP address is not 16-byte aligned, the first several frames (at most three) should be processed seperately.
2665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                while ((reinterpret_cast<uintptr_t>(inputP) & 0x0F) && n) {
2675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE
2685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    n--;
2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
2705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                // Now the inputP is aligned and start to apply SSE.
2725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                float* endP = inputP + n - n % 4;
2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                __m128 mInput;
2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                __m128 mK1;
2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                __m128 mK2;
2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                __m128 mul1;
2775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                __m128 mul2;
2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                __m128 sums1 = _mm_setzero_ps();
2805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                __m128 sums2 = _mm_setzero_ps();
2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                bool k1Aligned = !(reinterpret_cast<uintptr_t>(k1) & 0x0F);
2825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                bool k2Aligned = !(reinterpret_cast<uintptr_t>(k2) & 0x0F);
2835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#define LOAD_DATA(l1, l2)                        \
2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                mInput = _mm_load_ps(inputP);    \
2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                mK1 = _mm_##l1##_ps(k1);         \
2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                mK2 = _mm_##l2##_ps(k2);
2885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#define CONVOLVE_4_SAMPLES                       \
2905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                mul1 = _mm_mul_ps(mInput, mK1);  \
2915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                mul2 = _mm_mul_ps(mInput, mK2);  \
2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                sums1 = _mm_add_ps(sums1, mul1); \
2935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                sums2 = _mm_add_ps(sums2, mul2); \
2945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                inputP += 4;                     \
2955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                k1 += 4;                         \
2965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                k2 += 4;
2975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (k1Aligned && k2Aligned) { // both aligned
2995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    while (inputP < endP) {
3005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        LOAD_DATA(load, load)
3015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        CONVOLVE_4_SAMPLES
3025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    }
3035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                } else if (!k1Aligned && k2Aligned) { // only k2 aligned
3045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    while (inputP < endP) {
3055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        LOAD_DATA(loadu, load)
3065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        CONVOLVE_4_SAMPLES
3075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    }
3085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                } else if (k1Aligned && !k2Aligned) { // only k1 aligned
3095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    while (inputP < endP) {
3105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        LOAD_DATA(load, loadu)
3115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        CONVOLVE_4_SAMPLES
3125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    }
3135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                } else { // both non-aligned
3145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    while (inputP < endP) {
3155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        LOAD_DATA(loadu, loadu)
3165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        CONVOLVE_4_SAMPLES
3175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    }
3185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
3195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                // Summarize the SSE results to sum1 and sum2.
3215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                float* groupSumP = reinterpret_cast<float*>(&sums1);
3225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                sum1 += groupSumP[0] + groupSumP[1] + groupSumP[2] + groupSumP[3];
3235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                groupSumP = reinterpret_cast<float*>(&sums2);
3245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                sum2 += groupSumP[0] + groupSumP[1] + groupSumP[2] + groupSumP[3];
3255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                n %= 4;
3275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                while (n) {
3285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE
3295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    n--;
3305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
3315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#else
3325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                // FIXME: add ARM NEON optimizations for the following. The scalar code-path can probably also be optimized better.
33302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
3345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                // Optimize size 32 and size 64 kernels by unrolling the while loop.
3355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                // A 20 - 30% speed improvement was measured in some cases by using this approach.
33602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
3375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (n == 32) {
3385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 1
3395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 2
3405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 3
3415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 4
3425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 5
3435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 6
3445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 7
3455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 8
3465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 9
3475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 10
3485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 11
3495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 12
3505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 13
3515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 14
3525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 15
3535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 16
3545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 17
3555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 18
3565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 19
3575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 20
3585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 21
3595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 22
3605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 23
3615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 24
3625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 25
3635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 26
3645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 27
3655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 28
3665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 29
3675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 30
3685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 31
3695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 32
3705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                } else if (n == 64) {
3715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 1
3725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 2
3735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 3
3745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 4
3755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 5
3765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 6
3775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 7
3785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 8
3795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 9
3805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 10
3815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 11
3825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 12
3835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 13
3845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 14
3855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 15
3865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 16
3875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 17
3885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 18
3895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 19
3905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 20
3915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 21
3925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 22
3935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 23
3945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 24
3955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 25
3965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 26
3975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 27
3985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 28
3995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 29
4005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 30
4015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 31
4025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 32
4035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 33
4045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 34
4055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 35
4065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 36
4075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 37
4085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 38
4095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 39
4105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 40
4115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 41
4125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 42
4135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 43
4145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 44
4155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 45
4165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 46
4175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 47
4185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 48
4195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 49
4205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 50
4215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 51
4225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 52
4235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 53
4245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 54
4255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 55
4265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 56
4275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 57
4285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 58
4295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 59
4305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 60
4315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 61
4325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 62
4335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 63
4345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    CONVOLVE_ONE_SAMPLE // 64
4355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                } else {
4365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    while (n--) {
4375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        // Non-optimized using actual while loop.
4385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        CONVOLVE_ONE_SAMPLE
4395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    }
4405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
4415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif
4425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
4435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Linearly interpolate the two "convolutions".
4455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            double result = (1.0 - kernelInterpolationFactor) * sum1 + kernelInterpolationFactor * sum2;
4465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            *destination++ = result;
4485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Advance the virtual index.
4505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            m_virtualSourceIndex += m_scaleFactor;
4515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            --numberOfDestinationFrames;
4535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!numberOfDestinationFrames)
4545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return;
4555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
4565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Wrap back around to the start.
4585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_virtualSourceIndex -= m_blockSize;
4595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Step (3) Copy r3 to r1 and r4 to r2.
4615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // This wraps the last input frames back to the start of the buffer.
4625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        memcpy(r1, r3, sizeof(float) * (m_kernelSize / 2));
4635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        memcpy(r2, r4, sizeof(float) * (m_kernelSize / 2));
4645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Step (4)
4665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Refresh the buffer with more input.
4675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        consumeSource(r5, m_blockSize);
4685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
471c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} // namespace blink
4725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif // ENABLE(WEB_AUDIO)
474