mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 855990 - Part 4: Send the buffer seen by AnalyserNodeEngine to AnalyserNode; r=padenot
--HG-- extra : rebase_source : be0b1c8197c1e8582d9dda31a74484901c665b79
This commit is contained in:
parent
ee7bcb26f4
commit
7b9c5e3aa8
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user