From 7cb8ee882708c18089a2b94876978d567f8e9949 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Jim=C3=A9nez=20Moreno?= Date: Wed, 4 Jul 2018 23:05:18 +0200 Subject: [PATCH] Allow sharing AudioBufferSourceNode buffer --- examples/audio_decoder.rs | 8 ++- examples/play_noise.rs | 5 +- servo-media/src/audio/buffer_source_node.rs | 61 +++++++++++++-------- 3 files changed, 45 insertions(+), 29 deletions(-) diff --git a/examples/audio_decoder.rs b/examples/audio_decoder.rs index 8f3cbfca..4707514f 100644 --- a/examples/audio_decoder.rs +++ b/examples/audio_decoder.rs @@ -1,6 +1,6 @@ extern crate servo_media; -use servo_media::audio::buffer_source_node::AudioBufferSourceNodeMessage; +use servo_media::audio::buffer_source_node::{AudioBuffer, AudioBufferSourceNodeMessage}; use servo_media::audio::decoder::AudioDecoderCallbacks; use servo_media::audio::node::{AudioNodeMessage, AudioNodeType, AudioScheduledSourceNodeMessage}; use servo_media::ServoMedia; @@ -22,7 +22,8 @@ fn run_example(servo_media: Arc) { let mut file = File::open(filename).unwrap(); let mut bytes = vec![]; file.read_to_end(&mut bytes).unwrap(); - let decoded_audio: Arc>> = Arc::new(Mutex::new(Vec::new())); + // XXX Support multiple channels #55. + let decoded_audio: Arc> = Arc::new(Mutex::new(AudioBuffer::new(1, 0))); let progress = decoded_audio.clone(); let (sender, receiver) = mpsc::channel(); let callbacks = AudioDecoderCallbacks::new() @@ -36,6 +37,7 @@ fn run_example(servo_media: Arc) { progress .lock() .unwrap() + .buffers[0] .extend_from_slice((*buffer).as_ref()); }) .build(); @@ -53,7 +55,7 @@ fn run_example(servo_media: Arc) { context.message_node( buffer_source, AudioNodeMessage::AudioBufferSourceNode(AudioBufferSourceNodeMessage::SetBuffer( - decoded_audio.lock().unwrap().to_vec().into(), + Some(decoded_audio), )), ); let _ = context.resume(); diff --git a/examples/play_noise.rs b/examples/play_noise.rs index 8fab2670..96935f58 100644 --- a/examples/play_noise.rs +++ b/examples/play_noise.rs @@ -4,7 +4,7 @@ extern crate servo_media; use servo_media::audio::buffer_source_node::AudioBufferSourceNodeMessage; use servo_media::audio::node::{AudioNodeMessage, AudioNodeType, AudioScheduledSourceNodeMessage}; use servo_media::ServoMedia; -use std::sync::Arc; +use std::sync::{Arc, Mutex}; use std::{thread, time}; fn run_example(servo_media: Arc) { @@ -23,7 +23,8 @@ fn run_example(servo_media: Arc) { ); context.message_node( buffer_source, - AudioNodeMessage::AudioBufferSourceNode(AudioBufferSourceNodeMessage::SetBuffer(buffers.into())), + AudioNodeMessage::AudioBufferSourceNode( + AudioBufferSourceNodeMessage::SetBuffer(Some(Arc::new(Mutex::new(buffers.into()))))), ); let _ = context.resume(); thread::sleep(time::Duration::from_millis(5000)); diff --git a/servo-media/src/audio/buffer_source_node.rs b/servo-media/src/audio/buffer_source_node.rs index 221ca3d4..1db625e6 100644 --- a/servo-media/src/audio/buffer_source_node.rs +++ b/servo-media/src/audio/buffer_source_node.rs @@ -1,14 +1,17 @@ -use audio::node::ChannelInfo; use audio::block::{Block, Chunk, Tick, FRAMES_PER_BLOCK}; +use audio::node::ChannelInfo; use audio::node::{AudioNodeEngine, AudioScheduledSourceNodeMessage, BlockInfo}; use audio::param::{Param, UserAutomationEvent}; +use std::sync::{Arc, Mutex}; /// Control messages directed to AudioBufferSourceNodes. #[derive(Debug, Clone)] pub enum AudioBufferSourceNodeMessage { /// Set the data block holding the audio sample data to be played. - SetBuffer(AudioBuffer), + SetBuffer(Option>>), + /// Set the speed at which to render the audio stream. SetPlaybackRate(UserAutomationEvent), + /// Set detune, to modulate the speed at which is rendered the audio stream. SetDetune(UserAutomationEvent), } @@ -51,7 +54,7 @@ impl Default for AudioBufferSourceNodeOptions { pub struct AudioBufferSourceNode { channel_info: ChannelInfo, /// A data block holding the audio sample data to be played. - buffer: Option, + buffer: Option>>, /// AudioParam to modulate the speed at which is rendered the audio stream. detune: Param, /// Indicates if the region of audio data designated by loopStart and loopEnd @@ -75,9 +78,13 @@ pub struct AudioBufferSourceNode { impl AudioBufferSourceNode { pub fn new(options: AudioBufferSourceNodeOptions) -> Self { + let buffer = match options.buffer { + Some(buffer) => Some(Arc::new(Mutex::new(buffer))), + None => None, + }; Self { channel_info: Default::default(), - buffer: options.buffer, + buffer, detune: Param::new(options.detune), loop_enabled: options.loop_enabled, loop_end: options.loop_end, @@ -92,18 +99,22 @@ impl AudioBufferSourceNode { pub fn handle_message(&mut self, message: AudioBufferSourceNodeMessage, sample_rate: f32) { match message { AudioBufferSourceNodeMessage::SetBuffer(buffer) => { - self.buffer = Some(buffer); - }, + self.buffer = buffer; + } AudioBufferSourceNodeMessage::SetPlaybackRate(event) => { self.playback_rate.insert_event(event.to_event(sample_rate)); - }, + } AudioBufferSourceNodeMessage::SetDetune(event) => { self.detune.insert_event(event.to_event(sample_rate)); } } } - pub fn handle_source_node_message(&mut self, message: AudioScheduledSourceNodeMessage, sample_rate: f32) { + pub fn handle_source_node_message( + &mut self, + message: AudioScheduledSourceNodeMessage, + sample_rate: f32, + ) { match message { AudioScheduledSourceNodeMessage::Start(when) => { self.start(Tick::from_time(when, sample_rate)); @@ -130,11 +141,12 @@ impl AudioNodeEngine for AudioBufferSourceNode { return inputs; }; - if self.playback_offset >= buffer.len() || - self.should_play_at(info.frame) == (false, true) { - inputs.blocks.push(Default::default()); - return inputs; - } + if self.playback_offset >= buffer.lock().unwrap().len() + || self.should_play_at(info.frame) == (false, true) + { + inputs.blocks.push(Default::default()); + return inputs; + } let samples_to_copy = match self.stop_at { Some(stop_at) => { @@ -150,10 +162,10 @@ impl AudioNodeEngine for AudioBufferSourceNode { let next_offset = self.playback_offset + samples_to_copy; - if samples_to_copy == FRAMES_PER_BLOCK.0 as usize { // copy entire chan let mut block = Block::empty(); + let buffer = buffer.lock().unwrap(); for chan in 0..buffer.chans() { block.push_chan(&buffer.buffers[chan as usize][self.playback_offset..next_offset]); } @@ -161,11 +173,14 @@ impl AudioNodeEngine for AudioBufferSourceNode { } else { // silent fill and copy let mut block = Block::default(); + let buffer = buffer.lock().unwrap(); block.repeat(buffer.chans()); block.explicit_repeat(); for chan in 0..buffer.chans() { let data = block.data_chan_mut(chan); - data.copy_from_slice(&buffer.buffers[chan as usize][self.playback_offset..next_offset]); + data.copy_from_slice( + &buffer.buffers[chan as usize][self.playback_offset..next_offset], + ); } inputs.blocks.push(block) } @@ -174,14 +189,16 @@ impl AudioNodeEngine for AudioBufferSourceNode { inputs } - make_message_handler!(AudioBufferSourceNode: handle_message, - AudioScheduledSourceNode: handle_source_node_message); + make_message_handler!( + AudioBufferSourceNode: handle_message, + AudioScheduledSourceNode: handle_source_node_message + ); } #[derive(Debug, Clone)] pub struct AudioBuffer { /// Invariant: all buffers must be of the same length - pub buffers: Vec> + pub buffers: Vec>, } impl AudioBuffer { @@ -198,9 +215,7 @@ impl AudioBuffer { assert!(buf.len() == buffers[0].len()) } - Self { - buffers - } + Self { buffers } } pub fn len(&self) -> usize { @@ -214,9 +229,7 @@ impl AudioBuffer { impl From> for AudioBuffer { fn from(vec: Vec) -> Self { - Self { - buffers: vec![vec] - } + Self { buffers: vec![vec] } } }