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