comparison spandsp-0.0.6pre17/tests/g722_tests.c @ 4:26cd8f1ef0b1

import spandsp-0.0.6pre17
author Peter Meerwald <pmeerw@cosy.sbg.ac.at>
date Fri, 25 Jun 2010 15:50:58 +0200
parents
children
comparison
equal deleted inserted replaced
3:c6c5a16ce2f2 4:26cd8f1ef0b1
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.32 2009/06/02 14:55:36 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 this test software.
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 ../test-data/local/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 /* Enable the following definition to enable direct probing into the FAX structures */
60 //#define WITH_SPANDSP_INTERNALS
61
62 #if defined(HAVE_CONFIG_H)
63 #include <config.h>
64 #endif
65
66 #include <stdlib.h>
67 #include <stdio.h>
68 #include <fcntl.h>
69 #include <unistd.h>
70 #include <memory.h>
71 #include <ctype.h>
72 #include <sndfile.h>
73
74 #include "spandsp.h"
75
76 #if 1 //defined(WITH_SPANDSP_INTERNALS)
77 #include "spandsp/private/g722.h"
78 #endif
79
80 #define G722_SAMPLE_RATE 16000
81
82 #define BLOCK_LEN 320
83
84 #define MAX_TEST_VECTOR_LEN 40000
85
86 #define TESTDATA_DIR "../test-data/itu/g722/"
87
88 #define EIGHTK_IN_FILE_NAME "../test-data/local/short_nb_voice.wav"
89 #define IN_FILE_NAME "../test-data/local/short_wb_voice.wav"
90 #define ENCODED_FILE_NAME "g722.g722"
91 #define OUT_FILE_NAME "post_g722.wav"
92
93 #if 0
94 static const char *itu_test_files[] =
95 {
96 TESTDATA_DIR "T1C1.XMT", /* 69973 bytes */
97 TESTDATA_DIR "T1C2.XMT", /* 3605 bytes */
98 TESTDATA_DIR "T1D3.COD", /* 69973 bytes */
99
100 TESTDATA_DIR "T2R1.COD", /* 69973 bytes */
101 TESTDATA_DIR "T2R2.COD", /* 3605 bytes */
102
103 TESTDATA_DIR "T3L1.RC1", /* 69973 bytes */
104 TESTDATA_DIR "T3L1.RC2", /* 69973 bytes */
105 TESTDATA_DIR "T3L1.RC3", /* 69973 bytes */
106 TESTDATA_DIR "T3H1.RC0", /* 69973 bytes */
107 TESTDATA_DIR "T3L2.RC1", /* 3605 bytes */
108 TESTDATA_DIR "T3L2.RC2", /* 3605 bytes */
109 TESTDATA_DIR "T3L2.RC3", /* 3605 bytes */
110 TESTDATA_DIR "T3H2.RC0", /* 3605 bytes */
111 TESTDATA_DIR "T3L3.RC1", /* 69973 bytes */
112 TESTDATA_DIR "T3L3.RC2", /* 69973 bytes */
113 TESTDATA_DIR "T3L3.RC3", /* 69973 bytes */
114 TESTDATA_DIR "T3H3.RC0" /* 69973 bytes */
115 };
116 #endif
117
118 static const char *encode_test_files[] =
119 {
120 TESTDATA_DIR "T1C1.XMT",
121 TESTDATA_DIR "T2R1.COD",
122 TESTDATA_DIR "T1C2.XMT",
123 TESTDATA_DIR "T2R2.COD",
124 NULL
125 };
126
127 static const char *decode_test_files[] =
128 {
129 TESTDATA_DIR "T2R1.COD",
130 TESTDATA_DIR "T3L1.RC1",
131 TESTDATA_DIR "T3L1.RC2",
132 TESTDATA_DIR "T3L1.RC3",
133 TESTDATA_DIR "T3H1.RC0",
134
135 TESTDATA_DIR "T2R2.COD",
136 TESTDATA_DIR "T3L2.RC1",
137 TESTDATA_DIR "T3L2.RC2",
138 TESTDATA_DIR "T3L2.RC3",
139 TESTDATA_DIR "T3H2.RC0",
140
141 TESTDATA_DIR "T1D3.COD",
142 TESTDATA_DIR "T3L3.RC1",
143 TESTDATA_DIR "T3L3.RC2",
144 TESTDATA_DIR "T3L3.RC3",
145 TESTDATA_DIR "T3H3.RC0",
146
147 NULL
148 };
149
150 int16_t itu_data[MAX_TEST_VECTOR_LEN];
151 uint16_t itu_ref[MAX_TEST_VECTOR_LEN];
152 uint16_t itu_ref_upper[MAX_TEST_VECTOR_LEN];
153 uint8_t compressed[MAX_TEST_VECTOR_LEN];
154 int16_t decompressed[MAX_TEST_VECTOR_LEN];
155
156 static int hex_get(char *s)
157 {
158 int i;
159 int value;
160 int x;
161
162 for (value = i = 0; i < 4; i++)
163 {
164 x = *s++ - 0x30;
165 if (x > 9)
166 x -= 0x07;
167 if (x > 15)
168 x -= 0x20;
169 if (x < 0 || x > 15)
170 return -1;
171 value <<= 4;
172 value |= x;
173 }
174 return value;
175 }
176 /*- End of function --------------------------------------------------------*/
177
178 static int get_vector(FILE *file, uint16_t vec[])
179 {
180 char buf[132 + 1];
181 char *s;
182 int i;
183 int value;
184
185 while (fgets(buf, 133, file))
186 {
187 if (buf[0] == '/' && buf[1] == '*')
188 continue;
189 s = buf;
190 i = 0;
191 while ((value = hex_get(s)) >= 0)
192 {
193 vec[i++] = value;
194 s += 4;
195 }
196 return i;
197 }
198 return 0;
199 }
200 /*- End of function --------------------------------------------------------*/
201
202 static int get_test_vector(const char *file, uint16_t buf[], int max_len)
203 {
204 int octets;
205 int i;
206 FILE *infile;
207
208 if ((infile = fopen(file, "r")) == NULL)
209 {
210 fprintf(stderr, " Failed to open '%s'\n", file);
211 exit(2);
212 }
213 octets = 0;
214 while ((i = get_vector(infile, buf + octets)) > 0)
215 octets += i;
216 fclose(infile);
217 return octets;
218 }
219 /*- End of function --------------------------------------------------------*/
220
221 static void itu_compliance_tests(void)
222 {
223 g722_encode_state_t enc_state;
224 g722_decode_state_t dec_state;
225 int i;
226 int j;
227 int k;
228 int len_comp;
229 int len_comp_upper;
230 int len_data;
231 int len;
232 int len2;
233 int mode;
234 int file;
235
236 #if 1
237 /* ITU G.722 encode tests, using configuration 1. The QMF is bypassed */
238 for (file = 0; encode_test_files[file]; file += 2)
239 {
240 printf("Testing %s -> %s\n", encode_test_files[file], encode_test_files[file + 1]);
241
242 /* Get the input data */
243 len_data = get_test_vector(encode_test_files[file], (uint16_t *) itu_data, MAX_TEST_VECTOR_LEN);
244
245 /* Get the reference output data */
246 len_comp = get_test_vector(encode_test_files[file + 1], itu_ref, MAX_TEST_VECTOR_LEN);
247
248 /* Process the input data */
249 /* Skip the reset stuff at each end of the data */
250 for (i = 0; i < len_data; i++)
251 {
252 if ((itu_data[i] & 1) == 0)
253 break;
254 }
255 for (j = i; j < len_data; j++)
256 {
257 if ((itu_data[j] & 1))
258 break;
259 }
260 len = j - i;
261 g722_encode_init(&enc_state, 64000, 0);
262 enc_state.itu_test_mode = TRUE;
263 len2 = g722_encode(&enc_state, compressed, itu_data + i, len);
264
265 /* Check the result against the ITU's reference output data */
266 j = 0;
267 for (k = 0; k < len2; k++)
268 {
269 if ((compressed[k] & 0xFF) != ((itu_ref[k + i] >> 8) & 0xFF))
270 {
271 printf(">>> %6d %4x %4x\n", k, compressed[k] & 0xFF, itu_ref[k + i] & 0xFFFF);
272 j++;
273 }
274 }
275 printf("%d bad samples, out of %d/%d samples\n", j, len, len_data);
276 if (j)
277 {
278 printf("Test failed\n");
279 exit(2);
280 }
281 printf("Test passed\n");
282 }
283 #endif
284 #if 1
285 /* ITU G.722 decode tests, using configuration 2. The QMF is bypassed */
286 /* Run each of the tests for each of the modes - 48kbps, 56kbps and 64kbps. */
287 for (mode = 1; mode <= 3; mode++)
288 {
289 for (file = 0; decode_test_files[file]; file += 5)
290 {
291 printf("Testing mode %d, %s -> %s + %s\n",
292 mode,
293 decode_test_files[file],
294 decode_test_files[file + mode],
295 decode_test_files[file + 4]);
296
297 /* Get the input data */
298 len_data = get_test_vector(decode_test_files[file], (uint16_t *) itu_data, MAX_TEST_VECTOR_LEN);
299
300 /* Get the lower reference output data */
301 len_comp = get_test_vector(decode_test_files[file + mode], itu_ref, MAX_TEST_VECTOR_LEN);
302
303 /* Get the upper reference output data */
304 len_comp_upper = get_test_vector(decode_test_files[file + 4], itu_ref_upper, MAX_TEST_VECTOR_LEN);
305
306 /* Process the input data */
307 /* Skip the reset stuff at each end of the data */
308 for (i = 0; i < len_data; i++)
309 {
310 if ((itu_data[i] & 1) == 0)
311 break;
312 }
313 for (j = i; j < len_data; j++)
314 {
315 if ((itu_data[j] & 1))
316 break;
317 }
318 len = j - i;
319 for (k = 0; k < len; k++)
320 compressed[k] = itu_data[k + i] >> ((mode == 3) ? 10 : (mode == 2) ? 9 : 8);
321
322 g722_decode_init(&dec_state, (mode == 3) ? 48000 : (mode == 2) ? 56000 : 64000, 0);
323 dec_state.itu_test_mode = TRUE;
324 len2 = g722_decode(&dec_state, decompressed, compressed, len);
325
326 /* Check the result against the ITU's reference output data */
327 j = 0;
328 for (k = 0; k < len2; k += 2)
329 {
330 if ((decompressed[k] & 0xFFFF) != (itu_ref[(k >> 1) + i] & 0xFFFF)
331 ||
332 (decompressed[k + 1] & 0xFFFF) != (itu_ref_upper[(k >> 1) + i] & 0xFFFF))
333 {
334 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);
335 j++;
336 }
337 }
338 printf("%d bad samples, out of %d/%d samples\n", j, len, len_data);
339 if (j)
340 {
341 printf("Test failed\n");
342 exit(2);
343 }
344 printf("Test passed\n");
345 }
346 }
347 #endif
348 printf("Tests passed.\n");
349 }
350 /*- End of function --------------------------------------------------------*/
351
352 int main(int argc, char *argv[])
353 {
354 g722_encode_state_t enc_state;
355 g722_decode_state_t dec_state;
356 int len2;
357 int len3;
358 int i;
359 int file;
360 SNDFILE *inhandle;
361 SNDFILE *outhandle;
362 SF_INFO info;
363 int outframes;
364 int samples;
365 int opt;
366 int itutests;
367 int bit_rate;
368 int eight_k_in;
369 int eight_k_out;
370 int encode;
371 int decode;
372 int tone_test;
373 const char *in_file;
374 const char *out_file;
375 int16_t indata[BLOCK_LEN];
376 int16_t outdata[BLOCK_LEN];
377 uint8_t adpcmdata[BLOCK_LEN];
378 float tone_level;
379 uint32_t tone_phase;
380 int32_t tone_phase_rate;
381
382 bit_rate = 64000;
383 eight_k_in = FALSE;
384 eight_k_out = FALSE;
385 itutests = TRUE;
386 encode = FALSE;
387 decode = FALSE;
388 tone_test = FALSE;
389 in_file = NULL;
390 out_file = NULL;
391 while ((opt = getopt(argc, argv, "b:d:e:i:l:o:t")) != -1)
392 {
393 switch (opt)
394 {
395 case 'b':
396 bit_rate = atoi(optarg);
397 if (bit_rate != 48000 && bit_rate != 56000 && bit_rate != 64000)
398 {
399 fprintf(stderr, "Invalid bit rate selected. Only 48000, 56000 and 64000 are valid.\n");
400 exit(2);
401 }
402 itutests = FALSE;
403 break;
404 case 'd':
405 in_file = optarg;
406 decode = TRUE;
407 itutests = FALSE;
408 break;
409 case 'e':
410 in_file = optarg;
411 encode = TRUE;
412 itutests = FALSE;
413 break;
414 case 'i':
415 i = atoi(optarg);
416 if (i != 8000 && i != 16000)
417 {
418 fprintf(stderr, "Invalid incoming sample rate. Only 8000 and 16000 are valid.\n");
419 exit(2);
420 }
421 eight_k_in = (i == 8000);
422 if (eight_k_in)
423 in_file = EIGHTK_IN_FILE_NAME;
424 break;
425 case 'l':
426 out_file = optarg;
427 break;
428 case 'o':
429 i = atoi(optarg);
430 if (i != 8000 && i != 16000)
431 {
432 fprintf(stderr, "Invalid outgoing sample rate. Only 8000 and 16000 are valid.\n");
433 exit(2);
434 }
435 eight_k_out = (i == 8000);
436 break;
437 case 't':
438 tone_test = TRUE;
439 itutests = FALSE;
440 break;
441 default:
442 //usage();
443 exit(2);
444 }
445 }
446
447 if (itutests)
448 {
449 itu_compliance_tests();
450 }
451 else
452 {
453 tone_level = dds_scaling_dbm0f(2.5f);
454 tone_phase = 0;
455 tone_phase_rate = dds_phase_ratef(1500.0f/2.0f);
456 if (!decode && !encode)
457 {
458 decode =
459 encode = TRUE;
460 }
461 if (in_file == NULL)
462 {
463 if (encode)
464 {
465 if (eight_k_in)
466 in_file = EIGHTK_IN_FILE_NAME;
467 else
468 in_file = IN_FILE_NAME;
469 }
470 else
471 {
472 in_file = ENCODED_FILE_NAME;
473 }
474 }
475 if (out_file == NULL)
476 {
477 out_file = (decode) ? OUT_FILE_NAME : ENCODED_FILE_NAME;
478 }
479 inhandle = NULL;
480 outhandle = NULL;
481 file = -1;
482 if (encode)
483 {
484 if (eight_k_in)
485 {
486 if ((inhandle = sf_open(in_file, SFM_READ, &info)) == NULL)
487 {
488 fprintf(stderr, " Cannot open audio file '%s'\n", in_file);
489 exit(2);
490 }
491 if (info.samplerate != SAMPLE_RATE)
492 {
493 fprintf(stderr, " Unexpected sample rate %d in audio file '%s'\n", info.samplerate, in_file);
494 exit(2);
495 }
496 if (info.channels != 1)
497 {
498 fprintf(stderr, " Unexpected number of channels in audio file '%s'\n", in_file);
499 exit(2);
500 }
501 }
502 else
503 {
504 if ((inhandle = sf_open(in_file, SFM_READ, &info)) == NULL)
505 {
506 fprintf(stderr, " Cannot open audio file '%s'\n", in_file);
507 exit(2);
508 }
509 if (info.samplerate != G722_SAMPLE_RATE)
510 {
511 fprintf(stderr, " Unexpected sample rate %d in audio file '%s'\n", info.samplerate, in_file);
512 exit(2);
513 }
514 if (info.channels != 1)
515 {
516 fprintf(stderr, " Unexpected number of channels in audio file '%s'\n", in_file);
517 exit(2);
518 }
519 }
520 if (eight_k_in)
521 g722_encode_init(&enc_state, bit_rate, G722_PACKED | G722_SAMPLE_RATE_8000);
522 else
523 g722_encode_init(&enc_state, bit_rate, G722_PACKED);
524 }
525 else
526 {
527 if ((file = open(in_file, O_RDONLY)) < 0)
528 {
529 fprintf(stderr, " Failed to open '%s'\n", in_file);
530 exit(2);
531 }
532 }
533 if (decode)
534 {
535 memset(&info, 0, sizeof(info));
536 info.frames = 0;
537 info.samplerate = (eight_k_out) ? SAMPLE_RATE : G722_SAMPLE_RATE;
538 info.channels = 1;
539 info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16;
540 info.sections = 1;
541 info.seekable = 1;
542 if ((outhandle = sf_open(out_file, SFM_WRITE, &info)) == NULL)
543 {
544 fprintf(stderr, " Cannot create audio file '%s'\n", out_file);
545 exit(2);
546 }
547 if (eight_k_out)
548 g722_decode_init(&dec_state, bit_rate, G722_PACKED | G722_SAMPLE_RATE_8000);
549 else
550 g722_decode_init(&dec_state, bit_rate, G722_PACKED);
551 }
552 else
553 {
554 if ((file = open(out_file, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0)
555 {
556 fprintf(stderr, " Failed to open '%s'\n", out_file);
557 exit(2);
558 }
559 }
560 for (;;)
561 {
562 if (encode)
563 {
564 samples = sf_readf_short(inhandle, indata, BLOCK_LEN);
565 if (samples <= 0)
566 break;
567 if (tone_test)
568 {
569 for (i = 0; i < samples; i++)
570 indata[i] = dds_modf(&tone_phase, tone_phase_rate, tone_level, 0);
571 }
572 len2 = g722_encode(&enc_state, adpcmdata, indata, samples);
573 }
574 else
575 {
576 len2 = read(file, adpcmdata, BLOCK_LEN);
577 if (len2 <= 0)
578 break;
579 }
580 if (decode)
581 {
582 len3 = g722_decode(&dec_state, outdata, adpcmdata, len2);
583 outframes = sf_writef_short(outhandle, outdata, len3);
584 if (outframes != len3)
585 {
586 fprintf(stderr, " Error writing audio file\n");
587 exit(2);
588 }
589 }
590 else
591 {
592 len3 = write(file, adpcmdata, len2);
593 if (len3 <= 0)
594 break;
595 }
596 }
597 if (encode)
598 {
599 if (sf_close(inhandle))
600 {
601 fprintf(stderr, " Cannot close audio file '%s'\n", IN_FILE_NAME);
602 exit(2);
603 }
604 }
605 else
606 {
607 close(file);
608 }
609 if (decode)
610 {
611 if (sf_close(outhandle))
612 {
613 fprintf(stderr, " Cannot close audio file '%s'\n", OUT_FILE_NAME);
614 exit(2);
615 }
616 }
617 else
618 {
619 close(file);
620 }
621 printf("'%s' translated to '%s' at %dbps.\n", in_file, out_file, bit_rate);
622 }
623 return 0;
624 }
625 /*- End of function --------------------------------------------------------*/
626 /*- End of file ------------------------------------------------------------*/

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