Bug 865234 - Part 1: Add DOM bindings for the channel mixing attributes; r=roc

This commit is contained in:
Ehsan Akhgari 2013-04-27 18:44:50 -04:00
parent d93f90db4c
commit 13fd72e30d
21 changed files with 123 additions and 11 deletions

View File

@ -75,7 +75,10 @@ public:
};
AnalyserNode::AnalyserNode(AudioContext* aContext)
: AudioNode(aContext)
: AudioNode(aContext,
1,
ChannelCountMode::Explicit,
ChannelInterpretation::Speakers)
, mFFTSize(2048)
, mMinDecibels(-100.)
, mMaxDecibels(-30.)

View File

@ -403,7 +403,10 @@ public:
};
AudioBufferSourceNode::AudioBufferSourceNode(AudioContext* aContext)
: AudioNode(aContext)
: AudioNode(aContext,
2,
ChannelCountMode::Max,
ChannelInterpretation::Speakers)
, mLoopStart(0.0)
, mLoopEnd(0.0)
, mOffset(0.0)

View File

@ -16,7 +16,10 @@ namespace dom {
NS_IMPL_ISUPPORTS_INHERITED0(AudioDestinationNode, AudioNode)
AudioDestinationNode::AudioDestinationNode(AudioContext* aContext, MediaStreamGraph* aGraph)
: AudioNode(aContext)
: AudioNode(aContext,
2,
ChannelCountMode::Explicit,
ChannelInterpretation::Speakers)
{
mStream = aGraph->CreateAudioNodeStream(new AudioNodeEngine(this),
MediaStreamGraph::EXTERNAL_STREAM);

View File

@ -41,8 +41,14 @@ AudioNode::Release()
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(AudioNode)
NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
AudioNode::AudioNode(AudioContext* aContext)
AudioNode::AudioNode(AudioContext* aContext,
uint32_t aChannelCount,
ChannelCountMode aChannelCountMode,
ChannelInterpretation aChannelInterpretation)
: mContext(aContext)
, mChannelCount(aChannelCount)
, mChannelCountMode(aChannelCountMode)
, mChannelInterpretation(aChannelInterpretation)
{
MOZ_ASSERT(aContext);
nsDOMEventTargetHelper::BindToOwner(aContext->GetParentObject());

View File

@ -8,6 +8,7 @@
#define AudioNode_h_
#include "nsDOMEventTargetHelper.h"
#include "mozilla/dom/AudioNodeBinding.h"
#include "nsCycleCollectionParticipant.h"
#include "mozilla/Attributes.h"
#include "EnableWebAudioCheck.h"
@ -78,7 +79,10 @@ protected:
virtual ~AudioNode();
public:
explicit AudioNode(AudioContext* aContext);
AudioNode(AudioContext* aContext,
uint32_t aChannelCount,
ChannelCountMode aChannelCountMode,
ChannelInterpretation aChannelInterpretation);
// This should be idempotent (safe to call multiple times).
virtual void DestroyMediaStream();
@ -119,6 +123,28 @@ public:
virtual uint32_t NumberOfInputs() const { return 1; }
virtual uint32_t NumberOfOutputs() const { return 1; }
uint32_t ChannelCount() const { return mChannelCount; }
void SetChannelCount(uint32_t aChannelCount)
{
mChannelCount = aChannelCount;
}
ChannelCountMode ChannelCountModeValue() const
{
return mChannelCountMode;
}
void SetChannelCountModeValue(ChannelCountMode aMode)
{
mChannelCountMode = aMode;
}
ChannelInterpretation ChannelInterpretationValue() const
{
return mChannelInterpretation;
}
void SetChannelInterpretationValue(ChannelInterpretation aMode)
{
mChannelInterpretation = aMode;
}
struct InputNode {
~InputNode()
{
@ -174,6 +200,9 @@ private:
// exact matching entry, since mOutputNodes doesn't include the port
// identifiers and the same node could be connected on multiple ports.
nsTArray<nsRefPtr<AudioNode> > mOutputNodes;
uint32_t mChannelCount;
ChannelCountMode mChannelCountMode;
ChannelInterpretation mChannelInterpretation;
};
}

View File

@ -171,7 +171,10 @@ private:
};
BiquadFilterNode::BiquadFilterNode(AudioContext* aContext)
: AudioNode(aContext)
: AudioNode(aContext,
2,
ChannelCountMode::Max,
ChannelInterpretation::Speakers)
, mType(BiquadFilterType::Lowpass)
, mFrequency(new AudioParam(this, SendFrequencyToStream, 350.f))
, mDetune(new AudioParam(this, SendDetuneToStream, 0.f))

View File

@ -271,7 +271,10 @@ public:
};
DelayNode::DelayNode(AudioContext* aContext, double aMaxDelay)
: AudioNode(aContext)
: AudioNode(aContext,
2,
ChannelCountMode::Max,
ChannelInterpretation::Speakers)
, mDelay(new AudioParam(this, SendDelayToStream, 0.0f))
{
DelayNodeEngine* engine = new DelayNodeEngine(this, aContext->Destination());

View File

@ -177,7 +177,10 @@ private:
};
DynamicsCompressorNode::DynamicsCompressorNode(AudioContext* aContext)
: AudioNode(aContext)
: AudioNode(aContext,
2,
ChannelCountMode::Explicit,
ChannelInterpretation::Speakers)
, mThreshold(new AudioParam(this, SendThresholdToStream, -24.f))
, mKnee(new AudioParam(this, SendKneeToStream, 30.f))
, mRatio(new AudioParam(this, SendRatioToStream, 12.f))

View File

@ -95,7 +95,10 @@ public:
};
GainNode::GainNode(AudioContext* aContext)
: AudioNode(aContext)
: AudioNode(aContext,
2,
ChannelCountMode::Max,
ChannelInterpretation::Speakers)
, mGain(new AudioParam(this, SendGainToStream, 1.0f))
{
GainNodeEngine* engine = new GainNodeEngine(this, aContext->Destination());

View File

@ -174,7 +174,10 @@ public:
};
PannerNode::PannerNode(AudioContext* aContext)
: AudioNode(aContext)
: AudioNode(aContext,
2,
ChannelCountMode::Clamped_max,
ChannelInterpretation::Speakers)
// Please keep these default values consistent with PannerNodeEngine::PannerNodeEngine above.
, mPanningModel(PanningModelTypeValues::HRTF)
, mDistanceModel(DistanceModelTypeValues::Inverse)

