Skip to content

Commit 87a74d3

Browse files
b-maorottier
authored andcommitted
refactor: update to message passing API
1 parent 575bded commit 87a74d3

File tree

1 file changed

+55
-51
lines changed

1 file changed

+55
-51
lines changed

src/node/waveshaper.rs

Lines changed: 55 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,7 @@
1-
use std::{
2-
cell::OnceCell,
3-
sync::{
4-
atomic::{AtomicU32, Ordering},
5-
Arc,
6-
},
7-
};
1+
use std::any::Any;
2+
use std::cell::OnceCell;
3+
use std::sync::atomic::{AtomicU32, Ordering};
84

9-
use crossbeam_channel::{Receiver, Sender};
105
use rubato::{FftFixedInOut, Resampler as _};
116

127
use crate::{
@@ -17,8 +12,6 @@ use crate::{
1712

1813
use super::{AudioNode, ChannelConfig, ChannelConfigOptions};
1914

20-
struct CurveMessage(Vec<f32>);
21-
2215
/// enumerates the oversampling rate available for `WaveShaperNode`
2316
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
2417
// the naming comes from the web audio specification
@@ -66,8 +59,8 @@ pub struct WaveShaperOptions {
6659
impl Default for WaveShaperOptions {
6760
fn default() -> Self {
6861
Self {
69-
curve: None,
7062
oversample: OverSampleType::None,
63+
curve: None,
7164
channel_config: ChannelConfigOptions::default(),
7265
}
7366
}
@@ -135,9 +128,7 @@ pub struct WaveShaperNode {
135128
/// distortion curve
136129
curve: OnceCell<Vec<f32>>,
137130
/// oversample type
138-
oversample: Arc<AtomicU32>,
139-
/// Channel between node and renderer (sender part)
140-
sender: Sender<CurveMessage>,
131+
oversample: AtomicU32,
141132
}
142133

143134
impl AudioNode for WaveShaperNode {
@@ -168,36 +159,31 @@ impl WaveShaperNode {
168159
pub fn new<C: BaseAudioContext>(context: &C, options: WaveShaperOptions) -> Self {
169160
context.register(move |registration| {
170161
let WaveShaperOptions {
171-
curve,
172162
oversample,
163+
curve,
173164
channel_config,
174165
} = options;
175166

176167
let sample_rate = context.sample_rate() as usize;
177168
let channel_config = channel_config.into();
178-
let oversample = Arc::new(AtomicU32::new(oversample as u32));
179-
180-
// Channel to send the `curve` to the renderer
181-
// A capacity of 1 suffices since it is not allowed to set the value multiple times
182-
let (sender, receiver) = crossbeam_channel::bounded(1);
183169

184170
let config = RendererConfig {
171+
oversample,
172+
curve: curve.clone(),
185173
sample_rate,
186-
oversample: Arc::clone(&oversample),
187-
receiver,
188174
};
189175

190176
let renderer = WaveShaperRenderer::new(config);
191177
let node = Self {
192178
registration,
193179
channel_config,
194180
curve: OnceCell::new(),
195-
oversample,
196-
sender,
181+
oversample: AtomicU32::new(oversample as u32),
197182
};
198183

199184
if let Some(c) = curve {
200-
node.set_curve(c);
185+
// we are sure the OnceCell is empty, cannot fail
186+
let _ = node.curve.set(c);
201187
}
202188

203189
(node, Box::new(renderer))
@@ -227,15 +213,13 @@ impl WaveShaperNode {
227213
panic!("InvalidStateError - cannot assign curve twice");
228214
}
229215

230-
self.sender
231-
.send(CurveMessage(clone))
232-
.expect("Sending CurveMessage failed");
216+
self.registration.post_message(clone);
233217
}
234218

235219
/// Returns the `oversample` faactor of this node
236220
#[must_use]
237221
pub fn oversample(&self) -> OverSampleType {
238-
self.oversample.load(Ordering::SeqCst).into()
222+
self.oversample.load(Ordering::Acquire).into()
239223
}
240224

241225
/// set the `oversample` factor of this node
@@ -244,19 +228,20 @@ impl WaveShaperNode {
244228
///
245229
/// * `oversample` - the desired `OversampleType` variant
246230
pub fn set_oversample(&self, oversample: OverSampleType) {
247-
self.oversample.store(oversample as u32, Ordering::SeqCst);
231+
self.oversample.store(oversample as u32, Ordering::Release);
232+
self.registration.post_message(oversample);
248233
}
249234
}
250235

251236
/// Helper struct which regroups all parameters
252237
/// required to build `WaveShaperRenderer`
253238
struct RendererConfig {
239+
/// oversample factor
240+
oversample: OverSampleType,
241+
/// oversample factor
242+
curve: Option<Vec<f32>>,
254243
/// Sample rate (equals to audio context sample rate)
255244
sample_rate: usize,
256-
/// oversample factor
257-
oversample: Arc<AtomicU32>,
258-
/// Channel between node and renderer (receiver part)
259-
receiver: Receiver<CurveMessage>,
260245
}
261246

262247
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -331,10 +316,13 @@ impl Resampler {
331316
sample_rate_in,
332317
sample_rate_out,
333318
} = &config;
319+
334320
let processor =
335321
FftFixedInOut::new(*sample_rate_in, *sample_rate_out, *chunk_size_in, *channels)
336322
.unwrap();
323+
337324
let samples_out = processor.output_buffer_allocate(true);
325+
338326
Self {
339327
config,
340328
processor,
@@ -375,10 +363,14 @@ impl Resampler {
375363

376364
/// `WaveShaperRenderer` represents the rendering part of `WaveShaperNode`
377365
struct WaveShaperRenderer {
366+
/// oversample factor
367+
oversample: OverSampleType,
368+
/// distortion curve
369+
curve: Vec<f32>,
370+
/// whether the distortion curve has been set
371+
curve_set: bool,
378372
/// Sample rate (equals to audio context sample rate)
379373
sample_rate: usize,
380-
/// oversample factor
381-
oversample: Arc<AtomicU32>,
382374
/// Number of channels used to build the up/down sampler X2
383375
channels_x2: usize,
384376
/// Number of channels used to build the up/down sampler X4
@@ -391,10 +383,6 @@ struct WaveShaperRenderer {
391383
downsampler_x2: Resampler,
392384
// down sampler configured to divide by 4 the upsampled signal
393385
downsampler_x4: Resampler,
394-
/// distortion curve
395-
curve: Option<Vec<f32>>,
396-
/// Channel between node and renderer (receiver part)
397-
receiver: Receiver<CurveMessage>,
398386
}
399387

400388
impl AudioProcessor for WaveShaperRenderer {
@@ -414,15 +402,12 @@ impl AudioProcessor for WaveShaperRenderer {
414402
return false;
415403
}
416404

417-
// Check if a curve have been set at k-rate
418-
if let Ok(msg) = self.receiver.try_recv() {
419-
self.curve = Some(msg.0);
420-
}
421-
422405
*output = input.clone();
423406

424-
if let Some(curve) = &self.curve {
425-
match self.oversample.load(Ordering::SeqCst).into() {
407+
if self.curve_set {
408+
let curve = &self.curve;
409+
410+
match self.oversample {
426411
OverSampleType::None => {
427412
output.modify_channels(|channel| {
428413
channel.iter_mut().for_each(|o| *o = apply_curve(curve, *o));
@@ -507,6 +492,22 @@ impl AudioProcessor for WaveShaperRenderer {
507492
// @tbc - rubato::FftFixedInOut doesn't seem to introduce any latency
508493
false
509494
}
495+
496+
fn onmessage(&mut self, msg: &mut dyn Any) {
497+
if let Some(&oversample) = msg.downcast_ref::<OverSampleType>() {
498+
self.oversample = oversample;
499+
return;
500+
}
501+
502+
if let Some(curve) = msg.downcast_mut::<Vec<f32>>() {
503+
std::mem::swap(&mut self.curve, curve);
504+
self.curve_set = true;
505+
506+
return;
507+
}
508+
509+
log::warn!("WaveShaperRenderer: Dropping incoming message {msg:?}");
510+
}
510511
}
511512

512513
impl WaveShaperRenderer {
@@ -516,9 +517,12 @@ impl WaveShaperRenderer {
516517
let RendererConfig {
517518
sample_rate,
518519
oversample,
519-
receiver,
520+
curve,
520521
} = config;
521522

523+
let curve_set = curve.is_some();
524+
let curve = curve.unwrap_or(Vec::with_capacity(0));
525+
522526
let channels_x2 = 1;
523527
let channels_x4 = 1;
524528

@@ -533,16 +537,16 @@ impl WaveShaperRenderer {
533537
Resampler::new(ResamplerConfig::downsample_x4(channels_x2, sample_rate));
534538

535539
Self {
536-
sample_rate,
537540
oversample,
541+
curve,
542+
curve_set,
543+
sample_rate,
538544
channels_x2,
539545
channels_x4,
540546
upsampler_x2,
541547
upsampler_x4,
542548
downsampler_x2,
543549
downsampler_x4,
544-
curve: None,
545-
receiver,
546550
}
547551
}
548552
}

0 commit comments

Comments
 (0)