line_model_tests.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. /*
  2. * SpanDSP - a series of DSP components for telephony
  3. *
  4. * line_model_tests.c - Tests for the telephone line model.
  5. *
  6. * Written by Steve Underwood <steveu@coppice.org>
  7. *
  8. * Copyright (C) 2004 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. /*! \page line_model_tests_page Telephony line model tests
  26. \section line_model_tests_page_sec_1 What does it do?
  27. ???.
  28. \section line_model_tests_page_sec_2 How does it work?
  29. ???.
  30. */
  31. #if defined(HAVE_CONFIG_H)
  32. #include "config.h"
  33. #endif
  34. #include <stdlib.h>
  35. #include <stdio.h>
  36. #include <fcntl.h>
  37. #include <unistd.h>
  38. #include <string.h>
  39. #include <time.h>
  40. #include <sndfile.h>
  41. #define SPANDSP_EXPOSE_INTERNAL_STRUCTURES
  42. #include "spandsp.h"
  43. #include "spandsp-sim.h"
  44. #if !defined(NULL)
  45. #define NULL (void *) 0
  46. #endif
  47. #define BLOCK_LEN 160
  48. #define OUT_FILE_COMPLEXIFY "complexify.wav"
  49. #define IN_FILE_NAME1 "line_model_test_in1.wav"
  50. #define IN_FILE_NAME2 "line_model_test_in2.wav"
  51. #define OUT_FILE_NAME1 "line_model_one_way_test_out.wav"
  52. #define OUT_FILE_NAME2 "line_model_two_way_test_out.wav"
  53. int channel_codec;
  54. int rbs_pattern;
  55. static void complexify_tests(void)
  56. {
  57. complexify_state_t *s;
  58. complexf_t cc;
  59. int16_t amp;
  60. int i;
  61. SNDFILE *outhandle;
  62. int outframes;
  63. int16_t out[40000];
  64. awgn_state_t noise1;
  65. if ((outhandle = sf_open_telephony_write(OUT_FILE_COMPLEXIFY, 2)) == NULL)
  66. {
  67. fprintf(stderr, " Cannot create audio file '%s'\n", OUT_FILE_COMPLEXIFY);
  68. exit(2);
  69. }
  70. awgn_init_dbm0(&noise1, 1234567, -10.0f);
  71. s = complexify_init();
  72. for (i = 0; i < 20000; i++)
  73. {
  74. amp = awgn(&noise1);
  75. cc = complexify(s, amp);
  76. out[2*i] = cc.re;
  77. out[2*i + 1] = cc.im;
  78. }
  79. awgn_release(&noise1);
  80. complexify_free(s);
  81. outframes = sf_writef_short(outhandle, out, 20000);
  82. if (outframes != 20000)
  83. {
  84. fprintf(stderr, " Error writing audio file\n");
  85. exit(2);
  86. }
  87. if (sf_close_telephony(outhandle))
  88. {
  89. fprintf(stderr, " Cannot close audio file '%s'\n", OUT_FILE_COMPLEXIFY);
  90. exit(2);
  91. }
  92. }
  93. /*- End of function --------------------------------------------------------*/
  94. static void test_one_way_model(int line_model_no, int speech_test)
  95. {
  96. one_way_line_model_state_t *model;
  97. int16_t input1[BLOCK_LEN];
  98. int16_t output1[BLOCK_LEN];
  99. int16_t amp[2*BLOCK_LEN];
  100. SNDFILE *inhandle1;
  101. SNDFILE *outhandle;
  102. int outframes;
  103. int samples;
  104. int i;
  105. int j;
  106. awgn_state_t noise1;
  107. if ((model = one_way_line_model_init(line_model_no, -50, channel_codec, rbs_pattern)) == NULL)
  108. {
  109. fprintf(stderr, " Failed to create line model\n");
  110. exit(2);
  111. }
  112. awgn_init_dbm0(&noise1, 1234567, -10.0f);
  113. if (speech_test)
  114. {
  115. if ((inhandle1 = sf_open_telephony_read(IN_FILE_NAME1, 1)) == NULL)
  116. {
  117. fprintf(stderr, " Cannot open audio file '%s'\n", IN_FILE_NAME1);
  118. exit(2);
  119. }
  120. }
  121. else
  122. {
  123. inhandle1 = NULL;
  124. }
  125. if ((outhandle = sf_open_telephony_write(OUT_FILE_NAME1, 1)) == NULL)
  126. {
  127. fprintf(stderr, " Cannot create audio file '%s'\n", OUT_FILE_NAME1);
  128. exit(2);
  129. }
  130. for (i = 0; i < 10000; i++)
  131. {
  132. if (speech_test)
  133. {
  134. samples = sf_readf_short(inhandle1, input1, BLOCK_LEN);
  135. if (samples == 0)
  136. break;
  137. }
  138. else
  139. {
  140. for (j = 0; j < BLOCK_LEN; j++)
  141. input1[j] = awgn(&noise1);
  142. samples = BLOCK_LEN;
  143. }
  144. for (j = 0; j < samples; j++)
  145. {
  146. one_way_line_model(model,
  147. &output1[j],
  148. &input1[j],
  149. 1);
  150. amp[j] = output1[j];
  151. }
  152. outframes = sf_writef_short(outhandle, amp, samples);
  153. if (outframes != samples)
  154. {
  155. fprintf(stderr, " Error writing audio file\n");
  156. exit(2);
  157. }
  158. }
  159. if (speech_test)
  160. {
  161. if (sf_close_telephony(inhandle1))
  162. {
  163. fprintf(stderr, " Cannot close audio file '%s'\n", IN_FILE_NAME1);
  164. exit(2);
  165. }
  166. }
  167. if (sf_close_telephony(outhandle))
  168. {
  169. fprintf(stderr, " Cannot close audio file '%s'\n", OUT_FILE_NAME1);
  170. exit(2);
  171. }
  172. one_way_line_model_free(model);
  173. }
  174. /*- End of function --------------------------------------------------------*/
  175. static void test_both_ways_model(int line_model_no, int speech_test)
  176. {
  177. both_ways_line_model_state_t *model;
  178. int16_t input1[BLOCK_LEN];
  179. int16_t input2[BLOCK_LEN];
  180. int16_t output1[BLOCK_LEN];
  181. int16_t output2[BLOCK_LEN];
  182. int16_t amp[2*BLOCK_LEN];
  183. SNDFILE *inhandle1;
  184. SNDFILE *inhandle2;
  185. SNDFILE *outhandle;
  186. int outframes;
  187. int samples;
  188. int i;
  189. int j;
  190. awgn_state_t noise1;
  191. awgn_state_t noise2;
  192. if ((model = both_ways_line_model_init(line_model_no,
  193. -50,
  194. -15.0f,
  195. -15.0f,
  196. line_model_no + 1,
  197. -35,
  198. -15.0f,
  199. -15.0f,
  200. channel_codec,
  201. rbs_pattern)) == NULL)
  202. {
  203. fprintf(stderr, " Failed to create line model\n");
  204. exit(2);
  205. }
  206. awgn_init_dbm0(&noise1, 1234567, -10.0f);
  207. awgn_init_dbm0(&noise2, 1234567, -10.0f);
  208. if (speech_test)
  209. {
  210. if ((inhandle1 = sf_open_telephony_read(IN_FILE_NAME1, 1)) == NULL)
  211. {
  212. fprintf(stderr, " Cannot open audio file '%s'\n", IN_FILE_NAME1);
  213. exit(2);
  214. }
  215. if ((inhandle2 = sf_open_telephony_read(IN_FILE_NAME2, 1)) == NULL)
  216. {
  217. fprintf(stderr, " Cannot open audio file '%s'\n", IN_FILE_NAME2);
  218. exit(2);
  219. }
  220. }
  221. else
  222. {
  223. inhandle1 =
  224. inhandle2 = NULL;
  225. }
  226. if ((outhandle = sf_open_telephony_write(OUT_FILE_NAME2, 2)) == NULL)
  227. {
  228. fprintf(stderr, " Cannot create audio file '%s'\n", OUT_FILE_NAME2);
  229. exit(2);
  230. }
  231. for (i = 0; i < 10000; i++)
  232. {
  233. if (speech_test)
  234. {
  235. samples = sf_readf_short(inhandle1, input1, BLOCK_LEN);
  236. if (samples == 0)
  237. break;
  238. samples = sf_readf_short(inhandle2, input2, samples);
  239. if (samples == 0)
  240. break;
  241. }
  242. else
  243. {
  244. for (j = 0; j < BLOCK_LEN; j++)
  245. {
  246. input1[j] = awgn(&noise1);
  247. input2[j] = awgn(&noise2);
  248. }
  249. samples = BLOCK_LEN;
  250. }
  251. for (j = 0; j < samples; j++)
  252. {
  253. both_ways_line_model(model,
  254. &output1[j],
  255. &input1[j],
  256. &output2[j],
  257. &input2[j],
  258. 1);
  259. amp[2*j] = output1[j];
  260. amp[2*j + 1] = output2[j];
  261. }
  262. outframes = sf_writef_short(outhandle, amp, samples);
  263. if (outframes != samples)
  264. {
  265. fprintf(stderr, " Error writing audio file\n");
  266. exit(2);
  267. }
  268. }
  269. if (speech_test)
  270. {
  271. if (sf_close_telephony(inhandle1))
  272. {
  273. fprintf(stderr, " Cannot close audio file '%s'\n", IN_FILE_NAME1);
  274. exit(2);
  275. }
  276. if (sf_close_telephony(inhandle2))
  277. {
  278. fprintf(stderr, " Cannot close audio file '%s'\n", IN_FILE_NAME2);
  279. exit(2);
  280. }
  281. }
  282. if (sf_close_telephony(outhandle))
  283. {
  284. fprintf(stderr, " Cannot close audio file '%s'\n", OUT_FILE_NAME2);
  285. exit(2);
  286. }
  287. both_ways_line_model_free(model);
  288. }
  289. /*- End of function --------------------------------------------------------*/
  290. static void test_line_filter(int line_model_no)
  291. {
  292. float out;
  293. double sumin;
  294. double sumout;
  295. double gain;
  296. int i;
  297. int j;
  298. int p;
  299. int ptr;
  300. int len;
  301. swept_tone_state_t *s;
  302. float filter[129];
  303. int16_t buf[BLOCK_LEN];
  304. s = swept_tone_init(NULL, 200.0f, 3900.0f, -10.0f, 120*SAMPLE_RATE, 0);
  305. for (j = 0; j < 129; j++)
  306. filter[j] = 0.0f;
  307. ptr = 0;
  308. for (;;)
  309. {
  310. if ((len = swept_tone(s, buf, BLOCK_LEN)) <= 0)
  311. break;
  312. sumin = 0.0;
  313. sumout = 0.0;
  314. for (i = 0; i < len; i++)
  315. {
  316. /* Add the sample in the filter buffer */
  317. p = ptr;
  318. filter[p] = buf[i];
  319. if (++p == 129)
  320. p = 0;
  321. ptr = p;
  322. /* Apply the filter */
  323. out = 0.0f;
  324. for (j = 0; j < 129; j++)
  325. {
  326. out += line_models[line_model_no][128 - j]*filter[p];
  327. if (++p >= 129)
  328. p = 0;
  329. }
  330. sumin += buf[i]*buf[i];
  331. sumout += out*out;
  332. }
  333. /*endfor*/
  334. gain = (sumin != 0.0) ? 10.0*log10(sumout/sumin + 1.0e-10) : 0.0;
  335. printf("%7.1f %f\n", swept_tone_current_frequency(s), gain);
  336. }
  337. /*endfor*/
  338. swept_tone_free(s);
  339. }
  340. /*- End of function --------------------------------------------------------*/
  341. int main(int argc, char *argv[])
  342. {
  343. int line_model_no;
  344. int opt;
  345. bool speech_test;
  346. channel_codec = MUNGE_CODEC_NONE;
  347. line_model_no = 0;
  348. rbs_pattern = 0;
  349. speech_test = false;
  350. while ((opt = getopt(argc, argv, "c:m:r:s:")) != -1)
  351. {
  352. switch (opt)
  353. {
  354. case 'c':
  355. channel_codec = atoi(optarg);
  356. break;
  357. case 'm':
  358. line_model_no = atoi(optarg);
  359. break;
  360. case 'r':
  361. rbs_pattern = atoi(optarg);
  362. break;
  363. case 's':
  364. speech_test = atoi(optarg);
  365. break;
  366. default:
  367. //usage();
  368. exit(2);
  369. }
  370. }
  371. complexify_tests();
  372. test_one_way_model(line_model_no, speech_test);
  373. test_both_ways_model(line_model_no, speech_test);
  374. test_line_filter(line_model_no);
  375. }
  376. /*- End of function --------------------------------------------------------*/
  377. /*- End of file ------------------------------------------------------------*/