~ubuntu-branches/ubuntu/gutsy/libsamplerate/gutsy

« back to all changes in this revision

Viewing changes to tests/snr_bw_test.c

  • Committer: Bazaar Package Importer
  • Author(s): Anand Kumria
  • Date: 2004-03-16 23:29:17 UTC
  • Revision ID: james.westby@ubuntu.com-20040316232917-ivb5khznkdtkkylr
Tags: upstream-0.1.0
ImportĀ upstreamĀ versionĀ 0.1.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
** Copyright (C) 2002-2004 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 <math.h>
 
23
#include <time.h>
 
24
 
 
25
#include "config.h"
 
26
 
 
27
#if (HAVE_FFTW3)
 
28
 
 
29
#include <samplerate.h>
 
30
 
 
31
#include "util.h"
 
32
#include "calc_snr.h"
 
33
 
 
34
#define BUFFER_LEN              50000
 
35
#define MAX_FREQS               4
 
36
#define MAX_RATIOS              6
 
37
#define MAX_SPEC_LEN    (1<<15)
 
38
 
 
39
#ifndef M_PI
 
40
#define M_PI                    3.14159265358979323846264338
 
41
#endif
 
42
 
 
43
#define ARRAY_LEN(x)    ((int) (sizeof (x) / sizeof ((x) [0])))
 
44
 
 
45
enum
 
46
{       BOOLEAN_FALSE   = 0,
 
47
        BOOLEAN_TRUE    = 1
 
48
} ;
 
49
 
 
50
typedef struct
 
51
{       int             freq_count ;
 
52
        double  freqs [MAX_FREQS] ;
 
53
 
 
54
        double  src_ratio ;
 
55
        int             pass_band_peaks ;
 
56
 
 
57
        double  snr ;
 
58
        double  peak_value ;
 
59
} SINGLE_TEST ;
 
60
 
 
61
typedef struct
 
62
{       int                     converter ;
 
63
        int                     tests ;
 
64
        int                     do_bandwidth_test ;
 
65
        SINGLE_TEST     test_data [10] ;
 
66
} CONVERTER_TEST ;
 
67
 
 
68
static double snr_test (SINGLE_TEST *snr_test_data, int number, int converter, int verbose, double *conversion_rate) ;
 
69
static double find_peak (float *output, int output_len) ;
 
70
static double bandwidth_test (int converter, int verbose) ;
 
71
 
 
72
int
 
73
main (int argc, char *argv [])
 
