Bug 864091 - Part 3: Implement DynamicsCompressorNode's processing based on the Blink's implementation; r=padenot

This commit is contained in:
Ehsan Akhgari 2013-04-21 16:13:59 -04:00
parent f03533b4a7
commit 27c7c4dcf7
4 changed files with 74 additions and 19 deletions

View File

@ -201,6 +201,11 @@ public:
}
}
void CancelAllEvents()
{
mEvents.Clear();
}
// This method computes the AudioParam value at a given time based on the event timeline
template<class TimeType>
float GetValueAtTime(TimeType aTime) const

View File

@ -10,6 +10,11 @@
#include "AudioNodeStream.h"
#include "AudioDestinationNode.h"
#include "WebAudioUtils.h"
#include "blink/DynamicsCompressor.h"
using WebCore::DynamicsCompressor;
const unsigned DEFAULT_NUMBER_OF_CHANNELS = 2;
namespace mozilla {
namespace dom {
@ -41,9 +46,10 @@ public:
, mThreshold(-24.f)
, mKnee(30.f)
, mRatio(12.f)
, mReduction(0.f)
, mAttack(0.003f)
, mRelease(0.25f)
, mCompressor(new DynamicsCompressor(aNode->Context()->SampleRate(),
DEFAULT_NUMBER_OF_CHANNELS))
{
}
@ -56,7 +62,6 @@ public:
THRESHOLD,
KNEE,
RATIO,
REDUCTION,
ATTACK,
RELEASE
};
@ -76,10 +81,6 @@ public:
mRatio = aValue;
WebAudioUtils::ConvertAudioParamToTicks(mRatio, mSource, mDestination);
break;
case REDUCTION:
mReduction = aValue;
WebAudioUtils::ConvertAudioParamToTicks(mReduction, mSource, mDestination);
break;
case ATTACK:
mAttack = aValue;
WebAudioUtils::ConvertAudioParamToTicks(mAttack, mSource, mDestination);
@ -98,8 +99,62 @@ public:
AudioChunk* aOutput,
bool* aFinished) MOZ_OVERRIDE
{
// TODO: do the necessary computation here
*aOutput = aInput;
if (aInput.IsNull()) {
// Just output silence
*aOutput = aInput;
return;
}
TrackTicks pos = aStream->GetCurrentPosition();
mCompressor->setParameterValue(DynamicsCompressor::ParamThreshold,
mThreshold.GetValueAtTime(pos));
mCompressor->setParameterValue(DynamicsCompressor::ParamKnee,
mKnee.GetValueAtTime(pos));
mCompressor->setParameterValue(DynamicsCompressor::ParamRatio,
mRatio.GetValueAtTime(pos));
mCompressor->setParameterValue(DynamicsCompressor::ParamAttack,
mAttack.GetValueAtTime(pos));
mCompressor->setParameterValue(DynamicsCompressor::ParamRelease,
mRelease.GetValueAtTime(pos));
AllocateAudioBlock(DEFAULT_NUMBER_OF_CHANNELS, aOutput);
mCompressor->process(&aInput, aOutput, aInput.GetDuration());
SendReductionParamToMainThread(aStream,
mCompressor->parameterValue(DynamicsCompressor::ParamReduction));
}
private:
void SendReductionParamToMainThread(AudioNodeStream* aStream, float aReduction)
{
MOZ_ASSERT(!NS_IsMainThread());
class Command : public nsRunnable
{
public:
Command(AudioNodeStream* aStream, float aReduction)
: mStream(aStream)
, mReduction(aReduction)
{
}
NS_IMETHODIMP Run()
{
nsRefPtr<DynamicsCompressorNode> node = static_cast<DynamicsCompressorNode*>(mStream->Engine()->Node());
if (node) {
AudioParam* reduction = node->Reduction();
reduction->CancelAllEvents();
reduction->SetValue(mReduction);
}
return NS_OK;
}
private:
nsRefPtr<AudioNodeStream> mStream;
float mReduction;
};
NS_DispatchToMainThread(new Command(aStream, aReduction));
}
private:
@ -108,9 +163,9 @@ private:
AudioParamTimeline mThreshold;
AudioParamTimeline mKnee;
AudioParamTimeline mRatio;
AudioParamTimeline mReduction;
AudioParamTimeline mAttack;
AudioParamTimeline mRelease;
nsAutoPtr<DynamicsCompressor> mCompressor;
};
DynamicsCompressorNode::DynamicsCompressorNode(AudioContext* aContext)
@ -118,12 +173,13 @@ DynamicsCompressorNode::DynamicsCompressorNode(AudioContext* aContext)
, mThreshold(new AudioParam(this, SendThresholdToStream, -24.f))
, mKnee(new AudioParam(this, SendKneeToStream, 30.f))
, mRatio(new AudioParam(this, SendRatioToStream, 12.f))
, mReduction(new AudioParam(this, SendReductionToStream, 0.f))
, mReduction(new AudioParam(this, Callback, 0.f))
, mAttack(new AudioParam(this, SendAttackToStream, 0.003f))
, mRelease(new AudioParam(this, SendReleaseToStream, 0.25f))
{
DynamicsCompressorNodeEngine* engine = new DynamicsCompressorNodeEngine(this, aContext->Destination());
mStream = aContext->Graph()->CreateAudioNodeStream(engine, MediaStreamGraph::INTERNAL_STREAM);
mStream = aContext->Graph()->CreateAudioNodeStream(engine, MediaStreamGraph::INTERNAL_STREAM,
DEFAULT_NUMBER_OF_CHANNELS);
engine->SetSourceStream(static_cast<AudioNodeStream*> (mStream.get()));
}
@ -154,13 +210,6 @@ DynamicsCompressorNode::SendRatioToStream(AudioNode* aNode)
SendTimelineParameterToStream(This, DynamicsCompressorNodeEngine::RATIO, *This->mRatio);
}
void
DynamicsCompressorNode::SendReductionToStream(AudioNode* aNode)
{
DynamicsCompressorNode* This = static_cast<DynamicsCompressorNode*>(aNode);
SendTimelineParameterToStream(This, DynamicsCompressorNodeEngine::REDUCTION, *This->mReduction);
}
void
DynamicsCompressorNode::SendAttackToStream(AudioNode* aNode)
{

View File

@ -65,7 +65,6 @@ private:
static void SendThresholdToStream(AudioNode* aNode);
static void SendKneeToStream(AudioNode* aNode);
static void SendRatioToStream(AudioNode* aNode);
static void SendReductionToStream(AudioNode* aNode);
static void SendAttackToStream(AudioNode* aNode);
static void SendReleaseToStream(AudioNode* aNode);

View File

@ -213,6 +213,8 @@ void TestEventRemoval()
is(timeline.GetEventCount(), 3u, "Should successfully delete one event");
timeline.CancelScheduledValues(0.12);
is(timeline.GetEventCount(), 1u, "Should successfully delete two events");
timeline.CancelAllEvents();
ok(timeline.HasSimpleValue(), "No event should remain scheduled");
}
void TestBeforeFirstEventSetValue()