servo_media_audio/
offline_sink.rs1use std::cell::{Cell, RefCell};
6use std::sync::mpsc::Sender;
7
8use servo_media_streams::MediaSocket;
9
10use crate::block::{Chunk, FRAMES_PER_BLOCK_USIZE};
11use crate::render_thread::{AudioRenderThreadMsg, SinkEosCallback};
12use crate::sink::{AudioSink, AudioSinkError};
13
14pub struct ProcessedAudio(Box<[f32]>);
15
16impl AsRef<[f32]> for ProcessedAudio {
17 fn as_ref(&self) -> &[f32] {
18 &self.0
19 }
20}
21
22pub struct OfflineAudioSink {
23 buffer: RefCell<Option<Vec<f32>>>,
24 channel_count: usize,
25 has_enough_data: Cell<bool>,
26 length: usize,
27 rendered_blocks: Cell<usize>,
28 eos_callback: RefCell<Option<SinkEosCallback>>,
29}
30
31impl OfflineAudioSink {
32 pub fn new(channel_count: usize, length: usize) -> Self {
33 Self {
34 buffer: RefCell::new(None),
35 channel_count,
36 has_enough_data: Cell::new(false),
37 length,
38 rendered_blocks: Cell::new(0),
39 eos_callback: RefCell::new(None),
40 }
41 }
42}
43
44impl AudioSink for OfflineAudioSink {
45 fn init(&self, _: f32, _: Sender<AudioRenderThreadMsg>) -> Result<(), AudioSinkError> {
46 Ok(())
47 }
48 fn init_stream(&self, _: u8, _: f32, _: Box<dyn MediaSocket>) -> Result<(), AudioSinkError> {
49 unreachable!("OfflineAudioSink should never be used for MediaStreamDestinationNode")
50 }
51 fn play(&self) -> Result<(), AudioSinkError> {
52 self.has_enough_data.set(false);
53 Ok(())
54 }
55
56 fn stop(&self) -> Result<(), AudioSinkError> {
57 self.has_enough_data.set(true);
58 Ok(())
59 }
60
61 fn has_enough_data(&self) -> bool {
62 self.has_enough_data.get() ||
63 (self.rendered_blocks.get() * FRAMES_PER_BLOCK_USIZE >= self.length)
64 }
65
66 fn push_data(&self, mut chunk: Chunk) -> Result<(), AudioSinkError> {
67 let offset = self.rendered_blocks.get() * FRAMES_PER_BLOCK_USIZE;
68 let (last, copy_len) = if self.length - offset <= FRAMES_PER_BLOCK_USIZE {
69 (true, self.length - offset)
70 } else {
71 (false, FRAMES_PER_BLOCK_USIZE)
72 };
73 let mut buffer = self.buffer.borrow_mut();
74 if buffer.is_none() {
75 *buffer = Some(vec![0.; self.channel_count * self.length]);
76 }
77 if chunk.is_empty() {
78 chunk.blocks.push(Default::default());
79 }
80 if chunk.blocks[0].is_empty() {
81 chunk.blocks[0].explicit_silence();
82 }
83 if let Some(ref mut buffer) = *buffer {
84 for channel_number in 0..self.channel_count {
85 let channel_offset = offset + (channel_number * self.length);
86 let channel_data = &mut buffer[channel_offset..channel_offset + copy_len];
87 channel_data
88 .copy_from_slice(&chunk.blocks[0].data_chan(channel_number as u8)[0..copy_len]);
89 }
90 };
91 self.rendered_blocks.set(self.rendered_blocks.get() + 1);
92
93 if last {
94 if let Some(callback) = self.eos_callback.borrow_mut().take() {
95 let processed_audio = ProcessedAudio(buffer.take().unwrap().into_boxed_slice());
96 callback(Box::new(processed_audio));
97 }
98 }
99
100 Ok(())
101 }
102
103 fn set_eos_callback(
104 &self,
105 callback: Box<dyn Fn(Box<dyn AsRef<[f32]>>) + Send + Sync + 'static>,
106 ) {
107 *self.eos_callback.borrow_mut() = Some(callback);
108 }
109}