content/media/webaudio/blink/FFTConvolver.cpp

Fri, 16 Jan 2015 04:50:19 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 04:50:19 +0100
branch
TOR_BUG_9701
changeset 13
44a2da4a2ab2
permissions
-rw-r--r--

Replace accessor implementation with direct member state manipulation, by
request https://trac.torproject.org/projects/tor/ticket/9701#comment:32

michael@0 1 /*
michael@0 2 * Copyright (C) 2010 Google Inc. All rights reserved.
michael@0 3 *
michael@0 4 * Redistribution and use in source and binary forms, with or without
michael@0 5 * modification, are permitted provided that the following conditions
michael@0 6 * are met:
michael@0 7 *
michael@0 8 * 1. Redistributions of source code must retain the above copyright
michael@0 9 * notice, this list of conditions and the following disclaimer.
michael@0 10 * 2. Redistributions in binary form must reproduce the above copyright
michael@0 11 * notice, this list of conditions and the following disclaimer in the
michael@0 12 * documentation and/or other materials provided with the distribution.
michael@0 13 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
michael@0 14 * its contributors may be used to endorse or promote products derived
michael@0 15 * from this software without specific prior written permission.
michael@0 16 *
michael@0 17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
michael@0 18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
michael@0 19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
michael@0 20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
michael@0 21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
michael@0 22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
michael@0 23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
michael@0 24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
michael@0 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
michael@0 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
michael@0 27 */
michael@0 28
michael@0 29 #include "FFTConvolver.h"
michael@0 30 #include "mozilla/PodOperations.h"
michael@0 31
michael@0 32 using namespace mozilla;
michael@0 33
michael@0 34 namespace WebCore {
michael@0 35
michael@0 36 FFTConvolver::FFTConvolver(size_t fftSize)
michael@0 37 : m_frame(fftSize)
michael@0 38 , m_readWriteIndex(0)
michael@0 39 {
michael@0 40 m_inputBuffer.SetLength(fftSize);
michael@0 41 PodZero(m_inputBuffer.Elements(), fftSize);
michael@0 42 m_outputBuffer.SetLength(fftSize);
michael@0 43 PodZero(m_outputBuffer.Elements(), fftSize);
michael@0 44 m_lastOverlapBuffer.SetLength(fftSize / 2);
michael@0 45 PodZero(m_lastOverlapBuffer.Elements(), fftSize / 2);
michael@0 46 }
michael@0 47
michael@0 48 size_t FFTConvolver::sizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
michael@0 49 {
michael@0 50 size_t amount = 0;
michael@0 51 amount += m_frame.SizeOfExcludingThis(aMallocSizeOf);
michael@0 52 amount += m_inputBuffer.SizeOfExcludingThis(aMallocSizeOf);
michael@0 53 amount += m_outputBuffer.SizeOfExcludingThis(aMallocSizeOf);
michael@0 54 amount += m_lastOverlapBuffer.SizeOfExcludingThis(aMallocSizeOf);
michael@0 55 return amount;
michael@0 56 }
michael@0 57
michael@0 58 size_t FFTConvolver::sizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
michael@0 59 {
michael@0 60 return aMallocSizeOf(this) + sizeOfExcludingThis(aMallocSizeOf);
michael@0 61 }
michael@0 62
michael@0 63 void FFTConvolver::process(FFTBlock* fftKernel, const float* sourceP, float* destP, size_t framesToProcess)
michael@0 64 {
michael@0 65 size_t halfSize = fftSize() / 2;
michael@0 66
michael@0 67 // framesToProcess must be an exact multiple of halfSize,
michael@0 68 // or halfSize is a multiple of framesToProcess when halfSize > framesToProcess.
michael@0 69 bool isGood = !(halfSize % framesToProcess && framesToProcess % halfSize);
michael@0 70 MOZ_ASSERT(isGood);
michael@0 71 if (!isGood)
michael@0 72 return;
michael@0 73
michael@0 74 size_t numberOfDivisions = halfSize <= framesToProcess ? (framesToProcess / halfSize) : 1;
michael@0 75 size_t divisionSize = numberOfDivisions == 1 ? framesToProcess : halfSize;
michael@0 76
michael@0 77 for (size_t i = 0; i < numberOfDivisions; ++i, sourceP += divisionSize, destP += divisionSize) {
michael@0 78 // Copy samples to input buffer (note contraint above!)
michael@0 79 float* inputP = m_inputBuffer.Elements();
michael@0 80
michael@0 81 // Sanity check
michael@0 82 bool isCopyGood1 = sourceP && inputP && m_readWriteIndex + divisionSize <= m_inputBuffer.Length();
michael@0 83 MOZ_ASSERT(isCopyGood1);
michael@0 84 if (!isCopyGood1)
michael@0 85 return;
michael@0 86
michael@0 87 memcpy(inputP + m_readWriteIndex, sourceP, sizeof(float) * divisionSize);
michael@0 88
michael@0 89 // Copy samples from output buffer
michael@0 90 float* outputP = m_outputBuffer.Elements();
michael@0 91
michael@0 92 // Sanity check
michael@0 93 bool isCopyGood2 = destP && outputP && m_readWriteIndex + divisionSize <= m_outputBuffer.Length();
michael@0 94 MOZ_ASSERT(isCopyGood2);
michael@0 95 if (!isCopyGood2)
michael@0 96 return;
michael@0 97
michael@0 98 memcpy(destP, outputP + m_readWriteIndex, sizeof(float) * divisionSize);
michael@0 99 m_readWriteIndex += divisionSize;
michael@0 100
michael@0 101 // Check if it's time to perform the next FFT
michael@0 102 if (m_readWriteIndex == halfSize) {
michael@0 103 // The input buffer is now filled (get frequency-domain version)
michael@0 104 m_frame.PerformFFT(m_inputBuffer.Elements());
michael@0 105 m_frame.Multiply(*fftKernel);
michael@0 106 m_frame.GetInverseWithoutScaling(m_outputBuffer.Elements());
michael@0 107
michael@0 108 // Overlap-add 1st half from previous time
michael@0 109 AudioBufferAddWithScale(m_lastOverlapBuffer.Elements(), 1.0f,
michael@0 110 m_outputBuffer.Elements(), halfSize);
michael@0 111
michael@0 112 // Finally, save 2nd half of result
michael@0 113 bool isCopyGood3 = m_outputBuffer.Length() == 2 * halfSize && m_lastOverlapBuffer.Length() == halfSize;
michael@0 114 MOZ_ASSERT(isCopyGood3);
michael@0 115 if (!isCopyGood3)
michael@0 116 return;
michael@0 117
michael@0 118 memcpy(m_lastOverlapBuffer.Elements(), m_outputBuffer.Elements() + halfSize, sizeof(float) * halfSize);
michael@0 119
michael@0 120 // Reset index back to start for next time
michael@0 121 m_readWriteIndex = 0;
michael@0 122 }
michael@0 123 }
michael@0 124 }
michael@0 125
michael@0 126 void FFTConvolver::reset()
michael@0 127 {
michael@0 128 PodZero(m_lastOverlapBuffer.Elements(), m_lastOverlapBuffer.Length());
michael@0 129 m_readWriteIndex = 0;
michael@0 130 }
michael@0 131
michael@0 132 } // namespace WebCore

mercurial