gsm0610_tests.c 18 KB

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