View File

@ -359,7 +359,10 @@ ScriptProcessorNode::ScriptProcessorNode(AudioContext* aContext,
uint32_t aBufferSize,
uint32_t aNumberOfInputChannels,
uint32_t aNumberOfOutputChannels)
: AudioNode(aContext)
: AudioNode(aContext,
2,
ChannelCountMode::Explicit,
ChannelInterpretation::Speakers)
, mSharedBuffers(new SharedBuffers())
, mBufferSize(aBufferSize ?
aBufferSize : // respect what the web developer requested

View File

@ -31,6 +31,10 @@ addLoadEvent(function() {
source.connect(analyser);
analyser.connect(destination);
is(analyser.channelCount, 1, "analyser node has 2 input channels by default");
is(analyser.channelCountMode, "explicit", "Correct channelCountMode for the analyser node");
is(analyser.channelInterpretation, "speakers", "Correct channelCountInterpretation for the analyser node");
is(analyser.fftSize, 2048, "Correct default value for fftSize");
is(analyser.frequencyBinCount, 1024, "Correct default value for frequencyBinCount");
expectException(function() {

View File

@ -41,6 +41,9 @@ addLoadEvent(function() {
near(filter.detune.defaultValue, 0, "Correct default value for filter detune");
near(filter.Q.defaultValue, 1, "Correct default value for filter Q");
near(filter.gain.defaultValue, 0, "Correct default value for filter gain");
is(filter.channelCount, 2, "Biquad filter node has 2 input channels by default");
is(filter.channelCountMode, "max", "Correct channelCountMode for the biquad filter node");
is(filter.channelInterpretation, "speakers", "Correct channelCountInterpretation for the biquad filter node");
// Make sure that we can set all of the valid type values
var types = [

View File

@ -46,6 +46,9 @@ addLoadEvent(function() {
delay.delayTime.value = 0.5;
is(delay.delayTime.value, 0.5, "Correct initial value");
is(delay.delayTime.defaultValue, 0, "Correct default value");
is(delay.channelCount, 2, "delay node has 2 input channels by default");
is(delay.channelCountMode, "max", "Correct channelCountMode for the delay node");
is(delay.channelInterpretation, "speakers", "Correct channelCountInterpretation for the delay node");
var delay2 = context.createDelay(2);
is(delay2.delayTime.value, 0, "Correct initial value");

View File

@ -34,6 +34,10 @@ addLoadEvent(function() {
source.connect(compressor);
compressor.connect(destination);
is(compressor.channelCount, 2, "compressor node has 2 input channels by default");
is(compressor.channelCountMode, "explicit", "Correct channelCountMode for the compressor node");
is(compressor.channelInterpretation, "speakers", "Correct channelCountInterpretation for the compressor node");
// Verify default values
with (compressor) {
near(threshold.defaultValue, -24, "Correct default value for threshold");

View File

@ -46,6 +46,9 @@ addLoadEvent(function() {
gain.gain.value = 0.5;
is(gain.gain.value, 0.5, "Correct initial value");
is(gain.gain.defaultValue, 1.0, "Correct default value");
is(gain.channelCount, 2, "gain node has 2 input channels by default");
is(gain.channelCountMode, "max", "Correct channelCountMode for the gain node");
is(gain.channelInterpretation, "speakers", "Correct channelCountInterpretation for the gain node");
source.start(0);
sp.onaudioprocess = function(e) {

View File

@ -43,6 +43,9 @@ addLoadEvent(function() {
near(panner.coneInnerAngle, 360, "Correct default value for cone inner angle");
near(panner.coneOuterAngle, 360, "Correct default value for cone outer angle");
near(panner.coneOuterGain, 0, "Correct default value for cone outer gain");
is(panner.channelCount, 2, "panner node has 2 input channels by default");
is(panner.channelCountMode, "clamped-max", "Correct channelCountMode for the panner node");
is(panner.channelInterpretation, "speakers", "Correct channelCountInterpretation for the panner node");
panner.setPosition(1, 1, 1);
panner.setOrientation(1, 1, 1);

View File

@ -44,6 +44,10 @@ addLoadEvent(function() {
context.createScriptProcessor(255);
}, DOMException.INDEX_SIZE_ERR);
is(sourceSP.channelCount, 2, "script processor node has 2 input channels by default");
is(sourceSP.channelCountMode, "explicit", "Correct channelCountMode for the script processor node");
is(sourceSP.channelInterpretation, "speakers", "Correct channelCountInterpretation for the script processor node");
function findFirstNonZeroSample(buffer) {
for (var i = 0; i < buffer.length; ++i) {
if (buffer.getChannelData(0)[i] != 0) {

View File

@ -25,6 +25,9 @@ addLoadEvent(function() {
is(destination.context, context, "Destination node has proper context");
is(destination.numberOfInputs, 1, "Destination node has 1 inputs");
is(destination.numberOfOutputs, 0, "Destination node has 0 outputs");
is(destination.channelCount, 2, "Destination node has 2 input channels by default");
is(destination.channelCountMode, "explicit", "Correct channelCountMode for the destination node");
is(destination.channelInterpretation, "speakers", "Correct channelCountInterpretation for the destination node");
ok(destination instanceof EventTarget, "AudioNodes must be EventTargets");
testWith(context, buffer, destination, function(source) {
@ -84,6 +87,9 @@ function createNode(context, buffer, destination) {
is(source.loopStart, 0, "Correct default value for loopStart");
is(source.loopEnd, 0, "Correct default value for loopEnd");
ok(!source.buffer, "Source node should not have a buffer when it's created");
is(source.channelCount, 2, "source node has 2 input channels by default");
is(source.channelCountMode, "max", "Correct channelCountMode for the source node");
is(source.channelInterpretation, "speakers", "Correct channelCountInterpretation for the source node");
source.buffer = buffer;
ok(source.buffer, "Source node should have a buffer now");

View File

@ -116,6 +116,10 @@ DOMInterfaces = {
'AudioNode' : {
'concrete': False,
'binaryNames': {
'channelCountMode': 'channelCountModeValue',
'channelInterpretation': 'channelInterpretationValue',
},
},
'AudioParam' : {

View File

@ -10,6 +10,17 @@
* liability, trademark and document use rules apply.
*/
enum ChannelCountMode {
"max",
"clamped-max",
"explicit"
};
enum ChannelInterpretation {
"speakers",
"discrete"
};
[PrefControlled]
interface AudioNode : EventTarget {
@ -26,5 +37,10 @@ interface AudioNode : EventTarget {
readonly attribute unsigned long numberOfInputs;
readonly attribute unsigned long numberOfOutputs;
// Channel up-mixing and down-mixing rules for all inputs.
attribute unsigned long channelCount;
attribute ChannelCountMode channelCountMode;
attribute ChannelInterpretation channelInterpretation;
};