2
0

playout_tests.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. /*
  2. * SpanDSP - a series of DSP components for telephony
  3. *
  4. * playout_tests.c
  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. /*! \page playout_tests_page Playout (jitter buffering) tests
  26. \section playout_tests_page_sec_1 What does it do?
  27. These tests simulate timing jitter and packet loss in an audio stream, and see
  28. how well the playout module copes.
  29. */
  30. #if defined(HAVE_CONFIG_H)
  31. #include "config.h"
  32. #endif
  33. #include <stdlib.h>
  34. #include <stdio.h>
  35. #include <string.h>
  36. #include <sndfile.h>
  37. #include "spandsp.h"
  38. #include "spandsp/private/time_scale.h"
  39. #include "spandsp-sim.h"
  40. #define INPUT_FILE_NAME "playout_in.wav"
  41. #define OUTPUT_FILE_NAME "playout_out.wav"
  42. #define BLOCK_LEN 160
  43. static void dynamic_buffer_tests(void)
  44. {
  45. playout_state_t *s;
  46. playout_frame_t frame;
  47. playout_frame_t *p;
  48. plc_state_t plc;
  49. time_scale_state_t ts;
  50. int16_t *amp;
  51. int16_t fill[BLOCK_LEN];
  52. int16_t buf[20*BLOCK_LEN];
  53. int16_t out[10*BLOCK_LEN];
  54. timestamp_t time_stamp;
  55. timestamp_t next_actual_receive;
  56. timestamp_t next_scheduled_receive;
  57. int near_far_time_offset;
  58. int rng;
  59. int i;
  60. int j;
  61. int ret;
  62. int len;
  63. int inframes;
  64. int outframes;
  65. SNDFILE *inhandle;
  66. SNDFILE *outhandle;
  67. if ((inhandle = sf_open_telephony_read(INPUT_FILE_NAME, 1)) == NULL)
  68. {
  69. fprintf(stderr, " Failed to open audio file '%s'\n", INPUT_FILE_NAME);
  70. exit(2);
  71. }
  72. if ((outhandle = sf_open_telephony_write(OUTPUT_FILE_NAME, 1)) == NULL)
  73. {
  74. fprintf(stderr, " Failed to create audio file '%s'\n", OUTPUT_FILE_NAME);
  75. exit(2);
  76. }
  77. near_far_time_offset = 54321;
  78. time_stamp = 12345;
  79. next_actual_receive = time_stamp + near_far_time_offset;
  80. next_scheduled_receive = 0;
  81. for (i = 0; i < BLOCK_LEN; i++)
  82. fill[i] = 32767;
  83. if ((s = playout_init(2*BLOCK_LEN, 15*BLOCK_LEN)) == NULL)
  84. return;
  85. plc_init(&plc);
  86. time_scale_init(&ts, SAMPLE_RATE, 1.0);
  87. for (i = 0; i < 1000000; i++)
  88. {
  89. if (i >= next_actual_receive)
  90. {
  91. amp = malloc(BLOCK_LEN*sizeof(int16_t));
  92. inframes = sf_readf_short(inhandle, amp, BLOCK_LEN);
  93. if (inframes < BLOCK_LEN)
  94. break;
  95. ret = playout_put(s,
  96. amp,
  97. PLAYOUT_TYPE_SPEECH,
  98. inframes,
  99. time_stamp,
  100. next_actual_receive);
  101. #if 0
  102. switch (ret)
  103. {
  104. case PLAYOUT_OK:
  105. printf("<< Record\n");
  106. break;
  107. case PLAYOUT_ERROR:
  108. printf("<< Error\n");
  109. break;
  110. default:
  111. printf("<< Eh?\n");
  112. break;
  113. }
  114. #endif
  115. rng = rand() & 0xFF;
  116. if (i < 100000)
  117. rng = (rng*rng) >> 7;
  118. else if (i < 200000)
  119. rng = (rng*rng) >> 6;
  120. else if (i < 300000)
  121. rng = (rng*rng) >> 5;
  122. else if (i < 400000)
  123. rng = (rng*rng) >> 7;
  124. time_stamp += BLOCK_LEN;
  125. next_actual_receive = time_stamp + near_far_time_offset + rng;
  126. }
  127. if (i >= next_scheduled_receive)
  128. {
  129. do
  130. {
  131. ret = playout_get(s, &frame, next_scheduled_receive);
  132. if (ret == PLAYOUT_DROP)
  133. printf(">> Drop %d\n", next_scheduled_receive);
  134. }
  135. while (ret == PLAYOUT_DROP);
  136. switch (ret)
  137. {
  138. case PLAYOUT_OK:
  139. printf(">> Play %d\n", next_scheduled_receive);
  140. plc_rx(&plc, frame.data, frame.sender_len);
  141. len = time_scale(&ts, out, ((int16_t *) frame.data), frame.sender_len);
  142. printf("len = %d\n", len);
  143. for (j = 0; j < len; j++)
  144. {
  145. buf[2*j] = out[j];
  146. buf[2*j + 1] = 10*playout_current_length(s);
  147. }
  148. outframes = sf_writef_short(outhandle, buf, len);
  149. if (outframes != len)
  150. {
  151. fprintf(stderr, " Error writing out sound\n");
  152. exit(2);
  153. }
  154. free(frame.data);
  155. next_scheduled_receive += BLOCK_LEN;
  156. break;
  157. case PLAYOUT_FILLIN:
  158. printf(">> Fill %d\n", next_scheduled_receive);
  159. plc_fillin(&plc, fill, BLOCK_LEN);
  160. time_scale_rate(&ts, 0.5);
  161. len = time_scale(&ts, out, fill, BLOCK_LEN);
  162. time_scale_rate(&ts, 1.0);
  163. printf("len = %d\n", len);
  164. for (j = 0; j < len; j++)
  165. {
  166. buf[2*j] = out[j];
  167. buf[2*j + 1] = 10*playout_current_length(s);
  168. }
  169. outframes = sf_writef_short(outhandle, buf, len);
  170. if (outframes != len)
  171. {
  172. fprintf(stderr, " Error writing out sound\n");
  173. exit(2);
  174. }
  175. next_scheduled_receive += BLOCK_LEN;
  176. break;
  177. case PLAYOUT_DROP:
  178. printf(">> Drop %d\n", next_scheduled_receive);
  179. break;
  180. case PLAYOUT_NOFRAME:
  181. printf(">> No frame %d %d %d %d\n", next_scheduled_receive, playout_next_due(s), s->last_speech_sender_stamp, s->last_speech_sender_len);
  182. next_scheduled_receive += BLOCK_LEN;
  183. break;
  184. case PLAYOUT_EMPTY:
  185. printf(">> Empty %d\n", next_scheduled_receive);
  186. next_scheduled_receive += BLOCK_LEN;
  187. break;
  188. case PLAYOUT_ERROR:
  189. printf(">> Error %d\n", next_scheduled_receive);
  190. next_scheduled_receive += BLOCK_LEN;
  191. break;
  192. default:
  193. printf(">> Eh? %d\n", next_scheduled_receive);
  194. break;
  195. }
  196. }
  197. }
  198. if (sf_close_telephony(inhandle))
  199. {
  200. fprintf(stderr, " Cannot close audio file '%s'\n", INPUT_FILE_NAME);
  201. exit(2);
  202. }
  203. if (sf_close_telephony(outhandle))
  204. {
  205. fprintf(stderr, " Cannot close audio file '%s'\n", OUTPUT_FILE_NAME);
  206. exit(2);
  207. }
  208. printf("%10" PRId32 " %10" PRId32 " %10d\n", s->state_just_in_time, s->state_late, playout_current_length(s));
  209. /* Clear everything from the queue */
  210. while ((p = playout_get_unconditional(s)))
  211. /*free(p->data)*/;
  212. /* Now free the context itself */
  213. playout_free(s);
  214. }
  215. /*- End of function --------------------------------------------------------*/
  216. static void static_buffer_tests(void)
  217. {
  218. playout_state_t *s;
  219. playout_frame_t frame;
  220. playout_frame_t *p;
  221. int type;
  222. uint8_t fr[BLOCK_LEN];
  223. timestamp_t next_scheduled_send;
  224. int transit_time;
  225. timestamp_t next_actual_receive;
  226. timestamp_t next_scheduled_receive;
  227. int len;
  228. int i;
  229. int ret;
  230. next_scheduled_send = 0;
  231. transit_time = 320;
  232. next_actual_receive = next_scheduled_send + transit_time;
  233. next_scheduled_receive = 960;
  234. memset(fr, 0, sizeof(fr));
  235. type = PLAYOUT_TYPE_SPEECH;
  236. len = BLOCK_LEN;
  237. if ((s = playout_init(2*BLOCK_LEN, 2*BLOCK_LEN)) == NULL)
  238. return;
  239. for (i = 0; i < 1000000; i++)
  240. {
  241. if (i >= next_actual_receive)
  242. {
  243. ret = playout_put(s,
  244. fr,
  245. type,
  246. len,
  247. next_scheduled_send,
  248. next_actual_receive);
  249. switch (ret)
  250. {
  251. case PLAYOUT_OK:
  252. printf("<< Record\n");
  253. break;
  254. case PLAYOUT_ERROR:
  255. printf("<< Error\n");
  256. break;
  257. default:
  258. printf("<< Eh?\n");
  259. break;
  260. }
  261. next_scheduled_send += BLOCK_LEN;
  262. ret = rand() & 0xFF;
  263. ret = (ret*ret) >> 7;
  264. transit_time = 320 + ret;
  265. next_actual_receive = next_scheduled_send + transit_time;
  266. }
  267. if (i >= next_scheduled_receive)
  268. {
  269. do
  270. {
  271. ret = playout_get(s, &frame, next_scheduled_receive);
  272. }
  273. while (ret == PLAYOUT_DROP);
  274. switch (ret)
  275. {
  276. case PLAYOUT_OK:
  277. printf(">> Play\n");
  278. next_scheduled_receive += BLOCK_LEN;
  279. break;
  280. case PLAYOUT_FILLIN:
  281. printf(">> Fill\n");
  282. next_scheduled_receive += BLOCK_LEN;
  283. break;
  284. case PLAYOUT_DROP:
  285. printf(">> Drop\n");
  286. break;
  287. case PLAYOUT_NOFRAME:
  288. printf(">> No frame\n");
  289. next_scheduled_receive += BLOCK_LEN;
  290. break;
  291. case PLAYOUT_EMPTY:
  292. printf(">> Empty\n");
  293. next_scheduled_receive += BLOCK_LEN;
  294. break;
  295. case PLAYOUT_ERROR:
  296. printf(">> Error\n");
  297. next_scheduled_receive += BLOCK_LEN;
  298. break;
  299. default:
  300. printf(">> Eh?\n");
  301. break;
  302. }
  303. }
  304. }
  305. /* Clear everything from the queue */
  306. while ((p = playout_get_unconditional(s)))
  307. /*free(p->data)*/;
  308. /* Now free the context itself */
  309. playout_free(s);
  310. }
  311. /*- End of function --------------------------------------------------------*/
  312. int main(int argc, char *argv[])
  313. {
  314. printf("Dynamic buffering tests\n");
  315. dynamic_buffer_tests();
  316. printf("Static buffering tests\n");
  317. static_buffer_tests();
  318. }
  319. /*- End of function --------------------------------------------------------*/
  320. /*- End of file ------------------------------------------------------------*/