Skip to main content

servo_media_audio/
audio_node.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use std::cmp::min;
6use std::sync::mpsc::Sender;
7use std::sync::{Arc, OnceLock};
8
9use malloc_size_of_derive::MallocSizeOf;
10use servo_base::generic_channel::GenericCallback;
11use servo_media_streams::{MediaSocket, MediaStreamId};
12
13use crate::biquad_filter_node::{BiquadFilterNodeMessage, BiquadFilterNodeOptions};
14use crate::block::{Block, Chunk, Tick};
15use crate::buffer_source_node::{AudioBufferSourceNodeMessage, AudioBufferSourceNodeOptions};
16use crate::channel_node::ChannelNodeOptions;
17use crate::constant_source_node::ConstantSourceNodeOptions;
18use crate::delay_node::DelayNodeOptions;
19use crate::gain_node::GainNodeOptions;
20use crate::iir_filter_node::IIRFilterNodeOptions;
21use crate::media_element_source_node::MediaElementSourceNodeMessage;
22use crate::oscillator_node::{OscillatorNodeMessage, OscillatorNodeOptions};
23use crate::panner_node::{PannerNodeMessage, PannerNodeOptions};
24use crate::param::{Param, ParamRate, ParamType, UserAutomationEvent};
25use crate::stereo_panner::StereoPannerOptions;
26use crate::wave_shaper_node::{WaveShaperNodeMessage, WaveShaperNodeOptions};
27
28/// Information required to construct an audio node
29#[derive(MallocSizeOf)]
30pub enum AudioNodeInit {
31    AnalyserNode(#[conditional_malloc_size_of] Arc<OnceLock<GenericCallback<Block>>>),
32    BiquadFilterNode(BiquadFilterNodeOptions),
33    AudioBuffer,
34    AudioBufferSourceNode(AudioBufferSourceNodeOptions),
35    ChannelMergerNode(ChannelNodeOptions),
36    ChannelSplitterNode,
37    ConstantSourceNode(ConstantSourceNodeOptions),
38    ConvolverNode,
39    DelayNode(DelayNodeOptions),
40    DynamicsCompressionNode,
41    GainNode(GainNodeOptions),
42    IIRFilterNode(IIRFilterNodeOptions),
43    MediaElementSourceNode,
44    MediaStreamDestinationNode(#[ignore_malloc_size_of = "Fn"] Box<dyn MediaSocket>),
45    MediaStreamSourceNode(MediaStreamId),
46    OscillatorNode(OscillatorNodeOptions),
47    PannerNode(PannerNodeOptions),
48    PeriodicWave,
49    ScriptProcessorNode,
50    StereoPannerNode(StereoPannerOptions),
51    WaveShaperNode(WaveShaperNodeOptions),
52}
53
54/// Type of AudioNodeEngine.
55#[derive(Debug, Clone, Copy, PartialEq, Eq, MallocSizeOf)]
56pub enum AudioNodeType {
57    /// Not a constructable node
58    AudioListenerNode,
59    AnalyserNode,
60    BiquadFilterNode,
61    AudioBuffer,
62    AudioBufferSourceNode,
63    ChannelMergerNode,
64    ChannelSplitterNode,
65    ConstantSourceNode,
66    ConvolverNode,
67    DelayNode,
68    DelayReader, // Only constructed internally by the DelayNode
69    DelayWriter, // Only constructed internally by the DelayNode
70    DestinationNode,
71    DynamicsCompressionNode,
72    GainNode,
73    IIRFilterNode,
74    MediaElementSourceNode,
75    MediaStreamDestinationNode,
76    MediaStreamSourceNode,
77    OscillatorNode,
78    PannerNode,
79    PeriodicWave,
80    ScriptProcessorNode,
81    StereoPannerNode,
82    WaveShaperNode,
83}
84
85#[derive(Copy, Clone, PartialEq, Eq, Debug, MallocSizeOf)]
86pub enum ChannelCountMode {
87    Max,
88    ClampedMax,
89    Explicit,
90}
91
92#[derive(Copy, Clone, PartialEq, Eq, Debug, MallocSizeOf)]
93pub enum ChannelInterpretation {
94    Discrete,
95    Speakers,
96}
97
98#[derive(Copy, Clone)]
99pub struct BlockInfo {
100    pub sample_rate: f32,
101    pub frame: Tick,
102    pub time: f64,
103}
104
105impl BlockInfo {
106    /// Given the current block, calculate the absolute zero-relative
107    /// tick of the given tick
108    pub fn absolute_tick(&self, tick: Tick) -> Tick {
109        self.frame + tick
110    }
111}
112
113#[derive(Clone, Copy, MallocSizeOf)]
114pub struct ChannelInfo {
115    pub count: u8,
116    pub mode: ChannelCountMode,
117    pub interpretation: ChannelInterpretation,
118    pub context_channel_count: u8,
119}
120
121impl Default for ChannelInfo {
122    fn default() -> Self {
123        ChannelInfo {
124            count: 2,
125            mode: ChannelCountMode::Max,
126            interpretation: ChannelInterpretation::Speakers,
127            context_channel_count: 2,
128        }
129    }
130}
131
132impl ChannelInfo {
133    /// <https://webaudio.github.io/web-audio-api/#computednumberofchannels>
134    pub fn computed_number_of_channels(&self) -> u8 {
135        match self.mode {
136            ChannelCountMode::Max => self.context_channel_count,
137            ChannelCountMode::ClampedMax => min(self.count, self.context_channel_count),
138            ChannelCountMode::Explicit => self.count,
139        }
140    }
141}
142
143pub(crate) trait AudioNodeCommon {
144    fn channel_info(&self) -> &ChannelInfo;
145
146    fn channel_info_mut(&mut self) -> &mut ChannelInfo;
147}
148
149/// This trait represents the common features of all audio nodes.
150pub(crate) trait AudioNodeEngine: Send + AudioNodeCommon {
151    fn node_type(&self) -> AudioNodeType;
152
153    fn process(&mut self, inputs: Chunk, info: &BlockInfo) -> Chunk;
154
155    /// <https://webaudio.github.io/web-audio-api/#mute>
156    ///
157    /// Muting an AudioNode means that its output MUST be silence for the
158    /// rendering of this audio block.
159    fn mute_node(&mut self) -> Chunk {
160        let mut chunk = Chunk::default();
161        chunk
162            .blocks
163            .resize(self.input_count() as usize, Default::default());
164
165        let mode = self.channel_count_mode();
166        let count = self.channel_count();
167        let interpretation = self.channel_interpretation();
168        for block in &mut chunk.blocks {
169            if mode == ChannelCountMode::Explicit {
170                block.mix(count, interpretation);
171            }
172        }
173        chunk
174    }
175
176    fn message(&mut self, msg: AudioNodeMessage, sample_rate: f32) {
177        match msg {
178            AudioNodeMessage::GetParamValue(id, tx) => {
179                let _ = tx.send(self.get_param(id).value());
180            },
181            AudioNodeMessage::SetChannelCount(c) => self.set_channel_count(c),
182            AudioNodeMessage::SetChannelMode(c) => self.set_channel_count_mode(c),
183            AudioNodeMessage::SetChannelInterpretation(c) => self.set_channel_interpretation(c),
184            AudioNodeMessage::SetParam(id, event) => self
185                .get_param(id)
186                .insert_event(event.convert_to_event(sample_rate)),
187            AudioNodeMessage::SetParamRange(id, range) => self.get_param(id).update_range(range),
188            AudioNodeMessage::SetParamRate(id, rate) => self.get_param(id).set_rate(rate),
189            _ => self.message_specific(msg, sample_rate),
190        }
191    }
192
193    /// Messages specific to this node
194    fn message_specific(&mut self, _: AudioNodeMessage, _sample_rate: f32) {}
195
196    fn input_count(&self) -> u32 {
197        1
198    }
199    fn output_count(&self) -> u32 {
200        1
201    }
202
203    /// Number of input channels for each input port
204    fn channel_count(&self) -> u8 {
205        self.channel_info().count
206    }
207
208    fn channel_count_mode(&self) -> ChannelCountMode {
209        self.channel_info().mode
210    }
211
212    fn channel_interpretation(&self) -> ChannelInterpretation {
213        self.channel_info().interpretation
214    }
215
216    fn set_channel_interpretation(&mut self, i: ChannelInterpretation) {
217        self.channel_info_mut().interpretation = i
218    }
219    fn set_channel_count(&mut self, c: u8) {
220        self.channel_info_mut().count = c;
221    }
222    fn set_channel_count_mode(&mut self, m: ChannelCountMode) {
223        self.channel_info_mut().mode = m;
224    }
225
226    /// If we're the destination node, extract the contained data
227    fn destination_data(&mut self) -> Option<Chunk> {
228        None
229    }
230
231    fn get_param(&mut self, _: ParamType) -> &mut Param {
232        panic!("No params on node {:?}", self.node_type())
233    }
234
235    fn set_listenerdata(&mut self, _: Block) {
236        panic!("can't accept listener connections")
237    }
238}
239
240#[derive(MallocSizeOf)]
241pub enum AudioNodeMessage {
242    AudioBufferSourceNode(AudioBufferSourceNodeMessage),
243    AudioScheduledSourceNode(AudioScheduledSourceNodeMessage),
244    BiquadFilterNode(BiquadFilterNodeMessage),
245    GetParamValue(ParamType, Sender<f32>),
246    MediaElementSourceNode(MediaElementSourceNodeMessage),
247    OscillatorNode(OscillatorNodeMessage),
248    PannerNode(PannerNodeMessage),
249    SetChannelCount(u8),
250    SetChannelMode(ChannelCountMode),
251    SetChannelInterpretation(ChannelInterpretation),
252    SetParam(ParamType, UserAutomationEvent),
253    SetParamRange(ParamType, (f32, f32)),
254    SetParamRate(ParamType, ParamRate),
255    WaveShaperNode(WaveShaperNodeMessage),
256}
257
258pub struct OnEndedCallback(pub Box<dyn FnOnce() + Send + 'static>);
259
260impl OnEndedCallback {
261    pub fn new<F: FnOnce() + Send + 'static>(callback: F) -> Self {
262        OnEndedCallback(Box::new(callback))
263    }
264}
265
266/// Type of message directed to AudioScheduledSourceNodes.
267#[derive(MallocSizeOf)]
268pub enum AudioScheduledSourceNodeMessage {
269    /// Schedules a sound to playback at an exact time.
270    Start(f64),
271    /// Schedules a sound to stop playback at an exact time.
272    Stop(f64),
273    /// Register onended event callback.
274    RegisterOnEndedCallback(#[ignore_malloc_size_of = "Fn"] OnEndedCallback),
275}
276
277#[derive(Clone, Copy, PartialEq, Eq)]
278pub enum ShouldPlay {
279    /// Don't play anything
280    No,
281    /// Play, given start and end tick offsets
282    Between(Tick, Tick),
283}