web_audio_api/node/
mod.rs

1//! The AudioNode interface and concrete types
2
3use std::f32::consts::PI;
4use std::sync::OnceLock;
5
6use crate::render::{
7    AudioParamValues, AudioProcessor, AudioRenderQuantum, AudioWorkletGlobalScope,
8};
9use crate::AudioBufferIter;
10
11// traits
12mod audio_node;
13pub use audio_node::*;
14mod scheduled_source;
15pub use scheduled_source::*;
16
17// nodes
18mod analyser;
19pub use analyser::*;
20mod audio_buffer_source;
21pub use audio_buffer_source::*;
22mod biquad_filter;
23pub use biquad_filter::*;
24mod channel_merger;
25pub use channel_merger::*;
26mod channel_splitter;
27pub use channel_splitter::*;
28mod constant_source;
29pub use constant_source::*;
30mod convolver;
31pub use convolver::*;
32mod delay;
33pub use delay::*;
34mod destination;
35pub use destination::*;
36mod dynamics_compressor;
37pub use dynamics_compressor::*;
38mod gain;
39pub use gain::*;
40mod iir_filter;
41pub use iir_filter::*;
42mod media_element_source;
43pub use media_element_source::*;
44mod media_stream_destination;
45pub use media_stream_destination::*;
46mod media_stream_source;
47pub use media_stream_source::*;
48mod media_stream_track_source;
49pub use media_stream_track_source::*;
50mod oscillator;
51pub use oscillator::*;
52mod panner;
53pub use panner::*;
54mod script_processor;
55pub use script_processor::*;
56mod stereo_panner;
57pub use stereo_panner::*;
58mod waveshaper;
59pub use waveshaper::*;
60
61pub(crate) const TABLE_LENGTH_USIZE: usize = 8192;
62pub(crate) const TABLE_LENGTH_BY_4_USIZE: usize = TABLE_LENGTH_USIZE / 4;
63
64pub(crate) const TABLE_LENGTH_F32: f32 = TABLE_LENGTH_USIZE as f32;
65pub(crate) const TABLE_LENGTH_BY_4_F32: f32 = TABLE_LENGTH_BY_4_USIZE as f32;
66
67/// Precomputed sine table
68pub(crate) fn precomputed_sine_table() -> &'static [f32] {
69    static INSTANCE: OnceLock<Vec<f32>> = OnceLock::new();
70    INSTANCE.get_or_init(|| {
71        // Compute one period sine wavetable of size TABLE_LENGTH
72        (0..TABLE_LENGTH_USIZE)
73            .map(|x| ((x as f32) * 2.0 * PI * (1. / (TABLE_LENGTH_F32))).sin())
74            .collect()
75    })
76}
77
78// `MediaStreamRenderer` is internally used by `MediaElementAudioSourceNode` and
79// `MediaStreamAudioSourceNode`.
80struct MediaStreamRenderer<R> {
81    stream: R,
82    finished: bool,
83}
84
85impl<R> MediaStreamRenderer<R> {
86    fn new(stream: R) -> Self {
87        Self {
88            stream,
89            // scheduler,
90            finished: false,
91        }
92    }
93}
94
95impl<R: AudioBufferIter> AudioProcessor for MediaStreamRenderer<R> {
96    fn process(
97        &mut self,
98        _inputs: &[AudioRenderQuantum],
99        outputs: &mut [AudioRenderQuantum],
100        _params: AudioParamValues<'_>,
101        _scope: &AudioWorkletGlobalScope,
102    ) -> bool {
103        // single output node
104        let output = &mut outputs[0];
105
106        // @note - maybe we need to disciminate between a paused and depleted term
107        match self.stream.next() {
108            Some(Ok(buffer)) => {
109                let channels = buffer.number_of_channels();
110                output.set_number_of_channels(channels);
111                output
112                    .channels_mut()
113                    .iter_mut()
114                    .zip(buffer.channels())
115                    .for_each(|(o, i)| o.copy_from_slice(i.as_slice()));
116            }
117            Some(Err(e)) => {
118                log::warn!("Error playing audio stream: {}", e);
119                self.finished = true; // halt playback
120                output.make_silent()
121            }
122            None => {
123                if !self.finished {
124                    log::debug!("Stream finished");
125                    self.finished = true;
126                }
127                output.make_silent()
128            }
129        }
130
131        !self.finished
132    }
133}