Bug 855990 - Part 4: Send the buffer seen by AnalyserNodeEngine to AnalyserNode; r=padenot

--HG--
extra : rebase_source : be0b1c8197c1e8582d9dda31a74484901c665b79
This commit is contained in:
Ehsan Akhgari 2013-04-01 17:35:18 -04:00
parent ee7bcb26f4
commit 7b9c5e3aa8
2 changed files with 113 additions and 2 deletions

View File

@ -8,6 +8,7 @@
#include "mozilla/dom/AnalyserNodeBinding.h"
#include "AudioNodeEngine.h"
#include "AudioNodeStream.h"
#include "mozilla/Mutex.h"
namespace mozilla {
namespace dom {
@ -17,13 +18,58 @@ NS_IMPL_ISUPPORTS_INHERITED0(AnalyserNode, AudioNode)
class AnalyserNodeEngine : public AudioNodeEngine
{
public:
explicit AnalyserNodeEngine(AnalyserNode& aNode)
: mMutex("AnalyserNodeEngine")
, mNode(&aNode)
{
MOZ_ASSERT(NS_IsMainThread());
}
void DisconnectFromNode()
{
MutexAutoLock lock(mMutex);
mNode = nullptr;
}
virtual void ProduceAudioBlock(AudioNodeStream* aStream,
const AudioChunk& aInput,
AudioChunk* aOutput,
bool* aFinished)
{
*aOutput = aInput;
class TransferBuffer : public nsRunnable
{
public:
TransferBuffer(AnalyserNode* aNode,
const AudioChunk& aChunk)
: mNode(aNode)
, mChunk(aChunk)
{
}
NS_IMETHOD Run()
{
mNode->AppendChunk(mChunk);
return NS_OK;
}
private:
AnalyserNode* mNode;
AudioChunk mChunk;
};
MutexAutoLock lock(mMutex);
if (mNode &&
aInput.mChannelData.Length() > 0) {
nsRefPtr<TransferBuffer> transfer = new TransferBuffer(mNode, aInput);
NS_DispatchToMainThread(transfer);
}
}
private:
Mutex mMutex;
AnalyserNode* mNode; // weak pointer, cleared by AnalyserNode::DestroyMediaStream
};
AnalyserNode::AnalyserNode(AudioContext* aContext)
@ -32,9 +78,11 @@ AnalyserNode::AnalyserNode(AudioContext* aContext)
, mMinDecibels(-100.)
, mMaxDecibels(-30.)
, mSmoothingTimeConstant(.8)
, mWriteIndex(0)
{
mStream = aContext->Graph()->CreateAudioNodeStream(new AnalyserNodeEngine(),
mStream = aContext->Graph()->CreateAudioNodeStream(new AnalyserNodeEngine(*this),
MediaStreamGraph::INTERNAL_STREAM);
AllocateBuffer();
}
AnalyserNode::~AnalyserNode()
@ -57,7 +105,10 @@ AnalyserNode::SetFftSize(uint32_t aValue, ErrorResult& aRv)
aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
return;
}
mFFTSize = aValue;
if (mFFTSize != aValue) {
mFFTSize = aValue;
AllocateBuffer();
}
}
void
@ -105,6 +156,57 @@ AnalyserNode::GetByteTimeDomainData(Uint8Array& aArray)
{
}
void
AnalyserNode::DestroyMediaStream()
{
if (mStream) {
AudioNodeStream* ns = static_cast<AudioNodeStream*>(mStream.get());
AnalyserNodeEngine* engine = static_cast<AnalyserNodeEngine*>(ns->Engine());
engine->DisconnectFromNode();
}
AudioNode::DestroyMediaStream();
}
bool
AnalyserNode::AllocateBuffer()
{
bool result = true;
if (mBuffer.Length() != mFFTSize) {
result = mBuffer.SetLength(mFFTSize);
if (result) {
memset(mBuffer.Elements(), 0, sizeof(float) * mFFTSize);
mWriteIndex = 0;
}
}
return result;
}
void
AnalyserNode::AppendChunk(const AudioChunk& aChunk)
{
const uint32_t bufferSize = mBuffer.Length();
const uint32_t channelCount = aChunk.mChannelData.Length();
const uint32_t chunkCount = aChunk.mDuration;
MOZ_ASSERT((bufferSize & (bufferSize - 1)) == 0); // Must be a power of two!
MOZ_ASSERT(channelCount > 0);
MOZ_ASSERT(chunkCount == WEBAUDIO_BLOCK_SIZE);
memcpy(mBuffer.Elements() + mWriteIndex, aChunk.mChannelData[0], sizeof(float) * chunkCount);
for (uint32_t i = 1; i < channelCount; ++i) {
AudioBlockAddChannelWithScale(static_cast<const float*>(aChunk.mChannelData[i]), 1.0f,
mBuffer.Elements() + mWriteIndex);
}
if (channelCount > 1) {
AudioBlockInPlaceScale(mBuffer.Elements() + mWriteIndex, 1,
1.0f / aChunk.mChannelData.Length());
}
mWriteIndex += chunkCount;
MOZ_ASSERT(mWriteIndex <= bufferSize);
if (mWriteIndex >= bufferSize) {
mWriteIndex = 0;
}
}
}
}

View File

@ -29,6 +29,8 @@ public:
return true;
}
virtual void DestroyMediaStream() MOZ_OVERRIDE;
void GetFloatFrequencyData(Float32Array& aArray);
void GetByteFrequencyData(Uint8Array& aArray);
void GetByteTimeDomainData(Uint8Array& aArray);
@ -57,11 +59,18 @@ public:
}
void SetSmoothingTimeConstant(double aValue, ErrorResult& aRv);
private:
friend class AnalyserNodeEngine;
void AppendChunk(const AudioChunk& aChunk);
bool AllocateBuffer();
private:
uint32_t mFFTSize;
double mMinDecibels;
double mMaxDecibels;
double mSmoothingTimeConstant;
uint32_t mWriteIndex;
FallibleTArray<float> mBuffer;
};
}