1 /* 2 * Copyright (C) 2010 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 Computer, 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 #ifndef FFTFrame_h 30 #define FFTFrame_h 31 32 #include "AudioArray.h" 33 34 #if OS(DARWIN) && !USE(WEBAUDIO_FFMPEG) 35 #define USE_ACCELERATE_FFT 1 36 #else 37 #define USE_ACCELERATE_FFT 0 38 #endif 39 40 #if USE_ACCELERATE_FFT 41 #include <Accelerate/Accelerate.h> 42 #endif 43 44 #if !USE_ACCELERATE_FFT 45 46 #if USE(WEBAUDIO_MKL) 47 #include "mkl_dfti.h" 48 #endif // USE(WEBAUDIO_MKL) 49 50 #if USE(WEBAUDIO_FFTW) 51 #include "fftw3.h" 52 #endif // USE(WEBAUDIO_FFTW) 53 54 #if USE(WEBAUDIO_FFMPEG) 55 struct RDFTContext; 56 #endif // USE(WEBAUDIO_FFMPEG) 57 58 #endif // !USE_ACCELERATE_FFT 59 60 #include <wtf/PassOwnPtr.h> 61 #include <wtf/Platform.h> 62 #include <wtf/Threading.h> 63 64 namespace WebCore { 65 66 // Defines the interface for an "FFT frame", an object which is able to perform a forward 67 // and reverse FFT, internally storing the resultant frequency-domain data. 68 69 class FFTFrame { 70 public: 71 // The constructors, destructor, and methods up to the CROSS-PLATFORM section have platform-dependent implementations. 72 73 FFTFrame(unsigned fftSize); 74 FFTFrame(); // creates a blank/empty frame for later use with createInterpolatedFrame() 75 FFTFrame(const FFTFrame& frame); 76 ~FFTFrame(); 77 78 static void initialize(); 79 static void cleanup(); 80 void doFFT(float* data); 81 void doInverseFFT(float* data); 82 void multiply(const FFTFrame& frame); // multiplies ourself with frame : effectively operator*=() 83 84 float* realData() const; 85 float* imagData() const; 86 87 void print(); // for debugging 88 89 // CROSS-PLATFORM 90 // The remaining public methods have cross-platform implementations: 91 92 // Interpolates from frame1 -> frame2 as x goes from 0.0 -> 1.0 93 static PassOwnPtr<FFTFrame> createInterpolatedFrame(const FFTFrame& frame1, const FFTFrame& frame2, double x); 94 95 void doPaddedFFT(float* data, size_t dataSize); // zero-padding with dataSize <= fftSize 96 double extractAverageGroupDelay(); 97 void addConstantGroupDelay(double sampleFrameDelay); 98 fftSize()99 unsigned fftSize() const { return m_FFTSize; } log2FFTSize()100 unsigned log2FFTSize() const { return m_log2FFTSize; } 101 102 private: 103 unsigned m_FFTSize; 104 unsigned m_log2FFTSize; 105 106 void interpolateFrequencyComponents(const FFTFrame& frame1, const FFTFrame& frame2, double x); 107 108 #if USE_ACCELERATE_FFT dspSplitComplex()109 DSPSplitComplex& dspSplitComplex() { return m_frame; } dspSplitComplex()110 DSPSplitComplex dspSplitComplex() const { return m_frame; } 111 112 static FFTSetup fftSetupForSize(unsigned fftSize); 113 114 static FFTSetup* fftSetups; 115 116 FFTSetup m_FFTSetup; 117 118 DSPSplitComplex m_frame; 119 AudioFloatArray m_realData; 120 AudioFloatArray m_imagData; 121 #else // !USE_ACCELERATE_FFT 122 123 #if USE(WEBAUDIO_MKL) 124 // Interleaves the planar real and imaginary data and returns a 125 // pointer to the resulting storage which can be used for in-place 126 // or out-of-place operations. FIXME: ideally all of the MKL 127 // routines would operate on planar data and this method would be 128 // removed. 129 float* getUpToDateComplexData(); 130 131 static DFTI_DESCRIPTOR_HANDLE descriptorHandleForSize(unsigned fftSize); 132 133 static DFTI_DESCRIPTOR_HANDLE* descriptorHandles; 134 135 DFTI_DESCRIPTOR_HANDLE m_handle; 136 AudioFloatArray m_complexData; 137 AudioFloatArray m_realData; 138 AudioFloatArray m_imagData; 139 #endif // USE(WEBAUDIO_MKL) 140 141 #if USE(WEBAUDIO_FFMPEG) 142 static RDFTContext* contextForSize(unsigned fftSize, int trans); 143 144 RDFTContext* m_forwardContext; 145 RDFTContext* m_inverseContext; 146 147 float* getUpToDateComplexData(); 148 AudioFloatArray m_complexData; 149 AudioFloatArray m_realData; 150 AudioFloatArray m_imagData; 151 #endif // USE(WEBAUDIO_FFMPEG) 152 153 #if USE(WEBAUDIO_FFTW) 154 fftwf_plan m_forwardPlan; 155 fftwf_plan m_backwardPlan; 156 157 enum Direction { 158 Forward, 159 Backward 160 }; 161 162 // Both the real and imaginary data are stored here. 163 // The real data is stored first, followed by three float values of padding. 164 // The imaginary data is stored after the padding and is 16-byte aligned (if m_data itself is aligned). 165 // The reason we don't use separate arrays for real and imaginary is because the FFTW plans are shared 166 // between FFTFrame instances and require that the real and imaginary data pointers be the same distance apart. 167 AudioFloatArray m_data; 168 169 static Mutex *s_planLock; 170 static fftwf_plan* fftwForwardPlans; 171 static fftwf_plan* fftwBackwardPlans; 172 173 static fftwf_plan fftwPlanForSize(unsigned fftSize, Direction, 174 float*, float*, float*); 175 #endif // USE(WEBAUDIO_FFTW) 176 177 #endif // !USE_ACCELERATE_FFT 178 }; 179 180 } // namespace WebCore 181 182 #endif // FFTFrame_h 183