2 ** Copyright (c) 2002-2016, Erik de Castro Lopo <erikd@mega-nerd.com>
3 ** All rights reserved.
5 ** This code is released under 2-clause BSD license. Please see the
6 ** file at : https://github.com/erikd/libsamplerate/blob/master/COPYING
21 #include <samplerate.h>
25 #define BUFFER_LEN 50000
28 #define MAX_SPEC_LEN (1<<15)
31 #define M_PI 3.14159265358979323846264338
41 double freqs
[MAX_FREQS
] ;
53 int do_bandwidth_test
;
54 SINGLE_TEST test_data
[10] ;
57 static double snr_test (SINGLE_TEST
*snr_test_data
, int number
, int converter
, int verbose
) ;
58 static double find_peak (float *output
, int output_len
) ;
59 static double bandwidth_test (int converter
, int verbose
) ;
62 main (int argc
, char *argv
[])
63 { CONVERTER_TEST snr_test_data
[] =
65 { SRC_ZERO_ORDER_HOLD
,
68 { { 1, { 0.01111111111 }, 3.0, 1, 28.0, 1.0 },
69 { 1, { 0.01111111111 }, 0.6, 1, 36.0, 1.0 },
70 { 1, { 0.01111111111 }, 0.3, 1, 36.0, 1.0 },
71 { 1, { 0.01111111111 }, 1.0, 1, 150.0, 1.0 },
72 { 1, { 0.01111111111 }, 1.001, 1, 38.0, 1.0 },
73 { 2, { 0.011111, 0.324 }, 1.9999, 2, 14.0, 1.0 },
74 { 2, { 0.012345, 0.457 }, 0.456789, 1, 12.0, 1.0 },
75 { 1, { 0.3511111111 }, 1.33, 1, 10.0, 1.0 }
82 { { 1, { 0.01111111111 }, 3.0, 1, 73.0, 1.0 },
83 { 1, { 0.01111111111 }, 0.6, 1, 73.0, 1.0 },
84 { 1, { 0.01111111111 }, 0.3, 1, 73.0, 1.0 },
85 { 1, { 0.01111111111 }, 1.0, 1, 150.0, 1.0 },
86 { 1, { 0.01111111111 }, 1.001, 1, 77.0, 1.0 },
87 { 2, { 0.011111, 0.324 }, 1.9999, 2, 15.0, 0.94 },
88 { 2, { 0.012345, 0.457 }, 0.456789, 1, 25.0, 0.96 },
89 { 1, { 0.3511111111 }, 1.33, 1, 22.0, 0.99 }
96 { { 1, { 0.01111111111 }, 3.0, 1, 100.0, 1.0 },
97 { 1, { 0.01111111111 }, 0.6, 1, 99.0, 1.0 },
98 { 1, { 0.01111111111 }, 0.3, 1, 100.0, 1.0 },
99 { 1, { 0.01111111111 }, 1.0, 1, 150.0, 1.0 },
100 { 1, { 0.01111111111 }, 1.001, 1, 100.0, 1.0 },
101 { 2, { 0.011111, 0.324 }, 1.9999, 2, 97.0, 1.0 },
102 { 2, { 0.012345, 0.457 }, 0.456789, 1, 100.0, 0.5 },
103 { 2, { 0.011111, 0.45 }, 0.6, 1, 97.0, 0.5 },
104 { 1, { 0.3511111111 }, 1.33, 1, 97.0, 1.0 }
108 { SRC_SINC_MEDIUM_QUALITY
,
111 { { 1, { 0.01111111111 }, 3.0, 1, 145.0, 1.0 },
112 { 1, { 0.01111111111 }, 0.6, 1, 132.0, 1.0 },
113 { 1, { 0.01111111111 }, 0.3, 1, 138.0, 1.0 },
114 { 1, { 0.01111111111 }, 1.0, 1, 157.0, 1.0 },
115 { 1, { 0.01111111111 }, 1.001, 1, 148.0, 1.0 },
116 { 2, { 0.011111, 0.324 }, 1.9999, 2, 127.0, 1.0 },
117 { 2, { 0.012345, 0.457 }, 0.456789, 1, 123.0, 0.5 },
118 { 2, { 0.011111, 0.45 }, 0.6, 1, 126.0, 0.5 },
119 { 1, { 0.43111111111 }, 1.33, 1, 121.0, 1.0 }
123 { SRC_SINC_BEST_QUALITY
,
126 { { 1, { 0.01111111111 }, 3.0, 1, 147.0, 1.0 },
127 { 1, { 0.01111111111 }, 0.6, 1, 147.0, 1.0 },
128 { 1, { 0.01111111111 }, 0.3, 1, 148.0, 1.0 },
129 { 1, { 0.01111111111 }, 1.0, 1, 155.0, 1.0 },
130 { 1, { 0.01111111111 }, 1.001, 1, 148.0, 1.0 },
131 { 2, { 0.011111, 0.324 }, 1.9999, 2, 146.0, 1.0 },
132 { 2, { 0.012345, 0.457 }, 0.456789, 1, 147.0, 0.5 },
133 { 2, { 0.011111, 0.45 }, 0.6, 1, 144.0, 0.5 },
134 { 1, { 0.43111111111 }, 1.33, 1, 145.0, 1.0 }
137 } ; /* snr_test_data */
139 double best_snr
, snr
, freq3dB
;
140 int j
, k
, converter
, verbose
= 0 ;
142 if (argc
== 2 && strcmp (argv
[1], "--verbose") == 0)
147 for (j
= 0 ; j
< ARRAY_LEN (snr_test_data
) ; j
++)
148 { best_snr
= 5000.0 ;
150 converter
= snr_test_data
[j
].converter
;
152 printf (" Converter %d : %s\n", converter
, src_get_name (converter
)) ;
153 printf (" %s\n", src_get_description (converter
)) ;
155 for (k
= 0 ; k
< snr_test_data
[j
].tests
; k
++)
156 { snr
= snr_test (&(snr_test_data
[j
].test_data
[k
]), k
, converter
, verbose
) ;
161 printf (" Worst case Signal-to-Noise Ratio : %.2f dB.\n", best_snr
) ;
163 if (snr_test_data
[j
].do_bandwidth_test
== BOOLEAN_FALSE
)
164 { puts (" Bandwith test not performed on this converter.\n") ;
168 freq3dB
= bandwidth_test (converter
, verbose
) ;
170 printf (" Measured -3dB rolloff point : %5.2f %%.\n\n", freq3dB
) ;
178 /*==============================================================================
182 snr_test (SINGLE_TEST
*test_data
, int number
, int converter
, int verbose
)
183 { static float data
[BUFFER_LEN
+ 1] ;
184 static float output
[MAX_SPEC_LEN
] ;
186 SRC_STATE
*src_state
;
189 double output_peak
, snr
;
190 int k
, output_len
, input_len
, error
;
193 { printf ("\tSignal-to-Noise Ratio Test %d.\n"
194 "\t=====================================\n", number
) ;
195 printf ("\tFrequencies : [ ") ;
196 for (k
= 0 ; k
< test_data
->freq_count
; k
++)
197 printf ("%6.4f ", test_data
->freqs
[k
]) ;
199 printf ("]\n\tSRC Ratio : %8.4f\n", test_data
->src_ratio
) ;
202 { printf ("\tSignal-to-Noise Ratio Test %d : ", number
) ;
206 /* Set up the output array. */
207 if (test_data
->src_ratio
>= 1.0)
208 { output_len
= MAX_SPEC_LEN
;
209 input_len
= (int) ceil (MAX_SPEC_LEN
/ test_data
->src_ratio
) ;
210 if (input_len
> BUFFER_LEN
)
211 input_len
= BUFFER_LEN
;
214 { input_len
= BUFFER_LEN
;
215 output_len
= (int) ceil (BUFFER_LEN
* test_data
->src_ratio
) ;
216 output_len
&= ((~0u) << 4) ;
217 if (output_len
> MAX_SPEC_LEN
)
218 output_len
= MAX_SPEC_LEN
;
219 input_len
= (int) ceil (output_len
/ test_data
->src_ratio
) ;
222 memset (output
, 0, sizeof (output
)) ;
224 /* Generate input data array. */
225 gen_windowed_sines (test_data
->freq_count
, test_data
->freqs
, 1.0, data
, input_len
) ;
227 /* Perform sample rate conversion. */
228 if ((src_state
= src_new (converter
, 1, &error
)) == NULL
)
229 { printf ("\n\nLine %d : src_new() failed : %s.\n\n", __LINE__
, src_strerror (error
)) ;
233 src_data
.end_of_input
= 1 ; /* Only one buffer worth of input. */
235 src_data
.data_in
= data
;
236 src_data
.input_frames
= input_len
;
238 src_data
.src_ratio
= test_data
->src_ratio
;
240 src_data
.data_out
= output
;
241 src_data
.output_frames
= output_len
;
243 if ((error
= src_process (src_state
, &src_data
)))
244 { printf ("\n\nLine %d : %s\n\n", __LINE__
, src_strerror (error
)) ;
248 src_state
= src_delete (src_state
) ;
251 printf ("\tOutput Len : %ld\n", src_data
.output_frames_gen
) ;
253 if (abs (src_data
.output_frames_gen
- output_len
) > 4)
254 { printf ("\n\nLine %d : output data length should be %d.\n\n", __LINE__
, output_len
) ;
258 /* Check output peak. */
259 output_peak
= find_peak (output
, src_data
.output_frames_gen
) ;
262 printf ("\tOutput Peak : %6.4f\n", output_peak
) ;
264 if (fabs (output_peak
- test_data
->peak_value
) > 0.01)
265 { printf ("\n\nLine %d : output peak (%6.4f) should be %6.4f\n\n", __LINE__
, output_peak
, test_data
->peak_value
) ;
266 save_oct_float ("snr_test.dat", data
, BUFFER_LEN
, output
, output_len
) ;
270 /* Calculate signal-to-noise ratio. */
271 snr
= calculate_snr (output
, src_data
.output_frames_gen
, test_data
->pass_band_peaks
) ;
274 { /* An error occurred. */
275 save_oct_float ("snr_test.dat", data
, BUFFER_LEN
, output
, src_data
.output_frames_gen
) ;
280 printf ("\tSNR Ratio : %.2f dB\n", snr
) ;
282 if (snr
< test_data
->snr
)
283 { printf ("\n\nLine %d : SNR (%5.2f) should be > %6.2f dB\n\n", __LINE__
, snr
, test_data
->snr
) ;
288 puts ("\t-------------------------------------\n\tPass\n") ;
296 find_peak (float *data
, int len
)
297 { double peak
= 0.0 ;
300 for (k
= 0 ; k
< len
; k
++)
301 if (fabs (data
[k
]) > peak
)
302 peak
= fabs (data
[k
]) ;
309 find_attenuation (double freq
, int converter
, int verbose
)
310 { static float input
[BUFFER_LEN
] ;
311 static float output
[2 * BUFFER_LEN
] ;
317 gen_windowed_sines (1, &freq
, 1.0, input
, BUFFER_LEN
) ;
319 src_data
.end_of_input
= 1 ; /* Only one buffer worth of input. */
321 src_data
.data_in
= input
;
322 src_data
.input_frames
= BUFFER_LEN
;
324 src_data
.src_ratio
= 1.999 ;
326 src_data
.data_out
= output
;
327 src_data
.output_frames
= ARRAY_LEN (output
) ;
329 if ((error
= src_simple (&src_data
, converter
, 1)))
330 { printf ("\n\nLine %d : %s\n\n", __LINE__
, src_strerror (error
)) ;
334 output_peak
= find_peak (output
, ARRAY_LEN (output
)) ;
337 printf ("\tFreq : %6f InPeak : %6f OutPeak : %6f Atten : %6.2f dB\n",
338 freq
, 1.0, output_peak
, 20.0 * log10 (1.0 / output_peak
)) ;
340 return 20.0 * log10 (1.0 / output_peak
) ;
341 } /* find_attenuation */
344 bandwidth_test (int converter
, int verbose
)
345 { double f1
, f2
, a1
, a2
;
349 a1
= find_attenuation (f1
, converter
, verbose
) ;
352 a2
= find_attenuation (f2
, converter
, verbose
) ;
354 if (a1
> 3.0 || a2
< 3.0)
355 { printf ("\n\nLine %d : cannot bracket 3dB point.\n\n", __LINE__
) ;
359 while (a2
- a1
> 1.0)
360 { freq
= f1
+ 0.5 * (f2
- f1
) ;
361 atten
= find_attenuation (freq
, converter
, verbose
) ;
373 freq
= f1
+ (3.0 - a1
) * (f2
- f1
) / (a2
- a1
) ;
375 return 200.0 * freq
;
376 } /* bandwidth_test */
378 #else /* (HAVE_FFTW3) == 0 */
380 /* Alternative main function when librfftw is not available. */
385 "****************************************************************\n"
386 " This test cannot be run without FFTW (http://www.fftw.org/).\n"
387 " Both the real and the complex versions of the library are\n"
389 puts ("****************************************************************\n") ;