From af5186698a392658e244ad39ee55c00cc7fd78db Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Tue, 26 Jun 2018 17:06:25 -0700 Subject: [PATCH 1/6] Add AudioNodeCommon and some plumbing for setting channel counts --- servo-media-derive/src/lib.rs | 19 ++++++++ servo-media/src/audio/buffer_source_node.rs | 2 +- servo-media/src/audio/channel_node.rs | 2 + servo-media/src/audio/destination_node.rs | 1 + servo-media/src/audio/gain_node.rs | 1 + servo-media/src/audio/macros.rs | 10 ++-- servo-media/src/audio/node.rs | 51 +++++++++++++++++++-- servo-media/src/audio/oscillator_node.rs | 3 +- 8 files changed, 78 insertions(+), 11 deletions(-) diff --git a/servo-media-derive/src/lib.rs b/servo-media-derive/src/lib.rs index 149871b7..4bce7422 100644 --- a/servo-media-derive/src/lib.rs +++ b/servo-media-derive/src/lib.rs @@ -61,3 +61,22 @@ fn impl_audio_scheduled_source_node(ast: &syn::DeriveInput) -> quote::Tokens { } } } + +#[proc_macro_derive(AudioNodeCommon)] +pub fn channel_info(input: TokenStream) -> TokenStream { + let s = input.to_string(); + let ast = syn::parse_derive_input(&s).unwrap(); + let name = &ast.ident; + let gen = quote! { + impl ::audio::node::AudioNodeCommon for #name { + fn channel_info(&self) -> &::audio::node::ChannelInfo { + panic!() + } + + fn channel_info_mut(&mut self) -> &mut ::audio::node::ChannelInfo { + panic!() + } + } + }; + gen.parse().unwrap() +} diff --git a/servo-media/src/audio/buffer_source_node.rs b/servo-media/src/audio/buffer_source_node.rs index 25c9c4a2..76fbd637 100644 --- a/servo-media/src/audio/buffer_source_node.rs +++ b/servo-media/src/audio/buffer_source_node.rs @@ -42,7 +42,7 @@ impl Default for AudioBufferSourceNodeOptions { /// https://webaudio.github.io/web-audio-api/#AudioBufferSourceNode /// XXX Implement looping /// XXX Implement playbackRate and related bits -#[derive(AudioScheduledSourceNode)] +#[derive(AudioScheduledSourceNode, AudioNodeCommon)] #[allow(dead_code)] pub struct AudioBufferSourceNode { /// A data block holding the audio sample data to be played. diff --git a/servo-media/src/audio/channel_node.rs b/servo-media/src/audio/channel_node.rs index 316c2f5b..08ebb1f2 100644 --- a/servo-media/src/audio/channel_node.rs +++ b/servo-media/src/audio/channel_node.rs @@ -8,6 +8,7 @@ pub struct ChannelNodeOptions { pub channels: u8, } +#[derive(AudioNodeCommon)] pub struct ChannelMergerNode { channels: u8 } @@ -48,6 +49,7 @@ impl AudioNodeEngine for ChannelMergerNode { } +#[derive(AudioNodeCommon)] pub struct ChannelSplitterNode { channels: u8 } diff --git a/servo-media/src/audio/destination_node.rs b/servo-media/src/audio/destination_node.rs index 6a1fa981..6b580283 100644 --- a/servo-media/src/audio/destination_node.rs +++ b/servo-media/src/audio/destination_node.rs @@ -2,6 +2,7 @@ use audio::node::ChannelCountMode; use audio::node::{AudioNodeEngine, BlockInfo}; use audio::block::Chunk; +#[derive(AudioNodeCommon)] pub struct DestinationNode(Option); impl DestinationNode { diff --git a/servo-media/src/audio/gain_node.rs b/servo-media/src/audio/gain_node.rs index 15855eae..1ca093ca 100644 --- a/servo-media/src/audio/gain_node.rs +++ b/servo-media/src/audio/gain_node.rs @@ -19,6 +19,7 @@ impl Default for GainNodeOptions { } } +#[derive(AudioNodeCommon)] pub struct GainNode { gain: Param, } diff --git a/servo-media/src/audio/macros.rs b/servo-media/src/audio/macros.rs index bdb07763..74dae718 100644 --- a/servo-media/src/audio/macros.rs +++ b/servo-media/src/audio/macros.rs @@ -5,13 +5,14 @@ macro_rules! make_message_handler( $node:ident: $handler:ident ),+ ) => ( - fn message(&mut self, msg: ::audio::node::AudioNodeMessage, sample_rate: f32) { + fn message_specific(&mut self, msg: ::audio::node::AudioNodeMessage, sample_rate: f32) { match msg { $(::audio::node::AudioNodeMessage::$node(m) => self.$handler(m, sample_rate)),+, _ => (), } - }); + } ); +); #[macro_export] macro_rules! make_state_change( @@ -21,8 +22,9 @@ macro_rules! make_state_change( let (tx, rx) = mpsc::channel(); let _ = self.sender.send(AudioRenderThreadMsg::$render_msg(tx)); rx.recv().unwrap() - }); + } ); +); #[macro_export] macro_rules! make_render_thread_state_change( @@ -34,5 +36,5 @@ macro_rules! make_render_thread_state_change( self.state = ProcessingState::$state; self.sink.$sink_method() } - ); ); +); diff --git a/servo-media/src/audio/node.rs b/servo-media/src/audio/node.rs index 866ff521..7d511406 100644 --- a/servo-media/src/audio/node.rs +++ b/servo-media/src/audio/node.rs @@ -56,11 +56,45 @@ impl BlockInfo { } } + +pub struct ChannelInfo { + pub count: u8, + pub mode: ChannelCountMode, + pub interpretation: ChannelInterpretation, +} + +impl Default for ChannelInfo { + fn default() -> Self { + ChannelInfo { + count: 2, + mode: ChannelCountMode::Max, + interpretation: ChannelInterpretation::Speakers, + } + } +} + + +pub trait AudioNodeCommon { + fn channel_info(&self) -> &ChannelInfo; + + fn channel_info_mut(&mut self) -> &mut ChannelInfo; +} + /// This trait represents the common features of all audio nodes. -pub trait AudioNodeEngine: Send { +pub trait AudioNodeEngine: Send + AudioNodeCommon { fn process(&mut self, inputs: Chunk, info: &BlockInfo) -> Chunk; - fn message(&mut self, _: AudioNodeMessage, _sample_rate: f32) {} + fn message(&mut self, msg: AudioNodeMessage, sample_rate: f32) { + match msg { + AudioNodeMessage::SetChannelCount(c) => self.set_channel_count(c), + AudioNodeMessage::SetChannelMode(c) => self.set_channel_mode(c), + AudioNodeMessage::SetChannelInterpretation(c) => self.set_channel_interpretation(c), + _ => self.message_specific(msg, sample_rate), + } + } + + /// Messages specific to this node + fn message_specific(&mut self, _: AudioNodeMessage, _sample_rate: f32) {} fn input_count(&self) -> u32 { 1 @@ -71,17 +105,21 @@ pub trait AudioNodeEngine: Send { /// Number of input channels for each input port fn channel_count(&self) -> u8 { - 1 + self.channel_info().count } fn channel_count_mode(&self) -> ChannelCountMode { - ChannelCountMode::Max + self.channel_info().mode } fn channel_interpretation(&self) -> ChannelInterpretation { - ChannelInterpretation::Speakers + self.channel_info().interpretation } + fn set_channel_interpretation(&mut self, _: ChannelInterpretation) {} + fn set_channel_count(&mut self, _: u8) {} + fn set_channel_mode(&mut self, _: ChannelCountMode) {} + /// If we're the destination node, extract the contained data fn destination_data(&mut self) -> Option { None @@ -93,6 +131,9 @@ pub enum AudioNodeMessage { AudioScheduledSourceNode(AudioScheduledSourceNodeMessage), GainNode(GainNodeMessage), OscillatorNode(OscillatorNodeMessage), + SetChannelCount(u8), + SetChannelMode(ChannelCountMode), + SetChannelInterpretation(ChannelInterpretation), } /// This trait represents the common features of the source nodes such as diff --git a/servo-media/src/audio/oscillator_node.rs b/servo-media/src/audio/oscillator_node.rs index 0a2669fc..18893ac2 100644 --- a/servo-media/src/audio/oscillator_node.rs +++ b/servo-media/src/audio/oscillator_node.rs @@ -40,7 +40,7 @@ impl Default for OscillatorNodeOptions { } } -#[derive(AudioScheduledSourceNode)] +#[derive(AudioScheduledSourceNode, AudioNodeCommon)] pub struct OscillatorNode { frequency: Param, phase: f64, @@ -50,6 +50,7 @@ pub struct OscillatorNode { stop_at: Option, } + impl OscillatorNode { pub fn new(options: OscillatorNodeOptions) -> Self { Self { From 9086a9b2579ac855f1ce06442691ebe4d85fd581 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Tue, 26 Jun 2018 17:15:46 -0700 Subject: [PATCH 2/6] Add ChannelInfo to all nodes; use --- servo-media-derive/src/lib.rs | 4 +-- servo-media/src/audio/buffer_source_node.rs | 9 +++-- servo-media/src/audio/channel_node.rs | 37 ++++++++++++++++----- servo-media/src/audio/destination_node.rs | 28 +++++++++------- servo-media/src/audio/gain_node.rs | 8 ++--- servo-media/src/audio/node.rs | 14 +++++--- servo-media/src/audio/oscillator_node.rs | 9 +++-- 7 files changed, 67 insertions(+), 42 deletions(-) diff --git a/servo-media-derive/src/lib.rs b/servo-media-derive/src/lib.rs index 4bce7422..b01bbece 100644 --- a/servo-media-derive/src/lib.rs +++ b/servo-media-derive/src/lib.rs @@ -70,11 +70,11 @@ pub fn channel_info(input: TokenStream) -> TokenStream { let gen = quote! { impl ::audio::node::AudioNodeCommon for #name { fn channel_info(&self) -> &::audio::node::ChannelInfo { - panic!() + &self.channel_info } fn channel_info_mut(&mut self) -> &mut ::audio::node::ChannelInfo { - panic!() + &mut self.channel_info } } }; diff --git a/servo-media/src/audio/buffer_source_node.rs b/servo-media/src/audio/buffer_source_node.rs index 76fbd637..c04645e7 100644 --- a/servo-media/src/audio/buffer_source_node.rs +++ b/servo-media/src/audio/buffer_source_node.rs @@ -1,5 +1,6 @@ +use audio::node::ChannelInfo; use audio::block::{Block, Chunk, Tick, FRAMES_PER_BLOCK}; -use audio::node::{AudioNodeEngine, AudioScheduledSourceNodeMessage, BlockInfo, ChannelCountMode}; +use audio::node::{AudioNodeEngine, AudioScheduledSourceNodeMessage, BlockInfo}; use audio::param::Param; /// Control messages directed to AudioBufferSourceNodes. @@ -45,6 +46,7 @@ impl Default for AudioBufferSourceNodeOptions { #[derive(AudioScheduledSourceNode, AudioNodeCommon)] #[allow(dead_code)] pub struct AudioBufferSourceNode { + channel_info: ChannelInfo, /// A data block holding the audio sample data to be played. buffer: Option, /// AudioParam to modulate the speed at which is rendered the audio stream. @@ -71,6 +73,7 @@ pub struct AudioBufferSourceNode { impl AudioBufferSourceNode { pub fn new(options: AudioBufferSourceNodeOptions) -> Self { Self { + channel_info: Default::default(), buffer: options.buffer, detune: Param::new(options.detune), loop_enabled: options.loop_enabled, @@ -108,10 +111,6 @@ impl AudioNodeEngine for AudioBufferSourceNode { 0 } - fn channel_count_mode(&self) -> ChannelCountMode { - ChannelCountMode::Max - } - fn process(&mut self, mut inputs: Chunk, info: &BlockInfo) -> Chunk { debug_assert!(inputs.len() == 0); diff --git a/servo-media/src/audio/channel_node.rs b/servo-media/src/audio/channel_node.rs index 08ebb1f2..390bc7fc 100644 --- a/servo-media/src/audio/channel_node.rs +++ b/servo-media/src/audio/channel_node.rs @@ -1,6 +1,5 @@ -use audio::node::ChannelCountMode; use audio::block::FRAMES_PER_BLOCK_USIZE; -use audio::node::AudioNodeEngine; +use audio::node::{AudioNodeEngine, ChannelCountMode, ChannelInfo, ChannelInterpretation}; use audio::block::{Block, Chunk}; use audio::node::BlockInfo; @@ -10,12 +9,18 @@ pub struct ChannelNodeOptions { #[derive(AudioNodeCommon)] pub struct ChannelMergerNode { + channel_info: ChannelInfo, channels: u8 } impl ChannelMergerNode { pub fn new(params: ChannelNodeOptions) -> Self { ChannelMergerNode { + channel_info: ChannelInfo { + count: 1, + mode: ChannelCountMode::Explicit, + ..Default::default() + }, channels: params.channels } } @@ -43,21 +48,28 @@ impl AudioNodeEngine for ChannelMergerNode { self.channels as u32 } - fn channel_count_mode(&self) -> ChannelCountMode { - ChannelCountMode::Explicit + fn set_channel_count_mode(&mut self, _: ChannelCountMode) { + panic!("channel merger nodes cannot have their mode changed"); } + fn set_channel_count(&mut self, _: u8) { + panic!("channel merger nodes cannot have their channel count changed"); + } } #[derive(AudioNodeCommon)] pub struct ChannelSplitterNode { - channels: u8 + channel_info: ChannelInfo, } impl ChannelSplitterNode { pub fn new(params: ChannelNodeOptions) -> Self { ChannelSplitterNode { - channels: params.channels + channel_info: ChannelInfo { + count: params.channels, + mode: ChannelCountMode::Explicit, + interpretation: ChannelInterpretation::Discrete, + }, } } } @@ -78,11 +90,18 @@ impl AudioNodeEngine for ChannelSplitterNode { } fn output_count(&self) -> u32 { - self.channels as u32 + self.channel_count() as u32 } - fn channel_count_mode(&self) -> ChannelCountMode { - ChannelCountMode::Explicit + fn set_channel_count_mode(&mut self, _: ChannelCountMode) { + panic!("channel splitter nodes cannot have their mode changed"); } + fn set_channel_interpretation(&mut self, _: ChannelInterpretation) { + panic!("channel splitter nodes cannot have their channel interpretation changed"); + } + + fn set_channel_count(&mut self, _: u8) { + panic!("channel splitter nodes cannot have their channel count changed"); + } } diff --git a/servo-media/src/audio/destination_node.rs b/servo-media/src/audio/destination_node.rs index 6b580283..91bb0695 100644 --- a/servo-media/src/audio/destination_node.rs +++ b/servo-media/src/audio/destination_node.rs @@ -1,37 +1,41 @@ +use audio::node::ChannelInfo; use audio::node::ChannelCountMode; use audio::node::{AudioNodeEngine, BlockInfo}; use audio::block::Chunk; #[derive(AudioNodeCommon)] -pub struct DestinationNode(Option); +pub struct DestinationNode { + channel_info: ChannelInfo, + chunk: Option +} impl DestinationNode { pub fn new() -> Self { - DestinationNode(None) + DestinationNode { + channel_info: ChannelInfo { + mode: ChannelCountMode::Explicit, + ..Default::default() + }, + chunk: None, + } } } impl AudioNodeEngine for DestinationNode { fn process(&mut self, inputs: Chunk, _: &BlockInfo) -> Chunk { - self.0 = Some(inputs); + self.chunk = Some(inputs); Chunk::default() } fn destination_data(&mut self) -> Option { - self.0.take() + self.chunk.take() } fn output_count(&self) -> u32 { 0 } - fn channel_count(&self) -> u8 { - // currently hardcoded here and in our invocation of - // gst_audio::AudioInfo::new - 2 - } - - fn channel_count_mode(&self) -> ChannelCountMode { - ChannelCountMode::Explicit + fn set_channel_count_mode(&mut self, _: ChannelCountMode) { + panic!("destination nodes cannot have their mode changed"); } } diff --git a/servo-media/src/audio/gain_node.rs b/servo-media/src/audio/gain_node.rs index 1ca093ca..468187dc 100644 --- a/servo-media/src/audio/gain_node.rs +++ b/servo-media/src/audio/gain_node.rs @@ -1,4 +1,4 @@ -use audio::node::ChannelCountMode; +use audio::node::ChannelInfo; use audio::block::Chunk; use audio::block::Tick; use audio::node::AudioNodeEngine; @@ -21,12 +21,14 @@ impl Default for GainNodeOptions { #[derive(AudioNodeCommon)] pub struct GainNode { + channel_info: ChannelInfo, gain: Param, } impl GainNode { pub fn new(options: GainNodeOptions) -> Self { Self { + channel_info: Default::default(), gain: Param::new(options.gain), } } @@ -64,9 +66,5 @@ impl AudioNodeEngine for GainNode { inputs } - fn channel_count_mode(&self) -> ChannelCountMode { - ChannelCountMode::Max - } - make_message_handler!(GainNode: handle_message); } diff --git a/servo-media/src/audio/node.rs b/servo-media/src/audio/node.rs index 7d511406..f92e6ea0 100644 --- a/servo-media/src/audio/node.rs +++ b/servo-media/src/audio/node.rs @@ -87,7 +87,7 @@ pub trait AudioNodeEngine: Send + AudioNodeCommon { fn message(&mut self, msg: AudioNodeMessage, sample_rate: f32) { match msg { AudioNodeMessage::SetChannelCount(c) => self.set_channel_count(c), - AudioNodeMessage::SetChannelMode(c) => self.set_channel_mode(c), + AudioNodeMessage::SetChannelMode(c) => self.set_channel_count_mode(c), AudioNodeMessage::SetChannelInterpretation(c) => self.set_channel_interpretation(c), _ => self.message_specific(msg, sample_rate), } @@ -116,9 +116,15 @@ pub trait AudioNodeEngine: Send + AudioNodeCommon { self.channel_info().interpretation } - fn set_channel_interpretation(&mut self, _: ChannelInterpretation) {} - fn set_channel_count(&mut self, _: u8) {} - fn set_channel_mode(&mut self, _: ChannelCountMode) {} + fn set_channel_interpretation(&mut self, i: ChannelInterpretation) { + self.channel_info_mut().interpretation = i + } + fn set_channel_count(&mut self, c: u8) { + self.channel_info_mut().count = c; + } + fn set_channel_count_mode(&mut self, m: ChannelCountMode) { + self.channel_info_mut().mode = m; + } /// If we're the destination node, extract the contained data fn destination_data(&mut self) -> Option { diff --git a/servo-media/src/audio/oscillator_node.rs b/servo-media/src/audio/oscillator_node.rs index 18893ac2..99a5f8f8 100644 --- a/servo-media/src/audio/oscillator_node.rs +++ b/servo-media/src/audio/oscillator_node.rs @@ -1,5 +1,6 @@ +use audio::node::ChannelInfo; use audio::block::{Chunk, Tick}; -use audio::node::{AudioNodeEngine, AudioScheduledSourceNodeMessage, BlockInfo, ChannelCountMode}; +use audio::node::{AudioNodeEngine, AudioScheduledSourceNodeMessage, BlockInfo}; use audio::param::{Param, UserAutomationEvent}; use num_traits::cast::NumCast; @@ -42,6 +43,7 @@ impl Default for OscillatorNodeOptions { #[derive(AudioScheduledSourceNode, AudioNodeCommon)] pub struct OscillatorNode { + channel_info: ChannelInfo, frequency: Param, phase: f64, /// Time at which the source should start playing. @@ -54,6 +56,7 @@ pub struct OscillatorNode { impl OscillatorNode { pub fn new(options: OscillatorNodeOptions) -> Self { Self { + channel_info: Default::default(), frequency: Param::new(options.freq.into()), phase: 0., start_at: None, @@ -145,10 +148,6 @@ impl AudioNodeEngine for OscillatorNode { 0 } - fn channel_count_mode(&self) -> ChannelCountMode { - ChannelCountMode::Max - } - make_message_handler!(AudioScheduledSourceNode: handle_source_node_message, OscillatorNode: handle_message); } From fce248a10f7cc8675fd1e47c33b3ef1f55ed1921 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Wed, 27 Jun 2018 14:09:06 -0700 Subject: [PATCH 3/6] Use channel setting in audio sink --- .../src/backends/gstreamer/audio_sink.rs | 35 +++++++++++++++---- 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/servo-media/src/backends/gstreamer/audio_sink.rs b/servo-media/src/backends/gstreamer/audio_sink.rs index 31b2bbb8..f0d88673 100644 --- a/servo-media/src/backends/gstreamer/audio_sink.rs +++ b/servo-media/src/backends/gstreamer/audio_sink.rs @@ -42,6 +42,30 @@ impl GStreamerAudioSink { } } +impl GStreamerAudioSink { + fn set_audio_info(&self, sample_rate: f32, channels: u8) -> Result<(), ()> { + let audio_info = + gst_audio::AudioInfo::new(gst_audio::AUDIO_FORMAT_F32, sample_rate as u32, channels.into()) + .build() + .ok_or(())?; + self.appsrc.set_caps(&audio_info.to_caps().unwrap()); + *self.audio_info.borrow_mut() = Some(audio_info); + Ok(()) + } + + fn set_channels_if_changed(&self, channels: u8) -> Result<(), ()> { + let curr_channels = if let Some(ch) = self.audio_info.borrow().as_ref() { + ch.channels() + } else { + return Ok(()) + }; + if channels != curr_channels as u8 { + self.set_audio_info(self.sample_rate.get(), channels)? + } + Ok(()) + } +} + impl AudioSink for GStreamerAudioSink { fn init( &self, @@ -49,12 +73,7 @@ impl AudioSink for GStreamerAudioSink { graph_thread_channel: Sender, ) -> Result<(), ()> { self.sample_rate.set(sample_rate); - let audio_info = - gst_audio::AudioInfo::new(gst_audio::AUDIO_FORMAT_F32, sample_rate as u32, 2) - .build() - .ok_or(())?; - self.appsrc.set_caps(&audio_info.to_caps().unwrap()); - *self.audio_info.borrow_mut() = Some(audio_info); + self.set_audio_info(sample_rate, 2)?; self.appsrc.set_property_format(gst::Format::Time); let appsrc = self.appsrc.clone(); @@ -95,6 +114,10 @@ impl AudioSink for GStreamerAudioSink { } fn push_data(&self, mut chunk: Chunk) -> Result<(), ()> { + if let Some(block) = chunk.blocks.get(0) { + self.set_channels_if_changed(block.chan_count())?; + } + let sample_rate = self.sample_rate.get() as u64; let audio_info = self.audio_info.borrow(); let audio_info = audio_info.as_ref().unwrap(); From 4927042c8d1d8053d86f52f667807182067c2df6 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Wed, 27 Jun 2018 14:09:19 -0700 Subject: [PATCH 4/6] Make example dynamically change channels of destination --- examples/channels.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/examples/channels.rs b/examples/channels.rs index 3b96622c..f285659e 100644 --- a/examples/channels.rs +++ b/examples/channels.rs @@ -11,10 +11,10 @@ fn run_example(servo_media: Arc) { let context = servo_media.create_audio_context(Default::default()); let mut options = Default::default(); let osc = context.create_node(AudioNodeType::OscillatorNode(options)); - options.freq = 400.; + options.freq = 213.; let osc2 = context.create_node(AudioNodeType::OscillatorNode(options)); let mut options = GainNodeOptions::default(); - options.gain = 0.5; + options.gain = 0.7; let gain = context.create_node(AudioNodeType::GainNode(options)); let options = ChannelNodeOptions { channels: 2 }; let merger = context.create_node(AudioNodeType::ChannelMergerNode(options)); @@ -34,6 +34,8 @@ fn run_example(servo_media: Arc) { ); let _ = context.resume(); + thread::sleep(time::Duration::from_millis(5000)); + context.message_node(dest, AudioNodeMessage::SetChannelCount(1)); thread::sleep(time::Duration::from_millis(5000)); let _ = context.close(); From 8baec2904674c6ea1a64f102e433825d4fdd101b Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Wed, 27 Jun 2018 14:09:23 -0700 Subject: [PATCH 5/6] Fix downmixing code --- servo-media/src/audio/block.rs | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/servo-media/src/audio/block.rs b/servo-media/src/audio/block.rs index cc71040e..1de3873c 100644 --- a/servo-media/src/audio/block.rs +++ b/servo-media/src/audio/block.rs @@ -151,7 +151,11 @@ impl Block { } pub fn data_chan_frame(&self, frame: usize, chan: u8) -> f32 { - self.data_chan(chan)[frame] + if self.is_silence() { + 0. + } else { + self.data_chan(chan)[frame] + } } pub fn push_chan(&mut self, data: &[f32]) { @@ -261,7 +265,8 @@ impl Block { let mut v = Vec::with_capacity(FRAMES_PER_BLOCK_USIZE); for frame in 0..FRAMES_PER_BLOCK_USIZE { // output = 0.5 * (input.L + input.R); - v[frame] = 0.5 * (self.data_chan_frame(frame, 0) + self.data_chan_frame(frame, 1)); + let o = 0.5 * (self.data_chan_frame(frame, 0) + self.data_chan_frame(frame, 1)); + v.push(o); } self.buffer = v; self.channels = 1; @@ -271,10 +276,11 @@ impl Block { let mut v = Vec::with_capacity(FRAMES_PER_BLOCK_USIZE); for frame in 0..FRAMES_PER_BLOCK_USIZE { // output = 0.5 * (input.L + input.R + input.SL + input.SR); - v[frame] = 0.25 * (self.data_chan_frame(frame, 0) + - self.data_chan_frame(frame, 1) + - self.data_chan_frame(frame, 2) + - self.data_chan_frame(frame, 3)); + let o = 0.25 * (self.data_chan_frame(frame, 0) + + self.data_chan_frame(frame, 1) + + self.data_chan_frame(frame, 2) + + self.data_chan_frame(frame, 3)); + v.push(o); } self.buffer = v; self.channels = 1; @@ -284,7 +290,7 @@ impl Block { let mut v = Vec::with_capacity(FRAMES_PER_BLOCK_USIZE); for frame in 0..FRAMES_PER_BLOCK_USIZE { // output = sqrt(0.5) * (input.L + input.R) + input.C + 0.5 * (input.SL + input.SR) - v[frame] = + let o = // sqrt(0.5) * (input.L + input.R) SQRT_2 * (self.data_chan_frame(frame, 0) + self.data_chan_frame(frame, 1)) + @@ -295,6 +301,7 @@ impl Block { // 0.5 * (input.SL + input.SR) 0.5 * (self.data_chan_frame(frame, 4) + self.data_chan_frame(frame, 5)); + v.push(o); } self.buffer = v; self.channels = 1; @@ -304,6 +311,7 @@ impl Block { // stereo (4, 2) => { let mut v = Vec::with_capacity(2 * FRAMES_PER_BLOCK_USIZE); + v.resize(2 * FRAMES_PER_BLOCK_USIZE, 0.); for frame in 0..FRAMES_PER_BLOCK_USIZE { // output.L = 0.5 * (input.L + input.SL) v[frame] = @@ -318,6 +326,7 @@ impl Block { } (6, 2) => { let mut v = Vec::with_capacity(2 * FRAMES_PER_BLOCK_USIZE); + v.resize(2 * FRAMES_PER_BLOCK_USIZE, 0.); for frame in 0..FRAMES_PER_BLOCK_USIZE { // output.L = L + sqrt(0.5) * (input.C + input.SL) v[frame] = @@ -336,6 +345,7 @@ impl Block { // quad (6, 4) => { let mut v = Vec::with_capacity(6 * FRAMES_PER_BLOCK_USIZE); + v.resize(6 * FRAMES_PER_BLOCK_USIZE, 0.); for frame in 0..FRAMES_PER_BLOCK_USIZE { // output.L = L + sqrt(0.5) * input.C v[frame] = From ee53441c0cbe8e9d233b9580242cfedb3c3a3651 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Wed, 27 Jun 2018 14:50:40 -0700 Subject: [PATCH 6/6] Add debug impls --- examples/channels.rs | 4 ++-- servo-media/src/audio/buffer_source_node.rs | 3 +++ servo-media/src/audio/channel_node.rs | 1 + servo-media/src/audio/gain_node.rs | 2 ++ servo-media/src/audio/graph.rs | 8 ++++---- servo-media/src/audio/node.rs | 7 +++++-- servo-media/src/audio/oscillator_node.rs | 7 ++++--- servo-media/src/audio/render_thread.rs | 1 + servo-media/src/backends/gstreamer/audio_sink.rs | 2 +- 9 files changed, 23 insertions(+), 12 deletions(-) diff --git a/examples/channels.rs b/examples/channels.rs index f285659e..2a051e2a 100644 --- a/examples/channels.rs +++ b/examples/channels.rs @@ -34,9 +34,9 @@ fn run_example(servo_media: Arc) { ); let _ = context.resume(); - thread::sleep(time::Duration::from_millis(5000)); + thread::sleep(time::Duration::from_millis(2000)); context.message_node(dest, AudioNodeMessage::SetChannelCount(1)); - thread::sleep(time::Duration::from_millis(5000)); + thread::sleep(time::Duration::from_millis(2000)); let _ = context.close(); } diff --git a/servo-media/src/audio/buffer_source_node.rs b/servo-media/src/audio/buffer_source_node.rs index c04645e7..0bf54efe 100644 --- a/servo-media/src/audio/buffer_source_node.rs +++ b/servo-media/src/audio/buffer_source_node.rs @@ -4,6 +4,7 @@ use audio::node::{AudioNodeEngine, AudioScheduledSourceNodeMessage, BlockInfo}; use audio::param::Param; /// Control messages directed to AudioBufferSourceNodes. +#[derive(Debug, Clone)] pub enum AudioBufferSourceNodeMessage { /// Set the data block holding the audio sample data to be played. // XXX handle channels @@ -11,6 +12,7 @@ pub enum AudioBufferSourceNodeMessage { } /// This specifies options for constructing an AudioBufferSourceNode. +#[derive(Debug, Clone)] pub struct AudioBufferSourceNodeOptions { /// The audio asset to be played. pub buffer: Option, @@ -169,6 +171,7 @@ impl AudioNodeEngine for AudioBufferSourceNode { AudioScheduledSourceNode: handle_source_node_message); } +#[derive(Debug, Clone)] pub struct AudioBuffer { /// Invariant: all buffers must be of the same length pub buffers: Vec> diff --git a/servo-media/src/audio/channel_node.rs b/servo-media/src/audio/channel_node.rs index 390bc7fc..53a75eda 100644 --- a/servo-media/src/audio/channel_node.rs +++ b/servo-media/src/audio/channel_node.rs @@ -3,6 +3,7 @@ use audio::node::{AudioNodeEngine, ChannelCountMode, ChannelInfo, ChannelInterpr use audio::block::{Block, Chunk}; use audio::node::BlockInfo; +#[derive(Copy, Clone, Debug)] pub struct ChannelNodeOptions { pub channels: u8, } diff --git a/servo-media/src/audio/gain_node.rs b/servo-media/src/audio/gain_node.rs index 468187dc..595933ef 100644 --- a/servo-media/src/audio/gain_node.rs +++ b/servo-media/src/audio/gain_node.rs @@ -5,10 +5,12 @@ use audio::node::AudioNodeEngine; use audio::node::BlockInfo; use audio::param::{Param, UserAutomationEvent}; +#[derive(Debug, Clone)] pub enum GainNodeMessage { SetGain(UserAutomationEvent), } +#[derive(Copy, Clone, Debug)] pub struct GainNodeOptions { pub gain: f32, } diff --git a/servo-media/src/audio/graph.rs b/servo-media/src/audio/graph.rs index f84c411b..71c9580c 100644 --- a/servo-media/src/audio/graph.rs +++ b/servo-media/src/audio/graph.rs @@ -32,7 +32,7 @@ impl NodeId { /// /// Kind is a zero sized type and is useful for distinguishing /// between input and output ports (which may otherwise share indices) -#[derive(Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Hash)] +#[derive(Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Hash, Debug)] pub struct PortIndex(pub u32, pub Kind); impl PortId { @@ -42,14 +42,14 @@ impl PortId { } /// An identifier for a port. -#[derive(Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Hash)] +#[derive(Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Hash, Debug)] pub struct PortId(NodeId, PortIndex); -#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] +#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug)] /// Marker type for denoting that the port is an input port /// of the node it is connected to pub struct InputPort; -#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] +#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug)] /// Marker type for denoting that the port is an output port /// of the node it is connected to pub struct OutputPort; diff --git a/servo-media/src/audio/node.rs b/servo-media/src/audio/node.rs index f92e6ea0..dadddc97 100644 --- a/servo-media/src/audio/node.rs +++ b/servo-media/src/audio/node.rs @@ -5,6 +5,7 @@ use audio::gain_node::{GainNodeMessage, GainNodeOptions}; use audio::oscillator_node::{OscillatorNodeMessage, OscillatorNodeOptions}; /// Type of AudioNodeEngine. +#[derive(Debug, Clone)] pub enum AudioNodeType { AnalyserNode, BiquadFilterNode, @@ -27,7 +28,7 @@ pub enum AudioNodeType { WaveShaperNode, } -#[derive(Copy, Clone, PartialEq, Eq)] +#[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum ChannelCountMode { Max, ClampedMax, @@ -35,7 +36,7 @@ pub enum ChannelCountMode { } -#[derive(Copy, Clone, PartialEq, Eq)] +#[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum ChannelInterpretation { Discrete, Speakers @@ -132,6 +133,7 @@ pub trait AudioNodeEngine: Send + AudioNodeCommon { } } +#[derive(Clone, Debug)] pub enum AudioNodeMessage { AudioBufferSourceNode(AudioBufferSourceNodeMessage), AudioScheduledSourceNode(AudioScheduledSourceNodeMessage), @@ -155,6 +157,7 @@ pub trait AudioScheduledSourceNode { } /// Type of message directed to AudioScheduledSourceNodes. +#[derive(Debug, Clone)] pub enum AudioScheduledSourceNodeMessage { /// Schedules a sound to playback at an exact time. Start(f64), diff --git a/servo-media/src/audio/oscillator_node.rs b/servo-media/src/audio/oscillator_node.rs index 99a5f8f8..e028b800 100644 --- a/servo-media/src/audio/oscillator_node.rs +++ b/servo-media/src/audio/oscillator_node.rs @@ -4,16 +4,17 @@ use audio::node::{AudioNodeEngine, AudioScheduledSourceNodeMessage, BlockInfo}; use audio::param::{Param, UserAutomationEvent}; use num_traits::cast::NumCast; +#[derive(Copy, Clone, Debug)] pub enum OscillatorNodeMessage { SetFrequency(UserAutomationEvent), } -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct PeriodicWaveOptions { // XXX https://webaudio.github.io/web-audio-api/#dictdef-periodicwaveoptions } -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub enum OscillatorType { Sine, Square, @@ -22,7 +23,7 @@ pub enum OscillatorType { Custom, } -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct OscillatorNodeOptions { pub oscillator_type: OscillatorType, pub freq: f32, diff --git a/servo-media/src/audio/render_thread.rs b/servo-media/src/audio/render_thread.rs index 0f0637a6..9032e4a9 100644 --- a/servo-media/src/audio/render_thread.rs +++ b/servo-media/src/audio/render_thread.rs @@ -14,6 +14,7 @@ use std::sync::mpsc::{Receiver, Sender}; #[cfg(feature = "gst")] use backends::gstreamer::audio_sink::GStreamerAudioSink; +#[derive(Debug)] pub enum AudioRenderThreadMsg { CreateNode(AudioNodeType, Sender), ConnectPorts(PortId, PortId), diff --git a/servo-media/src/backends/gstreamer/audio_sink.rs b/servo-media/src/backends/gstreamer/audio_sink.rs index f0d88673..647bb919 100644 --- a/servo-media/src/backends/gstreamer/audio_sink.rs +++ b/servo-media/src/backends/gstreamer/audio_sink.rs @@ -60,7 +60,7 @@ impl GStreamerAudioSink { return Ok(()) }; if channels != curr_channels as u8 { - self.set_audio_info(self.sample_rate.get(), channels)? + self.set_audio_info(self.sample_rate.get(), channels)?; } Ok(()) }