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