cannam@126
|
1 /*
|
cannam@126
|
2 ** Copyright (c) 2002-2016, Erik de Castro Lopo <erikd@mega-nerd.com>
|
cannam@126
|
3 ** All rights reserved.
|
cannam@126
|
4 **
|
cannam@126
|
5 ** This code is released under 2-clause BSD license. Please see the
|
cannam@126
|
6 ** file at : https://github.com/erikd/libsamplerate/blob/master/COPYING
|
cannam@126
|
7 */
|
cannam@126
|
8
|
cannam@126
|
9 #include <stdio.h>
|
cannam@126
|
10 #include <stdlib.h>
|
cannam@126
|
11 #include <unistd.h>
|
cannam@126
|
12 #include <string.h>
|
cannam@126
|
13 #include <ctype.h>
|
cannam@126
|
14
|
cannam@126
|
15 #include "config.h"
|
cannam@126
|
16
|
cannam@126
|
17 #if (HAVE_FFTW3 && HAVE_SNDFILE && HAVE_SYS_TIMES_H)
|
cannam@126
|
18
|
cannam@126
|
19 #include <time.h>
|
cannam@126
|
20 #include <sys/times.h>
|
cannam@126
|
21
|
cannam@126
|
22 #include <sndfile.h>
|
cannam@126
|
23 #include <math.h>
|
cannam@126
|
24 #include <sys/utsname.h>
|
cannam@126
|
25
|
cannam@126
|
26 #include "util.h"
|
cannam@126
|
27
|
cannam@126
|
28 #define MAX_FREQS 4
|
cannam@126
|
29 #define BUFFER_LEN 80000
|
cannam@126
|
30
|
cannam@126
|
31 #define SAFE_STRNCAT(dest,src,len) \
|
cannam@126
|
32 { int safe_strncat_count ; \
|
cannam@126
|
33 safe_strncat_count = (len) - strlen (dest) - 1 ; \
|
cannam@126
|
34 strncat ((dest), (src), safe_strncat_count) ; \
|
cannam@126
|
35 (dest) [(len) - 1] = 0 ; \
|
cannam@126
|
36 } ;
|
cannam@126
|
37
|
cannam@126
|
38 typedef struct
|
cannam@126
|
39 { int freq_count ;
|
cannam@126
|
40 double freqs [MAX_FREQS] ;
|
cannam@126
|
41
|
cannam@126
|
42 int output_samplerate ;
|
cannam@126
|
43 int pass_band_peaks ;
|
cannam@126
|
44
|
cannam@126
|
45 double peak_value ;
|
cannam@126
|
46 } SNR_TEST ;
|
cannam@126
|
47
|
cannam@126
|
48 typedef struct
|
cannam@126
|
49 { const char *progname ;
|
cannam@126
|
50 const char *version_cmd ;
|
cannam@126
|
51 const char *version_start ;
|
cannam@126
|
52 const char *convert_cmd ;
|
cannam@126
|
53 int format ;
|
cannam@126
|
54 } RESAMPLE_PROG ;
|
cannam@126
|
55
|
cannam@126
|
56 static char *get_progname (char *) ;
|
cannam@126
|
57 static void usage_exit (const char *, const RESAMPLE_PROG *prog, int count) ;
|
cannam@126
|
58 static void measure_program (const RESAMPLE_PROG *prog, int verbose) ;
|
cannam@126
|
59 static void generate_source_wav (const char *filename, const double *freqs, int freq_count, int format) ;
|
cannam@126
|
60 static const char* get_machine_details (void) ;
|
cannam@126
|
61
|
cannam@126
|
62 static char version_string [512] ;
|
cannam@126
|
63
|
cannam@126
|
64 int
|
cannam@126
|
65 main (int argc, char *argv [])
|
cannam@126
|
66 { static RESAMPLE_PROG resample_progs [] =
|
cannam@126
|
67 { { "sndfile-resample",
|
cannam@126
|
68 "examples/sndfile-resample --version",
|
cannam@126
|
69 "libsamplerate",
|
cannam@126
|
70 "examples/sndfile-resample --max-speed -c 0 -to %d source.wav destination.wav",
|
cannam@126
|
71 SF_FORMAT_WAV | SF_FORMAT_PCM_32
|
cannam@126
|
72 },
|
cannam@126
|
73 { "sox",
|
cannam@126
|
74 "sox -h 2>&1",
|
cannam@126
|
75 "sox",
|
cannam@126
|
76 "sox source.wav -r %d destination.wav resample 0.835",
|
cannam@126
|
77 SF_FORMAT_WAV | SF_FORMAT_PCM_32
|
cannam@126
|
78 },
|
cannam@126
|
79 { "ResampAudio",
|
cannam@126
|
80 "ResampAudio --version",
|
cannam@126
|
81 "ResampAudio",
|
cannam@126
|
82 "ResampAudio -f cutoff=0.41,atten=100,ratio=128 -s %d source.wav destination.wav",
|
cannam@126
|
83 SF_FORMAT_WAV | SF_FORMAT_PCM_32
|
cannam@126
|
84 },
|
cannam@126
|
85
|
cannam@126
|
86 /*-
|
cannam@126
|
87 { /+*
|
cannam@126
|
88 ** The Shibatch converter doesn't work for all combinations of
|
cannam@126
|
89 ** source and destination sample rates. Therefore it can't be
|
cannam@126
|
90 ** included in this test.
|
cannam@126
|
91 *+/
|
cannam@126
|
92 "shibatch",
|
cannam@126
|
93 "ssrc",
|
cannam@126
|
94 "Shibatch",
|
cannam@126
|
95 "ssrc --rate %d source.wav destination.wav",
|
cannam@126
|
96 SF_FORMAT_WAV | SF_FORMAT_PCM_32
|
cannam@126
|
97 },-*/
|
cannam@126
|
98
|
cannam@126
|
99 /*-
|
cannam@126
|
100 { /+*
|
cannam@126
|
101 ** The resample program is not able to match the bandwidth and SNR
|
cannam@126
|
102 ** specs or sndfile-resample and hence will not be tested.
|
cannam@126
|
103 *+/
|
cannam@126
|
104 "resample",
|
cannam@126
|
105 "resample -version",
|
cannam@126
|
106 "resample",
|
cannam@126
|
107 "resample -to %d source.wav destination.wav",
|
cannam@126
|
108 SF_FORMAT_WAV | SF_FORMAT_FLOAT
|
cannam@126
|
109 },-*/
|
cannam@126
|
110
|
cannam@126
|
111 /*-
|
cannam@126
|
112 { "mplayer",
|
cannam@126
|
113 "mplayer -v 2>&1",
|
cannam@126
|
114 "MPlayer ",
|
cannam@126
|
115 "mplayer -ao pcm -srate %d source.wav >/dev/null 2>&1 && mv audiodump.wav destination.wav",
|
cannam@126
|
116 SF_FORMAT_WAV | SF_FORMAT_PCM_32
|
cannam@126
|
117 },-*/
|
cannam@126
|
118
|
cannam@126
|
119 } ; /* resample_progs */
|
cannam@126
|
120
|
cannam@126
|
121 char *progname ;
|
cannam@126
|
122 int prog = 0, verbose = 0 ;
|
cannam@126
|
123
|
cannam@126
|
124 progname = get_progname (argv [0]) ;
|
cannam@126
|
125
|
cannam@126
|
126 printf ("\n %s : evaluate a sample rate converter.\n", progname) ;
|
cannam@126
|
127
|
cannam@126
|
128 if (argc == 3 && strcmp ("--verbose", argv [1]) == 0)
|
cannam@126
|
129 { verbose = 1 ;
|
cannam@126
|
130 prog = atoi (argv [2]) ;
|
cannam@126
|
131 }
|
cannam@126
|
132 else if (argc == 2)
|
cannam@126
|
133 { verbose = 0 ;
|
cannam@126
|
134 prog = atoi (argv [1]) ;
|
cannam@126
|
135 }
|
cannam@126
|
136 else
|
cannam@126
|
137 usage_exit (progname, resample_progs, ARRAY_LEN (resample_progs)) ;
|
cannam@126
|
138
|
cannam@126
|
139 if (prog < 0 || prog >= ARRAY_LEN (resample_progs))
|
cannam@126
|
140 usage_exit (progname, resample_progs, ARRAY_LEN (resample_progs)) ;
|
cannam@126
|
141
|
cannam@126
|
142 measure_program (& (resample_progs [prog]), verbose) ;
|
cannam@126
|
143
|
cannam@126
|
144 puts ("") ;
|
cannam@126
|
145
|
cannam@126
|
146 return 0 ;
|
cannam@126
|
147 } /* main */
|
cannam@126
|
148
|
cannam@126
|
149 /*==============================================================================
|
cannam@126
|
150 */
|
cannam@126
|
151
|
cannam@126
|
152 static char *
|
cannam@126
|
153 get_progname (char *progname)
|
cannam@126
|
154 { char *cptr ;
|
cannam@126
|
155
|
cannam@126
|
156 if ((cptr = strrchr (progname, '/')) != NULL)
|
cannam@126
|
157 progname = cptr + 1 ;
|
cannam@126
|
158
|
cannam@126
|
159 if ((cptr = strrchr (progname, '\\')) != NULL)
|
cannam@126
|
160 progname = cptr + 1 ;
|
cannam@126
|
161
|
cannam@126
|
162 return progname ;
|
cannam@126
|
163 } /* get_progname */
|
cannam@126
|
164
|
cannam@126
|
165 static void
|
cannam@126
|
166 usage_exit (const char *progname, const RESAMPLE_PROG *prog, int count)
|
cannam@126
|
167 { int k ;
|
cannam@126
|
168
|
cannam@126
|
169 printf ("\n Usage : %s <number>\n\n", progname) ;
|
cannam@126
|
170
|
cannam@126
|
171 puts (" where <number> specifies the program to test:\n") ;
|
cannam@126
|
172
|
cannam@126
|
173 for (k = 0 ; k < count ; k++)
|
cannam@126
|
174 printf (" %d : %s\n", k, prog [k].progname) ;
|
cannam@126
|
175
|
cannam@126
|
176 puts ("\n"
|
cannam@126
|
177 " Obviously to test a given program you have to have it available on\n"
|
cannam@126
|
178 " your system. See http://www.mega-nerd.com/SRC/quality.html for\n"
|
cannam@126
|
179 " the download location of these programs.\n") ;
|
cannam@126
|
180
|
cannam@126
|
181 exit (1) ;
|
cannam@126
|
182 } /* usage_exit */
|
cannam@126
|
183
|
cannam@126
|
184 static const char*
|
cannam@126
|
185 get_machine_details (void)
|
cannam@126
|
186 { static char namestr [256] ;
|
cannam@126
|
187
|
cannam@126
|
188 struct utsname name ;
|
cannam@126
|
189
|
cannam@126
|
190 if (uname (&name) != 0)
|
cannam@126
|
191 { snprintf (namestr, sizeof (namestr), "Unknown") ;
|
cannam@126
|
192 return namestr ;
|
cannam@126
|
193 } ;
|
cannam@126
|
194
|
cannam@126
|
195 snprintf (namestr, sizeof (namestr), "%s (%s %s %s)", name.nodename,
|
cannam@126
|
196 name.machine, name.sysname, name.release) ;
|
cannam@126
|
197
|
cannam@126
|
198 return namestr ;
|
cannam@126
|
199 } /* get_machine_details */
|
cannam@126
|
200
|
cannam@126
|
201
|
cannam@126
|
202 /*==============================================================================
|
cannam@126
|
203 */
|
cannam@126
|
204
|
cannam@126
|
205 static void
|
cannam@126
|
206 get_version_string (const RESAMPLE_PROG *prog)
|
cannam@126
|
207 { FILE *file ;
|
cannam@126
|
208 char *cptr ;
|
cannam@126
|
209
|
cannam@126
|
210 /* Default. */
|
cannam@126
|
211 snprintf (version_string, sizeof (version_string), "no version") ;
|
cannam@126
|
212
|
cannam@126
|
213 if (prog->version_cmd == NULL)
|
cannam@126
|
214 return ;
|
cannam@126
|
215
|
cannam@126
|
216 if ((file = popen (prog->version_cmd, "r")) == NULL)
|
cannam@126
|
217 return ;
|
cannam@126
|
218
|
cannam@126
|
219 while ((cptr = fgets (version_string, sizeof (version_string), file)) != NULL)
|
cannam@126
|
220 {
|
cannam@126
|
221 if (strstr (cptr, prog->version_start) != NULL)
|
cannam@126
|
222 break ;
|
cannam@126
|
223
|
cannam@126
|
224 version_string [0] = 0 ;
|
cannam@126
|
225 } ;
|
cannam@126
|
226
|
cannam@126
|
227 pclose (file) ;
|
cannam@126
|
228
|
cannam@126
|
229 /* Remove trailing newline. */
|
cannam@126
|
230 if ((cptr = strchr (version_string, '\n')) != NULL)
|
cannam@126
|
231 cptr [0] = 0 ;
|
cannam@126
|
232
|
cannam@126
|
233 /* Remove leading whitespace from version string. */
|
cannam@126
|
234 cptr = version_string ;
|
cannam@126
|
235 while (cptr [0] != 0 && isspace (cptr [0]))
|
cannam@126
|
236 cptr ++ ;
|
cannam@126
|
237
|
cannam@126
|
238 if (cptr != version_string)
|
cannam@126
|
239 strncpy (version_string, cptr, sizeof (version_string)) ;
|
cannam@126
|
240
|
cannam@126
|
241 return ;
|
cannam@126
|
242 } /* get_version_string */
|
cannam@126
|
243
|
cannam@126
|
244 static void
|
cannam@126
|
245 generate_source_wav (const char *filename, const double *freqs, int freq_count, int format)
|
cannam@126
|
246 { static float buffer [BUFFER_LEN] ;
|
cannam@126
|
247
|
cannam@126
|
248 SNDFILE *sndfile ;
|
cannam@126
|
249 SF_INFO sfinfo ;
|
cannam@126
|
250
|
cannam@126
|
251 sfinfo.channels = 1 ;
|
cannam@126
|
252 sfinfo.samplerate = 44100 ;
|
cannam@126
|
253 sfinfo.format = format ;
|
cannam@126
|
254
|
cannam@126
|
255 if ((sndfile = sf_open (filename, SFM_WRITE, &sfinfo)) == NULL)
|
cannam@126
|
256 { printf ("Line %d : cound not open '%s' : %s\n", __LINE__, filename, sf_strerror (NULL)) ;
|
cannam@126
|
257 exit (1) ;
|
cannam@126
|
258 } ;
|
cannam@126
|
259
|
cannam@126
|
260 sf_command (sndfile, SFC_SET_ADD_PEAK_CHUNK, NULL, SF_FALSE) ;
|
cannam@126
|
261
|
cannam@126
|
262 gen_windowed_sines (freq_count, freqs, 0.9, buffer, ARRAY_LEN (buffer)) ;
|
cannam@126
|
263
|
cannam@126
|
264 if (sf_write_float (sndfile, buffer, ARRAY_LEN (buffer)) != ARRAY_LEN (buffer))
|
cannam@126
|
265 { printf ("Line %d : sf_write_float short write.\n", __LINE__) ;
|
cannam@126
|
266 exit (1) ;
|
cannam@126
|
267 } ;
|
cannam@126
|
268
|
cannam@126
|
269 sf_close (sndfile) ;
|
cannam@126
|
270 } /* generate_source_wav */
|
cannam@126
|
271
|
cannam@126
|
272 static double
|
cannam@126
|
273 measure_destination_wav (char *filename, int *output_samples, int expected_peaks)
|
cannam@126
|
274 { static float buffer [250000] ;
|
cannam@126
|
275
|
cannam@126
|
276 SNDFILE *sndfile ;
|
cannam@126
|
277 SF_INFO sfinfo ;
|
cannam@126
|
278 double snr ;
|
cannam@126
|
279
|
cannam@126
|
280 if ((sndfile = sf_open (filename, SFM_READ, &sfinfo)) == NULL)
|
cannam@126
|
281 { printf ("Line %d : Cound not open '%s' : %s\n", __LINE__, filename, sf_strerror (NULL)) ;
|
cannam@126
|
282 exit (1) ;
|
cannam@126
|
283 } ;
|
cannam@126
|
284
|
cannam@126
|
285 if (sfinfo.channels != 1)
|
cannam@126
|
286 { printf ("Line %d : Bad channel count (%d). Should be 1.\n", __LINE__, sfinfo.channels) ;
|
cannam@126
|
287 exit (1) ;
|
cannam@126
|
288 } ;
|
cannam@126
|
289
|
cannam@126
|
290 if (sfinfo.frames > ARRAY_LEN (buffer))
|
cannam@126
|
291 { printf ("Line %d : Too many frames (%ld) of data in file.\n", __LINE__, (long) sfinfo.frames) ;
|
cannam@126
|
292 exit (1) ;
|
cannam@126
|
293 } ;
|
cannam@126
|
294
|
cannam@126
|
295 *output_samples = (int) sfinfo.frames ;
|
cannam@126
|
296
|
cannam@126
|
297 if (sf_read_float (sndfile, buffer, sfinfo.frames) != sfinfo.frames)
|
cannam@126
|
298 { printf ("Line %d : Bad read.\n", __LINE__) ;
|
cannam@126
|
299 exit (1) ;
|
cannam@126
|
300 } ;
|
cannam@126
|
301
|
cannam@126
|
302 sf_close (sndfile) ;
|
cannam@126
|
303
|
cannam@126
|
304 snr = calculate_snr (buffer, sfinfo.frames, expected_peaks) ;
|
cannam@126
|
305
|
cannam@126
|
306 return snr ;
|
cannam@126
|
307 } /* measure_desination_wav */
|
cannam@126
|
308
|
cannam@126
|
309 static double
|
cannam@126
|
310 measure_snr (const RESAMPLE_PROG *prog, int *output_samples, int verbose)
|
cannam@126
|
311 { static SNR_TEST snr_test [] =
|
cannam@126
|
312 {
|
cannam@126
|
313 { 1, { 0.211111111111 }, 48000, 1, 1.0 },
|
cannam@126
|
314 { 1, { 0.011111111111 }, 132301, 1, 1.0 },
|
cannam@126
|
315 { 1, { 0.111111111111 }, 92301, 1, 1.0 },
|
cannam@126
|
316 { 1, { 0.011111111111 }, 26461, 1, 1.0 },
|
cannam@126
|
317 { 1, { 0.011111111111 }, 13231, 1, 1.0 },
|
cannam@126
|
318 { 1, { 0.011111111111 }, 44101, 1, 1.0 },
|
cannam@126
|
319 { 2, { 0.311111, 0.49 }, 78199, 2, 1.0 },
|
cannam@126
|
320 { 2, { 0.011111, 0.49 }, 12345, 1, 0.5 },
|
cannam@126
|
321 { 2, { 0.0123456, 0.4 }, 20143, 1, 0.5 },
|
cannam@126
|
322 { 2, { 0.0111111, 0.4 }, 26461, 1, 0.5 },
|
cannam@126
|
323 { 1, { 0.381111111111 }, 58661, 1, 1.0 }
|
cannam@126
|
324 } ; /* snr_test */
|
cannam@126
|
325 static char command [256] ;
|
cannam@126
|
326
|
cannam@126
|
327 double snr, worst_snr = 500.0 ;
|
cannam@126
|
328 int k , retval, sample_count ;
|
cannam@126
|
329
|
cannam@126
|
330 *output_samples = 0 ;
|
cannam@126
|
331
|
cannam@126
|
332 for (k = 0 ; k < ARRAY_LEN (snr_test) ; k++)
|
cannam@126
|
333 { remove ("source.wav") ;
|
cannam@126
|
334 remove ("destination.wav") ;
|
cannam@126
|
335
|
cannam@126
|
336 if (verbose)
|
cannam@126
|
337 printf (" SNR test #%d : ", k) ;
|
cannam@126
|
338 fflush (stdout) ;
|
cannam@126
|
339 generate_source_wav ("source.wav", snr_test [k].freqs, snr_test [k].freq_count, prog->format) ;
|
cannam@126
|
340
|
cannam@126
|
341 snprintf (command, sizeof (command), prog->convert_cmd, snr_test [k].output_samplerate) ;
|
cannam@126
|
342 SAFE_STRNCAT (command, " >/dev/null 2>&1", sizeof (command)) ;
|
cannam@126
|
343 if ((retval = system (command)) != 0)
|
cannam@126
|
344 printf ("system returned %d\n", retval) ;
|
cannam@126
|
345
|
cannam@126
|
346 snr = measure_destination_wav ("destination.wav", &sample_count, snr_test->pass_band_peaks) ;
|
cannam@126
|
347
|
cannam@126
|
348 *output_samples += sample_count ;
|
cannam@126
|
349
|
cannam@126
|
350 if (fabs (snr) < fabs (worst_snr))
|
cannam@126
|
351 worst_snr = fabs (snr) ;
|
cannam@126
|
352
|
cannam@126
|
353 if (verbose)
|
cannam@126
|
354 printf ("%6.2f dB\n", snr) ;
|
cannam@126
|
355 } ;
|
cannam@126
|
356
|
cannam@126
|
357 return worst_snr ;
|
cannam@126
|
358 } /* measure_snr */
|
cannam@126
|
359
|
cannam@126
|
360 /*------------------------------------------------------------------------------
|
cannam@126
|
361 */
|
cannam@126
|
362
|
cannam@126
|
363 static double
|
cannam@126
|
364 measure_destination_peak (const char *filename)
|
cannam@126
|
365 { static float data [2 * BUFFER_LEN] ;
|
cannam@126
|
366 SNDFILE *sndfile ;
|
cannam@126
|
367 SF_INFO sfinfo ;
|
cannam@126
|
368 double peak = 0.0 ;
|
cannam@126
|
369 int k = 0 ;
|
cannam@126
|
370
|
cannam@126
|
371 if ((sndfile = sf_open (filename, SFM_READ, &sfinfo)) == NULL)
|
cannam@126
|
372 { printf ("Line %d : failed to open file %s\n", __LINE__, filename) ;
|
cannam@126
|
373 exit (1) ;
|
cannam@126
|
374 } ;
|
cannam@126
|
375
|
cannam@126
|
376 if (sfinfo.channels != 1)
|
cannam@126
|
377 { printf ("Line %d : bad channel count.\n", __LINE__) ;
|
cannam@126
|
378 exit (1) ;
|
cannam@126
|
379 } ;
|
cannam@126
|
380
|
cannam@126
|
381 if (sfinfo.frames > ARRAY_LEN (data) + 4 || sfinfo.frames < ARRAY_LEN (data) - 100)
|
cannam@126
|
382 { printf ("Line %d : bad frame count (got %d, expected %d).\n", __LINE__, (int) sfinfo.frames, ARRAY_LEN (data)) ;
|
cannam@126
|
383 exit (1) ;
|
cannam@126
|
384 } ;
|
cannam@126
|
385
|
cannam@126
|
386 if (sf_read_float (sndfile, data, sfinfo.frames) != sfinfo.frames)
|
cannam@126
|
387 { printf ("Line %d : bad read.\n", __LINE__) ;
|
cannam@126
|
388 exit (1) ;
|
cannam@126
|
389 } ;
|
cannam@126
|
390
|
cannam@126
|
391 sf_close (sndfile) ;
|
cannam@126
|
392
|
cannam@126
|
393 for (k = 0 ; k < (int) sfinfo.frames ; k++)
|
cannam@126
|
394 if (fabs (data [k]) > peak)
|
cannam@126
|
395 peak = fabs (data [k]) ;
|
cannam@126
|
396
|
cannam@126
|
397 return peak ;
|
cannam@126
|
398 } /* measure_destination_peak */
|
cannam@126
|
399
|
cannam@126
|
400 static double
|
cannam@126
|
401 find_attenuation (double freq, const RESAMPLE_PROG *prog, int verbose)
|
cannam@126
|
402 { static char command [256] ;
|
cannam@126
|
403 double output_peak ;
|
cannam@126
|
404 int retval ;
|
cannam@126
|
405 char *filename ;
|
cannam@126
|
406
|
cannam@126
|
407 filename = "destination.wav" ;
|
cannam@126
|
408
|
cannam@126
|
409 generate_source_wav ("source.wav", &freq, 1, prog->format) ;
|
cannam@126
|
410
|
cannam@126
|
411 remove (filename) ;
|
cannam@126
|
412
|
cannam@126
|
413 snprintf (command, sizeof (command), prog->convert_cmd, 88189) ;
|
cannam@126
|
414 SAFE_STRNCAT (command, " >/dev/null 2>&1", sizeof (command)) ;
|
cannam@126
|
415 if ((retval = system (command)) != 0)
|
cannam@126
|
416 printf ("system returned %d\n", retval) ;
|
cannam@126
|
417
|
cannam@126
|
418 output_peak = measure_destination_peak (filename) ;
|
cannam@126
|
419
|
cannam@126
|
420 if (verbose)
|
cannam@126
|
421 printf (" freq : %f peak : %f\n", freq, output_peak) ;
|
cannam@126
|
422
|
cannam@126
|
423 return fabs (20.0 * log10 (output_peak)) ;
|
cannam@126
|
424 } /* find_attenuation */
|
cannam@126
|
425
|
cannam@126
|
426 static double
|
cannam@126
|
427 bandwidth_test (const RESAMPLE_PROG *prog, int verbose)
|
cannam@126
|
428 { double f1, f2, a1, a2 ;
|
cannam@126
|
429 double freq, atten ;
|
cannam@126
|
430
|
cannam@126
|
431 f1 = 0.35 ;
|
cannam@126
|
432 a1 = find_attenuation (f1, prog, verbose) ;
|
cannam@126
|
433
|
cannam@126
|
434 f2 = 0.49999 ;
|
cannam@126
|
435 a2 = find_attenuation (f2, prog, verbose) ;
|
cannam@126
|
436
|
cannam@126
|
437
|
cannam@126
|
438 if (fabs (a1) < 1e-2 && a2 < 3.0)
|
cannam@126
|
439 return -1.0 ;
|
cannam@126
|
440
|
cannam@126
|
441 if (a1 > 3.0 || a2 < 3.0)
|
cannam@126
|
442 { printf ("\n\nLine %d : cannot bracket 3dB point.\n\n", __LINE__) ;
|
cannam@126
|
443 exit (1) ;
|
cannam@126
|
444 } ;
|
cannam@126
|
445
|
cannam@126
|
446 while (a2 - a1 > 1.0)
|
cannam@126
|
447 { freq = f1 + 0.5 * (f2 - f1) ;
|
cannam@126
|
448 atten = find_attenuation (freq, prog, verbose) ;
|
cannam@126
|
449
|
cannam@126
|
450 if (atten < 3.0)
|
cannam@126
|
451 { f1 = freq ;
|
cannam@126
|
452 a1 = atten ;
|
cannam@126
|
453 }
|
cannam@126
|
454 else
|
cannam@126
|
455 { f2 = freq ;
|
cannam@126
|
456 a2 = atten ;
|
cannam@126
|
457 } ;
|
cannam@126
|
458 } ;
|
cannam@126
|
459
|
cannam@126
|
460 freq = f1 + (3.0 - a1) * (f2 - f1) / (a2 - a1) ;
|
cannam@126
|
461
|
cannam@126
|
462 return 200.0 * freq ;
|
cannam@126
|
463 } /* bandwidth_test */
|
cannam@126
|
464
|
cannam@126
|
465 static void
|
cannam@126
|
466 measure_program (const RESAMPLE_PROG *prog, int verbose)
|
cannam@126
|
467 { double snr, bandwidth, conversion_rate ;
|
cannam@126
|
468 int output_samples ;
|
cannam@126
|
469 struct tms time_data ;
|
cannam@126
|
470 time_t time_now ;
|
cannam@126
|
471
|
cannam@126
|
472 printf ("\n Machine : %s\n", get_machine_details ()) ;
|
cannam@126
|
473 time_now = time (NULL) ;
|
cannam@126
|
474 printf (" Date : %s", ctime (&time_now)) ;
|
cannam@126
|
475
|
cannam@126
|
476 get_version_string (prog) ;
|
cannam@126
|
477 printf (" Program : %s\n", version_string) ;
|
cannam@126
|
478 printf (" Command : %s\n\n", prog->convert_cmd) ;
|
cannam@126
|
479
|
cannam@126
|
480 snr = measure_snr (prog, &output_samples, verbose) ;
|
cannam@126
|
481
|
cannam@126
|
482 printf (" Worst case SNR : %6.2f dB\n", snr) ;
|
cannam@126
|
483
|
cannam@126
|
484 times (&time_data) ;
|
cannam@126
|
485
|
cannam@126
|
486 conversion_rate = (1.0 * output_samples * sysconf (_SC_CLK_TCK)) / time_data.tms_cutime ;
|
cannam@126
|
487
|
cannam@126
|
488 printf (" Conversion rate : %5.0f samples/sec\n", conversion_rate) ;
|
cannam@126
|
489
|
cannam@126
|
490 bandwidth = bandwidth_test (prog, verbose) ;
|
cannam@126
|
491
|
cannam@126
|
492 if (bandwidth > 0.0)
|
cannam@126
|
493 printf (" Measured bandwidth : %5.2f %%\n", bandwidth) ;
|
cannam@126
|
494 else
|
cannam@126
|
495 printf (" Could not measure bandwidth (no -3dB point found).\n") ;
|
cannam@126
|
496
|
cannam@126
|
497 return ;
|
cannam@126
|
498 } /* measure_program */
|
cannam@126
|
499
|
cannam@126
|
500 /*##############################################################################
|
cannam@126
|
501 */
|
cannam@126
|
502
|
cannam@126
|
503 #else
|
cannam@126
|
504
|
cannam@126
|
505 int
|
cannam@126
|
506 main (void)
|
cannam@126
|
507 { puts ("\n"
|
cannam@126
|
508 "****************************************************************\n"
|
cannam@126
|
509 " This program has been compiled without :\n"
|
cannam@126
|
510 " 1) FFTW (http://www.fftw.org/).\n"
|
cannam@126
|
511 " 2) libsndfile (http://www.zip.com.au/~erikd/libsndfile/).\n"
|
cannam@126
|
512 " Without these two libraries there is not much it can do.\n"
|
cannam@126
|
513 "****************************************************************\n") ;
|
cannam@126
|
514
|
cannam@126
|
515 return 0 ;
|
cannam@126
|
516 } /* main */
|
cannam@126
|
517
|
cannam@126
|
518 #endif /* (HAVE_FFTW3 && HAVE_SNDFILE) */
|
cannam@126
|
519
|