74
{       CONVERTER_TEST snr_test_data [] =
 
75
        {
 
76
                {       SRC_ZERO_ORDER_HOLD,
 
77
                        8,
 
78
                        BOOLEAN_FALSE,
 
79
                        {       {       1,      { 0.01111111111 },              3.0,            1,       29.0,  1.0 },
 
80
                                {       1,      { 0.01111111111 },              0.6,            1,       37.0,  1.0 },
 
81
                                {       1,      { 0.01111111111 },              0.3,            1,       37.0,  1.0 },
 
82
                                {       1,      { 0.01111111111 },              1.0,            1,      150.0,  1.0 },
 
83
                                {       1,      { 0.01111111111 },              1.001,          1,       38.0,  1.0 },
 
84
                                {       2,      { 0.011111, 0.324 },    1.9999,         2,       14.0,  1.0 },
 
85
                                {       2,      { 0.012345, 0.457 },    0.456789,       1,       32.0,  1.0 },
 
86
                                {       1,      { 0.3511111111 },               1.33,           1,       10.0,  1.0 }
 
87
                                }
 
88
                        },
 
89
 
 
90
                {       SRC_LINEAR,
 
91
                        8,
 
92
                        BOOLEAN_FALSE,
 
93
                        {       {       1,      { 0.01111111111 },              3.0,            1,       73.0,  1.0 },
 
94
                                {       1,      { 0.01111111111 },              0.6,            1,       74.0,  1.0 },
 
95
                                {       1,      { 0.01111111111 },              0.3,            1,       74.0,  1.0 },
 
96
                                {       1,      { 0.01111111111 },              1.0,            1,      150.0,  1.0 },
 
97
                                {       1,      { 0.01111111111 },              1.001,          1,       77.0,  1.0 },
 
98
                                {       2,      { 0.011111, 0.324 },    1.9999,         2,       97.0,  0.94 },
 
99
                                {       2,      { 0.012345, 0.457 },    0.456789,       1,       60.0,  0.96 },
 
100
                                {       1,      { 0.3511111111 },               1.33,           1,       22.0,  0.99 }
 
101
                                }
 
102
                        },
 
103
 
 
104
                {       SRC_SINC_FASTEST,
 
105
                        9,
 
106
                        BOOLEAN_TRUE,
 
107
                        {       {       1,      { 0.01111111111 },              3.0,            1,      100.0,  1.0 },
 
108
                                {       1,      { 0.01111111111 },              0.6,            1,      100.0,  1.0 },
 
109
                                {       1,      { 0.01111111111 },              0.3,            1,      100.0,  1.0 },
 
110
                                {       1,      { 0.01111111111 },              1.0,            1,      150.0,  1.0 },
 
111
                                {       1,      { 0.01111111111 },              1.001,          1,      100.0,  1.0 },
 
112
                                {       2,      { 0.011111, 0.324 },    1.9999,         2,       97.0,  1.0 },
 
113
                                {       2,      { 0.012345, 0.457 },    0.456789,       1,      100.0,  0.5 },
 
114
                                {       2,      { 0.011111, 0.45 },             0.6,            1,       97.0,  0.5 },
 
115
                                {       1,      { 0.3511111111 },               1.33,           1,       97.0,  1.0 }
 
116
                                }
 
117
                        },
 
118
 
 
119
                {       SRC_SINC_MEDIUM_QUALITY,
 
120
                        9,
 
121
                        BOOLEAN_TRUE,
 
122
                        {       {       1,      { 0.01111111111 },              3.0,            1,      100.0,  1.0 },
 
123
                                {       1,      { 0.01111111111 },              0.6,            1,      100.0,  1.0 },
 
124
                                {       1,      { 0.01111111111 },              0.3,            1,      100.0,  1.0 },
 
125
                                {       1,      { 0.01111111111 },              1.0,            1,      149.0,  1.0 },
 
126
                                {       1,      { 0.01111111111 },              1.001,          1,      100.0,  1.0 },
 
127
                                {       2,      { 0.011111, 0.324 },    1.9999,         2,       97.0,  1.0 },
 
128
                                {       2,      { 0.012345, 0.457 },    0.456789,       1,      100.0,  0.5 },
 
129
                                {       2,      { 0.011111, 0.45 },             0.6,            1,       97.0,  0.5 },
 
130
                                {       1,      { 0.43111111111 },              1.33,           1,       97.0,  1.0 }
 
131
                                }
 
132
                        },
 
133
 
 
134
                {       SRC_SINC_BEST_QUALITY,
 
135
                        9,
 
136
                        BOOLEAN_TRUE,
 
137
                        {       {       1,      { 0.01111111111 },              3.0,            1,      100.0,  1.0 },
 
138
                                {       1,      { 0.01111111111 },              0.6,            1,      100.0,  1.0 },
 
139
                                {       1,      { 0.01111111111 },              0.3,            1,      100.0,  1.0 },
 
140
                                {       1,      { 0.01111111111 },              1.0,            1,      154.0,  1.0 },
 
141
                                {       1,      { 0.01111111111 },              1.001,          1,      100.0,  1.0 },
 
142
                                {       2,      { 0.011111, 0.324 },    1.9999,         2,       97.0,  1.0 },
 
143
                                {       2,      { 0.012345, 0.457 },    0.456789,       1,      100.0,  0.5 },
 
144
                                {       2,      { 0.011111, 0.45 },             0.6,            1,       97.0,  0.5 },
 
145
                                {       1,      { 0.47111111111 },              1.33,           1,       97.0,  1.0 }
 
146
                                },
 
147
                        },
 
148
 
 
149
        } ; /* snr_test_data */
 
150
 
 
151
        double  best_snr, snr, freq3dB, conversion_rate, worst_conv_rate ;
 
152
        int     j, k, converter, verbose = 0 ;
 
153
 
 
154
        /* Force output of the Electric Fence banner message. */
 
155
        force_efence_banner () ;
 
156
 
 
157
        if (argc == 2 && strcmp (argv [1], "--verbose") == 0)
 
158
                verbose = 1 ;
 
159
 
 
160
        puts ("") ;
 
161
 
 
162
        for (j = 0 ; j < ARRAY_LEN (snr_test_data) ; j++)
 
163
        {       best_snr = 5000.0 ;
 
164
                worst_conv_rate = 1e200 ;
 
165
 
 
166
                converter = snr_test_data [j].converter ;
 
167
 
 
168
                printf ("    Converter %d : %s\n", converter, src_get_name (converter)) ;
 
169
                printf ("    %s\n", src_get_description (converter)) ;
 
170
 
 
171
                for (k = 0 ; k < snr_test_data [j].tests ; k++)
 
172
                {       snr = snr_test (&(snr_test_data [j].test_data [k]), k, converter, verbose, &conversion_rate) ;
 
173
                        if (best_snr > snr)
 
174
                                best_snr = snr ;
 
175
                        if (worst_conv_rate > conversion_rate)
 
176
                                worst_conv_rate = conversion_rate ;
 
177
                        } ;
 
178
 
 
179
                printf ("    Worst case Signal-to-Noise Ratio : %.2f dB.\n", best_snr) ;
 
180
                printf ("    Worst case conversion rate       : %.0f samples/sec.\n", worst_conv_rate) ;
 
181
 
 
182
                if (snr_test_data [j].do_bandwidth_test == BOOLEAN_FALSE)
 
183
                {       puts ("    Bandwith test not performed on this converter.\n") ;
 
184
                        continue ;
 
185
                        }
 
186
 
 
187
                freq3dB = bandwidth_test (converter, verbose) ;
 
188
 
 
189
                printf ("    Measured -3dB rolloff point      : %5.2f %%.\n\n", freq3dB) ;
 
190
                } ;
 
191
 
 
192
        return 0 ;
 
193
} /* main */
 
