gecko-dev/dom/media/webaudio/AnalyserNode.h
Karl Tomlinson e33037127f bug 1184801 process AnalyserNode input only when required r=padenot
This moves the application of volume and averaging of channels to the main
thread, performed when required.  It avoids a potential allocation on the
graph thread.  If doing a full analysis for frequency data, the extra work on
the main thread should be negligible.  I assume that repeatedly fetching the
same time domain data with getFloatFrequencyData() is not something we need to
optimize for.  If, in rare circumstances, the extra main thread work turns out
to be significant, then the main thread work in getters is self-regulating,
but too much load on the graph thread leads to catastrophic failure in the
audio.

This also fixes some bugs:

Input and output streams for other consumers are not corrupted by in-place
scaling of data intended to be read-only.

When there are additional channels and fftSize < WEBAUDIO_BLOCK_SIZE, the
channels are not written past the current length of a buffer, so there is no
longer a dependency on nsTArray's behavior of never not reducing allocation
size on length changes.

The most recent fftSize samples are now used even when fftSize <
WEBAUDIO_BLOCK_SIZE, instead of the first fftSize samples in the most recent
block.

Enough time domain data is recorded so that getters will work immediately
following a change in fftSize.

--HG--
extra : rebase_source : bbd8a3e705d73781bb838a47261bf7d60cd1a9a7
2015-07-22 19:50:37 +12:00

91 lines
2.3 KiB
C++

/* -*- 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 AnalyserNode_h_
#define AnalyserNode_h_
#include "AudioNode.h"
#include "FFTBlock.h"
#include "AlignedTArray.h"
namespace mozilla {
namespace dom {
class AudioContext;
class AnalyserNode final : public AudioNode
{
public:
explicit AnalyserNode(AudioContext* aContext);
NS_DECL_ISUPPORTS_INHERITED
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
void GetFloatFrequencyData(const Float32Array& aArray);
void GetByteFrequencyData(const Uint8Array& aArray);
void GetFloatTimeDomainData(const Float32Array& aArray);
void GetByteTimeDomainData(const Uint8Array& aArray);
uint32_t FftSize() const
{
return mAnalysisBlock.FFTSize();
}
void SetFftSize(uint32_t aValue, ErrorResult& aRv);
uint32_t FrequencyBinCount() const
{
return FftSize() / 2;
}
double MinDecibels() const
{
return mMinDecibels;
}
void SetMinDecibels(double aValue, ErrorResult& aRv);
double MaxDecibels() const
{
return mMaxDecibels;
}
void SetMaxDecibels(double aValue, ErrorResult& aRv);
double SmoothingTimeConstant() const
{
return mSmoothingTimeConstant;
}
void SetSmoothingTimeConstant(double aValue, ErrorResult& aRv);
virtual const char* NodeType() const override
{
return "AnalyserNode";
}
virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const override;
virtual size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const override;
protected:
~AnalyserNode() {}
private:
friend class AnalyserNodeEngine;
void AppendChunk(const AudioChunk& aChunk);
bool AllocateBuffer();
bool FFTAnalysis();
void ApplyBlackmanWindow(float* aBuffer, uint32_t aSize);
void GetTimeDomainData(float* aData, size_t aLength);
private:
FFTBlock mAnalysisBlock;
nsTArray<AudioChunk> mChunks;
double mMinDecibels;
double mMaxDecibels;
double mSmoothingTimeConstant;
size_t mCurrentChunk = 0;
AlignedTArray<float> mOutputBuffer;
};
} // namespace dom
} // namespace mozilla
#endif