Mercurial > hg > audiostuff
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 ------------------------------------------------------------*/ |