194
 
 
195
/*==============================================================================
 
196
*/
 
197
 
 
198
static double
 
199
snr_test (SINGLE_TEST *test_data, int number, int converter, int verbose, double *conversion_rate)
 
200
{       static float data [BUFFER_LEN + 1] ;
 
201
        static float output [MAX_SPEC_LEN] ;
 
202
 
 
203
        SRC_STATE       *src_state ;
 
204
        SRC_DATA        src_data ;
 
205
 
 
206
        clock_t start_clock, clock_time ;
 
207
 
 
208
        double          output_peak, snr ;
 
209
        int             k, output_len, input_len, error ;
 
210
 
 
211
        if (verbose != 0)
 
212
        {       printf ("\tSignal-to-Noise Ratio Test %d.\n"
 
213
                                "\t=====================================\n", number) ;
 
214
                printf ("\tFrequencies : [ ") ;
 
215
                for (k = 0 ; k < test_data->freq_count ; k++)
 
216
                        printf ("%6.4f ", test_data->freqs [k]) ;
 
217
 
 
218
                printf ("]\n\tSRC Ratio   : %8.4f\n", test_data->src_ratio) ;
 
219
                }
 
220
        else
 
221
        {       printf ("\tSignal-to-Noise Ratio Test %d : ", number) ;
 
222
                fflush (stdout) ;
 
223
                } ;
 
224
 
 
225
        /* Set up the output array. */
 
226
        if (test_data->src_ratio >= 1.0)
 
227
        {       output_len = MAX_SPEC_LEN ;
 
228
                input_len = (int) ceil (MAX_SPEC_LEN / test_data->src_ratio) ;
 
229
                if (input_len > BUFFER_LEN)
 
230
                        input_len = BUFFER_LEN ;
 
231
                }
 
232
        else
 
233
        {       input_len = BUFFER_LEN ;
 
234
                output_len = (int) ceil (BUFFER_LEN * test_data->src_ratio) ;
 
235
                output_len &= ((-1) << 4) ;
 
236
                if (output_len > MAX_SPEC_LEN)
 
237
                        output_len = MAX_SPEC_LEN ;
 
238
                input_len = (int) ceil (output_len / test_data->src_ratio) ;
 
239
                } ;
 
240
 
 
241
        memset (output, 0, sizeof (output)) ;
 
242
 
 
243
        /* Generate input data array. */
 
244
        gen_windowed_sines (data, input_len, test_data->freqs, test_data->freq_count) ;
 
245
 
 
246
        /* Perform sample rate conversion. */
 
247
        if ((src_state = src_new (converter, 1, &error)) == NULL)
 
248
        {       printf ("\n\nLine %d : src_new() failed : %s.\n\n", __LINE__, src_strerror (error)) ;
 
249
                exit (1) ;
 
250
                } ;
 
251
 
 
252
        src_data.end_of_input = 1 ; /* Only one buffer worth of input. */
 
253
 
 
254
        src_data.data_in = data ;
 
255
        src_data.input_frames = input_len ;
 
256
 
 
257
        src_data.src_ratio = test_data->src_ratio ;
 
258
 
 
259
        src_data.data_out = output ;
 
260
        src_data.output_frames = output_len ;
 
261
 
 
262
        start_clock = clock () ;
 
263
        if ((error = src_process (src_state, &src_data)))
 
264
        {       printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
 
265
                exit (1) ;
 
266
                } ;
 
267
 
 
268
        clock_time = clock () - start_clock ;
 
269
 
 
270
        src_state = src_delete (src_state) ;
 
271
 
 
272
        if (clock_time <= 0)
 
273
                clock_time = 1 ;
 
274
 
 
275
        *conversion_rate = (1.0 * output_len * CLOCKS_PER_SEC) / clock_time ;
 
276
        if (test_data->src_ratio < 1.0)
 
277
                *conversion_rate /= test_data->src_ratio ;
 
278
 
 
279
        if (verbose != 0)
 
280
        {       printf ("\tOutput Rate :   %.0f samples/sec\n", *conversion_rate) ;
 
281
 
 
282
                printf ("\tOutput Len  :   %ld\n", src_data.output_frames_gen) ;
 
283
                } ;
 
284
 
 
285
        if (abs (src_data.output_frames_gen - output_len) > 4)
 
286
        {       printf ("\n\nLine %d : output data length should be %d.\n\n", __LINE__, output_len) ;
 
287
                exit (1) ;
 
288
                } ;
 
289
 
 
290
        /* Check output peak. */
 
291
        output_peak = find_peak (output, src_data.output_frames_gen) ;
 
292
 
 
293
        if (verbose != 0)
 
294
                printf ("\tOutput Peak :   %6.4f\n", output_peak) ;
 
295
 
 
296
        if (fabs (output_peak - test_data->peak_value) > 0.01)
 
297
        {       printf ("\n\nLine %d : output peak (%6.4f) should be %6.4f\n\n", __LINE__, output_peak, test_data->peak_value) ;
 
298
                save_oct_float ("snr_test.dat", data, BUFFER_LEN, output, output_len) ;
 
299
                exit (1) ;
 
300
                } ;
 
301
 
 
302
        /* Calculate signal-to-noise ratio. */
 
303
        snr = calculate_snr (output, src_data.output_frames_gen) ;
 
304
 
 
305
        if (snr < 0.0)
 
306
        {       /* An error occurred. */
 
307
                save_oct_float ("snr_test.dat", data, BUFFER_LEN, output, src_data.output_frames_gen) ;
 
308
                exit (1) ;
 
309
                } ;
 
310
 
 
311
        if (verbose != 0)
 
312
                printf ("\tSNR Ratio   :   %.2f dB\n", snr) ;
 
313
 
 
314
        if (snr < test_data->snr)
 
315
        {       printf ("\n\nLine %d : SNR (%5.2f) should be > %6.2f dB\n\n", __LINE__, snr, test_data->snr) ;
 
316
                exit (1) ;
 
317
                } ;
 
318
 
 
319
        if (verbose != 0)
 
320
                puts ("\t-------------------------------------\n\tPass\n") ;
 
321
        else
 
322
                puts ("Pass") ;
 
323
 
 
324
        return snr ;
 
325
} /* snr_test */
 
