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

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