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    fn message(&mut self, msg: AudioNodeMessage, sample_rate: f32) {
153        match msg {
154            AudioNodeMessage::GetParamValue(id, tx) => {
155                let _ = tx.send(self.get_param(id).value());
156            },
157            AudioNodeMessage::SetChannelCount(c) => self.set_channel_count(c),
158            AudioNodeMessage::SetChannelMode(c) => self.set_channel_count_mode(c),
159            AudioNodeMessage::SetChannelInterpretation(c) => self.set_channel_interpretation(c),
160            AudioNodeMessage::SetParam(id, event) => self
161                .get_param(id)
162                .insert_event(event.convert_to_event(sample_rate)),
163            AudioNodeMessage::SetParamRate(id, rate) => self.get_param(id).set_rate(rate),
164            _ => self.message_specific(msg, sample_rate),
165        }
166    }
167
168    /// Messages specific to this node
169    fn message_specific(&mut self, _: AudioNodeMessage, _sample_rate: f32) {}
170
171    fn input_count(&self) -> u32 {
172        1
173    }
174    fn output_count(&self) -> u32 {
175        1
176    }
177
178    /// Number of input channels for each input port
179    fn channel_count(&self) -> u8 {
180        self.channel_info().count
181    }
182
183    fn channel_count_mode(&self) -> ChannelCountMode {
184        self.channel_info().mode
185    }
186
187    fn channel_interpretation(&self) -> ChannelInterpretation {
188        self.channel_info().interpretation
189    }
190
191    fn set_channel_interpretation(&mut self, i: ChannelInterpretation) {
192        self.channel_info_mut().interpretation = i
193    }
194    fn set_channel_count(&mut self, c: u8) {
195        self.channel_info_mut().count = c;
196    }
197    fn set_channel_count_mode(&mut self, m: ChannelCountMode) {
198        self.channel_info_mut().mode = m;
199    }
200
201    /// If we're the destination node, extract the contained data
202    fn destination_data(&mut self) -> Option<Chunk> {
203        None
204    }
205
206    fn get_param(&mut self, _: ParamType) -> &mut Param {
207        panic!("No params on node {:?}", self.node_type())
208    }
209
210    fn set_listenerdata(&mut self, _: Block) {
211        panic!("can't accept listener connections")
212    }
213}
214
215#[derive(MallocSizeOf)]
216pub enum AudioNodeMessage {
217    AudioBufferSourceNode(AudioBufferSourceNodeMessage),
218    AudioScheduledSourceNode(AudioScheduledSourceNodeMessage),
219    BiquadFilterNode(BiquadFilterNodeMessage),
220    GetParamValue(ParamType, Sender<f32>),
221    MediaElementSourceNode(MediaElementSourceNodeMessage),
222    OscillatorNode(OscillatorNodeMessage),
223    PannerNode(PannerNodeMessage),
224    SetChannelCount(u8),
225    SetChannelMode(ChannelCountMode),
226    SetChannelInterpretation(ChannelInterpretation),
227    SetParam(ParamType, UserAutomationEvent),
228    SetParamRate(ParamType, ParamRate),
229    WaveShaperNode(WaveShaperNodeMessage),
230}
231
232pub struct OnEndedCallback(pub Box<dyn FnOnce() + Send + 'static>);
233
234impl OnEndedCallback {
235    pub fn new<F: FnOnce() + Send + 'static>(callback: F) -> Self {
236        OnEndedCallback(Box::new(callback))
237    }
238}
239
240/// Type of message directed to AudioScheduledSourceNodes.
241#[derive(MallocSizeOf)]
242pub enum AudioScheduledSourceNodeMessage {
243    /// Schedules a sound to playback at an exact time.
244    Start(f64),
245    /// Schedules a sound to stop playback at an exact time.
246    Stop(f64),
247    /// Register onended event callback.
248    RegisterOnEndedCallback(#[ignore_malloc_size_of = "Fn"] OnEndedCallback),
249}
250
251#[derive(Clone, Copy, PartialEq, Eq)]
252pub enum ShouldPlay {
253    /// Don't play anything
254    No,
255    /// Play, given start and end tick offsets
256    Between(Tick, Tick),
257}