fax_tests.c 61 KB

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