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