Skip to content

Commit

Permalink
Merge pull request #512 from orottier/feature/fix-panic-in-worklet-no…
Browse files Browse the repository at this point in the history
…-outputs

Fix a panic in AudioWorklet rendering with zero outputs
  • Loading branch information
orottier authored Jun 3, 2024
2 parents ab55a77 + 2a1461e commit 98bc532
Showing 1 changed file with 50 additions and 8 deletions.
58 changes: 50 additions & 8 deletions src/worklet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,7 @@ impl<P: AudioWorkletProcessor> AudioProcessor for AudioWorkletRenderer<P> {
}

// Set the proper channel count for the outputs
if self.output_channel_count.is_empty() {
if !outputs.is_empty() && self.output_channel_count.is_empty() {
// special case - single input/output - inherit channel count from input
outputs[0].set_number_of_channels(inputs[0].number_of_channels());
} else {
Expand Down Expand Up @@ -404,13 +404,15 @@ impl<P: AudioWorkletProcessor> AudioProcessor for AudioWorkletRenderer<P> {
.map(|output_channel| unsafe { std::mem::transmute(output_channel) })
.for_each(|c| self.outputs_flat.push(c));

let mut outputs_flat = &mut self.outputs_flat[..];
for c in output_channel_count {
let (left, right) = outputs_flat.split_at_mut(*c);
// SAFETY - see comments above
let left_static = unsafe { std::mem::transmute(left) };
self.outputs_grouped.push(left_static);
outputs_flat = right;
if !outputs.is_empty() {
let mut outputs_flat = &mut self.outputs_flat[..];
for c in output_channel_count {
let (left, right) = outputs_flat.split_at_mut(*c);
// SAFETY - see comments above
let left_static = unsafe { std::mem::transmute(left) };
self.outputs_grouped.push(left_static);
outputs_flat = right;
}
}

let param_getter = AudioParamValues {
Expand Down Expand Up @@ -447,6 +449,8 @@ mod tests {
use super::*;
use crate::context::OfflineAudioContext;
use float_eq::assert_float_eq;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;

struct TestProcessor;

Expand Down Expand Up @@ -511,6 +515,44 @@ mod tests {
);
}

#[test]
fn test_worklet_only_input() {
struct SetBoolWhenRunProcessor(Arc<AtomicBool>);

impl AudioWorkletProcessor for SetBoolWhenRunProcessor {
type ProcessorOptions = Arc<AtomicBool>;

fn constructor(opts: Self::ProcessorOptions) -> Self {
Self(opts)
}

fn process<'a, 'b>(
&mut self,
_inputs: &'b [&'a [&'a [f32]]],
_outputs: &'b mut [&'a mut [&'a mut [f32]]],
_params: AudioParamValues<'b>,
_scope: &'b AudioWorkletGlobalScope,
) -> bool {
self.0.store(true, Ordering::Relaxed);
false
}
}

let has_run = Arc::new(AtomicBool::new(false));

let mut context = OfflineAudioContext::new(1, 128, 48000.);
let options = AudioWorkletNodeOptions {
number_of_inputs: 1,
number_of_outputs: 0,
processor_options: Arc::clone(&has_run),
..AudioWorkletNodeOptions::default()
};
let _ = AudioWorkletNode::new::<SetBoolWhenRunProcessor>(&context, options);

let _ = context.start_rendering_sync();
assert!(has_run.load(Ordering::Relaxed));
}

#[test]
fn test_worklet_output_channel_count() {
let mut context = OfflineAudioContext::new(1, 128, 48000.);
Expand Down

0 comments on commit 98bc532

Please sign in to comment.