comparison spandsp-0.0.6pre17/tests/gsm0610_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 * gsm0610_tests.c - Test the GSM 06.10 FR codec.
5 *
6 * Written by Steve Underwood <steveu@coppice.org>
7 *
8 * Copyright (C) 2006 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: gsm0610_tests.c,v 1.25 2009/05/30 15:23:13 steveu Exp $
26 */
27
28 /*! \file */
29
30 /*! \page gsm0610_tests_page GSM 06.10 full rate codec tests
31 \section gsm0610_tests_page_sec_1 What does it do?
32 Two sets of tests are performed:
33 - The tests defined in the GSM 06.10 specification, using the test data files supplied with
34 the specification.
35 - A generally audio quality test, consisting of compressing and decompressing a speeech
36 file for audible comparison.
37
38 \section gsm0610_tests_page_sec_2 How is it used?
39 To perform the tests in the GSM 06.10 specification you need to obtain the test data files from the
40 specification. These are copyright material, and so cannot be distributed with this test software.
41 They can, however, be freely downloaded from the ETSI web site.
42
43 The files, containing test vectors, which are supplied with the GSM 06.10 specification, should be
44 copied to etsitests/gsm0610/unpacked so the files are arranged in the following directories.
45
46 ./fr_A:
47 Seq01-A.cod Seq01-A.inp Seq01-A.out
48 Seq02-A.cod Seq02-A.inp Seq02-A.out
49 Seq03-A.cod Seq03-A.inp Seq03-A.out
50 Seq04-A.cod Seq04-A.inp Seq04-A.out
51 Seq05-A.out
52
53 ./fr_L:
54 Seq01.cod Seq01.inp Seq01.out
55 Seq02.cod Seq02.inp Seq02.out
56 Seq03.cod Seq03.inp Seq03.out
57 Seq04.cod Seq04.inp Seq04.out
58 Seq05.cod Seq05.out
59
60 ./fr_U:
61 Seq01-U.cod Seq01-U.inp Seq01-U.out
62 Seq02-U.cod Seq02-U.inp Seq02-U.out
63 Seq03-U.cod Seq03-U.inp Seq03-U.out
64 Seq04-U.cod Seq04-U.inp Seq04-U.out
65 Seq05-U.out
66
67 ./fr_homing_A:
68 Homing01_A.out
69 Seq01H_A.cod Seq01H_A.inp Seq01H_A.out
70 Seq02H_A.cod Seq02H_A.inp Seq02H_A.out
71 Seq03H_A.cod Seq03H_A.inp Seq03H_A.out
72 Seq04H_A.cod Seq04H_A.inp Seq04H_A.out
73 Seq05H_A.out
74 Seq06H_A.cod Seq06H_A.inp
75
76 ./fr_homing_L:
77 Homing01.cod Homing01.out
78 Seq01h.cod Seq01h.inp Seq01h.out
79 Seq02h.cod Seq02h.inp Seq02h.out
80 Seq03h.cod Seq03h.inp Seq03h.out
81 Seq04h.cod Seq04h.inp Seq04h.out
82 Seq05h.cod Seq05h.out
83 Seq06h.cod Seq06h.inp
84
85 ./fr_homing_U:
86 Homing01_U.out
87 Seq01H_U.cod Seq01H_U.inp Seq01H_U.out
88 Seq02H_U.cod Seq02H_U.inp Seq02H_U.out
89 Seq03H_U.cod Seq03H_U.inp Seq03H_U.out
90 Seq04H_U.cod Seq04H_U.inp Seq04H_U.out
91 Seq05H_U.out
92 Seq06H_U.cod Seq06H_U.inp
93
94 ./fr_sync_A:
95 Seqsync_A.inp
96 Sync000_A.cod --to-- Sync159_A.cod
97
98 ./fr_sync_L:
99 Bitsync.inp
100 Seqsync.inp
101 Sync000.cod --to-- Sync159.cod
102
103 ./fr_sync_U:
104 Seqsync_U.inp
105 Sync000_U.cod --to-- Sync159_U.cod
106
107 This is different from the directory structure in which they are supplied. Also, the files names are a little
108 different. The supplied names are messy, and inconsistent across the sets. The names required by these tests
109 just clean up these inconsistencies. Note that you will need a Windows machine to unpack some of the supplied
110 files.
111
112 To perform a general audio quality test, gsm0610_tests should be run. The file ../test-data/local/short_nb_voice.wav
113 will be compressed to GSM 06.10 data, decompressed, and the resulting audio stored in post_gsm0610.wav.
114 */
115
116 #if defined(HAVE_CONFIG_H)
117 #include "config.h"
118 #endif
119
120 #include <stdlib.h>
121 #include <stdio.h>
122 #include <fcntl.h>
123 #include <unistd.h>
124 #include <string.h>
125 #include <ctype.h>
126 #include <sndfile.h>
127
128 //#if defined(WITH_SPANDSP_INTERNALS)
129 #define SPANDSP_EXPOSE_INTERNAL_STRUCTURES
130 //#endif
131
132 #include "spandsp.h"
133 #include "spandsp-sim.h"
134
135 #define BLOCK_LEN 160
136
137 #define TESTDATA_DIR "../test-data/etsi/gsm0610/unpacked/fr_"
138
139 #define IN_FILE_NAME "../test-data/local/short_nb_voice.wav"
140 #define OUT_FILE_NAME "post_gsm0610.wav"
141
142 #define HIST_LEN 1000
143
144 uint8_t law_in_vector[1000000];
145 int16_t in_vector[1000000];
146 uint16_t code_vector_buf[1000000];
147 uint8_t code_vector[1000000];
148 uint8_t ref_code_vector[1000000];
149 uint8_t decoder_code_vector[1000000];
150 uint8_t law_out_vector[1000000];
151 int16_t out_vector[1000000];
152 int16_t ref_out_vector[1000000];
153 uint8_t ref_law_out_vector[1000000];
154 int vector_len;
155
156 static int get_test_vector(int full, int disk, const char *name)
157 {
158 char buf[500];
159 int in;
160 int len;
161 int i;
162
163 if (full)
164 {
165 sprintf(buf, "%s%c/%s.inp", TESTDATA_DIR, 'L', name);
166 if ((in = open(buf, O_RDONLY)) < 0)
167 {
168 fprintf(stderr, "Cannot open %s\n", buf);
169 exit(2);
170 }
171 len = read(in, in_vector, 1000000);
172 close(in);
173 len /= sizeof(int16_t);
174 vector_len = len;
175 }
176
177 sprintf(buf, "%s%c/%s.out", TESTDATA_DIR, 'L', name);
178 if ((in = open(buf, O_RDONLY)) < 0)
179 {
180 fprintf(stderr, "Cannot open %s\n", buf);
181 exit(2);
182 }
183 len = read(in, ref_out_vector, 1000000);
184 close(in);
185 len /= sizeof(int16_t);
186 if (full)
187 {
188 if (len != vector_len)
189 {
190 fprintf(stderr, "Input and reference vector lengths do not match - %d %d\n", vector_len, len);
191 exit(2);
192 }
193 }
194 else
195 {
196 vector_len = len;
197 }
198
199 sprintf(buf, "%s%c/%s.cod", TESTDATA_DIR, 'L', name);
200 if ((in = open(buf, O_RDONLY)) < 0)
201 {
202 fprintf(stderr, "Cannot open %s\n", buf);
203 exit(2);
204 }
205 len = read(in, code_vector_buf, 1000000);
206 close(in);
207 len /= sizeof(int16_t);
208 for (i = 0; i < len; i++)
209 {
210 ref_code_vector[i] = code_vector_buf[i];
211 decoder_code_vector[i] = code_vector_buf[i];
212 }
213 if (len*BLOCK_LEN != vector_len*76)
214 {
215 fprintf(stderr, "Input and code vector lengths do not match - %d %d\n", vector_len, len);
216 exit(2);
217 }
218
219 return len;
220 }
221 /*- End of function --------------------------------------------------------*/
222
223 static int get_law_test_vector(int full, int law, const char *name)
224 {
225 char buf[500];
226 int in;
227 int len;
228 int i;
229 int law_uc;
230
231 law_uc = toupper(law);
232
233 if (full)
234 {
235 sprintf(buf, "%s%c/%s-%c.inp", TESTDATA_DIR, law_uc, name, law_uc);
236 if ((in = open(buf, O_RDONLY)) < 0)
237 {
238 fprintf(stderr, "Cannot open %s\n", buf);
239 exit(2);
240 }
241 len = read(in, law_in_vector, 1000000);
242 close(in);
243 vector_len = len;
244
245 sprintf(buf, "%s%c/%s-%c.cod", TESTDATA_DIR, law_uc, name, law_uc);
246 if ((in = open(buf, O_RDONLY)) < 0)
247 {
248 fprintf(stderr, "Cannot open %s\n", buf);
249 exit(2);
250 }
251 len = read(in, code_vector_buf, 1000000);
252 close(in);
253 len /= sizeof(int16_t);
254 for (i = 0; i < len; i++)
255 ref_code_vector[i] = code_vector_buf[i];
256 if (len*BLOCK_LEN != vector_len*76)
257 {
258 fprintf(stderr, "Input and code vector lengths do not match - %d %d\n", vector_len, len);
259 exit(2);
260 }
261 }
262
263 sprintf(buf, "%s%c/%s-%c.out", TESTDATA_DIR, law_uc, name, law_uc);
264 if ((in = open(buf, O_RDONLY)) < 0)
265 {
266 fprintf(stderr, "Cannot open %s\n", buf);
267 exit(2);
268 }
269 len = read(in, ref_law_out_vector, 1000000);
270 close(in);
271 if (full)
272 {
273 if (len != vector_len)
274 {
275 fprintf(stderr, "Input and reference vector lengths do not match - %d %d\n", vector_len, len);
276 exit(2);
277 }
278 }
279 else
280 {
281 vector_len = len;
282 }
283
284 sprintf(buf, "%s%c/%s.cod", TESTDATA_DIR, 'L', name);
285 if ((in = open(buf, O_RDONLY)) < 0)
286 {
287 fprintf(stderr, "Cannot open %s\n", buf);
288 exit(2);
289 }
290 len = read(in, code_vector_buf, 1000000);
291 close(in);
292 len /= sizeof(int16_t);
293 for (i = 0; i < len; i++)
294 decoder_code_vector[i] = code_vector_buf[i];
295
296 return len;
297 }
298 /*- End of function --------------------------------------------------------*/
299
300 static int perform_linear_test(int full, int disk, const char *name)
301 {
302 gsm0610_state_t *gsm0610_enc_state;
303 gsm0610_state_t *gsm0610_dec_state;
304 int i;
305 int xxx;
306 int mismatches;
307
308 printf("Performing linear test '%s' from disk %d\n", name, disk);
309
310 get_test_vector(full, disk, name);
311
312 if (full)
313 {
314 if ((gsm0610_enc_state = gsm0610_init(NULL, GSM0610_PACKING_NONE)) == NULL)
315 {
316 fprintf(stderr, " Cannot create encoder\n");
317 exit(2);
318 }
319 xxx = gsm0610_encode(gsm0610_enc_state, code_vector, in_vector, vector_len);
320
321 printf("Check code vector of length %d\n", xxx);
322 for (i = 0, mismatches = 0; i < xxx; i++)
323 {
324 if (code_vector[i] != ref_code_vector[i])
325 {
326 printf("%8d/%3d: %6d %6d\n", i/76, i%76, code_vector[i], ref_code_vector[i]);
327 mismatches++;
328 }
329 }
330 gsm0610_release(gsm0610_enc_state);
331 if (mismatches)
332 {
333 printf("Test failed: %d of %d samples mismatch\n", mismatches, xxx);
334 exit(2);
335 }
336 printf("Test passed\n");
337 }
338
339 if ((gsm0610_dec_state = gsm0610_init(NULL, GSM0610_PACKING_NONE)) == NULL)
340 {
341 fprintf(stderr, " Cannot create decoder\n");
342 exit(2);
343 }
344 xxx = gsm0610_decode(gsm0610_dec_state, out_vector, decoder_code_vector, vector_len);
345 printf("Check output vector of length %d\n", vector_len);
346 for (i = 0, mismatches = 0; i < vector_len; i++)
347 {
348 if (out_vector[i] != ref_out_vector[i])
349 {
350 printf("%8d: %6d %6d\n", i, out_vector[i], ref_out_vector[i]);
351 mismatches++;
352 }
353 }
354 if (mismatches)
355 {
356 printf("Test failed: %d of %d samples mismatch\n", mismatches, vector_len);
357 exit(2);
358 }
359 gsm0610_release(gsm0610_dec_state);
360 printf("Test passed\n");
361 return 0;
362 }
363 /*- End of function --------------------------------------------------------*/
364
365 static int perform_law_test(int full, int law, const char *name)
366 {
367 gsm0610_state_t *gsm0610_enc_state;
368 gsm0610_state_t *gsm0610_dec_state;
369 int i;
370 int xxx;
371 int mismatches;
372
373 if (law == 'a')
374 printf("Performing A-law test '%s'\n", name);
375 else
376 printf("Performing u-law test '%s'\n", name);
377
378 get_law_test_vector(full, law, name);
379
380 if (full)
381 {
382 if ((gsm0610_enc_state = gsm0610_init(NULL, GSM0610_PACKING_NONE)) == NULL)
383 {
384 fprintf(stderr, " Cannot create encoder\n");
385 exit(2);
386 }
387 if (law == 'a')
388 {
389 for (i = 0; i < vector_len; i++)
390 in_vector[i] = alaw_to_linear(law_in_vector[i]);
391 }
392 else
393 {
394 for (i = 0; i < vector_len; i++)
395 in_vector[i] = ulaw_to_linear(law_in_vector[i]);
396 }
397 xxx = gsm0610_encode(gsm0610_enc_state, code_vector, in_vector, vector_len);
398
399 printf("Check code vector of length %d\n", xxx);
400 for (i = 0, mismatches = 0; i < xxx; i++)
401 {
402 if (code_vector[i] != ref_code_vector[i])
403 {
404 printf("%8d/%3d: %6d %6d %6d\n", i/76, i%76, code_vector[i], ref_code_vector[i], decoder_code_vector[i]);
405 mismatches++;
406 }
407 }
408 if (mismatches)
409 {
410 printf("Test failed: %d of %d samples mismatch\n", mismatches, xxx);
411 exit(2);
412 }
413 printf("Test passed\n");
414 gsm0610_release(gsm0610_enc_state);
415 }
416
417 if ((gsm0610_dec_state = gsm0610_init(NULL, GSM0610_PACKING_NONE)) == NULL)
418 {
419 fprintf(stderr, " Cannot create decoder\n");
420 exit(2);
421 }
422 xxx = gsm0610_decode(gsm0610_dec_state, out_vector, decoder_code_vector, vector_len);
423 if (law == 'a')
424 {
425 for (i = 0; i < vector_len; i++)
426 law_out_vector[i] = linear_to_alaw(out_vector[i]);
427 }
428 else
429 {
430 for (i = 0; i < vector_len; i++)
431 law_out_vector[i] = linear_to_ulaw(out_vector[i]);
432 }
433 printf("Check output vector of length %d\n", vector_len);
434 for (i = 0, mismatches = 0; i < vector_len; i++)
435 {
436 if (law_out_vector[i] != ref_law_out_vector[i])
437 {
438 printf("%8d: %6d %6d\n", i, law_out_vector[i], ref_law_out_vector[i]);
439 mismatches++;
440 }
441 }
442 if (mismatches)
443 {
444 printf("Test failed: %d of %d samples mismatch\n", mismatches, vector_len);
445 exit(2);
446 }
447 gsm0610_release(gsm0610_dec_state);
448 printf("Test passed\n");
449 return 0;
450 }
451 /*- End of function --------------------------------------------------------*/
452
453 static int repack_gsm0610_voip_to_wav49(uint8_t c[], const uint8_t d[])
454 {
455 gsm0610_frame_t frame[2];
456 int n;
457
458 n = gsm0610_unpack_voip(&frame[0], d);
459 gsm0610_unpack_voip(&frame[1], d + n);
460 n = gsm0610_pack_wav49(c, frame);
461 return n;
462 }
463 /*- End of function --------------------------------------------------------*/
464
465 static int repack_gsm0610_wav49_to_voip(uint8_t d[], const uint8_t c[])
466 {
467 gsm0610_frame_t frame[2];
468 int n[2];
469
470 gsm0610_unpack_wav49(frame, c);
471 n[0] = gsm0610_pack_voip(d, &frame[0]);
472 n[1] = gsm0610_pack_voip(d + n[0], &frame[1]);
473 return n[0] + n[1];
474 }
475 /*- End of function --------------------------------------------------------*/
476
477 static int perform_pack_unpack_test(void)
478 {
479 uint8_t a[66];
480 uint8_t b[66];
481 uint8_t c[66];
482 int i;
483 int j;
484
485 printf("Performing packing/unpacking tests (not part of the ETSI conformance tests).\n");
486 /* Try trans-packing a lot of random data looking for before/after mismatch. */
487 for (j = 0; j < 1000; j++)
488 {
489 for (i = 0; i < 65; i++)
490 a[i] = rand();
491 repack_gsm0610_wav49_to_voip(b, a);
492 repack_gsm0610_voip_to_wav49(c, b);
493 if (memcmp(a, c, 65))
494 {
495 printf("Test failed: data mismatch\n");
496 exit(2);
497 }
498
499 for (i = 0; i < 66; i++)
500 a[i] = rand();
501 /* Insert the magic code */
502 a[0] = (a[0] & 0xF) | 0xD0;
503 a[33] = (a[33] & 0xF) | 0xD0;
504 repack_gsm0610_voip_to_wav49(b, a);
505 repack_gsm0610_wav49_to_voip(c, b);
506 //for (i = 0; i < 66; i++)
507 // printf("%2d: 0x%02X 0x%02X\n", i, a[i], c[i]);
508 if (memcmp(a, c, 66))
509 {
510 printf("Test failed: data mismatch\n");
511 exit(2);
512 }
513 }
514 printf("Test passed\n");
515 return 0;
516 }
517 /*- End of function --------------------------------------------------------*/
518
519 static void etsi_compliance_tests(void)
520 {
521 perform_linear_test(TRUE, 1, "Seq01");
522 perform_linear_test(TRUE, 1, "Seq02");
523 perform_linear_test(TRUE, 1, "Seq03");
524 perform_linear_test(TRUE, 1, "Seq04");
525 perform_linear_test(FALSE, 1, "Seq05");
526 perform_law_test(TRUE, 'a', "Seq01");
527 perform_law_test(TRUE, 'a', "Seq02");
528 perform_law_test(TRUE, 'a', "Seq03");
529 perform_law_test(TRUE, 'a', "Seq04");
530 perform_law_test(FALSE, 'a', "Seq05");
531 perform_law_test(TRUE, 'u', "Seq01");
532 perform_law_test(TRUE, 'u', "Seq02");
533 perform_law_test(TRUE, 'u', "Seq03");
534 perform_law_test(TRUE, 'u', "Seq04");
535 perform_law_test(FALSE, 'u', "Seq05");
536 /* This is not actually an ETSI test */
537 perform_pack_unpack_test();
538
539 printf("Tests passed.\n");
540 }
541 /*- End of function --------------------------------------------------------*/
542
543 int main(int argc, char *argv[])
544 {
545 SNDFILE *inhandle;
546 SNDFILE *outhandle;
547 int frames;
548 int outframes;
549 int bytes;
550 int16_t pre_amp[HIST_LEN];
551 int16_t post_amp[HIST_LEN];
552 uint8_t gsm0610_data[HIST_LEN];
553 gsm0610_state_t *gsm0610_enc_state;
554 gsm0610_state_t *gsm0610_dec_state;
555 int opt;
556 int etsitests;
557 int packing;
558
559 etsitests = TRUE;
560 packing = GSM0610_PACKING_NONE;
561 while ((opt = getopt(argc, argv, "lp:")) != -1)
562 {
563 switch (opt)
564 {
565 case 'l':
566 etsitests = FALSE;
567 break;
568 case 'p':
569 packing = atoi(optarg);
570 break;
571 default:
572 //usage();
573 exit(2);
574 }
575 }
576
577 if (etsitests)
578 {
579 etsi_compliance_tests();
580 }
581 else
582 {
583 if ((inhandle = sf_open_telephony_read(IN_FILE_NAME, 1)) == NULL)
584 {
585 fprintf(stderr, " Cannot open audio file '%s'\n", IN_FILE_NAME);
586 exit(2);
587 }
588 if ((outhandle = sf_open_telephony_write(OUT_FILE_NAME, 1)) == NULL)
589 {
590 fprintf(stderr, " Cannot create audio file '%s'\n", OUT_FILE_NAME);
591 exit(2);
592 }
593
594 if ((gsm0610_enc_state = gsm0610_init(NULL, packing)) == NULL)
595 {
596 fprintf(stderr, " Cannot create encoder\n");
597 exit(2);
598 }
599
600 if ((gsm0610_dec_state = gsm0610_init(NULL, packing)) == NULL)
601 {
602 fprintf(stderr, " Cannot create decoder\n");
603 exit(2);
604 }
605
606 while ((frames = sf_readf_short(inhandle, pre_amp, 2*BLOCK_LEN)))
607 {
608 bytes = gsm0610_encode(gsm0610_enc_state, gsm0610_data, pre_amp, frames);
609 gsm0610_decode(gsm0610_dec_state, post_amp, gsm0610_data, bytes);
610 outframes = sf_writef_short(outhandle, post_amp, frames);
611 }
612
613 if (sf_close(inhandle) != 0)
614 {
615 fprintf(stderr, " Cannot close audio file '%s'\n", IN_FILE_NAME);
616 exit(2);
617 }
618 if (sf_close(outhandle) != 0)
619 {
620 fprintf(stderr, " Cannot close audio file '%s'\n", OUT_FILE_NAME);
621 exit(2);
622 }
623 gsm0610_release(gsm0610_enc_state);
624 gsm0610_release(gsm0610_dec_state);
625 }
626 return 0;
627 }
628 /*- End of function --------------------------------------------------------*/
629 /*- End of file ------------------------------------------------------------*/

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