• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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