1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
use crate::context::{AudioContextRegistration, BaseAudioContext};
use crate::media_streams::MediaStream;
use crate::resampling::Resampler;
use crate::RENDER_QUANTUM_SIZE;
use super::{AudioNode, ChannelConfig, MediaStreamRenderer};
/// Options for constructing a [`MediaStreamAudioSourceNode`]
// dictionary MediaStreamAudioSourceOptions {
// required MediaStream mediaStream;
// };
//
// @note - Does not extend AudioNodeOptions because AudioNodeOptions are
// useless for source nodes as they instruct how to upmix the inputs.
// This is a common source of confusion, see e.g. https://github.com/mdn/content/pull/18472
pub struct MediaStreamAudioSourceOptions<'a> {
pub media_stream: &'a MediaStream,
}
/// An audio source from a [`MediaStream`] (e.g. microphone input)
///
/// IMPORTANT: the media stream is polled on the render thread so you must ensure the media stream
/// iterator never blocks. Use a
/// [`MediaElementAudioSourceNode`](crate::node::MediaElementAudioSourceNode) for real time safe
/// media playback.
pub struct MediaStreamAudioSourceNode {
registration: AudioContextRegistration,
channel_config: ChannelConfig,
}
impl AudioNode for MediaStreamAudioSourceNode {
fn registration(&self) -> &AudioContextRegistration {
&self.registration
}
fn channel_config(&self) -> &ChannelConfig {
&self.channel_config
}
fn number_of_inputs(&self) -> usize {
0
}
fn number_of_outputs(&self) -> usize {
1
}
}
impl MediaStreamAudioSourceNode {
/// Create a new `MediaStreamAudioSourceNode`
///
/// # Panics
///
/// This method will panic when the provided `MediaStream` does not contain any audio tracks.
pub fn new<C: BaseAudioContext>(
context: &C,
options: MediaStreamAudioSourceOptions<'_>,
) -> Self {
context.register(move |registration| {
let node = MediaStreamAudioSourceNode {
registration,
channel_config: ChannelConfig::default(),
};
let resampler = Resampler::new(
context.sample_rate(),
RENDER_QUANTUM_SIZE,
options.media_stream.get_tracks()[0].iter(),
);
let render = MediaStreamRenderer::new(resampler);
(node, Box::new(render))
})
}
}