12bde8e466a4451c7319e3a072d118917957d6554Steve Block/*
22bde8e466a4451c7319e3a072d118917957d6554Steve Block * Copyright (C) 2011 Google Inc. All rights reserved.
32bde8e466a4451c7319e3a072d118917957d6554Steve Block *
42bde8e466a4451c7319e3a072d118917957d6554Steve Block * Redistribution and use in source and binary forms, with or without
52bde8e466a4451c7319e3a072d118917957d6554Steve Block * modification, are permitted provided that the following conditions
62bde8e466a4451c7319e3a072d118917957d6554Steve Block * are met:
72bde8e466a4451c7319e3a072d118917957d6554Steve Block *
82bde8e466a4451c7319e3a072d118917957d6554Steve Block * 1.  Redistributions of source code must retain the above copyright
92bde8e466a4451c7319e3a072d118917957d6554Steve Block *     notice, this list of conditions and the following disclaimer.
102bde8e466a4451c7319e3a072d118917957d6554Steve Block * 2.  Redistributions in binary form must reproduce the above copyright
112bde8e466a4451c7319e3a072d118917957d6554Steve Block *     notice, this list of conditions and the following disclaimer in the
122bde8e466a4451c7319e3a072d118917957d6554Steve Block *     documentation and/or other materials provided with the distribution.
132bde8e466a4451c7319e3a072d118917957d6554Steve Block * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
142bde8e466a4451c7319e3a072d118917957d6554Steve Block *     its contributors may be used to endorse or promote products derived
152bde8e466a4451c7319e3a072d118917957d6554Steve Block *     from this software without specific prior written permission.
162bde8e466a4451c7319e3a072d118917957d6554Steve Block *
172bde8e466a4451c7319e3a072d118917957d6554Steve Block * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
182bde8e466a4451c7319e3a072d118917957d6554Steve Block * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
192bde8e466a4451c7319e3a072d118917957d6554Steve Block * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
202bde8e466a4451c7319e3a072d118917957d6554Steve Block * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
212bde8e466a4451c7319e3a072d118917957d6554Steve Block * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
222bde8e466a4451c7319e3a072d118917957d6554Steve Block * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
232bde8e466a4451c7319e3a072d118917957d6554Steve Block * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
242bde8e466a4451c7319e3a072d118917957d6554Steve Block * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252bde8e466a4451c7319e3a072d118917957d6554Steve Block * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
262bde8e466a4451c7319e3a072d118917957d6554Steve Block * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272bde8e466a4451c7319e3a072d118917957d6554Steve Block */
282bde8e466a4451c7319e3a072d118917957d6554Steve Block
292bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "config.h"
302bde8e466a4451c7319e3a072d118917957d6554Steve Block
312bde8e466a4451c7319e3a072d118917957d6554Steve Block#if ENABLE(WEB_AUDIO)
322bde8e466a4451c7319e3a072d118917957d6554Steve Block
332bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "SincResampler.h"
342bde8e466a4451c7319e3a072d118917957d6554Steve Block
352bde8e466a4451c7319e3a072d118917957d6554Steve Block#include <wtf/MathExtras.h>
362bde8e466a4451c7319e3a072d118917957d6554Steve Block
372bde8e466a4451c7319e3a072d118917957d6554Steve Blockusing namespace std;
382bde8e466a4451c7319e3a072d118917957d6554Steve Block
392bde8e466a4451c7319e3a072d118917957d6554Steve Block// Input buffer layout, dividing the total buffer into regions (r0 - r5):
402bde8e466a4451c7319e3a072d118917957d6554Steve Block//
412bde8e466a4451c7319e3a072d118917957d6554Steve Block// |----------------|----------------------------------------------------------------|----------------|
422bde8e466a4451c7319e3a072d118917957d6554Steve Block//
432bde8e466a4451c7319e3a072d118917957d6554Steve Block//                                              blockSize + kernelSize / 2
442bde8e466a4451c7319e3a072d118917957d6554Steve Block//                   <-------------------------------------------------------------------------------->
452bde8e466a4451c7319e3a072d118917957d6554Steve Block//                                                  r0
462bde8e466a4451c7319e3a072d118917957d6554Steve Block//
472bde8e466a4451c7319e3a072d118917957d6554Steve Block//   kernelSize / 2   kernelSize / 2                                 kernelSize / 2     kernelSize / 2
482bde8e466a4451c7319e3a072d118917957d6554Steve Block// <---------------> <--------------->                              <---------------> <--------------->
492bde8e466a4451c7319e3a072d118917957d6554Steve Block//         r1                r2                                             r3                r4
502bde8e466a4451c7319e3a072d118917957d6554Steve Block//
512bde8e466a4451c7319e3a072d118917957d6554Steve Block//                                              blockSize
522bde8e466a4451c7319e3a072d118917957d6554Steve Block//                                     <-------------------------------------------------------------->
532bde8e466a4451c7319e3a072d118917957d6554Steve Block//                                                  r5
542bde8e466a4451c7319e3a072d118917957d6554Steve Block
552bde8e466a4451c7319e3a072d118917957d6554Steve Block// The Algorithm:
562bde8e466a4451c7319e3a072d118917957d6554Steve Block//
572bde8e466a4451c7319e3a072d118917957d6554Steve Block// 1) Consume input frames into r0 (r1 is zero-initialized).
582bde8e466a4451c7319e3a072d118917957d6554Steve Block// 2) Position kernel centered at start of r0 (r2) and generate output frames until kernel is centered at start of r4.
592bde8e466a4451c7319e3a072d118917957d6554Steve Block//    or we've finished generating all the output frames.
602bde8e466a4451c7319e3a072d118917957d6554Steve Block// 3) Copy r3 to r1 and r4 to r2.
612bde8e466a4451c7319e3a072d118917957d6554Steve Block// 4) Consume input frames into r5 (zero-pad if we run out of input).
622bde8e466a4451c7319e3a072d118917957d6554Steve Block// 5) Goto (2) until all of input is consumed.
632bde8e466a4451c7319e3a072d118917957d6554Steve Block//
642bde8e466a4451c7319e3a072d118917957d6554Steve Block// note: we're glossing over how the sub-sample handling works with m_virtualSourceIndex, etc.
652bde8e466a4451c7319e3a072d118917957d6554Steve Block
662bde8e466a4451c7319e3a072d118917957d6554Steve Blocknamespace WebCore {
672bde8e466a4451c7319e3a072d118917957d6554Steve Block
682bde8e466a4451c7319e3a072d118917957d6554Steve BlockSincResampler::SincResampler(double scaleFactor, unsigned kernelSize, unsigned numberOfKernelOffsets)
692bde8e466a4451c7319e3a072d118917957d6554Steve Block    : m_scaleFactor(scaleFactor)
702bde8e466a4451c7319e3a072d118917957d6554Steve Block    , m_kernelSize(kernelSize)
712bde8e466a4451c7319e3a072d118917957d6554Steve Block    , m_numberOfKernelOffsets(numberOfKernelOffsets)
722bde8e466a4451c7319e3a072d118917957d6554Steve Block    , m_kernelStorage(m_kernelSize * (m_numberOfKernelOffsets + 1))
732bde8e466a4451c7319e3a072d118917957d6554Steve Block    , m_virtualSourceIndex(0.0)
742bde8e466a4451c7319e3a072d118917957d6554Steve Block    , m_blockSize(512)
752bde8e466a4451c7319e3a072d118917957d6554Steve Block    , m_inputBuffer(m_blockSize + m_kernelSize) // See input buffer layout above.
762bde8e466a4451c7319e3a072d118917957d6554Steve Block    , m_source(0)
772bde8e466a4451c7319e3a072d118917957d6554Steve Block    , m_sourceFramesAvailable(0)
782bde8e466a4451c7319e3a072d118917957d6554Steve Block{
792bde8e466a4451c7319e3a072d118917957d6554Steve Block    initializeKernel();
802bde8e466a4451c7319e3a072d118917957d6554Steve Block}
812bde8e466a4451c7319e3a072d118917957d6554Steve Block
822bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid SincResampler::initializeKernel()
832bde8e466a4451c7319e3a072d118917957d6554Steve Block{
842bde8e466a4451c7319e3a072d118917957d6554Steve Block    // Blackman window parameters.
852bde8e466a4451c7319e3a072d118917957d6554Steve Block    double alpha = 0.16;
862bde8e466a4451c7319e3a072d118917957d6554Steve Block    double a0 = 0.5 * (1.0 - alpha);
872bde8e466a4451c7319e3a072d118917957d6554Steve Block    double a1 = 0.5;
882bde8e466a4451c7319e3a072d118917957d6554Steve Block    double a2 = 0.5 * alpha;
892bde8e466a4451c7319e3a072d118917957d6554Steve Block
902bde8e466a4451c7319e3a072d118917957d6554Steve Block    // sincScaleFactor is basically the normalized cutoff frequency of the low-pass filter.
912bde8e466a4451c7319e3a072d118917957d6554Steve Block    double sincScaleFactor = m_scaleFactor > 1.0 ? 1.0 / m_scaleFactor : 1.0;
922bde8e466a4451c7319e3a072d118917957d6554Steve Block
932bde8e466a4451c7319e3a072d118917957d6554Steve Block    // The sinc function is an idealized brick-wall filter, but since we're windowing it the
942bde8e466a4451c7319e3a072d118917957d6554Steve Block    // transition from pass to stop does not happen right away. So we should adjust the
952bde8e466a4451c7319e3a072d118917957d6554Steve Block    // lowpass filter cutoff slightly downward to avoid some aliasing at the very high-end.
962bde8e466a4451c7319e3a072d118917957d6554Steve Block    // FIXME: this value is empirical and to be more exact should vary depending on m_kernelSize.
972bde8e466a4451c7319e3a072d118917957d6554Steve Block    sincScaleFactor *= 0.9;
982bde8e466a4451c7319e3a072d118917957d6554Steve Block
992bde8e466a4451c7319e3a072d118917957d6554Steve Block    int n = m_kernelSize;
1002bde8e466a4451c7319e3a072d118917957d6554Steve Block    int halfSize = n / 2;
1012bde8e466a4451c7319e3a072d118917957d6554Steve Block
1022bde8e466a4451c7319e3a072d118917957d6554Steve Block    // Generates a set of windowed sinc() kernels.
1032bde8e466a4451c7319e3a072d118917957d6554Steve Block    // We generate a range of sub-sample offsets from 0.0 to 1.0.
1042bde8e466a4451c7319e3a072d118917957d6554Steve Block    for (unsigned offsetIndex = 0; offsetIndex <= m_numberOfKernelOffsets; ++offsetIndex) {
1052bde8e466a4451c7319e3a072d118917957d6554Steve Block        double subsampleOffset = static_cast<double>(offsetIndex) / m_numberOfKernelOffsets;
1062bde8e466a4451c7319e3a072d118917957d6554Steve Block
1072bde8e466a4451c7319e3a072d118917957d6554Steve Block        for (int i = 0; i < n; ++i) {
1082bde8e466a4451c7319e3a072d118917957d6554Steve Block            // Compute the sinc() with offset.
1092bde8e466a4451c7319e3a072d118917957d6554Steve Block            double s = sincScaleFactor * piDouble * (i - halfSize - subsampleOffset);
1102bde8e466a4451c7319e3a072d118917957d6554Steve Block            double sinc = !s ? 1.0 : sin(s) / s;
1112bde8e466a4451c7319e3a072d118917957d6554Steve Block            sinc *= sincScaleFactor;
1122bde8e466a4451c7319e3a072d118917957d6554Steve Block
1132bde8e466a4451c7319e3a072d118917957d6554Steve Block            // Compute Blackman window, matching the offset of the sinc().
1142bde8e466a4451c7319e3a072d118917957d6554Steve Block            double x = (i - subsampleOffset) / n;
1152bde8e466a4451c7319e3a072d118917957d6554Steve Block            double window = a0 - a1 * cos(2.0 * piDouble * x) + a2 * cos(4.0 * piDouble * x);
1162bde8e466a4451c7319e3a072d118917957d6554Steve Block
1172bde8e466a4451c7319e3a072d118917957d6554Steve Block            // Window the sinc() function and store at the correct offset.
1182bde8e466a4451c7319e3a072d118917957d6554Steve Block            m_kernelStorage[i + offsetIndex * m_kernelSize] = sinc * window;
1192bde8e466a4451c7319e3a072d118917957d6554Steve Block        }
1202bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
1212bde8e466a4451c7319e3a072d118917957d6554Steve Block}
1222bde8e466a4451c7319e3a072d118917957d6554Steve Block
1232bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid SincResampler::consumeSource(float* buffer, unsigned numberOfSourceFrames)
1242bde8e466a4451c7319e3a072d118917957d6554Steve Block{
1252bde8e466a4451c7319e3a072d118917957d6554Steve Block    ASSERT(m_source);
1262bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (!m_source)
1272bde8e466a4451c7319e3a072d118917957d6554Steve Block        return;
1282bde8e466a4451c7319e3a072d118917957d6554Steve Block
1292bde8e466a4451c7319e3a072d118917957d6554Steve Block    // Clamp to number of frames available and zero-pad.
1302bde8e466a4451c7319e3a072d118917957d6554Steve Block    unsigned framesToCopy = min(m_sourceFramesAvailable, numberOfSourceFrames);
1312bde8e466a4451c7319e3a072d118917957d6554Steve Block    memcpy(buffer, m_source, sizeof(float) * framesToCopy);
1322bde8e466a4451c7319e3a072d118917957d6554Steve Block
1332bde8e466a4451c7319e3a072d118917957d6554Steve Block    // Zero-pad if necessary.
1342bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (framesToCopy < numberOfSourceFrames)
1352bde8e466a4451c7319e3a072d118917957d6554Steve Block        memset(buffer + framesToCopy, 0, sizeof(float) * (numberOfSourceFrames - framesToCopy));
1362bde8e466a4451c7319e3a072d118917957d6554Steve Block
1372bde8e466a4451c7319e3a072d118917957d6554Steve Block    m_sourceFramesAvailable -= framesToCopy;
1382bde8e466a4451c7319e3a072d118917957d6554Steve Block    m_source += numberOfSourceFrames;
1392bde8e466a4451c7319e3a072d118917957d6554Steve Block}
1402bde8e466a4451c7319e3a072d118917957d6554Steve Block
1412bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid SincResampler::process(float* source, float* destination, unsigned numberOfSourceFrames)
1422bde8e466a4451c7319e3a072d118917957d6554Steve Block{
1432bde8e466a4451c7319e3a072d118917957d6554Steve Block    ASSERT(m_blockSize > m_kernelSize);
1442bde8e466a4451c7319e3a072d118917957d6554Steve Block    ASSERT(m_inputBuffer.size() >= m_blockSize + m_kernelSize);
1452bde8e466a4451c7319e3a072d118917957d6554Steve Block    ASSERT(!(m_kernelSize % 2));
1462bde8e466a4451c7319e3a072d118917957d6554Steve Block
1472bde8e466a4451c7319e3a072d118917957d6554Steve Block    // Setup various region pointers in the buffer (see diagram above).
1482bde8e466a4451c7319e3a072d118917957d6554Steve Block    float* r0 = m_inputBuffer.data() + m_kernelSize / 2;
1492bde8e466a4451c7319e3a072d118917957d6554Steve Block    float* r1 = m_inputBuffer.data();
1502bde8e466a4451c7319e3a072d118917957d6554Steve Block    float* r2 = r0;
1512bde8e466a4451c7319e3a072d118917957d6554Steve Block    float* r3 = r0 + m_blockSize - m_kernelSize / 2;
1522bde8e466a4451c7319e3a072d118917957d6554Steve Block    float* r4 = r0 + m_blockSize;
1532bde8e466a4451c7319e3a072d118917957d6554Steve Block    float* r5 = r0 + m_kernelSize / 2;
1542bde8e466a4451c7319e3a072d118917957d6554Steve Block
1552bde8e466a4451c7319e3a072d118917957d6554Steve Block    m_source = source;
1562bde8e466a4451c7319e3a072d118917957d6554Steve Block    m_sourceFramesAvailable = numberOfSourceFrames;
1572bde8e466a4451c7319e3a072d118917957d6554Steve Block
1582bde8e466a4451c7319e3a072d118917957d6554Steve Block    unsigned numberOfDestinationFrames = static_cast<unsigned>(numberOfSourceFrames / m_scaleFactor);
1592bde8e466a4451c7319e3a072d118917957d6554Steve Block
1602bde8e466a4451c7319e3a072d118917957d6554Steve Block    // Step (1)
1612bde8e466a4451c7319e3a072d118917957d6554Steve Block    // Prime the input buffer.
1622bde8e466a4451c7319e3a072d118917957d6554Steve Block    consumeSource(r0, m_blockSize + m_kernelSize / 2);
1632bde8e466a4451c7319e3a072d118917957d6554Steve Block
1642bde8e466a4451c7319e3a072d118917957d6554Steve Block    // Step (2)
1652bde8e466a4451c7319e3a072d118917957d6554Steve Block    m_virtualSourceIndex = 0;
1662bde8e466a4451c7319e3a072d118917957d6554Steve Block
1672bde8e466a4451c7319e3a072d118917957d6554Steve Block    while (numberOfDestinationFrames) {
1682bde8e466a4451c7319e3a072d118917957d6554Steve Block        while (m_virtualSourceIndex < m_blockSize) {
1692bde8e466a4451c7319e3a072d118917957d6554Steve Block            // m_virtualSourceIndex lies in between two kernel offsets so figure out what they are.
1702bde8e466a4451c7319e3a072d118917957d6554Steve Block            int sourceIndexI = static_cast<int>(m_virtualSourceIndex);
1712bde8e466a4451c7319e3a072d118917957d6554Steve Block            double subsampleRemainder = m_virtualSourceIndex - sourceIndexI;
1722bde8e466a4451c7319e3a072d118917957d6554Steve Block
1732bde8e466a4451c7319e3a072d118917957d6554Steve Block            double virtualOffsetIndex = subsampleRemainder * m_numberOfKernelOffsets;
1742bde8e466a4451c7319e3a072d118917957d6554Steve Block            int offsetIndex = static_cast<int>(virtualOffsetIndex);
1752bde8e466a4451c7319e3a072d118917957d6554Steve Block
1762bde8e466a4451c7319e3a072d118917957d6554Steve Block            float* k1 = m_kernelStorage.data() + offsetIndex * m_kernelSize;
1772bde8e466a4451c7319e3a072d118917957d6554Steve Block            float* k2 = k1 + m_kernelSize;
1782bde8e466a4451c7319e3a072d118917957d6554Steve Block
1792bde8e466a4451c7319e3a072d118917957d6554Steve Block            // Initialize input pointer based on quantized m_virtualSourceIndex.
1802bde8e466a4451c7319e3a072d118917957d6554Steve Block            float* inputP = r1 + sourceIndexI;
1812bde8e466a4451c7319e3a072d118917957d6554Steve Block
1822bde8e466a4451c7319e3a072d118917957d6554Steve Block            // We'll compute "convolutions" for the two kernels which straddle m_virtualSourceIndex
1832bde8e466a4451c7319e3a072d118917957d6554Steve Block            float sum1 = 0;
1842bde8e466a4451c7319e3a072d118917957d6554Steve Block            float sum2 = 0;
1852bde8e466a4451c7319e3a072d118917957d6554Steve Block
1862bde8e466a4451c7319e3a072d118917957d6554Steve Block            // Figure out how much to weight each kernel's "convolution".
1872bde8e466a4451c7319e3a072d118917957d6554Steve Block            double kernelInterpolationFactor = virtualOffsetIndex - offsetIndex;
1882bde8e466a4451c7319e3a072d118917957d6554Steve Block
1892bde8e466a4451c7319e3a072d118917957d6554Steve Block            // Generate a single output sample.
1902bde8e466a4451c7319e3a072d118917957d6554Steve Block            int n = m_kernelSize;
1912bde8e466a4451c7319e3a072d118917957d6554Steve Block
1922bde8e466a4451c7319e3a072d118917957d6554Steve Block            // FIXME: add SIMD optimizations for the following. The scalar code-path can probably also be optimized better.
1932bde8e466a4451c7319e3a072d118917957d6554Steve Block
1942bde8e466a4451c7319e3a072d118917957d6554Steve Block#define CONVOLVE_ONE_SAMPLE      \
1952bde8e466a4451c7319e3a072d118917957d6554Steve Block            input = *inputP++;   \
1962bde8e466a4451c7319e3a072d118917957d6554Steve Block            sum1 += input * *k1; \
1972bde8e466a4451c7319e3a072d118917957d6554Steve Block            sum2 += input * *k2; \
1982bde8e466a4451c7319e3a072d118917957d6554Steve Block            ++k1;                \
1992bde8e466a4451c7319e3a072d118917957d6554Steve Block            ++k2;
2002bde8e466a4451c7319e3a072d118917957d6554Steve Block
2012bde8e466a4451c7319e3a072d118917957d6554Steve Block            {
2022bde8e466a4451c7319e3a072d118917957d6554Steve Block                float input;
2032bde8e466a4451c7319e3a072d118917957d6554Steve Block
2042bde8e466a4451c7319e3a072d118917957d6554Steve Block                // Optimize size 32 and size 64 kernels by unrolling the while loop.
2052bde8e466a4451c7319e3a072d118917957d6554Steve Block                // A 20 - 30% speed improvement was measured in some cases by using this approach.
2062bde8e466a4451c7319e3a072d118917957d6554Steve Block
2072bde8e466a4451c7319e3a072d118917957d6554Steve Block                if (n == 32) {
2082bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 1
2092bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 2
2102bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 3
2112bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 4
2122bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 5
2132bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 6
2142bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 7
2152bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 8
2162bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 9
2172bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 10
2182bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 11
2192bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 12
2202bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 13
2212bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 14
2222bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 15
2232bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 16
2242bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 17
2252bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 18
2262bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 19
2272bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 20
2282bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 21
2292bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 22
2302bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 23
2312bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 24
2322bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 25
2332bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 26
2342bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 27
2352bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 28
2362bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 29
2372bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 30
2382bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 31
2392bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 32
2402bde8e466a4451c7319e3a072d118917957d6554Steve Block                } else if (n == 64) {
2412bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 1
2422bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 2
2432bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 3
2442bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 4
2452bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 5
2462bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 6
2472bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 7
2482bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 8
2492bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 9
2502bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 10
2512bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 11
2522bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 12
2532bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 13
2542bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 14
2552bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 15
2562bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 16
2572bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 17
2582bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 18
2592bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 19
2602bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 20
2612bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 21
2622bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 22
2632bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 23
2642bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 24
2652bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 25
2662bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 26
2672bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 27
2682bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 28
2692bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 29
2702bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 30
2712bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 31
2722bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 32
2732bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 33
2742bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 34
2752bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 35
2762bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 36
2772bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 37
2782bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 38
2792bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 39
2802bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 40
2812bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 41
2822bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 42
2832bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 43
2842bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 44
2852bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 45
2862bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 46
2872bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 47
2882bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 48
2892bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 49
2902bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 50
2912bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 51
2922bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 52
2932bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 53
2942bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 54
2952bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 55
2962bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 56
2972bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 57
2982bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 58
2992bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 59
3002bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 60
3012bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 61
3022bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 62
3032bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 63
3042bde8e466a4451c7319e3a072d118917957d6554Steve Block                    CONVOLVE_ONE_SAMPLE // 64
3052bde8e466a4451c7319e3a072d118917957d6554Steve Block                } else {
3062bde8e466a4451c7319e3a072d118917957d6554Steve Block                    while (n--) {
3072bde8e466a4451c7319e3a072d118917957d6554Steve Block                        // Non-optimized using actual while loop.
3082bde8e466a4451c7319e3a072d118917957d6554Steve Block                        CONVOLVE_ONE_SAMPLE
3092bde8e466a4451c7319e3a072d118917957d6554Steve Block                    }
3102bde8e466a4451c7319e3a072d118917957d6554Steve Block                }
3112bde8e466a4451c7319e3a072d118917957d6554Steve Block            }
3122bde8e466a4451c7319e3a072d118917957d6554Steve Block
3132bde8e466a4451c7319e3a072d118917957d6554Steve Block            // Linearly interpolate the two "convolutions".
3142bde8e466a4451c7319e3a072d118917957d6554Steve Block            double result = (1.0 - kernelInterpolationFactor) * sum1 + kernelInterpolationFactor * sum2;
3152bde8e466a4451c7319e3a072d118917957d6554Steve Block
3162bde8e466a4451c7319e3a072d118917957d6554Steve Block            *destination++ = result;
3172bde8e466a4451c7319e3a072d118917957d6554Steve Block
3182bde8e466a4451c7319e3a072d118917957d6554Steve Block            --numberOfDestinationFrames;
3192bde8e466a4451c7319e3a072d118917957d6554Steve Block            if (!numberOfDestinationFrames)
3202bde8e466a4451c7319e3a072d118917957d6554Steve Block                return;
3212bde8e466a4451c7319e3a072d118917957d6554Steve Block
3222bde8e466a4451c7319e3a072d118917957d6554Steve Block            // Advance the virtual index.
3232bde8e466a4451c7319e3a072d118917957d6554Steve Block            m_virtualSourceIndex += m_scaleFactor;
3242bde8e466a4451c7319e3a072d118917957d6554Steve Block        }
3252bde8e466a4451c7319e3a072d118917957d6554Steve Block
3262bde8e466a4451c7319e3a072d118917957d6554Steve Block        // Wrap back around to the start.
3272bde8e466a4451c7319e3a072d118917957d6554Steve Block        m_virtualSourceIndex -= m_blockSize;
3282bde8e466a4451c7319e3a072d118917957d6554Steve Block
3292bde8e466a4451c7319e3a072d118917957d6554Steve Block        // Step (3) Copy r3 to r1 and r4 to r2.
3302bde8e466a4451c7319e3a072d118917957d6554Steve Block        // This wraps the last input frames back to the start of the buffer.
3312bde8e466a4451c7319e3a072d118917957d6554Steve Block        memcpy(r1, r3, sizeof(float) * (m_kernelSize / 2));
3322bde8e466a4451c7319e3a072d118917957d6554Steve Block        memcpy(r2, r4, sizeof(float) * (m_kernelSize / 2));
3332bde8e466a4451c7319e3a072d118917957d6554Steve Block
3342bde8e466a4451c7319e3a072d118917957d6554Steve Block        // Step (4)
3352bde8e466a4451c7319e3a072d118917957d6554Steve Block        // Refresh the buffer with more input.
3362bde8e466a4451c7319e3a072d118917957d6554Steve Block        consumeSource(r5, m_blockSize);
3372bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
3382bde8e466a4451c7319e3a072d118917957d6554Steve Block}
3392bde8e466a4451c7319e3a072d118917957d6554Steve Block
3402bde8e466a4451c7319e3a072d118917957d6554Steve Block} // namespace WebCore
3412bde8e466a4451c7319e3a072d118917957d6554Steve Block
3422bde8e466a4451c7319e3a072d118917957d6554Steve Block#endif // ENABLE(WEB_AUDIO)
343