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) * 145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */ 255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// FFTFrame implementation using FFmpeg's RDFT algorithm, 275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// suitable for use on Windows and Linux. 285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h" 305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#if ENABLE(WEB_AUDIO) 325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#if USE(WEBAUDIO_FFMPEG) 345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/platform/audio/FFTFrame.h" 365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/platform/audio/VectorMath.h" 385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)extern "C" { 405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) #include <libavcodec/avfft.h> 415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 437757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#include "wtf/MathExtras.h" 445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 45926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)namespace { 46926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 47926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)struct FFTComplexProxy { 48926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) int16_t re; 49926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) int16_t im; 50926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}; 51926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 52926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)struct FFTContextProxy { 53926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) int nbits; 54926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) int inverse; 55926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) uint16_t* revtab; 56926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) FFTComplexProxy* tmpBuf; 57926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) int mdctSize; 58926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) int mdctBits; 59926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) void* tcos; 60926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) void* tsin; 61926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) void (*fftPermute)(); 62926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) void (*fftCalc)(); 63926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) void (*imdctCalc)(); 64926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) void (*imdctHalf)(); 65926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) void (*mdctCalc)(); 66926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) void (*mdctCalcw)(); 67926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) int fftPermutation; 68926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) int mdctPermutation; 69926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}; 70926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 71926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)struct RDFTContextProxy { 72926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) int nbits; 73926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) int inverse; 74926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) int signConvention; 75926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) const void* tcos; 76926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) const void* tsin; 77926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) FFTContextProxy fft; 78926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) void (*rdft_calc)(); 79926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}; 80926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 81926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)} 82926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace WebCore { 845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)const int kMaxFFTPow2Size = 24; 865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Normal constructor: allocates for a given fftSize. 885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)FFTFrame::FFTFrame(unsigned fftSize) 895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) : m_FFTSize(fftSize) 905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_log2FFTSize(static_cast<unsigned>(log2(fftSize))) 915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_forwardContext(0) 925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_inverseContext(0) 935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_complexData(fftSize) 945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_realData(fftSize / 2) 955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_imagData(fftSize / 2) 965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // We only allow power of two. 985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(1UL << m_log2FFTSize == m_FFTSize); 995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_forwardContext = contextForSize(fftSize, DFT_R2C); 1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_inverseContext = contextForSize(fftSize, IDFT_C2R); 1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Creates a blank/empty frame (interpolate() must later be called). 1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)FFTFrame::FFTFrame() 1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) : m_FFTSize(0) 1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_log2FFTSize(0) 1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_forwardContext(0) 1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_inverseContext(0) 1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Copy constructor. 1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)FFTFrame::FFTFrame(const FFTFrame& frame) 1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) : m_FFTSize(frame.m_FFTSize) 1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_log2FFTSize(frame.m_log2FFTSize) 1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_forwardContext(0) 1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_inverseContext(0) 1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_complexData(frame.m_FFTSize) 1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_realData(frame.m_FFTSize / 2) 1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_imagData(frame.m_FFTSize / 2) 1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_forwardContext = contextForSize(m_FFTSize, DFT_R2C); 1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_inverseContext = contextForSize(m_FFTSize, IDFT_C2R); 1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Copy/setup frame data. 1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unsigned nbytes = sizeof(float) * (m_FFTSize / 2); 1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) memcpy(realData(), frame.realData(), nbytes); 1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) memcpy(imagData(), frame.imagData(), nbytes); 1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void FFTFrame::initialize() 1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void FFTFrame::cleanup() 1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)FFTFrame::~FFTFrame() 1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) av_rdft_end(m_forwardContext); 1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) av_rdft_end(m_inverseContext); 1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void FFTFrame::multiply(const FFTFrame& frame) 1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) FFTFrame& frame1 = *this; 1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) FFTFrame& frame2 = const_cast<FFTFrame&>(frame); 1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float* realP1 = frame1.realData(); 1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float* imagP1 = frame1.imagData(); 1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const float* realP2 = frame2.realData(); 1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const float* imagP2 = frame2.imagData(); 1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unsigned halfSize = fftSize() / 2; 1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float real0 = realP1[0]; 1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float imag0 = imagP1[0]; 1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 16002772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch VectorMath::zvmul(realP1, imagP1, realP2, imagP2, realP1, imagP1, halfSize); 1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Multiply the packed DC/nyquist component 1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) realP1[0] = real0 * realP2[0]; 1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) imagP1[0] = imag0 * imagP2[0]; 1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Scale accounts the peculiar scaling of vecLib on the Mac. 1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // This ensures the right scaling all the way back to inverse FFT. 1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // FIXME: if we change the scaling on the Mac then this scale 1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // factor will need to change too. 1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float scale = 0.5f; 1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) VectorMath::vsmul(realP1, 1, &scale, realP1, 1, halfSize); 1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) VectorMath::vsmul(imagP1, 1, &scale, imagP1, 1, halfSize); 1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void FFTFrame::doFFT(const float* data) 1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Copy since processing is in-place. 1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float* p = m_complexData.data(); 1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) memcpy(p, data, sizeof(float) * m_FFTSize); 1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Compute Forward transform. 1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) av_rdft_calc(m_forwardContext, p); 1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // De-interleave to separate real and complex arrays. 1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int len = m_FFTSize / 2; 1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // FIXME: see above comment in multiply() about scaling. 1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const float scale = 2.0f; 1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (int i = 0; i < len; ++i) { 1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int baseComplexIndex = 2 * i; 1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // m_realData[0] is the DC component and m_imagData[0] is the nyquist component 1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // since the interleaved complex data is packed. 1955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_realData[i] = scale * p[baseComplexIndex]; 1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_imagData[i] = scale * p[baseComplexIndex + 1]; 1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void FFTFrame::doInverseFFT(float* data) 2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Prepare interleaved data. 2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float* interleavedData = getUpToDateComplexData(); 2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Compute inverse transform. 2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) av_rdft_calc(m_inverseContext, interleavedData); 2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Scale so that a forward then inverse FFT yields exactly the original data. 2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const float scale = 1.0 / m_FFTSize; 2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) VectorMath::vsmul(interleavedData, 1, &scale, data, 1, m_FFTSize); 2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)float* FFTFrame::realData() const 2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return const_cast<float*>(m_realData.data()); 2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)float* FFTFrame::imagData() const 2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return const_cast<float*>(m_imagData.data()); 2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)float* FFTFrame::getUpToDateComplexData() 2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // FIXME: if we can't completely get rid of this method, SSE 2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // optimization could be considered if it shows up hot on profiles. 2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int len = m_FFTSize / 2; 2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (int i = 0; i < len; ++i) { 2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int baseComplexIndex = 2 * i; 2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_complexData[baseComplexIndex] = m_realData[i]; 2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_complexData[baseComplexIndex + 1] = m_imagData[i]; 2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return const_cast<float*>(m_complexData.data()); 2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)RDFTContext* FFTFrame::contextForSize(unsigned fftSize, int trans) 2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // FIXME: This is non-optimal. Ideally, we'd like to share the contexts for FFTFrames of the same size. 2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // But FFmpeg's RDFT uses a scratch buffer inside the context and so they are not thread-safe. 2405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // We could improve this by sharing the FFTFrames on a per-thread basis. 2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(fftSize); 2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int pow2size = static_cast<int>(log2(fftSize)); 2435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(pow2size < kMaxFFTPow2Size); 2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RDFTContext* context = av_rdft_init(pow2size, (RDFTransformType)trans); 2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return context; 2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} // namespace WebCore 2505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif // !OS(DARWIN) && USE(WEBAUDIO_FFMPEG) 2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif // ENABLE(WEB_AUDIO) 254