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

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