Backed out changeset 2a08b161b02e (bug 926838)

This commit is contained in:
Carsten "Tomcat" Book 2015-05-05 15:51:27 +02:00
parent 4719e01a6e
commit 1084384de1
11 changed files with 64 additions and 246 deletions

View file

@ -1,85 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef AlignedTArray_h__
#define AlignedTArray_h__
#include "mozilla/Alignment.h"
#include "nsTArray.h"
/**
* E: element type, must be a POD type.
* N: N bytes alignment for the first element, defaults to 32
*/
template <typename E, int N, typename Alloc>
class AlignedTArray_Impl : public nsTArray_Impl<E, Alloc>
{
static_assert((N & (N-1)) == 0, "N must be power of 2");
typedef nsTArray_Impl<E, Alloc> base_type;
public:
typedef E elem_type;
typedef typename base_type::size_type size_type;
typedef typename base_type::index_type index_type;
AlignedTArray_Impl() {}
explicit AlignedTArray_Impl(size_type capacity) : base_type(capacity+sExtra) {}
elem_type* Elements() { return getAligned(base_type::Elements()); }
const elem_type* Elements() const { return getAligned(base_type::Elements()); }
elem_type& operator[](index_type i) { return Elements()[i];}
const elem_type& operator[](index_type i) const { return Elements()[i]; }
typename Alloc::ResultType SetLength(size_type newLen) {
return base_type::SetLength(newLen + sExtra);
}
size_type Length() const {
return base_type::Length() <= sExtra ? 0 : base_type::Length() - sExtra;
}
private:
AlignedTArray_Impl(const AlignedTArray_Impl& other) = delete;
void operator=(const AlignedTArray_Impl& other) = delete;
static const size_type sPadding = N <= MOZ_ALIGNOF(E) ? 0 : N - MOZ_ALIGNOF(E);
static const size_type sExtra = (sPadding + sizeof(E) - 1) / sizeof(E);
template <typename U>
static U* getAligned(U* p)
{
return reinterpret_cast<U*>(((uintptr_t)p + N - 1) & ~(N-1));
}
};
template <typename E, int N=32>
class AlignedTArray : public AlignedTArray_Impl<E, N, nsTArrayInfallibleAllocator>
{
public:
typedef AlignedTArray_Impl<E, N, nsTArrayInfallibleAllocator> base_type;
typedef AlignedTArray<E, N> self_type;
typedef typename base_type::size_type size_type;
AlignedTArray() {}
explicit AlignedTArray(size_type capacity) : base_type(capacity) {}
private:
AlignedTArray(const AlignedTArray& other) = delete;
void operator=(const AlignedTArray& other) = delete;
};
template <typename E, int N=32>
class AlignedFallibleTArray : public AlignedTArray_Impl<E, N, nsTArrayFallibleAllocator>
{
public:
typedef AlignedTArray_Impl<E, N, nsTArrayFallibleAllocator> base_type;
typedef AlignedFallibleTArray<E, N> self_type;
typedef typename base_type::size_type size_type;
AlignedFallibleTArray() {}
explicit AlignedFallibleTArray(size_type capacity) : base_type(capacity) {}
private:
AlignedFallibleTArray(const AlignedFallibleTArray& other) = delete;
void operator=(const AlignedFallibleTArray& other) = delete;
};
#endif // AlignedTArray_h__

View file

