blob: 0b870666aeff40bfe0547586f0c0a85061675190 [file] [log] [blame]
Emeric Vigiereebea672012-08-06 17:36:30 -04001/*
2** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
3**
4** This program is free software; you can redistribute it and/or modify
5** it under the terms of the GNU General Public License as published by
6** the Free Software Foundation; either version 2 of the License, or
7** (at your option) any later version.
8**
9** This program is distributed in the hope that it will be useful,
10** but WITHOUT ANY WARRANTY; without even the implied warranty of
11** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12** GNU General Public License for more details.
13**
14** You should have received a copy of the GNU General Public License
15** along with this program; if not, write to the Free Software
16** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
17*/
18
19/*
20** This code is part of Secret Rabbit Code aka libsamplerate. A commercial
21** use license for this code is available, please see:
22** http://www.mega-nerd.com/SRC/procedure.html
23*/
24
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28
29#include "config.h"
30#include "float_cast.h"
31#include "common.h"
32
33#define SINC_MAGIC_MARKER MAKE_MAGIC (' ', 's', 'i', 'n', 'c', ' ')
34
35/*========================================================================================
36*/
37
38#define MAKE_INCREMENT_T(x) ((increment_t) (x))
39
40#define SHIFT_BITS 12
41#define FP_ONE ((double) (((increment_t) 1) << SHIFT_BITS))
42#define INV_FP_ONE (1.0 / FP_ONE)
43
44/*========================================================================================
45*/
46
47typedef int32_t increment_t ;
48typedef float coeff_t ;
49
50#include "fastest_coeffs.h"
51#include "mid_qual_coeffs.h"
52#include "high_qual_coeffs.h"
53
54typedef struct
55{ int sinc_magic_marker ;
56
57 int channels ;
58 long in_count, in_used ;
59 long out_count, out_gen ;
60
61 int coeff_half_len, index_inc ;
62
63 double src_ratio, input_index ;
64
65 coeff_t const *coeffs ;
66
67 int b_current, b_end, b_real_end, b_len ;
68
69 /* Sure hope noone does more than 128 channels at once. */
70 double left_calc [128], right_calc [128] ;
71
72 /* C99 struct flexible array. */
73 float buffer [] ;
74} SINC_FILTER ;
75
76static int sinc_multichan_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) ;
77static int sinc_hex_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) ;
78static int sinc_quad_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) ;
79static int sinc_stereo_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) ;
80static int sinc_mono_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) ;
81
82static int prepare_data (SINC_FILTER *filter, SRC_DATA *data, int half_filter_chan_len) WARN_UNUSED ;
83
84static void sinc_reset (SRC_PRIVATE *psrc) ;
85
86static inline increment_t
87double_to_fp (double x)
88{ return (lrint ((x) * FP_ONE)) ;
89} /* double_to_fp */
90
91static inline increment_t
92int_to_fp (int x)
93{ return (((increment_t) (x)) << SHIFT_BITS) ;
94} /* int_to_fp */
95
96static inline int
97fp_to_int (increment_t x)
98{ return (((x) >> SHIFT_BITS)) ;
99} /* fp_to_int */
100
101static inline increment_t
102fp_fraction_part (increment_t x)
103{ return ((x) & ((((increment_t) 1) << SHIFT_BITS) - 1)) ;
104} /* fp_fraction_part */
105
106static inline double
107fp_to_double (increment_t x)
108{ return fp_fraction_part (x) * INV_FP_ONE ;
109} /* fp_to_double */
110
111
112/*----------------------------------------------------------------------------------------
113*/
114
115const char*
116sinc_get_name (int src_enum)
117{
118 switch (src_enum)
119 { case SRC_SINC_BEST_QUALITY :
120 return "Best Sinc Interpolator" ;
121
122 case SRC_SINC_MEDIUM_QUALITY :
123 return "Medium Sinc Interpolator" ;
124
125 case SRC_SINC_FASTEST :
126 return "Fastest Sinc Interpolator" ;
127
128 default: break ;
129 } ;
130
131 return NULL ;
132} /* sinc_get_descrition */
133
134const char*
135sinc_get_description (int src_enum)
136{
137 switch (src_enum)
138 { case SRC_SINC_FASTEST :
139 return "Band limited sinc interpolation, fastest, 97dB SNR, 80% BW." ;
140
141 case SRC_SINC_MEDIUM_QUALITY :
142 return "Band limited sinc interpolation, medium quality, 121dB SNR, 90% BW." ;
143
144 case SRC_SINC_BEST_QUALITY :
145 return "Band limited sinc interpolation, best quality, 145dB SNR, 96% BW." ;
146
147 default :
148 break ;
149 } ;
150
151 return NULL ;
152} /* sinc_get_descrition */
153
154int
155sinc_set_converter (SRC_PRIVATE *psrc, int src_enum)
156{ SINC_FILTER *filter, temp_filter ;
157 increment_t count ;
158 int bits ;
159
160 /* Quick sanity check. */
161 if (SHIFT_BITS >= sizeof (increment_t) * 8 - 1)
162 return SRC_ERR_SHIFT_BITS ;
163
164 if (psrc->private_data != NULL)
165 { free (psrc->private_data) ;
166 psrc->private_data = NULL ;
167 } ;
168
169 memset (&temp_filter, 0, sizeof (temp_filter)) ;
170
171 temp_filter.sinc_magic_marker = SINC_MAGIC_MARKER ;
172 temp_filter.channels = psrc->channels ;
173
174 if (psrc->channels > ARRAY_LEN (temp_filter.left_calc))
175 return SRC_ERR_BAD_CHANNEL_COUNT ;
176 else if (psrc->channels == 1)
177 { psrc->const_process = sinc_mono_vari_process ;
178 psrc->vari_process = sinc_mono_vari_process ;
179 }
180 else
181 if (psrc->channels == 2)
182 { psrc->const_process = sinc_stereo_vari_process ;
183 psrc->vari_process = sinc_stereo_vari_process ;
184 }
185 else
186 if (psrc->channels == 4)
187 { psrc->const_process = sinc_quad_vari_process ;
188 psrc->vari_process = sinc_quad_vari_process ;
189 }
190 else
191 if (psrc->channels == 6)
192 { psrc->const_process = sinc_hex_vari_process ;
193 psrc->vari_process = sinc_hex_vari_process ;
194 }
195 else
196 { psrc->const_process = sinc_multichan_vari_process ;
197 psrc->vari_process = sinc_multichan_vari_process ;
198 } ;
199 psrc->reset = sinc_reset ;
200
201 switch (src_enum)
202 { case SRC_SINC_FASTEST :
203 temp_filter.coeffs = fastest_coeffs.coeffs ;
204 temp_filter.coeff_half_len = ARRAY_LEN (fastest_coeffs.coeffs) - 1 ;
205 temp_filter.index_inc = fastest_coeffs.increment ;
206 break ;
207
208 case SRC_SINC_MEDIUM_QUALITY :
209 temp_filter.coeffs = slow_mid_qual_coeffs.coeffs ;
210 temp_filter.coeff_half_len = ARRAY_LEN (slow_mid_qual_coeffs.coeffs) - 1 ;
211 temp_filter.index_inc = slow_mid_qual_coeffs.increment ;
212 break ;
213
214 case SRC_SINC_BEST_QUALITY :
215 temp_filter.coeffs = slow_high_qual_coeffs.coeffs ;
216 temp_filter.coeff_half_len = ARRAY_LEN (slow_high_qual_coeffs.coeffs) - 1 ;
217 temp_filter.index_inc = slow_high_qual_coeffs.increment ;
218 break ;
219
220 default :
221 return SRC_ERR_BAD_CONVERTER ;
222 } ;
223
224 /*
225 ** FIXME : This needs to be looked at more closely to see if there is
226 ** a better way. Need to look at prepare_data () at the same time.
227 */
228
229 temp_filter.b_len = lrint (2.5 * temp_filter.coeff_half_len / (temp_filter.index_inc * 1.0) * SRC_MAX_RATIO) ;
230 temp_filter.b_len = MAX (temp_filter.b_len, 4096) ;
231 temp_filter.b_len *= temp_filter.channels ;
232
233 if ((filter = calloc (1, sizeof (SINC_FILTER) + sizeof (filter->buffer [0]) * (temp_filter.b_len + temp_filter.channels))) == NULL)
234 return SRC_ERR_MALLOC_FAILED ;
235
236 *filter = temp_filter ;
237 memset (&temp_filter, 0xEE, sizeof (temp_filter)) ;
238
239 psrc->private_data = filter ;
240
241 sinc_reset (psrc) ;
242
243 count = filter->coeff_half_len ;
244 for (bits = 0 ; (MAKE_INCREMENT_T (1) << bits) < count ; bits++)
245 count |= (MAKE_INCREMENT_T (1) << bits) ;
246
247 if (bits + SHIFT_BITS - 1 >= (int) (sizeof (increment_t) * 8))
248 return SRC_ERR_FILTER_LEN ;
249
250 return SRC_ERR_NO_ERROR ;
251} /* sinc_set_converter */
252
253static void
254sinc_reset (SRC_PRIVATE *psrc)
255{ SINC_FILTER *filter ;
256
257 filter = (SINC_FILTER*) psrc->private_data ;
258 if (filter == NULL)
259 return ;
260
261 filter->b_current = filter->b_end = 0 ;
262 filter->b_real_end = -1 ;
263
264 filter->src_ratio = filter->input_index = 0.0 ;
265
266 memset (filter->buffer, 0, filter->b_len * sizeof (filter->buffer [0])) ;
267
268 /* Set this for a sanity check */
269 memset (filter->buffer + filter->b_len, 0xAA, filter->channels * sizeof (filter->buffer [0])) ;
270} /* sinc_reset */
271
272/*========================================================================================
273** Beware all ye who dare pass this point. There be dragons here.
274*/
275
276static inline double
277calc_output_single (SINC_FILTER *filter, increment_t increment, increment_t start_filter_index)
278{ double fraction, left, right, icoeff ;
279 increment_t filter_index, max_filter_index ;
280 int data_index, coeff_count, indx ;
281
282 /* Convert input parameters into fixed point. */
283 max_filter_index = int_to_fp (filter->coeff_half_len) ;
284
285 /* First apply the left half of the filter. */
286 filter_index = start_filter_index ;
287 coeff_count = (max_filter_index - filter_index) / increment ;
288 filter_index = filter_index + coeff_count * increment ;
289 data_index = filter->b_current - coeff_count ;
290
291 left = 0.0 ;
292 do
293 { fraction = fp_to_double (filter_index) ;
294 indx = fp_to_int (filter_index) ;
295
296 icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;
297
298 left += icoeff * filter->buffer [data_index] ;
299
300 filter_index -= increment ;
301 data_index = data_index + 1 ;
302 }
303 while (filter_index >= MAKE_INCREMENT_T (0)) ;
304
305 /* Now apply the right half of the filter. */
306 filter_index = increment - start_filter_index ;
307 coeff_count = (max_filter_index - filter_index) / increment ;
308 filter_index = filter_index + coeff_count * increment ;
309 data_index = filter->b_current + 1 + coeff_count ;
310
311 right = 0.0 ;
312 do
313 { fraction = fp_to_double (filter_index) ;
314 indx = fp_to_int (filter_index) ;
315
316 icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;
317
318 right += icoeff * filter->buffer [data_index] ;
319
320 filter_index -= increment ;
321 data_index = data_index - 1 ;
322 }
323 while (filter_index > MAKE_INCREMENT_T (0)) ;
324
325 return (left + right) ;
326} /* calc_output_single */
327
328static int
329sinc_mono_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data)
330{ SINC_FILTER *filter ;
331 double input_index, src_ratio, count, float_increment, terminate, rem ;
332 increment_t increment, start_filter_index ;
333 int half_filter_chan_len, samples_in_hand ;
334
335 if (psrc->private_data == NULL)
336 return SRC_ERR_NO_PRIVATE ;
337
338 filter = (SINC_FILTER*) psrc->private_data ;
339
340 /* If there is not a problem, this will be optimised out. */
341 if (sizeof (filter->buffer [0]) != sizeof (data->data_in [0]))
342 return SRC_ERR_SIZE_INCOMPATIBILITY ;
343
344 filter->in_count = data->input_frames * filter->channels ;
345 filter->out_count = data->output_frames * filter->channels ;
346 filter->in_used = filter->out_gen = 0 ;
347
348 src_ratio = psrc->last_ratio ;
349
350 /* Check the sample rate ratio wrt the buffer len. */
351 count = (filter->coeff_half_len + 2.0) / filter->index_inc ;
352 if (MIN (psrc->last_ratio, data->src_ratio) < 1.0)
353 count /= MIN (psrc->last_ratio, data->src_ratio) ;
354
355 /* Maximum coefficientson either side of center point. */
356 half_filter_chan_len = filter->channels * (lrint (count) + 1) ;
357
358 input_index = psrc->last_position ;
359 float_increment = filter->index_inc ;
360
361 rem = fmod_one (input_index) ;
362 filter->b_current = (filter->b_current + filter->channels * lrint (input_index - rem)) % filter->b_len ;
363 input_index = rem ;
364
365 terminate = 1.0 / src_ratio + 1e-20 ;
366
367 /* Main processing loop. */
368 while (filter->out_gen < filter->out_count)
369 {
370 /* Need to reload buffer? */
371 samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ;
372
373 if (samples_in_hand <= half_filter_chan_len)
374 { if ((psrc->error = prepare_data (filter, data, half_filter_chan_len)) != 0)
375 return psrc->error ;
376
377 samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ;
378 if (samples_in_hand <= half_filter_chan_len)
379 break ;
380 } ;
381
382 /* This is the termination condition. */
383 if (filter->b_real_end >= 0)
384 { if (filter->b_current + input_index + terminate >= filter->b_real_end)
385 break ;
386 } ;
387
388 if (filter->out_count > 0 && fabs (psrc->last_ratio - data->src_ratio) > 1e-10)
389 src_ratio = psrc->last_ratio + filter->out_gen * (data->src_ratio - psrc->last_ratio) / filter->out_count ;
390
391 float_increment = filter->index_inc * 1.0 ;
392 if (src_ratio < 1.0)
393 float_increment = filter->index_inc * src_ratio ;
394
395 increment = double_to_fp (float_increment) ;
396
397 start_filter_index = double_to_fp (input_index * float_increment) ;
398
399 data->data_out [filter->out_gen] = (float) ((float_increment / filter->index_inc) *
400 calc_output_single (filter, increment, start_filter_index)) ;
401 filter->out_gen ++ ;
402
403 /* Figure out the next index. */
404 input_index += 1.0 / src_ratio ;
405 rem = fmod_one (input_index) ;
406
407 filter->b_current = (filter->b_current + filter->channels * lrint (input_index - rem)) % filter->b_len ;
408 input_index = rem ;
409 } ;
410
411 psrc->last_position = input_index ;
412
413 /* Save current ratio rather then target ratio. */
414 psrc->last_ratio = src_ratio ;
415
416 data->input_frames_used = filter->in_used / filter->channels ;
417 data->output_frames_gen = filter->out_gen / filter->channels ;
418
419 return SRC_ERR_NO_ERROR ;
420} /* sinc_mono_vari_process */
421
422static inline void
423calc_output_stereo (SINC_FILTER *filter, increment_t increment, increment_t start_filter_index, double scale, float * output)
424{ double fraction, left [2], right [2], icoeff ;
425 increment_t filter_index, max_filter_index ;
426 int data_index, coeff_count, indx ;
427
428 /* Convert input parameters into fixed point. */
429 max_filter_index = int_to_fp (filter->coeff_half_len) ;
430
431 /* First apply the left half of the filter. */
432 filter_index = start_filter_index ;
433 coeff_count = (max_filter_index - filter_index) / increment ;
434 filter_index = filter_index + coeff_count * increment ;
435 data_index = filter->b_current - filter->channels * coeff_count ;
436
437 left [0] = left [1] = 0.0 ;
438 do
439 { fraction = fp_to_double (filter_index) ;
440 indx = fp_to_int (filter_index) ;
441
442 icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;
443
444 left [0] += icoeff * filter->buffer [data_index] ;
445 left [1] += icoeff * filter->buffer [data_index + 1] ;
446
447 filter_index -= increment ;
448 data_index = data_index + 2 ;
449 }
450 while (filter_index >= MAKE_INCREMENT_T (0)) ;
451
452 /* Now apply the right half of the filter. */
453 filter_index = increment - start_filter_index ;
454 coeff_count = (max_filter_index - filter_index) / increment ;
455 filter_index = filter_index + coeff_count * increment ;
456 data_index = filter->b_current + filter->channels * (1 + coeff_count) ;
457
458 right [0] = right [1] = 0.0 ;
459 do
460 { fraction = fp_to_double (filter_index) ;
461 indx = fp_to_int (filter_index) ;
462
463 icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;
464
465 right [0] += icoeff * filter->buffer [data_index] ;
466 right [1] += icoeff * filter->buffer [data_index + 1] ;
467
468 filter_index -= increment ;
469 data_index = data_index - 2 ;
470 }
471 while (filter_index > MAKE_INCREMENT_T (0)) ;
472
473 output [0] = scale * (left [0] + right [0]) ;
474 output [1] = scale * (left [1] + right [1]) ;
475} /* calc_output_stereo */
476
477static int
478sinc_stereo_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data)
479{ SINC_FILTER *filter ;
480 double input_index, src_ratio, count, float_increment, terminate, rem ;
481 increment_t increment, start_filter_index ;
482 int half_filter_chan_len, samples_in_hand ;
483
484 if (psrc->private_data == NULL)
485 return SRC_ERR_NO_PRIVATE ;
486
487 filter = (SINC_FILTER*) psrc->private_data ;
488
489 /* If there is not a problem, this will be optimised out. */
490 if (sizeof (filter->buffer [0]) != sizeof (data->data_in [0]))
491 return SRC_ERR_SIZE_INCOMPATIBILITY ;
492
493 filter->in_count = data->input_frames * filter->channels ;
494 filter->out_count = data->output_frames * filter->channels ;
495 filter->in_used = filter->out_gen = 0 ;
496
497 src_ratio = psrc->last_ratio ;
498
499 /* Check the sample rate ratio wrt the buffer len. */
500 count = (filter->coeff_half_len + 2.0) / filter->index_inc ;
501 if (MIN (psrc->last_ratio, data->src_ratio) < 1.0)
502 count /= MIN (psrc->last_ratio, data->src_ratio) ;
503
504 /* Maximum coefficientson either side of center point. */
505 half_filter_chan_len = filter->channels * (lrint (count) + 1) ;
506
507 input_index = psrc->last_position ;
508 float_increment = filter->index_inc ;
509
510 rem = fmod_one (input_index) ;
511 filter->b_current = (filter->b_current + filter->channels * lrint (input_index - rem)) % filter->b_len ;
512 input_index = rem ;
513
514 terminate = 1.0 / src_ratio + 1e-20 ;
515
516 /* Main processing loop. */
517 while (filter->out_gen < filter->out_count)
518 {
519 /* Need to reload buffer? */
520 samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ;
521
522 if (samples_in_hand <= half_filter_chan_len)
523 { if ((psrc->error = prepare_data (filter, data, half_filter_chan_len)) != 0)
524 return psrc->error ;
525
526 samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ;
527 if (samples_in_hand <= half_filter_chan_len)
528 break ;
529 } ;
530
531 /* This is the termination condition. */
532 if (filter->b_real_end >= 0)
533 { if (filter->b_current + input_index + terminate >= filter->b_real_end)
534 break ;
535 } ;
536
537 if (filter->out_count > 0 && fabs (psrc->last_ratio - data->src_ratio) > 1e-10)
538 src_ratio = psrc->last_ratio + filter->out_gen * (data->src_ratio - psrc->last_ratio) / filter->out_count ;
539
540 float_increment = filter->index_inc * 1.0 ;
541 if (src_ratio < 1.0)
542 float_increment = filter->index_inc * src_ratio ;
543
544 increment = double_to_fp (float_increment) ;
545
546 start_filter_index = double_to_fp (input_index * float_increment) ;
547
548 calc_output_stereo (filter, increment, start_filter_index, float_increment / filter->index_inc, data->data_out + filter->out_gen) ;
549 filter->out_gen += 2 ;
550
551 /* Figure out the next index. */
552 input_index += 1.0 / src_ratio ;
553 rem = fmod_one (input_index) ;
554
555 filter->b_current = (filter->b_current + filter->channels * lrint (input_index - rem)) % filter->b_len ;
556 input_index = rem ;
557 } ;
558
559 psrc->last_position = input_index ;
560
561 /* Save current ratio rather then target ratio. */
562 psrc->last_ratio = src_ratio ;
563
564 data->input_frames_used = filter->in_used / filter->channels ;
565 data->output_frames_gen = filter->out_gen / filter->channels ;
566
567 return SRC_ERR_NO_ERROR ;
568} /* sinc_stereo_vari_process */
569
570static inline void
571calc_output_quad (SINC_FILTER *filter, increment_t increment, increment_t start_filter_index, double scale, float * output)
572{ double fraction, left [4], right [4], icoeff ;
573 increment_t filter_index, max_filter_index ;
574 int data_index, coeff_count, indx ;
575
576 /* Convert input parameters into fixed point. */
577 max_filter_index = int_to_fp (filter->coeff_half_len) ;
578
579 /* First apply the left half of the filter. */
580 filter_index = start_filter_index ;
581 coeff_count = (max_filter_index - filter_index) / increment ;
582 filter_index = filter_index + coeff_count * increment ;
583 data_index = filter->b_current - filter->channels * coeff_count ;
584
585 left [0] = left [1] = left [2] = left [3] = 0.0 ;
586 do
587 { fraction = fp_to_double (filter_index) ;
588 indx = fp_to_int (filter_index) ;
589
590 icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;
591
592 left [0] += icoeff * filter->buffer [data_index] ;
593 left [1] += icoeff * filter->buffer [data_index + 1] ;
594 left [2] += icoeff * filter->buffer [data_index + 2] ;
595 left [3] += icoeff * filter->buffer [data_index + 3] ;
596
597 filter_index -= increment ;
598 data_index = data_index + 4 ;
599 }
600 while (filter_index >= MAKE_INCREMENT_T (0)) ;
601
602 /* Now apply the right half of the filter. */
603 filter_index = increment - start_filter_index ;
604 coeff_count = (max_filter_index - filter_index) / increment ;
605 filter_index = filter_index + coeff_count * increment ;
606 data_index = filter->b_current + filter->channels * (1 + coeff_count) ;
607
608 right [0] = right [1] = right [2] = right [3] = 0.0 ;
609 do
610 { fraction = fp_to_double (filter_index) ;
611 indx = fp_to_int (filter_index) ;
612
613 icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;
614
615 right [0] += icoeff * filter->buffer [data_index] ;
616 right [1] += icoeff * filter->buffer [data_index + 1] ;
617 right [2] += icoeff * filter->buffer [data_index + 2] ;
618 right [3] += icoeff * filter->buffer [data_index + 3] ;
619
620 filter_index -= increment ;
621 data_index = data_index - 4 ;
622 }
623 while (filter_index > MAKE_INCREMENT_T (0)) ;
624
625 output [0] = scale * (left [0] + right [0]) ;
626 output [1] = scale * (left [1] + right [1]) ;
627 output [2] = scale * (left [2] + right [2]) ;
628 output [3] = scale * (left [3] + right [3]) ;
629} /* calc_output_quad */
630
631static int
632sinc_quad_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data)
633{ SINC_FILTER *filter ;
634 double input_index, src_ratio, count, float_increment, terminate, rem ;
635 increment_t increment, start_filter_index ;
636 int half_filter_chan_len, samples_in_hand ;
637
638 if (psrc->private_data == NULL)
639 return SRC_ERR_NO_PRIVATE ;
640
641 filter = (SINC_FILTER*) psrc->private_data ;
642
643 /* If there is not a problem, this will be optimised out. */
644 if (sizeof (filter->buffer [0]) != sizeof (data->data_in [0]))
645 return SRC_ERR_SIZE_INCOMPATIBILITY ;
646
647 filter->in_count = data->input_frames * filter->channels ;
648 filter->out_count = data->output_frames * filter->channels ;
649 filter->in_used = filter->out_gen = 0 ;
650
651 src_ratio = psrc->last_ratio ;
652
653 /* Check the sample rate ratio wrt the buffer len. */
654 count = (filter->coeff_half_len + 2.0) / filter->index_inc ;
655 if (MIN (psrc->last_ratio, data->src_ratio) < 1.0)
656 count /= MIN (psrc->last_ratio, data->src_ratio) ;
657
658 /* Maximum coefficientson either side of center point. */
659 half_filter_chan_len = filter->channels * (lrint (count) + 1) ;
660
661 input_index = psrc->last_position ;
662 float_increment = filter->index_inc ;
663
664 rem = fmod_one (input_index) ;
665 filter->b_current = (filter->b_current + filter->channels * lrint (input_index - rem)) % filter->b_len ;
666 input_index = rem ;
667
668 terminate = 1.0 / src_ratio + 1e-20 ;
669
670 /* Main processing loop. */
671 while (filter->out_gen < filter->out_count)
672 {
673 /* Need to reload buffer? */
674 samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ;
675
676 if (samples_in_hand <= half_filter_chan_len)
677 { if ((psrc->error = prepare_data (filter, data, half_filter_chan_len)) != 0)
678 return psrc->error ;
679
680 samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ;
681 if (samples_in_hand <= half_filter_chan_len)
682 break ;
683 } ;
684
685 /* This is the termination condition. */
686 if (filter->b_real_end >= 0)
687 { if (filter->b_current + input_index + terminate >= filter->b_real_end)
688 break ;
689 } ;
690
691 if (filter->out_count > 0 && fabs (psrc->last_ratio - data->src_ratio) > 1e-10)
692 src_ratio = psrc->last_ratio + filter->out_gen * (data->src_ratio - psrc->last_ratio) / filter->out_count ;
693
694 float_increment = filter->index_inc * 1.0 ;
695 if (src_ratio < 1.0)
696 float_increment = filter->index_inc * src_ratio ;
697
698 increment = double_to_fp (float_increment) ;
699
700 start_filter_index = double_to_fp (input_index * float_increment) ;
701
702 calc_output_quad (filter, increment, start_filter_index, float_increment / filter->index_inc, data->data_out + filter->out_gen) ;
703 filter->out_gen += 4 ;
704
705 /* Figure out the next index. */
706 input_index += 1.0 / src_ratio ;
707 rem = fmod_one (input_index) ;
708
709 filter->b_current = (filter->b_current + filter->channels * lrint (input_index - rem)) % filter->b_len ;
710 input_index = rem ;
711 } ;
712
713 psrc->last_position = input_index ;
714
715 /* Save current ratio rather then target ratio. */
716 psrc->last_ratio = src_ratio ;
717
718 data->input_frames_used = filter->in_used / filter->channels ;
719 data->output_frames_gen = filter->out_gen / filter->channels ;
720
721 return SRC_ERR_NO_ERROR ;
722} /* sinc_quad_vari_process */
723
724static inline void
725calc_output_hex (SINC_FILTER *filter, increment_t increment, increment_t start_filter_index, double scale, float * output)
726{ double fraction, left [6], right [6], icoeff ;
727 increment_t filter_index, max_filter_index ;
728 int data_index, coeff_count, indx ;
729
730 /* Convert input parameters into fixed point. */
731 max_filter_index = int_to_fp (filter->coeff_half_len) ;
732
733 /* First apply the left half of the filter. */
734 filter_index = start_filter_index ;
735 coeff_count = (max_filter_index - filter_index) / increment ;
736 filter_index = filter_index + coeff_count * increment ;
737 data_index = filter->b_current - filter->channels * coeff_count ;
738
739 left [0] = left [1] = left [2] = left [3] = left [4] = left [5] = 0.0 ;
740 do
741 { fraction = fp_to_double (filter_index) ;
742 indx = fp_to_int (filter_index) ;
743
744 icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;
745
746 left [0] += icoeff * filter->buffer [data_index] ;
747 left [1] += icoeff * filter->buffer [data_index + 1] ;
748 left [2] += icoeff * filter->buffer [data_index + 2] ;
749 left [3] += icoeff * filter->buffer [data_index + 3] ;
750 left [4] += icoeff * filter->buffer [data_index + 4] ;
751 left [5] += icoeff * filter->buffer [data_index + 5] ;
752
753 filter_index -= increment ;
754 data_index = data_index + 6 ;
755 }
756 while (filter_index >= MAKE_INCREMENT_T (0)) ;
757
758 /* Now apply the right half of the filter. */
759 filter_index = increment - start_filter_index ;
760 coeff_count = (max_filter_index - filter_index) / increment ;
761 filter_index = filter_index + coeff_count * increment ;
762 data_index = filter->b_current + filter->channels * (1 + coeff_count) ;
763
764 right [0] = right [1] = right [2] = right [3] = right [4] = right [5] = 0.0 ;
765 do
766 { fraction = fp_to_double (filter_index) ;
767 indx = fp_to_int (filter_index) ;
768
769 icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;
770
771 right [0] += icoeff * filter->buffer [data_index] ;
772 right [1] += icoeff * filter->buffer [data_index + 1] ;
773 right [2] += icoeff * filter->buffer [data_index + 2] ;
774 right [3] += icoeff * filter->buffer [data_index + 3] ;
775 right [4] += icoeff * filter->buffer [data_index + 4] ;
776 right [5] += icoeff * filter->buffer [data_index + 5] ;
777
778 filter_index -= increment ;
779 data_index = data_index - 6 ;
780 }
781 while (filter_index > MAKE_INCREMENT_T (0)) ;
782
783 output [0] = scale * (left [0] + right [0]) ;
784 output [1] = scale * (left [1] + right [1]) ;
785 output [2] = scale * (left [2] + right [2]) ;
786 output [3] = scale * (left [3] + right [3]) ;
787 output [4] = scale * (left [4] + right [4]) ;
788 output [5] = scale * (left [5] + right [5]) ;
789} /* calc_output_hex */
790
791static int
792sinc_hex_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data)
793{ SINC_FILTER *filter ;
794 double input_index, src_ratio, count, float_increment, terminate, rem ;
795 increment_t increment, start_filter_index ;
796 int half_filter_chan_len, samples_in_hand ;
797
798 if (psrc->private_data == NULL)
799 return SRC_ERR_NO_PRIVATE ;
800
801 filter = (SINC_FILTER*) psrc->private_data ;
802
803 /* If there is not a problem, this will be optimised out. */
804 if (sizeof (filter->buffer [0]) != sizeof (data->data_in [0]))
805 return SRC_ERR_SIZE_INCOMPATIBILITY ;
806
807 filter->in_count = data->input_frames * filter->channels ;
808 filter->out_count = data->output_frames * filter->channels ;
809 filter->in_used = filter->out_gen = 0 ;
810
811 src_ratio = psrc->last_ratio ;
812
813 /* Check the sample rate ratio wrt the buffer len. */
814 count = (filter->coeff_half_len + 2.0) / filter->index_inc ;
815 if (MIN (psrc->last_ratio, data->src_ratio) < 1.0)
816 count /= MIN (psrc->last_ratio, data->src_ratio) ;
817
818 /* Maximum coefficientson either side of center point. */
819 half_filter_chan_len = filter->channels * (lrint (count) + 1) ;
820
821 input_index = psrc->last_position ;
822 float_increment = filter->index_inc ;
823
824 rem = fmod_one (input_index) ;
825 filter->b_current = (filter->b_current + filter->channels * lrint (input_index - rem)) % filter->b_len ;
826 input_index = rem ;
827
828 terminate = 1.0 / src_ratio + 1e-20 ;
829
830 /* Main processing loop. */
831 while (filter->out_gen < filter->out_count)
832 {
833 /* Need to reload buffer? */
834 samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ;
835
836 if (samples_in_hand <= half_filter_chan_len)
837 { if ((psrc->error = prepare_data (filter, data, half_filter_chan_len)) != 0)
838 return psrc->error ;
839
840 samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ;
841 if (samples_in_hand <= half_filter_chan_len)
842 break ;
843 } ;
844
845 /* This is the termination condition. */
846 if (filter->b_real_end >= 0)
847 { if (filter->b_current + input_index + terminate >= filter->b_real_end)
848 break ;
849 } ;
850
851 if (filter->out_count > 0 && fabs (psrc->last_ratio - data->src_ratio) > 1e-10)
852 src_ratio = psrc->last_ratio + filter->out_gen * (data->src_ratio - psrc->last_ratio) / filter->out_count ;
853
854 float_increment = filter->index_inc * 1.0 ;
855 if (src_ratio < 1.0)
856 float_increment = filter->index_inc * src_ratio ;
857
858 increment = double_to_fp (float_increment) ;
859
860 start_filter_index = double_to_fp (input_index * float_increment) ;
861
862 calc_output_hex (filter, increment, start_filter_index, float_increment / filter->index_inc, data->data_out + filter->out_gen) ;
863 filter->out_gen += 6 ;
864
865 /* Figure out the next index. */
866 input_index += 1.0 / src_ratio ;
867 rem = fmod_one (input_index) ;
868
869 filter->b_current = (filter->b_current + filter->channels * lrint (input_index - rem)) % filter->b_len ;
870 input_index = rem ;
871 } ;
872
873 psrc->last_position = input_index ;
874
875 /* Save current ratio rather then target ratio. */
876 psrc->last_ratio = src_ratio ;
877
878 data->input_frames_used = filter->in_used / filter->channels ;
879 data->output_frames_gen = filter->out_gen / filter->channels ;
880
881 return SRC_ERR_NO_ERROR ;
882} /* sinc_hex_vari_process */
883
884static inline void
885calc_output_multi (SINC_FILTER *filter, increment_t increment, increment_t start_filter_index, int channels, double scale, float * output)
886{ double fraction, icoeff ;
887 /* The following line is 1999 ISO Standard C. If your compiler complains, get a better compiler. */
888 double *left, *right ;
889 increment_t filter_index, max_filter_index ;
890 int data_index, coeff_count, indx, ch ;
891
892 left = filter->left_calc ;
893 right = filter->right_calc ;
894
895 /* Convert input parameters into fixed point. */
896 max_filter_index = int_to_fp (filter->coeff_half_len) ;
897
898 /* First apply the left half of the filter. */
899 filter_index = start_filter_index ;
900 coeff_count = (max_filter_index - filter_index) / increment ;
901 filter_index = filter_index + coeff_count * increment ;
902 data_index = filter->b_current - channels * coeff_count ;
903
904 memset (left, 0, sizeof (left [0]) * channels) ;
905
906 do
907 { fraction = fp_to_double (filter_index) ;
908 indx = fp_to_int (filter_index) ;
909
910 icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;
911
912 /*
913 ** Duff's Device.
914 ** See : http://en.wikipedia.org/wiki/Duff's_device
915 */
916 ch = channels ;
917 do
918 {
919 switch (ch % 8)
920 { default :
921 ch -- ;
922 left [ch] += icoeff * filter->buffer [data_index + ch] ;
923 case 7 :
924 ch -- ;
925 left [ch] += icoeff * filter->buffer [data_index + ch] ;
926 case 6 :
927 ch -- ;
928 left [ch] += icoeff * filter->buffer [data_index + ch] ;
929 case 5 :
930 ch -- ;
931 left [ch] += icoeff * filter->buffer [data_index + ch] ;
932 case 4 :
933 ch -- ;
934 left [ch] += icoeff * filter->buffer [data_index + ch] ;
935 case 3 :
936 ch -- ;
937 left [ch] += icoeff * filter->buffer [data_index + ch] ;
938 case 2 :
939 ch -- ;
940 left [ch] += icoeff * filter->buffer [data_index + ch] ;
941 case 1 :
942 ch -- ;
943 left [ch] += icoeff * filter->buffer [data_index + ch] ;
944 } ;
945 }
946 while (ch > 0) ;
947
948 filter_index -= increment ;
949 data_index = data_index + channels ;
950 }
951 while (filter_index >= MAKE_INCREMENT_T (0)) ;
952
953 /* Now apply the right half of the filter. */
954 filter_index = increment - start_filter_index ;
955 coeff_count = (max_filter_index - filter_index) / increment ;
956 filter_index = filter_index + coeff_count * increment ;
957 data_index = filter->b_current + channels * (1 + coeff_count) ;
958
959 memset (right, 0, sizeof (right [0]) * channels) ;
960 do
961 { fraction = fp_to_double (filter_index) ;
962 indx = fp_to_int (filter_index) ;
963
964 icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;
965
966 ch = channels ;
967 do
968 {
969 switch (ch % 8)
970 { default :
971 ch -- ;
972 right [ch] += icoeff * filter->buffer [data_index + ch] ;
973 case 7 :
974 ch -- ;
975 right [ch] += icoeff * filter->buffer [data_index + ch] ;
976 case 6 :
977 ch -- ;
978 right [ch] += icoeff * filter->buffer [data_index + ch] ;
979 case 5 :
980 ch -- ;
981 right [ch] += icoeff * filter->buffer [data_index + ch] ;
982 case 4 :
983 ch -- ;
984 right [ch] += icoeff * filter->buffer [data_index + ch] ;
985 case 3 :
986 ch -- ;
987 right [ch] += icoeff * filter->buffer [data_index + ch] ;
988 case 2 :
989 ch -- ;
990 right [ch] += icoeff * filter->buffer [data_index + ch] ;
991 case 1 :
992 ch -- ;
993 right [ch] += icoeff * filter->buffer [data_index + ch] ;
994 } ;
995 }
996 while (ch > 0) ;
997
998 filter_index -= increment ;
999 data_index = data_index - channels ;
1000 }
1001 while (filter_index > MAKE_INCREMENT_T (0)) ;
1002
1003 ch = channels ;
1004 do
1005 {
1006 switch (ch % 8)
1007 { default :
1008 ch -- ;
1009 output [ch] = scale * (left [ch] + right [ch]) ;
1010 case 7 :
1011 ch -- ;
1012 output [ch] = scale * (left [ch] + right [ch]) ;
1013 case 6 :
1014 ch -- ;
1015 output [ch] = scale * (left [ch] + right [ch]) ;
1016 case 5 :
1017 ch -- ;
1018 output [ch] = scale * (left [ch] + right [ch]) ;
1019 case 4 :
1020 ch -- ;
1021 output [ch] = scale * (left [ch] + right [ch]) ;
1022 case 3 :
1023 ch -- ;
1024 output [ch] = scale * (left [ch] + right [ch]) ;
1025 case 2 :
1026 ch -- ;
1027 output [ch] = scale * (left [ch] + right [ch]) ;
1028 case 1 :
1029 ch -- ;
1030 output [ch] = scale * (left [ch] + right [ch]) ;
1031 } ;
1032 }
1033 while (ch > 0) ;
1034
1035 return ;
1036} /* calc_output_multi */
1037
1038static int
1039sinc_multichan_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data)
1040{ SINC_FILTER *filter ;
1041 double input_index, src_ratio, count, float_increment, terminate, rem ;
1042 increment_t increment, start_filter_index ;
1043 int half_filter_chan_len, samples_in_hand ;
1044
1045 if (psrc->private_data == NULL)
1046 return SRC_ERR_NO_PRIVATE ;
1047
1048 filter = (SINC_FILTER*) psrc->private_data ;
1049
1050 /* If there is not a problem, this will be optimised out. */
1051 if (sizeof (filter->buffer [0]) != sizeof (data->data_in [0]))
1052 return SRC_ERR_SIZE_INCOMPATIBILITY ;
1053
1054 filter->in_count = data->input_frames * filter->channels ;
1055 filter->out_count = data->output_frames * filter->channels ;
1056 filter->in_used = filter->out_gen = 0 ;
1057
1058 src_ratio = psrc->last_ratio ;
1059
1060 /* Check the sample rate ratio wrt the buffer len. */
1061 count = (filter->coeff_half_len + 2.0) / filter->index_inc ;
1062 if (MIN (psrc->last_ratio, data->src_ratio) < 1.0)
1063 count /= MIN (psrc->last_ratio, data->src_ratio) ;
1064
1065 /* Maximum coefficientson either side of center point. */
1066 half_filter_chan_len = filter->channels * (lrint (count) + 1) ;
1067
1068 input_index = psrc->last_position ;
1069 float_increment = filter->index_inc ;
1070
1071 rem = fmod_one (input_index) ;
1072 filter->b_current = (filter->b_current + filter->channels * lrint (input_index - rem)) % filter->b_len ;
1073 input_index = rem ;
1074
1075 terminate = 1.0 / src_ratio + 1e-20 ;
1076
1077 /* Main processing loop. */
1078 while (filter->out_gen < filter->out_count)
1079 {
1080 /* Need to reload buffer? */
1081 samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ;
1082
1083 if (samples_in_hand <= half_filter_chan_len)
1084 { if ((psrc->error = prepare_data (filter, data, half_filter_chan_len)) != 0)
1085 return psrc->error ;
1086
1087 samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ;
1088 if (samples_in_hand <= half_filter_chan_len)
1089 break ;
1090 } ;
1091
1092 /* This is the termination condition. */
1093 if (filter->b_real_end >= 0)
1094 { if (filter->b_current + input_index + terminate >= filter->b_real_end)
1095 break ;
1096 } ;
1097
1098 if (filter->out_count > 0 && fabs (psrc->last_ratio - data->src_ratio) > 1e-10)
1099 src_ratio = psrc->last_ratio + filter->out_gen * (data->src_ratio - psrc->last_ratio) / filter->out_count ;
1100
1101 float_increment = filter->index_inc * 1.0 ;
1102 if (src_ratio < 1.0)
1103 float_increment = filter->index_inc * src_ratio ;
1104
1105 increment = double_to_fp (float_increment) ;
1106
1107 start_filter_index = double_to_fp (input_index * float_increment) ;
1108
1109 calc_output_multi (filter, increment, start_filter_index, filter->channels, float_increment / filter->index_inc, data->data_out + filter->out_gen) ;
1110 filter->out_gen += psrc->channels ;
1111
1112 /* Figure out the next index. */
1113 input_index += 1.0 / src_ratio ;
1114 rem = fmod_one (input_index) ;
1115
1116 filter->b_current = (filter->b_current + filter->channels * lrint (input_index - rem)) % filter->b_len ;
1117 input_index = rem ;
1118 } ;
1119
1120 psrc->last_position = input_index ;
1121
1122 /* Save current ratio rather then target ratio. */
1123 psrc->last_ratio = src_ratio ;
1124
1125 data->input_frames_used = filter->in_used / filter->channels ;
1126 data->output_frames_gen = filter->out_gen / filter->channels ;
1127
1128 return SRC_ERR_NO_ERROR ;
1129} /* sinc_multichan_vari_process */
1130
1131/*----------------------------------------------------------------------------------------
1132*/
1133
1134static int
1135prepare_data (SINC_FILTER *filter, SRC_DATA *data, int half_filter_chan_len)
1136{ int len = 0 ;
1137
1138 if (filter->b_real_end >= 0)
1139 return 0 ; /* Should be terminating. Just return. */
1140
1141 if (filter->b_current == 0)
1142 { /* Initial state. Set up zeros at the start of the buffer and
1143 ** then load new data after that.
1144 */
1145 len = filter->b_len - 2 * half_filter_chan_len ;
1146
1147 filter->b_current = filter->b_end = half_filter_chan_len ;
1148 }
1149 else if (filter->b_end + half_filter_chan_len + filter->channels < filter->b_len)
1150 { /* Load data at current end position. */
1151 len = MAX (filter->b_len - filter->b_current - half_filter_chan_len, 0) ;
1152 }
1153 else
1154 { /* Move data at end of buffer back to the start of the buffer. */
1155 len = filter->b_end - filter->b_current ;
1156 memmove (filter->buffer, filter->buffer + filter->b_current - half_filter_chan_len,
1157 (half_filter_chan_len + len) * sizeof (filter->buffer [0])) ;
1158
1159 filter->b_current = half_filter_chan_len ;
1160 filter->b_end = filter->b_current + len ;
1161
1162 /* Now load data at current end of buffer. */
1163 len = MAX (filter->b_len - filter->b_current - half_filter_chan_len, 0) ;
1164 } ;
1165
1166 len = MIN (filter->in_count - filter->in_used, len) ;
1167 len -= (len % filter->channels) ;
1168
1169 if (len < 0 || filter->b_end + len > filter->b_len)
1170 return SRC_ERR_SINC_PREPARE_DATA_BAD_LEN ;
1171
1172 memcpy (filter->buffer + filter->b_end, data->data_in + filter->in_used,
1173 len * sizeof (filter->buffer [0])) ;
1174
1175 filter->b_end += len ;
1176 filter->in_used += len ;
1177
1178 if (filter->in_used == filter->in_count &&
1179 filter->b_end - filter->b_current < 2 * half_filter_chan_len && data->end_of_input)
1180 { /* Handle the case where all data in the current buffer has been
1181 ** consumed and this is the last buffer.
1182 */
1183
1184 if (filter->b_len - filter->b_end < half_filter_chan_len + 5)
1185 { /* If necessary, move data down to the start of the buffer. */
1186 len = filter->b_end - filter->b_current ;
1187 memmove (filter->buffer, filter->buffer + filter->b_current - half_filter_chan_len,
1188 (half_filter_chan_len + len) * sizeof (filter->buffer [0])) ;
1189
1190 filter->b_current = half_filter_chan_len ;
1191 filter->b_end = filter->b_current + len ;
1192 } ;
1193
1194 filter->b_real_end = filter->b_end ;
1195 len = half_filter_chan_len + 5 ;
1196
1197 if (len < 0 || filter->b_end + len > filter->b_len)
1198 len = filter->b_len - filter->b_end ;
1199
1200 memset (filter->buffer + filter->b_end, 0, len * sizeof (filter->buffer [0])) ;
1201 filter->b_end += len ;
1202 } ;
1203
1204 return 0 ;
1205} /* prepare_data */
1206
1207