326
 
 
327
static double
 
328
find_peak (float *data, int len)
 
329
{       double  peak = 0.0 ;
 
330
        int             k = 0 ;
 
331
 
 
332
        for (k = 0 ; k < len ; k++)
 
333
                if (fabs (data [k]) > peak)
 
334
                        peak = fabs (data [k]) ;
 
335
 
 
336
        return peak ;
 
337
} /* find_peak */
 
338
 
 
339
 
 
340
static double
 
341
find_attenuation (double freq, int converter, int verbose)
 
342
{       static float input      [BUFFER_LEN] ;
 
343
        static float output [2 * BUFFER_LEN] ;
 
344
 
 
345
        SRC_DATA        src_data ;
 
346
        double          output_peak ;
 
347
        int                     error ;
 
348
 
 
349
        gen_windowed_sines (input, BUFFER_LEN, &freq, 1) ;
 
350
 
 
351
        src_data.end_of_input = 1 ; /* Only one buffer worth of input. */
 
352
 
 
353
        src_data.data_in = input ;
 
354
        src_data.input_frames = BUFFER_LEN ;
 
355
 
 
356
        src_data.src_ratio = 1.999 ;
 
357
 
 
358
        src_data.data_out = output ;
 
359
        src_data.output_frames = ARRAY_LEN (output) ;
 
360
 
 
361
        if ((error = src_simple (&src_data, converter, 1)))
 
362
        {       printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
 
363
                exit (1) ;
 
364
                } ;
 
365
 
 
366
        output_peak = find_peak (output, ARRAY_LEN (output)) ;
 
367
 
 
368
        if (verbose)
 
369
                printf ("\tFreq : %6f   InPeak : %6f    OutPeak : %6f   Atten : %6.2f dB\n",
 
370
                                freq, 1.0, output_peak, 20.0 * log10 (1.0 / output_peak)) ;
 
371
 
 
372
        return 20.0 * log10 (1.0 / output_peak) ;
 
373
} /* find_attenuation */
 
