6
6
#![ cfg_attr( feature = "cargo-clippy" , allow( clippy:: cast_lossless) ) ]
7
7
#![ cfg_attr( feature = "cargo-clippy" , allow( clippy:: cast_ptr_alignment) ) ]
8
8
9
- use alloc:: vec:: Vec ;
10
9
use core:: f64;
10
+
11
+ #[ cfg( feature = "alloc" ) ]
12
+ use alloc:: vec:: Vec ;
13
+
11
14
#[ cfg( not( feature = "std" ) ) ]
12
15
use libm:: F64Ext ;
13
16
@@ -34,19 +37,27 @@ const FIXP_MASK: i32 = 0xffff;
34
37
pub enum SamplingMethod {
35
38
Fast ,
36
39
Interpolate ,
40
+ #[ cfg( feature = "alloc" ) ]
37
41
Resample ,
42
+ #[ cfg( feature = "alloc" ) ]
38
43
ResampleFast ,
39
44
}
40
45
46
+ #[ derive( Clone ) ]
47
+ struct Fir {
48
+ data : Vec < i16 > ,
49
+ n : i32 ,
50
+ res : i32 ,
51
+ }
52
+
41
53
#[ derive( Clone ) ]
42
54
pub struct Sampler {
43
55
// Dependencies
44
56
pub synth : Synth ,
45
57
// Configuration
46
58
cycles_per_sample : u32 ,
47
- fir : Vec < i16 > ,
48
- fir_n : i32 ,
49
- fir_res : i32 ,
59
+ #[ cfg( feature = "alloc" ) ]
60
+ fir : Fir ,
50
61
sampling_method : SamplingMethod ,
51
62
#[ cfg( all( feature = "std" , any( target_arch = "x86" , target_arch = "x86_64" ) ) ) ]
52
63
use_sse42 : bool ,
@@ -64,9 +75,12 @@ impl Sampler {
64
75
Sampler {
65
76
synth,
66
77
cycles_per_sample : 0 ,
67
- fir : Vec :: new ( ) ,
68
- fir_n : 0 ,
69
- fir_res : 0 ,
78
+ #[ cfg( feature = "alloc" ) ]
79
+ fir : Fir {
80
+ data : Vec :: new ( ) ,
81
+ n : 0 ,
82
+ res : 0 ,
83
+ } ,
70
84
sampling_method : SamplingMethod :: Fast ,
71
85
#[ cfg( all( feature = "std" , any( target_arch = "x86" , target_arch = "x86_64" ) ) ) ]
72
86
use_avx2 : alloc:: is_x86_feature_detected!( "avx2" ) ,
@@ -83,6 +97,8 @@ impl Sampler {
83
97
self . cycles_per_sample =
84
98
( clock_freq as f64 / sample_freq as f64 * ( 1 << FIXP_SHIFT ) as f64 + 0.5 ) as u32 ;
85
99
self . sampling_method = method;
100
+
101
+ #[ cfg( feature = "alloc" ) ]
86
102
if self . sampling_method == SamplingMethod :: Resample
87
103
|| self . sampling_method == SamplingMethod :: ResampleFast
88
104
{
@@ -109,7 +125,9 @@ impl Sampler {
109
125
match self . sampling_method {
110
126
SamplingMethod :: Fast => self . clock_fast ( delta, buffer, interleave) ,
111
127
SamplingMethod :: Interpolate => self . clock_interpolate ( delta, buffer, interleave) ,
128
+ #[ cfg( feature = "alloc" ) ]
112
129
SamplingMethod :: Resample => self . clock_resample_interpolate ( delta, buffer, interleave) ,
130
+ #[ cfg( feature = "alloc" ) ]
113
131
SamplingMethod :: ResampleFast => self . clock_resample_fast ( delta, buffer, interleave) ,
114
132
}
115
133
}
@@ -215,6 +233,7 @@ impl Sampler {
215
233
///
216
234
/// NB! the result of right shifting negative numbers is really
217
235
/// implementation dependent in the C++ standard.
236
+ #[ cfg( feature = "alloc" ) ]
218
237
#[ inline]
219
238
fn clock_resample_interpolate (
220
239
& mut self ,
@@ -242,34 +261,34 @@ impl Sampler {
242
261
delta -= delta_sample;
243
262
self . update_sample_offset2 ( next_sample_offset) ;
244
263
245
- let fir_offset_1 = ( self . offset * self . fir_res ) >> FIXP_SHIFT ;
246
- let fir_offset_rmd = ( self . offset * self . fir_res ) & FIXP_MASK ;
247
- let fir_start_1 = ( fir_offset_1 * self . fir_n ) as usize ;
248
- let fir_end_1 = fir_start_1 + self . fir_n as usize ;
249
- let sample_start_1 = ( self . index as i32 - self . fir_n + RING_SIZE as i32 ) as usize ;
250
- let sample_end_1 = sample_start_1 + self . fir_n as usize ;
264
+ let fir_offset_1 = ( self . offset * self . fir . res ) >> FIXP_SHIFT ;
265
+ let fir_offset_rmd = ( self . offset * self . fir . res ) & FIXP_MASK ;
266
+ let fir_start_1 = ( fir_offset_1 * self . fir . n ) as usize ;
267
+ let fir_end_1 = fir_start_1 + self . fir . n as usize ;
268
+ let sample_start_1 = ( self . index as i32 - self . fir . n + RING_SIZE as i32 ) as usize ;
269
+ let sample_end_1 = sample_start_1 + self . fir . n as usize ;
251
270
252
271
// Convolution with filter impulse response.
253
272
let v1 = self . compute_convolution_fir (
254
273
& self . buffer [ sample_start_1..sample_end_1] ,
255
- & self . fir [ fir_start_1..fir_end_1] ,
274
+ & self . fir . data [ fir_start_1..fir_end_1] ,
256
275
) ;
257
276
258
277
// Use next FIR table, wrap around to first FIR table using
259
278
// previous sample.
260
279
let mut fir_offset_2 = fir_offset_1 + 1 ;
261
280
let mut sample_start_2 = sample_start_1;
262
- if fir_offset_2 == self . fir_res {
281
+ if fir_offset_2 == self . fir . res {
263
282
fir_offset_2 = 0 ;
264
283
sample_start_2 -= 1 ;
265
284
}
266
- let fir_start_2 = ( fir_offset_2 * self . fir_n ) as usize ;
267
- let fir_end_2 = fir_start_2 + self . fir_n as usize ;
268
- let sample_end_2 = sample_start_2 + self . fir_n as usize ;
285
+ let fir_start_2 = ( fir_offset_2 * self . fir . n ) as usize ;
286
+ let fir_end_2 = fir_start_2 + self . fir . n as usize ;
287
+ let sample_end_2 = sample_start_2 + self . fir . n as usize ;
269
288
270
289
let v2 = self . compute_convolution_fir (
271
290
& self . buffer [ sample_start_2..sample_end_2] ,
272
- & self . fir [ fir_start_2..fir_end_2] ,
291
+ & self . fir . data [ fir_start_2..fir_end_2] ,
273
292
) ;
274
293
275
294
// Linear interpolation.
@@ -305,6 +324,7 @@ impl Sampler {
305
324
}
306
325
307
326
/// SID clocking with audio sampling - cycle based with audio resampling.
327
+ #[ cfg( feature = "alloc" ) ]
308
328
#[ inline]
309
329
fn clock_resample_fast (
310
330
& mut self ,
@@ -332,16 +352,16 @@ impl Sampler {
332
352
delta -= delta_sample;
333
353
self . update_sample_offset2 ( next_sample_offset) ;
334
354
335
- let fir_offset = ( self . offset * self . fir_res ) >> FIXP_SHIFT ;
336
- let fir_start = ( fir_offset * self . fir_n ) as usize ;
337
- let fir_end = fir_start + self . fir_n as usize ;
338
- let sample_start = ( self . index as i32 - self . fir_n + RING_SIZE as i32 ) as usize ;
339
- let sample_end = sample_start + self . fir_n as usize ;
355
+ let fir_offset = ( self . offset * self . fir . res ) >> FIXP_SHIFT ;
356
+ let fir_start = ( fir_offset * self . fir . n ) as usize ;
357
+ let fir_end = fir_start + self . fir . n as usize ;
358
+ let sample_start = ( self . index as i32 - self . fir . n + RING_SIZE as i32 ) as usize ;
359
+ let sample_end = sample_start + self . fir . n as usize ;
340
360
341
361
// Convolution with filter impulse response.
342
362
let mut v = self . compute_convolution_fir (
343
363
& self . buffer [ sample_start..sample_end] ,
344
- & self . fir [ fir_start..fir_end] ,
364
+ & self . fir . data [ fir_start..fir_end] ,
345
365
) ;
346
366
v >>= FIR_SHIFT ;
347
367
@@ -515,6 +535,7 @@ impl Sampler {
515
535
self . offset = next_sample_offset & FIXP_MASK ;
516
536
}
517
537
538
+ #[ cfg( feature = "alloc" ) ]
518
539
fn init_fir (
519
540
& mut self ,
520
541
clock_freq : f64 ,
@@ -557,8 +578,8 @@ impl Sampler {
557
578
558
579
// The filter length is equal to the filter order + 1.
559
580
// The filter length must be an odd number (sinc is symmetric about x = 0).
560
- self . fir_n = ( n_cap as f64 * cycles_per_sample) as i32 + 1 ;
561
- self . fir_n |= 1 ;
581
+ self . fir . n = ( n_cap as f64 * cycles_per_sample) as i32 + 1 ;
582
+ self . fir . n |= 1 ;
562
583
563
584
// We clamp the filter table resolution to 2^n, making the fixpoint
564
585
// sample_offset a whole multiple of the filter table resolution.
@@ -568,18 +589,20 @@ impl Sampler {
568
589
FIR_RES_FAST
569
590
} ;
570
591
let n = ( ( res as f64 / cycles_per_sample) . ln ( ) / ( 2.0f64 ) . ln ( ) ) . ceil ( ) as i32 ;
571
- self . fir_res = 1 << n;
592
+ self . fir . res = 1 << n;
572
593
573
- self . fir . clear ( ) ;
574
- self . fir . resize ( ( self . fir_n * self . fir_res ) as usize , 0 ) ;
594
+ self . fir . data . clear ( ) ;
595
+ self . fir
596
+ . data
597
+ . resize ( ( self . fir . n * self . fir . res ) as usize , 0 ) ;
575
598
576
599
// Calculate fir_RES FIR tables for linear interpolation.
577
- for i in 0 ..self . fir_res {
578
- let fir_offset = i * self . fir_n + self . fir_n / 2 ;
579
- let j_offset = i as f64 / self . fir_res as f64 ;
600
+ for i in 0 ..self . fir . res {
601
+ let fir_offset = i * self . fir . n + self . fir . n / 2 ;
602
+ let j_offset = i as f64 / self . fir . res as f64 ;
580
603
// Calculate FIR table. This is the sinc function, weighted by the
581
604
// Kaiser window.
582
- let fir_n_div2 = self . fir_n / 2 ;
605
+ let fir_n_div2 = self . fir . n / 2 ;
583
606
for j in -fir_n_div2..=fir_n_div2 {
584
607
let jx = j as f64 - j_offset;
585
608
let wt = wc * jx / cycles_per_sample;
@@ -593,7 +616,7 @@ impl Sampler {
593
616
let val = ( 1i32 << FIR_SHIFT ) as f64 * filter_scale * samples_per_cycle * wc / pi
594
617
* sincwt
595
618
* kaiser;
596
- self . fir [ ( fir_offset + j) as usize ] = ( val + 0.5 ) as i16 ;
619
+ self . fir . data [ ( fir_offset + j) as usize ] = ( val + 0.5 ) as i16 ;
597
620
}
598
621
}
599
622
}
0 commit comments