1 /*
2 * SpanDSP - a series of DSP components for telephony
3 *
4 * fax_tests.c - Tests for the audio and T.38 FAX modules.
5 *
6 * Written by Steve Underwood <steveu@coppice.org>
7 *
8 * Copyright (C) 2005, 2006, 2009, 2010 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
26 /*! \file */
27
28 /*! \page fax_tests_page FAX tests
29 \section fax_tests_page_sec_1 What does it do?
30 These tests exercise the following FAX to FAX paths:
31
32 TSB85 <-----------+ +-----------> TSB85
33 \ /
34 T.31 <-----------+ \ / +-----------> T.31
35 \ \ / /
36 +--Modems-+-+-----------TDM/RTP-----------+-+-Modems--+
37 | \ / |
38 | \ / |
39 T.30 <---+ T.38 gateway T.38 gateway +---> T.30
40 | \ / |
41 | \ / |
42 +---T.38---+-+----+----UDPTL/RTP----+----+ +---T.38---+
43 / / \ / \ \
44 T.31 <------------/ / +----------TCP----------+ \ +------------> T.31
45 / \
46 TSB85 <------------+ +------------> TSB85
47
48 T.30<->Modems<-------------------------TDM/RTP------------------------->Modems<->T.30
49 T.30<->Modems<-TDM/RTP->T.38 gateway<-UDPTL/RTP->T.38 gateway<-TDM/RTP->Modems<->T.30
50 T.30<->Modems<-TDM/RTP->T.38 gateway<-UDPTL/RTP-------------------------->T.38<->T.30
51 T.30<->T.38<--------------------------UDPTL/RTP->T.38 gateway<-TDM/RTP->Modems<->T.30
52 T.30<->T.38<--------------------------UDPTL/RTP-------------------------->T.38<->T.30
53
54 The T.31 and TSB85 parts are incomplete right now.
55 */
56
57 #if defined(HAVE_CONFIG_H)
58 #include "config.h"
59 #endif
60
61 #if defined(HAVE_FL_FL_H) && defined(HAVE_FL_FL_CARTESIAN_H) && defined(HAVE_FL_FL_AUDIO_METER_H)
62 #define ENABLE_GUI
63 #endif
64
65 #include <stdlib.h>
66 #include <inttypes.h>
67 #include <stdio.h>
68 #include <fcntl.h>
69 #include <string.h>
70 #include <assert.h>
71 #include <errno.h>
72 #include <sndfile.h>
73 #if !defined(_WIN32)
74 #include <unistd.h>
75 #endif
76
77 #if defined(HAVE_LIBXML_XMLMEMORY_H)
78 #include <libxml/xmlmemory.h>
79 #endif
80 #if defined(HAVE_LIBXML_PARSER_H)
81 #include <libxml/parser.h>
82 #endif
83 #if defined(HAVE_LIBXML_XINCLUDE_H)
84 #include <libxml/xinclude.h>
85 #endif
86
87 #include "udptl.h"
88 #include "spandsp.h"
89 #include "spandsp-sim.h"
90
91 #if defined(ENABLE_GUI)
92 #include "media_monitor.h"
93 #endif
94 #include "fax_tester.h"
95 #include "fax_utils.h"
96 #include "pcap_parse.h"
97
98 #define SAMPLES_PER_CHUNK 160
99
100 #define INPUT_TIFF_FILE_NAME "../test-data/itu/fax/itutests.tif"
101 #define OUTPUT_TIFF_FILE_NAME "fax_tests.tif"
102 #define INPUT_WAVE_FILE_NAME "fax_cap.wav"
103 #define OUTPUT_WAVE_FILE_NAME "fax_tests.wav"
104
105 enum
106 {
107 AUDIO_FAX = 1,
108 T38_FAX,
109 T31_AUDIO_FAX,
110 T31_T38_FAX,
111 TSB85_AUDIO_FAX,
112 TSB85_T38_FAX,
113 REPLAY_AUDIO_FAX,
114 REPLAY_T38_FAX,
115 AUDIO_TO_T38_GATEWAY,
116 PASSTHROUGH,
117 AUDIO_CHAN,
118 T38_CHAN
119 };
120
121 const char *output_tiff_file_name;
122
123 struct audio_buf_s
124 {
125 int16_t amp[SAMPLES_PER_CHUNK];
126 int len;
127 };
128
129 struct chain_element_s
130 {
131 int node_type;
132 int left_chan_type;
133 int right_chan_type;
134 struct
135 {
136 fax_state_t *fax_state;
137 t38_terminal_state_t *t38_state;
138 faxtester_state_t *faxtester_state;
139 t38_gateway_state_t *t38_gateway_state;
140 SNDFILE *wave_handle;
141 } node;
142 struct
143 {
144 g1050_state_t *g1050_path;
145 both_ways_line_model_state_t *line_model;
146 struct audio_buf_s *audio_in_buf;
147 struct audio_buf_s *audio_out_buf;
148 } path;
149 t30_state_t *t30_state;
150 t38_core_state_t *t38_core_state;
151 int t38_subst_seq;
152 bool phase_e_reached;
153 bool completed;
154 bool succeeded;
155 t30_exchanged_info_t expected_rx_info;
156
157 awgn_state_t *awgn_state;
158
159 struct audio_buf_s audio_buf[2];
160
161 int peer;
162 int t38_peer;
163
164 char tag[10];
165 };
166
167 struct chain_element_s chain[7];
168 int chain_elements = 2;
169
170 bool t38_simulate_incrementing_repeats = false;
171 bool use_receiver_not_ready = false;
172 bool test_local_interrupt = false;
173
174 double when = 0.0;
175
phase_b_handler(void * user_data,int result)176 static int phase_b_handler(void *user_data, int result)
177 {
178 int i;
179 int ch;
180 int status;
181 int len;
182 t30_state_t *s;
183 char tag[20];
184 const char *u;
185 const uint8_t *v;
186 t30_exchanged_info_t *info;
187
188 i = (int) (intptr_t) user_data;
189 s = chain[i].t30_state;
190 ch = i + 'A';
191 info = &chain[i].expected_rx_info;
192 snprintf(tag, sizeof(tag), "%c: Phase B", ch);
193 printf("%c: Phase B handler - (0x%X) %s\n", ch, result, t30_frametype(result));
194 fax_log_rx_parameters(s, tag);
195 status = T30_ERR_OK;
196
197 if ((u = t30_get_rx_ident(s)))
198 {
199 printf("%c: Phase B remote ident '%s'\n", ch, u);
200 if (info->ident[0] && strcmp(info->ident, u))
201 {
202 printf("%c: Phase B: remote ident incorrect! - expected '%s'\n", ch, info->ident);
203 status = T30_ERR_IDENT_UNACCEPTABLE;
204 }
205 }
206 else
207 {
208 if (info->ident[0])
209 {
210 printf("%c: Phase B: remote ident missing!\n", ch);
211 status = T30_ERR_IDENT_UNACCEPTABLE;
212 }
213 }
214 if ((u = t30_get_rx_sub_address(s)))
215 {
216 printf("%c: Phase B: remote sub-address '%s'\n", ch, u);
217 if (info->sub_address[0] && strcmp(info->sub_address, u))
218 {
219 printf("%c: Phase B: remote sub-address incorrect! - expected '%s'\n", ch, info->sub_address);
220 status = T30_ERR_SUB_UNACCEPTABLE;
221 }
222 }
223 else
224 {
225 if (info->sub_address[0])
226 {
227 printf("%c: Phase B: remote sub-address missing!\n", ch);
228 status = T30_ERR_SUB_UNACCEPTABLE;
229 }
230 }
231 if ((u = t30_get_rx_polled_sub_address(s)))
232 {
233 printf("%c: Phase B: remote polled sub-address '%s'\n", ch, u);
234 if (info->polled_sub_address[0] && strcmp(info->polled_sub_address, u))
235 {
236 printf("%c: Phase B: remote polled sub-address incorrect! - expected '%s'\n", ch, info->polled_sub_address);
237 status = T30_ERR_PSA_UNACCEPTABLE;
238 }
239 }
240 else
241 {
242 if (info->polled_sub_address[0])
243 {
244 printf("%c: Phase B: remote polled sub-address missing!\n", ch);
245 status = T30_ERR_PSA_UNACCEPTABLE;
246 }
247 }
248 if ((u = t30_get_rx_selective_polling_address(s)))
249 {
250 printf("%c: Phase B: remote selective polling address '%s'\n", ch, u);
251 if (info->selective_polling_address[0] && strcmp(info->selective_polling_address, u))
252 {
253 printf("%c: Phase B: remote selective polling address incorrect! - expected '%s'\n", ch, info->selective_polling_address);
254 status = T30_ERR_SEP_UNACCEPTABLE;
255 }
256 }
257 else
258 {
259 if (info->selective_polling_address[0])
260 {
261 printf("%c: Phase B: remote selective polling address missing!\n", ch);
262 status = T30_ERR_SEP_UNACCEPTABLE;
263 }
264 }
265 if ((u = t30_get_rx_sender_ident(s)))
266 {
267 printf("%c: Phase B: remote sender ident '%s'\n", ch, u);
268 if (info->sender_ident[0] && strcmp(info->sender_ident, u))
269 {
270 printf("%c: Phase B: remote sender ident incorrect! - expected '%s'\n", ch, info->sender_ident);
271 status = T30_ERR_SID_UNACCEPTABLE;
272 }
273 }
274 else
275 {
276 if (info->sender_ident[0])
277 {
278 printf("%c: Phase B: remote sender ident missing!\n", ch);
279 status = T30_ERR_SID_UNACCEPTABLE;
280 }
281 }
282 if ((u = t30_get_rx_password(s)))
283 {
284 printf("%c: Phase B: remote password '%s'\n", ch, u);
285 if (info->password[0] && strcmp(info->password, u))
286 {
287 printf("%c: Phase B: remote password incorrect! - expected '%s'\n", ch, info->password);
288 status = T30_ERR_PWD_UNACCEPTABLE;
289 }
290 }
291 else
292 {
293 if (info->password[0])
294 {
295 printf("%c: Phase B: remote password missing!\n", ch);
296 status = T30_ERR_PWD_UNACCEPTABLE;
297 }
298 }
299 if ((len = t30_get_rx_nsf(s, &v)))
300 {
301 printf("%c: Phase B: NSF %d bytes\n", ch, len);
302 if (info->nsf_len && (info->nsf_len != len || memcmp(info->nsf, v, len)))
303 {
304 printf("%c: Phase B: remote NSF incorrect! - expected %u bytes\n", ch, (unsigned int) info->nsf_len);
305 }
306 }
307 else
308 {
309 if (info->nsf_len)
310 {
311 printf("%c: Phase B: remote NSF missing! - expected %u bytes\n", ch, (unsigned int) info->nsf_len);
312 }
313 }
314 if ((len = t30_get_rx_nsc(s, &v)))
315 {
316 printf("%c: Phase B: NSC %d bytes\n", ch, len);
317 if (info->nsc_len && (info->nsc_len != len || memcmp(info->nsc, v, len)))
318 {
319 printf("%c: Phase B: remote NSC incorrect! - expected %u bytes\n", ch, (unsigned int) info->nsc_len);
320 }
321 }
322 else
323 {
324 if (info->nsc_len)
325 {
326 printf("%c: Phase B: remote NSC missing! - expected %u bytes\n", ch, (unsigned int) info->nsc_len);
327 }
328 }
329 if ((len = t30_get_rx_nss(s, &v)))
330 {
331 printf("%c: Phase B: NSS %d bytes\n", ch, len);
332 if (info->nss_len && (info->nss_len != len || memcmp(info->nss, v, len)))
333 {
334 printf("%c: Phase B: remote NSS incorrect! - expected %u bytes\n", ch, (unsigned int) info->nss_len);
335 }
336 }
337 else
338 {
339 if (info->nss_len)
340 {
341 printf("%c: Phase B: remote NSS missing! - expected %u bytes\n", ch, (unsigned int) info->nsf_len);
342 }
343 }
344
345 return status;
346 }
347 /*- End of function --------------------------------------------------------*/
348
phase_d_handler(void * user_data,int result)349 static int phase_d_handler(void *user_data, int result)
350 {
351 int i;
352 int ch;
353 t30_state_t *s;
354 char tag[20];
355
356 i = (int) (intptr_t) user_data;
357 s = chain[i].t30_state;
358 ch = i + 'A';
359 snprintf(tag, sizeof(tag), "%c: Phase D", ch);
360 printf("%c: Phase D handler - (0x%X) %s\n", ch, result, t30_frametype(result));
361 fax_log_page_transfer_statistics(s, tag);
362 fax_log_tx_parameters(s, tag);
363 fax_log_rx_parameters(s, tag);
364
365 if (use_receiver_not_ready)
366 t30_set_receiver_not_ready(s, 3);
367
368 if (test_local_interrupt)
369 {
370 if (i == 0)
371 {
372 printf("%c: Initiating interrupt request\n", ch);
373 t30_local_interrupt_request(s, true);
374 }
375 else
376 {
377 switch (result)
378 {
379 case T30_PIP:
380 case T30_PRI_MPS:
381 case T30_PRI_EOM:
382 case T30_PRI_EOP:
383 printf("%c: Accepting interrupt request\n", ch);
384 t30_local_interrupt_request(s, true);
385 break;
386 case T30_PIN:
387 break;
388 }
389 }
390 }
391 return T30_ERR_OK;
392 }
393 /*- End of function --------------------------------------------------------*/
394
phase_e_handler(void * user_data,int result)395 static void phase_e_handler(void *user_data, int result)
396 {
397 int i;
398 int ch;
399 t30_stats_t t;
400 t30_state_t *s;
401 char tag[20];
402
403 i = (int) (intptr_t) user_data;
404 s = chain[i].t30_state;
405 ch = i + 'A';
406 snprintf(tag, sizeof(tag), "%c: Phase E", ch);
407 printf("%c: Phase E handler - (%d) %s\n", ch, result, t30_completion_code_to_str(result));
408 fax_log_final_transfer_statistics(s, tag);
409 fax_log_tx_parameters(s, tag);
410 fax_log_rx_parameters(s, tag);
411 t30_get_transfer_statistics(s, &t);
412 chain[i].succeeded = (result == T30_ERR_OK);
413 chain[i].phase_e_reached = true;
414 }
415 /*- End of function --------------------------------------------------------*/
416
real_time_t30_frame_handler(void * user_data,bool incoming,const uint8_t * msg,int len)417 static void real_time_t30_frame_handler(void *user_data,
418 bool incoming,
419 const uint8_t *msg,
420 int len)
421 {
422 int i;
423 int ch;
424
425 i = (intptr_t) user_data;
426 ch = i + 'A';
427 printf("%c: Real time frame handler - %s, %s, length = %d\n",
428 ch,
429 (incoming) ? "line->T.30" : "T.30->line",
430 t30_frametype(msg[2]),
431 len);
432 }
433 /*- End of function --------------------------------------------------------*/
434
document_handler(void * user_data,int event)435 static int document_handler(void *user_data, int event)
436 {
437 int i;
438 int ch;
439
440 i = (intptr_t) user_data;
441 ch = i + 'A';
442 printf("%c: Document handler - event %d\n", ch, event);
443 return false;
444 }
445 /*- End of function --------------------------------------------------------*/
446
set_t30_callbacks(t30_state_t * t30,int chan)447 static void set_t30_callbacks(t30_state_t *t30, int chan)
448 {
449 t30_set_phase_b_handler(t30, phase_b_handler, (void *) (intptr_t) chan);
450 t30_set_phase_d_handler(t30, phase_d_handler, (void *) (intptr_t) chan);
451 t30_set_phase_e_handler(t30, phase_e_handler, (void *) (intptr_t) chan);
452 t30_set_real_time_frame_handler(t30, real_time_t30_frame_handler, (void *) (intptr_t) chan);
453 t30_set_document_handler(t30, document_handler, (void *) (intptr_t) chan);
454 }
455 /*- End of function --------------------------------------------------------*/
456
real_time_gateway_frame_handler(void * user_data,bool incoming,const uint8_t * msg,int len)457 static void real_time_gateway_frame_handler(void *user_data,
458 bool incoming,
459 const uint8_t *msg,
460 int len)
461 {
462 int i;
463
464 i = (intptr_t) user_data;
465 printf("%c: Real time gateway frame handler - %s, %s, length = %d\n",
466 i + 'A',
467 (incoming) ? "PSTN->T.38" : "T.38->PSTN",
468 t30_frametype(msg[2]),
469 len);
470 }
471 /*- End of function --------------------------------------------------------*/
472
tx_packet_handler(t38_core_state_t * s,void * user_data,const uint8_t * buf,int len,int count)473 static int tx_packet_handler(t38_core_state_t *s, void *user_data, const uint8_t *buf, int len, int count)
474 {
475 int i;
476 int chan;
477
478 /* This routine queues messages between two instances of T.38 processing */
479 chan = (intptr_t) user_data;
480 if (t38_simulate_incrementing_repeats)
481 {
482 for (i = 0; i < count; i++)
483 {
484 span_log(&s->logging, SPAN_LOG_FLOW, "Send seq %d, len %d\n", chain[chan].t38_subst_seq, len);
485
486 if (g1050_put(chain[chan].path.g1050_path, buf, len, chain[chan].t38_subst_seq, when) < 0)
487 printf("Lost packet %d\n", chain[chan].t38_subst_seq);
488 chain[chan].t38_subst_seq = (chain[chan].t38_subst_seq + 1) & 0xFFFF;
489 }
490 }
491 else
492 {
493 span_log(&s->logging, SPAN_LOG_FLOW, "Send seq %d, len %d, count %d\n", s->tx_seq_no, len, count);
494
495 for (i = 0; i < count; i++)
496 {
497 if (g1050_put(chain[chan].path.g1050_path, buf, len, s->tx_seq_no, when) < 0)
498 printf("Lost packet %d\n", s->tx_seq_no);
499 }
500 }
501 return 0;
502 }
503 /*- End of function --------------------------------------------------------*/
504
t33_tests(void)505 static void t33_tests(void)
506 {
507 int n;
508 int item_no;
509 int type;
510 uint8_t num[21];
511 uint8_t new_t33[133];
512 /* These patterns are from the T.33 spec */
513 static const uint8_t *pkts[] =
514 {
515 (const uint8_t *) "#1234567890#1234",
516 (const uint8_t *) "1234#5678#8910",
517 (const uint8_t *) "#6174444100#1234#567",
518 (const uint8_t *) "1234#5678##2032223",
519 (const uint8_t *) "#2037445555##6446666",
520 (const uint8_t *) "#2037445555#1234##6446666#5678",
521 //(const uint8_t *) "#123456789012345678901#1234##6446666#5678",
522 (const uint8_t *) ""
523 };
524
525 printf("T.33 sub-address packing/unpacking tests\n");
526 for (n = 0; pkts[n][0]; n++)
527 {
528 new_t33[0] = '\0';
529 printf("'%s'\n", pkts[n]);
530 for (item_no = 0; item_no < 100; item_no++)
531 {
532 if ((type = t33_sub_address_extract_field(num, pkts[n], item_no)) <= 0)
533 {
534 if (type == T33_NONE)
535 break;
536 printf("Bad sub-address field\n");
537 exit(2);
538 }
539 switch (type)
540 {
541 case T33_SST:
542 printf("SST '%s'\n", num);
543 t33_sub_address_add_field(new_t33, num, type);
544 break;
545 case T33_EXT:
546 printf(" EXT '%s'\n", num);
547 t33_sub_address_add_field(new_t33, num, type);
548 break;
549 }
550 }
551 if (strcmp((const char *) pkts[n], (const char *) new_t33))
552 {
553 printf("Re-encode mismatch '%s' '%s'\n", pkts[n], new_t33);
554 exit(2);
555 }
556 }
557 }
558 /*- End of function --------------------------------------------------------*/
559
main(int argc,char * argv[])560 int main(int argc, char *argv[])
561 {
562 int16_t silence[SAMPLES_PER_CHUNK];
563 int16_t t38_amp_hist_a[8][SAMPLES_PER_CHUNK];
564 int16_t t38_amp_hist_b[8][SAMPLES_PER_CHUNK];
565 int16_t audio_log[SAMPLES_PER_CHUNK*4];
566 int hist_ptr;
567 int log_audio;
568 int msg_len;
569 uint8_t msg[1024];
570 int outframes;
571 SNDFILE *wave_handle;
572 bool use_ecm;
573 bool use_tep;
574 bool use_polled_mode;
575 bool use_transmit_on_idle;
576 bool feedback_audio;
577 int t38_version;
578 const char *input_tiff_file_name;
579 const char *replay_file_name;
580 int i;
581 int j;
582 int k;
583 int seq_no;
584 int g1050_model_no;
585 int g1050_speed_pattern_no;
586 int t38_transport;
587 double tx_when;
588 double rx_when;
589 int supported_modems;
590 int opt;
591 int start_page;
592 int end_page;
593 int drop_frame;
594 int drop_frame_rate;
595 float signal_scaling;
596 int signal_level;
597 int noise_level;
598 int code_to_look_up;
599 int scan_line_time;
600 int allowed_bilevel_resolutions[2];
601 int allowed;
602 bool remove_fill_bits;
603 bool colour_enabled;
604 bool t37_like_output;
605 t38_stats_t t38_stats;
606 t30_stats_t t30_stats;
607 logging_state_t *logging;
608 int expected_pages;
609 char *page_header_info;
610 char *page_header_tz;
611 const char *xml_file_name;
612 const char *xml_test_name[2];
613 int xml_step;
614 char buf[132 + 1];
615 int line_model_no;
616 int channel_codec;
617 int rbs_pattern;
618 #if defined(ENABLE_GUI)
619 int use_gui;
620 #endif
621
622 #if defined(ENABLE_GUI)
623 use_gui = false;
624 #endif
625 log_audio = false;
626 use_ecm = false;
627 t38_version = 1;
628 input_tiff_file_name = INPUT_TIFF_FILE_NAME;
629 output_tiff_file_name = OUTPUT_TIFF_FILE_NAME;
630 t38_simulate_incrementing_repeats = false;
631 g1050_model_no = 0;
632 g1050_speed_pattern_no = 1;
633 remove_fill_bits = false;
634 use_tep = false;
635 feedback_audio = false;
636 use_transmit_on_idle = true;
637 use_polled_mode = false;
638 supported_modems = T30_SUPPORT_V27TER | T30_SUPPORT_V29 | T30_SUPPORT_V17;
639 page_header_info = NULL;
640 page_header_tz = NULL;
641 drop_frame = 0;
642 drop_frame_rate = 0;
643 start_page = -1;
644 end_page = -1;
645 signal_level = 0;
646 noise_level = -99;
647 scan_line_time = 0;
648 replay_file_name = INPUT_WAVE_FILE_NAME;
649 code_to_look_up = -1;
650 allowed_bilevel_resolutions[0] = 0;
651 allowed_bilevel_resolutions[1] = 0;
652 allowed = 0;
653 line_model_no = 0;
654 channel_codec = MUNGE_CODEC_NONE;
655 rbs_pattern = 0;
656 colour_enabled = false;
657 t37_like_output = false;
658 t38_transport = T38_TRANSPORT_UDPTL;
659 xml_file_name = "../spandsp/tsb85.xml";
660 xml_test_name[0] = "MRGN01";
661 xml_test_name[1] = "MRGN01";
662 xml_step = 0;
663 while ((opt = getopt(argc, argv, "7b:c:Cd:D:efFgH:i:Ilm:M:n:p:Ps:S:tT:u:v:x:X:z:")) != -1)
664 {
665 switch (opt)
666 {
667 case '7':
668 t37_like_output = true;
669 break;
670 case 'b':
671 allowed_bilevel_resolutions[allowed] = atoi(optarg);
672 allowed ^= 1;
673 break;
674 case 'c':
675 code_to_look_up = atoi(optarg);
676 break;
677 case 'C':
678 colour_enabled = true;
679 break;
680 case 'd':
681 replay_file_name = optarg;
682 break;
683 case 'D':
684 drop_frame_rate =
685 drop_frame = atoi(optarg);
686 break;
687 case 'e':
688 use_ecm = true;
689 break;
690 case 'f':
691 feedback_audio = true;
692 break;
693 case 'F':
694 remove_fill_bits = true;
695 break;
696 case 'g':
697 #if defined(ENABLE_GUI)
698 use_gui = true;
699 #else
700 fprintf(stderr, "Graphical monitoring not available\n");
701 exit(2);
702 #endif
703 break;
704 case 'H':
705 page_header_info = optarg;
706 break;
707 case 'i':
708 input_tiff_file_name = optarg;
709 break;
710 case 'I':
711 t38_simulate_incrementing_repeats = true;
712 break;
713 case 'l':
714 log_audio = true;
715 break;
716 case 'm':
717 supported_modems = atoi(optarg);
718 break;
719 case 'M':
720 g1050_model_no = optarg[0] - 'A' + 1;
721 break;
722 case 'n':
723 noise_level = atoi(optarg);
724 break;
725 case 'p':
726 /*
727 -p FAX-audio-FAX
728 -p FAX-T38-FAX
729 -p FAX-audio-T38gateway-T38-T38gateway-audio-FAX
730 -p FAX-T38-T38gateway-audio-T38gateway-T38-FAX
731 -p FAX-T38-T38gateway-audio-FAX
732 -p FAX-audio-T38gateway-T38-FAX
733 -p tester-audio-FAX
734 -p tester-T38-FAX
735 -p tester-audio-T38gateway-T38-T38gateway-audio-FAX
736 -p tester-T38-T38gateway-audio-T38gateway-T38-FAX
737 -p tester-T38-T38gateway-audio-FAX
738 -p tester-audio-T38gateway-T38-FAX
739 */
740 for (i = 0, chain_elements = 0, k = 0; chain_elements < 7; i++)
741 {
742 if (optarg[i] != '-' && optarg[i] != '\0')
743 continue;
744 j = optarg[i];
745 optarg[i] = '\0';
746 if (strcmp(&optarg[k], "FAX") == 0)
747 {
748 chain[chain_elements++].node_type = AUDIO_FAX;
749 }
750 else if (strcmp(&optarg[k], "T38") == 0)
751 {
752 chain[chain_elements++].node_type = T38_FAX;
753 }
754 else if (strcmp(&optarg[k], "T31") == 0)
755 {
756 chain[chain_elements++].node_type = T31_AUDIO_FAX;
757 }
758 else if (strcmp(&optarg[k], "tester") == 0)
759 {
760 chain[chain_elements++].node_type = TSB85_AUDIO_FAX;
761 }
762 else if (strcmp(&optarg[k], "replay") == 0)
763 {
764 chain[chain_elements++].node_type = REPLAY_AUDIO_FAX;
765 }
766 else if (strcmp(&optarg[k], "T38gateway") == 0)
767 {
768 chain[chain_elements++].node_type = AUDIO_TO_T38_GATEWAY;
769 }
770 else if (strcmp(&optarg[k], "passthrough") == 0)
771 {
772 chain[chain_elements++].node_type = PASSTHROUGH;
773 }
774 else
775 {
776 fprintf(stderr, "Unknown FAX path element %s\n", &optarg[k]);
777 exit(2);
778 }
779 k = i + 1;
780 if (j == '\0')
781 break;
782 }
783 #if 0
784 if ((chain[0].node_type == AUDIO_FAX && chain[chain_elements - 1].node_type != AUDIO_FAX)
785 ||
786 (chain[0].node_type != AUDIO_FAX && chain[chain_elements - 1].node_type == AUDIO_FAX))
787 {
788 fprintf(stderr, "Invalid FAX path\n");
789 exit(2);
790 }
791 #endif
792 break;
793 case 'P':
794 use_polled_mode = true;
795 break;
796 case 's':
797 g1050_speed_pattern_no = atoi(optarg);
798 break;
799 #if 0
800 case 's':
801 signal_level = atoi(optarg);
802 break;
803 #endif
804 case 'S':
805 scan_line_time = atoi(optarg);
806 break;
807 case 't':
808 use_tep = true;
809 break;
810 case 'T':
811 start_page = 0;
812 end_page = atoi(optarg);
813 break;
814 case 'u':
815 if (strcasecmp(optarg, "udptl") == 0)
816 t38_transport = T38_TRANSPORT_UDPTL;
817 else if (strcasecmp(optarg, "rtp") == 0)
818 t38_transport = T38_TRANSPORT_RTP;
819 else if (strcasecmp(optarg, "tcp") == 0)
820 t38_transport = T38_TRANSPORT_TCP;
821 else if (strcasecmp(optarg, "tcp-tpkt") == 0)
822 t38_transport = T38_TRANSPORT_TCP_TPKT;
823 else
824 {
825 fprintf(stderr, "Unknown T.38 transport mode\n");
826 exit(2);
827 }
828 break;
829 case 'v':
830 t38_version = atoi(optarg);
831 break;
832 case 'x':
833 xml_test_name[xml_step] = optarg;
834 xml_step ^= 1;
835 break;
836 case 'X':
837 xml_file_name = optarg;
838 break;
839 case 'z':
840 page_header_tz = optarg;
841 break;
842 default:
843 //usage();
844 exit(2);
845 break;
846 }
847 }
848
849 if (code_to_look_up >= 0)
850 {
851 printf("Result code %d is %s\n", code_to_look_up, t30_completion_code_to_str(code_to_look_up));
852 exit(0);
853 }
854
855 printf("Using T.38 version %d\n", t38_version);
856 if (use_ecm)
857 printf("Using ECM\n");
858
859 wave_handle = NULL;
860 if (log_audio)
861 {
862 if ((wave_handle = sf_open_telephony_write(OUTPUT_WAVE_FILE_NAME, 4)) == NULL)
863 {
864 fprintf(stderr, " Cannot create audio file '%s'\n", OUTPUT_WAVE_FILE_NAME);
865 exit(2);
866 }
867 }
868 memset(silence, 0, sizeof(silence));
869
870 srand48(0x1234567);
871
872 memset(t38_amp_hist_a, 0, sizeof(t38_amp_hist_a));
873 memset(t38_amp_hist_b, 0, sizeof(t38_amp_hist_b));
874
875 /* Set up the nodes */
876 chain[0].peer = chain_elements - 1;
877 chain[chain_elements - 1].peer = 0;
878
879 for (i = 0; i < chain_elements; i++)
880 {
881 chain[i].tag[0] = i + 'A';
882 chain[i].tag[1] = '\0';
883
884 memset(&chain[i].audio_buf[0], 0, sizeof(chain[i].audio_buf[0]));
885 memset(&chain[i].audio_buf[1], 0, sizeof(chain[i].audio_buf[1]));
886 memset(&chain[i].expected_rx_info, 0, sizeof(chain[i].expected_rx_info));
887
888 switch (chain[i].node_type)
889 {
890 case AUDIO_FAX:
891 if ((chain[i].node.fax_state = fax_init(NULL, (i == 0))) == NULL)
892 {
893 fprintf(stderr, " Cannot start FAX instance\n");
894 exit(2);
895 }
896 chain[i].t30_state = fax_get_t30_state(chain[i].node.fax_state);
897
898 logging = fax_get_logging_state(chain[i].node.fax_state);
899 span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
900 span_log_set_tag(logging, chain[i].tag);
901
902 logging = fax_modems_get_logging_state(&chain[i].node.fax_state->modems);
903 span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
904 span_log_set_tag(logging, chain[i].tag);
905
906 logging = t30_get_logging_state(chain[i].t30_state);
907 span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
908 span_log_set_tag(logging, chain[i].tag);
909
910 set_t30_callbacks(chain[i].t30_state, i);
911
912 chain[i].path.audio_in_buf = &chain[i + ((i == 0) ? 1 : -1)].audio_buf[0];
913 chain[i].path.audio_out_buf = &chain[i].audio_buf[0];
914
915 chain[i].awgn_state = NULL;
916 signal_scaling = 1.0f;
917 if (noise_level > -99)
918 {
919 chain[i].awgn_state = awgn_init_dbm0(NULL, 1234567, noise_level);
920 signal_scaling = powf(10.0f, signal_level/20.0f);
921 printf("Signal scaling %f\n", signal_scaling);
922 }
923 break;
924 case T38_FAX:
925 if ((chain[i].node.t38_state = t38_terminal_init(NULL, (i == 0), tx_packet_handler, (void *) (intptr_t) i)) == NULL)
926 {
927 fprintf(stderr, " Cannot start the T.38 terminal instance\n");
928 exit(2);
929 }
930 chain[i].t30_state = t38_terminal_get_t30_state(chain[i].node.t38_state);
931 chain[i].t38_core_state = t38_terminal_get_t38_core_state(chain[i].node.t38_state);
932
933 logging = t38_terminal_get_logging_state(chain[i].node.t38_state);
934 span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
935 span_log_set_tag(logging, chain[i].tag);
936
937 logging = t38_core_get_logging_state(chain[i].t38_core_state);
938 span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
939 span_log_set_tag(logging, chain[i].tag);
940
941 logging = t30_get_logging_state(chain[i].t30_state);
942 span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
943 span_log_set_tag(logging, chain[i].tag);
944
945 set_t30_callbacks(chain[i].t30_state, i);
946
947 if (i == 0)
948 {
949 chain[i].t38_peer = i + 1;
950 }
951 else
952 {
953 switch (chain[i - 1].node_type)
954 {
955 case T38_FAX:
956 case AUDIO_TO_T38_GATEWAY:
957 chain[i].t38_peer = i - 1;
958 break;
959 default:
960 chain[i].t38_peer = i + 1;
961 break;
962 }
963 }
964 break;
965 case T31_AUDIO_FAX:
966 break;
967 case T31_T38_FAX:
968 break;
969 case TSB85_AUDIO_FAX:
970 case TSB85_T38_FAX:
971 if ((chain[i].node.faxtester_state = faxtester_init(NULL, xml_file_name, xml_test_name[(i == 0) ? 0 : 1])) == NULL)
972 {
973 fprintf(stderr, " Cannot start FAX tester instance\n");
974 exit(2);
975 }
976 logging = faxtester_get_logging_state(chain[i].node.faxtester_state);
977 span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
978 span_log_set_tag(logging, chain[i].tag);
979
980 faxtester_set_transmit_on_idle(chain[i].node.faxtester_state, true);
981
982 chain[i].path.audio_in_buf = &chain[i + ((i == 0) ? 1 : -1)].audio_buf[0];
983 chain[i].path.audio_out_buf = &chain[i].audio_buf[0];
984
985 if (i == 0)
986 {
987 chain[i].t38_peer = i + 1;
988 }
989 else
990 {
991 switch (chain[i - 1].node_type)
992 {
993 case T38_FAX:
994 case AUDIO_TO_T38_GATEWAY:
995 chain[i].t38_peer = i - 1;
996 break;
997 default:
998 chain[i].t38_peer = i + 1;
999 break;
1000 }
1001 }
1002
1003 chain[i].awgn_state = NULL;
1004 signal_scaling = 1.0f;
1005 if (noise_level > -99)
1006 {
1007 chain[i].awgn_state = awgn_init_dbm0(NULL, 1234567, noise_level);
1008 signal_scaling = powf(10.0f, signal_level/20.0f);
1009 printf("Signal scaling %f\n", signal_scaling);
1010 }
1011 break;
1012 case REPLAY_AUDIO_FAX:
1013 if ((chain[i].node.wave_handle = sf_open_telephony_read(replay_file_name, 1)) == NULL)
1014 {
1015 fprintf(stderr, " Cannot open audio file '%s'\n", replay_file_name);
1016 exit(2);
1017 }
1018
1019 chain[i].path.audio_in_buf = &chain[i + ((i == 0) ? 1 : -1)].audio_buf[0];
1020 chain[i].path.audio_out_buf = &chain[i].audio_buf[0];
1021 break;
1022 case AUDIO_TO_T38_GATEWAY:
1023 if ((chain[i].node.t38_gateway_state = t38_gateway_init(NULL, tx_packet_handler, (void *) (intptr_t) i)) == NULL)
1024 {
1025 fprintf(stderr, " Cannot start T.38 gateway instance\n");
1026 exit(2);
1027 }
1028 chain[i].t38_core_state = t38_gateway_get_t38_core_state(chain[i].node.t38_gateway_state);
1029
1030 logging = t38_gateway_get_logging_state(chain[i].node.t38_gateway_state);
1031 span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
1032 span_log_set_tag(logging, chain[i].tag);
1033
1034 logging = fax_modems_get_logging_state(&chain[i].node.t38_gateway_state->audio.modems);
1035 span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
1036 span_log_set_tag(logging, chain[i].tag);
1037
1038 logging = t38_core_get_logging_state(chain[i].t38_core_state);
1039 span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
1040 span_log_set_tag(logging, chain[i].tag);
1041
1042 t38_gateway_set_transmit_on_idle(chain[i].node.t38_gateway_state, use_transmit_on_idle);
1043 t38_gateway_set_supported_modems(chain[i].node.t38_gateway_state, supported_modems);
1044 //t38_gateway_set_nsx_suppression(chain[i].node.t38_state, NULL, 0, NULL, 0);
1045 t38_gateway_set_fill_bit_removal(chain[i].node.t38_gateway_state, remove_fill_bits);
1046 t38_gateway_set_real_time_frame_handler(chain[i].node.t38_gateway_state, real_time_gateway_frame_handler, (void *) (intptr_t) i);
1047 t38_gateway_set_ecm_capability(chain[i].node.t38_gateway_state, use_ecm);
1048 t38_set_t38_version(chain[i].t38_core_state, t38_version);
1049
1050 if (i == 0)
1051 {
1052 chain[i].t38_peer = i + 1;
1053 chain[i].path.audio_in_buf = NULL;
1054 }
1055 else
1056 {
1057 switch (chain[i - 1].node_type)
1058 {
1059 case T38_FAX:
1060 case AUDIO_TO_T38_GATEWAY:
1061 chain[i].t38_peer = i - 1;
1062 chain[i].path.audio_in_buf = &chain[i + 1].audio_buf[0];
1063 break;
1064 default:
1065 chain[i].t38_peer = i + 1;
1066 chain[i].path.audio_in_buf = &chain[i - 1].audio_buf[0];
1067 break;
1068 }
1069 }
1070
1071 chain[i].path.audio_out_buf = &chain[i].audio_buf[0];
1072
1073 chain[i].awgn_state = NULL;
1074 signal_scaling = 1.0f;
1075 if (noise_level > -99)
1076 {
1077 chain[i].awgn_state = awgn_init_dbm0(NULL, 1234567, noise_level);
1078 signal_scaling = powf(10.0f, signal_level/20.0f);
1079 printf("Signal scaling %f\n", signal_scaling);
1080 }
1081 }
1082 if ((chain[i].path.g1050_path = g1050_init(g1050_model_no, g1050_speed_pattern_no, 100, 33)) == NULL)
1083 {
1084 fprintf(stderr, " Failed to start IP network path model\n");
1085 exit(2);
1086 }
1087 }
1088
1089 for (i = 0; i < chain_elements; i++)
1090 {
1091 j = i + 1;
1092 if (chain[i].t30_state)
1093 {
1094 sprintf(buf, "%d%d%d%d%d%d%d%d", j, j, j, j, j, j, j, j);
1095 t30_set_tx_ident(chain[i].t30_state, buf);
1096 strcpy(chain[chain[i].peer].expected_rx_info.ident, buf);
1097 sprintf(buf, "Sub-address %d", j);
1098 t30_set_tx_sub_address(chain[i].t30_state, buf);
1099 //strcpy(chain[chain[i].peer].expected_rx_info.sub_address, buf);
1100 sprintf(buf, "Sender ID %d", j);
1101 t30_set_tx_sender_ident(chain[i].t30_state, buf);
1102 //strcpy(chain[chain[i].peer].expected_rx_info.sender_ident, buf);
1103 sprintf(buf, "Password %d", j);
1104 t30_set_tx_password(chain[i].t30_state, buf);
1105 //strcpy(chain[chain[i].peer].expected_rx_info.password, buf);
1106 sprintf(buf, "Polled sub-add %d", j);
1107 t30_set_tx_polled_sub_address(chain[i].t30_state, buf);
1108 //strcpy(chain[chain[i].peer].expected_rx_info.polled_sub_address, buf);
1109 sprintf(buf, "Select poll add %d", j);
1110 t30_set_tx_selective_polling_address(chain[i].t30_state, buf);
1111 //strcpy(chain[chain[i].peer].expected_rx_info.selective_polling_address, buf);
1112 t30_set_tx_page_header_info(chain[i].t30_state, page_header_info);
1113 if (page_header_tz)
1114 t30_set_tx_page_header_tz(chain[i].t30_state, page_header_tz);
1115
1116 if (i != 0)
1117 {
1118 t30_set_tx_nsf(chain[i].t30_state, (const uint8_t *) "\x50\x00\x00\x00Spandsp\x00", 12);
1119 chain[chain[i].peer].expected_rx_info.nsf = (uint8_t *) "\x50\x00\x00\x00Spandsp\x00";
1120 chain[chain[i].peer].expected_rx_info.nsf_len = 12;
1121 }
1122
1123 t30_set_supported_modems(chain[i].t30_state, supported_modems);
1124 t30_set_supported_t30_features(chain[i].t30_state,
1125 T30_SUPPORT_IDENTIFICATION
1126 | T30_SUPPORT_SELECTIVE_POLLING
1127 | T30_SUPPORT_SUB_ADDRESSING);
1128 t30_set_supported_image_sizes(chain[i].t30_state,
1129 T4_SUPPORT_WIDTH_215MM
1130 | T4_SUPPORT_WIDTH_255MM
1131 | T4_SUPPORT_WIDTH_303MM
1132 | T4_SUPPORT_LENGTH_US_LETTER
1133 | T4_SUPPORT_LENGTH_US_LEGAL
1134 | T4_SUPPORT_LENGTH_UNLIMITED);
1135 switch (allowed_bilevel_resolutions[(i == 0) ? 0 : 1])
1136 {
1137 case 0:
1138 /* Allow anything */
1139 t30_set_supported_bilevel_resolutions(chain[i].t30_state,
1140 T4_RESOLUTION_R8_STANDARD
1141 | T4_RESOLUTION_R8_FINE
1142 | T4_RESOLUTION_R8_SUPERFINE
1143 | T4_RESOLUTION_R16_SUPERFINE
1144 | T4_RESOLUTION_200_100
1145 | T4_RESOLUTION_200_200
1146 | T4_RESOLUTION_200_400
1147 | T4_RESOLUTION_300_300
1148 | T4_RESOLUTION_300_600
1149 | T4_RESOLUTION_400_400
1150 | T4_RESOLUTION_400_800
1151 | T4_RESOLUTION_600_600
1152 | T4_RESOLUTION_600_1200
1153 | T4_RESOLUTION_1200_1200);
1154 break;
1155 case 1:
1156 /* Allow anything metric */
1157 t30_set_supported_bilevel_resolutions(chain[i].t30_state,
1158 T4_RESOLUTION_R8_STANDARD
1159 | T4_RESOLUTION_R8_FINE
1160 | T4_RESOLUTION_R8_SUPERFINE
1161 | T4_RESOLUTION_R16_SUPERFINE);
1162 break;
1163 case 2:
1164 /* Allow anything inch based */
1165 t30_set_supported_bilevel_resolutions(chain[i].t30_state,
1166 T4_RESOLUTION_200_100
1167 | T4_RESOLUTION_200_200
1168 | T4_RESOLUTION_200_400
1169 | T4_RESOLUTION_300_300
1170 | T4_RESOLUTION_300_600
1171 | T4_RESOLUTION_400_400
1172 | T4_RESOLUTION_400_800
1173 | T4_RESOLUTION_600_600
1174 | T4_RESOLUTION_600_1200
1175 | T4_RESOLUTION_1200_1200);
1176 break;
1177 case 3:
1178 /* Allow only restricted length resolution */
1179 t30_set_supported_bilevel_resolutions(chain[i].t30_state,
1180 T4_RESOLUTION_R8_STANDARD
1181 | T4_RESOLUTION_R8_FINE
1182 | T4_RESOLUTION_200_100
1183 | T4_RESOLUTION_200_200);
1184 break;
1185 case 4:
1186 /* Allow only more restricted length resolution */
1187 t30_set_supported_bilevel_resolutions(chain[i].t30_state,
1188 T4_RESOLUTION_R8_STANDARD
1189 | T4_RESOLUTION_200_100);
1190 break;
1191 }
1192 if (colour_enabled)
1193 {
1194 t30_set_supported_colour_resolutions(chain[i].t30_state,
1195 T4_RESOLUTION_100_100
1196 | T4_RESOLUTION_200_200
1197 | T4_RESOLUTION_300_300
1198 | T4_RESOLUTION_400_400
1199 | T4_RESOLUTION_600_600
1200 | T4_RESOLUTION_1200_1200);
1201 }
1202 else
1203 {
1204 t30_set_supported_colour_resolutions(chain[i].t30_state, 0);
1205 }
1206 if (t37_like_output)
1207 {
1208 t30_set_supported_output_compressions(chain[i].t30_state,
1209 T4_COMPRESSION_T85
1210 | T4_COMPRESSION_T85_L0
1211 | T4_COMPRESSION_T6
1212 | T4_COMPRESSION_T42_T81);
1213 }
1214 else
1215 {
1216 t30_set_supported_output_compressions(chain[i].t30_state,
1217 T4_COMPRESSION_T6
1218 | T4_COMPRESSION_JPEG);
1219 }
1220
1221 t30_set_ecm_capability(chain[i].t30_state, use_ecm);
1222 t30_set_supported_compressions(chain[i].t30_state,
1223 T4_COMPRESSION_T4_1D
1224 | T4_COMPRESSION_T4_2D
1225 | T4_COMPRESSION_T6
1226 | T4_COMPRESSION_T85
1227 | T4_COMPRESSION_T85_L0
1228 //| T4_COMPRESSION_T88
1229 | T4_COMPRESSION_T43
1230 | T4_COMPRESSION_T45
1231 | T4_COMPRESSION_T42_T81
1232 | T4_COMPRESSION_SYCC_T81
1233 | T4_COMPRESSION_GRAYSCALE
1234 | T4_COMPRESSION_COLOUR
1235 | T4_COMPRESSION_12BIT
1236 | T4_COMPRESSION_COLOUR_TO_GRAY
1237 | T4_COMPRESSION_GRAY_TO_BILEVEL
1238 | T4_COMPRESSION_COLOUR_TO_BILEVEL
1239 | T4_COMPRESSION_RESCALING
1240 | 0);
1241 t30_set_minimum_scan_line_time(chain[i].t30_state, scan_line_time);
1242 }
1243
1244 switch (chain[i].node_type)
1245 {
1246 case AUDIO_FAX:
1247 fax_set_transmit_on_idle(chain[i].node.fax_state, use_transmit_on_idle);
1248 fax_set_tep_mode(chain[i].node.fax_state, use_tep);
1249 break;
1250 case T38_FAX:
1251 t38_set_t38_version(chain[i].t38_core_state, t38_version);
1252 //t30_set_iaf_mode(chain[i].t30_state, T30_IAF_MODE_NO_FILL_BITS);
1253 switch (t38_transport)
1254 {
1255 case T38_TRANSPORT_UDPTL:
1256 case T38_TRANSPORT_RTP:
1257 t38_terminal_set_fill_bit_removal(chain[i].node.t38_state, remove_fill_bits);
1258 t38_terminal_set_tep_mode(chain[i].node.t38_state, use_tep);
1259 break;
1260 case T38_TRANSPORT_TCP:
1261 case T38_TRANSPORT_TCP_TPKT:
1262 t38_terminal_set_fill_bit_removal(chain[i].node.t38_state, true);
1263 t38_terminal_set_config(chain[i].node.t38_state, T38_TERMINAL_OPTION_NO_PACING | T38_TERMINAL_OPTION_NO_INDICATORS);
1264 t38_terminal_set_tep_mode(chain[i].node.t38_state, false);
1265 break;
1266 }
1267 break;
1268 }
1269 }
1270
1271 for (i = 0; i < chain_elements; i++)
1272 {
1273 switch (chain[i].node_type)
1274 {
1275 case TSB85_AUDIO_FAX:
1276 case TSB85_T38_FAX:
1277 if (chain[chain[i].peer].node_type == AUDIO_FAX)
1278 chain[i].node.faxtester_state->far_fax = chain[chain[i].peer].node.fax_state;
1279 else
1280 chain[i].node.faxtester_state->far_t38 = chain[chain[i].peer].node.t38_state;
1281 chain[i].node.faxtester_state->far_t30 = chain[chain[i].peer].t30_state;
1282 chain[i].node.faxtester_state->far_tag = chain[i].peer + 'A';
1283
1284 while (faxtester_next_step(chain[i].node.faxtester_state) == 0)
1285 /*dummy loop*/;
1286 /*endwhile*/
1287 break;
1288 case REPLAY_AUDIO_FAX:
1289 break;
1290 case PASSTHROUGH:
1291 if (chain[i - 1].path.audio_in_buf == &chain[i].audio_buf[0])
1292 chain[i - 1].path.audio_in_buf = &chain[i + 1].audio_buf[0];
1293 if (chain[i + 1].path.audio_in_buf == &chain[i].audio_buf[0])
1294 chain[i + 1].path.audio_in_buf = &chain[i - 1].audio_buf[0];
1295 break;
1296 }
1297 }
1298
1299 switch (chain[chain_elements - 1].node_type)
1300 {
1301 case AUDIO_FAX:
1302 case T38_FAX:
1303 k = (use_polled_mode) ? (chain_elements - 1) : 0;
1304 if (chain[k].t30_state)
1305 t30_set_tx_file(chain[k].t30_state, input_tiff_file_name, start_page, end_page);
1306 break;
1307 }
1308 switch (chain[0].node_type)
1309 {
1310 case AUDIO_FAX:
1311 case T38_FAX:
1312 k = (use_polled_mode) ? 0 : (chain_elements - 1);
1313 if (chain[k].t30_state)
1314 t30_set_rx_file(chain[k].t30_state, output_tiff_file_name, -1);
1315 break;
1316 }
1317
1318 #if defined(ENABLE_GUI)
1319 if (use_gui)
1320 start_media_monitor();
1321 #endif
1322 hist_ptr = 0;
1323 for (;;)
1324 {
1325 memset(audio_log, 0, sizeof(audio_log));
1326
1327 for (i = 0; i < chain_elements; i++)
1328 {
1329 /* Update T.30 timing */
1330 switch (chain[i].node_type)
1331 {
1332 case AUDIO_FAX:
1333 /* Update timing */
1334 logging = t30_get_logging_state(chain[i].t30_state);
1335 span_log_bump_samples(logging, SAMPLES_PER_CHUNK);
1336 logging = fax_get_logging_state(chain[i].node.fax_state);
1337 span_log_bump_samples(logging, SAMPLES_PER_CHUNK);
1338 logging = fax_modems_get_logging_state(&chain[i].node.fax_state->modems);
1339 span_log_bump_samples(logging, SAMPLES_PER_CHUNK);
1340 #if 0
1341 /* Probe inside the modems to update their logs */
1342 span_log_bump_samples(chain[i].node.fax_state->modems.v27ter_rx.logging, len);
1343 span_log_bump_samples(chain[i].node.fax_state->modems.v29_rx.logging, len);
1344 span_log_bump_samples(chain[i].node.fax_state->modems.v17_rx.logging, len);
1345 #endif
1346
1347 #if 0
1348 /* Mute the signal */
1349 vec_zeroi16(chain[i].path.audio_in_buf->amp, SAMPLES_PER_CHUNK);
1350 chain[i].path.audio_in_buf->len = SAMPLES_PER_CHUNK;
1351 #endif
1352 if (log_audio)
1353 {
1354 k = (i == 0) ? 0 : 2;
1355 for (j = 0; j < chain[i].path.audio_in_buf->len; j++)
1356 audio_log[4*j + k] = chain[i].path.audio_in_buf->amp[j];
1357 }
1358 fax_rx(chain[i].node.fax_state, chain[i].path.audio_in_buf->amp, chain[i].path.audio_in_buf->len);
1359 if (!t30_call_active(chain[i].t30_state))
1360 {
1361 chain[i].completed = true;
1362 continue;
1363 }
1364
1365 chain[i].path.audio_out_buf->len = fax_tx(chain[i].node.fax_state, chain[i].path.audio_out_buf->amp, SAMPLES_PER_CHUNK);
1366 if (!use_transmit_on_idle)
1367 {
1368 /* The receive side always expects a full block of samples, but the
1369 transmit side may not be sending any when it doesn't need to. We
1370 may need to pad with some silence. */
1371 if (chain[i].path.audio_out_buf->len < SAMPLES_PER_CHUNK)
1372 {
1373 vec_zeroi16(&chain[i].path.audio_out_buf->amp[chain[i].path.audio_out_buf->len], SAMPLES_PER_CHUNK - chain[i].path.audio_out_buf->len);
1374 chain[i].path.audio_out_buf->len = SAMPLES_PER_CHUNK;
1375 }
1376 }
1377 if (chain[i].awgn_state)
1378 {
1379 for (j = 0; j < chain[i].path.audio_out_buf->len; j++)
1380 chain[i].path.audio_out_buf->amp[j] = ((int16_t) (chain[i].path.audio_out_buf->amp[j]*signal_scaling)) + awgn(chain[i].awgn_state);
1381 }
1382 if (log_audio)
1383 {
1384 k = (i == 0) ? 1 : 3;
1385 for (j = 0; j < chain[i].path.audio_out_buf->len; j++)
1386 audio_log[4*j + k] = chain[i].path.audio_out_buf->amp[j];
1387 }
1388 if (feedback_audio)
1389 {
1390 for (j = 0; j < chain[i].path.audio_out_buf->len; j++)
1391 chain[i].path.audio_out_buf->amp[j] += t38_amp_hist_a[hist_ptr][j] >> 1;
1392 memcpy(t38_amp_hist_a[hist_ptr], chain[i].path.audio_out_buf->amp, sizeof(int16_t)*SAMPLES_PER_CHUNK);
1393 }
1394 break;
1395 case T38_FAX:
1396 /* Update timing */
1397 logging = t30_get_logging_state(chain[i].t30_state);
1398 span_log_bump_samples(logging, SAMPLES_PER_CHUNK);
1399 logging = t38_terminal_get_logging_state(chain[i].node.t38_state);
1400 span_log_bump_samples(logging, SAMPLES_PER_CHUNK);
1401 logging = t38_core_get_logging_state(chain[i].t38_core_state);
1402 span_log_bump_samples(logging, SAMPLES_PER_CHUNK);
1403
1404 chain[i].completed = t38_terminal_send_timeout(chain[i].node.t38_state, SAMPLES_PER_CHUNK);
1405
1406 while ((msg_len = g1050_get(chain[i].path.g1050_path, msg, 1024, when, &seq_no, &tx_when, &rx_when)) >= 0)
1407 {
1408 #if defined(ENABLE_GUI)
1409 if (use_gui)
1410 media_monitor_rx(seq_no, tx_when, rx_when);
1411 #endif
1412 t38_core_rx_ifp_packet(chain[chain[i].t38_peer].t38_core_state, msg, msg_len, seq_no);
1413 }
1414 break;
1415 case TSB85_AUDIO_FAX:
1416 /* Update timing */
1417 logging = faxtester_get_logging_state(chain[i].node.faxtester_state);
1418 span_log_bump_samples(logging, SAMPLES_PER_CHUNK);
1419 #if 0
1420 /* Probe inside the modems to update their logs */
1421 span_log_bump_samples(&chain[i].node.faxtester_state->modems.v27ter_rx.logging, len);
1422 span_log_bump_samples(&chain[i].node.faxtester_state->modems.v29_rx.logging, len);
1423 span_log_bump_samples(&chain[i].node.faxtester_state->modems.v17_rx.logging, len);
1424 #endif
1425
1426 if (log_audio)
1427 {
1428 k = (i == 0) ? 0 : 2;
1429 for (j = 0; j < chain[i].path.audio_in_buf->len; j++)
1430 audio_log[4*j + k] = chain[i].path.audio_in_buf->amp[j];
1431 }
1432 faxtester_rx(chain[i].node.faxtester_state, chain[i].path.audio_in_buf->amp, chain[i].path.audio_in_buf->len);
1433 chain[i].path.audio_out_buf->len = faxtester_tx(chain[i].node.faxtester_state, chain[i].path.audio_out_buf->amp, SAMPLES_PER_CHUNK);
1434 if (chain[i].path.audio_out_buf->len == 0)
1435 break;
1436 if (log_audio)
1437 {
1438 k = (i == 0) ? 1 : 3;
1439 for (j = 0; j < chain[i].path.audio_out_buf->len; j++)
1440 audio_log[4*j + k] = chain[i].path.audio_out_buf->amp[j];
1441 }
1442 if (chain[i].node.faxtester_state->test_for_call_clear && !chain[i].node.faxtester_state->far_end_cleared_call)
1443 {
1444 chain[i].node.faxtester_state->call_clear_timer += chain[i].path.audio_out_buf->len;
1445 if (!t30_call_active(chain[i].node.faxtester_state->far_t30))
1446 {
1447 span_log(faxtester_get_logging_state(chain[i].node.faxtester_state),
1448 SPAN_LOG_FLOW,
1449 "Far end cleared after %dms (limits %dms to %dms)\n",
1450 chain[i].node.faxtester_state->call_clear_timer/8,
1451 chain[i].node.faxtester_state->timein_x,
1452 chain[i].node.faxtester_state->timeout);
1453 if (chain[i].node.faxtester_state->call_clear_timer/8 < chain[i].node.faxtester_state->timein_x || chain[i].node.faxtester_state->call_clear_timer/8 > chain[i].node.faxtester_state->timeout_x)
1454 {
1455 printf("Test failed\n");
1456 exit(2);
1457 }
1458 span_log(faxtester_get_logging_state(chain[i].node.faxtester_state), SPAN_LOG_FLOW, "Clear time OK\n");
1459 chain[i].node.faxtester_state->far_end_cleared_call = true;
1460 chain[i].node.faxtester_state->test_for_call_clear = false;
1461 while (faxtester_next_step(chain[i].node.faxtester_state) == 0)
1462 /*dummy loop*/;
1463 /*endwhile*/
1464 }
1465 /*endif*/
1466 }
1467 /*endif*/
1468 break;
1469 case REPLAY_AUDIO_FAX:
1470 chain[i].path.audio_out_buf->len = sf_readf_short(chain[i].node.wave_handle, chain[i].path.audio_out_buf->amp, SAMPLES_PER_CHUNK);
1471 if (chain[i].path.audio_out_buf->len == 0)
1472 break;
1473 break;
1474 case AUDIO_TO_T38_GATEWAY:
1475 /* Update timing */
1476 logging = t38_gateway_get_logging_state(chain[i].node.t38_gateway_state);
1477 span_log_bump_samples(logging, SAMPLES_PER_CHUNK);
1478 logging = t38_core_get_logging_state(chain[i].t38_core_state);
1479 span_log_bump_samples(logging, SAMPLES_PER_CHUNK);
1480 #if 0
1481 /* Probe inside the modems to update their logs */
1482 span_log_bump_samples(&chain[i].node.t38_gateway_state->modems.v27ter_rx.logging, len);
1483 span_log_bump_samples(&chain[i].node.t38_gateway_state->modems.v29_rx.logging, len);
1484 span_log_bump_samples(&chain[i].node.t38_gateway_state->modems.v17_rx.logging, len);
1485 #endif
1486
1487 if (drop_frame_rate && --drop_frame == 0)
1488 {
1489 drop_frame = drop_frame_rate;
1490 if (t38_gateway_rx_fillin(chain[i].node.t38_gateway_state, SAMPLES_PER_CHUNK))
1491 break;
1492 }
1493 else
1494 {
1495 if (t38_gateway_rx(chain[i].node.t38_gateway_state, chain[i].path.audio_in_buf->amp, chain[i].path.audio_in_buf->len))
1496 break;
1497 }
1498
1499 chain[i].path.audio_out_buf->len = t38_gateway_tx(chain[i].node.t38_gateway_state, chain[i].path.audio_out_buf->amp, SAMPLES_PER_CHUNK);
1500 if (!use_transmit_on_idle)
1501 {
1502 if (chain[i].path.audio_out_buf->len < SAMPLES_PER_CHUNK)
1503 {
1504 vec_zeroi16(&chain[i].path.audio_out_buf->amp[chain[i].path.audio_out_buf->len], SAMPLES_PER_CHUNK - chain[i].path.audio_out_buf->len);
1505 chain[i].path.audio_out_buf->len = SAMPLES_PER_CHUNK;
1506 }
1507 }
1508 if (feedback_audio)
1509 {
1510 for (j = 0; j < chain[i].path.audio_out_buf->len; j++)
1511 chain[i].path.audio_out_buf->amp[j] += t38_amp_hist_a[hist_ptr][j] >> 1;
1512 vec_movei16(t38_amp_hist_a[hist_ptr], chain[i].path.audio_out_buf->amp, SAMPLES_PER_CHUNK);
1513 }
1514
1515 #if 0
1516 if (log_audio)
1517 {
1518 k = (i == 0) ? 1 : 3;
1519 for (j = 0; j < chain[i].path.audio_out_buf->len; j++)
1520 audio_log[4*j + k] = chain[i].path.audio_out_buf->amp[j];
1521 }
1522 #endif
1523 while ((msg_len = g1050_get(chain[i].path.g1050_path, msg, 1024, when, &seq_no, &tx_when, &rx_when)) >= 0)
1524 {
1525 #if defined(ENABLE_GUI)
1526 if (use_gui)
1527 media_monitor_rx(seq_no, tx_when, rx_when);
1528 #endif
1529 t38_core_rx_ifp_packet(chain[chain[i].t38_peer].t38_core_state, msg, msg_len, seq_no);
1530 }
1531 break;
1532 }
1533 }
1534 if (log_audio)
1535 {
1536 outframes = sf_writef_short(wave_handle, audio_log, SAMPLES_PER_CHUNK);
1537 if (outframes != SAMPLES_PER_CHUNK)
1538 break;
1539 }
1540
1541 when += (float) SAMPLES_PER_CHUNK/(float) SAMPLE_RATE;
1542
1543 if (chain[0].completed && chain[chain_elements - 1].completed)
1544 break;
1545 #if defined(ENABLE_GUI)
1546 if (use_gui)
1547 media_monitor_update_display();
1548 #endif
1549 if (++hist_ptr > 3)
1550 hist_ptr = 0;
1551 }
1552
1553 for (i = 0; i < chain_elements; i++)
1554 {
1555 switch (chain[i].node_type)
1556 {
1557 case AUDIO_TO_T38_GATEWAY:
1558 t38_gateway_get_transfer_statistics(chain[i].node.t38_gateway_state, &t38_stats);
1559 printf("%c side exchanged %d pages at %dbps, in %s mode\n",
1560 i + 'A',
1561 t38_stats.pages_transferred,
1562 t38_stats.bit_rate,
1563 (t38_stats.error_correcting_mode) ? "ECM" : "non-ECM");
1564 break;
1565 }
1566 }
1567 if (log_audio)
1568 {
1569 if (sf_close_telephony(wave_handle))
1570 {
1571 fprintf(stderr, " Cannot close audio file '%s'\n", OUTPUT_WAVE_FILE_NAME);
1572 exit(2);
1573 }
1574 }
1575
1576 /* Check how many pages should have been transferred */
1577 expected_pages = get_tiff_total_pages(input_tiff_file_name);
1578 if (end_page >= 0 && expected_pages > end_page + 1)
1579 expected_pages = end_page + 1;
1580 if (start_page >= 0)
1581 expected_pages -= start_page;
1582 /* Check how many pages were transferred */
1583 for (j = 0; j < 2; j++)
1584 {
1585 i = (j == 0) ? 0 : (chain_elements - 1);
1586 if (!chain[i].phase_e_reached)
1587 break;
1588 if (!chain[i].succeeded)
1589 break;
1590
1591 t30_get_transfer_statistics(chain[i].t30_state, &t30_stats);
1592 if ((!use_polled_mode && i != 0) || (use_polled_mode && i == 0))
1593 {
1594 if (t30_stats.pages_tx != 0 || t30_stats.pages_rx != expected_pages)
1595 break;
1596 }
1597 else
1598 {
1599 if (t30_stats.pages_tx != expected_pages || t30_stats.pages_rx != 0)
1600 break;
1601 }
1602 }
1603 for (i = 0; i < chain_elements; i++)
1604 {
1605 switch (chain[i].node_type)
1606 {
1607 case AUDIO_FAX:
1608 fax_free(chain[i].node.fax_state);
1609 break;
1610 case T38_FAX:
1611 t38_terminal_free(chain[i].node.t38_state);
1612 break;
1613 case TSB85_AUDIO_FAX:
1614 case TSB85_T38_FAX:
1615 faxtester_free(chain[i].node.faxtester_state);
1616 break;
1617 case REPLAY_AUDIO_FAX:
1618 if (sf_close_telephony(chain[i].node.wave_handle))
1619 {
1620 fprintf(stderr, " Cannot close audio file '%s'\n", replay_file_name);
1621 exit(2);
1622 }
1623 chain[i].node.wave_handle = NULL;
1624 break;
1625 case AUDIO_TO_T38_GATEWAY:
1626 t38_gateway_free(chain[i].node.t38_gateway_state);
1627 break;
1628 }
1629 if (chain[i].path.g1050_path)
1630 {
1631 g1050_free(chain[i].path.g1050_path);
1632 chain[i].path.g1050_path = NULL;
1633 }
1634 }
1635 if (j < 2)
1636 {
1637 printf("Tests failed\n");
1638 exit(2);
1639 }
1640 t33_tests();
1641 printf("Tests passed\n");
1642 return 0;
1643 }
1644 /*- End of function --------------------------------------------------------*/
1645 /*- End of file ------------------------------------------------------------*/
1646