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