Line data Source code
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 : #include "FFTConvolver.h"
30 : #include "mozilla/PodOperations.h"
31 :
32 : using namespace mozilla;
33 :
34 : namespace WebCore {
35 :
36 0 : FFTConvolver::FFTConvolver(size_t fftSize, size_t renderPhase)
37 : : m_frame(fftSize)
38 0 : , m_readWriteIndex(renderPhase % (fftSize / 2))
39 : {
40 0 : MOZ_ASSERT(fftSize >= 2 * WEBAUDIO_BLOCK_SIZE);
41 0 : m_inputBuffer.SetLength(fftSize);
42 0 : PodZero(m_inputBuffer.Elements(), fftSize);
43 0 : m_outputBuffer.SetLength(fftSize);
44 0 : PodZero(m_outputBuffer.Elements(), fftSize);
45 0 : m_lastOverlapBuffer.SetLength(fftSize / 2);
46 0 : PodZero(m_lastOverlapBuffer.Elements(), fftSize / 2);
47 0 : }
48 :
49 0 : size_t FFTConvolver::sizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
50 : {
51 0 : size_t amount = 0;
52 0 : amount += m_frame.SizeOfExcludingThis(aMallocSizeOf);
53 0 : amount += m_inputBuffer.ShallowSizeOfExcludingThis(aMallocSizeOf);
54 0 : amount += m_outputBuffer.ShallowSizeOfExcludingThis(aMallocSizeOf);
55 0 : amount += m_lastOverlapBuffer.ShallowSizeOfExcludingThis(aMallocSizeOf);
56 0 : return amount;
57 : }
58 :
59 0 : size_t FFTConvolver::sizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
60 : {
61 0 : return aMallocSizeOf(this) + sizeOfExcludingThis(aMallocSizeOf);
62 : }
63 :
64 0 : const float* FFTConvolver::process(FFTBlock* fftKernel, const float* sourceP)
65 : {
66 0 : size_t halfSize = fftSize() / 2;
67 :
68 : // WEBAUDIO_BLOCK_SIZE must be an exact multiple of halfSize,
69 : // halfSize must be a multiple of WEBAUDIO_BLOCK_SIZE
70 : // and > WEBAUDIO_BLOCK_SIZE.
71 0 : MOZ_ASSERT(halfSize % WEBAUDIO_BLOCK_SIZE == 0 &&
72 : WEBAUDIO_BLOCK_SIZE <= halfSize);
73 :
74 : // Copy samples to input buffer (note contraint above!)
75 0 : float* inputP = m_inputBuffer.Elements();
76 :
77 0 : MOZ_ASSERT(sourceP && inputP && m_readWriteIndex + WEBAUDIO_BLOCK_SIZE <= m_inputBuffer.Length());
78 :
79 0 : memcpy(inputP + m_readWriteIndex, sourceP, sizeof(float) * WEBAUDIO_BLOCK_SIZE);
80 :
81 0 : float* outputP = m_outputBuffer.Elements();
82 0 : m_readWriteIndex += WEBAUDIO_BLOCK_SIZE;
83 :
84 : // Check if it's time to perform the next FFT
85 0 : if (m_readWriteIndex == halfSize) {
86 : // The input buffer is now filled (get frequency-domain version)
87 0 : m_frame.PerformFFT(m_inputBuffer.Elements());
88 0 : m_frame.Multiply(*fftKernel);
89 0 : m_frame.GetInverseWithoutScaling(m_outputBuffer.Elements());
90 :
91 : // Overlap-add 1st half from previous time
92 0 : AudioBufferAddWithScale(m_lastOverlapBuffer.Elements(), 1.0f,
93 0 : m_outputBuffer.Elements(), halfSize);
94 :
95 : // Finally, save 2nd half of result
96 0 : MOZ_ASSERT(m_outputBuffer.Length() == 2 * halfSize && m_lastOverlapBuffer.Length() == halfSize);
97 :
98 0 : memcpy(m_lastOverlapBuffer.Elements(), m_outputBuffer.Elements() + halfSize, sizeof(float) * halfSize);
99 :
100 : // Reset index back to start for next time
101 0 : m_readWriteIndex = 0;
102 : }
103 :
104 0 : return outputP + m_readWriteIndex;
105 : }
106 :
107 0 : void FFTConvolver::reset()
108 : {
109 0 : PodZero(m_lastOverlapBuffer.Elements(), m_lastOverlapBuffer.Length());
110 0 : m_readWriteIndex = 0;
111 0 : }
112 :
113 0 : size_t FFTConvolver::latencyFrames() const
114 : {
115 0 : return std::max<size_t>(fftSize()/2, WEBAUDIO_BLOCK_SIZE) -
116 0 : WEBAUDIO_BLOCK_SIZE;
117 : }
118 :
119 : } // namespace WebCore
|