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
77
78
79
80
81
82
83
84
85
86
87
use crate::buffer::{AudioBuffer, ChannelConfig, ChannelConfigOptions, Resampler};
use crate::context::{AsBaseAudioContext, AudioContextRegistration};
use crate::control::{Controller, Scheduler};
use crate::media::MediaElement;
use crate::{SampleRate, BUFFER_SIZE};

use super::{
    AudioControllableSourceNode, AudioNode, AudioScheduledSourceNode, MediaStreamRenderer,
};

/// Options for constructing a AudioBufferSourceNode
#[derive(Default)]
pub struct AudioBufferSourceNodeOptions {
    pub buffer: Option<AudioBuffer>,
    pub channel_config: ChannelConfigOptions,
}

/// An audio source from an in-memory audio asset in an AudioBuffer
///
/// Note: do not forget to `start()` the node.
pub struct AudioBufferSourceNode {
    registration: AudioContextRegistration,
    channel_config: ChannelConfig,
    controller: Controller,
}

impl AudioScheduledSourceNode for AudioBufferSourceNode {
    fn scheduler(&self) -> &Scheduler {
        self.controller.scheduler()
    }
}
impl AudioControllableSourceNode for AudioBufferSourceNode {
    fn controller(&self) -> &Controller {
        &self.controller
    }
}

impl AudioNode for AudioBufferSourceNode {
    fn registration(&self) -> &AudioContextRegistration {
        &self.registration
    }

    fn channel_config_raw(&self) -> &ChannelConfig {
        &self.channel_config
    }

    fn number_of_inputs(&self) -> u32 {
        0
    }
    fn number_of_outputs(&self) -> u32 {
        1
    }
}

impl AudioBufferSourceNode {
    pub fn new<C: AsBaseAudioContext>(context: &C, options: AudioBufferSourceNodeOptions) -> Self {
        context.base().register(move |registration| {
            // unwrap_or_default buffer
            let buffer = options
                .buffer
                .unwrap_or_else(|| AudioBuffer::new(1, BUFFER_SIZE, SampleRate(44_100)));

            // wrap input in resampler
            let resampler = Resampler::new(
                context.base().sample_rate(),
                BUFFER_SIZE,
                std::iter::once(Ok(buffer)),
            );

            // wrap resampler in media-element (for loop/play/pause)
            let media = MediaElement::new(resampler);
            let controller = media.controller().clone();
            let scheduler = controller.scheduler().clone();

            // setup user facing audio node
            let node = AudioBufferSourceNode {
                registration,
                channel_config: options.channel_config.into(),
                controller,
            };

            let render = MediaStreamRenderer::new(media, scheduler);

            (node, Box::new(render))
        })
    }
}