1/* 2 * Copyright (C) 2011 Google Inc. All rights reserved. 3 * Copyright (C) 2012 Intel Inc. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 16 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 19 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27// FFTFrame implementation using Intel IPP's DFT algorithm, 28// suitable for use on Linux. 29 30#include "config.h" 31 32#if ENABLE(WEB_AUDIO) 33 34#if USE(WEBAUDIO_IPP) 35 36#include "platform/audio/FFTFrame.h" 37 38#include "wtf/MathExtras.h" 39 40namespace blink { 41 42const unsigned maximumFFTPower2Size = 24; 43 44// Normal constructor: allocates for a given fftSize. 45FFTFrame::FFTFrame(unsigned fftSize) 46 : m_FFTSize(fftSize) 47 , m_log2FFTSize(static_cast<unsigned>(log2(fftSize))) 48 , m_realData(fftSize / 2) 49 , m_imagData(fftSize / 2) 50 , m_complexData(fftSize) 51{ 52 // We only allow power of two. 53 ASSERT(1UL << m_log2FFTSize == m_FFTSize); 54 ASSERT(m_log2FFTSize <= maximumFFTPower2Size); 55 56 ippsDFTInitAlloc_R_32f(&m_DFTSpec, m_FFTSize, IPP_FFT_NODIV_BY_ANY, ippAlgHintFast); 57 int bufferSize = 0; 58 ippsDFTGetBufSize_R_32f(m_DFTSpec, &bufferSize); 59 m_buffer = ippsMalloc_8u(bufferSize); 60} 61 62// Creates a blank/empty frame (interpolate() must later be called). 63FFTFrame::FFTFrame() 64 : m_FFTSize(0) 65 , m_log2FFTSize(0) 66{ 67} 68 69// Copy constructor. 70FFTFrame::FFTFrame(const FFTFrame& frame) 71 : m_FFTSize(frame.m_FFTSize) 72 , m_log2FFTSize(frame.m_log2FFTSize) 73 , m_realData(frame.m_FFTSize / 2) 74 , m_imagData(frame.m_FFTSize / 2) 75 , m_complexData(frame.m_FFTSize) 76{ 77 ippsDFTInitAlloc_R_32f(&m_DFTSpec, m_FFTSize, IPP_FFT_NODIV_BY_ANY, ippAlgHintFast); 78 int bufferSize = 0; 79 ippsDFTGetBufSize_R_32f(m_DFTSpec, &bufferSize); 80 m_buffer = ippsMalloc_8u(bufferSize); 81 82 // Copy/setup frame data. 83 unsigned numberOfBytes = sizeof(float) * m_FFTSize; 84 memcpy(realData(), frame.realData(), numberOfBytes); 85 memcpy(imagData(), frame.imagData(), numberOfBytes); 86} 87 88void FFTFrame::initialize() 89{ 90} 91 92void FFTFrame::cleanup() 93{ 94} 95 96FFTFrame::~FFTFrame() 97{ 98 ippsFree(m_buffer); 99 ippsDFTFree_R_32f(m_DFTSpec); 100} 101 102void FFTFrame::doFFT(const float* data) 103{ 104 Ipp32f* complexP = m_complexData.data(); 105 106 // Compute Forward transform to perm format. 107 ippsDFTFwd_RToPerm_32f(reinterpret_cast<Ipp32f*>(const_cast<float*>(data)), complexP, m_DFTSpec, m_buffer); 108 109 Ipp32f* realP = m_realData.data(); 110 Ipp32f* imagP = m_imagData.data(); 111 ippsCplxToReal_32fc(reinterpret_cast<Ipp32fc*>(complexP), realP, imagP, m_FFTSize >> 1); 112} 113 114void FFTFrame::doInverseFFT(float* data) 115{ 116 Ipp32f* complexP = getUpToDateComplexData(); 117 118 // Compute inverse transform. 119 ippsDFTInv_PermToR_32f(complexP, reinterpret_cast<Ipp32f*>(data), m_DFTSpec, m_buffer); 120 121 // Scale so that a forward then inverse FFT yields exactly the original data. 122 const float scale = 1.0 / m_FFTSize; 123 124 ippsMulC_32f_I(scale, reinterpret_cast<Ipp32f*>(data), m_FFTSize); 125} 126 127float* FFTFrame::getUpToDateComplexData() 128{ 129 int len = m_FFTSize >> 1; 130 // Merge the real and imagimary vectors to complex vector. 131 Ipp32f* realP = m_realData.data(); 132 Ipp32f* imagP = m_imagData.data(); 133 Ipp32fc* complexP = reinterpret_cast<Ipp32fc*>(m_complexData.data()); 134 ippsRealToCplx_32f(realP, imagP, complexP, len); 135 136 return const_cast<float*>(m_complexData.data()); 137} 138 139} // namespace blink 140 141#endif // USE(WEBAUDIO_IPP) 142 143#endif // ENABLE(WEB_AUDIO) 144