@ -251,16 +251,17 @@ bool
AnalyserNode::FFTAnalysis() AnalyserNode::FFTAnalysis()
{ {
float* inputBuffer; float* inputBuffer;
AlignedFallibleTArray<float> tmpBuffer; bool allocated = false;
if (mWriteIndex == 0) { if (mWriteIndex == 0) {
inputBuffer = mBuffer.Elements(); inputBuffer = mBuffer.Elements();
} else { } else {
if (tmpBuffer.SetLength(FftSize())) { inputBuffer = static_cast<float*>(malloc(FftSize() * sizeof(float)));
if (!inputBuffer) {
return false; return false;
} }
inputBuffer = tmpBuffer.Elements();
memcpy(inputBuffer, mBuffer.Elements() + mWriteIndex, sizeof(float) * (FftSize() - mWriteIndex)); memcpy(inputBuffer, mBuffer.Elements() + mWriteIndex, sizeof(float) * (FftSize() - mWriteIndex));
memcpy(inputBuffer + FftSize() - mWriteIndex, mBuffer.Elements(), sizeof(float) * mWriteIndex); memcpy(inputBuffer + FftSize() - mWriteIndex, mBuffer.Elements(), sizeof(float) * mWriteIndex);
allocated = true;
} }
ApplyBlackmanWindow(inputBuffer, FftSize()); ApplyBlackmanWindow(inputBuffer, FftSize());
@ -278,6 +279,9 @@ AnalyserNode::FFTAnalysis()
(1.0 - mSmoothingTimeConstant) * scalarMagnitude; (1.0 - mSmoothingTimeConstant) * scalarMagnitude;
} }
if (allocated) {
free(inputBuffer);
}
return true; return true;
} }
@ -301,16 +305,16 @@ AnalyserNode::AllocateBuffer()
{ {
bool result = true; bool result = true;
if (mBuffer.Length() != FftSize()) { if (mBuffer.Length() != FftSize()) {
if (mBuffer.SetLength(FftSize())) { result = mBuffer.SetLength(FftSize());
return false; if (result) {
} memset(mBuffer.Elements(), 0, sizeof(float) * FftSize());
memset(mBuffer.Elements(), 0, sizeof(float) * FftSize()); mWriteIndex = 0;
mWriteIndex = 0;
if (mOutputBuffer.SetLength(FrequencyBinCount())) { result = mOutputBuffer.SetLength(FrequencyBinCount());
return false; if (result) {
memset(mOutputBuffer.Elements(), 0, sizeof(float) * FrequencyBinCount());
}
} }
memset(mOutputBuffer.Elements(), 0, sizeof(float) * FrequencyBinCount());
} }
return result; return result;
} }

View file

@ -9,7 +9,6 @@
#include "AudioNode.h" #include "AudioNode.h"
#include "FFTBlock.h" #include "FFTBlock.h"
#include "AlignedTArray.h"
namespace mozilla { namespace mozilla {
namespace dom { namespace dom {
@ -78,8 +77,8 @@ private:
double mMaxDecibels; double mMaxDecibels;
double mSmoothingTimeConstant; double mSmoothingTimeConstant;
uint32_t mWriteIndex; uint32_t mWriteIndex;
AlignedFallibleTArray<float> mBuffer; FallibleTArray<float> mBuffer;
AlignedFallibleTArray<float> mOutputBuffer; FallibleTArray<float> mOutputBuffer;
}; };
} }

View file

