Skip to content

Commit 13dd3f8

Browse files
authored
Merge pull request #402 from orottier/bugfix/fix-panic-with-some-constructor-options
Fix panic in AudioBufferSource and Oscillator when supplying some options
2 parents 32e5a7c + 4ca55c8 commit 13dd3f8

File tree

2 files changed

+83
-35
lines changed

2 files changed

+83
-35
lines changed

src/node/audio_buffer_source.rs

Lines changed: 42 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -159,16 +159,16 @@ impl AudioScheduledSourceNode for AudioBufferSourceNode {
159159
impl AudioBufferSourceNode {
160160
/// Create a new [`AudioBufferSourceNode`] instance
161161
pub fn new<C: BaseAudioContext>(context: &C, options: AudioBufferSourceOptions) -> Self {
162-
context.register(move |registration| {
163-
let AudioBufferSourceOptions {
164-
buffer,
165-
detune,
166-
loop_,
167-
loop_start,
168-
loop_end,
169-
playback_rate,
170-
} = options;
171-
162+
let AudioBufferSourceOptions {
163+
buffer,
164+
detune,
165+
loop_,
166+
loop_start,
167+
loop_end,
168+
playback_rate,
169+
} = options;
170+
171+
let mut node = context.register(move |registration| {
172172
// these parameters can't be changed to a-rate
173173
// @see - <https://webaudio.github.io/web-audio-api/#audioparam-automation-rate-constraints>
174174
let detune_param_options = AudioParamDescriptor {
@@ -214,7 +214,7 @@ impl AudioBufferSourceNode {
214214
ended_triggered: false,
215215
};
216216

217-
let mut node = Self {
217+
let node = Self {
218218
registration,
219219
channel_config: ChannelConfig::default(),
220220
detune: d_param,
@@ -225,12 +225,15 @@ impl AudioBufferSourceNode {
225225
source_started: false,
226226
};
227227

228-
if let Some(buf) = buffer {
229-
node.set_buffer(buf);
230-
}
231-
232228
(node, Box::new(renderer))
233-
})
229+
});
230+
231+
// renderer has been sent to render thread, we can send it messages
232+
if let Some(buf) = buffer {
233+
node.set_buffer(buf);
234+
}
235+
236+
node
234237
}
235238

236239
/// Start the playback at the given time and with a given offset
@@ -789,6 +792,29 @@ mod tests {
789792

790793
use super::*;
791794

795+
#[test]
796+
fn test_construct_with_options_and_run() {
797+
let sample_rate = 44100.;
798+
let length = RENDER_QUANTUM_SIZE;
799+
let context = OfflineAudioContext::new(1, length, sample_rate);
800+
801+
let buffer = AudioBuffer::from(vec![vec![1.; RENDER_QUANTUM_SIZE]], sample_rate);
802+
let options = AudioBufferSourceOptions {
803+
buffer: Some(buffer),
804+
..Default::default()
805+
};
806+
let mut src = AudioBufferSourceNode::new(&context, options);
807+
src.connect(&context.destination());
808+
src.start();
809+
let res = context.start_rendering_sync();
810+
811+
assert_float_eq!(
812+
res.channel_data(0).as_slice()[..],
813+
&[1.; RENDER_QUANTUM_SIZE][..],
814+
abs_all <= 0.
815+
);
816+
}
817+
792818
#[test]
793819
fn test_playing_some_file() {
794820
let context = OfflineAudioContext::new(2, RENDER_QUANTUM_SIZE, 44_100.);

src/node/oscillator.rs

Lines changed: 41 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -181,18 +181,18 @@ impl OscillatorNode {
181181
/// * `context` - The `AudioContext`
182182
/// * `options` - The OscillatorOptions
183183
pub fn new<C: BaseAudioContext>(context: &C, options: OscillatorOptions) -> Self {
184-
context.register(move |registration| {
184+
let OscillatorOptions {
185+
type_,
186+
frequency,
187+
detune,
188+
channel_config,
189+
periodic_wave,
190+
} = options;
191+
192+
let mut node = context.register(move |registration| {
185193
let sample_rate = context.sample_rate();
186194
let nyquist = sample_rate / 2.;
187195

188-
let OscillatorOptions {
189-
type_,
190-
frequency,
191-
detune,
192-
channel_config,
193-
periodic_wave,
194-
} = options;
195-
196196
// frequency audio parameter
197197
let freq_param_options = AudioParamDescriptor {
198198
name: String::new(),
@@ -229,21 +229,23 @@ impl OscillatorNode {
229229
sine_table: precomputed_sine_table(),
230230
};
231231

232-
let mut node = Self {
232+
let node = Self {
233233
registration,
234234
channel_config: channel_config.into(),
235235
frequency: f_param,
236236
detune: det_param,
237237
type_,
238238
};
239239

240-
// if periodic wave has been given, init it
241-
if let Some(p_wave) = periodic_wave {
242-
node.set_periodic_wave(p_wave);
243-
}
244-
245240
(node, Box::new(renderer))
246-
})
241+
});
242+
243+
// renderer has been sent to render thread, we can send it messages
244+
if let Some(p_wave) = periodic_wave {
245+
node.set_periodic_wave(p_wave);
246+
}
247+
248+
node
247249
}
248250

249251
/// A-rate [`AudioParam`] that defines the fundamental frequency of the
@@ -579,7 +581,7 @@ mod tests {
579581

580582
let context = OfflineAudioContext::new(2, 1, 44_100.);
581583

582-
let osc = context.create_oscillator();
584+
let mut osc = context.create_oscillator();
583585

584586
let freq = osc.frequency.value();
585587
assert_float_eq!(freq, default_freq, abs_all <= 0.);
@@ -588,6 +590,11 @@ mod tests {
588590
assert_float_eq!(det, default_det, abs_all <= 0.);
589591

590592
assert_eq!(osc.type_(), default_type);
593+
594+
// should not panic when run
595+
osc.start();
596+
osc.connect(&context.destination());
597+
let _ = context.start_rendering_sync();
591598
}
592599

593600
#[test]
@@ -598,7 +605,7 @@ mod tests {
598605

599606
let context = OfflineAudioContext::new(2, 1, 44_100.);
600607

601-
let osc = OscillatorNode::new(&context, OscillatorOptions::default());
608+
let mut osc = OscillatorNode::new(&context, OscillatorOptions::default());
602609

603610
let freq = osc.frequency.value();
604611
assert_float_eq!(freq, default_freq, abs_all <= 0.);
@@ -607,6 +614,11 @@ mod tests {
607614
assert_float_eq!(det, default_det, abs_all <= 0.);
608615

609616
assert_eq!(osc.type_(), default_type);
617+
618+
// should not panic when run
619+
osc.start();
620+
osc.connect(&context.destination());
621+
let _ = context.start_rendering_sync();
610622
}
611623

612624
#[test]
@@ -630,9 +642,14 @@ mod tests {
630642
..OscillatorOptions::default()
631643
};
632644

633-
let osc = OscillatorNode::new(&context, options);
645+
let mut osc = OscillatorNode::new(&context, options);
634646

635647
assert_eq!(osc.type_(), expected_type);
648+
649+
// should not panic when run
650+
osc.start();
651+
osc.connect(&context.destination());
652+
let _ = context.start_rendering_sync();
636653
}
637654

638655
#[test]
@@ -652,6 +669,11 @@ mod tests {
652669

653670
osc.set_type(OscillatorType::Sine);
654671
assert_eq!(osc.type_(), expected_type);
672+
673+
// should not panic when run
674+
osc.start();
675+
osc.connect(&context.destination());
676+
let _ = context.start_rendering_sync();
655677
}
656678

657679
// # Test waveforms

0 commit comments

Comments
 (0)