@@ -34,8 +34,8 @@ struct resample_state {
34
34
struct {
35
35
int n , d ;
36
36
} ratio ;
37
- ssize_t m , sinc_len , sinc_fr_len , tmp_fr_len , in_len , out_len ;
38
- ssize_t in_buf_pos , out_buf_pos , drain_pos , drain_frames , out_delay ;
37
+ int sinc_fr_len , tmp_fr_len , in_len , out_len ;
38
+ int in_buf_pos , out_buf_pos , drain_pos , drain_frames , out_delay ;
39
39
fftw_complex * sinc_fr ;
40
40
fftw_complex * tmp_fr , * tmp_fr_2 ;
41
41
sample_t * * input , * * output , * * overlap ;
@@ -48,10 +48,12 @@ static double window(const double x)
48
48
#if WINDOW_SHAPE == 1
49
49
/* Blackman (~75dB stopband attenuation) */
50
50
#define M_FACT 6
51
+ if (x >= 1.0 || x <= 0.0 ) return 0.0 ;
51
52
return 0.42 - 0.5 * cos (2 * M_PI * x ) + 0.08 * cos (4 * M_PI * x );
52
53
#elif WINDOW_SHAPE == 2
53
54
/* Nuttall window (continuous first derivative) (~112dB stopband attenuation) */
54
55
#define M_FACT 8
56
+ if (x >= 1.0 || x <= 0.0 ) return 0.0 ;
55
57
return 0.355768 - 0.487396 * cos (2 * M_PI * x ) + 0.144232 * cos (4 * M_PI * x ) - 0.012604 * cos (6 * M_PI * x );
56
58
#else
57
59
#error "error: illegal WINDOW_SHAPE"
@@ -68,32 +70,32 @@ static double norm_sinc(const double x, const double fc)
68
70
sample_t * resample_effect_run (struct effect * e , ssize_t * frames , sample_t * ibuf , sample_t * obuf )
69
71
{
70
72
struct resample_state * state = (struct resample_state * ) e -> data ;
71
- ssize_t i , k , j , l , d1 , d2 , iframes = 0 , oframes = 0 ;
73
+ ssize_t iframes = 0 , oframes = 0 ;
72
74
const ssize_t max_oframes = ratio_mult_ceil (* frames , state -> ratio .n , state -> ratio .d );
73
75
74
76
while (iframes < * frames ) {
75
77
while (state -> in_buf_pos < state -> in_len && iframes < * frames ) {
76
- for (i = 0 ; i < e -> ostream .channels ; ++ i )
78
+ for (int i = 0 ; i < e -> ostream .channels ; ++ i )
77
79
state -> input [i ][state -> in_buf_pos ] = ibuf [iframes * e -> ostream .channels + i ];
78
80
++ iframes ;
79
81
++ state -> in_buf_pos ;
80
82
}
81
83
82
84
while (state -> out_buf_pos < state -> out_len && oframes < max_oframes && state -> has_output ) {
83
- for (i = 0 ; i < e -> ostream .channels ; ++ i )
85
+ for (int i = 0 ; i < e -> ostream .channels ; ++ i )
84
86
obuf [oframes * e -> ostream .channels + i ] = state -> output [i ][state -> out_buf_pos ];
85
87
++ oframes ;
86
88
++ state -> out_buf_pos ;
87
89
}
88
90
89
91
if (state -> in_buf_pos == state -> in_len && (!state -> has_output || state -> out_buf_pos == state -> out_len )) {
90
- for (i = 0 ; i < e -> ostream .channels ; ++ i ) {
92
+ for (int i = 0 ; i < e -> ostream .channels ; ++ i ) {
91
93
/* FFT(state->input[i]) -> state->tmp_fr */
92
94
fftw_execute (state -> r2c_plan [i ]);
93
95
memset (state -> tmp_fr_2 , 0 , state -> tmp_fr_len * sizeof (fftw_complex ));
94
96
/* convolve input with sinc filter */
95
97
state -> tmp_fr_2 [0 ] = state -> tmp_fr [0 ] * state -> sinc_fr [0 ];
96
- for (k = 1 , j = 1 , l = 1 , d1 = 1 , d2 = 1 ;; ++ k ) {
98
+ for (int k = 1 , j = 1 , l = 1 , d1 = 1 , d2 = 1 ;; ++ k ) {
97
99
fftw_complex s = (d1 == 1 ) ? state -> tmp_fr [j ] : conj (state -> tmp_fr [j ]);
98
100
state -> tmp_fr_2 [l ] += (d2 == 1 ) ? s * state -> sinc_fr [k ] : conj (s * state -> sinc_fr [k ]);
99
101
if (k + 1 == state -> sinc_fr_len ) break ;
@@ -111,10 +113,10 @@ sample_t * resample_effect_run(struct effect *e, ssize_t *frames, sample_t *ibuf
111
113
/* IFFT(state->tmp_fr_2) -> state->output[i] */
112
114
fftw_execute (state -> c2r_plan [i ]);
113
115
/* normalize */
114
- for (k = 0 ; k < state -> out_len * 2 ; ++ k )
116
+ for (int k = 0 ; k < state -> out_len * 2 ; ++ k )
115
117
state -> output [i ][k ] /= state -> in_len * 2 ;
116
118
/* handle overlap */
117
- for (k = 0 ; k < state -> out_len ; ++ k ) {
119
+ for (int k = 0 ; k < state -> out_len ; ++ k ) {
118
120
state -> output [i ][k ] += state -> overlap [i ][k ];
119
121
state -> overlap [i ][k ] = state -> output [i ][k + state -> out_len ];
120
122
}
@@ -260,11 +262,12 @@ struct effect * resample_effect_init(const struct effect_info *ei, const struct
260
262
const int m = lround (M_FACT / (width / max_rate ));
261
263
const int sinc_os = MINIMUM (min_factor , SINC_MAX_OVERSAMPLE );
262
264
const double fc_os = fc / sinc_os ;
263
- const int m_os = m * sinc_os ;
265
+ const int m_os = ( m + 1 ) * sinc_os - 1 ;
264
266
265
267
/* determine array lengths */
266
- state -> m = (m + 1 ) * 2 - 1 ; /* final impulse length after convolving sinc function with itself */
267
- int len_mult = (state -> m % max_factor != 0 ) ? state -> m / max_factor + 1 : state -> m / max_factor ;
268
+ const int m_conv = (m + 1 ) * 2 - 1 ; /* after convolving sinc function with itself */
269
+ int len_mult = (m_conv + 1 ) / max_factor ;
270
+ if ((m_conv + 1 ) % max_factor != 0 ) len_mult += 1 ;
268
271
if (len_mult > 16 ) { /* 17 is the first slow size */
269
272
const int fast_len_mult = next_fast_fftw_len (len_mult );
270
273
if (fast_len_mult != len_mult
@@ -273,17 +276,17 @@ struct effect * resample_effect_init(const struct effect_info *ei, const struct
273
276
|| next_fast_fftw_len (state -> ratio .d ) == state -> ratio .d ))
274
277
len_mult = fast_len_mult ;
275
278
}
276
- state -> sinc_len = max_factor * len_mult * sinc_os ;
279
+ const int sinc_len = max_factor * len_mult * sinc_os ;
277
280
state -> in_len = state -> ratio .d * len_mult ;
278
281
state -> out_len = state -> ratio .n * len_mult ;
279
282
state -> tmp_fr_len = max_factor * len_mult + 1 ;
280
- state -> sinc_fr_len = state -> sinc_len + 1 ;
283
+ state -> sinc_fr_len = sinc_len + 1 ;
281
284
282
285
/* calculate output delay */
283
286
if (rate == max_rate )
284
- state -> out_delay = state -> m / 2 ;
287
+ state -> out_delay = m_conv / 2 ;
285
288
else
286
- state -> out_delay = lround (state -> m / 2 * ((double ) state -> ratio .n / state -> ratio .d ));
289
+ state -> out_delay = lround (m_conv / 2 * ((double ) state -> ratio .n / state -> ratio .d ));
287
290
288
291
/* allocate arrays, construct fftw plans */
289
292
state -> input = calloc (e -> ostream .channels , sizeof (sample_t * ));
@@ -293,12 +296,12 @@ struct effect * resample_effect_init(const struct effect_info *ei, const struct
293
296
state -> c2r_plan = calloc (e -> ostream .channels , sizeof (fftw_plan ));
294
297
state -> tmp_fr = fftw_malloc (state -> tmp_fr_len * sizeof (fftw_complex ));
295
298
state -> tmp_fr_2 = fftw_malloc (state -> tmp_fr_len * sizeof (fftw_complex ));
296
- sinc = fftw_malloc (state -> sinc_len * 2 * sizeof (sample_t ));
299
+ sinc = fftw_malloc (sinc_len * 2 * sizeof (sample_t ));
297
300
state -> sinc_fr = fftw_malloc (state -> sinc_fr_len * sizeof (fftw_complex ));
298
301
299
302
dsp_fftw_acquire ();
300
303
const int planner_flags = (dsp_fftw_load_wisdom ()) ? FFTW_MEASURE : FFTW_ESTIMATE ;
301
- sinc_plan = fftw_plan_dft_r2c_1d (state -> sinc_len * 2 , sinc , state -> sinc_fr , FFTW_ESTIMATE );
304
+ sinc_plan = fftw_plan_dft_r2c_1d (sinc_len * 2 , sinc , state -> sinc_fr , FFTW_ESTIMATE );
302
305
for (int i = 0 ; i < e -> ostream .channels ; ++ i ) {
303
306
state -> input [i ] = fftw_malloc (state -> in_len * 2 * sizeof (sample_t ));
304
307
state -> output [i ] = fftw_malloc (state -> out_len * 2 * sizeof (sample_t ));
@@ -310,13 +313,14 @@ struct effect * resample_effect_init(const struct effect_info *ei, const struct
310
313
memset (state -> overlap [i ], 0 , state -> out_len * sizeof (sample_t ));
311
314
}
312
315
dsp_fftw_release ();
313
- memset (sinc , 0 , state -> sinc_len * 2 * sizeof (sample_t ));
316
+ memset (sinc , 0 , sinc_len * 2 * sizeof (sample_t ));
314
317
memset (state -> sinc_fr , 0 , state -> sinc_fr_len * sizeof (fftw_complex ));
315
318
memset (state -> tmp_fr , 0 , state -> tmp_fr_len * sizeof (fftw_complex ));
316
319
memset (state -> tmp_fr_2 , 0 , state -> tmp_fr_len * sizeof (fftw_complex ));
317
320
318
321
/* generate windowed sinc function */
319
- for (int i = 0 ; i < m_os + 1 ; ++ i )
322
+ /* note: all supported windows are zero at endpoints, so skip the first and last indicies */
323
+ for (int i = 1 ; i < m_os ; ++ i )
320
324
sinc [i ] = norm_sinc ((i * 2 - m_os )/2.0 , fc_os ) * window ((double ) i / m_os );
321
325
322
326
fftw_execute (sinc_plan );
@@ -327,8 +331,8 @@ struct effect * resample_effect_init(const struct effect_info *ei, const struct
327
331
for (int i = 0 ; i < state -> sinc_fr_len ; ++ i )
328
332
state -> sinc_fr [i ] *= state -> sinc_fr [i ];
329
333
330
- LOG_FMT (LL_VERBOSE , "%s: info: gcd=%d ratio=%d/%d width=%fHz fc=%f filter_len=%zd in_len=%zd out_len=%zd sinc_oversample=%d" ,
331
- argv [0 ], gcd , state -> ratio .n , state -> ratio .d , width , fc , state -> m , state -> in_len , state -> out_len , sinc_os );
334
+ LOG_FMT (LL_VERBOSE , "%s: info: gcd=%d ratio=%d/%d width=%fHz fc=%f filter_len=%d in_len=%d out_len=%d sinc_oversample=%d" ,
335
+ argv [0 ], gcd , state -> ratio .n , state -> ratio .d , width , fc , m_conv + 1 , state -> in_len , state -> out_len , sinc_os );
332
336
333
337
return e ;
334
338
}
0 commit comments