content/media/webaudio/FFTBlock.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
michael@0 3 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #ifndef FFTBlock_h_
michael@0 8 #define FFTBlock_h_
michael@0 9
michael@0 10 #include "nsTArray.h"
michael@0 11 #include "AudioNodeEngine.h"
michael@0 12 #include "kiss_fft/kiss_fftr.h"
michael@0 13
michael@0 14 namespace mozilla {
michael@0 15
michael@0 16 // This class defines an FFT block, loosely modeled after Blink's FFTFrame
michael@0 17 // class to make sharing code with Blink easy.
michael@0 18 // Currently it's implemented on top of KissFFT on all platforms.
michael@0 19 class FFTBlock {
michael@0 20 public:
michael@0 21 explicit FFTBlock(uint32_t aFFTSize)
michael@0 22 : mFFT(nullptr)
michael@0 23 , mIFFT(nullptr)
michael@0 24 , mFFTSize(aFFTSize)
michael@0 25 {
michael@0 26 MOZ_COUNT_CTOR(FFTBlock);
michael@0 27 mOutputBuffer.SetLength(aFFTSize / 2 + 1);
michael@0 28 PodZero(mOutputBuffer.Elements(), aFFTSize / 2 + 1);
michael@0 29 }
michael@0 30 ~FFTBlock()
michael@0 31 {
michael@0 32 MOZ_COUNT_DTOR(FFTBlock);
michael@0 33 Clear();
michael@0 34 }
michael@0 35
michael@0 36 // Return a new FFTBlock with frequency components interpolated between
michael@0 37 // |block0| and |block1| with |interp| between 0.0 and 1.0.
michael@0 38 static FFTBlock*
michael@0 39 CreateInterpolatedBlock(const FFTBlock& block0,
michael@0 40 const FFTBlock& block1, double interp);
michael@0 41
michael@0 42 // Transform FFTSize() points of aData and store the result internally.
michael@0 43 void PerformFFT(const float* aData)
michael@0 44 {
michael@0 45 EnsureFFT();
michael@0 46 kiss_fftr(mFFT, aData, mOutputBuffer.Elements());
michael@0 47 }
michael@0 48 // Inverse-transform internal data and store the resulting FFTSize()
michael@0 49 // points in aData.
michael@0 50 void GetInverse(float* aDataOut)
michael@0 51 {
michael@0 52 GetInverseWithoutScaling(aDataOut);
michael@0 53 AudioBufferInPlaceScale(aDataOut, 1.0f / mFFTSize, mFFTSize);
michael@0 54 }
michael@0 55 // Inverse-transform internal frequency data and store the resulting
michael@0 56 // FFTSize() points in |aDataOut|. If frequency data has not already been
michael@0 57 // scaled, then the output will need scaling by 1/FFTSize().
michael@0 58 void GetInverseWithoutScaling(float* aDataOut)
michael@0 59 {
michael@0 60 EnsureIFFT();
michael@0 61 kiss_fftri(mIFFT, mOutputBuffer.Elements(), aDataOut);
michael@0 62 }
michael@0 63 // Inverse-transform the FFTSize()/2+1 points of data in each
michael@0 64 // of aRealDataIn and aImagDataIn and store the resulting
michael@0 65 // FFTSize() points in aRealDataOut.
michael@0 66 void PerformInverseFFT(float* aRealDataIn,
michael@0 67 float *aImagDataIn,
michael@0 68 float *aRealDataOut)
michael@0 69 {
michael@0 70 EnsureIFFT();
michael@0 71 const uint32_t inputSize = mFFTSize / 2 + 1;
michael@0 72 nsTArray<kiss_fft_cpx> inputBuffer;
michael@0 73 inputBuffer.SetLength(inputSize);
michael@0 74 for (uint32_t i = 0; i < inputSize; ++i) {
michael@0 75 inputBuffer[i].r = aRealDataIn[i];
michael@0 76 inputBuffer[i].i = aImagDataIn[i];
michael@0 77 }
michael@0 78 kiss_fftri(mIFFT, inputBuffer.Elements(), aRealDataOut);
michael@0 79 for (uint32_t i = 0; i < mFFTSize; ++i) {
michael@0 80 aRealDataOut[i] /= mFFTSize;
michael@0 81 }
michael@0 82 }
michael@0 83
michael@0 84 void Multiply(const FFTBlock& aFrame)
michael@0 85 {
michael@0 86 BufferComplexMultiply(reinterpret_cast<const float*>(mOutputBuffer.Elements()),
michael@0 87 reinterpret_cast<const float*>(aFrame.mOutputBuffer.Elements()),
michael@0 88 reinterpret_cast<float*>(mOutputBuffer.Elements()),
michael@0 89 mFFTSize / 2 + 1);
michael@0 90 }
michael@0 91
michael@0 92 // Perform a forward FFT on |aData|, assuming zeros after dataSize samples,
michael@0 93 // and pre-scale the generated internal frequency domain coefficients so
michael@0 94 // that GetInverseWithoutScaling() can be used to transform to the time
michael@0 95 // domain. This is useful for convolution kernels.
michael@0 96 void PadAndMakeScaledDFT(const float* aData, size_t dataSize)
michael@0 97 {
michael@0 98 MOZ_ASSERT(dataSize <= FFTSize());
michael@0 99 nsTArray<float> paddedData;
michael@0 100 paddedData.SetLength(FFTSize());
michael@0 101 AudioBufferCopyWithScale(aData, 1.0f / FFTSize(),
michael@0 102 paddedData.Elements(), dataSize);
michael@0 103 PodZero(paddedData.Elements() + dataSize, mFFTSize - dataSize);
michael@0 104 PerformFFT(paddedData.Elements());
michael@0 105 }
michael@0 106
michael@0 107 void SetFFTSize(uint32_t aSize)
michael@0 108 {
michael@0 109 mFFTSize = aSize;
michael@0 110 mOutputBuffer.SetLength(aSize / 2 + 1);
michael@0 111 PodZero(mOutputBuffer.Elements(), aSize / 2 + 1);
michael@0 112 Clear();
michael@0 113 }
michael@0 114
michael@0 115 // Return the average group delay and removes this from the frequency data.
michael@0 116 double ExtractAverageGroupDelay();
michael@0 117
michael@0 118 uint32_t FFTSize() const
michael@0 119 {
michael@0 120 return mFFTSize;
michael@0 121 }
michael@0 122 float RealData(uint32_t aIndex) const
michael@0 123 {
michael@0 124 return mOutputBuffer[aIndex].r;
michael@0 125 }
michael@0 126 float ImagData(uint32_t aIndex) const
michael@0 127 {
michael@0 128 return mOutputBuffer[aIndex].i;
michael@0 129 }
michael@0 130
michael@0 131 size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
michael@0 132 {
michael@0 133 size_t amount = 0;
michael@0 134 amount += aMallocSizeOf(mFFT);
michael@0 135 amount += aMallocSizeOf(mIFFT);
michael@0 136 amount += mOutputBuffer.SizeOfExcludingThis(aMallocSizeOf);
michael@0 137 return amount;
michael@0 138 }
michael@0 139
michael@0 140 size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
michael@0 141 {
michael@0 142 return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
michael@0 143 }
michael@0 144
michael@0 145 private:
michael@0 146 FFTBlock(const FFTBlock& other) MOZ_DELETE;
michael@0 147 void operator=(const FFTBlock& other) MOZ_DELETE;
michael@0 148
michael@0 149 void EnsureFFT()
michael@0 150 {
michael@0 151 if (!mFFT) {
michael@0 152 mFFT = kiss_fftr_alloc(mFFTSize, 0, nullptr, nullptr);
michael@0 153 }
michael@0 154 }
michael@0 155 void EnsureIFFT()
michael@0 156 {
michael@0 157 if (!mIFFT) {
michael@0 158 mIFFT = kiss_fftr_alloc(mFFTSize, 1, nullptr, nullptr);
michael@0 159 }
michael@0 160 }
michael@0 161 void Clear()
michael@0 162 {
michael@0 163 free(mFFT);
michael@0 164 free(mIFFT);
michael@0 165 mFFT = mIFFT = nullptr;
michael@0 166 }
michael@0 167 void AddConstantGroupDelay(double sampleFrameDelay);
michael@0 168 void InterpolateFrequencyComponents(const FFTBlock& block0,
michael@0 169 const FFTBlock& block1, double interp);
michael@0 170
michael@0 171 kiss_fftr_cfg mFFT, mIFFT;
michael@0 172 nsTArray<kiss_fft_cpx> mOutputBuffer;
michael@0 173 uint32_t mFFTSize;
michael@0 174 };
michael@0 175
michael@0 176 }
michael@0 177
michael@0 178 #endif
michael@0 179

mercurial