From 1be41686d30aed8385750cc6fc323972515e07ed Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Wed, 19 Sep 2018 21:37:32 +0530 Subject: [PATCH] Implement BiquadFilterNode --- components/script/dom/baseaudiocontext.rs | 7 + components/script/dom/biquadfilternode.rs | 184 ++++++++++++++++++ components/script/dom/mod.rs | 1 + .../dom/webidls/BiquadFilterNode.webidl | 39 ++++ .../webaudio/idlharness.https.window.js.ini | 123 ------------ .../ctor-biquadfilter.html.ini | 1 - tests/wpt/mozilla/meta/MANIFEST.json | 2 +- .../wpt/mozilla/tests/mozilla/interfaces.html | 1 + 8 files changed, 233 insertions(+), 125 deletions(-) create mode 100644 components/script/dom/biquadfilternode.rs create mode 100644 components/script/dom/webidls/BiquadFilterNode.webidl diff --git a/components/script/dom/baseaudiocontext.rs b/components/script/dom/baseaudiocontext.rs index 514a51f113b..86a715d1b5b 100644 --- a/components/script/dom/baseaudiocontext.rs +++ b/components/script/dom/baseaudiocontext.rs @@ -18,6 +18,7 @@ use dom::bindings::codegen::Bindings::BaseAudioContextBinding::AudioContextState use dom::bindings::codegen::Bindings::BaseAudioContextBinding::BaseAudioContextMethods; use dom::bindings::codegen::Bindings::BaseAudioContextBinding::DecodeErrorCallback; use dom::bindings::codegen::Bindings::BaseAudioContextBinding::DecodeSuccessCallback; +use dom::bindings::codegen::Bindings::BiquadFilterNodeBinding::BiquadFilterOptions; use dom::bindings::codegen::Bindings::ChannelMergerNodeBinding::ChannelMergerOptions; use dom::bindings::codegen::Bindings::GainNodeBinding::GainOptions; use dom::bindings::codegen::Bindings::OscillatorNodeBinding::OscillatorOptions; @@ -28,6 +29,7 @@ use dom::bindings::num::Finite; use dom::bindings::refcounted::Trusted; use dom::bindings::reflector::DomObject; use dom::bindings::root::{DomRoot, MutNullableDom}; +use dom::biquadfilternode::BiquadFilterNode; use dom::channelmergernode::ChannelMergerNode; use dom::domexception::{DOMErrorName, DOMException}; use dom::eventtarget::EventTarget; @@ -344,6 +346,11 @@ impl BaseAudioContextMethods for BaseAudioContext { AnalyserNode::new(&self.global().as_window(), &self, &AnalyserOptions::empty()) } + /// https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-createbiquadfilter + fn CreateBiquadFilter(&self) -> Fallible> { + BiquadFilterNode::new(&self.global().as_window(), &self, &BiquadFilter::empty()) + } + /// https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-createchannelmerger fn CreateChannelMerger(&self, count: u32) -> Fallible> { let mut opts = ChannelMergerOptions::empty(); diff --git a/components/script/dom/biquadfilternode.rs b/components/script/dom/biquadfilternode.rs new file mode 100644 index 00000000000..77c39ca7d04 --- /dev/null +++ b/components/script/dom/biquadfilternode.rs @@ -0,0 +1,184 @@ +/* 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/. */ + +use dom::audionode::AudioNode; +use dom::audioparam::AudioParam; +use dom::baseaudiocontext::BaseAudioContext; +use dom::bindings::codegen::Bindings::AudioNodeBinding::{ChannelCountMode, ChannelInterpretation}; +use dom::bindings::codegen::Bindings::AudioParamBinding::AutomationRate; +use dom::bindings::codegen::Bindings::BiquadFilterNodeBinding::{self, BiquadFilterNodeMethods}; +use dom::bindings::codegen::Bindings::BiquadFilterNodeBinding::BiquadFilterOptions; +use dom::bindings::codegen::Bindings::BiquadFilterNodeBinding::BiquadFilterType; +use dom::bindings::error::Fallible; +use dom::bindings::reflector::reflect_dom_object; +use dom::bindings::root::{Dom, DomRoot}; +use dom::window::Window; +use dom_struct::dom_struct; +use servo_media::audio::biquad_filter_node::{BiquadFilterNodeOptions, FilterType}; +use servo_media::audio::biquad_filter_node::BiquadFilterNodeMessage; +use servo_media::audio::node::{AudioNodeInit, AudioNodeMessage}; +use servo_media::audio::param::ParamType; +use std::cell::Cell; +use std::f32; + +#[dom_struct] +pub struct BiquadFilterNode { + node: AudioNode, + gain: Dom, + frequency: Dom, + q: Dom, + detune: Dom, + filter: Cell, +} + +impl BiquadFilterNode { + #[allow(unrooted_must_root)] + pub fn new_inherited( + window: &Window, + context: &BaseAudioContext, + options: &BiquadFilterOptions, + ) -> Fallible { + let node_options = options.parent + .unwrap_or(2, ChannelCountMode::Max, + ChannelInterpretation::Speakers); + let filter = Cell::new(options.type_); + let options = options.into(); + let node = AudioNode::new_inherited( + AudioNodeInit::BiquadFilterNode(options), + context, + node_options, + 1, // inputs + 1, // outputs + )?; + let gain = AudioParam::new( + window, + context, + node.node_id(), + ParamType::Gain, + AutomationRate::A_rate, + options.gain, // default value + f32::MIN, // min value + f32::MAX, // max value + ); + let q = AudioParam::new( + window, + context, + node.node_id(), + ParamType::Q, + AutomationRate::A_rate, + options.q, // default value + f32::MIN, // min value + f32::MAX, // max value + ); + let frequency = AudioParam::new( + window, + context, + node.node_id(), + ParamType::Frequency, + AutomationRate::A_rate, + options.frequency, // default value + f32::MIN, // min value + f32::MAX, // max value + ); + let detune = AudioParam::new( + window, + context, + node.node_id(), + ParamType::Detune, + AutomationRate::A_rate, + options.detune, // default value + f32::MIN, // min value + f32::MAX, // max value + ); + Ok(BiquadFilterNode { + node, + filter, + gain: Dom::from_ref(&gain), + q: Dom::from_ref(&q), + frequency: Dom::from_ref(&frequency), + detune: Dom::from_ref(&detune), + }) + } + + #[allow(unrooted_must_root)] + pub fn new( + window: &Window, + context: &BaseAudioContext, + options: &BiquadFilterOptions, + ) -> Fallible> { + let node = BiquadFilterNode::new_inherited(window, context, options)?; + Ok(reflect_dom_object(Box::new(node), window, BiquadFilterNodeBinding::Wrap)) + } + + pub fn Constructor( + window: &Window, + context: &BaseAudioContext, + options: &BiquadFilterOptions, + ) -> Fallible> { + BiquadFilterNode::new(window, context, options) + } +} + +impl BiquadFilterNodeMethods for BiquadFilterNode { + // https://webaudio.github.io/web-audio-api/#dom-biquadfilternode-gain + fn Gain(&self) -> DomRoot { + DomRoot::from_ref(&self.gain) + } + + // https://webaudio.github.io/web-audio-api/#dom-biquadfilternode-q + fn Q(&self) -> DomRoot { + DomRoot::from_ref(&self.gain) + } + + // https://webaudio.github.io/web-audio-api/#dom-biquadfilternode-detune + fn Detune(&self) -> DomRoot { + DomRoot::from_ref(&self.gain) + } + + // https://webaudio.github.io/web-audio-api/#dom-biquadfilternode-frequency + fn Frequency(&self) -> DomRoot { + DomRoot::from_ref(&self.gain) + } + + // https://webaudio.github.io/web-audio-api/#dom-biquadfilternode-type + fn Type(&self) -> BiquadFilterType { + self.filter.get() + } + + // https://webaudio.github.io/web-audio-api/#dom-biquadfilternode-type + fn SetType(&self, filter: BiquadFilterType) { + self.filter.set(filter); + self.node + .message(AudioNodeMessage::BiquadFilterNode( + BiquadFilterNodeMessage::SetFilterType(filter.into()), + )); + } +} + +impl<'a> From<&'a BiquadFilterOptions> for BiquadFilterNodeOptions { + fn from(options: &'a BiquadFilterOptions) -> Self { + Self { + gain: *options.gain, + q: *options.Q, + frequency: *options.frequency, + detune: *options.detune, + filter: options.type_.into() + } + } +} + +impl From for FilterType { + fn from(filter: BiquadFilterType) -> FilterType { + match filter { + BiquadFilterType::Lowpass => FilterType::LowPass, + BiquadFilterType::Highpass => FilterType::HighPass, + BiquadFilterType::Bandpass => FilterType::BandPass, + BiquadFilterType::Lowshelf => FilterType::LowShelf, + BiquadFilterType::Highshelf => FilterType::HighShelf, + BiquadFilterType::Peaking => FilterType::Peaking, + BiquadFilterType::Allpass => FilterType::AllPass, + BiquadFilterType::Notch => FilterType::Notch, + } + } +} diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs index 54b9adcc422..07425cccae1 100644 --- a/components/script/dom/mod.rs +++ b/components/script/dom/mod.rs @@ -228,6 +228,7 @@ pub mod audioscheduledsourcenode; pub mod baseaudiocontext; pub mod beforeunloadevent; pub mod bindings; +pub mod biquadfilternode; pub mod blob; pub mod bluetooth; pub mod bluetoothadvertisingevent; diff --git a/components/script/dom/webidls/BiquadFilterNode.webidl b/components/script/dom/webidls/BiquadFilterNode.webidl new file mode 100644 index 00000000000..24e993f5aa4 --- /dev/null +++ b/components/script/dom/webidls/BiquadFilterNode.webidl @@ -0,0 +1,39 @@ +/* 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/. */ +/* + * The origin of this IDL file is + * https://webaudio.github.io/web-audio-api/#biquadfilternode + */ + +enum BiquadFilterType { + "lowpass", + "highpass", + "bandpass", + "lowshelf", + "highshelf", + "peaking", + "notch", + "allpass" +}; + +dictionary BiquadFilterOptions : AudioNodeOptions { + BiquadFilterType type = "lowpass"; + float Q = 1; + float detune = 0; + float frequency = 350; + float gain = 0; +}; + +[Exposed=Window, + Constructor (BaseAudioContext context, optional BiquadFilterOptions options)] +interface BiquadFilterNode : AudioNode { + attribute BiquadFilterType type; + readonly attribute AudioParam frequency; + readonly attribute AudioParam detune; + readonly attribute AudioParam Q; + readonly attribute AudioParam gain; + // the AudioParam model of https://github.com/servo/servo/issues/21659 needs to + // be implemented before we implement this + // void getFrequencyResponse (Float32Array frequencyHz, Float32Array magResponse, Float32Array phaseResponse); +}; diff --git a/tests/wpt/metadata/webaudio/idlharness.https.window.js.ini b/tests/wpt/metadata/webaudio/idlharness.https.window.js.ini index 50e3231ac0c..e9f5094764f 100644 --- a/tests/wpt/metadata/webaudio/idlharness.https.window.js.ini +++ b/tests/wpt/metadata/webaudio/idlharness.https.window.js.ini @@ -275,138 +275,15 @@ [AudioProcessingEvent interface: new AudioProcessingEvent('', {\n playbackTime: 0, inputBuffer: buffer, outputBuffer: buffer\n }) must inherit property "outputBuffer" with the proper type] expected: FAIL - [BiquadFilterNode interface: existence and properties of interface object] - expected: FAIL - - [BiquadFilterNode interface object length] - expected: FAIL - - [BiquadFilterNode interface object name] - expected: FAIL - - [BiquadFilterNode interface: existence and properties of interface prototype object] - expected: FAIL - - [BiquadFilterNode interface: existence and properties of interface prototype object's "constructor" property] - expected: FAIL - - [BiquadFilterNode interface: existence and properties of interface prototype object's @@unscopables property] - expected: FAIL - - [BiquadFilterNode interface: attribute type] - expected: FAIL - - [BiquadFilterNode interface: attribute frequency] - expected: FAIL - - [BiquadFilterNode interface: attribute detune] - expected: FAIL - - [BiquadFilterNode interface: attribute Q] - expected: FAIL - - [BiquadFilterNode interface: attribute gain] - expected: FAIL - [BiquadFilterNode interface: operation getFrequencyResponse(Float32Array, Float32Array, Float32Array)] expected: FAIL - [BiquadFilterNode must be primary interface of new BiquadFilterNode(context)] - expected: FAIL - - [Stringification of new BiquadFilterNode(context)] - expected: FAIL - - [BiquadFilterNode interface: new BiquadFilterNode(context) must inherit property "type" with the proper type] - expected: FAIL - - [BiquadFilterNode interface: new BiquadFilterNode(context) must inherit property "frequency" with the proper type] - expected: FAIL - - [BiquadFilterNode interface: new BiquadFilterNode(context) must inherit property "detune" with the proper type] - expected: FAIL - - [BiquadFilterNode interface: new BiquadFilterNode(context) must inherit property "Q" with the proper type] - expected: FAIL - - [BiquadFilterNode interface: new BiquadFilterNode(context) must inherit property "gain" with the proper type] - expected: FAIL - [BiquadFilterNode interface: new BiquadFilterNode(context) must inherit property "getFrequencyResponse(Float32Array, Float32Array, Float32Array)" with the proper type] expected: FAIL [BiquadFilterNode interface: calling getFrequencyResponse(Float32Array, Float32Array, Float32Array) on new BiquadFilterNode(context) with too few arguments must throw TypeError] expected: FAIL - [AudioNode interface: new BiquadFilterNode(context) must inherit property "connect(AudioNode, unsigned long, unsigned long)" with the proper type] - expected: FAIL - - [AudioNode interface: calling connect(AudioNode, unsigned long, unsigned long) on new BiquadFilterNode(context) with too few arguments must throw TypeError] - expected: FAIL - - [AudioNode interface: new BiquadFilterNode(context) must inherit property "connect(AudioParam, unsigned long)" with the proper type] - expected: FAIL - - [AudioNode interface: calling connect(AudioParam, unsigned long) on new BiquadFilterNode(context) with too few arguments must throw TypeError] - expected: FAIL - - [AudioNode interface: new BiquadFilterNode(context) must inherit property "disconnect()" with the proper type] - expected: FAIL - - [AudioNode interface: new BiquadFilterNode(context) must inherit property "disconnect(unsigned long)" with the proper type] - expected: FAIL - - [AudioNode interface: calling disconnect(unsigned long) on new BiquadFilterNode(context) with too few arguments must throw TypeError] - expected: FAIL - - [AudioNode interface: new BiquadFilterNode(context) must inherit property "disconnect(AudioNode)" with the proper type] - expected: FAIL - - [AudioNode interface: calling disconnect(AudioNode) on new BiquadFilterNode(context) with too few arguments must throw TypeError] - expected: FAIL - - [AudioNode interface: new BiquadFilterNode(context) must inherit property "disconnect(AudioNode, unsigned long)" with the proper type] - expected: FAIL - - [AudioNode interface: calling disconnect(AudioNode, unsigned long) on new BiquadFilterNode(context) with too few arguments must throw TypeError] - expected: FAIL - - [AudioNode interface: new BiquadFilterNode(context) must inherit property "disconnect(AudioNode, unsigned long, unsigned long)" with the proper type] - expected: FAIL - - [AudioNode interface: calling disconnect(AudioNode, unsigned long, unsigned long) on new BiquadFilterNode(context) with too few arguments must throw TypeError] - expected: FAIL - - [AudioNode interface: new BiquadFilterNode(context) must inherit property "disconnect(AudioParam)" with the proper type] - expected: FAIL - - [AudioNode interface: calling disconnect(AudioParam) on new BiquadFilterNode(context) with too few arguments must throw TypeError] - expected: FAIL - - [AudioNode interface: new BiquadFilterNode(context) must inherit property "disconnect(AudioParam, unsigned long)" with the proper type] - expected: FAIL - - [AudioNode interface: calling disconnect(AudioParam, unsigned long) on new BiquadFilterNode(context) with too few arguments must throw TypeError] - expected: FAIL - - [AudioNode interface: new BiquadFilterNode(context) must inherit property "context" with the proper type] - expected: FAIL - - [AudioNode interface: new BiquadFilterNode(context) must inherit property "numberOfInputs" with the proper type] - expected: FAIL - - [AudioNode interface: new BiquadFilterNode(context) must inherit property "numberOfOutputs" with the proper type] - expected: FAIL - - [AudioNode interface: new BiquadFilterNode(context) must inherit property "channelCount" with the proper type] - expected: FAIL - - [AudioNode interface: new BiquadFilterNode(context) must inherit property "channelCountMode" with the proper type] - expected: FAIL - - [AudioNode interface: new BiquadFilterNode(context) must inherit property "channelInterpretation" with the proper type] - expected: FAIL - [ChannelSplitterNode interface: existence and properties of interface object] expected: FAIL diff --git a/tests/wpt/metadata/webaudio/the-audio-api/the-biquadfilternode-interface/ctor-biquadfilter.html.ini b/tests/wpt/metadata/webaudio/the-audio-api/the-biquadfilternode-interface/ctor-biquadfilter.html.ini index 74f212f13ee..cf399bc62be 100644 --- a/tests/wpt/metadata/webaudio/the-audio-api/the-biquadfilternode-interface/ctor-biquadfilter.html.ini +++ b/tests/wpt/metadata/webaudio/the-audio-api/the-biquadfilternode-interface/ctor-biquadfilter.html.ini @@ -1,5 +1,4 @@ [ctor-biquadfilter.html] - expected: ERROR [X node0 = new BiquadFilterNode(context) incorrectly threw TypeError: "window[name\] is not a constructor".] expected: FAIL diff --git a/tests/wpt/mozilla/meta/MANIFEST.json b/tests/wpt/mozilla/meta/MANIFEST.json index 3388ffd2562..de3bc22eaeb 100644 --- a/tests/wpt/mozilla/meta/MANIFEST.json +++ b/tests/wpt/mozilla/meta/MANIFEST.json @@ -27038,7 +27038,7 @@ "testharness" ], "mozilla/interfaces.html": [ - "840c233a14c3d041e43a125a6d1452670aa4fbb4", + "4863f4d1036e945cfaae1f112981fac3367b2e49", "testharness" ], "mozilla/interfaces.js": [ diff --git a/tests/wpt/mozilla/tests/mozilla/interfaces.html b/tests/wpt/mozilla/tests/mozilla/interfaces.html index 840c233a14c..4863f4d1036 100644 --- a/tests/wpt/mozilla/tests/mozilla/interfaces.html +++ b/tests/wpt/mozilla/tests/mozilla/interfaces.html @@ -23,6 +23,7 @@ test_interfaces([ "AudioScheduledSourceNode", "BaseAudioContext", "BeforeUnloadEvent", + "BiquadFilterNode", "Blob", "CanvasGradient", "CanvasRenderingContext2D",