History

Merge from -optim branch.

Erik de Castro Lopo committed 17 years ago

Commit 32a6ce82 parents 94966fc 1bb5e8a5 files · +648 −69Browse files

Unified · Split

5 files
  1. ChangeLog +15 −0
  2. src/src_sinc.c +347 −27
  3. tests/Makefile.am +10 −5
  4. tests/multi_channel_test.c +59 −37
  5. tests/multichan_throughput_test.c +217 −0
ChangeLog+15−0
@@ -1,3 +1,12 @@
12008-12-13 Erik de Castro Lopo <erikd AT mega-nerd DOT com>
2
3 * tests/multichan_throughput_test.c
4 Do throughput test on all three SINC based converters.
5
6 * src/src_sinc.c
7 Rejig converter so filter coefficients are calculated once per frame and
8 special case channel counts of 1, 2 and 4.
9
12008-12-12 Erik de Castro Lopo <erikd AT mega-nerd DOT com>102008-12-12 Erik de Castro Lopo <erikd AT mega-nerd DOT com>
2 11
3 * src/samplerate.c examples/audio_out.c tests/*.c12 * src/samplerate.c examples/audio_out.c tests/*.c
@@ -8,6 +17,9 @@ · 4 unmodified lines
8 Fix a potential memory leak. Thanks to Peter G. Vavaroutsos for point this17 Fix a potential memory leak. Thanks to Peter G. Vavaroutsos for point this
9 out.18 out.
10 19
20 * tests/multi_channel_test.c
21 Robustify test.
22
112008-12-11 Erik de Castro Lopo <erikd AT mega-nerd DOT com>232008-12-11 Erik de Castro Lopo <erikd AT mega-nerd DOT com>
12 24
13 * reconfigure.mk autogen.sh25 * reconfigure.mk autogen.sh
@@ -16,6 +28,9 @@ · 2 unmodified lines
16 * configure.ac28 * configure.ac
17 Various updates.29 Various updates.
18 30
31 * tests/multichan_throughput_test.c tests/Makefile.am
32 Add new test and hook into build.
33
192008-11-11 Erik de Castro Lopo <erikd AT mega-nerd DOT com>342008-11-11 Erik de Castro Lopo <erikd AT mega-nerd DOT com>
20 35
21 * doc/index.html36 * doc/index.html
src/src_sinc.c+347−27
@@ -65,11 +65,15 @@ typedef struct · 64 unmodified lines
65 coeff_t const *coeffs ;65 coeff_t const *coeffs ;
66 66
67 int b_current, b_end, b_real_end, b_len ;67 int b_current, b_end, b_real_end, b_len ;
68 float buffer [1] ;68
69 /* C99 struct flexible array. */
70 float buffer [] ;
69} SINC_FILTER ;71} SINC_FILTER ;
70 72
71static int sinc_multichan_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) ;73static int sinc_multichan_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) ;
72static int sinc_1chan_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) ;74static int sinc_quad_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) ;
75static int sinc_stereo_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) ;
76static int sinc_mono_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) ;
73 77
74static void prepare_data (SINC_FILTER *filter, SRC_DATA *data, int half_filter_chan_len) ;78static void prepare_data (SINC_FILTER *filter, SRC_DATA *data, int half_filter_chan_len) ;
75 79
@@ -164,8 +168,18 @@ sinc_set_converter (SRC_PRIVATE *psrc, int src_enum) · 88 unmodified lines
164 temp_filter.channels = psrc->channels ;168 temp_filter.channels = psrc->channels ;
165 169
166 if (psrc->channels == 1)170 if (psrc->channels == 1)
167 { psrc->const_process = sinc_1chan_vari_process ;171 { psrc->const_process = sinc_mono_vari_process ;
168 psrc->vari_process = sinc_1chan_vari_process ;172 psrc->vari_process = sinc_mono_vari_process ;
173 }
174 else
175 if (psrc->channels == 2)
176 { psrc->const_process = sinc_stereo_vari_process ;
177 psrc->vari_process = sinc_stereo_vari_process ;
178 }
179 else
180 if (psrc->channels == 4)
181 { psrc->const_process = sinc_quad_vari_process ;
182 psrc->vari_process = sinc_quad_vari_process ;
169 }183 }
170 else184 else
171 { psrc->const_process = sinc_multichan_vari_process ;185 { psrc->const_process = sinc_multichan_vari_process ;
@@ -300,9 +314,102 @@ calc_output_single (SINC_FILTER *filter, increment_t increment, increment_t star · 128 unmodified lines
300 return (left + right) ;314 return (left + right) ;
301} /* calc_output_single */315} /* calc_output_single */
302 316
303static inline double317static int
304calc_output_multi (SINC_FILTER *filter, increment_t increment, increment_t start_filter_index, int ch)318sinc_mono_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data)
305{ double fraction, left, right, icoeff ;319{ SINC_FILTER *filter ;
320 double input_index, src_ratio, count, float_increment, terminate, rem ;
321 increment_t increment, start_filter_index ;
322 int half_filter_chan_len, samples_in_hand ;
323
324 if (psrc->private_data == NULL)
325 return SRC_ERR_NO_PRIVATE ;
326
327 filter = (SINC_FILTER*) psrc->private_data ;
328
329 /* If there is not a problem, this will be optimised out. */
330 if (sizeof (filter->buffer [0]) != sizeof (data->data_in [0]))
331 return SRC_ERR_SIZE_INCOMPATIBILITY ;
332
333 filter->in_count = data->input_frames * filter->channels ;
334 filter->out_count = data->output_frames * filter->channels ;
335 filter->in_used = filter->out_gen = 0 ;
336
337 src_ratio = psrc->last_ratio ;
338
339 /* Check the sample rate ratio wrt the buffer len. */
340 count = (filter->coeff_half_len + 2.0) / filter->index_inc ;
341 if (MIN (psrc->last_ratio, data->src_ratio) < 1.0)
342 count /= MIN (psrc->last_ratio, data->src_ratio) ;
343
344 /* Maximum coefficientson either side of center point. */
345 half_filter_chan_len = filter->channels * (lrint (count) + 1) ;
346
347 input_index = psrc->last_position ;
348 float_increment = filter->index_inc ;
349
350 rem = fmod_one (input_index) ;
351 filter->b_current = (filter->b_current + filter->channels * lrint (input_index - rem)) % filter->b_len ;
352 input_index = rem ;
353
354 terminate = 1.0 / src_ratio + 1e-20 ;
355
356 /* Main processing loop. */
357 while (filter->out_gen < filter->out_count)
358 {
359 /* Need to reload buffer? */
360 samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ;
361
362 if (samples_in_hand <= half_filter_chan_len)
363 { prepare_data (filter, data, half_filter_chan_len) ;
364
365 samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ;
366 if (samples_in_hand <= half_filter_chan_len)
367 break ;
368 } ;
369
370 /* This is the termination condition. */
371 if (filter->b_real_end >= 0)
372 { if (filter->b_current + input_index + terminate >= filter->b_real_end)
373 break ;
374 } ;
375
376 if (filter->out_count > 0 && fabs (psrc->last_ratio - data->src_ratio) > 1e-10)
377 src_ratio = psrc->last_ratio + filter->out_gen * (data->src_ratio - psrc->last_ratio) / filter->out_count ;
378
379 float_increment = filter->index_inc * 1.0 ;
380 if (src_ratio < 1.0)
381 float_increment = filter->index_inc * src_ratio ;
382
383 increment = double_to_fp (float_increment) ;
384
385 start_filter_index = double_to_fp (input_index * float_increment) ;
386
387 data->data_out [filter->out_gen] = (float) ((float_increment / filter->index_inc) *
388 calc_output_single (filter, increment, start_filter_index)) ;
389 filter->out_gen ++ ;
390
391 /* Figure out the next index. */
392 input_index += 1.0 / src_ratio ;
393 rem = fmod_one (input_index) ;
394
395 filter->b_current = (filter->b_current + filter->channels * lrint (input_index - rem)) % filter->b_len ;
396 input_index = rem ;
397 } ;
398
399 psrc->last_position = input_index ;
400
401 /* Save current ratio rather then target ratio. */
402 psrc->last_ratio = src_ratio ;
403
404 data->input_frames_used = filter->in_used / filter->channels ;
405 data->output_frames_gen = filter->out_gen / filter->channels ;
406
407 return SRC_ERR_NO_ERROR ;
408} /* sinc_mono_vari_process */
409
410static inline void
411calc_output_stereo (SINC_FILTER *filter, increment_t increment, increment_t start_filter_index, double scale, float * output)
412{ double fraction, left [2], right [2], icoeff ;
306 increment_t filter_index, max_filter_index ;413 increment_t filter_index, max_filter_index ;
307 int data_index, coeff_count, indx ;414 int data_index, coeff_count, indx ;
308 415
@@ -313,19 +420,20 @@ calc_output_multi (SINC_FILTER *filter, increment_t increment, increment_t start · 4 unmodified lines
313 filter_index = start_filter_index ;420 filter_index = start_filter_index ;
314 coeff_count = (max_filter_index - filter_index) / increment ;421 coeff_count = (max_filter_index - filter_index) / increment ;
315 filter_index = filter_index + coeff_count * increment ;422 filter_index = filter_index + coeff_count * increment ;
316 data_index = filter->b_current - filter->channels * coeff_count + ch ;423 data_index = filter->b_current - filter->channels * coeff_count ;
317 424
318 left = 0.0 ;425 left [0] = left [1] = 0.0 ;
319 do426 do
320 { fraction = fp_to_double (filter_index) ;427 { fraction = fp_to_double (filter_index) ;
321 indx = fp_to_int (filter_index) ;428 indx = fp_to_int (filter_index) ;
322 429
323 icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;430 icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;
324 431
325 left += icoeff * filter->buffer [data_index] ;432 left [0] += icoeff * filter->buffer [data_index] ;
433 left [1] += icoeff * filter->buffer [data_index + 1] ;
326 434
327 filter_index -= increment ;435 filter_index -= increment ;
328 data_index = data_index + filter->channels ;436 data_index = data_index + 2 ;
329 }437 }
330 while (filter_index >= MAKE_INCREMENT_T (0)) ;438 while (filter_index >= MAKE_INCREMENT_T (0)) ;
331 439
@@ -333,27 +441,29 @@ calc_output_multi (SINC_FILTER *filter, increment_t increment, increment_t start · 1 unmodified line
333 filter_index = increment - start_filter_index ;441 filter_index = increment - start_filter_index ;
334 coeff_count = (max_filter_index - filter_index) / increment ;442 coeff_count = (max_filter_index - filter_index) / increment ;
335 filter_index = filter_index + coeff_count * increment ;443 filter_index = filter_index + coeff_count * increment ;
336 data_index = filter->b_current + filter->channels * (1 + coeff_count) + ch ;444 data_index = filter->b_current + filter->channels * (1 + coeff_count) ;
337 445
338 right = 0.0 ;446 right [0] = right [1] = 0.0 ;
339 do447 do
340 { fraction = fp_to_double (filter_index) ;448 { fraction = fp_to_double (filter_index) ;
341 indx = fp_to_int (filter_index) ;449 indx = fp_to_int (filter_index) ;
342 450
343 icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;451 icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;
344 452
345 right += icoeff * filter->buffer [data_index] ;453 right [0] += icoeff * filter->buffer [data_index] ;
454 right [1] += icoeff * filter->buffer [data_index + 1] ;
346 455
347 filter_index -= increment ;456 filter_index -= increment ;
348 data_index = data_index - filter->channels ;457 data_index = data_index - filter->channels ;
349 }458 }
350 while (filter_index > MAKE_INCREMENT_T (0)) ;459 while (filter_index > MAKE_INCREMENT_T (0)) ;
351 460
352 return (left + right) ;461 output [0] = scale * (left [0] + right [0]) ;
353} /* calc_output_multi */462 output [1] = scale * (left [1] + right [1]) ;
463} /* calc_output_stereo */
354 464
355static int465static int
356sinc_1chan_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data)466sinc_stereo_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data)
357{ SINC_FILTER *filter ;467{ SINC_FILTER *filter ;
358 double input_index, src_ratio, count, float_increment, terminate, rem ;468 double input_index, src_ratio, count, float_increment, terminate, rem ;
359 increment_t increment, start_filter_index ;469 increment_t increment, start_filter_index ;
@@ -422,9 +532,8 @@ sinc_1chan_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) · 62 unmodified lines
422 532
423 start_filter_index = double_to_fp (input_index * float_increment) ;533 start_filter_index = double_to_fp (input_index * float_increment) ;
424 534
425 data->data_out [filter->out_gen] = (float) ((float_increment / filter->index_inc) *535 calc_output_stereo (filter, increment, start_filter_index, float_increment / filter->index_inc, data->data_out + filter->out_gen) ;
426 calc_output_single (filter, increment, start_filter_index)) ;536 filter->out_gen += 2 ;
427 filter->out_gen ++ ;
428 537
429 /* Figure out the next index. */538 /* Figure out the next index. */
430 input_index += 1.0 / src_ratio ;539 input_index += 1.0 / src_ratio ;
@@ -443,14 +552,75 @@ sinc_1chan_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) · 12 unmodified lines
443 data->output_frames_gen = filter->out_gen / filter->channels ;552 data->output_frames_gen = filter->out_gen / filter->channels ;
444 553
445 return SRC_ERR_NO_ERROR ;554 return SRC_ERR_NO_ERROR ;
446} /* sinc_1chan_vari_process */555} /* sinc_stereo_vari_process */
556
557static inline void
558calc_output_quad (SINC_FILTER *filter, increment_t increment, increment_t start_filter_index, double scale, float * output)
559{ double fraction, left [4], right [4], icoeff ;
560 increment_t filter_index, max_filter_index ;
561 int data_index, coeff_count, indx ;
562
563 /* Convert input parameters into fixed point. */
564 max_filter_index = int_to_fp (filter->coeff_half_len) ;
565
566 /* First apply the left half of the filter. */
567 filter_index = start_filter_index ;
568 coeff_count = (max_filter_index - filter_index) / increment ;
569 filter_index = filter_index + coeff_count * increment ;
570 data_index = filter->b_current - filter->channels * coeff_count ;
571
572 left [0] = left [1] = left [2] = left [3] = 0.0 ;
573 do
574 { fraction = fp_to_double (filter_index) ;
575 indx = fp_to_int (filter_index) ;
576
577 icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;
578
579 left [0] += icoeff * filter->buffer [data_index] ;
580 left [1] += icoeff * filter->buffer [data_index + 1] ;
581 left [2] += icoeff * filter->buffer [data_index + 2] ;
582 left [3] += icoeff * filter->buffer [data_index + 3] ;
583
584 filter_index -= increment ;
585 data_index = data_index + 4 ;
586 }
587 while (filter_index >= MAKE_INCREMENT_T (0)) ;
588
589 /* Now apply the right half of the filter. */
590 filter_index = increment - start_filter_index ;
591 coeff_count = (max_filter_index - filter_index) / increment ;
592 filter_index = filter_index + coeff_count * increment ;
593 data_index = filter->b_current + filter->channels * (1 + coeff_count) ;
594
595 right [0] = right [1] = right [2] = right [3] = 0.0 ;
596 do
597 { fraction = fp_to_double (filter_index) ;
598 indx = fp_to_int (filter_index) ;
599
600 icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;
601
602 right [0] += icoeff * filter->buffer [data_index] ;
603 right [1] += icoeff * filter->buffer [data_index + 1] ;
604 right [2] += icoeff * filter->buffer [data_index + 2] ;
605 right [3] += icoeff * filter->buffer [data_index + 3] ;
606
607 filter_index -= increment ;
608 data_index = data_index - filter->channels ;
609 }
610 while (filter_index > MAKE_INCREMENT_T (0)) ;
611
612 output [0] = scale * (left [0] + right [0]) ;
613 output [1] = scale * (left [1] + right [1]) ;
614 output [2] = scale * (left [2] + right [2]) ;
615 output [3] = scale * (left [3] + right [3]) ;
616} /* calc_output_quad */
447 617
448static int618static int
449sinc_multichan_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data)619sinc_quad_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data)
450{ SINC_FILTER *filter ;620{ SINC_FILTER *filter ;
451 double input_index, src_ratio, count, float_increment, terminate, rem ;621 double input_index, src_ratio, count, float_increment, terminate, rem ;
452 increment_t increment, start_filter_index ;622 increment_t increment, start_filter_index ;
453 int half_filter_chan_len, samples_in_hand, ch ;623 int half_filter_chan_len, samples_in_hand ;
454 624
455 if (psrc->private_data == NULL)625 if (psrc->private_data == NULL)
456 return SRC_ERR_NO_PRIVATE ;626 return SRC_ERR_NO_PRIVATE ;
@@ -515,12 +685,162 @@ sinc_multichan_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) · 58 unmodified lines
515 685
516 start_filter_index = double_to_fp (input_index * float_increment) ;686 start_filter_index = double_to_fp (input_index * float_increment) ;
517 687
518 for (ch = 0 ; ch < filter->channels ; ch++)688 calc_output_quad (filter, increment, start_filter_index, float_increment / filter->index_inc, data->data_out + filter->out_gen) ;
519 { data->data_out [filter->out_gen] = (float) ((float_increment / filter->index_inc) *689 filter->out_gen += 4 ;
520 calc_output_multi (filter, increment, start_filter_index, ch)) ;690
521 filter->out_gen ++ ;691 /* Figure out the next index. */
692 input_index += 1.0 / src_ratio ;
693 rem = fmod_one (input_index) ;
694
695 filter->b_current = (filter->b_current + filter->channels * lrint (input_index - rem)) % filter->b_len ;
696 input_index = rem ;
697 } ;
698
699 psrc->last_position = input_index ;
700
701 /* Save current ratio rather then target ratio. */
702 psrc->last_ratio = src_ratio ;
703
704 data->input_frames_used = filter->in_used / filter->channels ;
705 data->output_frames_gen = filter->out_gen / filter->channels ;
706
707 return SRC_ERR_NO_ERROR ;
708} /* sinc_quad_vari_process */
709
710static inline void
711calc_output_multi (SINC_FILTER *filter, increment_t increment, increment_t start_filter_index, int channels, double scale, float * output)
712{ double fraction, left [channels], right [channels], icoeff ;
713 increment_t filter_index, max_filter_index ;
714 int data_index, coeff_count, indx, ch ;
715
716 /* Convert input parameters into fixed point. */
717 max_filter_index = int_to_fp (filter->coeff_half_len) ;
718
719 /* First apply the left half of the filter. */
720 filter_index = start_filter_index ;
721 coeff_count = (max_filter_index - filter_index) / increment ;
722 filter_index = filter_index + coeff_count * increment ;
723 data_index = filter->b_current - channels * coeff_count ;
724
725 memset (left, 0, sizeof (left)) ;
726
727 do
728 { fraction = fp_to_double (filter_index) ;
729 indx = fp_to_int (filter_index) ;
730
731 icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;
732
733 ch = channels ;
734 while (-- ch >= 0)
735 left [ch] += icoeff * filter->buffer [data_index + ch] ;
736
737 filter_index -= increment ;
738 data_index = data_index + channels ;
739 }
740 while (filter_index >= MAKE_INCREMENT_T (0)) ;
741
742 /* Now apply the right half of the filter. */
743 filter_index = increment - start_filter_index ;
744 coeff_count = (max_filter_index - filter_index) / increment ;
745 filter_index = filter_index + coeff_count * increment ;
746 data_index = filter->b_current + channels * (1 + coeff_count) ;
747
748 memset (right, 0, sizeof (right)) ;
749 do
750 { fraction = fp_to_double (filter_index) ;
751 indx = fp_to_int (filter_index) ;
752
753 icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;
754
755 ch = channels ;
756 while (-- ch >= 0)
757 right [ch] += icoeff * filter->buffer [data_index + ch] ;
758
759 filter_index -= increment ;
760 data_index = data_index - channels ;
761 }
762 while (filter_index > MAKE_INCREMENT_T (0)) ;
763
764 ch = channels ;
765 while (-- ch >= 0)
766 output [ch] = scale * (left [ch] + right [ch]) ;
767
768 return ;
769} /* calc_output_multi */
770
771static int
772sinc_multichan_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data)
773{ SINC_FILTER *filter ;
774 double input_index, src_ratio, count, float_increment, terminate, rem ;
775 increment_t increment, start_filter_index ;
776 int half_filter_chan_len, samples_in_hand ;
777
778 if (psrc->private_data == NULL)
779 return SRC_ERR_NO_PRIVATE ;
780
781 filter = (SINC_FILTER*) psrc->private_data ;
782
783 /* If there is not a problem, this will be optimised out. */
784 if (sizeof (filter->buffer [0]) != sizeof (data->data_in [0]))
785 return SRC_ERR_SIZE_INCOMPATIBILITY ;
786
787 filter->in_count = data->input_frames * filter->channels ;
788 filter->out_count = data->output_frames * filter->channels ;
789 filter->in_used = filter->out_gen = 0 ;
790
791 src_ratio = psrc->last_ratio ;
792
793 /* Check the sample rate ratio wrt the buffer len. */
794 count = (filter->coeff_half_len + 2.0) / filter->index_inc ;
795 if (MIN (psrc->last_ratio, data->src_ratio) < 1.0)
796 count /= MIN (psrc->last_ratio, data->src_ratio) ;
797
798 /* Maximum coefficientson either side of center point. */
799 half_filter_chan_len = filter->channels * (lrint (count) + 1) ;
800
801 input_index = psrc->last_position ;
802 float_increment = filter->index_inc ;
803
804 rem = fmod_one (input_index) ;
805 filter->b_current = (filter->b_current + filter->channels * lrint (input_index - rem)) % filter->b_len ;
806 input_index = rem ;
807
808 terminate = 1.0 / src_ratio + 1e-20 ;
809
810 /* Main processing loop. */
811 while (filter->out_gen < filter->out_count)
812 {
813 /* Need to reload buffer? */
814 samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ;
815
816 if (samples_in_hand <= half_filter_chan_len)
817 { prepare_data (filter, data, half_filter_chan_len) ;
818
819 samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ;
820 if (samples_in_hand <= half_filter_chan_len)
821 break ;
822 } ;
823
824 /* This is the termination condition. */
825 if (filter->b_real_end >= 0)
826 { if (filter->b_current + input_index + terminate >= filter->b_real_end)
827 break ;
522 } ;828 } ;
523 829
830 if (filter->out_count > 0 && fabs (psrc->last_ratio - data->src_ratio) > 1e-10)
831 src_ratio = psrc->last_ratio + filter->out_gen * (data->src_ratio - psrc->last_ratio) / filter->out_count ;
832
833 float_increment = filter->index_inc * 1.0 ;
834 if (src_ratio < 1.0)
835 float_increment = filter->index_inc * src_ratio ;
836
837 increment = double_to_fp (float_increment) ;
838
839 start_filter_index = double_to_fp (input_index * float_increment) ;
840
841 calc_output_multi (filter, increment, start_filter_index, filter->channels, float_increment / filter->index_inc, data->data_out + filter->out_gen) ;
842 filter->out_gen += psrc->channels ;
843
524 /* Figure out the next index. */844 /* Figure out the next index. */
525 input_index += 1.0 / src_ratio ;845 input_index += 1.0 / src_ratio ;
526 rem = fmod_one (input_index) ;846 rem = fmod_one (input_index) ;
tests/Makefile.am+10−5
@@ -1,7 +1,8 @@
1noinst_PROGRAMS = misc_test termination_test simple_test callback_test \1noinst_PROGRAMS = misc_test termination_test simple_test callback_test \
2 reset_test multi_channel_test snr_bw_test \2 reset_test multi_channel_test snr_bw_test \
3 float_short_test varispeed_test callback_hang_test \3 float_short_test varispeed_test callback_hang_test \
4 src-evaluate throughput_test downsample_test4 src-evaluate throughput_test multichan_throughput_test \
5 downsample_test
5 6
6SAMPLRATEDIR =../src7SAMPLRATEDIR =../src
7INCLUDES = -I$(srcdir)/$(SAMPLRATEDIR)8INCLUDES = -I$(srcdir)/$(SAMPLRATEDIR)
@@ -48,14 +49,18 @@ varispeed_test_LDADD = $(SAMPLRATEDIR)/libsamplerate.la $(FFTW3_LIBS) · 40 unmodified lines
48 49
49# This program is for evaluating other sample rate converters.50# This program is for evaluating other sample rate converters.
50 51
51src_evaluate_SOURCES = src-evaluate.c calc_snr.c util.c
52src_evaluate_CFLAGS = @SNDFILE_CFLAGS@ @FFTW3_CFLAGS@
53src_evaluate_LDADD = $(SNDFILE_LIBS) $(FFTW3_LIBS)
54
55throughput_test_CFLAGS = $(AM_CFLAGS) @FFTW3_CFLAGS@52throughput_test_CFLAGS = $(AM_CFLAGS) @FFTW3_CFLAGS@
56throughput_test_SOURCES = throughput_test.c util.c calc_snr.c53throughput_test_SOURCES = throughput_test.c util.c calc_snr.c
57throughput_test_LDADD = $(SAMPLRATEDIR)/libsamplerate.la $(FFTW3_LIBS)54throughput_test_LDADD = $(SAMPLRATEDIR)/libsamplerate.la $(FFTW3_LIBS)
58 55
56multichan_throughput_test_CFLAGS = $(AM_CFLAGS) @FFTW3_CFLAGS@
57multichan_throughput_test_SOURCES = multichan_throughput_test.c util.c calc_snr.c
58multichan_throughput_test_LDADD = $(SAMPLRATEDIR)/libsamplerate.la $(FFTW3_LIBS)
59
60src_evaluate_SOURCES = src-evaluate.c calc_snr.c util.c
61src_evaluate_CFLAGS = @SNDFILE_CFLAGS@ @FFTW3_CFLAGS@
62src_evaluate_LDADD = $(SNDFILE_LIBS) $(FFTW3_LIBS)
63
59#===============================================================================64#===============================================================================
60 65
61check: $(noinst_PROGRAMS)66check: $(noinst_PROGRAMS)
tests/multi_channel_test.c+59−37
@@ -22,52 +22,68 @@ · 21 unmodified lines
22#include <stdlib.h>22#include <stdlib.h>
23#include <string.h>23#include <string.h>
24#include <math.h>24#include <math.h>
25#include <assert.h>
25 26
26#include <samplerate.h>27#include <samplerate.h>
27 28
28#include "util.h"29#include "util.h"
29#define BUFFER_LEN (1<<15)30#define BUFFER_LEN 50000
30#define BLOCK_LEN (12)31#define BLOCK_LEN (12)
31 32
33#define MAX_CHANNELS 4
34
32static void simple_test (int converter, int channel_count, double target_snr) ;35static void simple_test (int converter, int channel_count, double target_snr) ;
33static void process_test (int converter, int channel_count, double target_snr) ;36static void process_test (int converter, int channel_count, double target_snr) ;
34static void callback_test (int converter, int channel_count, double target_snr) ;37static void callback_test (int converter, int channel_count, double target_snr) ;
35 38
36int39int
37main (void)40main (void)
38{41{ double target ;
42
39 puts ("\n Zero Order Hold interpolator :") ;43 puts ("\n Zero Order Hold interpolator :") ;
40 simple_test (SRC_ZERO_ORDER_HOLD, 1, 45.0) ;44 target = 38.0 ;
41 process_test (SRC_ZERO_ORDER_HOLD, 1, 45.0) ;45 simple_test (SRC_ZERO_ORDER_HOLD, 1, target) ;
42 callback_test (SRC_ZERO_ORDER_HOLD, 1, 45.0) ;46 process_test (SRC_ZERO_ORDER_HOLD, 1, target) ;
43 simple_test (SRC_ZERO_ORDER_HOLD, 2, 44.0) ;47 callback_test (SRC_ZERO_ORDER_HOLD, 1, target) ;
44 process_test (SRC_ZERO_ORDER_HOLD, 2, 44.0) ;48 simple_test (SRC_ZERO_ORDER_HOLD, 2, target) ;
45 callback_test (SRC_ZERO_ORDER_HOLD, 2, 44.0) ;49 process_test (SRC_ZERO_ORDER_HOLD, 2, target) ;
46 simple_test (SRC_ZERO_ORDER_HOLD, 3, 44.0) ;50 callback_test (SRC_ZERO_ORDER_HOLD, 2, target) ;
47 process_test (SRC_ZERO_ORDER_HOLD, 3, 44.0) ;51 simple_test (SRC_ZERO_ORDER_HOLD, 3, target) ;
48 callback_test (SRC_ZERO_ORDER_HOLD, 3, 44.0) ;52 process_test (SRC_ZERO_ORDER_HOLD, 3, target) ;
53 callback_test (SRC_ZERO_ORDER_HOLD, 3, target) ;
54 simple_test (SRC_ZERO_ORDER_HOLD, 4, target) ;
55 process_test (SRC_ZERO_ORDER_HOLD, 4, target) ;
56 callback_test (SRC_ZERO_ORDER_HOLD, 4, target) ;
49 57
50 puts ("\n Linear interpolator :") ;58 puts ("\n Linear interpolator :") ;
51 simple_test (SRC_LINEAR, 1, 92.0) ;59 target = 79.0 ;
52 process_test (SRC_LINEAR, 1, 92.0) ;60 simple_test (SRC_LINEAR, 1, target) ;
53 callback_test (SRC_LINEAR, 1, 92.0) ;61 process_test (SRC_LINEAR, 1, target) ;
54 simple_test (SRC_LINEAR, 2, 90.0) ;62 callback_test (SRC_LINEAR, 1, target) ;
55 process_test (SRC_LINEAR, 2, 90.0) ;63 simple_test (SRC_LINEAR, 2, target) ;
56 callback_test (SRC_LINEAR, 2, 90.0) ;64 process_test (SRC_LINEAR, 2, target) ;
57 simple_test (SRC_LINEAR, 3, 88.0) ;65 callback_test (SRC_LINEAR, 2, target) ;
58 process_test (SRC_LINEAR, 3, 88.0) ;66 simple_test (SRC_LINEAR, 3, target) ;
59 callback_test (SRC_LINEAR, 3, 88.0) ;67 process_test (SRC_LINEAR, 3, target) ;
68 callback_test (SRC_LINEAR, 3, target) ;
69 simple_test (SRC_LINEAR, 4, target) ;
70 process_test (SRC_LINEAR, 4, target) ;
71 callback_test (SRC_LINEAR, 4, target) ;
60 72
61 puts ("\n Sinc interpolator :") ;73 puts ("\n Sinc interpolator :") ;
62 simple_test (SRC_SINC_FASTEST, 1, 100.0) ;74 target = 100.0 ;
63 process_test (SRC_SINC_FASTEST, 1, 100.0) ;75 simple_test (SRC_SINC_FASTEST, 1, target) ;
64 callback_test (SRC_SINC_FASTEST, 1, 100.0) ;76 process_test (SRC_SINC_FASTEST, 1, target) ;
65 simple_test (SRC_SINC_FASTEST, 2, 100.0) ;77 callback_test (SRC_SINC_FASTEST, 1, target) ;
66 process_test (SRC_SINC_FASTEST, 2, 100.0) ;78 simple_test (SRC_SINC_FASTEST, 2, target) ;
67 callback_test (SRC_SINC_FASTEST, 2, 100.0) ;79 process_test (SRC_SINC_FASTEST, 2, target) ;
68 simple_test (SRC_SINC_FASTEST, 3, 100.0) ;80 callback_test (SRC_SINC_FASTEST, 2, target) ;
69 process_test (SRC_SINC_FASTEST, 3, 100.0) ;81 simple_test (SRC_SINC_FASTEST, 3, target) ;
70 callback_test (SRC_SINC_FASTEST, 3, 100.0) ;82 process_test (SRC_SINC_FASTEST, 3, target) ;
83 callback_test (SRC_SINC_FASTEST, 3, target) ;
84 simple_test (SRC_SINC_FASTEST, 4, target) ;
85 process_test (SRC_SINC_FASTEST, 4, target) ;
86 callback_test (SRC_SINC_FASTEST, 4, target) ;
71 87
72 puts ("") ;88 puts ("") ;
73 89
@@ -77,10 +93,10 @@ main (void) · 3 unmodified lines
77/*==============================================================================93/*==============================================================================
78*/94*/
79 95
80static float input_serial [BUFFER_LEN] ;96static float input_serial [BUFFER_LEN * MAX_CHANNELS] ;
81static float input_interleaved [BUFFER_LEN] ;97static float input_interleaved [BUFFER_LEN * MAX_CHANNELS] ;
82static float output_interleaved [BUFFER_LEN] ;98static float output_interleaved [BUFFER_LEN * MAX_CHANNELS] ;
83static float output_serial [BUFFER_LEN] ;99static float output_serial [BUFFER_LEN * MAX_CHANNELS] ;
84 100
85static void101static void
86simple_test (int converter, int channel_count, double target_snr)102simple_test (int converter, int channel_count, double target_snr)
@@ -92,12 +108,14 @@ simple_test (int converter, int channel_count, double target_snr) · 5 unmodified lines
92 printf ("\t%-22s (%d channel%c) ............. ", "simple_test", channel_count, channel_count > 1 ? 's' : ' ') ;108 printf ("\t%-22s (%d channel%c) ............. ", "simple_test", channel_count, channel_count > 1 ? 's' : ' ') ;
93 fflush (stdout) ;109 fflush (stdout) ;
94 110
111 assert (channel_count <= MAX_CHANNELS) ;
112
95 memset (input_serial, 0, sizeof (input_serial)) ;113 memset (input_serial, 0, sizeof (input_serial)) ;
96 memset (input_interleaved, 0, sizeof (input_interleaved)) ;114 memset (input_interleaved, 0, sizeof (input_interleaved)) ;
97 memset (output_interleaved, 0, sizeof (output_interleaved)) ;115 memset (output_interleaved, 0, sizeof (output_interleaved)) ;
98 memset (output_serial, 0, sizeof (output_serial)) ;116 memset (output_serial, 0, sizeof (output_serial)) ;
99 117
100 frames = MIN (ARRAY_LEN (input_serial) / channel_count, 1 << 16) ;118 frames = BUFFER_LEN ;
101 119
102 /* Calculate channel_count separate windowed sine waves. */120 /* Calculate channel_count separate windowed sine waves. */
103 for (ch = 0 ; ch < channel_count ; ch++)121 for (ch = 0 ; ch < channel_count ; ch++)
@@ -162,16 +180,18 @@ process_test (int converter, int channel_count, double target_snr) · 58 unmodified lines
162 printf ("\t%-22s (%d channel%c) ............. ", "process_test", channel_count, channel_count > 1 ? 's' : ' ') ;180 printf ("\t%-22s (%d channel%c) ............. ", "process_test", channel_count, channel_count > 1 ? 's' : ' ') ;
163 fflush (stdout) ;181 fflush (stdout) ;
164 182
183 assert (channel_count <= MAX_CHANNELS) ;
184
165 memset (input_serial, 0, sizeof (input_serial)) ;185 memset (input_serial, 0, sizeof (input_serial)) ;
166 memset (input_interleaved, 0, sizeof (input_interleaved)) ;186 memset (input_interleaved, 0, sizeof (input_interleaved)) ;
167 memset (output_interleaved, 0, sizeof (output_interleaved)) ;187 memset (output_interleaved, 0, sizeof (output_interleaved)) ;
168 memset (output_serial, 0, sizeof (output_serial)) ;188 memset (output_serial, 0, sizeof (output_serial)) ;
169 189
170 frames = MIN (ARRAY_LEN (input_serial) / channel_count, 1 << 16) ;190 frames = BUFFER_LEN ;
171 191
172 /* Calculate channel_count separate windowed sine waves. */192 /* Calculate channel_count separate windowed sine waves. */
173 for (ch = 0 ; ch < channel_count ; ch++)193 for (ch = 0 ; ch < channel_count ; ch++)
174 { freq = (200.0 + 33.333333333 * ch) / 44100.0 ;194 { freq = (400.0 + 11.333333333 * ch) / 44100.0 ;
175 gen_windowed_sines (1, &freq, 1.0, input_serial + ch * frames, frames) ;195 gen_windowed_sines (1, &freq, 1.0, input_serial + ch * frames, frames) ;
176 } ;196 } ;
177 197
@@ -288,13 +308,15 @@ callback_test (int converter, int channel_count, double target_snr) · 110 unmodified lines
288 printf ("\t%-22s (%d channel%c) ............. ", "callback_test", channel_count, channel_count > 1 ? 's' : ' ') ;308 printf ("\t%-22s (%d channel%c) ............. ", "callback_test", channel_count, channel_count > 1 ? 's' : ' ') ;
289 fflush (stdout) ;309 fflush (stdout) ;
290 310
311 assert (channel_count <= MAX_CHANNELS) ;
312
291 memset (input_serial, 0, sizeof (input_serial)) ;313 memset (input_serial, 0, sizeof (input_serial)) ;
292 memset (input_interleaved, 0, sizeof (input_interleaved)) ;314 memset (input_interleaved, 0, sizeof (input_interleaved)) ;
293 memset (output_interleaved, 0, sizeof (output_interleaved)) ;315 memset (output_interleaved, 0, sizeof (output_interleaved)) ;
294 memset (output_serial, 0, sizeof (output_serial)) ;316 memset (output_serial, 0, sizeof (output_serial)) ;
295 memset (&test_callback_data, 0, sizeof (test_callback_data)) ;317 memset (&test_callback_data, 0, sizeof (test_callback_data)) ;
296 318
297 frames = MIN (ARRAY_LEN (input_serial) / channel_count, 1 << 16) ;319 frames = BUFFER_LEN ;
298 320
299 /* Calculate channel_count separate windowed sine waves. */321 /* Calculate channel_count separate windowed sine waves. */
300 for (ch = 0 ; ch < channel_count ; ch++)322 for (ch = 0 ; ch < channel_count ; ch++)
tests/multichan_throughput_test.c+217−0
@@ -0,0 +1,217 @@
1/*
2** Copyright (C) 2008 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#include <stdio.h>
20#include <stdlib.h>
21#include <string.h>
22#include <time.h>
23#include <unistd.h>
24
25#include <samplerate.h>
26
27#include "config.h"
28
29#include "util.h"
30#include "float_cast.h"
31
32#define BUFFER_LEN (1<<17)
33
34static float input [BUFFER_LEN] ;
35static float output [BUFFER_LEN] ;
36
37static long
38throughput_test (int converter, int channels, long best_throughput)
39{ SRC_DATA src_data ;
40 clock_t start_time, clock_time ;
41 double duration ;
42 long total_frames = 0, throughput ;
43 int error ;
44
45 printf (" %-30s %2d ", src_get_name (converter), channels) ;
46 fflush (stdout) ;
47
48 src_data.data_in = input ;
49 src_data.input_frames = ARRAY_LEN (input) / channels ;
50
51 src_data.data_out = output ;
52 src_data.output_frames = ARRAY_LEN (output) / channels ;
53
54 src_data.src_ratio = 0.99 ;
55
56 sleep (2) ;
57
58 start_time = clock () ;
59
60 do
61 {
62 if ((error = src_simple (&src_data, converter, channels)) != 0)
63 { puts (src_strerror (error)) ;
64 exit (1) ;
65 } ;
66
67 total_frames += src_data.output_frames_gen ;
68
69 clock_time = clock () - start_time ;
70 duration = (1.0 * clock_time) / CLOCKS_PER_SEC ;
71 }
72 while (duration < 5.0) ;
73
74 if (src_data.input_frames_used != src_data.input_frames)
75 { printf ("\n\nLine %d : input frames used %ld should be %ld\n", __LINE__, src_data.input_frames_used, src_data.input_frames) ;
76 exit (1) ;
77 } ;
78
79 if (fabs (src_data.src_ratio * src_data.input_frames_used - src_data.output_frames_gen) > 2)
80 { printf ("\n\nLine %d : input / output length mismatch.\n\n", __LINE__) ;
81 printf (" input len : %d\n", ARRAY_LEN (input) / channels) ;
82 printf (" output len : %ld (should be %g +/- 2)\n\n", src_data.output_frames_gen,
83 floor (0.5 + src_data.src_ratio * src_data.input_frames_used)) ;
84 exit (1) ;
85 } ;
86
87 throughput = lrint (floor (total_frames / duration)) ;
88
89 if (best_throughput == 0)
90 { best_throughput = MAX (throughput, best_throughput) ;
91 printf ("%5.2f %10ld\n", duration, throughput) ;
92 }
93 else
94 { best_throughput = MAX (throughput, best_throughput) ;
95 printf ("%5.2f %10ld %10ld\n", duration, throughput, best_throughput) ;
96 }
97
98 return best_throughput ;
99} /* throughput_test */
100
101static void
102single_run (void)
103{ int k ;
104
105 printf ("\n CPU : ") ;
106 print_cpu_name () ;
107
108 puts (
109 "\n"
110 " Converter Channels Duration Throughput\n"
111 " ---------------------------------------------------------------------"
112 ) ;
113
114 for (k = 1 ; k <= 5 ; k++)
115 throughput_test (SRC_SINC_FASTEST, k, 0) ;
116
117 puts ("") ;
118 for (k = 1 ; k <= 5 ; k++)
119 throughput_test (SRC_SINC_MEDIUM_QUALITY, k, 0) ;
120
121 puts ("") ;
122 for (k = 1 ; k <= 5 ; k++)
123 throughput_test (SRC_SINC_BEST_QUALITY, k, 0) ;
124
125 puts ("") ;
126 return ;
127} /* single_run */
128
129static void
130multi_run (int run_count)
131{ int k, ch ;
132
133 printf ("\n CPU name : ") ;
134 print_cpu_name () ;
135
136 puts (
137 "\n"
138 " Converter Channels Duration Throughput Best Throughput\n"
139 " ----------------------------------------------------------------------------------------"
140 ) ;
141
142 for (ch = 1 ; ch <= 5 ; ch++)
143 { long sinc_fastest = 0, sinc_medium = 0, sinc_best = 0 ;
144
145 for (k = 0 ; k < run_count ; k++)
146 { sinc_fastest = throughput_test (SRC_SINC_FASTEST, ch, sinc_fastest) ;
147 sinc_medium = throughput_test (SRC_SINC_MEDIUM_QUALITY, ch, sinc_medium) ;
148 sinc_best = throughput_test (SRC_SINC_BEST_QUALITY, ch, sinc_best) ;
149
150 puts ("") ;
151
152 /* Let the CPU cool down. We might be running on a laptop. */
153 sleep (10) ;
154 } ;
155
156 puts (
157 "\n"
158 " Converter Best Throughput\n"
159 " ------------------------------------------------"
160 ) ;
161
162 printf (" %-30s %10ld\n", src_get_name (SRC_SINC_FASTEST), sinc_fastest) ;
163 printf (" %-30s %10ld\n", src_get_name (SRC_SINC_MEDIUM_QUALITY), sinc_medium) ;
164 printf (" %-30s %10ld\n", src_get_name (SRC_SINC_BEST_QUALITY), sinc_best) ;
165 } ;
166
167 puts ("") ;
168} /* multi_run */
169
170static void
171usage_exit (const char * argv0)
172{ const char * cptr ;
173
174 if ((cptr = strrchr (argv0, '/')) != NULL)
175 argv0 = cptr ;
176
177 printf (
178 "Usage :\n"
179 " %s - Single run of the throughput test.\n"
180 " %s --best-of N - Do N runs of test a print bext result.\n"
181 "\n",
182 argv0, argv0) ;
183
184 exit (0) ;
185} /* usage_exit */
186
187int
188main (int argc, char ** argv)
189{ double freq ;
190
191 memset (input, 0, sizeof (input)) ;
192 freq = 0.01 ;
193 gen_windowed_sines (1, &freq, 1.0, input, BUFFER_LEN) ;
194
195 if (argc == 1)
196 single_run () ;
197 else if (argc == 3 && strcmp (argv [1], "--best-of") == 0)
198 { int run_count = atoi (argv [2]) ;
199
200 if (run_count < 1 || run_count > 20)
201 { printf ("Please be sensible. Run count should be in range (1, 10].\n") ;
202 exit (1) ;
203 } ;
204
205 multi_run (run_count) ;
206 }
207 else
208 usage_exit (argv [0]) ;
209
210 puts (
211 " Duration is in seconds.\n"
212 " Throughput is in frames/sec (more is better).\n"
213 ) ;
214
215 return 0 ;
216} /* main */
217

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t