servo_media_audio/
media_element_source_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::collections::HashMap;
6use std::collections::hash_map::Entry;
7use std::sync::mpsc::Sender;
8use std::sync::{Arc, Mutex};
9
10use player::audio::AudioRenderer;
11
12use crate::block::{Block, Chunk, FRAMES_PER_BLOCK};
13use crate::node::{AudioNodeEngine, AudioNodeType, BlockInfo, ChannelInfo};
14
15#[derive(Debug, Clone)]
16pub enum MediaElementSourceNodeMessage {
17    GetAudioRenderer(Sender<Arc<Mutex<dyn AudioRenderer>>>),
18}
19
20#[derive(AudioNodeCommon)]
21pub(crate) struct MediaElementSourceNode {
22    channel_info: ChannelInfo,
23    renderer: Arc<Mutex<dyn AudioRenderer>>,
24    buffers: Arc<Mutex<Vec<Vec<f32>>>>,
25    playback_offset: usize,
26}
27
28impl MediaElementSourceNode {
29    pub fn new(channel_info: ChannelInfo) -> Self {
30        let buffers = Arc::new(Mutex::new(Vec::new()));
31        let renderer = Arc::new(Mutex::new(MediaElementSourceNodeRenderer::new(
32            buffers.clone(),
33        )));
34        Self {
35            channel_info,
36            renderer,
37            buffers,
38            playback_offset: 0,
39        }
40    }
41
42    pub fn handle_message(&mut self, message: MediaElementSourceNodeMessage, _: f32) {
43        match message {
44            MediaElementSourceNodeMessage::GetAudioRenderer(sender) => {
45                let _ = sender.send(self.renderer.clone());
46            },
47        }
48    }
49}
50
51impl AudioNodeEngine for MediaElementSourceNode {
52    fn node_type(&self) -> AudioNodeType {
53        AudioNodeType::MediaElementSourceNode
54    }
55
56    fn process(&mut self, mut inputs: Chunk, _info: &BlockInfo) -> Chunk {
57        debug_assert!(inputs.is_empty());
58
59        let buffers = self.buffers.lock().unwrap();
60        let chans = buffers.len() as u8;
61
62        if chans == 0 {
63            inputs.blocks.push(Default::default());
64            return inputs;
65        }
66
67        let len = buffers[0].len();
68
69        let frames_per_block = FRAMES_PER_BLOCK.0 as usize;
70        let samples_to_copy = if self.playback_offset + frames_per_block > len {
71            len - self.playback_offset
72        } else {
73            frames_per_block
74        };
75        let next_offset = self.playback_offset + samples_to_copy;
76        if samples_to_copy == FRAMES_PER_BLOCK.0 as usize {
77            // copy entire chan
78            let mut block = Block::empty();
79            for chan in 0..chans {
80                block.push_chan(&buffers[chan as usize][self.playback_offset..next_offset]);
81            }
82            inputs.blocks.push(block)
83        } else {
84            // silent fill and copy
85            let mut block = Block::default();
86            block.repeat(chans);
87            block.explicit_repeat();
88            for chan in 0..chans {
89                let data = block.data_chan_mut(chan);
90                let (_, data) = data.split_at_mut(0);
91                let (data, _) = data.split_at_mut(samples_to_copy);
92                data.copy_from_slice(&buffers[chan as usize][self.playback_offset..next_offset]);
93            }
94            inputs.blocks.push(block)
95        }
96
97        self.playback_offset = next_offset;
98
99        inputs
100    }
101
102    fn input_count(&self) -> u32 {
103        0
104    }
105
106    make_message_handler!(MediaElementSourceNode: handle_message);
107}
108
109struct MediaElementSourceNodeRenderer {
110    buffers: Arc<Mutex<Vec<Vec<f32>>>>,
111    channels: HashMap<u32, usize>,
112}
113
114impl MediaElementSourceNodeRenderer {
115    pub fn new(buffers: Arc<Mutex<Vec<Vec<f32>>>>) -> Self {
116        Self {
117            buffers,
118            channels: HashMap::new(),
119        }
120    }
121}
122
123impl AudioRenderer for MediaElementSourceNodeRenderer {
124    fn render(&mut self, sample: Box<dyn AsRef<[f32]>>, channel_pos: u32) {
125        let channel = match self.channels.entry(channel_pos) {
126            Entry::Occupied(entry) => *entry.get(),
127            Entry::Vacant(entry) => {
128                let mut buffers = self.buffers.lock().unwrap();
129                let len = buffers.len();
130                buffers.resize(len + 1, Vec::new());
131                *entry.insert(buffers.len())
132            },
133        };
134        self.buffers.lock().unwrap()[channel - 1].extend_from_slice((*sample).as_ref());
135    }
136}