1/* 2 * Copyright (C) 2013 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of Apple Inc. ("Apple") nor the names of 14 * its contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29#include "config.h" 30 31#if ENABLE(WEB_AUDIO) 32 33#include "UpSampler.h" 34 35#include <wtf/MathExtras.h> 36 37namespace WebCore { 38 39UpSampler::UpSampler(size_t inputBlockSize) 40 : m_inputBlockSize(inputBlockSize) 41 , m_kernel(DefaultKernelSize) 42 , m_convolver(inputBlockSize) 43 , m_tempBuffer(inputBlockSize) 44 , m_inputBuffer(inputBlockSize * 2) 45{ 46 initializeKernel(); 47} 48 49void UpSampler::initializeKernel() 50{ 51 // Blackman window parameters. 52 double alpha = 0.16; 53 double a0 = 0.5 * (1.0 - alpha); 54 double a1 = 0.5; 55 double a2 = 0.5 * alpha; 56 57 int n = m_kernel.size(); 58 int halfSize = n / 2; 59 double subsampleOffset = -0.5; 60 61 for (int i = 0; i < n; ++i) { 62 // Compute the sinc() with offset. 63 double s = piDouble * (i - halfSize - subsampleOffset); 64 double sinc = !s ? 1.0 : sin(s) / s; 65 66 // Compute Blackman window, matching the offset of the sinc(). 67 double x = (i - subsampleOffset) / n; 68 double window = a0 - a1 * cos(2.0 * piDouble * x) + a2 * cos(4.0 * piDouble * x); 69 70 // Window the sinc() function. 71 m_kernel[i] = sinc * window; 72 } 73} 74 75void UpSampler::process(const float* sourceP, float* destP, size_t sourceFramesToProcess) 76{ 77 bool isInputBlockSizeGood = sourceFramesToProcess == m_inputBlockSize; 78 ASSERT(isInputBlockSizeGood); 79 if (!isInputBlockSizeGood) 80 return; 81 82 bool isTempBufferGood = sourceFramesToProcess == m_tempBuffer.size(); 83 ASSERT(isTempBufferGood); 84 if (!isTempBufferGood) 85 return; 86 87 bool isKernelGood = m_kernel.size() == DefaultKernelSize; 88 ASSERT(isKernelGood); 89 if (!isKernelGood) 90 return; 91 92 size_t halfSize = m_kernel.size() / 2; 93 94 // Copy source samples to 2nd half of input buffer. 95 bool isInputBufferGood = m_inputBuffer.size() == sourceFramesToProcess * 2 && halfSize <= sourceFramesToProcess; 96 ASSERT(isInputBufferGood); 97 if (!isInputBufferGood) 98 return; 99 100 float* inputP = m_inputBuffer.data() + sourceFramesToProcess; 101 memcpy(inputP, sourceP, sizeof(float) * sourceFramesToProcess); 102 103 // Copy even sample-frames 0,2,4,6... (delayed by the linear phase delay) directly into destP. 104 for (unsigned i = 0; i < sourceFramesToProcess; ++i) 105 destP[i * 2] = *((inputP - halfSize) + i); 106 107 // Compute odd sample-frames 1,3,5,7... 108 float* oddSamplesP = m_tempBuffer.data(); 109 m_convolver.process(&m_kernel, sourceP, oddSamplesP, sourceFramesToProcess); 110 111 for (unsigned i = 0; i < sourceFramesToProcess; ++i) 112 destP[i * 2 + 1] = oddSamplesP[i]; 113 114 // Copy 2nd half of input buffer to 1st half. 115 memcpy(m_inputBuffer.data(), inputP, sizeof(float) * sourceFramesToProcess); 116} 117 118void UpSampler::reset() 119{ 120 m_convolver.reset(); 121 m_inputBuffer.zero(); 122} 123 124size_t UpSampler::latencyFrames() const 125{ 126 // Divide by two since this is a linear phase kernel and the delay is at the center of the kernel. 127 return m_kernel.size() / 2; 128} 129 130} // namespace WebCore 131 132#endif // ENABLE(WEB_AUDIO) 133