Implement BiquadFilterNode

This commit is contained in:
Manish Goregaokar 2018-09-19 21:37:32 +05:30
parent 431ad807d2
commit 1be41686d3
8 changed files with 233 additions and 125 deletions

View file

@ -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<DomRoot<BiquadFilterNode>> {
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<DomRoot<ChannelMergerNode>> {
let mut opts = ChannelMergerOptions::empty();

View file

@ -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<AudioParam>,
frequency: Dom<AudioParam>,
q: Dom<AudioParam>,
detune: Dom<AudioParam>,
filter: Cell<BiquadFilterType>,
}
impl BiquadFilterNode {
#[allow(unrooted_must_root)]
pub fn new_inherited(
window: &Window,
context: &BaseAudioContext,
options: &BiquadFilterOptions,
) -> Fallible<BiquadFilterNode> {
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<DomRoot<BiquadFilterNode>> {
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<DomRoot<BiquadFilterNode>> {
BiquadFilterNode::new(window, context, options)
}
}
impl BiquadFilterNodeMethods for BiquadFilterNode {
// https://webaudio.github.io/web-audio-api/#dom-biquadfilternode-gain
fn Gain(&self) -> DomRoot<AudioParam> {
DomRoot::from_ref(&self.gain)
}
// https://webaudio.github.io/web-audio-api/#dom-biquadfilternode-q
fn Q(&self) -> DomRoot<AudioParam> {
DomRoot::from_ref(&self.gain)
}
// https://webaudio.github.io/web-audio-api/#dom-biquadfilternode-detune
fn Detune(&self) -> DomRoot<AudioParam> {
DomRoot::from_ref(&self.gain)
}
// https://webaudio.github.io/web-audio-api/#dom-biquadfilternode-frequency
fn Frequency(&self) -> DomRoot<AudioParam> {
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<BiquadFilterType> 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,
}
}
}

View file

@ -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;

View file

@ -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);
};