Skip to content

Commit 37c75a3

Browse files
committed
Change ScriptProcessorNode::onaudioprocess API - use owned buffer value
This is easier for the node bindings. We hook into the Drop call of the event to ship the output buffer to the render thread. TODO: I found a gnarly bug where the ScriptProcessorRenderer would be cleared from the audio graph erroneously. AudioContextRegistration should not be allowed to implement Clone because it has a very meaningful Drop implementation. That's why I now resort to an `Arc` hack to prevent the Drop method to run.
1 parent 13a1bdd commit 37c75a3

File tree

4 files changed

+18
-6
lines changed

4 files changed

+18
-6
lines changed

examples/script_processor.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ fn main() {
2828
});
2929

3030
let node = context.create_script_processor(512, 1, 1);
31-
node.set_onaudioprocess(|e| {
31+
node.set_onaudioprocess(|mut e| {
3232
let mut rng = rand::thread_rng();
3333
e.output_buffer
3434
.get_channel_data_mut(0)

src/events.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,15 @@ pub struct AudioProcessingEvent {
5252
/// The time when the audio will be played in the same time coordinate system as the
5353
/// AudioContext's currentTime.
5454
pub playback_time: f64,
55+
pub(crate) registration: Option<Arc<crate::context::AudioContextRegistration>>,
56+
}
57+
58+
impl Drop for AudioProcessingEvent {
59+
fn drop(&mut self) {
60+
if let Some(registration) = self.registration.take() {
61+
registration.post_message(self.output_buffer.clone());
62+
}
63+
}
5564
}
5665

5766
/// The OfflineAudioCompletionEvent Event interface

src/node/script_processor.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use crate::render::{
77
use crate::{AudioBuffer, RENDER_QUANTUM_SIZE};
88

99
use std::any::Any;
10+
use std::sync::Arc;
1011

1112
/// Options for constructing an [`ScriptProcessorNode`]
1213
#[derive(Clone, Debug)]
@@ -139,18 +140,19 @@ impl ScriptProcessorNode {
139140
///
140141
/// Only a single event handler is active at any time. Calling this method multiple times will
141142
/// override the previous event handler.
142-
pub fn set_onaudioprocess<F: FnMut(&mut AudioProcessingEvent) + Send + 'static>(
143+
pub fn set_onaudioprocess<F: FnMut(AudioProcessingEvent) + Send + 'static>(
143144
&self,
144145
mut callback: F,
145146
) {
146-
let registration = self.registration.clone();
147+
// TODO, hack: use Arc to prevent drop of AudioContextRegistration
148+
let registration = Arc::new(self.registration.clone());
147149
let callback = move |v| {
148150
let mut payload = match v {
149151
EventPayload::AudioProcessing(v) => v,
150152
_ => unreachable!(),
151153
};
152-
callback(&mut payload);
153-
registration.post_message(payload.output_buffer);
154+
payload.registration = Some(Arc::clone(&registration));
155+
callback(payload);
154156
};
155157

156158
self.context().set_event_handler(
@@ -301,7 +303,7 @@ mod tests {
301303

302304
let node = context.create_script_processor(BUFFER_SIZE, 0, 1);
303305
node.connect(&context.destination());
304-
node.set_onaudioprocess(|e| {
306+
node.set_onaudioprocess(|mut e| {
305307
e.output_buffer.get_channel_data_mut(0).fill(1.); // set all samples to 1.
306308
});
307309

src/render/processor.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ impl AudioWorkletGlobalScope {
6868
input_buffer,
6969
output_buffer,
7070
playback_time,
71+
registration: None,
7172
};
7273
let dispatch = EventDispatch::audio_processing(self.node_id.get(), event);
7374
let _ = self.event_sender.try_send(dispatch);

0 commit comments

Comments
 (0)