comparison spandsp-0.0.3/spandsp-0.0.3/tests/g722_tests.c @ 5:f762bf195c4b

import spandsp-0.0.3
author Peter Meerwald <pmeerw@cosy.sbg.ac.at>
date Fri, 25 Jun 2010 16:00:21 +0200
parents
children
comparison
equal deleted inserted replaced
4:26cd8f1ef0b1 5:f762bf195c4b
1 /*
2 * SpanDSP - a series of DSP components for telephony
3 *
4 * g722_tests.c - Test G.722 encode and decode.
5 *
6 * Written by Steve Underwood <steveu@coppice.org>
7 *
8 * Copyright (C) 2005 Steve Underwood
9 *
10 * All rights reserved.
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2, as
14 * published by the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 * $Id: g722_tests.c,v 1.17 2006/11/19 14:07:27 steveu Exp $
26 */
27
28 /*! \file */
29
30 /*! \page g722_tests_page G.722 tests
31 \section g722_tests_page_sec_1 What does it do?
32 This modules implements two sets of tests:
33 - The tests defined in the G.722 specification, using the test data files supplied
34 with the specification.
35 - A generally audio quality test, consisting of compressing and decompressing a speeech
36 file for audible comparison.
37
38 The speech file should be recorded at 16 bits/sample, 16000 samples/second, and named
39 "pre_g722.wav".
40
41 The ITU tests use the codec in a special mode, in which the QMFs, which split and recombine the
42 sub-bands, are disabled. This means they do not test 100% of the codec. This is the reason for
43 including the additional listening test.
44
45 \section g722_tests_page_sec_2 How is it used?
46 To perform the tests in the G.722 specification you need to obtain the test data files from the
47 specification. These are copyright material, and so cannot be distributed with spandsp.
48
49 The files, containing test vectors, which are supplied with the G.722 specification, should be
50 copied to itutests/g722. The ITU tests can then be run by executing g722_tests without
51 any parameters.
52
53 To perform a general audio quality test, g722_tests should be run with a parameter specifying
54 the required bit rate for compression. The valid parameters are "-48", "-56", and "-64".
55 The file ../localtests/short_wb_voice.wav will be compressed to the specified bit rate, decompressed,
56 and the resulting audio stored in post_g722.wav.
57 */
58
59 #ifdef HAVE_CONFIG_H
60 #include <config.h>
61 #endif
62
63 #include <stdlib.h>
64 #include <unistd.h>
65 #include <stdio.h>
66 #include <fcntl.h>
67 #include <inttypes.h>
68 #include <memory.h>
69 #include <stdlib.h>
70 #if defined(HAVE_TGMATH_H)
71 #include <tgmath.h>
72 #endif
73 #if defined(HAVE_MATH_H)
74 #include <math.h>
75 #endif
76 #include <audiofile.h>
77 #include <ctype.h>
78 #include <tiffio.h>
79
80 #include "spandsp.h"
81
82 #define G722_SAMPLE_RATE 16000
83
84 #define BLOCK_LEN 320
85
86 #define MAX_TEST_VECTOR_LEN 40000
87
88 #define TESTDATA_DIR "../itutests/g722/"
89
90 #define EIGHTK_IN_FILE_NAME "../localtests/short_nb_voice.wav"
91 #define IN_FILE_NAME "../localtests/short_wb_voice.wav"
92 #define OUT_FILE_NAME "post_g722.wav"
93
94 #if 0
95 static const char *itu_test_files[] =
96 {
97 TESTDATA_DIR "T1C1.XMT", /* 69973 bytes */
98 TESTDATA_DIR "T1C2.XMT", /* 3605 bytes */
99 TESTDATA_DIR "T1D3.COD", /* 69973 bytes */
100
101 TESTDATA_DIR "T2R1.COD", /* 69973 bytes */
102 TESTDATA_DIR "T2R2.COD", /* 3605 bytes */
103
104 TESTDATA_DIR "T3L1.RC1", /* 69973 bytes */
105 TESTDATA_DIR "T3L1.RC2", /* 69973 bytes */
106 TESTDATA_DIR "T3L1.RC3", /* 69973 bytes */
107 TESTDATA_DIR "T3H1.RC0", /* 69973 bytes */
108 TESTDATA_DIR "T3L2.RC1", /* 3605 bytes */
109 TESTDATA_DIR "T3L2.RC2", /* 3605 bytes */
110 TESTDATA_DIR "T3L2.RC3", /* 3605 bytes */
111 TESTDATA_DIR "T3H2.RC0", /* 3605 bytes */
112 TESTDATA_DIR "T3L3.RC1", /* 69973 bytes */
113 TESTDATA_DIR "T3L3.RC2", /* 69973 bytes */
114 TESTDATA_DIR "T3L3.RC3", /* 69973 bytes */
115 TESTDATA_DIR "T3H3.RC0" /* 69973 bytes */
116 };
117 #endif
118
119 static const char *encode_test_files[] =
120 {
121 TESTDATA_DIR "T1C1.XMT", TESTDATA_DIR "T2R1.COD",
122 TESTDATA_DIR "T1C2.XMT", TESTDATA_DIR "T2R2.COD",
123 NULL
124 };
125
126 static const char *decode_test_files[] =
127 {
128 TESTDATA_DIR "T2R1.COD",
129 TESTDATA_DIR "T3L1.RC1",
130 TESTDATA_DIR "T3L1.RC2",
131 TESTDATA_DIR "T3L1.RC3",
132 TESTDATA_DIR "T3H1.RC0",
133
134 TESTDATA_DIR "T2R2.COD",
135 TESTDATA_DIR "T3L2.RC1",
136 TESTDATA_DIR "T3L2.RC2",
137 TESTDATA_DIR "T3L2.RC3",
138 TESTDATA_DIR "T3H2.RC0",
139
140 TESTDATA_DIR "T1D3.COD",
141 TESTDATA_DIR "T3L3.RC1",
142 TESTDATA_DIR "T3L3.RC2",
143 TESTDATA_DIR "T3L3.RC3",
144 TESTDATA_DIR "T3H3.RC0",
145
146 NULL
147 };
148
149 int16_t itu_data[MAX_TEST_VECTOR_LEN];
150 uint16_t itu_ref[MAX_TEST_VECTOR_LEN];
151 uint16_t itu_ref_upper[MAX_TEST_VECTOR_LEN];
152 uint8_t compressed[MAX_TEST_VECTOR_LEN];
153 int16_t decompressed[MAX_TEST_VECTOR_LEN];
154
155 static int hex_get(char *s)
156 {
157 int i;
158 int value;
159 int x;
160
161 for (value = i = 0; i < 4; i++)
162 {
163 x = *s++ - 0x30;
164 if (x > 9)
165 x -= 0x07;
166 if (x > 15)
167 x -= 0x20;
168 if (x < 0 || x > 15)
169 return -1;
170 value <<= 4;
171 value |= x;
172 }
173 return value;
174 }
175 /*- End of function --------------------------------------------------------*/
176
177 static int get_vector(FILE *file, uint16_t vec[])
178 {
179 char buf[132 + 1];
180 char *s;
181 int i;
182 int value;
183
184 while (fgets(buf, 133, file))
185 {
186 if (buf[0] == '/' && buf[1] == '*')
187 continue;
188 s = buf;
189 i = 0;
190 while ((value = hex_get(s)) >= 0)
191 {
192 vec[i++] = value;
193 s += 4;
194 }
195 return i;
196 }
197 return 0;
198 }
199 /*- End of function --------------------------------------------------------*/
200
201 static int get_test_vector(const char *file, uint16_t buf[], int max_len)
202 {
203 int octets;
204 int i;
205 FILE *infile;
206
207 if ((infile = fopen(file, "r")) == NULL)
208 {
209 fprintf(stderr, " Failed to open '%s'\n", file);
210 exit(2);
211 }
212 octets = 0;
213 while ((i = get_vector(infile, buf + octets)) > 0)
214 octets += i;
215 fclose(infile);
216 return octets;
217 }
218 /*- End of function --------------------------------------------------------*/
219
220 int main(int argc, char *argv[])
221 {
222 g722_encode_state_t enc_state;
223 g722_decode_state_t dec_state;
224 int len;
225 int len_comp;
226 int len_comp_upper;
227 int len_data;
228 int len2;
229 int len3;
230 int i;
231 int j;
232 int k;
233 int file;
234 AFfilehandle inhandle;
235 AFfilehandle outhandle;
236 AFfilesetup filesetup;
237 int outframes;
238 int samples;
239 int mode;
240 int itutests;
241 int bit_rate;
242 int eight_k_in;
243 int eight_k_out;
244 float x;
245 int16_t indata[BLOCK_LEN];
246 int16_t outdata[BLOCK_LEN];
247 uint8_t adpcmdata[BLOCK_LEN];
248
249 i = 1;
250 bit_rate = 64000;
251 eight_k_in = FALSE;
252 eight_k_out = FALSE;
253 itutests = TRUE;
254 while (argc > i)
255 {
256 if (strcmp(argv[i], "-48") == 0)
257 {
258 bit_rate = 48000;
259 itutests = FALSE;
260 i++;
261 }
262 else if (strcmp(argv[i], "-56") == 0)
263 {
264 bit_rate = 56000;
265 itutests = FALSE;
266 i++;
267 }
268 else if (strcmp(argv[i], "-64") == 0)
269 {
270 bit_rate = 64000;
271 itutests = FALSE;
272 i++;
273 }
274 else if (strcmp(argv[i], "-8k8k") == 0)
275 {
276 eight_k_in = TRUE;
277 eight_k_out = TRUE;
278 i++;
279 }
280 else if (strcmp(argv[i], "-8k16k") == 0)
281 {
282 eight_k_in = TRUE;
283 eight_k_out = FALSE;
284 i++;
285 }
286 else if (strcmp(argv[i], "-16k8k") == 0)
287 {
288 eight_k_in = FALSE;
289 eight_k_out = TRUE;
290 i++;
291 }
292 else if (strcmp(argv[i], "-16k16k") == 0)
293 {
294 eight_k_in = FALSE;
295 eight_k_out = FALSE;
296 i++;
297 }
298 else
299 {
300 fprintf(stderr, "Unknown parameter %s specified.\n", argv[i]);
301 exit(2);
302 }
303 }
304
305 if (itutests)
306 {
307 /* ITU G.722 encode tests, using configuration 1. The QMF is bypassed */
308 for (file = 0; encode_test_files[file]; file += 2)
309 {
310 printf("Testing %s -> %s\n", encode_test_files[file], encode_test_files[file + 1]);
311
312 /* Get the input data */
313 len_data = get_test_vector(encode_test_files[file], (uint16_t *) itu_data, MAX_TEST_VECTOR_LEN);
314
315 /* Get the reference output data */
316 len_comp = get_test_vector(encode_test_files[file + 1], itu_ref, MAX_TEST_VECTOR_LEN);
317
318 /* Process the input data */
319 /* Skip the reset stuff at each end of the data */
320 for (i = 0; i < len_data; i++)
321 {
322 if ((itu_data[i] & 1) == 0)
323 break;
324 }
325 for (j = i; j < len_data; j++)
326 {
327 if ((itu_data[j] & 1))
328 break;
329 }
330 len = j - i;
331 g722_encode_init(&enc_state, 64000, FALSE);
332 enc_state.itu_test_mode = TRUE;
333 len2 = g722_encode(&enc_state, compressed, itu_data + i, len);
334
335 /* Check the result against the ITU's reference output data */
336 j = 0;
337 for (k = 0; k < len2; k++)
338 {
339 if ((compressed[k] & 0xFF) != ((itu_ref[k + i] >> 8) & 0xFF))
340 {
341 printf(">>> %6d %4x %4x\n", k, compressed[k] & 0xFF, itu_ref[k + i] & 0xFFFF);
342 j++;
343 }
344 }
345 printf("%d bad samples, out of %d/%d samples\n", j, len, len_data);
346 if (j)
347 {
348 printf("Test failed\n");
349 exit(2);
350 }
351 printf("Test passed\n");
352 }
353
354 /* ITU G.722 decode tests, using configuration 2. The QMF is bypassed */
355 /* Run each of the tests for each of the modes - 48kbps, 56kbps and 64kbps. */
356 for (mode = 1; mode <= 3; mode++)
357 {
358 for (file = 0; decode_test_files[file]; file += 5)
359 {
360 printf("Testing mode %d, %s -> %s + %s\n",
361 mode,
362 decode_test_files[file],
363 decode_test_files[file + mode],
364 decode_test_files[file + 4]);
365
366 /* Get the input data */
367 len_data = get_test_vector(decode_test_files[file], (uint16_t *) itu_data, MAX_TEST_VECTOR_LEN);
368
369 /* Get the lower reference output data */
370 len_comp = get_test_vector(decode_test_files[file + mode], itu_ref, MAX_TEST_VECTOR_LEN);
371
372 /* Get the upper reference output data */
373 len_comp_upper = get_test_vector(decode_test_files[file + 4], itu_ref_upper, MAX_TEST_VECTOR_LEN);
374
375 /* Process the input data */
376 /* Skip the reset stuff at each end of the data */
377 for (i = 0; i < len_data; i++)
378 {
379 if ((itu_data[i] & 1) == 0)
380 break;
381 }
382 for (j = i; j < len_data; j++)
383 {
384 if ((itu_data[j] & 1))
385 break;
386 }
387 len = j - i;
388 for (k = 0; k < len; k++)
389 compressed[k] = itu_data[k + i] >> ((mode == 3) ? 10 : (mode == 2) ? 9 : 8);
390
391 g722_decode_init(&dec_state, (mode == 3) ? 48000 : (mode == 2) ? 56000 : 64000, FALSE);
392 dec_state.itu_test_mode = TRUE;
393 len2 = g722_decode(&dec_state, decompressed, compressed, len);
394
395 /* Check the result against the ITU's reference output data */
396 j = 0;
397 for (k = 0; k < len2; k += 2)
398 {
399 if ((decompressed[k] & 0xFFFF) != (itu_ref[(k >> 1) + i] & 0xFFFF)
400 ||
401 (decompressed[k + 1] & 0xFFFF) != (itu_ref_upper[(k >> 1) + i] & 0xFFFF))
402 {
403 printf(">>> %6d %4x %4x %4x %4x\n", k >> 1, decompressed[k] & 0xFFFF, decompressed[k + 1] & 0xFFFF, itu_ref[(k >> 1) + i] & 0xFFFF, itu_ref_upper[(k >> 1) + i] & 0xFFFF);
404 j++;
405 }
406 }
407 printf("%d bad samples, out of %d/%d samples\n", j, len, len_data);
408 if (j)
409 {
410 printf("Test failed\n");
411 exit(2);
412 }
413 printf("Test passed\n");
414 }
415 }
416
417 printf("Tests passed.\n");
418 }
419 else
420 {
421 if (eight_k_in)
422 {
423 if ((inhandle = afOpenFile(EIGHTK_IN_FILE_NAME, "r", NULL)) == AF_NULL_FILEHANDLE)
424 {
425 fprintf(stderr, " Cannot open wave file '%s'\n", EIGHTK_IN_FILE_NAME);
426 exit(2);
427 }
428 if ((x = afGetFrameSize(inhandle, AF_DEFAULT_TRACK, 1)) != 2.0)
429 {
430 printf(" Unexpected frame size in wave file '%s'\n", EIGHTK_IN_FILE_NAME);
431 exit(2);
432 }
433 if ((x = afGetRate(inhandle, AF_DEFAULT_TRACK)) != (float) SAMPLE_RATE)
434 {
435 printf(" Unexpected sample rate %f in wave file '%s'\n", x, EIGHTK_IN_FILE_NAME);
436 exit(2);
437 }
438 if ((x = afGetChannels(inhandle, AF_DEFAULT_TRACK)) != 1.0)
439 {
440 printf(" Unexpected number of channels in wave file '%s'\n", EIGHTK_IN_FILE_NAME);
441 exit(2);
442 }
443 }
444 else
445 {
446 if ((inhandle = afOpenFile(IN_FILE_NAME, "r", NULL)) == AF_NULL_FILEHANDLE)
447 {
448 fprintf(stderr, " Cannot open wave file '%s'\n", IN_FILE_NAME);
449 exit(2);
450 }
451 if ((x = afGetFrameSize(inhandle, AF_DEFAULT_TRACK, 1)) != 2.0)
452 {
453 printf(" Unexpected frame size in wave file '%s'\n", IN_FILE_NAME);
454 exit(2);
455 }
456 if ((x = afGetRate(inhandle, AF_DEFAULT_TRACK)) != (float) G722_SAMPLE_RATE)
457 {
458 printf(" Unexpected sample rate %f in wave file '%s'\n", x, IN_FILE_NAME);
459 exit(2);
460 }
461 if ((x = afGetChannels(inhandle, AF_DEFAULT_TRACK)) != 1.0)
462 {
463 printf(" Unexpected number of channels in wave file '%s'\n", IN_FILE_NAME);
464 exit(2);
465 }
466 }
467
468 if ((filesetup = afNewFileSetup()) == AF_NULL_FILESETUP)
469 {
470 fprintf(stderr, " Failed to create file setup\n");
471 exit(2);
472 }
473 afInitSampleFormat(filesetup, AF_DEFAULT_TRACK, AF_SAMPFMT_TWOSCOMP, 16);
474 if (eight_k_out)
475 afInitRate(filesetup, AF_DEFAULT_TRACK, (float) SAMPLE_RATE);
476 else
477 afInitRate(filesetup, AF_DEFAULT_TRACK, (float) G722_SAMPLE_RATE);
478 afInitFileFormat(filesetup, AF_FILE_WAVE);
479 afInitChannels(filesetup, AF_DEFAULT_TRACK, 1);
480 if ((outhandle = afOpenFile(OUT_FILE_NAME, "w", filesetup)) == AF_NULL_FILEHANDLE)
481 {
482 fprintf(stderr, " Cannot create wave file '%s'\n", OUT_FILE_NAME);
483 exit(2);
484 }
485 if (eight_k_in)
486 g722_encode_init(&enc_state, bit_rate, G722_PACKED | G722_SAMPLE_RATE_8000);
487 else
488 g722_encode_init(&enc_state, bit_rate, G722_PACKED);
489 if (eight_k_out)
490 g722_decode_init(&dec_state, bit_rate, G722_PACKED | G722_SAMPLE_RATE_8000);
491 else
492 g722_decode_init(&dec_state, bit_rate, G722_PACKED);
493 for (;;)
494 {
495 samples = afReadFrames(inhandle,
496 AF_DEFAULT_TRACK,
497 indata,
498 BLOCK_LEN);
499 if (samples <= 0)
500 break;
501 len2 = g722_encode(&enc_state, adpcmdata, indata, samples);
502 len3 = g722_decode(&dec_state, outdata, adpcmdata, len2);
503 outframes = afWriteFrames(outhandle,
504 AF_DEFAULT_TRACK,
505 outdata,
506 len3);
507 if (outframes != len3)
508 {
509 fprintf(stderr, " Error writing wave file\n");
510 exit(2);
511 }
512 }
513 if (afCloseFile(inhandle))
514 {
515 fprintf(stderr, " Cannot close wave file '%s'\n", IN_FILE_NAME);
516 exit(2);
517 }
518 if (afCloseFile(outhandle))
519 {
520 fprintf(stderr, " Cannot close wave file '%s'\n", OUT_FILE_NAME);
521 exit(2);
522 }
523 afFreeFileSetup(filesetup);
524
525 printf("'%s' transcoded to '%s' at %dbps.\n", IN_FILE_NAME, OUT_FILE_NAME, bit_rate);
526 }
527 return 0;
528 }
529 /*- End of function --------------------------------------------------------*/
530 /*- End of file ------------------------------------------------------------*/

Repositories maintained by Peter Meerwald, pmeerw@pmeerw.net.