comparison spandsp-0.0.6pre17/tests/t38_gateway_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 * t38_gateway_tests.c - Tests for the T.38 FoIP gateway module.
5 *
6 * Written by Steve Underwood <steveu@coppice.org>
7 *
8 * Copyright (C) 2005, 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: t38_gateway_tests.c,v 1.82.4.1 2009/12/19 09:47:57 steveu Exp $
26 */
27
28 /*! \file */
29
30 /*! \page t38_gateway_tests_page T.38 gateway tests
31 \section t38_gateway_tests_page_sec_1 What does it do?
32 These tests exercise the path
33
34 FAX machine <-> T.38 gateway <-> T.38 gateway <-> FAX machine
35 */
36
37 /* Enable the following definition to enable direct probing into the FAX structures */
38 //#define WITH_SPANDSP_INTERNALS
39
40 #if defined(HAVE_CONFIG_H)
41 #include <config.h>
42 #endif
43
44 #if defined(HAVE_FL_FL_H) && defined(HAVE_FL_FL_CARTESIAN_H) && defined(HAVE_FL_FL_AUDIO_METER_H)
45 #define ENABLE_GUI
46 #endif
47
48 #include <stdlib.h>
49 #include <stdio.h>
50 #include <fcntl.h>
51 #include <string.h>
52 #include <assert.h>
53 #include <errno.h>
54 #include <sndfile.h>
55 #if !defined(_WIN32)
56 #include <unistd.h>
57 #endif
58
59 //#if defined(WITH_SPANDSP_INTERNALS)
60 #define SPANDSP_EXPOSE_INTERNAL_STRUCTURES
61 //#endif
62
63 #include "spandsp.h"
64 #include "spandsp-sim.h"
65
66 #if defined(ENABLE_GUI)
67 #include "media_monitor.h"
68 #endif
69 #include "fax_utils.h"
70
71 #define SAMPLES_PER_CHUNK 160
72
73 #define INPUT_FILE_NAME "../test-data/itu/fax/itutests.tif"
74 #define OUTPUT_FILE_NAME "t38.tif"
75 #define OUTPUT_FILE_NAME_WAVE "t38_gateway.wav"
76 #define OUTPUT_FILE_NAME_T30A "t38_gateway_t30a.wav"
77 #define OUTPUT_FILE_NAME_T38A "t38_gateway_t38a.wav"
78 #define OUTPUT_FILE_NAME_T30B "t38_gateway_t30b.wav"
79 #define OUTPUT_FILE_NAME_T38B "t38_gateway_t38b.wav"
80
81 fax_state_t *fax_state_a;
82 t38_gateway_state_t *t38_state_a;
83 t38_gateway_state_t *t38_state_b;
84 fax_state_t *fax_state_b;
85
86 g1050_state_t *path_a_to_b;
87 g1050_state_t *path_b_to_a;
88
89 double when = 0.0;
90
91 int done[2] = {FALSE, FALSE};
92 int succeeded[2] = {FALSE, FALSE};
93
94 int simulate_incrementing_repeats = FALSE;
95
96 static int phase_b_handler(t30_state_t *s, void *user_data, int result)
97 {
98 int i;
99 char tag[20];
100
101 i = (int) (intptr_t) user_data;
102 snprintf(tag, sizeof(tag), "%c: Phase B", i);
103 printf("%c: Phase B handler on channel %c - (0x%X) %s\n", i, i, result, t30_frametype(result));
104 log_rx_parameters(s, tag);
105 return T30_ERR_OK;
106 }
107 /*- End of function --------------------------------------------------------*/
108
109 static int phase_d_handler(t30_state_t *s, void *user_data, int result)
110 {
111 int i;
112 char tag[20];
113
114 i = (int) (intptr_t) user_data;
115 snprintf(tag, sizeof(tag), "%c: Phase D", i);
116 printf("%c: Phase D handler on channel %c - (0x%X) %s\n", i, i, result, t30_frametype(result));
117 log_transfer_statistics(s, tag);
118 log_tx_parameters(s, tag);
119 log_rx_parameters(s, tag);
120 return T30_ERR_OK;
121 }
122 /*- End of function --------------------------------------------------------*/
123
124 static void phase_e_handler(t30_state_t *s, void *user_data, int result)
125 {
126 int i;
127 t30_stats_t t;
128 char tag[20];
129
130 i = (int) (intptr_t) user_data;
131 snprintf(tag, sizeof(tag), "%c: Phase E", i);
132 printf("%c: Phase E handler on channel %c - (%d) %s\n", i, i, result, t30_completion_code_to_str(result));
133 log_transfer_statistics(s, tag);
134 log_tx_parameters(s, tag);
135 log_rx_parameters(s, tag);
136 t30_get_transfer_statistics(s, &t);
137 succeeded[i - 'A'] = (result == T30_ERR_OK) && (t.pages_tx == 12 || t.pages_rx == 12);
138 done[i - 'A'] = TRUE;
139 }
140 /*- End of function --------------------------------------------------------*/
141
142 static void real_time_frame_handler(t38_gateway_state_t *s,
143 void *user_data,
144 int direction,
145 const uint8_t *msg,
146 int len)
147 {
148 int i;
149
150 i = (intptr_t) user_data;
151 printf("%d: Real time frame handler on channel %d - %s, %s, length = %d\n",
152 i,
153 i,
154 (direction) ? "PSTN->T.38" : "T.38->PSTN",
155 t30_frametype(msg[2]),
156 len);
157 }
158 /*- End of function --------------------------------------------------------*/
159
160 static int tx_packet_handler_a(t38_core_state_t *s, void *user_data, const uint8_t *buf, int len, int count)
161 {
162 t38_terminal_state_t *t;
163 int i;
164 static int subst_seq = 0;
165
166 /* This routine queues messages between two instances of T.38 processing */
167 t = (t38_terminal_state_t *) user_data;
168 if (simulate_incrementing_repeats)
169 {
170 for (i = 0; i < count; i++)
171 {
172 span_log(&s->logging, SPAN_LOG_FLOW, "Send seq %d, len %d\n", subst_seq, len);
173
174 g1050_put(path_a_to_b, buf, len, subst_seq, when);
175 subst_seq = (subst_seq + 1) & 0xFFFF;
176 }
177 }
178 else
179 {
180 span_log(&s->logging, SPAN_LOG_FLOW, "Send seq %d, len %d, count %d\n", s->tx_seq_no, len, count);
181
182 for (i = 0; i < count; i++)
183 g1050_put(path_a_to_b, buf, len, s->tx_seq_no, when);
184 }
185 return 0;
186 }
187 /*- End of function --------------------------------------------------------*/
188
189 static int tx_packet_handler_b(t38_core_state_t *s, void *user_data, const uint8_t *buf, int len, int count)
190 {
191 t38_terminal_state_t *t;
192 int i;
193 static int subst_seq = 0;
194
195 /* This routine queues messages between two instances of T.38 processing */
196 t = (t38_terminal_state_t *) user_data;
197 if (simulate_incrementing_repeats)
198 {
199 for (i = 0; i < count; i++)
200 {
201 span_log(&s->logging, SPAN_LOG_FLOW, "Send seq %d, len %d\n", subst_seq, len);
202
203 g1050_put(path_b_to_a, buf, len, subst_seq, when);
204 subst_seq = (subst_seq + 1) & 0xFFFF;
205 }
206 }
207 else
208 {
209 span_log(&s->logging, SPAN_LOG_FLOW, "Send seq %d, len %d, count %d\n", s->tx_seq_no, len, count);
210
211 for (i = 0; i < count; i++)
212 g1050_put(path_b_to_a, buf, len, s->tx_seq_no, when);
213 }
214 return 0;
215 }
216 /*- End of function --------------------------------------------------------*/
217
218 int main(int argc, char *argv[])
219 {
220 int16_t silence[SAMPLES_PER_CHUNK];
221 int16_t t30_amp_a[SAMPLES_PER_CHUNK];
222 int16_t t38_amp_a[SAMPLES_PER_CHUNK];
223 int16_t t38_amp_hist_a[8][SAMPLES_PER_CHUNK];
224 int16_t t38_amp_b[SAMPLES_PER_CHUNK];
225 int16_t t38_amp_hist_b[8][SAMPLES_PER_CHUNK];
226 int16_t t30_amp_b[SAMPLES_PER_CHUNK];
227 int16_t out_amp[SAMPLES_PER_CHUNK*4];
228 int t30_len_a;
229 int t38_len_a;
230 int t38_len_b;
231 int t30_len_b;
232 int hist_ptr;
233 int log_audio;
234 int msg_len;
235 uint8_t msg[1024];
236 int outframes;
237 SNDFILE *wave_handle;
238 int use_ecm;
239 int use_tep;
240 int feedback_audio;
241 int use_transmit_on_idle;
242 int t38_version;
243 const char *input_file_name;
244 int i;
245 int seq_no;
246 int model_no;
247 int speed_pattern_no;
248 double tx_when;
249 double rx_when;
250 int supported_modems;
251 int fill_removal;
252 int use_gui;
253 int opt;
254 t38_stats_t stats;
255 fax_state_t *fax;
256 t30_state_t *t30;
257 t38_gateway_state_t *t38;
258 t38_core_state_t *t38_core;
259 logging_state_t *logging;
260
261 log_audio = FALSE;
262 use_ecm = FALSE;
263 t38_version = 1;
264 input_file_name = INPUT_FILE_NAME;
265 simulate_incrementing_repeats = FALSE;
266 model_no = 0;
267 speed_pattern_no = 1;
268 fill_removal = FALSE;
269 use_gui = FALSE;
270 use_tep = FALSE;
271 feedback_audio = FALSE;
272 use_transmit_on_idle = TRUE;
273 supported_modems = T30_SUPPORT_V27TER | T30_SUPPORT_V29 | T30_SUPPORT_V17;
274 while ((opt = getopt(argc, argv, "efFgi:Ilm:M:s:tv:")) != -1)
275 {
276 switch (opt)
277 {
278 case 'e':
279 use_ecm = TRUE;
280 break;
281 case 'f':
282 feedback_audio = TRUE;
283 break;
284 case 'F':
285 fill_removal = TRUE;
286 break;
287 case 'g':
288 #if defined(ENABLE_GUI)
289 use_gui = TRUE;
290 #else
291 fprintf(stderr, "Graphical monitoring not available\n");
292 exit(2);
293 #endif
294 break;
295 case 'i':
296 input_file_name = optarg;
297 break;
298 case 'I':
299 simulate_incrementing_repeats = TRUE;
300 break;
301 case 'l':
302 log_audio = TRUE;
303 break;
304 case 'm':
305 supported_modems = atoi(optarg);
306 break;
307 case 'M':
308 model_no = optarg[0] - 'A' + 1;
309 break;
310 case 's':
311 speed_pattern_no = atoi(optarg);
312 break;
313 case 't':
314 use_tep = TRUE;
315 break;
316 case 'v':
317 t38_version = atoi(optarg);
318 break;
319 default:
320 //usage();
321 exit(2);
322 break;
323 }
324 }
325
326 printf("Using T.38 version %d\n", t38_version);
327 if (use_ecm)
328 printf("Using ECM\n");
329
330 wave_handle = NULL;
331 if (log_audio)
332 {
333 if ((wave_handle = sf_open_telephony_write(OUTPUT_FILE_NAME_WAVE, 4)) == NULL)
334 {
335 fprintf(stderr, " Cannot create audio file '%s'\n", OUTPUT_FILE_NAME_WAVE);
336 exit(2);
337 }
338 }
339 memset(silence, 0, sizeof(silence));
340
341 srand48(0x1234567);
342 if ((path_a_to_b = g1050_init(model_no, speed_pattern_no, 100, 33)) == NULL)
343 {
344 fprintf(stderr, "Failed to start IP network path model\n");
345 exit(2);
346 }
347 if ((path_b_to_a = g1050_init(model_no, speed_pattern_no, 100, 33)) == NULL)
348 {
349 fprintf(stderr, "Failed to start IP network path model\n");
350 exit(2);
351 }
352
353 if ((fax_state_a = fax_init(NULL, TRUE)) == NULL)
354 {
355 fprintf(stderr, "Cannot start FAX\n");
356 exit(2);
357 }
358 fax = fax_state_a;
359 t30 = fax_get_t30_state(fax);
360 fax_set_transmit_on_idle(fax, use_transmit_on_idle);
361 fax_set_tep_mode(fax, use_tep);
362 t30_set_supported_modems(t30, supported_modems);
363 t30_set_tx_ident(t30, "11111111");
364 t30_set_tx_nsf(t30, (const uint8_t *) "\x50\x00\x00\x00Spandsp\x00", 12);
365 t30_set_tx_file(t30, input_file_name, -1, -1);
366 t30_set_phase_b_handler(t30, phase_b_handler, (void *) (intptr_t) 'A');
367 t30_set_phase_d_handler(t30, phase_d_handler, (void *) (intptr_t) 'A');
368 t30_set_phase_e_handler(t30, phase_e_handler, (void *) (intptr_t) 'A');
369 t30_set_ecm_capability(t30, use_ecm);
370 if (use_ecm)
371 t30_set_supported_compressions(t30, T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION | T30_SUPPORT_T6_COMPRESSION);
372 t30_set_minimum_scan_line_time(t30, 40);
373 //t30_set_iaf_mode(t30, T30_IAF_MODE_NO_FILL_BITS);
374
375 logging = fax_get_logging_state(fax);
376 span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
377 span_log_set_tag(logging, "FAX-A ");
378
379 logging = t30_get_logging_state(t30);
380 span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
381 span_log_set_tag(logging, "FAX-A ");
382
383 memset(t30_amp_a, 0, sizeof(t30_amp_a));
384 memset(t38_amp_hist_a, 0, sizeof(t38_amp_hist_a));
385 memset(t38_amp_hist_b, 0, sizeof(t38_amp_hist_b));
386
387 if ((t38_state_a = t38_gateway_init(NULL, tx_packet_handler_a, t38_state_b)) == NULL)
388 {
389 fprintf(stderr, "Cannot start the T.38 channel\n");
390 exit(2);
391 }
392 t38 = t38_state_a;
393 t38_core = t38_gateway_get_t38_core_state(t38);
394 t38_gateway_set_transmit_on_idle(t38, use_transmit_on_idle);
395 t38_gateway_set_supported_modems(t38, supported_modems);
396 //t38_gateway_set_nsx_suppression(t38, NULL, 0, NULL, 0);
397 t38_gateway_set_fill_bit_removal(t38, fill_removal);
398 t38_gateway_set_real_time_frame_handler(t38, real_time_frame_handler, NULL);
399 t38_set_t38_version(t38_core, t38_version);
400 t38_gateway_set_ecm_capability(t38, use_ecm);
401
402 logging = t38_gateway_get_logging_state(t38);
403 span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
404 span_log_set_tag(logging, "T.38-A");
405
406 logging = t38_core_get_logging_state(t38_core);
407 span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
408 span_log_set_tag(logging, "T.38-A");
409 memset(t38_amp_a, 0, sizeof(t38_amp_a));
410
411 if ((t38_state_b = t38_gateway_init(NULL, tx_packet_handler_b, t38_state_a)) == NULL)
412 {
413 fprintf(stderr, "Cannot start the T.38 channel\n");
414 exit(2);
415 }
416 t38 = t38_state_b;
417 t38_core = t38_gateway_get_t38_core_state(t38);
418 t38_gateway_set_transmit_on_idle(t38, use_transmit_on_idle);
419 t38_gateway_set_supported_modems(t38, supported_modems);
420 //t38_gateway_set_nsx_suppression(t38, FALSE);
421 t38_gateway_set_fill_bit_removal(t38, fill_removal);
422 t38_set_t38_version(t38_core, t38_version);
423 t38_gateway_set_ecm_capability(t38, use_ecm);
424
425 logging = t38_gateway_get_logging_state(t38);
426 span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
427 span_log_set_tag(logging, "T.38-B");
428
429 logging = t38_core_get_logging_state(t38_core);
430 span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
431 span_log_set_tag(logging, "T.38-B");
432 memset(t38_amp_b, 0, sizeof(t38_amp_b));
433
434 if ((fax_state_b = fax_init(NULL, FALSE)) == NULL)
435 {
436 fprintf(stderr, "Cannot start FAX\n");
437 exit(2);
438 }
439 fax = fax_state_b;
440 t30 = fax_get_t30_state(fax);
441 fax_set_transmit_on_idle(fax, use_transmit_on_idle);
442 fax_set_tep_mode(fax, use_tep);
443 t30_set_supported_modems(t30, supported_modems);
444 t30_set_tx_ident(t30, "22222222");
445 t30_set_tx_nsf(t30, (const uint8_t *) "\x50\x00\x00\x00Spandsp\x00", 12);
446 t30_set_rx_file(t30, OUTPUT_FILE_NAME, -1);
447 t30_set_phase_b_handler(t30, phase_b_handler, (void *) (intptr_t) 'B');
448 t30_set_phase_d_handler(t30, phase_d_handler, (void *) (intptr_t) 'B');
449 t30_set_phase_e_handler(t30, phase_e_handler, (void *) (intptr_t) 'B');
450 t30_set_ecm_capability(t30, use_ecm);
451 if (use_ecm)
452 t30_set_supported_compressions(t30, T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION | T30_SUPPORT_T6_COMPRESSION);
453 t30_set_minimum_scan_line_time(t30, 40);
454
455 logging = fax_get_logging_state(fax);
456 span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
457 span_log_set_tag(logging, "FAX-B ");
458
459 logging = t30_get_logging_state(t30);
460 span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
461 span_log_set_tag(logging, "FAX-B ");
462
463 memset(t30_amp_b, 0, sizeof(t30_amp_b));
464
465 #if defined(ENABLE_GUI)
466 if (use_gui)
467 start_media_monitor();
468 #endif
469 hist_ptr = 0;
470 for (;;)
471 {
472 logging = fax_get_logging_state(fax_state_a);
473 span_log_bump_samples(logging, SAMPLES_PER_CHUNK);
474 t30 = fax_get_t30_state(fax_state_a);
475 logging = t30_get_logging_state(t30);
476 span_log_bump_samples(logging, SAMPLES_PER_CHUNK);
477 logging = t38_gateway_get_logging_state(t38_state_a);
478 span_log_bump_samples(logging, SAMPLES_PER_CHUNK);
479 t38_core = t38_gateway_get_t38_core_state(t38_state_a);
480 logging = t38_core_get_logging_state(t38_core);
481 span_log_bump_samples(logging, SAMPLES_PER_CHUNK);
482 logging = t38_gateway_get_logging_state(t38_state_b);
483 span_log_bump_samples(logging, SAMPLES_PER_CHUNK);
484 t38_core = t38_gateway_get_t38_core_state(t38_state_b);
485 logging = t38_core_get_logging_state(t38_core);
486 span_log_bump_samples(logging, SAMPLES_PER_CHUNK);
487 logging = fax_get_logging_state(fax_state_b);
488 span_log_bump_samples(logging, SAMPLES_PER_CHUNK);
489 t30 = fax_get_t30_state(fax_state_b);
490 logging = t30_get_logging_state(t30);
491 span_log_bump_samples(logging, SAMPLES_PER_CHUNK);
492 memset(out_amp, 0, sizeof(out_amp));
493
494 t30_len_a = fax_tx(fax_state_a, t30_amp_a, SAMPLES_PER_CHUNK);
495 if (!use_transmit_on_idle)
496 {
497 /* The receive side always expects a full block of samples, but the
498 transmit side may not be sending any when it doesn't need to. We
499 may need to pad with some silence. */
500 if (t30_len_a < SAMPLES_PER_CHUNK)
501 {
502 memset(t30_amp_a + t30_len_a, 0, sizeof(int16_t)*(SAMPLES_PER_CHUNK - t30_len_a));
503 t30_len_a = SAMPLES_PER_CHUNK;
504 }
505 }
506 if (log_audio)
507 {
508 for (i = 0; i < t30_len_a; i++)
509 out_amp[i*4] = t30_amp_a[i];
510 }
511 if (feedback_audio)
512 {
513 for (i = 0; i < t30_len_a; i++)
514 t30_amp_a[i] += t38_amp_hist_a[hist_ptr][i] >> 1;
515 memcpy(t38_amp_hist_a[hist_ptr], t38_amp_a, sizeof(int16_t)*SAMPLES_PER_CHUNK);
516 }
517 if (t38_gateway_rx(t38_state_a, t30_amp_a, t30_len_a))
518 break;
519
520 t38_len_a = t38_gateway_tx(t38_state_a, t38_amp_a, SAMPLES_PER_CHUNK);
521 if (!use_transmit_on_idle)
522 {
523 if (t38_len_a < SAMPLES_PER_CHUNK)
524 {
525 memset(t38_amp_a + t38_len_a, 0, sizeof(int16_t)*(SAMPLES_PER_CHUNK - t38_len_a));
526 t38_len_a = SAMPLES_PER_CHUNK;
527 }
528 }
529 if (log_audio)
530 {
531 for (i = 0; i < t38_len_a; i++)
532 out_amp[i*4 + 1] = t38_amp_a[i];
533 }
534 if (fax_rx(fax_state_a, t38_amp_a, SAMPLES_PER_CHUNK))
535 break;
536
537 t30_len_b = fax_tx(fax_state_b, t30_amp_b, SAMPLES_PER_CHUNK);
538 if (!use_transmit_on_idle)
539 {
540 /* The receive side always expects a full block of samples, but the
541 transmit side may not be sending any when it doesn't need to. We
542 may need to pad with some silence. */
543 if (t30_len_b < SAMPLES_PER_CHUNK)
544 {
545 memset(t30_amp_b + t30_len_b, 0, sizeof(int16_t)*(SAMPLES_PER_CHUNK - t30_len_b));
546 t30_len_b = SAMPLES_PER_CHUNK;
547 }
548 }
549 if (log_audio)
550 {
551 for (i = 0; i < t30_len_b; i++)
552 out_amp[i*4 + 3] = t30_amp_b[i];
553 }
554 if (feedback_audio)
555 {
556 for (i = 0; i < t30_len_b; i++)
557 t30_amp_b[i] += t38_amp_hist_b[hist_ptr][i] >> 1;
558 memcpy(t38_amp_hist_b[hist_ptr], t38_amp_b, sizeof(int16_t)*SAMPLES_PER_CHUNK);
559 }
560 if (t38_gateway_rx(t38_state_b, t30_amp_b, t30_len_b))
561 break;
562
563 t38_len_b = t38_gateway_tx(t38_state_b, t38_amp_b, SAMPLES_PER_CHUNK);
564 if (!use_transmit_on_idle)
565 {
566 if (t38_len_b < SAMPLES_PER_CHUNK)
567 {
568 memset(t38_amp_b + t38_len_b, 0, sizeof(int16_t)*(SAMPLES_PER_CHUNK - t38_len_b));
569 t38_len_b = SAMPLES_PER_CHUNK;
570 }
571 }
572 if (log_audio)
573 {
574 for (i = 0; i < t38_len_b; i++)
575 out_amp[i*4 + 2] = t38_amp_b[i];
576 }
577 if (fax_rx(fax_state_b, t38_amp_b, SAMPLES_PER_CHUNK))
578 break;
579
580 when += (float) SAMPLES_PER_CHUNK/(float) SAMPLE_RATE;
581
582 while ((msg_len = g1050_get(path_a_to_b, msg, 1024, when, &seq_no, &tx_when, &rx_when)) >= 0)
583 {
584 #if defined(ENABLE_GUI)
585 if (use_gui)
586 media_monitor_rx(seq_no, tx_when, rx_when);
587 #endif
588 t38_core = t38_gateway_get_t38_core_state(t38_state_b);
589 t38_core_rx_ifp_packet(t38_core, msg, msg_len, seq_no);
590 }
591 while ((msg_len = g1050_get(path_b_to_a, msg, 1024, when, &seq_no, &tx_when, &rx_when)) >= 0)
592 {
593 #if defined(ENABLE_GUI)
594 if (use_gui)
595 media_monitor_rx(seq_no, tx_when, rx_when);
596 #endif
597 t38_core = t38_gateway_get_t38_core_state(t38_state_a);
598 t38_core_rx_ifp_packet(t38_core, msg, msg_len, seq_no);
599 }
600 if (log_audio)
601 {
602 outframes = sf_writef_short(wave_handle, out_amp, SAMPLES_PER_CHUNK);
603 if (outframes != SAMPLES_PER_CHUNK)
604 break;
605 }
606
607 if (done[0] && done[1])
608 break;
609 #if defined(ENABLE_GUI)
610 if (use_gui)
611 media_monitor_update_display();
612 #endif
613 if (++hist_ptr > 3)
614 hist_ptr = 0;
615 }
616 t38_gateway_get_transfer_statistics(t38_state_a, &stats);
617 printf("A side exchanged %d pages at %dbps, in %s mode\n",
618 stats.pages_transferred,
619 stats.bit_rate,
620 (stats.error_correcting_mode) ? "ECM" : "non-ECM");
621 t38_gateway_get_transfer_statistics(t38_state_a, &stats);
622 printf("B side exchanged %d pages at %dbps, in %s mode\n",
623 stats.pages_transferred,
624 stats.bit_rate,
625 (stats.error_correcting_mode) ? "ECM" : "non-ECM");
626 fax_release(fax_state_a);
627 fax_release(fax_state_b);
628 if (log_audio)
629 {
630 if (sf_close(wave_handle) != 0)
631 {
632 fprintf(stderr, " Cannot close audio file '%s'\n", OUTPUT_FILE_NAME_WAVE);
633 exit(2);
634 }
635 }
636 if (!succeeded[0] || !succeeded[1])
637 {
638 printf("Tests failed\n");
639 exit(2);
640 }
641 printf("Tests passed\n");
642 return 0;
643 }
644 /*- End of function --------------------------------------------------------*/
645 /*- End of file ------------------------------------------------------------*/

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