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
40 namespace blink {
41
42 const unsigned maximumFFTPower2Size = 24;
43
44 // Normal constructor: allocates for a given fftSize.
FFTFrame(unsigned fftSize)45 FFTFrame::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).
FFTFrame()63 FFTFrame::FFTFrame()
64 : m_FFTSize(0)
65 , m_log2FFTSize(0)
66 {
67 }
68
69 // Copy constructor.
FFTFrame(const FFTFrame & frame)70 FFTFrame::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
initialize()88 void FFTFrame::initialize()
89 {
90 }
91
cleanup()92 void FFTFrame::cleanup()
93 {
94 }
95
~FFTFrame()96 FFTFrame::~FFTFrame()
97 {
98 ippsFree(m_buffer);
99 ippsDFTFree_R_32f(m_DFTSpec);
100 }
101
doFFT(const float * data)102 void 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
doInverseFFT(float * data)114 void 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
getUpToDateComplexData()127 float* 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