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 } ;
8
4
9
- use crossbeam_channel:: { Receiver , Sender } ;
10
5
use rubato:: { FftFixedInOut , Resampler as _} ;
11
6
12
7
use crate :: {
@@ -17,8 +12,6 @@ use crate::{
17
12
18
13
use super :: { AudioNode , ChannelConfig , ChannelConfigOptions } ;
19
14
20
- struct CurveMessage ( Vec < f32 > ) ;
21
-
22
15
/// enumerates the oversampling rate available for `WaveShaperNode`
23
16
#[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
24
17
// the naming comes from the web audio specification
@@ -66,8 +59,8 @@ pub struct WaveShaperOptions {
66
59
impl Default for WaveShaperOptions {
67
60
fn default ( ) -> Self {
68
61
Self {
69
- curve : None ,
70
62
oversample : OverSampleType :: None ,
63
+ curve : None ,
71
64
channel_config : ChannelConfigOptions :: default ( ) ,
72
65
}
73
66
}
@@ -135,9 +128,7 @@ pub struct WaveShaperNode {
135
128
/// distortion curve
136
129
curve : OnceCell < Vec < f32 > > ,
137
130
/// oversample type
138
- oversample : Arc < AtomicU32 > ,
139
- /// Channel between node and renderer (sender part)
140
- sender : Sender < CurveMessage > ,
131
+ oversample : AtomicU32 ,
141
132
}
142
133
143
134
impl AudioNode for WaveShaperNode {
@@ -168,36 +159,31 @@ impl WaveShaperNode {
168
159
pub fn new < C : BaseAudioContext > ( context : & C , options : WaveShaperOptions ) -> Self {
169
160
context. register ( move |registration| {
170
161
let WaveShaperOptions {
171
- curve,
172
162
oversample,
163
+ curve,
173
164
channel_config,
174
165
} = options;
175
166
176
167
let sample_rate = context. sample_rate ( ) as usize ;
177
168
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 ) ;
183
169
184
170
let config = RendererConfig {
171
+ oversample,
172
+ curve : curve. clone ( ) ,
185
173
sample_rate,
186
- oversample : Arc :: clone ( & oversample) ,
187
- receiver,
188
174
} ;
189
175
190
176
let renderer = WaveShaperRenderer :: new ( config) ;
191
177
let node = Self {
192
178
registration,
193
179
channel_config,
194
180
curve : OnceCell :: new ( ) ,
195
- oversample,
196
- sender,
181
+ oversample : AtomicU32 :: new ( oversample as u32 ) ,
197
182
} ;
198
183
199
184
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) ;
201
187
}
202
188
203
189
( node, Box :: new ( renderer) )
@@ -227,15 +213,13 @@ impl WaveShaperNode {
227
213
panic ! ( "InvalidStateError - cannot assign curve twice" ) ;
228
214
}
229
215
230
- self . sender
231
- . send ( CurveMessage ( clone) )
232
- . expect ( "Sending CurveMessage failed" ) ;
216
+ self . registration . post_message ( clone) ;
233
217
}
234
218
235
219
/// Returns the `oversample` faactor of this node
236
220
#[ must_use]
237
221
pub fn oversample ( & self ) -> OverSampleType {
238
- self . oversample . load ( Ordering :: SeqCst ) . into ( )
222
+ self . oversample . load ( Ordering :: Acquire ) . into ( )
239
223
}
240
224
241
225
/// set the `oversample` factor of this node
@@ -244,19 +228,20 @@ impl WaveShaperNode {
244
228
///
245
229
/// * `oversample` - the desired `OversampleType` variant
246
230
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) ;
248
233
}
249
234
}
250
235
251
236
/// Helper struct which regroups all parameters
252
237
/// required to build `WaveShaperRenderer`
253
238
struct RendererConfig {
239
+ /// oversample factor
240
+ oversample : OverSampleType ,
241
+ /// oversample factor
242
+ curve : Option < Vec < f32 > > ,
254
243
/// Sample rate (equals to audio context sample rate)
255
244
sample_rate : usize ,
256
- /// oversample factor
257
- oversample : Arc < AtomicU32 > ,
258
- /// Channel between node and renderer (receiver part)
259
- receiver : Receiver < CurveMessage > ,
260
245
}
261
246
262
247
#[ derive( Debug , Clone , PartialEq , Eq ) ]
@@ -331,10 +316,13 @@ impl Resampler {
331
316
sample_rate_in,
332
317
sample_rate_out,
333
318
} = & config;
319
+
334
320
let processor =
335
321
FftFixedInOut :: new ( * sample_rate_in, * sample_rate_out, * chunk_size_in, * channels)
336
322
. unwrap ( ) ;
323
+
337
324
let samples_out = processor. output_buffer_allocate ( true ) ;
325
+
338
326
Self {
339
327
config,
340
328
processor,
@@ -375,10 +363,14 @@ impl Resampler {
375
363
376
364
/// `WaveShaperRenderer` represents the rendering part of `WaveShaperNode`
377
365
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 ,
378
372
/// Sample rate (equals to audio context sample rate)
379
373
sample_rate : usize ,
380
- /// oversample factor
381
- oversample : Arc < AtomicU32 > ,
382
374
/// Number of channels used to build the up/down sampler X2
383
375
channels_x2 : usize ,
384
376
/// Number of channels used to build the up/down sampler X4
@@ -391,10 +383,6 @@ struct WaveShaperRenderer {
391
383
downsampler_x2 : Resampler ,
392
384
// down sampler configured to divide by 4 the upsampled signal
393
385
downsampler_x4 : Resampler ,
394
- /// distortion curve
395
- curve : Option < Vec < f32 > > ,
396
- /// Channel between node and renderer (receiver part)
397
- receiver : Receiver < CurveMessage > ,
398
386
}
399
387
400
388
impl AudioProcessor for WaveShaperRenderer {
@@ -414,15 +402,12 @@ impl AudioProcessor for WaveShaperRenderer {
414
402
return false ;
415
403
}
416
404
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
-
422
405
* output = input. clone ( ) ;
423
406
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 {
426
411
OverSampleType :: None => {
427
412
output. modify_channels ( |channel| {
428
413
channel. iter_mut ( ) . for_each ( |o| * o = apply_curve ( curve, * o) ) ;
@@ -507,6 +492,22 @@ impl AudioProcessor for WaveShaperRenderer {
507
492
// @tbc - rubato::FftFixedInOut doesn't seem to introduce any latency
508
493
false
509
494
}
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
+ }
510
511
}
511
512
512
513
impl WaveShaperRenderer {
@@ -516,9 +517,12 @@ impl WaveShaperRenderer {
516
517
let RendererConfig {
517
518
sample_rate,
518
519
oversample,
519
- receiver ,
520
+ curve ,
520
521
} = config;
521
522
523
+ let curve_set = curve. is_some ( ) ;
524
+ let curve = curve. unwrap_or ( Vec :: with_capacity ( 0 ) ) ;
525
+
522
526
let channels_x2 = 1 ;
523
527
let channels_x4 = 1 ;
524
528
@@ -533,16 +537,16 @@ impl WaveShaperRenderer {
533
537
Resampler :: new ( ResamplerConfig :: downsample_x4 ( channels_x2, sample_rate) ) ;
534
538
535
539
Self {
536
- sample_rate,
537
540
oversample,
541
+ curve,
542
+ curve_set,
543
+ sample_rate,
538
544
channels_x2,
539
545
channels_x4,
540
546
upsampler_x2,
541
547
upsampler_x4,
542
548
downsampler_x2,
543
549
downsampler_x4,
544
- curve : None ,
545
- receiver,
546
550
}
547
551
}
548
552
}
0 commit comments