mirror of
https://github.com/servo/servo.git
synced 2025-07-23 07:13:52 +01:00
Auto merge of #21502 - Manishearth:listener, r=ferjm
Add AudioListener/AudioPanner DOM interfaces Seems to work. I'll need some changes to the servo-media side to support the panner node getters as well as the older `setPosition()`/etc APIs. I'll get to those later. r? @ferjm <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/21502) <!-- Reviewable:end -->
This commit is contained in:
commit
d827370804
28 changed files with 822 additions and 340 deletions
18
Cargo.lock
generated
18
Cargo.lock
generated
|
@ -3197,7 +3197,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "servo-media"
|
name = "servo-media"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/servo/media#7a5c334698aa1e8a9cf95c5bd761e4a31489b6db"
|
source = "git+https://github.com/servo/media#6ecac1c6259b3995e8d6a368e49777e5c2d398ae"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"servo-media-audio 0.1.0 (git+https://github.com/servo/media)",
|
"servo-media-audio 0.1.0 (git+https://github.com/servo/media)",
|
||||||
"servo-media-gstreamer 0.1.0 (git+https://github.com/servo/media)",
|
"servo-media-gstreamer 0.1.0 (git+https://github.com/servo/media)",
|
||||||
|
@ -3207,9 +3207,10 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "servo-media-audio"
|
name = "servo-media-audio"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/servo/media#7a5c334698aa1e8a9cf95c5bd761e4a31489b6db"
|
source = "git+https://github.com/servo/media#6ecac1c6259b3995e8d6a368e49777e5c2d398ae"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byte-slice-cast 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"byte-slice-cast 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"euclid 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"petgraph 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
"petgraph 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"servo_media_derive 0.1.0 (git+https://github.com/servo/media)",
|
"servo_media_derive 0.1.0 (git+https://github.com/servo/media)",
|
||||||
|
@ -3219,7 +3220,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "servo-media-gstreamer"
|
name = "servo-media-gstreamer"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/servo/media#7a5c334698aa1e8a9cf95c5bd761e4a31489b6db"
|
source = "git+https://github.com/servo/media#6ecac1c6259b3995e8d6a368e49777e5c2d398ae"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byte-slice-cast 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"byte-slice-cast 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"glib 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"glib 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -3227,7 +3228,7 @@ dependencies = [
|
||||||
"gstreamer-app 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"gstreamer-app 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"gstreamer-audio 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"gstreamer-audio 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"gstreamer-player 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"gstreamer-player 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ipc-channel 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"regex 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"regex 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"servo-media-audio 0.1.0 (git+https://github.com/servo/media)",
|
"servo-media-audio 0.1.0 (git+https://github.com/servo/media)",
|
||||||
"servo-media-player 0.1.0 (git+https://github.com/servo/media)",
|
"servo-media-player 0.1.0 (git+https://github.com/servo/media)",
|
||||||
|
@ -3237,7 +3238,12 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "servo-media-player"
|
name = "servo-media-player"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/servo/media#7a5c334698aa1e8a9cf95c5bd761e4a31489b6db"
|
source = "git+https://github.com/servo/media#6ecac1c6259b3995e8d6a368e49777e5c2d398ae"
|
||||||
|
dependencies = [
|
||||||
|
"ipc-channel 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"serde 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"serde_derive 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "servo-skia"
|
name = "servo-skia"
|
||||||
|
@ -3318,7 +3324,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "servo_media_derive"
|
name = "servo_media_derive"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/servo/media#7a5c334698aa1e8a9cf95c5bd761e4a31489b6db"
|
source = "git+https://github.com/servo/media#6ecac1c6259b3995e8d6a368e49777e5c2d398ae"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"quote 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"quote 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
|
|
@ -10,7 +10,6 @@ use dom::bindings::reflector::reflect_dom_object;
|
||||||
use dom::bindings::root::DomRoot;
|
use dom::bindings::root::DomRoot;
|
||||||
use dom::globalscope::GlobalScope;
|
use dom::globalscope::GlobalScope;
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use servo_media::audio::node::AudioNodeInit;
|
|
||||||
|
|
||||||
#[dom_struct]
|
#[dom_struct]
|
||||||
pub struct AudioDestinationNode {
|
pub struct AudioDestinationNode {
|
||||||
|
@ -23,9 +22,8 @@ impl AudioDestinationNode {
|
||||||
options: &AudioNodeOptions,
|
options: &AudioNodeOptions,
|
||||||
) -> AudioDestinationNode {
|
) -> AudioDestinationNode {
|
||||||
AudioDestinationNode {
|
AudioDestinationNode {
|
||||||
node: AudioNode::new_inherited(
|
node: AudioNode::new_inherited_for_id(
|
||||||
AudioNodeInit::DestinationNode,
|
context.destination_node(),
|
||||||
Some(context.destination_node()),
|
|
||||||
context,
|
context,
|
||||||
options,
|
options,
|
||||||
1,
|
1,
|
||||||
|
|
190
components/script/dom/audiolistener.rs
Normal file
190
components/script/dom/audiolistener.rs
Normal file
|
@ -0,0 +1,190 @@
|
||||||
|
/* 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::audioparam::AudioParam;
|
||||||
|
use dom::baseaudiocontext::BaseAudioContext;
|
||||||
|
use dom::bindings::codegen::Bindings::AudioListenerBinding::{self, AudioListenerMethods};
|
||||||
|
use dom::bindings::codegen::Bindings::AudioParamBinding::AutomationRate;
|
||||||
|
use dom::bindings::reflector::{Reflector, reflect_dom_object};
|
||||||
|
use dom::bindings::root::{Dom, DomRoot};
|
||||||
|
use dom::window::Window;
|
||||||
|
use dom_struct::dom_struct;
|
||||||
|
use servo_media::audio::param::{ParamType, ParamDir};
|
||||||
|
use std::f32;
|
||||||
|
|
||||||
|
#[dom_struct]
|
||||||
|
pub struct AudioListener {
|
||||||
|
reflector_: Reflector,
|
||||||
|
position_x: Dom<AudioParam>,
|
||||||
|
position_y: Dom<AudioParam>,
|
||||||
|
position_z: Dom<AudioParam>,
|
||||||
|
forward_x: Dom<AudioParam>,
|
||||||
|
forward_y: Dom<AudioParam>,
|
||||||
|
forward_z: Dom<AudioParam>,
|
||||||
|
up_x: Dom<AudioParam>,
|
||||||
|
up_y: Dom<AudioParam>,
|
||||||
|
up_z: Dom<AudioParam>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AudioListener {
|
||||||
|
fn new_inherited(
|
||||||
|
window: &Window,
|
||||||
|
context: &BaseAudioContext,
|
||||||
|
) -> AudioListener {
|
||||||
|
let node = context.listener();
|
||||||
|
|
||||||
|
let position_x = AudioParam::new(
|
||||||
|
window,
|
||||||
|
context,
|
||||||
|
node,
|
||||||
|
ParamType::Position(ParamDir::X),
|
||||||
|
AutomationRate::A_rate,
|
||||||
|
0., // default value
|
||||||
|
f32::MIN, // min value
|
||||||
|
f32::MAX, // max value
|
||||||
|
);
|
||||||
|
let position_y = AudioParam::new(
|
||||||
|
window,
|
||||||
|
context,
|
||||||
|
node,
|
||||||
|
ParamType::Position(ParamDir::Y),
|
||||||
|
AutomationRate::A_rate,
|
||||||
|
0., // default value
|
||||||
|
f32::MIN, // min value
|
||||||
|
f32::MAX, // max value
|
||||||
|
);
|
||||||
|
let position_z = AudioParam::new(
|
||||||
|
window,
|
||||||
|
context,
|
||||||
|
node,
|
||||||
|
ParamType::Position(ParamDir::Z),
|
||||||
|
AutomationRate::A_rate,
|
||||||
|
0., // default value
|
||||||
|
f32::MIN, // min value
|
||||||
|
f32::MAX, // max value
|
||||||
|
);
|
||||||
|
let forward_x = AudioParam::new(
|
||||||
|
window,
|
||||||
|
context,
|
||||||
|
node,
|
||||||
|
ParamType::Forward(ParamDir::X),
|
||||||
|
AutomationRate::A_rate,
|
||||||
|
0., // default value
|
||||||
|
f32::MIN, // min value
|
||||||
|
f32::MAX, // max value
|
||||||
|
);
|
||||||
|
let forward_y = AudioParam::new(
|
||||||
|
window,
|
||||||
|
context,
|
||||||
|
node,
|
||||||
|
ParamType::Forward(ParamDir::Y),
|
||||||
|
AutomationRate::A_rate,
|
||||||
|
0., // default value
|
||||||
|
f32::MIN, // min value
|
||||||
|
f32::MAX, // max value
|
||||||
|
);
|
||||||
|
let forward_z = AudioParam::new(
|
||||||
|
window,
|
||||||
|
context,
|
||||||
|
node,
|
||||||
|
ParamType::Forward(ParamDir::Z),
|
||||||
|
AutomationRate::A_rate,
|
||||||
|
-1., // default value
|
||||||
|
f32::MIN, // min value
|
||||||
|
f32::MAX, // max value
|
||||||
|
);
|
||||||
|
let up_x = AudioParam::new(
|
||||||
|
window,
|
||||||
|
context,
|
||||||
|
node,
|
||||||
|
ParamType::Up(ParamDir::X),
|
||||||
|
AutomationRate::A_rate,
|
||||||
|
0., // default value
|
||||||
|
f32::MIN, // min value
|
||||||
|
f32::MAX, // max value
|
||||||
|
);
|
||||||
|
let up_y = AudioParam::new(
|
||||||
|
window,
|
||||||
|
context,
|
||||||
|
node,
|
||||||
|
ParamType::Up(ParamDir::Y),
|
||||||
|
AutomationRate::A_rate,
|
||||||
|
1., // default value
|
||||||
|
f32::MIN, // min value
|
||||||
|
f32::MAX, // max value
|
||||||
|
);
|
||||||
|
let up_z = AudioParam::new(
|
||||||
|
window,
|
||||||
|
context,
|
||||||
|
node,
|
||||||
|
ParamType::Up(ParamDir::Z),
|
||||||
|
AutomationRate::A_rate,
|
||||||
|
0., // default value
|
||||||
|
f32::MIN, // min value
|
||||||
|
f32::MAX, // max value
|
||||||
|
);
|
||||||
|
AudioListener {
|
||||||
|
reflector_: Reflector::new(),
|
||||||
|
position_x: Dom::from_ref(&position_x),
|
||||||
|
position_y: Dom::from_ref(&position_y),
|
||||||
|
position_z: Dom::from_ref(&position_z),
|
||||||
|
forward_x: Dom::from_ref(&forward_x),
|
||||||
|
forward_y: Dom::from_ref(&forward_y),
|
||||||
|
forward_z: Dom::from_ref(&forward_z),
|
||||||
|
up_x: Dom::from_ref(&up_x),
|
||||||
|
up_y: Dom::from_ref(&up_y),
|
||||||
|
up_z: Dom::from_ref(&up_z),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unrooted_must_root)]
|
||||||
|
pub fn new(
|
||||||
|
window: &Window,
|
||||||
|
context: &BaseAudioContext,
|
||||||
|
) -> DomRoot<AudioListener> {
|
||||||
|
let node = AudioListener::new_inherited(window, context);
|
||||||
|
reflect_dom_object(Box::new(node), window, AudioListenerBinding::Wrap)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AudioListenerMethods for AudioListener {
|
||||||
|
// https://webaudio.github.io/web-audio-api/#dom-audiolistener-positionx
|
||||||
|
fn PositionX(&self) -> DomRoot<AudioParam> {
|
||||||
|
DomRoot::from_ref(&self.position_x)
|
||||||
|
}
|
||||||
|
// https://webaudio.github.io/web-audio-api/#dom-audiolistener-positiony
|
||||||
|
fn PositionY(&self) -> DomRoot<AudioParam> {
|
||||||
|
DomRoot::from_ref(&self.position_y)
|
||||||
|
}
|
||||||
|
// https://webaudio.github.io/web-audio-api/#dom-audiolistener-positionz
|
||||||
|
fn PositionZ(&self) -> DomRoot<AudioParam> {
|
||||||
|
DomRoot::from_ref(&self.position_z)
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://webaudio.github.io/web-audio-api/#dom-audiolistener-forwardx
|
||||||
|
fn ForwardX(&self) -> DomRoot<AudioParam> {
|
||||||
|
DomRoot::from_ref(&self.forward_x)
|
||||||
|
}
|
||||||
|
// https://webaudio.github.io/web-audio-api/#dom-audiolistener-forwardy
|
||||||
|
fn ForwardY(&self) -> DomRoot<AudioParam> {
|
||||||
|
DomRoot::from_ref(&self.forward_y)
|
||||||
|
}
|
||||||
|
// https://webaudio.github.io/web-audio-api/#dom-audiolistener-forwardz
|
||||||
|
fn ForwardZ(&self) -> DomRoot<AudioParam> {
|
||||||
|
DomRoot::from_ref(&self.forward_z)
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://webaudio.github.io/web-audio-api/#dom-audiolistener-upx
|
||||||
|
fn UpX(&self) -> DomRoot<AudioParam> {
|
||||||
|
DomRoot::from_ref(&self.up_x)
|
||||||
|
}
|
||||||
|
// https://webaudio.github.io/web-audio-api/#dom-audiolistener-upy
|
||||||
|
fn UpY(&self) -> DomRoot<AudioParam> {
|
||||||
|
DomRoot::from_ref(&self.up_y)
|
||||||
|
}
|
||||||
|
// https://webaudio.github.io/web-audio-api/#dom-audiolistener-upz
|
||||||
|
fn UpZ(&self) -> DomRoot<AudioParam> {
|
||||||
|
DomRoot::from_ref(&self.up_z)
|
||||||
|
}
|
||||||
|
}
|
|
@ -36,17 +36,26 @@ pub struct AudioNode {
|
||||||
channel_interpretation: Cell<ChannelInterpretation>,
|
channel_interpretation: Cell<ChannelInterpretation>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl AudioNode {
|
impl AudioNode {
|
||||||
pub fn new_inherited(
|
pub fn new_inherited(
|
||||||
node_type: AudioNodeInit,
|
node_type: AudioNodeInit,
|
||||||
node_id: Option<NodeId>,
|
|
||||||
context: &BaseAudioContext,
|
context: &BaseAudioContext,
|
||||||
options: &AudioNodeOptions,
|
options: &AudioNodeOptions,
|
||||||
number_of_inputs: u32,
|
number_of_inputs: u32,
|
||||||
number_of_outputs: u32,
|
number_of_outputs: u32,
|
||||||
) -> AudioNode {
|
) -> AudioNode {
|
||||||
let node_id =
|
let node_id = context.audio_context_impl().create_node(node_type);
|
||||||
node_id.unwrap_or_else(|| context.audio_context_impl().create_node(node_type));
|
AudioNode::new_inherited_for_id(node_id, context, options, number_of_inputs, number_of_outputs)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_inherited_for_id(
|
||||||
|
node_id: NodeId,
|
||||||
|
context: &BaseAudioContext,
|
||||||
|
options: &AudioNodeOptions,
|
||||||
|
number_of_inputs: u32,
|
||||||
|
number_of_outputs: u32,
|
||||||
|
) -> AudioNode {
|
||||||
AudioNode {
|
AudioNode {
|
||||||
eventtarget: EventTarget::new_inherited(),
|
eventtarget: EventTarget::new_inherited(),
|
||||||
node_id,
|
node_id,
|
||||||
|
@ -204,6 +213,11 @@ impl AudioNodeMethods for AudioNode {
|
||||||
return Err(Error::IndexSize);
|
return Err(Error::IndexSize);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
EventTargetTypeId::AudioNode(AudioNodeTypeId::PannerNode) => {
|
||||||
|
if value > 2 {
|
||||||
|
return Err(Error::NotSupported)
|
||||||
|
}
|
||||||
|
}
|
||||||
// XXX We do not support any of the other AudioNodes with
|
// XXX We do not support any of the other AudioNodes with
|
||||||
// constraints yet. Add more cases here as we add support
|
// constraints yet. Add more cases here as we add support
|
||||||
// for new AudioNodes.
|
// for new AudioNodes.
|
||||||
|
@ -237,6 +251,11 @@ impl AudioNodeMethods for AudioNode {
|
||||||
return Err(Error::InvalidState);
|
return Err(Error::InvalidState);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
EventTargetTypeId::AudioNode(AudioNodeTypeId::PannerNode) => {
|
||||||
|
if value == ChannelCountMode::Max {
|
||||||
|
return Err(Error::NotSupported)
|
||||||
|
}
|
||||||
|
}
|
||||||
// XXX We do not support any of the other AudioNodes with
|
// XXX We do not support any of the other AudioNodes with
|
||||||
// constraints yet. Add more cases here as we add support
|
// constraints yet. Add more cases here as we add support
|
||||||
// for new AudioNodes.
|
// for new AudioNodes.
|
||||||
|
|
|
@ -34,7 +34,6 @@ impl AudioScheduledSourceNode {
|
||||||
AudioScheduledSourceNode {
|
AudioScheduledSourceNode {
|
||||||
node: AudioNode::new_inherited(
|
node: AudioNode::new_inherited(
|
||||||
node_type,
|
node_type,
|
||||||
None, /* node_id */
|
|
||||||
context,
|
context,
|
||||||
options,
|
options,
|
||||||
number_of_inputs,
|
number_of_inputs,
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
use dom::audiobuffer::AudioBuffer;
|
use dom::audiobuffer::AudioBuffer;
|
||||||
use dom::audiobuffersourcenode::AudioBufferSourceNode;
|
use dom::audiobuffersourcenode::AudioBufferSourceNode;
|
||||||
use dom::audiodestinationnode::AudioDestinationNode;
|
use dom::audiodestinationnode::AudioDestinationNode;
|
||||||
|
use dom::audiolistener::AudioListener;
|
||||||
use dom::audionode::MAX_CHANNEL_COUNT;
|
use dom::audionode::MAX_CHANNEL_COUNT;
|
||||||
use dom::bindings::callback::ExceptionHandling;
|
use dom::bindings::callback::ExceptionHandling;
|
||||||
use dom::bindings::cell::DomRefCell;
|
use dom::bindings::cell::DomRefCell;
|
||||||
|
@ -17,6 +18,7 @@ use dom::bindings::codegen::Bindings::BaseAudioContextBinding::DecodeErrorCallba
|
||||||
use dom::bindings::codegen::Bindings::BaseAudioContextBinding::DecodeSuccessCallback;
|
use dom::bindings::codegen::Bindings::BaseAudioContextBinding::DecodeSuccessCallback;
|
||||||
use dom::bindings::codegen::Bindings::GainNodeBinding::GainOptions;
|
use dom::bindings::codegen::Bindings::GainNodeBinding::GainOptions;
|
||||||
use dom::bindings::codegen::Bindings::OscillatorNodeBinding::OscillatorOptions;
|
use dom::bindings::codegen::Bindings::OscillatorNodeBinding::OscillatorOptions;
|
||||||
|
use dom::bindings::codegen::Bindings::PannerNodeBinding::PannerOptions;
|
||||||
use dom::bindings::error::{Error, ErrorResult, Fallible};
|
use dom::bindings::error::{Error, ErrorResult, Fallible};
|
||||||
use dom::bindings::inheritance::Castable;
|
use dom::bindings::inheritance::Castable;
|
||||||
use dom::bindings::num::Finite;
|
use dom::bindings::num::Finite;
|
||||||
|
@ -27,6 +29,7 @@ use dom::domexception::{DOMErrorName, DOMException};
|
||||||
use dom::eventtarget::EventTarget;
|
use dom::eventtarget::EventTarget;
|
||||||
use dom::gainnode::GainNode;
|
use dom::gainnode::GainNode;
|
||||||
use dom::oscillatornode::OscillatorNode;
|
use dom::oscillatornode::OscillatorNode;
|
||||||
|
use dom::pannernode::PannerNode;
|
||||||
use dom::promise::Promise;
|
use dom::promise::Promise;
|
||||||
use dom::window::Window;
|
use dom::window::Window;
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
|
@ -63,9 +66,10 @@ struct DecodeResolver {
|
||||||
pub struct BaseAudioContext {
|
pub struct BaseAudioContext {
|
||||||
eventtarget: EventTarget,
|
eventtarget: EventTarget,
|
||||||
#[ignore_malloc_size_of = "servo_media"]
|
#[ignore_malloc_size_of = "servo_media"]
|
||||||
audio_context_impl: Rc<AudioContext<Backend>>,
|
audio_context_impl: AudioContext<Backend>,
|
||||||
/// https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-destination
|
/// https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-destination
|
||||||
destination: MutNullableDom<AudioDestinationNode>,
|
destination: MutNullableDom<AudioDestinationNode>,
|
||||||
|
listener: MutNullableDom<AudioListener>,
|
||||||
/// Resume promises which are soon to be fulfilled by a queued task.
|
/// Resume promises which are soon to be fulfilled by a queued task.
|
||||||
#[ignore_malloc_size_of = "promises are hard"]
|
#[ignore_malloc_size_of = "promises are hard"]
|
||||||
in_flight_resume_promises_queue: DomRefCell<VecDeque<(Box<[Rc<Promise>]>, ErrorResult)>>,
|
in_flight_resume_promises_queue: DomRefCell<VecDeque<(Box<[Rc<Promise>]>, ErrorResult)>>,
|
||||||
|
@ -95,12 +99,11 @@ impl BaseAudioContext {
|
||||||
|
|
||||||
let context = BaseAudioContext {
|
let context = BaseAudioContext {
|
||||||
eventtarget: EventTarget::new_inherited(),
|
eventtarget: EventTarget::new_inherited(),
|
||||||
audio_context_impl: Rc::new(
|
audio_context_impl: ServoMedia::get()
|
||||||
ServoMedia::get()
|
.unwrap()
|
||||||
.unwrap()
|
.create_audio_context(options.into()),
|
||||||
.create_audio_context(options.into()),
|
|
||||||
),
|
|
||||||
destination: Default::default(),
|
destination: Default::default(),
|
||||||
|
listener: Default::default(),
|
||||||
in_flight_resume_promises_queue: Default::default(),
|
in_flight_resume_promises_queue: Default::default(),
|
||||||
pending_resume_promises: Default::default(),
|
pending_resume_promises: Default::default(),
|
||||||
decode_resolvers: Default::default(),
|
decode_resolvers: Default::default(),
|
||||||
|
@ -117,14 +120,18 @@ impl BaseAudioContext {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn audio_context_impl(&self) -> Rc<AudioContext<Backend>> {
|
pub fn audio_context_impl(&self) -> &AudioContext<Backend> {
|
||||||
self.audio_context_impl.clone()
|
&self.audio_context_impl
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn destination_node(&self) -> NodeId {
|
pub fn destination_node(&self) -> NodeId {
|
||||||
self.audio_context_impl.dest_node()
|
self.audio_context_impl.dest_node()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn listener(&self) -> NodeId {
|
||||||
|
self.audio_context_impl.listener()
|
||||||
|
}
|
||||||
|
|
||||||
// https://webaudio.github.io/web-audio-api/#allowed-to-start
|
// https://webaudio.github.io/web-audio-api/#allowed-to-start
|
||||||
pub fn is_allowed_to_start(&self) -> bool {
|
pub fn is_allowed_to_start(&self) -> bool {
|
||||||
self.state.get() == AudioContextState::Suspended
|
self.state.get() == AudioContextState::Suspended
|
||||||
|
@ -297,6 +304,15 @@ impl BaseAudioContextMethods for BaseAudioContext {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-listener
|
||||||
|
fn Listener(&self) -> DomRoot<AudioListener> {
|
||||||
|
let global = self.global();
|
||||||
|
let window = global.as_window();
|
||||||
|
self.listener.or_init(|| {
|
||||||
|
AudioListener::new(&window, self)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-onstatechange
|
/// https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-onstatechange
|
||||||
event_handler!(statechange, GetOnstatechange, SetOnstatechange);
|
event_handler!(statechange, GetOnstatechange, SetOnstatechange);
|
||||||
|
|
||||||
|
@ -314,6 +330,12 @@ impl BaseAudioContextMethods for BaseAudioContext {
|
||||||
GainNode::new(&self.global().as_window(), &self, &GainOptions::empty())
|
GainNode::new(&self.global().as_window(), &self, &GainOptions::empty())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-createpanner
|
||||||
|
fn CreatePanner(&self) -> Fallible<DomRoot<PannerNode>> {
|
||||||
|
PannerNode::new(&self.global().as_window(), &self, &PannerOptions::empty())
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-createbuffer
|
/// https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-createbuffer
|
||||||
fn CreateBuffer(
|
fn CreateBuffer(
|
||||||
&self,
|
&self,
|
||||||
|
|
|
@ -92,6 +92,7 @@ use servo_media::Backend;
|
||||||
use servo_media::audio::buffer_source_node::AudioBuffer;
|
use servo_media::audio::buffer_source_node::AudioBuffer;
|
||||||
use servo_media::audio::context::AudioContext;
|
use servo_media::audio::context::AudioContext;
|
||||||
use servo_media::audio::graph::NodeId;
|
use servo_media::audio::graph::NodeId;
|
||||||
|
use servo_media::audio::panner_node::{DistanceModel, PanningModel};
|
||||||
use servo_media::audio::param::ParamType;
|
use servo_media::audio::param::ParamType;
|
||||||
use servo_url::{ImmutableOrigin, MutableOrigin, ServoUrl};
|
use servo_url::{ImmutableOrigin, MutableOrigin, ServoUrl};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
@ -434,7 +435,7 @@ unsafe_no_jsmanaged_fields!(SourceSet);
|
||||||
unsafe_no_jsmanaged_fields!(AudioBuffer);
|
unsafe_no_jsmanaged_fields!(AudioBuffer);
|
||||||
unsafe_no_jsmanaged_fields!(AudioContext<Backend>);
|
unsafe_no_jsmanaged_fields!(AudioContext<Backend>);
|
||||||
unsafe_no_jsmanaged_fields!(NodeId);
|
unsafe_no_jsmanaged_fields!(NodeId);
|
||||||
unsafe_no_jsmanaged_fields!(ParamType);
|
unsafe_no_jsmanaged_fields!(DistanceModel, PanningModel, ParamType);
|
||||||
|
|
||||||
unsafe impl<'a> JSTraceable for &'a str {
|
unsafe impl<'a> JSTraceable for &'a str {
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -38,7 +38,6 @@ impl GainNode {
|
||||||
node_options.channelInterpretation = Some(ChannelInterpretation::Speakers);
|
node_options.channelInterpretation = Some(ChannelInterpretation::Speakers);
|
||||||
let node = AudioNode::new_inherited(
|
let node = AudioNode::new_inherited(
|
||||||
AudioNodeInit::GainNode(gain_options.into()),
|
AudioNodeInit::GainNode(gain_options.into()),
|
||||||
None,
|
|
||||||
context,
|
context,
|
||||||
&node_options,
|
&node_options,
|
||||||
1, // inputs
|
1, // inputs
|
||||||
|
|
|
@ -220,6 +220,7 @@ pub mod audiobuffer;
|
||||||
pub mod audiobuffersourcenode;
|
pub mod audiobuffersourcenode;
|
||||||
pub mod audiocontext;
|
pub mod audiocontext;
|
||||||
pub mod audiodestinationnode;
|
pub mod audiodestinationnode;
|
||||||
|
pub mod audiolistener;
|
||||||
pub mod audionode;
|
pub mod audionode;
|
||||||
pub mod audioparam;
|
pub mod audioparam;
|
||||||
pub mod audioscheduledsourcenode;
|
pub mod audioscheduledsourcenode;
|
||||||
|
@ -408,6 +409,7 @@ pub mod pagetransitionevent;
|
||||||
pub mod paintrenderingcontext2d;
|
pub mod paintrenderingcontext2d;
|
||||||
pub mod paintsize;
|
pub mod paintsize;
|
||||||
pub mod paintworkletglobalscope;
|
pub mod paintworkletglobalscope;
|
||||||
|
pub mod pannernode;
|
||||||
pub mod performance;
|
pub mod performance;
|
||||||
pub mod performanceentry;
|
pub mod performanceentry;
|
||||||
pub mod performancemark;
|
pub mod performancemark;
|
||||||
|
|
354
components/script/dom/pannernode.rs
Normal file
354
components/script/dom/pannernode.rs
Normal file
|
@ -0,0 +1,354 @@
|
||||||
|
/* 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::AudioNodeBinding::AudioNodeOptions;
|
||||||
|
use dom::bindings::codegen::Bindings::AudioParamBinding::{AudioParamMethods, AutomationRate};
|
||||||
|
use dom::bindings::codegen::Bindings::PannerNodeBinding::{self, PannerNodeMethods, PannerOptions};
|
||||||
|
use dom::bindings::codegen::Bindings::PannerNodeBinding::{DistanceModelType, PanningModelType};
|
||||||
|
use dom::bindings::error::{Error, Fallible};
|
||||||
|
use dom::bindings::inheritance::Castable;
|
||||||
|
use dom::bindings::num::Finite;
|
||||||
|
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::node::{AudioNodeInit, AudioNodeMessage};
|
||||||
|
use servo_media::audio::panner_node::{DistanceModel, PannerNodeOptions, PanningModel};
|
||||||
|
use servo_media::audio::panner_node::PannerNodeMessage;
|
||||||
|
use servo_media::audio::param::{ParamDir, ParamType};
|
||||||
|
use std::cell::Cell;
|
||||||
|
use std::f32;
|
||||||
|
|
||||||
|
#[dom_struct]
|
||||||
|
pub struct PannerNode {
|
||||||
|
node: AudioNode,
|
||||||
|
position_x: Dom<AudioParam>,
|
||||||
|
position_y: Dom<AudioParam>,
|
||||||
|
position_z: Dom<AudioParam>,
|
||||||
|
orientation_x: Dom<AudioParam>,
|
||||||
|
orientation_y: Dom<AudioParam>,
|
||||||
|
orientation_z: Dom<AudioParam>,
|
||||||
|
#[ignore_malloc_size_of = "servo_media"]
|
||||||
|
panning_model: Cell<PanningModel>,
|
||||||
|
#[ignore_malloc_size_of = "servo_media"]
|
||||||
|
distance_model: Cell<DistanceModel>,
|
||||||
|
ref_distance: Cell<f64>,
|
||||||
|
max_distance: Cell<f64>,
|
||||||
|
rolloff_factor: Cell<f64>,
|
||||||
|
cone_inner_angle: Cell<f64>,
|
||||||
|
cone_outer_angle: Cell<f64>,
|
||||||
|
cone_outer_gain: Cell<f64>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PannerNode {
|
||||||
|
#[allow(unrooted_must_root)]
|
||||||
|
pub fn new_inherited(
|
||||||
|
window: &Window,
|
||||||
|
context: &BaseAudioContext,
|
||||||
|
options: &PannerOptions,
|
||||||
|
) -> Fallible<PannerNode> {
|
||||||
|
let count = options.parent.channelCount.unwrap_or(2);
|
||||||
|
let mode = options.parent.channelCountMode.unwrap_or(ChannelCountMode::Clamped_max);
|
||||||
|
if mode == ChannelCountMode::Max {
|
||||||
|
return Err(Error::NotSupported)
|
||||||
|
}
|
||||||
|
if count > 2 {
|
||||||
|
return Err(Error::NotSupported)
|
||||||
|
}
|
||||||
|
let mut node_options = AudioNodeOptions::empty();
|
||||||
|
node_options.channelCount = Some(count);
|
||||||
|
node_options.channelCountMode = Some(mode);
|
||||||
|
node_options.channelInterpretation = Some(ChannelInterpretation::Speakers);
|
||||||
|
let options = options.into();
|
||||||
|
let node = AudioNode::new_inherited(
|
||||||
|
AudioNodeInit::PannerNode(options),
|
||||||
|
context,
|
||||||
|
&node_options,
|
||||||
|
1, // inputs
|
||||||
|
1, // outputs
|
||||||
|
);
|
||||||
|
let id = node.node_id();
|
||||||
|
let position_x = AudioParam::new(
|
||||||
|
window,
|
||||||
|
context,
|
||||||
|
id,
|
||||||
|
ParamType::Position(ParamDir::X),
|
||||||
|
AutomationRate::A_rate,
|
||||||
|
options.position_x, // default value
|
||||||
|
f32::MIN, // min value
|
||||||
|
f32::MAX, // max value
|
||||||
|
);
|
||||||
|
let position_y = AudioParam::new(
|
||||||
|
window,
|
||||||
|
context,
|
||||||
|
id,
|
||||||
|
ParamType::Position(ParamDir::Y),
|
||||||
|
AutomationRate::A_rate,
|
||||||
|
options.position_y, // default value
|
||||||
|
f32::MIN, // min value
|
||||||
|
f32::MAX, // max value
|
||||||
|
);
|
||||||
|
let position_z = AudioParam::new(
|
||||||
|
window,
|
||||||
|
context,
|
||||||
|
id,
|
||||||
|
ParamType::Position(ParamDir::Z),
|
||||||
|
AutomationRate::A_rate,
|
||||||
|
options.position_z, // default value
|
||||||
|
f32::MIN, // min value
|
||||||
|
f32::MAX, // max value
|
||||||
|
);
|
||||||
|
let orientation_x = AudioParam::new(
|
||||||
|
window,
|
||||||
|
context,
|
||||||
|
id,
|
||||||
|
ParamType::Orientation(ParamDir::X),
|
||||||
|
AutomationRate::A_rate,
|
||||||
|
options.orientation_x, // default value
|
||||||
|
f32::MIN, // min value
|
||||||
|
f32::MAX, // max value
|
||||||
|
);
|
||||||
|
let orientation_y = AudioParam::new(
|
||||||
|
window,
|
||||||
|
context,
|
||||||
|
id,
|
||||||
|
ParamType::Orientation(ParamDir::Y),
|
||||||
|
AutomationRate::A_rate,
|
||||||
|
options.orientation_y, // default value
|
||||||
|
f32::MIN, // min value
|
||||||
|
f32::MAX, // max value
|
||||||
|
);
|
||||||
|
let orientation_z = AudioParam::new(
|
||||||
|
window,
|
||||||
|
context,
|
||||||
|
id,
|
||||||
|
ParamType::Orientation(ParamDir::Z),
|
||||||
|
AutomationRate::A_rate,
|
||||||
|
options.orientation_z, // default value
|
||||||
|
f32::MIN, // min value
|
||||||
|
f32::MAX, // max value
|
||||||
|
);
|
||||||
|
Ok(PannerNode {
|
||||||
|
node,
|
||||||
|
position_x: Dom::from_ref(&position_x),
|
||||||
|
position_y: Dom::from_ref(&position_y),
|
||||||
|
position_z: Dom::from_ref(&position_z),
|
||||||
|
orientation_x: Dom::from_ref(&orientation_x),
|
||||||
|
orientation_y: Dom::from_ref(&orientation_y),
|
||||||
|
orientation_z: Dom::from_ref(&orientation_z),
|
||||||
|
panning_model: Cell::new(options.panning_model),
|
||||||
|
distance_model: Cell::new(options.distance_model),
|
||||||
|
ref_distance: Cell::new(options.ref_distance),
|
||||||
|
max_distance: Cell::new(options.max_distance),
|
||||||
|
rolloff_factor: Cell::new(options.rolloff_factor),
|
||||||
|
cone_inner_angle: Cell::new(options.cone_inner_angle),
|
||||||
|
cone_outer_angle: Cell::new(options.cone_outer_angle),
|
||||||
|
cone_outer_gain: Cell::new(options.cone_outer_gain),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unrooted_must_root)]
|
||||||
|
pub fn new(
|
||||||
|
window: &Window,
|
||||||
|
context: &BaseAudioContext,
|
||||||
|
options: &PannerOptions,
|
||||||
|
) -> Fallible<DomRoot<PannerNode>> {
|
||||||
|
let node = PannerNode::new_inherited(window, context, options)?;
|
||||||
|
Ok(reflect_dom_object(Box::new(node), window, PannerNodeBinding::Wrap))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn Constructor(
|
||||||
|
window: &Window,
|
||||||
|
context: &BaseAudioContext,
|
||||||
|
options: &PannerOptions,
|
||||||
|
) -> Fallible<DomRoot<PannerNode>> {
|
||||||
|
PannerNode::new(window, context, options)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PannerNodeMethods for PannerNode {
|
||||||
|
// https://webaudio.github.io/web-audio-api/#dom-pannernode-positionx
|
||||||
|
fn PositionX(&self) -> DomRoot<AudioParam> {
|
||||||
|
DomRoot::from_ref(&self.position_x)
|
||||||
|
}
|
||||||
|
// https://webaudio.github.io/web-audio-api/#dom-pannernode-positiony
|
||||||
|
fn PositionY(&self) -> DomRoot<AudioParam> {
|
||||||
|
DomRoot::from_ref(&self.position_y)
|
||||||
|
}
|
||||||
|
// https://webaudio.github.io/web-audio-api/#dom-pannernode-positionz
|
||||||
|
fn PositionZ(&self) -> DomRoot<AudioParam> {
|
||||||
|
DomRoot::from_ref(&self.position_z)
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://webaudio.github.io/web-audio-api/#dom-pannernode-orientationx
|
||||||
|
fn OrientationX(&self) -> DomRoot<AudioParam> {
|
||||||
|
DomRoot::from_ref(&self.orientation_x)
|
||||||
|
}
|
||||||
|
// https://webaudio.github.io/web-audio-api/#dom-pannernode-orientationy
|
||||||
|
fn OrientationY(&self) -> DomRoot<AudioParam> {
|
||||||
|
DomRoot::from_ref(&self.orientation_y)
|
||||||
|
}
|
||||||
|
// https://webaudio.github.io/web-audio-api/#dom-pannernode-orientationz
|
||||||
|
fn OrientationZ(&self) -> DomRoot<AudioParam> {
|
||||||
|
DomRoot::from_ref(&self.orientation_z)
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://webaudio.github.io/web-audio-api/#dom-pannernode-distancemodel
|
||||||
|
fn DistanceModel(&self) -> DistanceModelType {
|
||||||
|
match self.distance_model.get() {
|
||||||
|
DistanceModel::Linear => DistanceModelType::Linear,
|
||||||
|
DistanceModel::Inverse => DistanceModelType::Inverse,
|
||||||
|
DistanceModel::Exponential => DistanceModelType::Exponential,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// https://webaudio.github.io/web-audio-api/#dom-pannernode-distancemodel
|
||||||
|
fn SetDistanceModel(&self, model: DistanceModelType) {
|
||||||
|
self.distance_model.set(model.into());
|
||||||
|
let msg = PannerNodeMessage::SetDistanceModel(self.distance_model.get());
|
||||||
|
self.upcast::<AudioNode>().message(AudioNodeMessage::PannerNode(msg));
|
||||||
|
}
|
||||||
|
// https://webaudio.github.io/web-audio-api/#dom-pannernode-panningmodel
|
||||||
|
fn PanningModel(&self) -> PanningModelType {
|
||||||
|
match self.panning_model.get() {
|
||||||
|
PanningModel::EqualPower => PanningModelType::Equalpower,
|
||||||
|
PanningModel::HRTF => PanningModelType::HRTF,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// https://webaudio.github.io/web-audio-api/#dom-pannernode-panningmodel
|
||||||
|
fn SetPanningModel(&self, model: PanningModelType) {
|
||||||
|
self.panning_model.set(model.into());
|
||||||
|
let msg = PannerNodeMessage::SetPanningModel(self.panning_model.get());
|
||||||
|
self.upcast::<AudioNode>().message(AudioNodeMessage::PannerNode(msg));
|
||||||
|
}
|
||||||
|
// https://webaudio.github.io/web-audio-api/#dom-pannernode-refdistance
|
||||||
|
fn RefDistance(&self) -> Finite<f64> {
|
||||||
|
Finite::wrap(self.ref_distance.get())
|
||||||
|
}
|
||||||
|
// https://webaudio.github.io/web-audio-api/#dom-pannernode-refdistance
|
||||||
|
fn SetRefDistance(&self, val: Finite<f64>) {
|
||||||
|
self.ref_distance.set(*val);
|
||||||
|
let msg = PannerNodeMessage::SetRefDistance(self.ref_distance.get());
|
||||||
|
self.upcast::<AudioNode>().message(AudioNodeMessage::PannerNode(msg));
|
||||||
|
}
|
||||||
|
// https://webaudio.github.io/web-audio-api/#dom-pannernode-maxdistance
|
||||||
|
fn MaxDistance(&self) -> Finite<f64> {
|
||||||
|
Finite::wrap(self.max_distance.get())
|
||||||
|
}
|
||||||
|
// https://webaudio.github.io/web-audio-api/#dom-pannernode-maxdistance
|
||||||
|
fn SetMaxDistance(&self, val: Finite<f64>) -> Fallible<()> {
|
||||||
|
if *val < 0. {
|
||||||
|
return Err(Error::NotSupported)
|
||||||
|
}
|
||||||
|
self.max_distance.set(*val);
|
||||||
|
let msg = PannerNodeMessage::SetMaxDistance(self.max_distance.get());
|
||||||
|
self.upcast::<AudioNode>().message(AudioNodeMessage::PannerNode(msg));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
// https://webaudio.github.io/web-audio-api/#dom-pannernode-rollofffactor
|
||||||
|
fn RolloffFactor(&self) -> Finite<f64> {
|
||||||
|
Finite::wrap(self.rolloff_factor.get())
|
||||||
|
}
|
||||||
|
// https://webaudio.github.io/web-audio-api/#dom-pannernode-rollofffactor
|
||||||
|
fn SetRolloffFactor(&self, val: Finite<f64>) -> Fallible<()> {
|
||||||
|
if *val < 0. {
|
||||||
|
return Err(Error::Range("value should be positive".into()))
|
||||||
|
}
|
||||||
|
self.rolloff_factor.set(*val);
|
||||||
|
let msg = PannerNodeMessage::SetRolloff(self.rolloff_factor.get());
|
||||||
|
self.upcast::<AudioNode>().message(AudioNodeMessage::PannerNode(msg));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
// https://webaudio.github.io/web-audio-api/#dom-pannernode-coneinnerangle
|
||||||
|
fn ConeInnerAngle(&self) -> Finite<f64> {
|
||||||
|
Finite::wrap(self.cone_inner_angle.get())
|
||||||
|
}
|
||||||
|
// https://webaudio.github.io/web-audio-api/#dom-pannernode-coneinnerangle
|
||||||
|
fn SetConeInnerAngle(&self, val: Finite<f64>) {
|
||||||
|
self.cone_inner_angle.set(*val);
|
||||||
|
let msg = PannerNodeMessage::SetConeInner(self.cone_inner_angle.get());
|
||||||
|
self.upcast::<AudioNode>().message(AudioNodeMessage::PannerNode(msg));
|
||||||
|
}
|
||||||
|
// https://webaudio.github.io/web-audio-api/#dom-pannernode-coneouterangle
|
||||||
|
fn ConeOuterAngle(&self) -> Finite<f64> {
|
||||||
|
Finite::wrap(self.cone_outer_angle.get())
|
||||||
|
}
|
||||||
|
// https://webaudio.github.io/web-audio-api/#dom-pannernode-coneouterangle
|
||||||
|
fn SetConeOuterAngle(&self, val: Finite<f64>) {
|
||||||
|
self.cone_outer_angle.set(*val);
|
||||||
|
let msg = PannerNodeMessage::SetConeOuter(self.cone_outer_angle.get());
|
||||||
|
self.upcast::<AudioNode>().message(AudioNodeMessage::PannerNode(msg));
|
||||||
|
}
|
||||||
|
// https://webaudio.github.io/web-audio-api/#dom-pannernode-coneoutergain
|
||||||
|
fn ConeOuterGain(&self) -> Finite<f64> {
|
||||||
|
Finite::wrap(self.cone_outer_gain.get())
|
||||||
|
}
|
||||||
|
// https://webaudio.github.io/web-audio-api/#dom-pannernode-coneoutergain
|
||||||
|
fn SetConeOuterGain(&self, val: Finite<f64>) -> Fallible<()> {
|
||||||
|
if *val < 0. || *val > 360. {
|
||||||
|
return Err(Error::InvalidState)
|
||||||
|
}
|
||||||
|
self.cone_outer_gain.set(*val);
|
||||||
|
let msg = PannerNodeMessage::SetConeGain(self.cone_outer_gain.get());
|
||||||
|
self.upcast::<AudioNode>().message(AudioNodeMessage::PannerNode(msg));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://webaudio.github.io/web-audio-api/#dom-pannernode-setposition
|
||||||
|
fn SetPosition(&self, x: Finite<f32>, y: Finite<f32>, z: Finite<f32>) {
|
||||||
|
self.position_x.SetValue(x);
|
||||||
|
self.position_y.SetValue(y);
|
||||||
|
self.position_z.SetValue(z);
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://webaudio.github.io/web-audio-api/#dom-pannernode-setorientation
|
||||||
|
fn SetOrientation(&self, x: Finite<f32>, y: Finite<f32>, z: Finite<f32>) {
|
||||||
|
self.orientation_x.SetValue(x);
|
||||||
|
self.orientation_y.SetValue(y);
|
||||||
|
self.orientation_z.SetValue(z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a PannerOptions> for PannerNodeOptions {
|
||||||
|
fn from(options: &'a PannerOptions) -> Self {
|
||||||
|
Self {
|
||||||
|
panning_model: options.panningModel.into(),
|
||||||
|
distance_model: options.distanceModel.into(),
|
||||||
|
position_x: *options.positionX,
|
||||||
|
position_y: *options.positionY,
|
||||||
|
position_z: *options.positionZ,
|
||||||
|
orientation_x: *options.orientationX,
|
||||||
|
orientation_y: *options.orientationY,
|
||||||
|
orientation_z: *options.orientationZ,
|
||||||
|
ref_distance: *options.refDistance,
|
||||||
|
max_distance: *options.maxDistance,
|
||||||
|
rolloff_factor: *options.rolloffFactor,
|
||||||
|
cone_inner_angle: *options.coneInnerAngle,
|
||||||
|
cone_outer_angle: *options.coneOuterAngle,
|
||||||
|
cone_outer_gain: *options.coneOuterGain,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<DistanceModelType> for DistanceModel {
|
||||||
|
fn from(model: DistanceModelType) -> Self {
|
||||||
|
match model {
|
||||||
|
DistanceModelType::Linear => DistanceModel::Linear,
|
||||||
|
DistanceModelType::Inverse => DistanceModel::Inverse,
|
||||||
|
DistanceModelType::Exponential => DistanceModel::Exponential,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<PanningModelType> for PanningModel {
|
||||||
|
fn from(model: PanningModelType) -> Self {
|
||||||
|
match model {
|
||||||
|
PanningModelType::Equalpower => PanningModel::EqualPower,
|
||||||
|
PanningModelType::HRTF => PanningModel::HRTF,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
22
components/script/dom/webidls/AudioListener.webidl
Normal file
22
components/script/dom/webidls/AudioListener.webidl
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
/* 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/#audiolistener
|
||||||
|
*/
|
||||||
|
|
||||||
|
[Exposed=Window]
|
||||||
|
interface AudioListener {
|
||||||
|
readonly attribute AudioParam positionX;
|
||||||
|
readonly attribute AudioParam positionY;
|
||||||
|
readonly attribute AudioParam positionZ;
|
||||||
|
readonly attribute AudioParam forwardX;
|
||||||
|
readonly attribute AudioParam forwardY;
|
||||||
|
readonly attribute AudioParam forwardZ;
|
||||||
|
readonly attribute AudioParam upX;
|
||||||
|
readonly attribute AudioParam upY;
|
||||||
|
readonly attribute AudioParam upZ;
|
||||||
|
// void setPosition (float x, float y, float z);
|
||||||
|
// void setOrientation (float x, float y, float z, float xUp, float yUp, float zUp);
|
||||||
|
};
|
|
@ -20,7 +20,7 @@ interface BaseAudioContext : EventTarget {
|
||||||
readonly attribute AudioDestinationNode destination;
|
readonly attribute AudioDestinationNode destination;
|
||||||
readonly attribute float sampleRate;
|
readonly attribute float sampleRate;
|
||||||
readonly attribute double currentTime;
|
readonly attribute double currentTime;
|
||||||
// readonly attribute AudioListener listener;
|
readonly attribute AudioListener listener;
|
||||||
readonly attribute AudioContextState state;
|
readonly attribute AudioContextState state;
|
||||||
Promise<void> resume();
|
Promise<void> resume();
|
||||||
attribute EventHandler onstatechange;
|
attribute EventHandler onstatechange;
|
||||||
|
@ -42,7 +42,7 @@ interface BaseAudioContext : EventTarget {
|
||||||
// IIRFilterNode createIIRFilter(sequence<double> feedforward,
|
// IIRFilterNode createIIRFilter(sequence<double> feedforward,
|
||||||
// sequence<double> feedback);
|
// sequence<double> feedback);
|
||||||
// WaveShaperNode createWaveShaper();
|
// WaveShaperNode createWaveShaper();
|
||||||
// PannerNode createPanner();
|
[Throws] PannerNode createPanner();
|
||||||
// StereoPannerNode createStereoPanner();
|
// StereoPannerNode createStereoPanner();
|
||||||
// ConvolverNode createConvolver();
|
// ConvolverNode createConvolver();
|
||||||
// ChannelSplitterNode createChannelSplitter(optional unsigned long numberOfOutputs = 6);
|
// ChannelSplitterNode createChannelSplitter(optional unsigned long numberOfOutputs = 6);
|
||||||
|
|
56
components/script/dom/webidls/PannerNode.webidl
Normal file
56
components/script/dom/webidls/PannerNode.webidl
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
/* 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/#pannernode
|
||||||
|
*/
|
||||||
|
|
||||||
|
dictionary PannerOptions : AudioNodeOptions {
|
||||||
|
PanningModelType panningModel = "equalpower";
|
||||||
|
DistanceModelType distanceModel = "inverse";
|
||||||
|
float positionX = 0;
|
||||||
|
float positionY = 0;
|
||||||
|
float positionZ = 0;
|
||||||
|
float orientationX = 1;
|
||||||
|
float orientationY = 0;
|
||||||
|
float orientationZ = 0;
|
||||||
|
double refDistance = 1;
|
||||||
|
double maxDistance = 10000;
|
||||||
|
double rolloffFactor = 1;
|
||||||
|
double coneInnerAngle = 360;
|
||||||
|
double coneOuterAngle = 360;
|
||||||
|
double coneOuterGain = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum DistanceModelType {
|
||||||
|
"linear",
|
||||||
|
"inverse",
|
||||||
|
"exponential"
|
||||||
|
};
|
||||||
|
|
||||||
|
enum PanningModelType {
|
||||||
|
"equalpower",
|
||||||
|
"HRTF"
|
||||||
|
};
|
||||||
|
|
||||||
|
[Exposed=Window,
|
||||||
|
Constructor (BaseAudioContext context, optional PannerOptions options)]
|
||||||
|
interface PannerNode : AudioNode {
|
||||||
|
attribute PanningModelType panningModel;
|
||||||
|
readonly attribute AudioParam positionX;
|
||||||
|
readonly attribute AudioParam positionY;
|
||||||
|
readonly attribute AudioParam positionZ;
|
||||||
|
readonly attribute AudioParam orientationX;
|
||||||
|
readonly attribute AudioParam orientationY;
|
||||||
|
readonly attribute AudioParam orientationZ;
|
||||||
|
attribute DistanceModelType distanceModel;
|
||||||
|
attribute double refDistance;
|
||||||
|
[SetterThrows] attribute double maxDistance;
|
||||||
|
[SetterThrows] attribute double rolloffFactor;
|
||||||
|
attribute double coneInnerAngle;
|
||||||
|
attribute double coneOuterAngle;
|
||||||
|
[SetterThrows] attribute double coneOuterGain;
|
||||||
|
void setPosition (float x, float y, float z);
|
||||||
|
void setOrientation (float x, float y, float z);
|
||||||
|
};
|
32
tests/html/webaudio/test_panner_listener.html
Normal file
32
tests/html/webaudio/test_panner_listener.html
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
<script type="text/javascript">
|
||||||
|
let ctx = new AudioContext();
|
||||||
|
let osc = ctx.createOscillator();
|
||||||
|
let options = {
|
||||||
|
"coneOuterAngle": 0,
|
||||||
|
"positionX": 100, "positionY": 0, "positionZ": 100,
|
||||||
|
"refDistance": 100, "rolloffFactor": 0.01
|
||||||
|
};
|
||||||
|
let panner = new PannerNode(ctx, options);
|
||||||
|
osc.connect(panner);
|
||||||
|
panner.connect(ctx.destination);
|
||||||
|
osc.start();
|
||||||
|
panner.positionX.linearRampToValueAtTime(-100, 0.2);
|
||||||
|
panner.positionZ.linearRampToValueAtTime(100, 0.2);
|
||||||
|
panner.positionX.linearRampToValueAtTime(-100, 0.4);
|
||||||
|
panner.positionZ.linearRampToValueAtTime(-100, 0.4);
|
||||||
|
panner.positionX.linearRampToValueAtTime(100, 0.6);
|
||||||
|
panner.positionZ.linearRampToValueAtTime(-100, 0.6);
|
||||||
|
panner.positionX.linearRampToValueAtTime(100, 0.8);
|
||||||
|
panner.positionZ.linearRampToValueAtTime(100, 0.8);
|
||||||
|
panner.positionX.linearRampToValueAtTime(-100, 1.0);
|
||||||
|
panner.positionZ.linearRampToValueAtTime(100, 1.0);
|
||||||
|
panner.positionX.linearRampToValueAtTime(-100, 1.2);
|
||||||
|
panner.positionZ.linearRampToValueAtTime(-100, 1.2);
|
||||||
|
panner.positionX.linearRampToValueAtTime(100, 1.4);
|
||||||
|
panner.positionZ.linearRampToValueAtTime(-100, 1.4);
|
||||||
|
panner.positionX.linearRampToValueAtTime(100, 1.6);
|
||||||
|
panner.positionZ.linearRampToValueAtTime(100, 1.6);
|
||||||
|
panner.positionZ.linearRampToValueAtTime(10000, 3);
|
||||||
|
ctx.listener.positionZ.setValueAtTime(0, 3);
|
||||||
|
ctx.listener.positionZ.linearRampToValueAtTime(10000, 4);
|
||||||
|
</script>
|
|
@ -1,13 +0,0 @@
|
||||||
[historical.html]
|
|
||||||
[dopplerFactor member should not exist on the AudioListener.]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[speedOfSound member should not exist on the AudioListener.]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[setVelocity member should not exist on the AudioListener.]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[setVelocity should not exist on PannerNodes.]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -5,9 +5,6 @@
|
||||||
[Test driver]
|
[Test driver]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[BaseAudioContext interface: attribute listener]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[BaseAudioContext interface: attribute audioWorklet]
|
[BaseAudioContext interface: attribute audioWorklet]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -38,9 +35,6 @@
|
||||||
[BaseAudioContext interface: operation createIIRFilter([object Object\], [object Object\])]
|
[BaseAudioContext interface: operation createIIRFilter([object Object\], [object Object\])]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[BaseAudioContext interface: operation createPanner()]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[BaseAudioContext interface: operation createPeriodicWave([object Object\], [object Object\], PeriodicWaveConstraints)]
|
[BaseAudioContext interface: operation createPeriodicWave([object Object\], [object Object\], PeriodicWaveConstraints)]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -98,9 +92,6 @@
|
||||||
[AudioContext interface: context must inherit property "createMediaStreamDestination()" with the proper type]
|
[AudioContext interface: context must inherit property "createMediaStreamDestination()" with the proper type]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[BaseAudioContext interface: context must inherit property "listener" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[BaseAudioContext interface: context must inherit property "audioWorklet" with the proper type]
|
[BaseAudioContext interface: context must inherit property "audioWorklet" with the proper type]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -143,9 +134,6 @@
|
||||||
[BaseAudioContext interface: calling createIIRFilter([object Object\], [object Object\]) on context with too few arguments must throw TypeError]
|
[BaseAudioContext interface: calling createIIRFilter([object Object\], [object Object\]) on context with too few arguments must throw TypeError]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[BaseAudioContext interface: context must inherit property "createPanner()" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[BaseAudioContext interface: context must inherit property "createPeriodicWave([object Object\], [object Object\], PeriodicWaveConstraints)" with the proper type]
|
[BaseAudioContext interface: context must inherit property "createPeriodicWave([object Object\], [object Object\], PeriodicWaveConstraints)" with the proper type]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -179,9 +167,6 @@
|
||||||
[OfflineAudioContext interface: calling suspend(double) on new OfflineAudioContext(1, 1, sample_rate) with too few arguments must throw TypeError]
|
[OfflineAudioContext interface: calling suspend(double) on new OfflineAudioContext(1, 1, sample_rate) with too few arguments must throw TypeError]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[BaseAudioContext interface: new OfflineAudioContext(1, 1, sample_rate) must inherit property "listener" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[BaseAudioContext interface: new OfflineAudioContext(1, 1, sample_rate) must inherit property "audioWorklet" with the proper type]
|
[BaseAudioContext interface: new OfflineAudioContext(1, 1, sample_rate) must inherit property "audioWorklet" with the proper type]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -224,9 +209,6 @@
|
||||||
[BaseAudioContext interface: calling createIIRFilter([object Object\], [object Object\]) on new OfflineAudioContext(1, 1, sample_rate) with too few arguments must throw TypeError]
|
[BaseAudioContext interface: calling createIIRFilter([object Object\], [object Object\]) on new OfflineAudioContext(1, 1, sample_rate) with too few arguments must throw TypeError]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[BaseAudioContext interface: new OfflineAudioContext(1, 1, sample_rate) must inherit property "createPanner()" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[BaseAudioContext interface: new OfflineAudioContext(1, 1, sample_rate) must inherit property "createPeriodicWave([object Object\], [object Object\], PeriodicWaveConstraints)" with the proper type]
|
[BaseAudioContext interface: new OfflineAudioContext(1, 1, sample_rate) must inherit property "createPeriodicWave([object Object\], [object Object\], PeriodicWaveConstraints)" with the proper type]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -416,90 +398,12 @@
|
||||||
[AudioNode interface: new AnalyserNode(context) must inherit property "channelInterpretation" with the proper type]
|
[AudioNode interface: new AnalyserNode(context) must inherit property "channelInterpretation" with the proper type]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[AudioListener interface: existence and properties of interface object]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[AudioListener interface object length]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[AudioListener interface object name]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[AudioListener interface: existence and properties of interface prototype object]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[AudioListener interface: existence and properties of interface prototype object's "constructor" property]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[AudioListener interface: existence and properties of interface prototype object's @@unscopables property]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[AudioListener interface: attribute positionX]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[AudioListener interface: attribute positionY]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[AudioListener interface: attribute positionZ]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[AudioListener interface: attribute forwardX]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[AudioListener interface: attribute forwardY]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[AudioListener interface: attribute forwardZ]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[AudioListener interface: attribute upX]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[AudioListener interface: attribute upY]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[AudioListener interface: attribute upZ]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[AudioListener interface: operation setPosition(float, float, float)]
|
[AudioListener interface: operation setPosition(float, float, float)]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[AudioListener interface: operation setOrientation(float, float, float, float, float, float)]
|
[AudioListener interface: operation setOrientation(float, float, float, float, float, float)]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[AudioListener must be primary interface of context.listener]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Stringification of context.listener]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[AudioListener interface: context.listener must inherit property "positionX" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[AudioListener interface: context.listener must inherit property "positionY" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[AudioListener interface: context.listener must inherit property "positionZ" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[AudioListener interface: context.listener must inherit property "forwardX" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[AudioListener interface: context.listener must inherit property "forwardY" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[AudioListener interface: context.listener must inherit property "forwardZ" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[AudioListener interface: context.listener must inherit property "upX" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[AudioListener interface: context.listener must inherit property "upY" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[AudioListener interface: context.listener must inherit property "upZ" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[AudioListener interface: context.listener must inherit property "setPosition(float, float, float)" with the proper type]
|
[AudioListener interface: context.listener must inherit property "setPosition(float, float, float)" with the proper type]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -1673,201 +1577,6 @@
|
||||||
[OscillatorNode interface: calling setPeriodicWave(PeriodicWave) on new OscillatorNode(context) with too few arguments must throw TypeError]
|
[OscillatorNode interface: calling setPeriodicWave(PeriodicWave) on new OscillatorNode(context) with too few arguments must throw TypeError]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[PannerNode interface: existence and properties of interface object]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[PannerNode interface object length]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[PannerNode interface object name]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[PannerNode interface: existence and properties of interface prototype object]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[PannerNode interface: existence and properties of interface prototype object's "constructor" property]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[PannerNode interface: existence and properties of interface prototype object's @@unscopables property]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[PannerNode interface: attribute panningModel]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[PannerNode interface: attribute positionX]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[PannerNode interface: attribute positionY]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[PannerNode interface: attribute positionZ]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[PannerNode interface: attribute orientationX]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[PannerNode interface: attribute orientationY]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[PannerNode interface: attribute orientationZ]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[PannerNode interface: attribute distanceModel]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[PannerNode interface: attribute refDistance]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[PannerNode interface: attribute maxDistance]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[PannerNode interface: attribute rolloffFactor]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[PannerNode interface: attribute coneInnerAngle]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[PannerNode interface: attribute coneOuterAngle]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[PannerNode interface: attribute coneOuterGain]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[PannerNode interface: operation setPosition(float, float, float)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[PannerNode interface: operation setOrientation(float, float, float)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[PannerNode must be primary interface of new PannerNode(context)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Stringification of new PannerNode(context)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[PannerNode interface: new PannerNode(context) must inherit property "panningModel" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[PannerNode interface: new PannerNode(context) must inherit property "positionX" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[PannerNode interface: new PannerNode(context) must inherit property "positionY" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[PannerNode interface: new PannerNode(context) must inherit property "positionZ" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[PannerNode interface: new PannerNode(context) must inherit property "orientationX" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[PannerNode interface: new PannerNode(context) must inherit property "orientationY" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[PannerNode interface: new PannerNode(context) must inherit property "orientationZ" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[PannerNode interface: new PannerNode(context) must inherit property "distanceModel" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[PannerNode interface: new PannerNode(context) must inherit property "refDistance" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[PannerNode interface: new PannerNode(context) must inherit property "maxDistance" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[PannerNode interface: new PannerNode(context) must inherit property "rolloffFactor" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[PannerNode interface: new PannerNode(context) must inherit property "coneInnerAngle" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[PannerNode interface: new PannerNode(context) must inherit property "coneOuterAngle" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[PannerNode interface: new PannerNode(context) must inherit property "coneOuterGain" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[PannerNode interface: new PannerNode(context) must inherit property "setPosition(float, float, float)" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[PannerNode interface: calling setPosition(float, float, float) on new PannerNode(context) with too few arguments must throw TypeError]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[PannerNode interface: new PannerNode(context) must inherit property "setOrientation(float, float, float)" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[PannerNode interface: calling setOrientation(float, float, float) on new PannerNode(context) with too few arguments must throw TypeError]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[AudioNode interface: new PannerNode(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 PannerNode(context) with too few arguments must throw TypeError]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[AudioNode interface: new PannerNode(context) must inherit property "connect(AudioParam, unsigned long)" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[AudioNode interface: calling connect(AudioParam, unsigned long) on new PannerNode(context) with too few arguments must throw TypeError]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[AudioNode interface: new PannerNode(context) must inherit property "disconnect()" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[AudioNode interface: new PannerNode(context) must inherit property "disconnect(unsigned long)" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[AudioNode interface: calling disconnect(unsigned long) on new PannerNode(context) with too few arguments must throw TypeError]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[AudioNode interface: new PannerNode(context) must inherit property "disconnect(AudioNode)" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[AudioNode interface: calling disconnect(AudioNode) on new PannerNode(context) with too few arguments must throw TypeError]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[AudioNode interface: new PannerNode(context) must inherit property "disconnect(AudioNode, unsigned long)" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[AudioNode interface: calling disconnect(AudioNode, unsigned long) on new PannerNode(context) with too few arguments must throw TypeError]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[AudioNode interface: new PannerNode(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 PannerNode(context) with too few arguments must throw TypeError]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[AudioNode interface: new PannerNode(context) must inherit property "disconnect(AudioParam)" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[AudioNode interface: calling disconnect(AudioParam) on new PannerNode(context) with too few arguments must throw TypeError]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[AudioNode interface: new PannerNode(context) must inherit property "disconnect(AudioParam, unsigned long)" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[AudioNode interface: calling disconnect(AudioParam, unsigned long) on new PannerNode(context) with too few arguments must throw TypeError]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[AudioNode interface: new PannerNode(context) must inherit property "context" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[AudioNode interface: new PannerNode(context) must inherit property "numberOfInputs" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[AudioNode interface: new PannerNode(context) must inherit property "numberOfOutputs" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[AudioNode interface: new PannerNode(context) must inherit property "channelCount" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[AudioNode interface: new PannerNode(context) must inherit property "channelCountMode" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[AudioNode interface: new PannerNode(context) must inherit property "channelInterpretation" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[PeriodicWave interface: existence and properties of interface object]
|
[PeriodicWave interface: existence and properties of interface object]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,2 +1,5 @@
|
||||||
[audiobuffersource-multi-channels.html]
|
[audiobuffersource-multi-channels.html]
|
||||||
expected: CRASH
|
expected: TIMEOUT
|
||||||
|
[X Rendered audio for channel 0 does not equal [0,0.19242584705352783,0.3714718818664551,0.5250332355499268,0.6435103416442871,0.7207010388374329,0.7542802691459656,0.7458723187446594,0.7007185816764832,0.6269197463989258,0.5344454050064087,0.4339446425437927,0.33560463786125183,0.24808235466480255,0.17771567404270172,0.12810270488262177...\] with an element-wise tolerance of {"absoluteThreshold":0.000030517578125,"relativeThreshold":0}.\n\tIndex\tActual\t\t\tExpected\t\tAbsError\t\tRelError\t\tTest threshold\n\t[1\]\t6.2648326158523560e-2\t1.9242584705352783e-1\t1.2977752089500427e-1\t6.7442873648311685e-1\t3.0517578125000000e-5\n\t[2\]\t1.2505052983760834e-1\t3.7147188186645508e-1\t2.4642135202884674e-1\t6.6336474995282613e-1\t3.0517578125000000e-5\n\t[3\]\t1.8696144223213196e-1\t5.2503323554992676e-1\t3.3807179331779480e-1\t6.4390551002679652e-1\t3.0517578125000000e-5\n\t[4\]\t2.4813784658908844e-1\t6.4351034164428711e-1\t3.9537249505519867e-1\t6.1439959775152853e-1\t3.0517578125000000e-5\n\t[5\]\t3.0833941698074341e-1\t7.2070103883743286e-1\t4.1236162185668945e-1\t5.7216737542361873e-1\t3.0517578125000000e-5\n\t...and 44074 more errors.\n\tMax AbsError of 8.6889546364545822e-1 at index of 129.\n\t[129\]\t9.7299009561538696e-1\t1.0409463196992874e-1\t8.6889546364545822e-1\t8.3471687944145678e+0\t3.0517578125000000e-5\n\tMax RelError of 1.2424206265621037e+5 at index of 1363.\n\t[1363\]\t-5.8316510915756226e-1\t4.6938193918322213e-6\t5.8316980297695409e-1\t1.2424206265621037e+5\t3.0517578125000000e-5\n]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
[ctor-panner.html]
|
[ctor-panner.html]
|
||||||
expected: ERROR
|
|
||||||
[X context = new OfflineAudioContext(...) incorrectly threw ReferenceError: "OfflineAudioContext is not defined".]
|
[X context = new OfflineAudioContext(...) incorrectly threw ReferenceError: "OfflineAudioContext is not defined".]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -9,3 +8,15 @@
|
||||||
[X node0 = new PannerNode(context) incorrectly threw TypeError: "window[name\] is not a constructor".]
|
[X node0 = new PannerNode(context) incorrectly threw TypeError: "window[name\] is not a constructor".]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
[< [test AudioNodeOptions\] 2 out of 18 assertions were failed.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[X new PannerNode(c, {"channelCount":0}) did not throw an exception.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[# AUDIT TASK RUNNER FINISHED: 1 out of 5 tasks were failed.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[X node6.channelInterpretation is not equal to discrete. Got speakers.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,2 +1,10 @@
|
||||||
[distance-exponential.html]
|
[distance-exponential.html]
|
||||||
expected: ERROR
|
[X Number of impulses is not equal to 100. Got 0.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[< [test\] 1 out of 2 assertions were failed.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[# AUDIT TASK RUNNER FINISHED: 1 out of 1 tasks were failed.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,2 +1,10 @@
|
||||||
[distance-inverse.html]
|
[distance-inverse.html]
|
||||||
expected: ERROR
|
[X Number of impulses is not equal to 100. Got 0.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[# AUDIT TASK RUNNER FINISHED: 1 out of 1 tasks were failed.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[< [test\] 1 out of 2 assertions were failed.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,2 +1,10 @@
|
||||||
[distance-linear.html]
|
[distance-linear.html]
|
||||||
expected: ERROR
|
[X Number of impulses is not equal to 100. Got 0.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[< [test\] 1 out of 2 assertions were failed.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[# AUDIT TASK RUNNER FINISHED: 1 out of 1 tasks were failed.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,2 +1,10 @@
|
||||||
[panner-automation-equalpower-stereo.html]
|
[panner-automation-equalpower-stereo.html]
|
||||||
expected: ERROR
|
[X Number of impulses found is not equal to 100. Got 0.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[< [test\] 1 out of 4 assertions were failed.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[# AUDIT TASK RUNNER FINISHED: 1 out of 1 tasks were failed.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -11,3 +11,28 @@
|
||||||
|
|
||||||
[X new PannerNode(c, {refDistance: -1}) threw "ReferenceError" instead of EcmaScript error RangeError.]
|
[X new PannerNode(c, {refDistance: -1}) threw "ReferenceError" instead of EcmaScript error RangeError.]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
[X panner.maxDistance = 0 did not throw an exception.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[X panner.maxDistance = -1 threw "NotSupportedError" instead of EcmaScript error RangeError.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[< [max-distance-error\] 4 out of 6 assertions were failed.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[X new PannerNode(c, {maxDistance: 0}) did not throw an exception.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[X panner.refDistance = -1 did not throw an exception.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[X new PannerNode(c, {refDistance: -1}) did not throw an exception.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[< [ref-distance-error\] 2 out of 6 assertions were failed.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[X new PannerNode(c, {maxDistance: -1}) did not throw an exception.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,2 +1,10 @@
|
||||||
[panner-equalpower-stereo.html]
|
[panner-equalpower-stereo.html]
|
||||||
expected: ERROR
|
[X Number of impulses found is not equal to 100. Got 0.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[< [test\] 1 out of 4 assertions were failed.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[# AUDIT TASK RUNNER FINISHED: 1 out of 1 tasks were failed.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,2 +1,8 @@
|
||||||
[panner-equalpower.html]
|
[panner-equalpower.html]
|
||||||
expected: ERROR
|
expected: TIMEOUT
|
||||||
|
[X Number of impulses found is not equal to 100. Got 0.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[< [test\] 1 out of 4 assertions were failed.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
[pannernode-basic.html]
|
[pannernode-basic.html]
|
||||||
expected: ERROR
|
|
||||||
[X Initialize context and panner incorrectly threw TypeError: "context.createPanner is not a function".]
|
[X Initialize context and panner incorrectly threw TypeError: "context.createPanner is not a function".]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -65286,7 +65286,7 @@
|
||||||
"testharness"
|
"testharness"
|
||||||
],
|
],
|
||||||
"mozilla/interfaces.html": [
|
"mozilla/interfaces.html": [
|
||||||
"ad419477302c2f55fd0b0f7b90d4b36ee9700988",
|
"179f9c6c6928b3a4194c82f85cd1cce81123a5bc",
|
||||||
"testharness"
|
"testharness"
|
||||||
],
|
],
|
||||||
"mozilla/interfaces.js": [
|
"mozilla/interfaces.js": [
|
||||||
|
|
|
@ -16,6 +16,7 @@ test_interfaces([
|
||||||
"AudioBufferSourceNode",
|
"AudioBufferSourceNode",
|
||||||
"AudioContext",
|
"AudioContext",
|
||||||
"AudioDestinationNode",
|
"AudioDestinationNode",
|
||||||
|
"AudioListener",
|
||||||
"AudioNode",
|
"AudioNode",
|
||||||
"AudioParam",
|
"AudioParam",
|
||||||
"AudioScheduledSourceNode",
|
"AudioScheduledSourceNode",
|
||||||
|
@ -173,6 +174,7 @@ test_interfaces([
|
||||||
"OfflineAudioContext",
|
"OfflineAudioContext",
|
||||||
"OscillatorNode",
|
"OscillatorNode",
|
||||||
"PageTransitionEvent",
|
"PageTransitionEvent",
|
||||||
|
"PannerNode",
|
||||||
"Performance",
|
"Performance",
|
||||||
"PerformanceEntry",
|
"PerformanceEntry",
|
||||||
"PerformanceMark",
|
"PerformanceMark",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue