Skip to main content

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