374
 
 
375
static double
 
376
bandwidth_test (int converter, int verbose)
 
377
{       double  f1, f2, a1, a2 ;
 
378
        double  freq, atten ;
 
379
 
 
380
        f1 = 0.35 ;
 
381
        a1 = find_attenuation (f1, converter, verbose) ;
 
382
 
 
383
        f2 = 0.495 ;
 
384
        a2 = find_attenuation (f2, converter, verbose) ;
 
385
 
 
386
        if (a1 > 3.0 || a2 < 3.0)
 
387
        {       printf ("\n\nLine %d : cannot bracket 3dB point.\n\n", __LINE__) ;
 
388
                exit (1) ;
 
389
                } ;
 
390
 
 
391
        while (a2 - a1 > 1.0)
 
392
        {       freq = f1 + 0.5 * (f2 - f1) ;
 
393
                atten = find_attenuation (freq, converter, verbose) ;
 
394
 
 
395
                if (atten < 3.0)
 
396
                {       f1 = freq ;
 
397
                        a1 = atten ;
 
398
                        }
 
399
                else
 
400
                {       f2 = freq ;
 
401
                        a2 = atten ;
 
402
                        } ;
 
403
                } ;
 
404
 
 
405
        freq = f1 + (3.0 - a1) * (f2 - f1) / (a2 - a1) ;
 
406
 
 
407
        return 200.0 * freq ;
 
408
} /* bandwidth_test */
 
409
 
 
410
#else /* (HAVE_FFTW3) == 0 */
 
411
 
 
412
/* Alternative main function when librfftw is not available. */
 
413
 
 
414
int
 
415
main (void)
 
416
{       puts ("\n"
 
417
                "****************************************************************\n"
 
418
                " This test cannot be run without FFTW (http://www.fftw.org/).\n"
 
419
                " Both the real and the complex versions of the library are\n"
 
420
                " required.") ;
 
421
 
 
422
#if (defined (WIN32) || defined (_WIN32))
 
423
        puts (" It it not known whether FFTW compiles and runs on Win32.") ;
 
424
#endif
 
425
        puts ("****************************************************************\n") ;
 
426
 
 
427
        return 0 ;
 
428
} /* main */
 
429
 
 
430
#endif
 
431
 
 
432
/*
 
433
** Do not edit or modify anything in this comment block.
 
434
** The arch-tag line is a file identity tag for the GNU Arch 
 
435
** revision control system.
 
436
**
 
437
** arch-tag: c31544f5-637f-4640-953b-1f3f71de11b6
 
438
*/
 
439