script/dom/audio/
iirfilternode.rs1use std::sync::Arc;
6
7use dom_struct::dom_struct;
8use itertools::Itertools;
9use js::context::JSContext;
10use js::gc::CustomAutoRooterGuard;
11use js::rust::HandleObject;
12use js::typedarray::Float32Array;
13use script_bindings::reflector::reflect_dom_object_with_proto;
14use servo_media::audio::audio_node::AudioNodeInit;
15use servo_media::audio::graph::NodeId;
16use servo_media::audio::iir_filter_node::{IIRFilterNode as IIRFilter, IIRFilterNodeOptions};
17
18use crate::conversions::Convert;
19use crate::dom::audio::audionode::{AudioNode, AudioNodeOptionsHelper};
20use crate::dom::audio::baseaudiocontext::BaseAudioContext;
21use crate::dom::audionode::UnwrappedAudioNodeOptions;
22use crate::dom::bindings::codegen::Bindings::AudioNodeBinding::{
23 ChannelCountMode, ChannelInterpretation,
24};
25use crate::dom::bindings::codegen::Bindings::IIRFilterNodeBinding::{
26 IIRFilterNodeMethods, IIRFilterOptions,
27};
28use crate::dom::bindings::error::{Error, Fallible};
29use crate::dom::bindings::num::Finite;
30use crate::dom::bindings::root::DomRoot;
31use crate::dom::window::Window;
32
33#[dom_struct]
34pub(crate) struct IIRFilterNode {
35 node: AudioNode,
36 feedforward: Vec<Finite<f64>>,
37 feedback: Vec<Finite<f64>>,
38}
39
40impl IIRFilterNode {
41 fn new_inherited(
42 node_id: Option<NodeId>,
43 context: &BaseAudioContext,
44 node_options: UnwrappedAudioNodeOptions,
45 feedforward: Vec<Finite<f64>>,
46 feedback: Vec<Finite<f64>>,
47 ) -> Self {
48 IIRFilterNode {
49 node: AudioNode::new_inherited(
50 node_id,
51 context,
52 node_options,
53 1, 1, ),
56 feedforward,
57 feedback,
58 }
59 }
60}
61
62impl IIRFilterNodeMethods<crate::DomTypeHolder> for IIRFilterNode {
63 fn Constructor(
65 cx: &mut JSContext,
66 window: &Window,
67 proto: Option<HandleObject>,
68 context: &BaseAudioContext,
69 options: &IIRFilterOptions,
70 ) -> Fallible<DomRoot<IIRFilterNode>> {
71 if !(1..=20).contains(&options.feedforward.len()) ||
72 !(1..=20).contains(&options.feedback.len())
73 {
74 return Err(Error::NotSupported(None));
75 }
76 if options.feedforward.iter().all(|v| **v == 0.0) || *options.feedback[0] == 0.0 {
77 return Err(Error::InvalidState(None));
78 }
79 let node_options =
80 options
81 .parent
82 .unwrap_or(2, ChannelCountMode::Max, ChannelInterpretation::Speakers);
83
84 if AudioNode::channel_count_check(node_options.count) {
85 return Err(Error::NotSupported(Some(String::from(
86 "Channel count not supported",
87 ))));
88 }
89
90 let feedforward = (*options.feedforward).to_vec();
91 let feedback = (*options.feedback).to_vec();
92 let init_options = options.clone().convert();
93 let audio_node_init = AudioNodeInit::IIRFilterNode(init_options);
94 let node_id =
95 AudioNode::generate_audio_node_id(cx, &node_options, audio_node_init, context);
96
97 Ok(reflect_dom_object_with_proto(
98 cx,
99 Box::new(IIRFilterNode::new_inherited(
100 node_id,
101 context,
102 node_options,
103 feedforward,
104 feedback,
105 )),
106 window,
107 proto,
108 ))
109 }
110
111 fn GetFrequencyResponse(
113 &self,
114 frequency_hz: CustomAutoRooterGuard<Float32Array>,
115 mut mag_response: CustomAutoRooterGuard<Float32Array>,
116 mut phase_response: CustomAutoRooterGuard<Float32Array>,
117 ) -> Result<(), Error> {
118 let frequency_hz_vec = frequency_hz.to_vec().unwrap_or(vec![]);
119 let mut mag_response_vec = mag_response.to_vec().unwrap_or(vec![]);
120 let mut phase_response_vec = phase_response.to_vec().unwrap_or(vec![]);
121
122 let len = frequency_hz.len();
123 if len != mag_response.len() || len != phase_response.len() {
124 return Err(Error::InvalidAccess(None));
125 }
126 let feedforward: Vec<f64> = (self.feedforward.iter().map(|v| **v).collect_vec()).to_vec();
127 let feedback: Vec<f64> = (self.feedback.iter().map(|v| **v).collect_vec()).to_vec();
128 IIRFilter::get_frequency_response(
129 &feedforward,
130 &feedback,
131 &frequency_hz_vec,
132 &mut mag_response_vec,
133 &mut phase_response_vec,
134 );
135
136 mag_response.update(&mag_response_vec);
137 phase_response.update(&phase_response_vec);
138
139 Ok(())
140 }
141}
142
143impl Convert<IIRFilterNodeOptions> for IIRFilterOptions {
144 fn convert(self) -> IIRFilterNodeOptions {
145 let feedforward: Vec<f64> = (*self.feedforward.iter().map(|v| **v).collect_vec()).to_vec();
146 let feedback: Vec<f64> = (*self.feedback.iter().map(|v| **v).collect_vec()).to_vec();
147 IIRFilterNodeOptions {
148 feedforward: Arc::new(feedforward),
149 feedback: Arc::new(feedback),
150 }
151 }
152}