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