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 @@
1+2008-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+
110 2008-12-12 Erik de Castro Lopo <erikd AT mega-nerd DOT com>
211
312 * src/samplerate.c examples/audio_out.c tests/*.c
@@ -8,6 +17,9 @@ · 4 unmodified lines
817 Fix a potential memory leak. Thanks to Peter G. Vavaroutsos for point this
918 out.
1019
20+ * tests/multi_channel_test.c
21+ Robustify test.
22+
1123 2008-12-11 Erik de Castro Lopo <erikd AT mega-nerd DOT com>
1224
1325 * reconfigure.mk autogen.sh
@@ -16,6 +28,9 @@ · 2 unmodified lines
1628 * configure.ac
1729 Various updates.
1830
31+ * tests/multichan_throughput_test.c tests/Makefile.am
32+ Add new test and hook into build.
33+
1934 2008-11-11 Erik de Castro Lopo <erikd AT mega-nerd DOT com>
2035
2136 * doc/index.html
src/src_sinc.c+347−27
@@ -65,11 +65,15 @@ typedef struct · 64 unmodified lines
6565 coeff_t const *coeffs ;
6666
6767 int b_current, b_end, b_real_end, b_len ;
68− float buffer [1] ;
68+
69+ /* C99 struct flexible array. */
70+ float buffer [] ;
6971 } SINC_FILTER ;
7072
7173 static int sinc_multichan_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) ;
72−static int sinc_1chan_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) ;
74+static int sinc_quad_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) ;
75+static int sinc_stereo_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) ;
76+static int sinc_mono_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) ;
7377
7478 static void prepare_data (SINC_FILTER *filter, SRC_DATA *data, int half_filter_chan_len) ;
7579
@@ -164,8 +168,18 @@ sinc_set_converter (SRC_PRIVATE *psrc, int src_enum) · 88 unmodified lines
164168 temp_filter.channels = psrc->channels ;
165169
166170 if (psrc->channels == 1)
167− { psrc->const_process = sinc_1chan_vari_process ;
168− psrc->vari_process = sinc_1chan_vari_process ;
171+ { psrc->const_process = sinc_mono_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 ;
169183 }
170184 else
171185 { 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
300314 return (left + right) ;
301315 } /* calc_output_single */
302316
303−static inline double
304−calc_output_multi (SINC_FILTER *filter, increment_t increment, increment_t start_filter_index, int ch)
305−{ double fraction, left, right, icoeff ;
317+static int
318+sinc_mono_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data)
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+
410+static inline void
411+calc_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 ;
306413 increment_t filter_index, max_filter_index ;
307414 int data_index, coeff_count, indx ;
308415
@@ -313,19 +420,20 @@ calc_output_multi (SINC_FILTER *filter, increment_t increment, increment_t start · 4 unmodified lines
313420 filter_index = start_filter_index ;
314421 coeff_count = (max_filter_index - filter_index) / increment ;
315422 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 ;
317424
318− left = 0.0 ;
425+ left [0] = left [1] = 0.0 ;
319426 do
320427 { fraction = fp_to_double (filter_index) ;
321428 indx = fp_to_int (filter_index) ;
322429
323430 icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;
324431
325− left += icoeff * filter->buffer [data_index] ;
432+ left [0] += icoeff * filter->buffer [data_index] ;
433+ left [1] += icoeff * filter->buffer [data_index + 1] ;
326434
327435 filter_index -= increment ;
328− data_index = data_index + filter->channels ;
436+ data_index = data_index + 2 ;
329437 }
330438 while (filter_index >= MAKE_INCREMENT_T (0)) ;
331439
@@ -333,27 +441,29 @@ calc_output_multi (SINC_FILTER *filter, increment_t increment, increment_t start · 1 unmodified line
333441 filter_index = increment - start_filter_index ;
334442 coeff_count = (max_filter_index - filter_index) / increment ;
335443 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) ;
337445
338− right = 0.0 ;
446+ right [0] = right [1] = 0.0 ;
339447 do
340448 { fraction = fp_to_double (filter_index) ;
341449 indx = fp_to_int (filter_index) ;
342450
343451 icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;
344452
345− right += icoeff * filter->buffer [data_index] ;
453+ right [0] += icoeff * filter->buffer [data_index] ;
454+ right [1] += icoeff * filter->buffer [data_index + 1] ;
346455
347456 filter_index -= increment ;
348457 data_index = data_index - filter->channels ;
349458 }
350459 while (filter_index > MAKE_INCREMENT_T (0)) ;
351460
352− return (left + right) ;
353−} /* calc_output_multi */
461+ output [0] = scale * (left [0] + right [0]) ;
462+ output [1] = scale * (left [1] + right [1]) ;
463+} /* calc_output_stereo */
354464
355465 static int
356−sinc_1chan_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data)
466+sinc_stereo_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data)
357467 { SINC_FILTER *filter ;
358468 double input_index, src_ratio, count, float_increment, terminate, rem ;
359469 increment_t increment, start_filter_index ;
@@ -422,9 +532,8 @@ sinc_1chan_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) · 62 unmodified lines
422532
423533 start_filter_index = double_to_fp (input_index * float_increment) ;
424534
425− data->data_out [filter->out_gen] = (float) ((float_increment / filter->index_inc) *
426− calc_output_single (filter, increment, start_filter_index)) ;
427− filter->out_gen ++ ;
535+ calc_output_stereo (filter, increment, start_filter_index, float_increment / filter->index_inc, data->data_out + filter->out_gen) ;
536+ filter->out_gen += 2 ;
428537
429538 /* Figure out the next index. */
430539 input_index += 1.0 / src_ratio ;
@@ -443,14 +552,75 @@ sinc_1chan_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) · 12 unmodified lines
443552 data->output_frames_gen = filter->out_gen / filter->channels ;
444553
445554 return SRC_ERR_NO_ERROR ;
446−} /* sinc_1chan_vari_process */
555+} /* sinc_stereo_vari_process */
556+
557+static inline void
558+calc_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 */
447617
448618 static int
449−sinc_multichan_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data)
619+sinc_quad_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data)
450620 { SINC_FILTER *filter ;
451621 double input_index, src_ratio, count, float_increment, terminate, rem ;
452622 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 ;
454624
455625 if (psrc->private_data == NULL)
456626 return SRC_ERR_NO_PRIVATE ;
@@ -515,12 +685,162 @@ sinc_multichan_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) · 58 unmodified lines
515685
516686 start_filter_index = double_to_fp (input_index * float_increment) ;
517687
518− for (ch = 0 ; ch < filter->channels ; ch++)
519− { data->data_out [filter->out_gen] = (float) ((float_increment / filter->index_inc) *
520− calc_output_multi (filter, increment, start_filter_index, ch)) ;
521− filter->out_gen ++ ;
688+ calc_output_quad (filter, increment, start_filter_index, float_increment / filter->index_inc, data->data_out + filter->out_gen) ;
689+ filter->out_gen += 4 ;
690+
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+
710+static inline void
711+calc_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+
771+static int
772+sinc_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 ;
522828 } ;
523829
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+
524844 /* Figure out the next index. */
525845 input_index += 1.0 / src_ratio ;
526846 rem = fmod_one (input_index) ;
tests/Makefile.am+10−5
@@ -1,7 +1,8 @@
11 noinst_PROGRAMS = misc_test termination_test simple_test callback_test \
22 reset_test multi_channel_test snr_bw_test \
33 float_short_test varispeed_test callback_hang_test \
4− src-evaluate throughput_test downsample_test
4+ src-evaluate throughput_test multichan_throughput_test \
5+ downsample_test
56
67 SAMPLRATEDIR =../src
78 INCLUDES = -I$(srcdir)/$(SAMPLRATEDIR)
@@ -48,14 +49,18 @@ varispeed_test_LDADD = $(SAMPLRATEDIR)/libsamplerate.la $(FFTW3_LIBS) · 40 unmodified lines
4849
4950 # This program is for evaluating other sample rate converters.
5051
51−src_evaluate_SOURCES = src-evaluate.c calc_snr.c util.c
52−src_evaluate_CFLAGS = @SNDFILE_CFLAGS@ @FFTW3_CFLAGS@
53−src_evaluate_LDADD = $(SNDFILE_LIBS) $(FFTW3_LIBS)
54−
5552 throughput_test_CFLAGS = $(AM_CFLAGS) @FFTW3_CFLAGS@
5653 throughput_test_SOURCES = throughput_test.c util.c calc_snr.c
5754 throughput_test_LDADD = $(SAMPLRATEDIR)/libsamplerate.la $(FFTW3_LIBS)
5855
56+multichan_throughput_test_CFLAGS = $(AM_CFLAGS) @FFTW3_CFLAGS@
57+multichan_throughput_test_SOURCES = multichan_throughput_test.c util.c calc_snr.c
58+multichan_throughput_test_LDADD = $(SAMPLRATEDIR)/libsamplerate.la $(FFTW3_LIBS)
59+
60+src_evaluate_SOURCES = src-evaluate.c calc_snr.c util.c
61+src_evaluate_CFLAGS = @SNDFILE_CFLAGS@ @FFTW3_CFLAGS@
62+src_evaluate_LDADD = $(SNDFILE_LIBS) $(FFTW3_LIBS)
63+
5964 #===============================================================================
6065
6166 check: $(noinst_PROGRAMS)
tests/multi_channel_test.c+59−37
@@ -22,52 +22,68 @@ · 21 unmodified lines
2222 #include <stdlib.h>
2323 #include <string.h>
2424 #include <math.h>
25+#include <assert.h>
2526
2627 #include <samplerate.h>
2728
2829 #include "util.h"
29−#define BUFFER_LEN (1<<15)
30+#define BUFFER_LEN 50000
3031 #define BLOCK_LEN (12)
3132
33+#define MAX_CHANNELS 4
34+
3235 static void simple_test (int converter, int channel_count, double target_snr) ;
3336 static void process_test (int converter, int channel_count, double target_snr) ;
3437 static void callback_test (int converter, int channel_count, double target_snr) ;
3538
3639 int
3740 main (void)
38−{
41+{ double target ;
42+
3943 puts ("\n Zero Order Hold interpolator :") ;
40− simple_test (SRC_ZERO_ORDER_HOLD, 1, 45.0) ;
41− process_test (SRC_ZERO_ORDER_HOLD, 1, 45.0) ;
42− callback_test (SRC_ZERO_ORDER_HOLD, 1, 45.0) ;
43− simple_test (SRC_ZERO_ORDER_HOLD, 2, 44.0) ;
44− process_test (SRC_ZERO_ORDER_HOLD, 2, 44.0) ;
45− callback_test (SRC_ZERO_ORDER_HOLD, 2, 44.0) ;
46− simple_test (SRC_ZERO_ORDER_HOLD, 3, 44.0) ;
47− process_test (SRC_ZERO_ORDER_HOLD, 3, 44.0) ;
48− callback_test (SRC_ZERO_ORDER_HOLD, 3, 44.0) ;
44+ target = 38.0 ;
45+ simple_test (SRC_ZERO_ORDER_HOLD, 1, target) ;
46+ process_test (SRC_ZERO_ORDER_HOLD, 1, target) ;
47+ callback_test (SRC_ZERO_ORDER_HOLD, 1, target) ;
48+ simple_test (SRC_ZERO_ORDER_HOLD, 2, target) ;
49+ process_test (SRC_ZERO_ORDER_HOLD, 2, target) ;
50+ callback_test (SRC_ZERO_ORDER_HOLD, 2, target) ;
51+ simple_test (SRC_ZERO_ORDER_HOLD, 3, target) ;
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) ;
4957
5058 puts ("\n Linear interpolator :") ;
51− simple_test (SRC_LINEAR, 1, 92.0) ;
52− process_test (SRC_LINEAR, 1, 92.0) ;
53− callback_test (SRC_LINEAR, 1, 92.0) ;
54− simple_test (SRC_LINEAR, 2, 90.0) ;
55− process_test (SRC_LINEAR, 2, 90.0) ;
56− callback_test (SRC_LINEAR, 2, 90.0) ;
57− simple_test (SRC_LINEAR, 3, 88.0) ;
58− process_test (SRC_LINEAR, 3, 88.0) ;
59− callback_test (SRC_LINEAR, 3, 88.0) ;
59+ target = 79.0 ;
60+ simple_test (SRC_LINEAR, 1, target) ;
61+ process_test (SRC_LINEAR, 1, target) ;
62+ callback_test (SRC_LINEAR, 1, target) ;
63+ simple_test (SRC_LINEAR, 2, target) ;
64+ process_test (SRC_LINEAR, 2, target) ;
65+ callback_test (SRC_LINEAR, 2, target) ;
66+ simple_test (SRC_LINEAR, 3, target) ;
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) ;
6072
6173 puts ("\n Sinc interpolator :") ;
62− simple_test (SRC_SINC_FASTEST, 1, 100.0) ;
63− process_test (SRC_SINC_FASTEST, 1, 100.0) ;
64− callback_test (SRC_SINC_FASTEST, 1, 100.0) ;
65− simple_test (SRC_SINC_FASTEST, 2, 100.0) ;
66− process_test (SRC_SINC_FASTEST, 2, 100.0) ;
67− callback_test (SRC_SINC_FASTEST, 2, 100.0) ;
68− simple_test (SRC_SINC_FASTEST, 3, 100.0) ;
69− process_test (SRC_SINC_FASTEST, 3, 100.0) ;
70− callback_test (SRC_SINC_FASTEST, 3, 100.0) ;
74+ target = 100.0 ;
75+ simple_test (SRC_SINC_FASTEST, 1, target) ;
76+ process_test (SRC_SINC_FASTEST, 1, target) ;
77+ callback_test (SRC_SINC_FASTEST, 1, target) ;
78+ simple_test (SRC_SINC_FASTEST, 2, target) ;
79+ process_test (SRC_SINC_FASTEST, 2, target) ;
80+ callback_test (SRC_SINC_FASTEST, 2, target) ;
81+ simple_test (SRC_SINC_FASTEST, 3, target) ;
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) ;
7187
7288 puts ("") ;
7389
@@ -77,10 +93,10 @@ main (void) · 3 unmodified lines
7793 /*==============================================================================
7894 */
7995
80−static float input_serial [BUFFER_LEN] ;
81−static float input_interleaved [BUFFER_LEN] ;
82−static float output_interleaved [BUFFER_LEN] ;
83−static float output_serial [BUFFER_LEN] ;
96+static float input_serial [BUFFER_LEN * MAX_CHANNELS] ;
97+static float input_interleaved [BUFFER_LEN * MAX_CHANNELS] ;
98+static float output_interleaved [BUFFER_LEN * MAX_CHANNELS] ;
99+static float output_serial [BUFFER_LEN * MAX_CHANNELS] ;
84100
85101 static void
86102 simple_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
92108 printf ("\t%-22s (%d channel%c) ............. ", "simple_test", channel_count, channel_count > 1 ? 's' : ' ') ;
93109 fflush (stdout) ;
94110
111+ assert (channel_count <= MAX_CHANNELS) ;
112+
95113 memset (input_serial, 0, sizeof (input_serial)) ;
96114 memset (input_interleaved, 0, sizeof (input_interleaved)) ;
97115 memset (output_interleaved, 0, sizeof (output_interleaved)) ;
98116 memset (output_serial, 0, sizeof (output_serial)) ;
99117
100− frames = MIN (ARRAY_LEN (input_serial) / channel_count, 1 << 16) ;
118+ frames = BUFFER_LEN ;
101119
102120 /* Calculate channel_count separate windowed sine waves. */
103121 for (ch = 0 ; ch < channel_count ; ch++)
@@ -162,16 +180,18 @@ process_test (int converter, int channel_count, double target_snr) · 58 unmodified lines
162180 printf ("\t%-22s (%d channel%c) ............. ", "process_test", channel_count, channel_count > 1 ? 's' : ' ') ;
163181 fflush (stdout) ;
164182
183+ assert (channel_count <= MAX_CHANNELS) ;
184+
165185 memset (input_serial, 0, sizeof (input_serial)) ;
166186 memset (input_interleaved, 0, sizeof (input_interleaved)) ;
167187 memset (output_interleaved, 0, sizeof (output_interleaved)) ;
168188 memset (output_serial, 0, sizeof (output_serial)) ;
169189
170− frames = MIN (ARRAY_LEN (input_serial) / channel_count, 1 << 16) ;
190+ frames = BUFFER_LEN ;
171191
172192 /* Calculate channel_count separate windowed sine waves. */
173193 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 ;
175195 gen_windowed_sines (1, &freq, 1.0, input_serial + ch * frames, frames) ;
176196 } ;
177197
@@ -288,13 +308,15 @@ callback_test (int converter, int channel_count, double target_snr) · 110 unmodified lines
288308 printf ("\t%-22s (%d channel%c) ............. ", "callback_test", channel_count, channel_count > 1 ? 's' : ' ') ;
289309 fflush (stdout) ;
290310
311+ assert (channel_count <= MAX_CHANNELS) ;
312+
291313 memset (input_serial, 0, sizeof (input_serial)) ;
292314 memset (input_interleaved, 0, sizeof (input_interleaved)) ;
293315 memset (output_interleaved, 0, sizeof (output_interleaved)) ;
294316 memset (output_serial, 0, sizeof (output_serial)) ;
295317 memset (&test_callback_data, 0, sizeof (test_callback_data)) ;
296318
297− frames = MIN (ARRAY_LEN (input_serial) / channel_count, 1 << 16) ;
319+ frames = BUFFER_LEN ;
298320
299321 /* Calculate channel_count separate windowed sine waves. */
300322 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+
34+static float input [BUFFER_LEN] ;
35+static float output [BUFFER_LEN] ;
36+
37+static long
38+throughput_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+
101+static void
102+single_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+
129+static void
130+multi_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+
170+static void
171+usage_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+
187+int
188+main (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