@ -44,7 +44,8 @@ FFTBlock* FFTBlock::CreateInterpolatedBlock(const FFTBlock& block0, const FFTBlo
// In the time-domain, the 2nd half of the response must be zero, to avoid circular convolution aliasing... // In the time-domain, the 2nd half of the response must be zero, to avoid circular convolution aliasing...
int fftSize = newBlock->FFTSize(); int fftSize = newBlock->FFTSize();
AlignedTArray<float> buffer(fftSize); nsTArray<float> buffer;
buffer.SetLength(fftSize);
newBlock->GetInverseWithoutScaling(buffer.Elements()); newBlock->GetInverseWithoutScaling(buffer.Elements());
AudioBufferInPlaceScale(buffer.Elements(), 1.0f / fftSize, fftSize / 2); AudioBufferInPlaceScale(buffer.Elements(), 1.0f / fftSize, fftSize / 2);
PodZero(buffer.Elements() + fftSize / 2, fftSize / 2); PodZero(buffer.Elements() + fftSize / 2, fftSize / 2);
@ -59,10 +60,10 @@ void FFTBlock::InterpolateFrequencyComponents(const FFTBlock& block0, const FFTB
{ {
// FIXME : with some work, this method could be optimized // FIXME : with some work, this method could be optimized
ComplexU* dft = mOutputBuffer.Elements(); kiss_fft_cpx* dft = mOutputBuffer.Elements();
const ComplexU* dft1 = block0.mOutputBuffer.Elements(); const kiss_fft_cpx* dft1 = block0.mOutputBuffer.Elements();
const ComplexU* dft2 = block1.mOutputBuffer.Elements(); const kiss_fft_cpx* dft2 = block1.mOutputBuffer.Elements();
MOZ_ASSERT(mFFTSize == block0.FFTSize()); MOZ_ASSERT(mFFTSize == block0.FFTSize());
MOZ_ASSERT(mFFTSize == block1.FFTSize()); MOZ_ASSERT(mFFTSize == block1.FFTSize());
@ -153,7 +154,7 @@ void FFTBlock::InterpolateFrequencyComponents(const FFTBlock& block0, const FFTB
double FFTBlock::ExtractAverageGroupDelay() double FFTBlock::ExtractAverageGroupDelay()
{ {
ComplexU* dft = mOutputBuffer.Elements(); kiss_fft_cpx* dft = mOutputBuffer.Elements();
double aveSum = 0.0; double aveSum = 0.0;
double weightSum = 0.0; double weightSum = 0.0;
@ -204,7 +205,7 @@ void FFTBlock::AddConstantGroupDelay(double sampleFrameDelay)
{ {
int halfSize = FFTSize() / 2; int halfSize = FFTSize() / 2;
ComplexU* dft = mOutputBuffer.Elements(); kiss_fft_cpx* dft = mOutputBuffer.Elements();
const double kSamplePhaseDelay = (2.0 * M_PI) / double(FFTSize()); const double kSamplePhaseDelay = (2.0 * M_PI) / double(FFTSize());

View file

@ -7,13 +7,7 @@
#ifndef FFTBlock_h_ #ifndef FFTBlock_h_
#define FFTBlock_h_ #define FFTBlock_h_
#ifdef BUILD_ARM_NEON #include "nsTArray.h"
#include <cmath>
#include "mozilla/arm.h"
#include "dl/sp/api/omxSP.h"
#endif
#include "AlignedTArray.h"
#include "AudioNodeEngine.h" #include "AudioNodeEngine.h"
#include "kiss_fft/kiss_fftr.h" #include "kiss_fft/kiss_fftr.h"
@ -24,26 +18,15 @@ namespace mozilla {
// Currently it's implemented on top of KissFFT on all platforms. // Currently it's implemented on top of KissFFT on all platforms.
class FFTBlock final class FFTBlock final
{ {
union ComplexU {
kiss_fft_cpx c;
float f[2];
struct {
float r;
float i;
};
};
public: public:
explicit FFTBlock(uint32_t aFFTSize) explicit FFTBlock(uint32_t aFFTSize)
: mKissFFT(nullptr) : mFFT(nullptr)
, mKissIFFT(nullptr) , mIFFT(nullptr)
#ifdef BUILD_ARM_NEON , mFFTSize(aFFTSize)
, mOmxFFT(nullptr)
, mOmxIFFT(nullptr)
#endif
{ {
MOZ_COUNT_CTOR(FFTBlock); MOZ_COUNT_CTOR(FFTBlock);
SetFFTSize(aFFTSize); mOutputBuffer.SetLength(aFFTSize / 2 + 1);
PodZero(mOutputBuffer.Elements(), aFFTSize / 2 + 1);
} }
~FFTBlock() ~FFTBlock()
{ {
@ -61,17 +44,10 @@ public:
void PerformFFT(const float* aData) void PerformFFT(const float* aData)
{ {
EnsureFFT(); EnsureFFT();
#ifdef BUILD_ARM_NEON kiss_fftr(mFFT, aData, mOutputBuffer.Elements());
if (mozilla::supports_neon()) {
omxSP_FFTFwd_RToCCS_F32_Sfs(aData, mOutputBuffer.Elements()->f, mOmxFFT);
} else
#endif
{
kiss_fftr(mKissFFT, aData, &(mOutputBuffer.Elements()->c));
}
} }
// Inverse-transform internal data and store the resulting FFTSize() // Inverse-transform internal data and store the resulting FFTSize()
// points in aDataOut. // points in aData.
void GetInverse(float* aDataOut) void GetInverse(float* aDataOut)
{ {
GetInverseWithoutScaling(aDataOut); GetInverseWithoutScaling(aDataOut);
@ -83,17 +59,7 @@ public:
void GetInverseWithoutScaling(float* aDataOut) void GetInverseWithoutScaling(float* aDataOut)
{ {
EnsureIFFT(); EnsureIFFT();
#ifdef BUILD_ARM_NEON kiss_fftri(mIFFT, mOutputBuffer.Elements(), aDataOut);
if (mozilla::supports_neon()) {
omxSP_FFTInv_CCSToR_F32_Sfs(mOutputBuffer.Elements()->f, aDataOut, mOmxIFFT);
// There is no function that computes de inverse FFT without scaling, so
// we have to scale back up here. Bug 1158741.
AudioBufferInPlaceScale(aDataOut, mFFTSize, mFFTSize);
} else
#endif
{
kiss_fftri(mKissIFFT, &(mOutputBuffer.Elements()->c), aDataOut);
}
} }
// Inverse-transform the FFTSize()/2+1 points of data in each // Inverse-transform the FFTSize()/2+1 points of data in each
// of aRealDataIn and aImagDataIn and store the resulting // of aRealDataIn and aImagDataIn and store the resulting
@ -104,30 +70,23 @@ public:
{ {
EnsureIFFT(); EnsureIFFT();
const uint32_t inputSize = mFFTSize / 2 + 1; const uint32_t inputSize = mFFTSize / 2 + 1;
AlignedTArray<ComplexU> inputBuffer(inputSize); nsTArray<kiss_fft_cpx> inputBuffer;
inputBuffer.SetLength(inputSize);
for (uint32_t i = 0; i < inputSize; ++i) { for (uint32_t i = 0; i < inputSize; ++i) {
inputBuffer[i].r = aRealDataIn[i]; inputBuffer[i].r = aRealDataIn[i];
inputBuffer[i].i = aImagDataIn[i]; inputBuffer[i].i = aImagDataIn[i];
} }
#ifdef BUILD_ARM_NEON kiss_fftri(mIFFT, inputBuffer.Elements(), aRealDataOut);
if (mozilla::supports_neon()) { for (uint32_t i = 0; i < mFFTSize; ++i) {
omxSP_FFTInv_CCSToR_F32_Sfs(inputBuffer.Elements()->f, aRealDataOut[i] /= mFFTSize;
aRealDataOut, mOmxIFFT);
} else
#endif
{
kiss_fftri(mKissIFFT, &(inputBuffer.Elements()->c), aRealDataOut);
for (uint32_t i = 0; i < mFFTSize; ++i) {
aRealDataOut[i] /= mFFTSize;
}
} }
} }
void Multiply(const FFTBlock& aFrame) void Multiply(const FFTBlock& aFrame)
{ {
BufferComplexMultiply(mOutputBuffer.Elements()->f, BufferComplexMultiply(reinterpret_cast<const float*>(mOutputBuffer.Elements()),
aFrame.mOutputBuffer.Elements()->f, reinterpret_cast<const float*>(aFrame.mOutputBuffer.Elements()),
mOutputBuffer.Elements()->f, reinterpret_cast<float*>(mOutputBuffer.Elements()),
mFFTSize / 2 + 1); mFFTSize / 2 + 1);
} }
@ -138,7 +97,7 @@ public:
void PadAndMakeScaledDFT(const float* aData, size_t dataSize) void PadAndMakeScaledDFT(const float* aData, size_t dataSize)
{ {
MOZ_ASSERT(dataSize <= FFTSize()); MOZ_ASSERT(dataSize <= FFTSize());
AlignedTArray<float> paddedData; nsTArray<float> paddedData;
paddedData.SetLength(FFTSize()); paddedData.SetLength(FFTSize());
AudioBufferCopyWithScale(aData, 1.0f / FFTSize(), AudioBufferCopyWithScale(aData, 1.0f / FFTSize(),
paddedData.Elements(), dataSize); paddedData.Elements(), dataSize);
@ -173,8 +132,8 @@ public:
size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
{ {
size_t amount = 0; size_t amount = 0;
amount += aMallocSizeOf(mKissFFT); amount += aMallocSizeOf(mFFT);
amount += aMallocSizeOf(mKissIFFT); amount += aMallocSizeOf(mIFFT);
amount += mOutputBuffer.SizeOfExcludingThis(aMallocSizeOf); amount += mOutputBuffer.SizeOfExcludingThis(aMallocSizeOf);
return amount; return amount;
} }
@ -190,78 +149,31 @@ private:
void EnsureFFT() void EnsureFFT()
{ {
#ifdef BUILD_ARM_NEON if (!mFFT) {
if (mozilla::supports_neon()) { mFFT = kiss_fftr_alloc(mFFTSize, 0, nullptr, nullptr);
if (!mOmxFFT) {
mOmxFFT = createOmxFFT(mFFTSize);
}
} else
#endif
{
if (!mKissFFT) {
mKissFFT = kiss_fftr_alloc(mFFTSize, 0, nullptr, nullptr);
}
} }
} }
void EnsureIFFT() void EnsureIFFT()
{ {
#ifdef BUILD_ARM_NEON if (!mIFFT) {
if (mozilla::supports_neon()) { mIFFT = kiss_fftr_alloc(mFFTSize, 1, nullptr, nullptr);
if (!mOmxIFFT) {
mOmxIFFT = createOmxFFT(mFFTSize);
}
} else
#endif
{
if (!mKissIFFT) {
mKissIFFT = kiss_fftr_alloc(mFFTSize, 1, nullptr, nullptr);
}
} }
} }
#ifdef BUILD_ARM_NEON
static OMXFFTSpec_R_F32* createOmxFFT(uint32_t aFFTSize)
{
MOZ_ASSERT((aFFTSize & (aFFTSize-1)) == 0);
OMX_INT bufSize;
OMX_INT order = log((double)aFFTSize)/M_LN2;
MOZ_ASSERT(aFFTSize>>order == 1);
OMXResult status = omxSP_FFTGetBufSize_R_F32(order, &bufSize);
if (status == OMX_Sts_NoErr) {
OMXFFTSpec_R_F32* context = static_cast<OMXFFTSpec_R_F32*>(malloc(bufSize));
if (omxSP_FFTInit_R_F32(context, order) != OMX_Sts_NoErr) {
return nullptr;
}
return context;
}
return nullptr;
}
#endif
void Clear() void Clear()
{ {
#ifdef BUILD_ARM_NEON free(mFFT);
free(mOmxFFT); free(mIFFT);
free(mOmxIFFT); mFFT = mIFFT = nullptr;
mOmxFFT = mOmxIFFT = nullptr;
#endif
free(mKissFFT);
free(mKissIFFT);
mKissFFT = mKissIFFT = nullptr;
} }
void AddConstantGroupDelay(double sampleFrameDelay); void AddConstantGroupDelay(double sampleFrameDelay);
void InterpolateFrequencyComponents(const FFTBlock& block0, void InterpolateFrequencyComponents(const FFTBlock& block0,
const FFTBlock& block1, double interp); const FFTBlock& block1, double interp);
kiss_fftr_cfg mKissFFT; kiss_fftr_cfg mFFT, mIFFT;
kiss_fftr_cfg mKissIFFT; nsTArray<kiss_fft_cpx> mOutputBuffer;
#ifdef BUILD_ARM_NEON
OMXFFTSpec_R_F32* mOmxFFT;
OMXFFTSpec_R_F32* mOmxIFFT;
#endif
AlignedTArray<ComplexU> mOutputBuffer;
uint32_t mFFTSize; uint32_t mFFTSize;
}; };
} }
#endif #endif

View file

@ -35,7 +35,7 @@
namespace WebCore { namespace WebCore {
typedef AlignedTArray<float> AlignedAudioFloatArray; typedef nsTArray<float> AudioFloatArray;
using mozilla::FFTBlock; using mozilla::FFTBlock;
class FFTConvolver { class FFTConvolver {
@ -66,13 +66,13 @@ private:
// Buffer input until we get fftSize / 2 samples then do an FFT // Buffer input until we get fftSize / 2 samples then do an FFT
size_t m_readWriteIndex; size_t m_readWriteIndex;
AlignedAudioFloatArray m_inputBuffer; AudioFloatArray m_inputBuffer;
// Stores output which we read a little at a time // Stores output which we read a little at a time
AlignedAudioFloatArray m_outputBuffer; AudioFloatArray m_outputBuffer;
// Saves the 2nd half of the FFT buffer, so we can do an overlap-add with the 1st half of the next one // Saves the 2nd half of the FFT buffer, so we can do an overlap-add with the 1st half of the next one
AlignedAudioFloatArray m_lastOverlapBuffer; AudioFloatArray m_lastOverlapBuffer;
}; };
} // namespace WebCore } // namespace WebCore

View file

@ -51,14 +51,6 @@ HRTFKernel::HRTFKernel(float* impulseResponse, size_t length, float sampleRate)
: m_frameDelay(0) : m_frameDelay(0)
, m_sampleRate(sampleRate) , m_sampleRate(sampleRate)
{ {
AlignedTArray<float> buffer;
// copy to a 32-byte aligned buffer
if (((uintptr_t)impulseResponse & 31) != 0) {
buffer.SetLength(length);
mozilla::PodCopy(buffer.Elements(), impulseResponse, length);
impulseResponse = buffer.Elements();
}
// Determine the leading delay (average group delay) for the response. // Determine the leading delay (average group delay) for the response.
m_frameDelay = extractAverageGroupDelay(impulseResponse, length); m_frameDelay = extractAverageGroupDelay(impulseResponse, length);

View file

@ -35,8 +35,6 @@ struct AudioChunk;
namespace WebCore { namespace WebCore {
typedef nsTArray<float> AudioFloatArray;
class HRTFDatabaseLoader; class HRTFDatabaseLoader;
using mozilla::AudioChunk; using mozilla::AudioChunk;

View file

@ -220,7 +220,7 @@ void PeriodicWave::createBandLimitedTables(const float* realData, const float* i
imagP[halfSize-1] = 0; imagP[halfSize-1] = 0;
// Create the band-limited table. // Create the band-limited table.
AlignedAudioFloatArray* table = new AlignedAudioFloatArray(m_periodicWaveSize); AudioFloatArray* table = new AudioFloatArray(m_periodicWaveSize);
m_bandLimitedTables.AppendElement(table); m_bandLimitedTables.AppendElement(table);
// Apply an inverse FFT to generate the time-domain table data. // Apply an inverse FFT to generate the time-domain table data.

View file

@ -32,12 +32,10 @@
#include "mozilla/dom/OscillatorNodeBinding.h" #include "mozilla/dom/OscillatorNodeBinding.h"
#include <nsAutoPtr.h> #include <nsAutoPtr.h>
#include <nsTArray.h> #include <nsTArray.h>
#include "AlignedTArray.h"
#include "mozilla/MemoryReporting.h" #include "mozilla/MemoryReporting.h"
namespace WebCore { namespace WebCore {
typedef AlignedTArray<float> AlignedAudioFloatArray;
typedef nsTArray<float> AudioFloatArray; typedef nsTArray<float> AudioFloatArray;
class PeriodicWave { class PeriodicWave {
@ -100,7 +98,7 @@ private:
// Creates tables based on numberOfComponents Fourier coefficients. // Creates tables based on numberOfComponents Fourier coefficients.
void createBandLimitedTables(const float* real, const float* imag, unsigned numberOfComponents); void createBandLimitedTables(const float* real, const float* imag, unsigned numberOfComponents);
nsTArray<nsAutoPtr<AlignedAudioFloatArray> > m_bandLimitedTables; nsTArray<nsAutoPtr<AudioFloatArray> > m_bandLimitedTables;
}; };
} // namespace WebCore } // namespace WebCore

View file

@ -21,7 +21,6 @@ MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']
BROWSER_CHROME_MANIFESTS += ['test/browser.ini'] BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
EXPORTS += [ EXPORTS += [
'AlignedTArray.h',
'AudioContext.h', 'AudioContext.h',
'AudioEventTimeline.h', 'AudioEventTimeline.h',
'AudioNodeEngine.h', 'AudioNodeEngine.h',