Skip to main content

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_F32: f32 = TABLE_LENGTH_USIZE as f32;
63
64/// Precomputed sine table
65pub(crate) fn precomputed_sine_table() -> &'static [f32] {
66    static INSTANCE: OnceLock<Vec<f32>> = OnceLock::new();
67    INSTANCE.get_or_init(|| {
68        // Compute one period sine wavetable of size TABLE_LENGTH
69        (0..TABLE_LENGTH_USIZE)
70            .map(|x| ((x as f32) * 2.0 * PI * (1. / (TABLE_LENGTH_F32))).sin())
71            .collect()
72    })
73}
74
75// `MediaStreamRenderer` is internally used by `MediaElementAudioSourceNode` and
76// `MediaStreamAudioSourceNode`.
77struct MediaStreamRenderer<R> {
78    stream: R,
79    finished: bool,
80}
81
82impl<R> MediaStreamRenderer<R> {
83    fn new(stream: R) -> Self {
84        Self {
85            stream,
86            // scheduler,
87            finished: false,
88        }
89    }
90}
91
92impl<R: AudioBufferIter> AudioProcessor for MediaStreamRenderer<R> {
93    fn process(
94        &mut self,
95        _inputs: &[AudioRenderQuantum],
96        outputs: &mut [AudioRenderQuantum],
97        _params: AudioParamValues<'_>,
98        _scope: &AudioWorkletGlobalScope,
99    ) -> bool {
100        // single output node
101        let output = &mut outputs[0];
102
103        // @note - maybe we need to disciminate between a paused and depleted term
104        match self.stream.next() {
105            Some(Ok(buffer)) => {
106                let channels = buffer.number_of_channels();
107                output.set_number_of_channels(channels);
108                output
109                    .channels_mut()
110                    .iter_mut()
111                    .zip(buffer.channels())
112                    .for_each(|(o, i)| o.copy_from_slice(i.as_slice()));
113            }
114            Some(Err(e)) => {
115                log::warn!("Error playing audio stream: {}", e);
116                self.finished = true; // halt playback
117                output.make_silent()
118            }
119            None => {
120                if !self.finished {
121                    log::debug!("Stream finished");
122                    self.finished = true;
123                }
124                output.make_silent()
125            }
126        }
127
128        !self.finished
129    }
130}