int main(int argc, char *argv[]) { t38_core_state_t t38_core_a; t38_core_state_t t38_core_b; for (t38_version = 0; t38_version < 2; t38_version++) { printf("Using T.38 version %d\n", t38_version); if (t38_core_init(&t38_core_a, rx_indicator_handler, rx_data_handler, rx_missing_handler, &t38_core_b, tx_packet_handler, &t38_core_b) == NULL) { fprintf(stderr, "Cannot start the T.38 core\n"); exit(2); } if (t38_core_init(&t38_core_b, rx_indicator_handler, rx_data_handler, rx_missing_handler, &t38_core_a, tx_packet_handler, &t38_core_a) == NULL) { fprintf(stderr, "Cannot start the T.38 core\n"); exit(2); } t38_set_t38_version(&t38_core_a, t38_version); t38_set_t38_version(&t38_core_b, t38_version); span_log_set_level(&t38_core_a.logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG); span_log_set_tag(&t38_core_a.logging, "T.38-A"); span_log_set_level(&t38_core_b.logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG); span_log_set_tag(&t38_core_b.logging, "T.38-B"); if (encode_decode_tests(&t38_core_a, &t38_core_b)) { printf("Encode/decode tests failed\n"); exit(2); } if (attack_tests(&t38_core_a)) { printf("Attack tests failed\n"); exit(2); } } if (!succeeded) { printf("Tests failed\n"); exit(2); } printf("Tests passed\n"); return 0; }
static int encode_decode_tests(void) { char buf[100]; ademco_contactid_receiver_state_t *receiver; ademco_contactid_sender_state_t *sender; logging_state_t *logging; ademco_contactid_report_t result; int i; printf("Encode and decode tests\n"); if ((receiver = ademco_contactid_receiver_init(NULL, NULL, NULL)) == NULL) return 2; logging = ademco_contactid_receiver_get_logging_state(receiver); span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); span_log_set_tag(logging, "Ademco-rx"); if ((sender = ademco_contactid_sender_init(NULL, NULL, NULL)) == NULL) return 2; logging = ademco_contactid_sender_get_logging_state(sender); span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); span_log_set_tag(logging, "Ademco-tx"); for (i = 0; i < 5; i++) { if (encode_msg(buf, &reports[i]) < 0) { printf("Bad encode message\n"); return -1; } printf("'%s'\n", buf); if (decode_msg(&result, buf)) { printf("Bad decode message\n"); return -1; } ademco_contactid_receiver_log_msg(receiver, &result); printf("\n"); if (memcmp(&reports[i], &result, sizeof(result))) { printf("Received message does not match the one sent\n"); return -1; } } if (encode_msg(buf, &reports[5]) >= 0) { printf("Incorrectly good message\n"); return -1; } printf("'%s'\n", buf); printf("\n"); printf(" Passed\n"); return 0; }
int main(int argc, char *argv[]) { int i; int bit; int insert_caller_bit_errors; int insert_answerer_bit_errors; int opt; insert_caller_bit_errors = FALSE; insert_answerer_bit_errors = FALSE; variable_length = FALSE; while ((opt = getopt(argc, argv, "bv")) != -1) { switch (opt) { case 'b': insert_caller_bit_errors = 11000; insert_answerer_bit_errors = 10000; break; case 'v': variable_length = TRUE; break; default: //usage(); exit(2); break; } } v42_init(&caller, TRUE, TRUE, v42_get_frames, v42_put_frames, (void *) &caller); v42_init(&answerer, FALSE, TRUE, v42_get_frames, v42_put_frames, (void *) &answerer); v42_set_status_callback(&caller, v42_status, (void *) &caller); v42_set_status_callback(&answerer, v42_status, (void *) &answerer); v42_restart(&caller); v42_restart(&answerer); span_log_set_level(&caller.logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_DEBUG); span_log_set_tag(&caller.logging, "caller"); span_log_set_level(&answerer.logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_DEBUG); span_log_set_tag(&answerer.logging, "answerer"); for (i = 0; i < 1000000; i++) { bit = v42_tx_bit(&caller); if (insert_caller_bit_errors && i%insert_caller_bit_errors == 0) bit ^= 1; v42_rx_bit(&answerer, bit); bit = v42_tx_bit(&answerer); if (insert_answerer_bit_errors && i%insert_answerer_bit_errors == 0) bit ^= 1; v42_rx_bit(&caller, bit); } return 0; }
/* Setup SPAN logging according to Asterisk debug level */ static int set_logging(logging_state_t *state) { int level = SPAN_LOG_WARNING + option_debug; span_log_set_message_handler(state, span_message); span_log_set_level(state, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | level); return 0; }
int main(int argc, char *argv[]) { const char *xml_file_name; const char *test_name; logging_state_t *logging; int opt; #if 0 string_test(); #endif xml_file_name = "../spandsp/tsb85.xml"; test_name = "MRGN01"; log_audio = false; while ((opt = getopt(argc, argv, "lx:")) != -1) { switch (opt) { case 'l': log_audio = true; break; case 'x': xml_file_name = optarg; break; default: //usage(); exit(2); break; } } argc -= optind; argv += optind; if (argc > 0) test_name = argv[0]; if ((state = faxtester_init(NULL, xml_file_name, test_name)) == NULL) { fprintf(stderr, "Cannot start FAX tester instance\n"); printf("Test failed\n"); exit(2); } logging = faxtester_get_logging_state(state); span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME | SPAN_LOG_FLOW); span_log_set_tag(logging, "B"); /* We found the test we want, so run it. */ exchange(state); faxtester_free(state); printf("Done\n"); return 0; }
static int mitel_cm7291_side_2_and_bellcore_tests(void) { int j; SNDFILE *inhandle; int frames; ademco_contactid_sender_state_t *sender; logging_state_t *logging; if ((sender = ademco_contactid_sender_init(NULL, talkoff_tx_callback, NULL)) == NULL) return -1; logging = ademco_contactid_sender_get_logging_state(sender); span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); span_log_set_tag(logging, "Ademco-tx"); tx_callback_reported = FALSE; /* The remainder of the Mitel tape is the talk-off test */ /* Here we use the Bellcore test tapes (much tougher), in six files - 1 from each side of the original 3 cassette tapes */ /* Bellcore say you should get no more than 470 false detections with a good receiver. Dialogic claim 20. Of course, we can do better than that, eh? */ printf("Talk-off test\n"); for (j = 0; bellcore_files[j][0]; j++) { if ((inhandle = sf_open_telephony_read(bellcore_files[j], 1)) == NULL) { printf(" Cannot open speech file '%s'\n", bellcore_files[j]); return -1; } while ((frames = sf_readf_short(inhandle, amp, SAMPLE_RATE))) { ademco_contactid_sender_rx(sender, amp, frames); } if (sf_close_telephony(inhandle)) { printf(" Cannot close speech file '%s'\n", bellcore_files[j]); return -1; } printf(" File %d gave %d false hits.\n", j + 1, 0); } if (tx_callback_reported) { printf(" Failed\n"); return -1; } printf(" Passed\n"); return 0; }
static int t38_tests(int use_gui, int test_sending, int model_no, int speed_pattern_no) { t38_terminal_state_t *t38_state; int fast_send; int fast_send_tcf; int fast_blocks; uint8_t fast_buf[1000]; int msg_len; uint8_t msg[1024]; int t38_version; int without_pacing; int use_tep; int seq_no; double tx_when; double rx_when; t30_state_t *t30; t38_core_state_t *t38_core; logging_state_t *logging; int i; t38_version = 1; without_pacing = FALSE; use_tep = FALSE; srand48(0x1234567); if ((path_a_to_b = g1050_init(model_no, speed_pattern_no, 100, 33)) == NULL) { fprintf(stderr, "Failed to start IP network path model\n"); exit(2); } if ((path_b_to_a = g1050_init(model_no, speed_pattern_no, 100, 33)) == NULL) { fprintf(stderr, "Failed to start IP network path model\n"); exit(2); } if ((t31_state = t31_init(NULL, at_tx_handler, NULL, modem_call_control, NULL, t31_tx_packet_handler, NULL)) == NULL) { fprintf(stderr, " Cannot start the T.31 T.38 modem\n"); exit(2); } logging = t31_get_logging_state(t31_state); span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(logging, "T.31"); t38_core = t31_get_t38_core_state(t31_state); logging = t38_core_get_logging_state(t38_core); span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(logging, "T.31"); span_log_set_level(&t31_state->at_state.logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(&t31_state->at_state.logging, "T.31"); t31_set_mode(t31_state, TRUE); t38_set_t38_version(t38_core, t38_version); if (test_sending) { if ((t38_state = t38_terminal_init(NULL, FALSE, t38_tx_packet_handler, t31_state)) == NULL) { fprintf(stderr, "Cannot start the T.38 channel\n"); exit(2); } t30 = t38_terminal_get_t30_state(t38_state); t30_set_rx_file(t30, OUTPUT_FILE_NAME, -1); fax_test_seq = fax_send_test_seq; countdown = 0; } else { if ((t38_state = t38_terminal_init(NULL, TRUE, t38_tx_packet_handler, t31_state)) == NULL) { fprintf(stderr, "Cannot start the T.38 channel\n"); exit(2); } t30 = t38_terminal_get_t30_state(t38_state); t30_set_tx_file(t30, INPUT_FILE_NAME, -1, -1); fax_test_seq = fax_receive_test_seq; countdown = 250; } t30 = t38_terminal_get_t30_state(t38_state); t38_core = t38_terminal_get_t38_core_state(t38_state); t38_set_t38_version(t38_core, t38_version); t38_terminal_set_config(t38_state, without_pacing); t38_terminal_set_tep_mode(t38_state, use_tep); t30_set_tx_ident(t30, "11111111"); t30_set_supported_modems(t30, T30_SUPPORT_V27TER | T30_SUPPORT_V29 | T30_SUPPORT_V17); //t30_set_tx_nsf(t30, (const uint8_t *) "\x50\x00\x00\x00Spandsp\x00", 12); t30_set_phase_b_handler(t30, phase_b_handler, (void *) 'A'); t30_set_phase_d_handler(t30, phase_d_handler, (void *) 'A'); t30_set_phase_e_handler(t30, phase_e_handler, (void *) 'A'); logging = t38_terminal_get_logging_state(t38_state); span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(logging, "T.38"); t38_core = t38_terminal_get_t38_core_state(t38_state); span_log_set_level(&t38_core->logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(&t38_core->logging, "T.38"); logging = t30_get_logging_state(t30); span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(logging, "T.38"); fast_send = FALSE; fast_send_tcf = TRUE; fast_blocks = 0; kick = TRUE; #if defined(ENABLE_GUI) if (use_gui) start_media_monitor(); #endif while (!done) { logging = t38_terminal_get_logging_state(t38_state); span_log_bump_samples(logging, SAMPLES_PER_CHUNK); t38_core = t38_terminal_get_t38_core_state(t38_state); logging = t38_core_get_logging_state(t38_core); span_log_bump_samples(logging, SAMPLES_PER_CHUNK); t30 = t38_terminal_get_t30_state(t38_state); logging = t30_get_logging_state(t30); span_log_bump_samples(logging, SAMPLES_PER_CHUNK); logging = t31_get_logging_state(t31_state); span_log_bump_samples(logging, SAMPLES_PER_CHUNK); t38_core = t31_get_t38_core_state(t31_state); logging = t38_core_get_logging_state(t38_core); span_log_bump_samples(logging, SAMPLES_PER_CHUNK); span_log_bump_samples(&t31_state->at_state.logging, SAMPLES_PER_CHUNK); t38_terminal_send_timeout(t38_state, SAMPLES_PER_CHUNK); t31_t38_send_timeout(t31_state, SAMPLES_PER_CHUNK); when += (float) SAMPLES_PER_CHUNK/(float) SAMPLE_RATE; if (kick) { kick = FALSE; if (fax_test_seq[test_seq_ptr].command > (const char *) 2) { if (fax_test_seq[test_seq_ptr].command[0]) { printf("%s\n", fax_test_seq[test_seq_ptr].command); t31_at_rx(t31_state, fax_test_seq[test_seq_ptr].command, fax_test_seq[test_seq_ptr].len_command); } } else { if (fax_test_seq[test_seq_ptr].command == (const char *) 2) { printf("Fast send TCF\n"); fast_send = TRUE; fast_send_tcf = TRUE; fast_blocks = 100; } else { printf("Fast send image\n"); fast_send = TRUE; fast_send_tcf = FALSE; fast_blocks = 100; } } } if (fast_send) { /* Send fast modem data */ if (fast_send_tcf) { memset(fast_buf, 0, 36); } else { if (fast_blocks == 1) { /* Create the end of page condition */ for (i = 0; i < 36; i += 2) { fast_buf[i] = 0x00; fast_buf[i + 1] = 0x80; } } else { /* Create a chunk of white page */ for (i = 0; i < 36; i += 4) { fast_buf[i] = 0x00; fast_buf[i + 1] = 0x80; fast_buf[i + 2] = 0xB2; fast_buf[i + 3] = 0x01; } } } if (fast_blocks == 1) { /* Insert EOLs */ fast_buf[35] = ETX; fast_buf[34] = DLE; fast_buf[31] = fast_buf[28] = fast_buf[25] = fast_buf[22] = fast_buf[19] = fast_buf[16] = 1; } t31_at_rx(t31_state, (char *) fast_buf, 36); if (--fast_blocks == 0) fast_send = FALSE; } if (countdown) { if (answered) { countdown = 0; t31_call_event(t31_state, AT_CALL_EVENT_ANSWERED); } else if (--countdown == 0) { t31_call_event(t31_state, AT_CALL_EVENT_ALERTING); countdown = 250; } } while ((msg_len = g1050_get(path_a_to_b, msg, 1024, when, &seq_no, &tx_when, &rx_when)) >= 0) { #if defined(ENABLE_GUI) if (use_gui) media_monitor_rx(seq_no, tx_when, rx_when); #endif t38_core = t31_get_t38_core_state(t31_state); t38_core_rx_ifp_packet(t38_core, msg, msg_len, seq_no); } while ((msg_len = g1050_get(path_b_to_a, msg, 1024, when, &seq_no, &tx_when, &rx_when)) >= 0) { #if defined(ENABLE_GUI) if (use_gui) media_monitor_rx(seq_no, tx_when, rx_when); #endif t38_core = t38_terminal_get_t38_core_state(t38_state); t38_core_rx_ifp_packet(t38_core, msg, msg_len, seq_no); } #if defined(ENABLE_GUI) if (use_gui) media_monitor_update_display(); #endif } t38_terminal_release(t38_state); return 0; }
int main(int argc, char *argv[]) { int16_t amp[2][BLOCK_LEN]; int16_t model_amp[2][BLOCK_LEN]; int16_t out_amp[2*BLOCK_LEN]; SNDFILE *inhandle; SNDFILE *outhandle; int outframes; int samples; int samples2; int i; int j; int test_bps; int line_model_no; int bits_per_test; int noise_level; int signal_level; int channel_codec; int rbs_pattern; int guard_tone_option; int opt; bool log_audio; channel_codec = MUNGE_CODEC_NONE; rbs_pattern = 0; test_bps = 2400; line_model_no = 0; decode_test_file = NULL; noise_level = -70; signal_level = -13; bits_per_test = 50000; guard_tone_option = V22BIS_GUARD_TONE_1800HZ; log_audio = false; while ((opt = getopt(argc, argv, "b:B:c:d:gG:lm:n:r:s:")) != -1) { switch (opt) { case 'b': test_bps = atoi(optarg); if (test_bps != 2400 && test_bps != 1200) { fprintf(stderr, "Invalid bit rate specified\n"); exit(2); } break; case 'B': bits_per_test = atoi(optarg); break; case 'c': channel_codec = atoi(optarg); break; case 'd': decode_test_file = optarg; break; case 'g': #if defined(ENABLE_GUI) use_gui = true; #else fprintf(stderr, "Graphical monitoring not available\n"); exit(2); #endif break; case 'G': guard_tone_option = atoi(optarg); break; case 'l': log_audio = true; break; case 'm': line_model_no = atoi(optarg); break; case 'n': noise_level = atoi(optarg); break; case 'r': rbs_pattern = atoi(optarg); break; case 's': signal_level = atoi(optarg); break; default: //usage(); exit(2); break; } } inhandle = NULL; if (decode_test_file) { /* We will decode the audio from a file. */ if ((inhandle = sf_open_telephony_read(decode_test_file, 1)) == NULL) { fprintf(stderr, " Cannot open audio file '%s'\n", decode_test_file); exit(2); } } outhandle = NULL; if (log_audio) { if ((outhandle = sf_open_telephony_write(OUT_FILE_NAME, 2)) == NULL) { fprintf(stderr, " Cannot create audio file '%s'\n", OUT_FILE_NAME); exit(2); } } memset(endpoint, 0, sizeof(endpoint)); for (i = 0; i < 2; i++) { endpoint[i].v22bis = v22bis_init(NULL, test_bps, guard_tone_option, (i == 0), v22bis_getbit, &endpoint[i], v22bis_putbit, &endpoint[i]); v22bis_tx_power(endpoint[i].v22bis, signal_level); /* Move the carrier off a bit */ endpoint[i].v22bis->tx.carrier_phase_rate = dds_phase_ratef((i == 0) ? 1207.0f : 2407.0f); v22bis_rx_set_qam_report_handler(endpoint[i].v22bis, qam_report, (void *) &endpoint[i]); span_log_set_level(&endpoint[i].v22bis->logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME | SPAN_LOG_FLOW); span_log_set_tag(&endpoint[i].v22bis->logging, (i == 0) ? "caller" : "answerer"); endpoint[i].smooth_power = 0.0f; endpoint[i].symbol_no = 0; bert_init(&endpoint[i].bert_tx, bits_per_test, BERT_PATTERN_ITU_O152_11, test_bps, 20); bert_init(&endpoint[i].bert_rx, bits_per_test, BERT_PATTERN_ITU_O152_11, test_bps, 20); bert_set_report(&endpoint[i].bert_rx, 10000, reporter, &endpoint[i]); } #if defined(ENABLE_GUI) if (use_gui) { endpoint[0].qam_monitor = qam_monitor_init(6.0f, V22BIS_CONSTELLATION_SCALING_FACTOR, "Calling modem"); endpoint[1].qam_monitor = qam_monitor_init(6.0f, V22BIS_CONSTELLATION_SCALING_FACTOR, "Answering modem"); } #endif if ((model = both_ways_line_model_init(line_model_no, (float) noise_level, -15.0f, -15.0f, line_model_no, (float) noise_level, -15.0f, -15.0f, channel_codec, rbs_pattern)) == NULL) { fprintf(stderr, " Failed to create line model\n"); exit(2); } samples = 0; for (;;) { for (i = 0; i < 2; i++) { samples = v22bis_tx(endpoint[i].v22bis, amp[i], BLOCK_LEN); #if defined(ENABLE_GUI) if (use_gui) qam_monitor_update_audio_level(endpoint[i].qam_monitor, amp[i], samples); #endif if (samples == 0) { /* Note that we might get a few bad bits as the carrier shuts down. */ bert_result(&endpoint[i].bert_rx, &endpoint[i].latest_results); bert_init(&endpoint[i].bert_tx, bits_per_test, BERT_PATTERN_ITU_O152_11, test_bps, 20); bert_init(&endpoint[i].bert_rx, bits_per_test, BERT_PATTERN_ITU_O152_11, test_bps, 20); bert_set_report(&endpoint[i].bert_rx, 10000, reporter, &endpoint[i]); printf("Restarting on zero output\n"); v22bis_restart(endpoint[i].v22bis, test_bps); } } #if 1 both_ways_line_model(model, model_amp[0], amp[0], model_amp[1], amp[1], samples); #else vec_copyi16(model_amp[0], amp[0], samples); vec_copyi16(model_amp[1], amp[1], samples); #endif if (decode_test_file) { samples2 = sf_readf_short(inhandle, model_amp[0], samples); if (samples2 != samples) break; } for (i = 0; i < 2; i++) { span_log_bump_samples(&endpoint[i].v22bis->logging, samples); v22bis_rx(endpoint[i ^ 1].v22bis, model_amp[i], samples); for (j = 0; j < samples; j++) out_amp[2*j + i] = model_amp[i][j]; for ( ; j < BLOCK_LEN; j++) out_amp[2*j + i] = 0; } if (log_audio) { outframes = sf_writef_short(outhandle, out_amp, BLOCK_LEN); if (outframes != BLOCK_LEN) { fprintf(stderr, " Error writing audio file\n"); exit(2); } } } #if defined(ENABLE_GUI) if (use_gui) qam_wait_to_end(endpoint[0].qam_monitor); #endif if (decode_test_file) { if (sf_close_telephony(inhandle)) { fprintf(stderr, " Cannot close audio file '%s'\n", decode_test_file); exit(2); } } if (log_audio) { if (sf_close_telephony(outhandle)) { fprintf(stderr, " Cannot close audio file '%s'\n", OUT_FILE_NAME); exit(2); } } return 0; }
int main(int argc, char *argv[]) { fsk_rx_state_t *fsk; v17_rx_state_t *v17; v29_rx_state_t *v29; v27ter_rx_state_t *v27ter_4800; v27ter_rx_state_t *v27ter_2400; int16_t amp[SAMPLES_PER_CHUNK]; SNDFILE *inhandle; SF_INFO info; int len; const char *filename; logging_state_t *logging; filename = "fax_samp.wav"; if (argc > 1) filename = argv[1]; memset(&info, 0, sizeof(info)); if ((inhandle = sf_open(filename, SFM_READ, &info)) == NULL) { fprintf(stderr, " Cannot open audio file '%s' for reading\n", filename); exit(2); } if (info.samplerate != SAMPLE_RATE) { fprintf(stderr, " Unexpected sample rate in audio file '%s'\n", filename); exit(2); } if (info.channels != 1) { fprintf(stderr, " Unexpected number of channels in audio file '%s'\n", filename); exit(2); } memset(&t30_dummy, 0, sizeof(t30_dummy)); span_log_init(&t30_dummy.logging, SPAN_LOG_FLOW, NULL); span_log_set_protocol(&t30_dummy.logging, "T.30"); hdlc_rx_init(&hdlcrx, FALSE, TRUE, 5, hdlc_accept, NULL); fsk = fsk_rx_init(NULL, &preset_fsk_specs[FSK_V21CH2], FSK_FRAME_MODE_SYNC, v21_put_bit, NULL); v17 = v17_rx_init(NULL, 14400, v17_put_bit, NULL); v29 = v29_rx_init(NULL, 9600, v29_put_bit, NULL); //v29 = v29_rx_init(NULL, 7200, v29_put_bit, NULL); v27ter_4800 = v27ter_rx_init(NULL, 4800, v27ter_put_bit, NULL); v27ter_2400 = v27ter_rx_init(NULL, 2400, v27ter_put_bit, NULL); fsk_rx_signal_cutoff(fsk, -45.5); v17_rx_signal_cutoff(v17, -45.5); v29_rx_signal_cutoff(v29, -45.5); v27ter_rx_signal_cutoff(v27ter_4800, -40.0); v27ter_rx_signal_cutoff(v27ter_2400, -40.0); #if 1 logging = v17_rx_get_logging_state(v17); span_log_init(logging, SPAN_LOG_FLOW, NULL); span_log_set_protocol(logging, "V.17"); span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_FLOW); logging = v29_rx_get_logging_state(v29); span_log_init(logging, SPAN_LOG_FLOW, NULL); span_log_set_protocol(logging, "V.29"); span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_FLOW); logging = v27ter_rx_get_logging_state(v27ter_4800); span_log_init(logging, SPAN_LOG_FLOW, NULL); span_log_set_protocol(logging, "V.27ter-4800"); span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_FLOW); logging = v27ter_rx_get_logging_state(v27ter_2400); span_log_init(logging, SPAN_LOG_FLOW, NULL); span_log_set_protocol(logging, "V.27ter-2400"); span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_FLOW); #endif if (t4_rx_init(&t4_rx_state, "fax_decode.tif", T4_COMPRESSION_ITU_T4_2D) == NULL) { fprintf(stderr, "Failed to init\n"); exit(0); } for (;;) { len = sf_readf_short(inhandle, amp, SAMPLES_PER_CHUNK); if (len < SAMPLES_PER_CHUNK) break; fsk_rx(fsk, amp, len); v17_rx(v17, amp, len); v29_rx(v29, amp, len); v27ter_rx(v27ter_4800, amp, len); v27ter_rx(v27ter_2400, amp, len); } t4_rx_release(&t4_rx_state); if (sf_close(inhandle)) { fprintf(stderr, " Cannot close audio file '%s'\n", filename); exit(2); } return 0; }
int main(int argc, char *argv[]) { int16_t silence[SAMPLES_PER_CHUNK]; int16_t t30_amp[2][SAMPLES_PER_CHUNK]; int16_t t38_amp[2][SAMPLES_PER_CHUNK]; int16_t t38_amp_hist_a[8][SAMPLES_PER_CHUNK]; int16_t t38_amp_hist_b[8][SAMPLES_PER_CHUNK]; int16_t out_amp[SAMPLES_PER_CHUNK*4]; int16_t *fax_rx_buf[2]; int16_t *fax_tx_buf[2]; int16_t *t38_gateway_rx_buf[2]; int16_t *t38_gateway_tx_buf[2]; int t30_len[2]; int t38_len[2]; int hist_ptr; int log_audio; int msg_len; uint8_t msg[1024]; int outframes; SNDFILE *wave_handle; SNDFILE *input_wave_handle; int use_ecm; int use_tep; int feedback_audio; int use_transmit_on_idle; int t38_version; const char *input_tiff_file_name; const char *decode_file_name; int i; int j; int seq_no; int g1050_model_no; int g1050_speed_pattern_no; int t38_transport; double tx_when; double rx_when; int supported_modems; int remove_fill_bits; int opt; int start_page; int end_page; int drop_frame; int drop_frame_rate; float signal_scaling; int signal_level; int noise_level; int code_to_look_up; int scan_line_time; t38_stats_t t38_stats; t30_stats_t t30_stats; logging_state_t *logging; int expected_pages; char *page_header_info; char *page_header_tz; const char *tag; char buf[132 + 1]; #if defined(ENABLE_GUI) int use_gui; #endif #if defined(ENABLE_GUI) use_gui = FALSE; #endif log_audio = FALSE; use_ecm = FALSE; t38_version = 1; input_tiff_file_name = INPUT_TIFF_FILE_NAME; t38_simulate_incrementing_repeats = FALSE; g1050_model_no = 0; g1050_speed_pattern_no = 1; remove_fill_bits = FALSE; use_tep = FALSE; feedback_audio = FALSE; use_transmit_on_idle = TRUE; supported_modems = T30_SUPPORT_V27TER | T30_SUPPORT_V29 | T30_SUPPORT_V17; page_header_info = NULL; page_header_tz = NULL; drop_frame = 0; drop_frame_rate = 0; start_page = -1; end_page = -1; signal_level = 0; noise_level = -99; scan_line_time = 0; decode_file_name = NULL; code_to_look_up = -1; t38_transport = T38_TRANSPORT_UDPTL; while ((opt = getopt(argc, argv, "c:d:D:efFgH:i:Ilm:M:n:p:s:tT:u:v:z:")) != -1) { switch (opt) { case 'c': code_to_look_up = atoi(optarg); break; case 'd': decode_file_name = optarg; break; case 'D': drop_frame_rate = drop_frame = atoi(optarg); break; case 'e': use_ecm = TRUE; break; case 'f': feedback_audio = TRUE; break; case 'F': remove_fill_bits = TRUE; break; case 'g': #if defined(ENABLE_GUI) use_gui = TRUE; #else fprintf(stderr, "Graphical monitoring not available\n"); exit(2); #endif break; case 'H': page_header_info = optarg; break; case 'i': input_tiff_file_name = optarg; break; case 'I': t38_simulate_incrementing_repeats = TRUE; break; case 'l': log_audio = TRUE; break; case 'm': supported_modems = atoi(optarg); break; case 'M': g1050_model_no = optarg[0] - 'A' + 1; break; case 'n': noise_level = atoi(optarg); break; case 'p': for (i = 0; i < 2; i++) { switch (optarg[i]) { case 'A': mode[i] = AUDIO_FAX; break; case 'G': mode[i] = T38_GATEWAY_FAX; break; case 'T': mode[i] = T38_TERMINAL_FAX; break; default: fprintf(stderr, "Unknown FAX path element %c\n", optarg[i]); exit(2); } } if ((mode[0] == AUDIO_FAX && mode[1] != AUDIO_FAX) || (mode[0] != AUDIO_FAX && mode[1] == AUDIO_FAX)) { fprintf(stderr, "Invalid FAX path %s\n", optarg); exit(2); } break; case 's': g1050_speed_pattern_no = atoi(optarg); break; #if 0 case 's': signal_level = atoi(optarg); break; #endif case 'S': scan_line_time = atoi(optarg); break; case 't': use_tep = TRUE; break; case 'T': start_page = 0; end_page = atoi(optarg); break; case 'u': if (strcasecmp(optarg, "udptl") == 0) t38_transport = T38_TRANSPORT_UDPTL; else if (strcasecmp(optarg, "rtp") == 0) t38_transport = T38_TRANSPORT_RTP; else if (strcasecmp(optarg, "tcp") == 0) t38_transport = T38_TRANSPORT_TCP; else if (strcasecmp(optarg, "tcp-tpkt") == 0) t38_transport = T38_TRANSPORT_TCP_TPKT; else { fprintf(stderr, "Unknown T.38 transport mode\n"); exit(2); } break; case 'v': t38_version = atoi(optarg); break; case 'z': page_header_tz = optarg; break; default: //usage(); exit(2); break; } } if (code_to_look_up >= 0) { printf("Result code %d is %s\n", code_to_look_up, t30_completion_code_to_str(code_to_look_up)); exit(0); } printf("Using T.38 version %d\n", t38_version); if (use_ecm) printf("Using ECM\n"); wave_handle = NULL; if (log_audio) { if ((wave_handle = sf_open_telephony_write(OUTPUT_WAVE_FILE_NAME, 4)) == NULL) { fprintf(stderr, " Cannot create audio file '%s'\n", OUTPUT_WAVE_FILE_NAME); exit(2); } } memset(silence, 0, sizeof(silence)); srand48(0x1234567); /* Set up the nodes */ input_wave_handle = NULL; if (mode[0] == T38_TERMINAL_FAX) { } else { if (decode_file_name) { if ((input_wave_handle = sf_open_telephony_read(decode_file_name, 1)) == NULL) { fprintf(stderr, " Cannot open audio file '%s'\n", decode_file_name); exit(2); } } } for (i = 0; i < 2; i++) { tag = (i == 0) ? "A" : "B"; memset(&expected_rx_info[i], 0, sizeof(expected_rx_info[i])); if (mode[i] == T38_TERMINAL_FAX) { if ((t38_state[i] = t38_terminal_init(NULL, (i == 0), tx_packet_handler, (void *) (intptr_t) i)) == NULL) { fprintf(stderr, "Cannot start the T.38 terminal instance\n"); exit(2); } t30_state[i] = t38_terminal_get_t30_state(t38_state[i]); t38_core_state[i] = t38_terminal_get_t38_core_state(t38_state[i]); logging = t38_terminal_get_logging_state(t38_state[i]); span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(logging, tag); logging = t38_core_get_logging_state(t38_core_state[i]); span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(logging, tag); logging = t30_get_logging_state(t30_state[i]); span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(logging, tag); } else { if ((fax_state[i] = fax_init(NULL, (i == 0))) == NULL) { fprintf(stderr, "Cannot start FAX instance\n"); exit(2); } t30_state[i] = fax_get_t30_state(fax_state[i]); logging = fax_get_logging_state(fax_state[i]); span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(logging, tag); logging = fax_modems_get_logging_state(&fax_state[i]->modems); span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(logging, tag); logging = t30_get_logging_state(t30_state[i]); span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(logging, tag); if (mode[i] == T38_GATEWAY_FAX) { if ((t38_gateway_state[i] = t38_gateway_init(NULL, tx_packet_handler, (void *) (intptr_t) i)) == NULL) { fprintf(stderr, "Cannot start the T.38 gateway instancel\n"); exit(2); } t38_core_state[i] = t38_gateway_get_t38_core_state(t38_gateway_state[i]); logging = t38_gateway_get_logging_state(t38_gateway_state[i]); span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(logging, tag); logging = fax_modems_get_logging_state(&t38_gateway_state[i]->audio.modems); span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(logging, tag); logging = t38_core_get_logging_state(t38_core_state[i]); span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(logging, tag); fax_rx_buf[i] = t38_amp[i]; fax_tx_buf[i] = t30_amp[i]; t38_gateway_rx_buf[i] = t30_amp[i]; t38_gateway_tx_buf[i] = t38_amp[i]; } else { fax_rx_buf[i] = t30_amp[i]; fax_tx_buf[i] = t30_amp[i ^ 1]; t38_gateway_rx_buf[i] = NULL; t38_gateway_tx_buf[i] = NULL; } awgn_state[i] = NULL; signal_scaling = 1.0f; if (noise_level > -99) { awgn_state[i] = awgn_init_dbm0(NULL, 1234567, noise_level); signal_scaling = powf(10.0f, signal_level/20.0f); printf("Signal scaling %f\n", signal_scaling); } } set_t30_callbacks(t30_state[i], i); } /* Set up the channels */ for (i = 0; i < 2; i++) { if ((g1050_path[i] = g1050_init(g1050_model_no, g1050_speed_pattern_no, 100, 33)) == NULL) { fprintf(stderr, "Failed to start IP network path model\n"); exit(2); } memset(audio_buffer[2*i], 0, SAMPLES_PER_CHUNK*sizeof(int16_t)); memset(audio_buffer[2*i + 1], 0, SAMPLES_PER_CHUNK*sizeof(int16_t)); memset(t30_amp[i], 0, sizeof(t30_amp[i])); memset(t38_amp[i], 0, sizeof(t38_amp[i])); } memset(t38_amp_hist_a, 0, sizeof(t38_amp_hist_a)); memset(t38_amp_hist_b, 0, sizeof(t38_amp_hist_b)); for (i = 0; i < 2; i++) { j = i + 1; sprintf(buf, "%d%d%d%d%d%d%d%d", j, j, j, j, j, j, j, j); t30_set_tx_ident(t30_state[i], buf); strcpy(expected_rx_info[i ^ 1].ident, buf); sprintf(buf, "Sub-address %d", j); t30_set_tx_sub_address(t30_state[i], buf); //strcpy(expected_rx_info[i ^ 1].sub_address, buf); sprintf(buf, "Sender ID %d", j); t30_set_tx_sender_ident(t30_state[i], buf); //strcpy(expected_rx_info[i ^ 1].sender_ident, buf); sprintf(buf, "Password %d", j); t30_set_tx_password(t30_state[i], buf); //strcpy(expected_rx_info[i ^ 1].password, buf); sprintf(buf, "Polled sub-add %d", j); t30_set_tx_polled_sub_address(t30_state[i], buf); //strcpy(expected_rx_info[i ^ 1].polled_sub_address, buf); sprintf(buf, "Select poll add %d", j); t30_set_tx_selective_polling_address(t30_state[i], buf); //strcpy(expected_rx_info[i ^ 1].selective_polling_address, buf); t30_set_tx_page_header_info(t30_state[i], page_header_info); if (page_header_tz) t30_set_tx_page_header_tz(t30_state[i], page_header_tz); if ((i & 1) == 1) { t30_set_tx_nsf(t30_state[i], (const uint8_t *) "\x50\x00\x00\x00Spandsp\x00", 12); expected_rx_info[i ^ 1].nsf = (uint8_t *) "\x50\x00\x00\x00Spandsp\x00"; expected_rx_info[i ^ 1].nsf_len = 12; } t30_set_supported_modems(t30_state[i], supported_modems); t30_set_supported_t30_features(t30_state[i], T30_SUPPORT_IDENTIFICATION | T30_SUPPORT_SELECTIVE_POLLING | T30_SUPPORT_SUB_ADDRESSING); t30_set_supported_image_sizes(t30_state[i], T30_SUPPORT_US_LETTER_LENGTH | T30_SUPPORT_US_LEGAL_LENGTH | T30_SUPPORT_UNLIMITED_LENGTH | T30_SUPPORT_215MM_WIDTH | T30_SUPPORT_255MM_WIDTH | T30_SUPPORT_303MM_WIDTH); t30_set_supported_resolutions(t30_state[i], T30_SUPPORT_STANDARD_RESOLUTION | T30_SUPPORT_FINE_RESOLUTION | T30_SUPPORT_SUPERFINE_RESOLUTION | T30_SUPPORT_R8_RESOLUTION | T30_SUPPORT_R16_RESOLUTION | T30_SUPPORT_300_300_RESOLUTION | T30_SUPPORT_400_400_RESOLUTION | T30_SUPPORT_600_600_RESOLUTION | T30_SUPPORT_1200_1200_RESOLUTION | T30_SUPPORT_300_600_RESOLUTION | T30_SUPPORT_400_800_RESOLUTION | T30_SUPPORT_600_1200_RESOLUTION); t30_set_ecm_capability(t30_state[i], use_ecm); if (use_ecm) { t30_set_supported_compressions(t30_state[i], T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION | T30_SUPPORT_T6_COMPRESSION | T30_SUPPORT_T81_COMPRESSION | T30_SUPPORT_T85_COMPRESSION | T30_SUPPORT_T85_L0_COMPRESSION); } else { t30_set_supported_compressions(t30_state[i], T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION); } t30_set_minimum_scan_line_time(t30_state[i], scan_line_time); if (mode[i] == T38_GATEWAY_FAX) { t38_gateway_set_transmit_on_idle(t38_gateway_state[i], use_transmit_on_idle); t38_gateway_set_supported_modems(t38_gateway_state[i], supported_modems); //t38_gateway_set_nsx_suppression(t38_state[i], NULL, 0, NULL, 0); t38_gateway_set_fill_bit_removal(t38_gateway_state[i], remove_fill_bits); t38_gateway_set_real_time_frame_handler(t38_gateway_state[i], real_time_gateway_frame_handler, (void *) (intptr_t) i); t38_gateway_set_ecm_capability(t38_gateway_state[i], use_ecm); } if (mode[i] != AUDIO_FAX) { t38_set_t38_version(t38_core_state[i], t38_version); } if (mode[i] == T38_TERMINAL_FAX) { //t30_set_iaf_mode(t30_state[i], T30_IAF_MODE_NO_FILL_BITS); switch (t38_transport) { case T38_TRANSPORT_UDPTL: case T38_TRANSPORT_RTP: t38_terminal_set_fill_bit_removal(t38_state[i], remove_fill_bits); t38_terminal_set_tep_mode(t38_state[i], use_tep); break; case T38_TRANSPORT_TCP: case T38_TRANSPORT_TCP_TPKT: t38_terminal_set_fill_bit_removal(t38_state[i], TRUE); t38_terminal_set_config(t38_state[i], T38_TERMINAL_OPTION_NO_PACING | T38_TERMINAL_OPTION_NO_INDICATORS); t38_terminal_set_tep_mode(t38_state[i], FALSE); break; } } else { fax_set_transmit_on_idle(fax_state[i], use_transmit_on_idle); fax_set_tep_mode(fax_state[i], use_tep); } } t30_set_tx_file(t30_state[0], input_tiff_file_name, start_page, end_page); t30_set_rx_file(t30_state[1], OUTPUT_TIFF_FILE_NAME, -1); #if defined(ENABLE_GUI) if (use_gui) start_media_monitor(); #endif hist_ptr = 0; for (;;) { memset(out_amp, 0, sizeof(out_amp)); for (i = 0; i < 2; i++) { /* Update T.30 timing */ logging = t30_get_logging_state(t30_state[i]); span_log_bump_samples(logging, SAMPLES_PER_CHUNK); if (mode[i] == T38_TERMINAL_FAX) { /* Update T.38 termination timing */ logging = t38_terminal_get_logging_state(t38_state[i]); span_log_bump_samples(logging, SAMPLES_PER_CHUNK); logging = t38_core_get_logging_state(t38_core_state[i]); span_log_bump_samples(logging, SAMPLES_PER_CHUNK); completed[i] = t38_terminal_send_timeout(t38_state[i], SAMPLES_PER_CHUNK); } else { /* Update audio FAX timing */ logging = fax_get_logging_state(fax_state[i]); span_log_bump_samples(logging, SAMPLES_PER_CHUNK); fax_rx(fax_state[i], fax_rx_buf[i], SAMPLES_PER_CHUNK); if (!t30_call_active(t30_state[i])) { completed[i] = TRUE; continue; } if (i == 0 && input_wave_handle) { t30_len[i] = sf_readf_short(input_wave_handle, fax_tx_buf[i], SAMPLES_PER_CHUNK); if (t30_len[i] == 0) break; } else { t30_len[i] = fax_tx(fax_state[i], fax_tx_buf[i], SAMPLES_PER_CHUNK); if (!use_transmit_on_idle) { /* The receive side always expects a full block of samples, but the transmit side may not be sending any when it doesn't need to. We may need to pad with some silence. */ if (t30_len[i] < SAMPLES_PER_CHUNK) { memset(t30_amp[i] + t30_len[i], 0, sizeof(int16_t)*(SAMPLES_PER_CHUNK - t30_len[i])); t30_len[i] = SAMPLES_PER_CHUNK; } } if (awgn_state[i]) { for (j = 0; j < t30_len[i]; j++) fax_tx_buf[i][j] = ((int16_t) (fax_tx_buf[i][j]*signal_scaling)) + awgn(awgn_state[i]); } } if (log_audio) { for (j = 0; j < t30_len[i]; j++) out_amp[4*j + 2*i] = t30_amp[i][j]; } if (feedback_audio) { for (j = 0; j < t30_len[i]; j++) t30_amp[i][j] += t38_amp_hist_a[hist_ptr][j] >> 1; memcpy(t38_amp_hist_a[hist_ptr], t38_amp[i], sizeof(int16_t)*SAMPLES_PER_CHUNK); } if (mode[i] == T38_GATEWAY_FAX) { /* Update T.38 gateway timing */ logging = t38_gateway_get_logging_state(t38_gateway_state[i]); span_log_bump_samples(logging, SAMPLES_PER_CHUNK); logging = t38_core_get_logging_state(t38_core_state[i]); span_log_bump_samples(logging, SAMPLES_PER_CHUNK); if (drop_frame_rate && --drop_frame == 0) { drop_frame = drop_frame_rate; if (t38_gateway_rx_fillin(t38_gateway_state[i], SAMPLES_PER_CHUNK)) break; } else { if (t38_gateway_rx(t38_gateway_state[i], t38_gateway_rx_buf[i], SAMPLES_PER_CHUNK)) break; } t38_len[i] = t38_gateway_tx(t38_gateway_state[i], t38_gateway_tx_buf[i], SAMPLES_PER_CHUNK); if (!use_transmit_on_idle) { if (t38_len[i] < SAMPLES_PER_CHUNK) { memset(t38_amp[i] + t38_len[i], 0, sizeof(int16_t)*(SAMPLES_PER_CHUNK - t38_len[i])); t38_len[i] = SAMPLES_PER_CHUNK; } } if (feedback_audio) { for (j = 0; j < t30_len[i]; j++) t30_amp[i][j] += t38_amp_hist_a[hist_ptr][j] >> 1; memcpy(t38_amp_hist_a[hist_ptr], t38_amp[i], sizeof(int16_t)*SAMPLES_PER_CHUNK); } if (log_audio) { for (j = 0; j < t38_len[i]; j++) out_amp[4*j + 2*i + 1] = t38_amp[i][j]; } } } if (mode[i] != AUDIO_FAX) { while ((msg_len = g1050_get(g1050_path[i], msg, 1024, when, &seq_no, &tx_when, &rx_when)) >= 0) { #if defined(ENABLE_GUI) if (use_gui) media_monitor_rx(seq_no, tx_when, rx_when); #endif t38_core_rx_ifp_packet(t38_core_state[i ^ 1], msg, msg_len, seq_no); } } } if (log_audio) { outframes = sf_writef_short(wave_handle, out_amp, SAMPLES_PER_CHUNK); if (outframes != SAMPLES_PER_CHUNK) break; } when += (float) SAMPLES_PER_CHUNK/(float) SAMPLE_RATE; if (completed[0] && completed[1]) break; #if defined(ENABLE_GUI) if (use_gui) media_monitor_update_display(); #endif if (++hist_ptr > 3) hist_ptr = 0; }
int main(int argc, char *argv[]) { int16_t amp[SAMPLES_PER_CHUNK]; int samples; int caller_available_modulations; int answerer_available_modulations; SNDFILE *inhandle; SNDFILE *outhandle; int opt; int log_audio; char *decode_test_file; v8_state_t *v8_caller; v8_state_t *v8_answerer; v8_parms_t v8_call_parms; v8_parms_t v8_answer_parms; logging_state_t *logging; decode_test_file = NULL; log_audio = false; while ((opt = getopt(argc, argv, "d:l")) != -1) { switch (opt) { case 'd': decode_test_file = optarg; break; case 'l': log_audio = true; break; default: //usage(); exit(2); break; } } if (decode_test_file) { caller_available_modulations = V8_MOD_V17 | V8_MOD_V21 | V8_MOD_V22 | V8_MOD_V23HDX | V8_MOD_V23 | V8_MOD_V26BIS | V8_MOD_V26TER | V8_MOD_V27TER | V8_MOD_V29 | V8_MOD_V32 | V8_MOD_V34HDX | V8_MOD_V34 | V8_MOD_V90 | V8_MOD_V92; answerer_available_modulations = V8_MOD_V17 | V8_MOD_V21 | V8_MOD_V22 | V8_MOD_V23HDX | V8_MOD_V23 | V8_MOD_V26BIS | V8_MOD_V26TER | V8_MOD_V27TER | V8_MOD_V29 | V8_MOD_V32 | V8_MOD_V34HDX | V8_MOD_V34 | V8_MOD_V90 | V8_MOD_V92; printf("Decode file '%s'\n", decode_test_file); v8_call_parms.modem_connect_tone = MODEM_CONNECT_TONES_NONE; v8_call_parms.send_ci = true; v8_call_parms.v92 = -1; v8_call_parms.call_function = V8_CALL_V_SERIES; v8_call_parms.modulations = caller_available_modulations; v8_call_parms.protocol = V8_PROTOCOL_LAPM_V42; v8_call_parms.pcm_modem_availability = 0; v8_call_parms.pstn_access = 0; v8_call_parms.nsf = -1; v8_call_parms.t66 = -1; v8_caller = v8_init(NULL, true, &v8_call_parms, handler, (void *) "caller"); logging = v8_get_logging_state(v8_caller); span_log_set_level(logging, SPAN_LOG_FLOW | SPAN_LOG_SHOW_TAG); span_log_set_tag(logging, "caller"); v8_answer_parms.modem_connect_tone = MODEM_CONNECT_TONES_ANSAM_PR; v8_answer_parms.send_ci = true; v8_answer_parms.v92 = -1; v8_answer_parms.call_function = V8_CALL_V_SERIES; v8_answer_parms.modulations = answerer_available_modulations; v8_answer_parms.protocol = V8_PROTOCOL_LAPM_V42; v8_answer_parms.pcm_modem_availability = 0; v8_answer_parms.pstn_access = 0; v8_answer_parms.nsf = -1; v8_answer_parms.t66 = -1; v8_answerer = v8_init(NULL, false, &v8_answer_parms, handler, (void *) "answerer"); logging = v8_get_logging_state(v8_answerer); span_log_set_level(logging, SPAN_LOG_FLOW | SPAN_LOG_SHOW_TAG); span_log_set_tag(logging, "answerer"); if ((inhandle = sf_open_telephony_read(decode_test_file, 1)) == NULL) { fprintf(stderr, " Cannot open speech file '%s'\n", decode_test_file); exit (2); } /*endif*/ while ((samples = sf_readf_short(inhandle, amp, SAMPLES_PER_CHUNK))) { v8_rx(v8_caller, amp, samples); v8_rx(v8_answerer, amp, samples); v8_tx(v8_caller, amp, samples); v8_tx(v8_answerer, amp, samples); } /*endwhile*/ v8_free(v8_caller); v8_free(v8_answerer); if (sf_close_telephony(inhandle)) { fprintf(stderr, " Cannot close speech file '%s'\n", decode_test_file); exit(2); } /*endif*/ } else { outhandle = NULL; if (log_audio) { if ((outhandle = sf_open_telephony_write(OUTPUT_FILE_NAME, 2)) == NULL) { fprintf(stderr, " Cannot create audio file '%s'\n", OUTPUT_FILE_NAME); exit(2); } /*endif*/ } /*endif*/ printf("Test 1: V.8 terminal calls V.8 terminal\n"); v8_calls_v8_tests(outhandle); printf("Test 2: non-V.8 terminal calls V.8 terminal\n"); non_v8_calls_v8_tests(outhandle); printf("Test 3: V.8 terminal calls non-V.8 terminal\n"); v8_calls_non_v8_tests(outhandle); if (outhandle) { if (sf_close_telephony(outhandle)) { fprintf(stderr, " Cannot close audio file '%s'\n", OUTPUT_FILE_NAME); exit(2); } /*endif*/ } /*endif*/ printf("Tests passed.\n"); } return 0; }
int main(int argc, char *argv[]) { v27ter_rx_state_t rx; v27ter_tx_state_t tx; bert_results_t bert_results; int16_t gen_amp[BLOCK_LEN]; int16_t amp[BLOCK_LEN]; AFfilehandle inhandle; AFfilehandle outhandle; AFfilesetup filesetup; int outframes; int samples; int tep; int test_bps; int noise_level; int signal_level; int bits_per_test; int line_model_no; int block; int log_audio; int channel_codec; int rbs_pattern; float x; int opt; channel_codec = MUNGE_CODEC_NONE; rbs_pattern = 0; test_bps = 4800; tep = FALSE; line_model_no = 0; decode_test_file = NULL; use_gui = FALSE; noise_level = -70; signal_level = -13; bits_per_test = 50000; log_audio = FALSE; while ((opt = getopt(argc, argv, "b:c:d:glm:n:r:s:t")) != -1) { switch (opt) { case 'b': bits_per_test = atoi(optarg); break; case 'c': channel_codec = atoi(optarg); break; case 'd': decode_test_file = optarg; break; case 'g': #if defined(ENABLE_GUI) use_gui = TRUE; #else fprintf(stderr, "Graphical monitoring not available\n"); exit(2); #endif break; case 'l': log_audio = TRUE; break; case 'm': line_model_no = atoi(optarg); break; case 'n': noise_level = atoi(optarg); break; case 'r': rbs_pattern = atoi(optarg); break; case 's': signal_level = atoi(optarg); break; case 't': tep = TRUE; break; default: //usage(); exit(2); break; } } argc -= optind; argv += optind; if (argc > 0) { if (strcmp(argv[0], "4800") == 0) test_bps = 4800; else if (strcmp(argv[0], "2400") == 0) test_bps = 2400; else { fprintf(stderr, "Invalid bit rate\n"); exit(2); } } inhandle = NULL; outhandle = NULL; filesetup = AF_NULL_FILESETUP; if (log_audio) { if ((filesetup = afNewFileSetup()) == AF_NULL_FILESETUP) { fprintf(stderr, " Failed to create file setup\n"); exit(2); } afInitSampleFormat(filesetup, AF_DEFAULT_TRACK, AF_SAMPFMT_TWOSCOMP, 16); afInitRate(filesetup, AF_DEFAULT_TRACK, (float) SAMPLE_RATE); afInitFileFormat(filesetup, AF_FILE_WAVE); afInitChannels(filesetup, AF_DEFAULT_TRACK, 1); if ((outhandle = afOpenFile(OUT_FILE_NAME, "w", filesetup)) == AF_NULL_FILEHANDLE) { fprintf(stderr, " Cannot create wave file '%s'\n", OUT_FILE_NAME); exit(2); } } if (decode_test_file) { /* We will decode the audio from a wave file. */ if ((inhandle = afOpenFile(decode_test_file, "r", NULL)) == AF_NULL_FILEHANDLE) { fprintf(stderr, " Cannot open wave file '%s'\n", decode_test_file); exit(2); } if ((x = afGetFrameSize(inhandle, AF_DEFAULT_TRACK, 1)) != 2.0f) { printf(" Unexpected frame size in speech file '%s' (%f)\n", decode_test_file, x); exit(2); } if ((x = afGetRate(inhandle, AF_DEFAULT_TRACK)) != (float) SAMPLE_RATE) { printf(" Unexpected sample rate in speech file '%s' (%f)\n", decode_test_file, x); exit(2); } if ((x = afGetChannels(inhandle, AF_DEFAULT_TRACK)) != 1.0f) { printf(" Unexpected number of channels in speech file '%s' (%f)\n", decode_test_file, x); exit(2); } } else { /* We will generate V.27ter audio, and add some noise to it. */ v27ter_tx_init(&tx, test_bps, tep, v27tergetbit, NULL); v27ter_tx_power(&tx, signal_level); v27ter_tx_set_modem_status_handler(&tx, v27ter_tx_status, (void *) &tx); /* Move the carrier off a bit */ tx.carrier_phase_rate = dds_phase_ratef(1810.0f); bert_init(&bert, bits_per_test, BERT_PATTERN_ITU_O152_11, test_bps, 20); bert_set_report(&bert, 10000, reporter, NULL); if ((line_model = one_way_line_model_init(line_model_no, (float) noise_level, channel_codec, rbs_pattern)) == NULL) { fprintf(stderr, " Failed to create line model\n"); exit(2); } } v27ter_rx_init(&rx, test_bps, v27terputbit, NULL); v27ter_rx_set_modem_status_handler(&rx, v27ter_rx_status, (void *) &rx); v27ter_rx_set_qam_report_handler(&rx, qam_report, (void *) &rx); span_log_set_level(&rx.logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); span_log_set_tag(&rx.logging, "V.27ter-rx"); #if defined(ENABLE_GUI) if (use_gui) { qam_monitor = qam_monitor_init(2.0f, NULL); if (!decode_test_file) { start_line_model_monitor(129); line_model_monitor_line_model_update(line_model->near_filter, line_model->near_filter_len); } } #endif memset(&latest_results, 0, sizeof(latest_results)); for (block = 0; ; block++) { if (decode_test_file) { samples = afReadFrames(inhandle, AF_DEFAULT_TRACK, amp, BLOCK_LEN); #if defined(ENABLE_GUI) if (use_gui) qam_monitor_update_audio_level(qam_monitor, amp, samples); #endif if (samples == 0) break; } else { samples = v27ter_tx(&tx, gen_amp, BLOCK_LEN); #if defined(ENABLE_GUI) if (use_gui) qam_monitor_update_audio_level(qam_monitor, gen_amp, samples); #endif if (samples == 0) { printf("Restarting on zero output\n"); /* Push a little silence through, to ensure all the data bits get out of the buffers */ memset(amp, 0, BLOCK_LEN*sizeof(int16_t)); v27ter_rx(&rx, amp, BLOCK_LEN); v27ter_rx(&rx, amp, BLOCK_LEN); v27ter_rx(&rx, amp, BLOCK_LEN); /* Note that we might get a few bad bits as the carrier shuts down. */ bert_result(&bert, &bert_results); fprintf(stderr, "Final result %ddBm0, %d bits, %d bad bits, %d resyncs\n", signal_level, bert_results.total_bits, bert_results.bad_bits, bert_results.resyncs); fprintf(stderr, "Last report %ddBm0, %d bits, %d bad bits, %d resyncs\n", signal_level, latest_results.total_bits, latest_results.bad_bits, latest_results.resyncs); /* See if bit errors are appearing yet. Also check we are getting enough bits out of the receiver. The last regular report should be error free, though the final report will generally contain bits errors as the carrier was dying. The total number of bits out of the receiver should be at least the number we sent. Also, since BERT sync should have occurred rapidly at the start of transmission, the last report should have occurred at not much less than the total number of bits we sent. */ if (bert_results.total_bits < bits_per_test || latest_results.total_bits < bits_per_test - 100 || latest_results.bad_bits != 0) { break; } memset(&latest_results, 0, sizeof(latest_results)); signal_level--; v27ter_tx_restart(&tx, test_bps, tep); v27ter_tx_power(&tx, signal_level); v27ter_rx_restart(&rx, test_bps, FALSE); bert_init(&bert, bits_per_test, BERT_PATTERN_ITU_O152_11, test_bps, 20); bert_set_report(&bert, 10000, reporter, NULL); one_way_line_model_release(line_model); if ((line_model = one_way_line_model_init(line_model_no, (float) noise_level, channel_codec, 0)) == NULL) { fprintf(stderr, " Failed to create line model\n"); exit(2); } } if (log_audio) { outframes = afWriteFrames(outhandle, AF_DEFAULT_TRACK, gen_amp, samples); if (outframes != samples) { fprintf(stderr, " Error writing wave file\n"); exit(2); } } one_way_line_model(line_model, amp, gen_amp, samples); } #if defined(ENABLE_GUI) if (use_gui && !decode_test_file) line_model_monitor_line_spectrum_update(amp, samples); #endif v27ter_rx(&rx, amp, samples); if (decode_test_file == NULL && block%500 == 0) printf("Noise level is %d\n", noise_level); } if (!decode_test_file) { bert_result(&bert, &bert_results); fprintf(stderr, "At completion:\n"); fprintf(stderr, "Final result %ddBm0, %d bits, %d bad bits, %d resyncs\n", signal_level, bert_results.total_bits, bert_results.bad_bits, bert_results.resyncs); fprintf(stderr, "Last report %ddBm0, %d bits, %d bad bits, %d resyncs\n", signal_level, latest_results.total_bits, latest_results.bad_bits, latest_results.resyncs); one_way_line_model_release(line_model); if (signal_level > -43) { printf("Tests failed.\n"); exit(2); } printf("Tests passed.\n"); } #if defined(ENABLE_GUI) if (use_gui) qam_wait_to_end(qam_monitor); #endif if (log_audio) { if (afCloseFile(outhandle)) { fprintf(stderr, " Cannot close wave file '%s'\n", OUT_FILE_NAME); exit(2); } afFreeFileSetup(filesetup); } return 0; }
static int v8_calls_non_v8_tests(SNDFILE *outhandle) { v8_state_t *v8_caller; modem_connect_tones_tx_state_t *non_v8_answerer_tx; logging_state_t *caller_logging; int caller_available_modulations; int i; int samples; int outframes; int16_t amp[SAMPLES_PER_CHUNK]; int16_t out_amp[2*SAMPLES_PER_CHUNK]; v8_parms_t v8_call_parms; caller_available_modulations = V8_MOD_V17 | V8_MOD_V21 | V8_MOD_V22 | V8_MOD_V23HDX | V8_MOD_V23 | V8_MOD_V26BIS | V8_MOD_V26TER | V8_MOD_V27TER | V8_MOD_V29 | V8_MOD_V32 | V8_MOD_V34HDX | V8_MOD_V34 | V8_MOD_V90 | V8_MOD_V92; negotiations_ok = 0; v8_call_parms.modem_connect_tone = MODEM_CONNECT_TONES_NONE; v8_call_parms.send_ci = true; v8_call_parms.v92 = -1; v8_call_parms.call_function = V8_CALL_V_SERIES; v8_call_parms.modulations = caller_available_modulations; v8_call_parms.protocol = V8_PROTOCOL_LAPM_V42; v8_call_parms.pcm_modem_availability = 0; v8_call_parms.pstn_access = 0; v8_call_parms.nsf = -1; v8_call_parms.t66 = -1; v8_caller = v8_init(NULL, true, &v8_call_parms, handler, (void *) "caller"); non_v8_answerer_tx = modem_connect_tones_tx_init(NULL, MODEM_CONNECT_TONES_ANS_PR); caller_logging = v8_get_logging_state(v8_caller); span_log_set_level(caller_logging, SPAN_LOG_FLOW | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(caller_logging, "caller"); for (i = 0; i < 1000; i++) { samples = v8_tx(v8_caller, amp, SAMPLES_PER_CHUNK); if (samples < SAMPLES_PER_CHUNK) { vec_zeroi16(amp + samples, SAMPLES_PER_CHUNK - samples); samples = SAMPLES_PER_CHUNK; } /*endif*/ span_log_bump_samples(caller_logging, samples); for (i = 0; i < samples; i++) out_amp[2*i] = amp[i]; /*endfor*/ samples = modem_connect_tones_tx(non_v8_answerer_tx, amp, SAMPLES_PER_CHUNK); if (samples < SAMPLES_PER_CHUNK) { vec_zeroi16(amp + samples, SAMPLES_PER_CHUNK - samples); samples = SAMPLES_PER_CHUNK; } /*endif*/ if (v8_rx(v8_caller, amp, samples)) break; /*endif*/ for (i = 0; i < samples; i++) out_amp[2*i + 1] = amp[i]; /*endfor*/ if (outhandle) { outframes = sf_writef_short(outhandle, out_amp, samples); if (outframes != samples) { fprintf(stderr, " Error writing audio file\n"); exit(2); } /*endif*/ } /*endif*/ } /*endfor*/ v8_free(v8_caller); modem_connect_tones_tx_free(non_v8_answerer_tx); if (negotiations_ok != 42) { printf("Tests failed.\n"); exit(2); } /*endif*/ return 0; }
static int end_to_end_tests(void) { ademco_contactid_receiver_state_t *receiver; ademco_contactid_sender_state_t *sender; logging_state_t *logging; codec_munge_state_t *munge; awgn_state_t noise_source; int16_t amp[SAMPLES_PER_CHUNK]; int16_t sndfile_buf[2*SAMPLES_PER_CHUNK]; int samples; int i; int j; printf("End to end tests\n"); if ((outhandle = sf_open_telephony_write(OUTPUT_FILE_NAME, 2)) == NULL) { fprintf(stderr, " Cannot open audio file '%s'\n", OUTPUT_FILE_NAME); exit(2); } if ((receiver = ademco_contactid_receiver_init(NULL, rx_callback, NULL)) == NULL) return -1; ademco_contactid_receiver_set_realtime_callback(receiver, rx_callback, receiver); logging = ademco_contactid_receiver_get_logging_state(receiver); span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); span_log_set_tag(logging, "Ademco-rx"); if ((sender = ademco_contactid_sender_init(NULL, tx_callback, NULL)) == NULL) return -1; ademco_contactid_sender_set_realtime_callback(sender, tx_callback, sender); logging = ademco_contactid_sender_get_logging_state(sender); span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); span_log_set_tag(logging, "Ademco-tx"); awgn_init_dbm0(&noise_source, 1234567, -50); munge = codec_munge_init(MUNGE_CODEC_ALAW, 0); sending_complete = FALSE; rx_callback_reported = FALSE; for (i = 0; i < 1000; i++) { samples = ademco_contactid_sender_tx(sender, amp, SAMPLES_PER_CHUNK); for (j = samples; j < SAMPLES_PER_CHUNK; j++) amp[j] = 0; for (j = 0; j < SAMPLES_PER_CHUNK; j++) sndfile_buf[2*j] = amp[j]; /* There is no point in impairing this signal. It is just DTMF tones, which will work as wel as the DTMF detector beign used. */ ademco_contactid_receiver_rx(receiver, amp, SAMPLES_PER_CHUNK); samples = ademco_contactid_receiver_tx(receiver, amp, SAMPLES_PER_CHUNK); for (j = samples; j < SAMPLES_PER_CHUNK; j++) amp[j] = 0; /* We add AWGN and codec impairments to the signal, to stress the tone detector. */ codec_munge(munge, amp, SAMPLES_PER_CHUNK); for (j = 0; j < SAMPLES_PER_CHUNK; j++) { sndfile_buf[2*j + 1] = amp[j]; /* Add noise to the tones */ amp[j] += awgn(&noise_source); } codec_munge(munge, amp, SAMPLES_PER_CHUNK); ademco_contactid_sender_rx(sender, amp, SAMPLES_PER_CHUNK); sf_writef_short(outhandle, sndfile_buf, SAMPLES_PER_CHUNK); } if (!rx_callback_reported) { fprintf(stderr, " Report not received\n"); return -1; } if (sf_close_telephony(outhandle)) { fprintf(stderr, " Cannot close audio file '%s'\n", OUTPUT_FILE_NAME); return -1; } printf(" Passed\n"); return 0; }
int main(int argc, char *argv[]) { v17_rx_state_t *rx; v17_tx_state_t *tx; bert_results_t bert_results; int16_t gen_amp[BLOCK_LEN]; int16_t amp[BLOCK_LEN]; SNDFILE *inhandle; SNDFILE *outhandle; int outframes; int samples; int tep; int block_no; int noise_level; int signal_level; int bits_per_test; int line_model_no; int log_audio; int channel_codec; int rbs_pattern; int opt; logging_state_t *logging; channel_codec = MUNGE_CODEC_NONE; rbs_pattern = 0; test_bps = 14400; tep = FALSE; line_model_no = 0; decode_test_file = NULL; use_gui = FALSE; noise_level = -70; signal_level = -13; bits_per_test = 50000; log_audio = FALSE; while ((opt = getopt(argc, argv, "b:B:c:d:glm:n:r:s:t")) != -1) { switch (opt) { case 'b': test_bps = atoi(optarg); if (test_bps != 14400 && test_bps != 12000 && test_bps != 9600 && test_bps != 7200 && test_bps != 4800) { /* 4800 is an extension of V.17, to provide full coverage of the V.32bis modes */ fprintf(stderr, "Invalid bit rate specified\n"); exit(2); } break; case 'B': bits_per_test = atoi(optarg); break; case 'c': channel_codec = atoi(optarg); break; case 'd': decode_test_file = optarg; break; case 'g': #if defined(ENABLE_GUI) use_gui = TRUE; #else fprintf(stderr, "Graphical monitoring not available\n"); exit(2); #endif break; case 'l': log_audio = TRUE; break; case 'm': line_model_no = atoi(optarg); break; case 'n': noise_level = atoi(optarg); break; case 'r': rbs_pattern = atoi(optarg); break; case 's': signal_level = atoi(optarg); break; case 't': tep = TRUE; break; default: //usage(); exit(2); break; } } inhandle = NULL; outhandle = NULL; #if defined(HAVE_FENV_H) fpe_trap_setup(); #endif if (log_audio) { if ((outhandle = sf_open_telephony_write(OUT_FILE_NAME, 1)) == NULL) { fprintf(stderr, " Cannot create audio file '%s'\n", OUT_FILE_NAME); exit(2); } } if (decode_test_file) { /* We will decode the audio from a file. */ tx = NULL; if ((inhandle = sf_open_telephony_read(decode_test_file, 1)) == NULL) { fprintf(stderr, " Cannot open audio file '%s'\n", decode_test_file); exit(2); } } else { /* We will generate V.17 audio, and add some noise to it. */ tx = v17_tx_init(NULL, test_bps, tep, v17getbit, NULL); logging = v17_tx_get_logging_state(tx); span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); span_log_set_tag(logging, "V.17-tx"); v17_tx_power(tx, signal_level); v17_tx_set_modem_status_handler(tx, v17_tx_status, (void *) tx); #if defined(WITH_SPANDSP_INTERNALS) /* Move the carrier off a bit */ tx->carrier_phase_rate = dds_phase_ratef(1792.0f); tx->carrier_phase = 0x40000000; #endif bert_init(&bert, bits_per_test, BERT_PATTERN_ITU_O152_11, test_bps, 20); bert_set_report(&bert, 10000, reporter, NULL); if ((line_model = one_way_line_model_init(line_model_no, (float) noise_level, channel_codec, rbs_pattern)) == NULL) { fprintf(stderr, " Failed to create line model\n"); exit(2); } one_way_line_model_set_dc(line_model, 0.0f); #if defined(ADD_MAINS_INTERFERENCE) one_way_line_model_set_mains_pickup(line_model, 50, -40.0f); #endif } rx = v17_rx_init(NULL, test_bps, v17putbit, NULL); logging = v17_rx_get_logging_state(rx); span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); span_log_set_tag(logging, "V.17-rx"); v17_rx_set_modem_status_handler(rx, v17_rx_status, (void *) rx); v17_rx_set_qam_report_handler(rx, qam_report, (void *) rx); #if defined(ENABLE_GUI) if (use_gui) { qam_monitor = qam_monitor_init(10.0f, NULL); if (!decode_test_file) { start_line_model_monitor(129); line_model_monitor_line_model_update(line_model->near_filter, line_model->near_filter_len); } } #endif memset(&latest_results, 0, sizeof(latest_results)); for (block_no = 0; block_no < 100000000; block_no++) { if (decode_test_file) { samples = sf_readf_short(inhandle, amp, BLOCK_LEN); #if defined(ENABLE_GUI) if (use_gui) qam_monitor_update_audio_level(qam_monitor, amp, samples); #endif if (samples == 0) break; } else { samples = v17_tx(tx, gen_amp, BLOCK_LEN); #if defined(ENABLE_GUI) if (use_gui) qam_monitor_update_audio_level(qam_monitor, gen_amp, samples); #endif if (samples == 0) { printf("Restarting on zero output\n"); /* Push a little silence through, to ensure all the data bits get out of the buffers */ vec_zeroi16(amp, BLOCK_LEN); v17_rx(rx, amp, BLOCK_LEN); /* Note that we might get a few bad bits as the carrier shuts down. */ bert_result(&bert, &bert_results); fprintf(stderr, "Final result %ddBm0/%ddBm0, %d bits, %d bad bits, %d resyncs\n", signal_level, noise_level, bert_results.total_bits, bert_results.bad_bits, bert_results.resyncs); fprintf(stderr, "Last report %ddBm0/%ddBm0, %d bits, %d bad bits, %d resyncs\n", signal_level, noise_level, latest_results.total_bits, latest_results.bad_bits, latest_results.resyncs); /* See if bit errors are appearing yet. Also check we are getting enough bits out of the receiver. The last regular report should be error free, though the final report will generally contain bits errors as the carrier was dying. The total number of bits out of the receiver should be at least the number we sent. Also, since BERT sync should have occurred rapidly at the start of transmission, the last report should have occurred at not much less than the total number of bits we sent. */ if (bert_results.total_bits < bits_per_test || latest_results.total_bits < bits_per_test - 100 || latest_results.bad_bits != 0) { break; } memset(&latest_results, 0, sizeof(latest_results)); #if defined(WITH_SPANDSP_INTERNALS) signal_level--; /* Bump the receiver AGC gain by 1dB, to compensate for the above */ rx->agc_scaling_save *= 1.122f; #endif v17_tx_restart(tx, test_bps, tep, TRUE); v17_tx_power(tx, signal_level); v17_rx_restart(rx, test_bps, TRUE); //rx.eq_put_step = rand()%(192*10/3); bert_init(&bert, bits_per_test, BERT_PATTERN_ITU_O152_11, test_bps, 20); bert_set_report(&bert, 10000, reporter, NULL); one_way_line_model_release(line_model); if ((line_model = one_way_line_model_init(line_model_no, (float) noise_level, channel_codec, 0)) == NULL) { fprintf(stderr, " Failed to create line model\n"); exit(2); } } if (log_audio) { outframes = sf_writef_short(outhandle, gen_amp, samples); if (outframes != samples) { fprintf(stderr, " Error writing audio file\n"); exit(2); } } one_way_line_model(line_model, amp, gen_amp, samples); } #if defined(ENABLE_GUI) if (use_gui && !decode_test_file) line_model_monitor_line_spectrum_update(amp, samples); #endif v17_rx(rx, amp, samples); } if (!decode_test_file) { bert_result(&bert, &bert_results); fprintf(stderr, "At completion:\n"); fprintf(stderr, "Final result %ddBm0/%ddBm0, %d bits, %d bad bits, %d resyncs\n", signal_level, noise_level, bert_results.total_bits, bert_results.bad_bits, bert_results.resyncs); fprintf(stderr, "Last report %ddBm0/%ddBm0, %d bits, %d bad bits, %d resyncs\n", signal_level, noise_level, latest_results.total_bits, latest_results.bad_bits, latest_results.resyncs); one_way_line_model_release(line_model); if (signal_level > -43) { printf("Tests failed.\n"); exit(2); } printf("Tests passed.\n"); } #if defined(ENABLE_GUI) if (use_gui) qam_wait_to_end(qam_monitor); #endif if (decode_test_file) { if (sf_close_telephony(inhandle)) { fprintf(stderr, " Cannot close audio file '%s'\n", decode_test_file); exit(2); } } if (log_audio) { if (sf_close_telephony(outhandle)) { fprintf(stderr, " Cannot close audio file '%s'\n", OUT_FILE_NAME); exit(2); } } return 0; }
int main(int argc, char *argv[]) { logging_state_t *log; int i; uint8_t buf[1000]; struct timespec delay; /* Set up a logger */ if ((log = span_log_init(NULL, 123, "TAG")) == NULL) { fprintf(stderr, "Failed to initialise log.\n"); exit(2); } /* Try it */ span_log_set_level(log, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_FLOW); if (span_log(log, SPAN_LOG_FLOW, "Logging to fprintf, as simple as %d %d %d\n", 1, 2, 3)) fprintf(stderr, "Logged.\n"); else fprintf(stderr, "Not logged.\n"); /* Now set a custom log handler */ span_log_set_message_handler(log, &message_handler, NULL); span_log_set_sample_rate(log, 44100); /* Try the different logging elements */ span_log_set_level(log, SPAN_LOG_SHOW_TAG | SPAN_LOG_FLOW); if (span_log(log, SPAN_LOG_FLOW, "Log with tag %d %d %d\n", 1, 2, 3)) fprintf(stderr, "Logged.\n"); else fprintf(stderr, "Not logged.\n"); span_log_set_level(log, SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); if (span_log(log, SPAN_LOG_FLOW, "Log with protocol %d %d %d\n", 1, 2, 3)) fprintf(stderr, "Logged.\n"); else fprintf(stderr, "Not logged.\n"); span_log_set_level(log, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_FLOW); if (span_log(log, SPAN_LOG_ERROR, "Log with severity log %d %d %d\n", 1, 2, 3)) fprintf(stderr, "Logged.\n"); else fprintf(stderr, "Not logged.\n"); span_log_set_level(log, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_FLOW); span_log_set_tag(log, "NewTag"); if (span_log(log, SPAN_LOG_FLOW, "Log with new tag %d %d %d\n", 1, 2, 3)) fprintf(stderr, "Logged.\n"); else fprintf(stderr, "Not logged.\n"); span_log_set_protocol(log, "Protocol"); if (span_log(log, SPAN_LOG_FLOW, "Log with protocol %d %d %d\n", 1, 2, 3)) fprintf(stderr, "Logged.\n"); else fprintf(stderr, "Not logged.\n"); /* Test logging of buffer contents */ for (i = 0; i < 1000; i++) buf[i] = i; if (span_log_buf(log, SPAN_LOG_FLOW, "Buf", buf, 10)) fprintf(stderr, "Logged.\n"); else fprintf(stderr, "Not logged.\n"); if (span_log_buf(log, SPAN_LOG_FLOW, "Buf", buf, 1000)) fprintf(stderr, "Logged.\n"); else fprintf(stderr, "Not logged.\n"); /* Test the correct severities will be logged */ for (i = 0; i < 10; i++) { if (!span_log_test(log, i)) { if (i != 6) tests_failed = true; break; } } /* Check timestamping by samples */ span_log_set_level(log, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_FLOW | SPAN_LOG_SHOW_SAMPLE_TIME); for (i = 0; i < 10; i++) { span_log(log, SPAN_LOG_FLOW, "Time tagged log %d %d %d\n", 1, 2, 3); span_log_bump_samples(log, 441*2); } /* Check timestamping by current date and time */ span_log_set_message_handler(log, &message_handler2, NULL); span_log_set_level(log, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_FLOW | SPAN_LOG_SHOW_DATE); for (i = 0; i < 10; i++) { span_log(log, SPAN_LOG_FLOW, "Date/time tagged log %d %d %d\n", 1, 2, 3); delay.tv_sec = 0; delay.tv_nsec = 20000000; nanosleep(&delay, NULL); } if (tests_failed || !msg_done) { printf("Tests failed - %d %d.\n", tests_failed, msg_done); return 2; } span_log_set_message_handler(log, &message_handler, NULL); printf("Tests passed.\n"); return 0; }
static int fax_t38(struct cw_channel *chan, t38_terminal_state_t *t38, const char *file, int calling_party, int verbose) { char *x; struct cw_frame *inf = NULL; int ready = 1; int res = 0; uint64_t now; uint64_t passage; t30_state_t *t30; t38_core_state_t *t38_core; memset(t38, 0, sizeof(*t38)); if (t38_terminal_init(t38, calling_party, t38_tx_packet_handler, chan) == NULL) { cw_log(LOG_WARNING, "Unable to start T.38 termination.\n"); return -1; } t30 = t38_terminal_get_t30_state(t38); t38_core = t38_terminal_get_t38_core_state(t38); span_log_set_message_handler(&t38->logging, span_message); span_log_set_message_handler(&t30->logging, span_message); span_log_set_message_handler(&t38_core->logging, span_message); if (verbose) { span_log_set_level(&t38->logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); span_log_set_level(&t30->logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); span_log_set_level(&t38_core->logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); } fax_set_common(chan, t30, file, calling_party, verbose); passage = nowis(); t38_terminal_set_tep_mode(t38, TRUE); while (ready && ready_to_talk(chan)) { if (chan->t38_status != T38_NEGOTIATED) break; if ((res = cw_waitfor(chan, 20)) < 0) { ready = 0; break; } now = nowis(); t38_terminal_send_timeout(t38, (now - passage)/125); passage = now; /* End application when T38/T30 has finished */ if (!t30_call_active(t30)) break; if ((inf = cw_read(chan)) == NULL) { ready = 0; break; } if (inf->frametype == CW_FRAME_MODEM && inf->subclass == CW_MODEM_T38) t38_core_rx_ifp_packet(t38_core, inf->data, inf->datalen, inf->seq_no); cw_fr_free(inf); } return ready; }
int main(int argc, char *argv[]) { int16_t silence[SAMPLES_PER_CHUNK]; int16_t t30_amp_a[SAMPLES_PER_CHUNK]; int16_t t38_amp_a[SAMPLES_PER_CHUNK]; int16_t t38_amp_b[SAMPLES_PER_CHUNK]; int16_t t30_amp_b[SAMPLES_PER_CHUNK]; int16_t out_amp[SAMPLES_PER_CHUNK*4]; int t30_len_a; int t38_len_a; int t38_len_b; int t30_len_b; int log_audio; int msg_len; uint8_t msg[1024]; int outframes; AFfilesetup filesetup; AFfilehandle wave_handle; int use_ecm; int use_tep; int use_transmit_on_idle; int t38_version; const char *input_file_name; int i; int seq_no; int model_no; int speed_pattern_no; double tx_when; double rx_when; int use_gui; int opt; log_audio = FALSE; use_ecm = FALSE; t38_version = 1; input_file_name = INPUT_FILE_NAME; simulate_incrementing_repeats = FALSE; model_no = 0; speed_pattern_no = 1; use_gui = FALSE; use_tep = FALSE; use_transmit_on_idle = TRUE; while ((opt = getopt(argc, argv, "egi:Ilm:s:tv:")) != -1) { switch (opt) { case 'e': use_ecm = TRUE; break; case 'g': use_gui = TRUE; break; case 'i': input_file_name = optarg; break; case 'I': simulate_incrementing_repeats = TRUE; break; case 'l': log_audio = TRUE; break; case 'm': model_no = optarg[0] - 'A' + 1; break; case 's': speed_pattern_no = atoi(optarg); break; case 't': use_tep = TRUE; break; case 'v': t38_version = atoi(optarg); break; } } printf("Using T.38 version %d\n", t38_version); if (use_ecm) printf("Using ECM\n"); filesetup = AF_NULL_FILESETUP; wave_handle = AF_NULL_FILEHANDLE; if (log_audio) { if ((filesetup = afNewFileSetup()) == AF_NULL_FILESETUP) { fprintf(stderr, " Failed to create file setup\n"); exit(2); } afInitSampleFormat(filesetup, AF_DEFAULT_TRACK, AF_SAMPFMT_TWOSCOMP, 16); afInitRate(filesetup, AF_DEFAULT_TRACK, (float) SAMPLE_RATE); afInitFileFormat(filesetup, AF_FILE_WAVE); afInitChannels(filesetup, AF_DEFAULT_TRACK, 4); if ((wave_handle = afOpenFile(OUTPUT_FILE_NAME_WAVE, "w", filesetup)) == AF_NULL_FILEHANDLE) { fprintf(stderr, " Cannot create wave file '%s'\n", OUTPUT_FILE_NAME_WAVE); exit(2); } } memset(silence, 0, sizeof(silence)); srand48(0x1234567); if ((path_a_to_b = g1050_init(model_no, speed_pattern_no, 100, 33)) == NULL) { fprintf(stderr, "Failed to start IP network path model\n"); exit(2); } if ((path_b_to_a = g1050_init(model_no, speed_pattern_no, 100, 33)) == NULL) { fprintf(stderr, "Failed to start IP network path model\n"); exit(2); } if (fax_init(&fax_state_a, TRUE) == NULL) { fprintf(stderr, "Cannot start FAX\n"); exit(2); } fax_set_transmit_on_idle(&fax_state_a, use_transmit_on_idle); fax_set_tep_mode(&fax_state_a, use_tep); //t30_set_supported_modems(&(fax_state_a.t30_state), T30_SUPPORT_V27TER | T30_SUPPORT_V29); t30_set_local_ident(&fax_state_a.t30_state, "11111111"); t30_set_tx_file(&fax_state_a.t30_state, input_file_name, -1, -1); t30_set_phase_b_handler(&fax_state_a.t30_state, phase_b_handler, (void *) (intptr_t) 'A'); t30_set_phase_d_handler(&fax_state_a.t30_state, phase_d_handler, (void *) (intptr_t) 'A'); t30_set_phase_e_handler(&fax_state_a.t30_state, phase_e_handler, (void *) (intptr_t) 'A'); t30_set_local_nsf(&fax_state_a.t30_state, (const uint8_t *) "\x50\x00\x00\x00Spandsp\x00", 12); t30_set_ecm_capability(&fax_state_a.t30_state, use_ecm); if (use_ecm) t30_set_supported_compressions(&fax_state_a.t30_state, T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION | T30_SUPPORT_T6_COMPRESSION); span_log_set_level(&fax_state_a.logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(&fax_state_a.logging, "FAX-A "); span_log_set_level(&fax_state_a.t30_state.logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(&fax_state_a.t30_state.logging, "FAX-A "); memset(t30_amp_a, 0, sizeof(t30_amp_a)); if (t38_gateway_init(&t38_state_a, tx_packet_handler_a, &t38_state_b) == NULL) { fprintf(stderr, "Cannot start the T.38 channel\n"); exit(2); } t38_gateway_set_transmit_on_idle(&t38_state_a, use_transmit_on_idle); //t38_gateway_set_supported_modems(&t38_state_a, T30_SUPPORT_V27TER | T30_SUPPORT_V29); //t38_gateway_set_nsx_suppression(&t38_state_a, FALSE); t38_set_t38_version(&t38_state_a.t38, t38_version); t38_gateway_set_ecm_capability(&t38_state_a, use_ecm); span_log_set_level(&t38_state_a.logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(&t38_state_a.logging, "T.38-A"); span_log_set_level(&t38_state_a.t38.logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(&t38_state_a.t38.logging, "T.38-A"); memset(t38_amp_a, 0, sizeof(t38_amp_a)); if (t38_gateway_init(&t38_state_b, tx_packet_handler_b, &t38_state_a) == NULL) { fprintf(stderr, "Cannot start the T.38 channel\n"); exit(2); } t38_gateway_set_transmit_on_idle(&t38_state_b, use_transmit_on_idle); //t38_gateway_set_supported_modems(&t38_state_b, T30_SUPPORT_V27TER | T30_SUPPORT_V29); //t38_gateway_set_nsx_suppression(&t38_state_b, FALSE); t38_set_t38_version(&t38_state_b.t38, t38_version); t38_gateway_set_ecm_capability(&t38_state_b, use_ecm); span_log_set_level(&t38_state_b.logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(&t38_state_b.logging, "T.38-B"); span_log_set_level(&t38_state_b.t38.logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(&t38_state_b.t38.logging, "T.38-B"); memset(t38_amp_b, 0, sizeof(t38_amp_b)); if (fax_init(&fax_state_b, FALSE) == NULL) { fprintf(stderr, "Cannot start FAX\n"); exit(2); } fax_set_transmit_on_idle(&fax_state_b, use_transmit_on_idle); fax_set_tep_mode(&fax_state_b, use_tep); t30_set_local_ident(&fax_state_b.t30_state, "22222222"); t30_set_rx_file(&fax_state_b.t30_state, OUTPUT_FILE_NAME, -1); t30_set_phase_b_handler(&fax_state_b.t30_state, phase_b_handler, (void *) (intptr_t) 'B'); t30_set_phase_d_handler(&fax_state_b.t30_state, phase_d_handler, (void *) (intptr_t) 'B'); t30_set_phase_e_handler(&fax_state_b.t30_state, phase_e_handler, (void *) (intptr_t) 'B'); t30_set_local_nsf(&fax_state_b.t30_state, (const uint8_t *) "\x50\x00\x00\x00Spandsp\x00", 12); t30_set_ecm_capability(&fax_state_b.t30_state, use_ecm); if (use_ecm) t30_set_supported_compressions(&fax_state_b.t30_state, T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION | T30_SUPPORT_T6_COMPRESSION); span_log_set_level(&fax_state_b.logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(&fax_state_b.logging, "FAX-B "); span_log_set_level(&fax_state_b.t30_state.logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(&fax_state_b.t30_state.logging, "FAX-B "); memset(t30_amp_b, 0, sizeof(t30_amp_b)); #if defined(ENABLE_GUI) if (use_gui) start_media_monitor(); #endif for (;;) { span_log_bump_samples(&fax_state_a.logging, SAMPLES_PER_CHUNK); span_log_bump_samples(&fax_state_a.t30_state.logging, SAMPLES_PER_CHUNK); span_log_bump_samples(&t38_state_a.logging, SAMPLES_PER_CHUNK); span_log_bump_samples(&t38_state_a.t38.logging, SAMPLES_PER_CHUNK); span_log_bump_samples(&t38_state_b.logging, SAMPLES_PER_CHUNK); span_log_bump_samples(&t38_state_b.t38.logging, SAMPLES_PER_CHUNK); span_log_bump_samples(&fax_state_b.logging, SAMPLES_PER_CHUNK); span_log_bump_samples(&fax_state_b.t30_state.logging, SAMPLES_PER_CHUNK); memset(out_amp, 0, sizeof(out_amp)); t30_len_a = fax_tx(&fax_state_a, t30_amp_a, SAMPLES_PER_CHUNK); if (!use_transmit_on_idle) { /* The receive side always expects a full block of samples, but the transmit side may not be sending any when it doesn't need to. We may need to pad with some silence. */ if (t30_len_a < SAMPLES_PER_CHUNK) { memset(t30_amp_a + t30_len_a, 0, sizeof(int16_t)*(SAMPLES_PER_CHUNK - t30_len_a)); t30_len_a = SAMPLES_PER_CHUNK; } } if (log_audio) { for (i = 0; i < t30_len_a; i++) out_amp[i*4] = t30_amp_a[i]; } if (t38_gateway_rx(&t38_state_a, t30_amp_a, t30_len_a)) break; t38_len_a = t38_gateway_tx(&t38_state_a, t38_amp_a, SAMPLES_PER_CHUNK); if (!use_transmit_on_idle) { if (t38_len_a < SAMPLES_PER_CHUNK) { memset(t38_amp_a + t38_len_a, 0, sizeof(int16_t)*(SAMPLES_PER_CHUNK - t38_len_a)); t38_len_a = SAMPLES_PER_CHUNK; } } if (log_audio) { for (i = 0; i < t38_len_a; i++) out_amp[i*4 + 1] = t38_amp_a[i]; } if (fax_rx(&fax_state_a, t38_amp_a, SAMPLES_PER_CHUNK)) break; t30_len_b = fax_tx(&fax_state_b, t30_amp_b, SAMPLES_PER_CHUNK); if (!use_transmit_on_idle) { /* The receive side always expects a full block of samples, but the transmit side may not be sending any when it doesn't need to. We may need to pad with some silence. */ if (t30_len_b < SAMPLES_PER_CHUNK) { memset(t30_amp_b + t30_len_b, 0, sizeof(int16_t)*(SAMPLES_PER_CHUNK - t30_len_b)); t30_len_b = SAMPLES_PER_CHUNK; } } if (log_audio) { for (i = 0; i < t30_len_b; i++) out_amp[i*4 + 3] = t30_amp_b[i]; } if (t38_gateway_rx(&t38_state_b, t30_amp_b, t30_len_b)) break; t38_len_b = t38_gateway_tx(&t38_state_b, t38_amp_b, SAMPLES_PER_CHUNK); if (!use_transmit_on_idle) { if (t38_len_b < SAMPLES_PER_CHUNK) { memset(t38_amp_b + t38_len_b, 0, sizeof(int16_t)*(SAMPLES_PER_CHUNK - t38_len_b)); t38_len_b = SAMPLES_PER_CHUNK; } } if (log_audio) { for (i = 0; i < t38_len_b; i++) out_amp[i*4 + 2] = t38_amp_b[i]; } if (fax_rx(&fax_state_b, t38_amp_b, SAMPLES_PER_CHUNK)) break; when += 0.02; while ((msg_len = g1050_get(path_a_to_b, msg, 1024, when, &seq_no, &tx_when, &rx_when)) >= 0) { #if defined(ENABLE_GUI) if (use_gui) media_monitor_rx(seq_no, tx_when, rx_when); #endif t38_core_rx_ifp_packet(&t38_state_b.t38, msg, msg_len, seq_no); } while ((msg_len = g1050_get(path_b_to_a, msg, 1024, when, &seq_no, &tx_when, &rx_when)) >= 0) { #if defined(ENABLE_GUI) if (use_gui) media_monitor_rx(seq_no, tx_when, rx_when); #endif t38_core_rx_ifp_packet(&t38_state_a.t38, msg, msg_len, seq_no); } if (log_audio) { outframes = afWriteFrames(wave_handle, AF_DEFAULT_TRACK, out_amp, SAMPLES_PER_CHUNK); if (outframes != SAMPLES_PER_CHUNK) break; } if (done[0] && done[1]) break; #if defined(ENABLE_GUI) if (use_gui) media_monitor_update_display(); #endif } if (log_audio) { if (afCloseFile(wave_handle) != 0) { fprintf(stderr, " Cannot close wave file '%s'\n", OUTPUT_FILE_NAME_WAVE); exit(2); } afFreeFileSetup(filesetup); } if (!succeeded[0] || !succeeded[1]) { printf("Tests failed\n"); exit(2); } printf("Tests passed\n"); return 0; }
static int fax_audio(struct cw_channel *chan, fax_state_t *fax, const char *file, int calling_party, int verbose) { char *x; struct cw_frame *inf = NULL; struct cw_frame outf; int ready = 1; int samples = 0; int res = 0; int len = 0; int generator_mode = 0; uint64_t begin = 0; uint64_t received_frames = 0; uint8_t __buf[sizeof(uint16_t)*MAX_BLOCK_SIZE + 2*CW_FRIENDLY_OFFSET]; uint8_t *buf = __buf + CW_FRIENDLY_OFFSET; #if 0 struct cw_frame *dspf = NULL; struct cw_dsp *dsp = NULL; #endif uint64_t voice_frames; t30_state_t *t30; memset(fax, 0, sizeof(*fax)); if (fax_init(fax, calling_party) == NULL) { cw_log(LOG_WARNING, "Unable to start FAX\n"); return -1; } t30 = fax_get_t30_state(fax); fax_set_transmit_on_idle(fax, TRUE); span_log_set_message_handler(&fax->logging, span_message); span_log_set_message_handler(&t30->logging, span_message); if (verbose) { span_log_set_level(&fax->logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); span_log_set_level(&t30->logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); } fax_set_common(chan, t30, file, calling_party, verbose); fax_set_transmit_on_idle(fax, TRUE); if (calling_party) { voice_frames = 0; } else { #if 0 /* Initializing the DSP */ if ((dsp = cw_dsp_new()) == NULL) { cw_log(LOG_WARNING, "Unable to allocate DSP!\n"); } else { cw_dsp_set_threshold(dsp, 256); cw_dsp_set_features(dsp, DSP_FEATURE_DTMF_DETECT | DSP_FEATURE_FAX_CNG_DETECT); cw_dsp_digitmode(dsp, DSP_DIGITMODE_DTMF | DSP_DIGITMODE_RELAXDTMF); } #endif voice_frames = 1; } /* This is the main loop */ begin = nowis(); while (ready && ready_to_talk(chan)) { if (chan->t38_status == T38_NEGOTIATED) break; if ((res = cw_waitfor(chan, 20)) < 0) { ready = 0; break; } if (!t30_call_active(t30)) break; if ((inf = cw_read(chan)) == NULL) { ready = 0; break; } /* We got a frame */ if (inf->frametype == CW_FRAME_VOICE) { #if 0 if (dsp) { if ((dspf = cw_frdup(inf))) dspf = cw_dsp_process(chan, dsp, dspf); if (dspf) { if (dspf->frametype == CW_FRAME_DTMF) { if (dspf->subclass == 'f') { cw_log(LOG_DEBUG, "Fax detected in RxFax !!!\n"); cw_app_request_t38(chan); /* Prevent any further attempts to negotiate T.38 */ cw_dsp_free(dsp); dsp = NULL; } } cw_fr_free(dspf); dspf = NULL; } } #else if (voice_frames) { /* Wait a little before trying to switch to T.38, as some things don't seem to like entirely missing the audio. */ if (++voice_frames == 100) { cw_log(LOG_DEBUG, "Requesting T.38 negotation in RxFax !!!\n"); cw_app_request_t38(chan); voice_frames = 0; } } #endif received_frames++; if (fax_rx(fax, inf->data, inf->samples)) break; samples = (inf->samples <= MAX_BLOCK_SIZE) ? inf->samples : MAX_BLOCK_SIZE; if ((len = fax_tx(fax, (int16_t *) &buf[CW_FRIENDLY_OFFSET], samples)) > 0) { cw_fr_init_ex(&outf, CW_FRAME_VOICE, CW_FORMAT_SLINEAR, "FAX"); outf.datalen = len*sizeof(int16_t); outf.samples = len; outf.data = &buf[CW_FRIENDLY_OFFSET]; outf.offset = CW_FRIENDLY_OFFSET; if (cw_write(chan, &outf) < 0) { cw_log(LOG_WARNING, "Unable to write frame to channel; %s\n", strerror(errno)); break; } } } else { if ((nowis() - begin) > 1000000) { if (received_frames < 20) { /* Just to be sure we have had no frames ... */ cw_log(LOG_NOTICE, "Switching to generator mode\n"); generator_mode = 1; break; } } } cw_fr_free(inf); inf = NULL; } if (inf) { cw_fr_free(inf); inf = NULL; } if (generator_mode) { /* This is activated when we don't receive any frame for X seconds (see above)... */ cw_log(LOG_NOTICE, "Starting generator\n"); #if 0 if (dsp) cw_dsp_reset(dsp); #endif cw_generator_activate(chan, &faxgen, fax); while (ready && ready_to_talk(chan)) { if (chan->t38_status == T38_NEGOTIATED) break; if ((res = cw_waitfor(chan, 20)) < 0) { ready = 0; break; } if (!t30_call_active(t30)) break; if ((inf = cw_read(chan)) == NULL) { ready = 0; break; } /* We got a frame */ if (inf->frametype == CW_FRAME_VOICE) { #if 0 if (dsp) { if ((dspf = cw_frdup(inf))) dspf = cw_dsp_process(chan, dsp, dspf); if (dspf) { if (dspf->frametype == CW_FRAME_DTMF) { if (dspf->subclass == 'f') { cw_log(LOG_DEBUG, "Fax detected in RxFax !!!\n"); cw_app_request_t38(chan); /* Prevent any further attempts to negotiate T.38 */ cw_dsp_free(dsp); dsp = NULL; } } cw_fr_free(dspf); dspf = NULL; } } #else if (voice_frames) { if (++voice_frames == 100) { cw_log(LOG_DEBUG, "Requesting T.38 negotation in RxFax !!!\n"); cw_app_request_t38(chan); voice_frames = 0; } } #endif if (fax_rx(fax, inf->data, inf->samples)) { ready = 0; break; } } cw_fr_free(inf); inf = NULL; } if (inf) { cw_fr_free(inf); inf = NULL; } cw_log(LOG_NOTICE, "Stopping generator\n"); cw_generator_deactivate(chan); } #if 0 if (dsp) cw_dsp_free(dsp); #endif return ready; }
int main(int argc, char *argv[]) { fsk_rx_state_t *fsk; v17_rx_state_t *v17; v29_rx_state_t *v29; v27ter_rx_state_t *v27ter; int16_t amp[SAMPLES_PER_CHUNK]; AFfilehandle inhandle; int len; const char *filename; float x; logging_state_t *logging; filename = "fax_samp.wav"; if (argc > 1) filename = argv[1]; if ((inhandle = afOpenFile(filename, "r", NULL)) == AF_NULL_FILEHANDLE) { fprintf(stderr, " Cannot open wave file '%s'\n", filename); exit(2); } if ((x = afGetFrameSize(inhandle, AF_DEFAULT_TRACK, 1)) != 2.0) { printf(" Unexpected frame size in speech file '%s' (%f)\n", filename, x); exit(2); } if ((x = afGetRate(inhandle, AF_DEFAULT_TRACK)) != (float) SAMPLE_RATE) { printf(" Unexpected sample rate in speech file '%s' (%f)\n", filename, x); exit(2); } if ((x = afGetChannels(inhandle, AF_DEFAULT_TRACK)) != 1.0) { printf(" Unexpected number of channels in speech file '%s' (%f)\n", filename, x); exit(2); } memset(&t30_dummy, 0, sizeof(t30_dummy)); span_log_init(&t30_dummy.logging, SPAN_LOG_FLOW, NULL); span_log_set_protocol(&t30_dummy.logging, "T.30"); hdlc_rx_init(&hdlcrx, FALSE, TRUE, 5, hdlc_accept, NULL); fsk = fsk_rx_init(NULL, &preset_fsk_specs[FSK_V21CH2], TRUE, v21_put_bit, NULL); v17 = v17_rx_init(NULL, 14400, v17_put_bit, NULL); v29 = v29_rx_init(NULL, 9600, v29_put_bit, NULL); //v29 = v29_rx_init(NULL, 7200, v29_put_bit, NULL); v27ter = v27ter_rx_init(NULL, 4800, v27ter_put_bit, NULL); fsk_rx_signal_cutoff(fsk, -45.5); v17_rx_signal_cutoff(v17, -45.5); v29_rx_signal_cutoff(v29, -45.5); v27ter_rx_signal_cutoff(v27ter, -40.0); #if 1 logging = v17_rx_get_logging_state(v17); span_log_init(logging, SPAN_LOG_FLOW, NULL); span_log_set_protocol(logging, "V.17"); span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_FLOW); logging = v29_rx_get_logging_state(v29); span_log_init(logging, SPAN_LOG_FLOW, NULL); span_log_set_protocol(logging, "V.29"); span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_FLOW); logging = v27ter_rx_get_logging_state(v27ter); span_log_init(logging, SPAN_LOG_FLOW, NULL); span_log_set_protocol(logging, "V.27ter"); span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_FLOW); #endif if (t4_rx_init(&t4_state, "fax_decode.tif", T4_COMPRESSION_ITU_T4_2D) == NULL) { fprintf(stderr, "Failed to init\n"); exit(0); } for (;;) { len = afReadFrames(inhandle, AF_DEFAULT_TRACK, amp, SAMPLES_PER_CHUNK); if (len < SAMPLES_PER_CHUNK) break; fsk_rx(fsk, amp, len); v17_rx(v17, amp, len); v29_rx(v29, amp, len); //v27ter_rx(v27ter, amp, len); } t4_rx_release(&t4_state); if (afCloseFile(inhandle) != 0) { fprintf(stderr, " Cannot close wave file '%s'\n", filename); exit(2); } return 0; }
static int t30_tests(int log_audio, int test_sending) { int k; int outframes; fax_state_t *fax_state; int16_t t30_amp[SAMPLES_PER_CHUNK]; int16_t t31_amp[SAMPLES_PER_CHUNK]; int16_t silence[SAMPLES_PER_CHUNK]; int16_t out_amp[2*SAMPLES_PER_CHUNK]; int t30_len; int t31_len; SNDFILE *wave_handle; SNDFILE *in_handle; int fast_send; int fast_send_tcf; int fast_blocks; uint8_t fast_buf[1000]; t30_state_t *t30; logging_state_t *logging; int i; wave_handle = NULL; if (log_audio) { if ((wave_handle = sf_open_telephony_write(OUTPUT_WAVE_FILE_NAME, 2)) == NULL) { fprintf(stderr, " Cannot create audio file '%s'\n", OUTPUT_WAVE_FILE_NAME); exit(2); } } memset(silence, 0, sizeof(silence)); in_handle = NULL; if (decode_test_file) { if ((in_handle = sf_open_telephony_read(decode_test_file, 1)) == NULL) { fprintf(stderr, " Cannot create audio file '%s'\n", decode_test_file); exit(2); } } if ((t31_state = t31_init(NULL, at_tx_handler, NULL, modem_call_control, NULL, NULL, NULL)) == NULL) { fprintf(stderr, " Cannot start the T.31 FAX modem\n"); exit(2); } logging = t31_get_logging_state(t31_state); span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(logging, "T.31"); if (test_sending) { fax_state = fax_init(NULL, FALSE); t30 = fax_get_t30_state(fax_state); t30_set_rx_file(t30, OUTPUT_FILE_NAME, -1); fax_test_seq = fax_send_test_seq; countdown = 0; } else { fax_state = fax_init(NULL, TRUE); t30 = fax_get_t30_state(fax_state); t30_set_tx_file(t30, INPUT_FILE_NAME, -1, -1); fax_test_seq = fax_receive_test_seq; countdown = 250; } t30_set_tx_ident(t30, "11111111"); t30_set_supported_modems(t30, T30_SUPPORT_V27TER | T30_SUPPORT_V29 | T30_SUPPORT_V17); t30_set_phase_b_handler(t30, phase_b_handler, (void *) 'A'); t30_set_phase_d_handler(t30, phase_d_handler, (void *) 'A'); t30_set_phase_e_handler(t30, phase_e_handler, (void *) 'A'); memset(t30_amp, 0, sizeof(t30_amp)); logging = t30_get_logging_state(t30); span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(logging, "FAX"); logging = fax_get_logging_state(fax_state); span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(logging, "FAX"); fast_send = FALSE; fast_send_tcf = TRUE; fast_blocks = 0; kick = TRUE; while (!done) { if (kick) { kick = FALSE; if (fax_test_seq[test_seq_ptr].command > (const char *) 2) { if (fax_test_seq[test_seq_ptr].command[0]) { printf("%s\n", fax_test_seq[test_seq_ptr].command); t31_at_rx(t31_state, fax_test_seq[test_seq_ptr].command, fax_test_seq[test_seq_ptr].len_command); } } else { if (fax_test_seq[test_seq_ptr].command == (const char *) 2) { printf("Fast send TCF\n"); fast_send = TRUE; fast_send_tcf = TRUE; fast_blocks = 100; } else { printf("Fast send image\n"); fast_send = TRUE; fast_send_tcf = FALSE; fast_blocks = 100; } } } if (fast_send) { /* Send fast modem data */ if (fast_send_tcf) { memset(fast_buf, 0, 36); } else { if (fast_blocks == 1) { /* Create the end of page condition */ for (i = 0; i < 36; i += 2) { fast_buf[i] = 0x00; fast_buf[i + 1] = 0x80; } } else { /* Create a chunk of white page */ for (i = 0; i < 36; i += 4) { fast_buf[i] = 0x00; fast_buf[i + 1] = 0x80; fast_buf[i + 2] = 0xB2; fast_buf[i + 3] = 0x01; } } } if (fast_blocks == 1) { /* Insert EOLs */ fast_buf[35] = ETX; fast_buf[34] = DLE; fast_buf[31] = fast_buf[28] = fast_buf[25] = fast_buf[22] = fast_buf[19] = fast_buf[16] = 1; } t31_at_rx(t31_state, (char *) fast_buf, 36); if (--fast_blocks == 0) fast_send = FALSE; } t30_len = fax_tx(fax_state, t30_amp, SAMPLES_PER_CHUNK); /* The receive side always expects a full block of samples, but the transmit side may not be sending any when it doesn't need to. We may need to pad with some silence. */ if (t30_len < SAMPLES_PER_CHUNK) { memset(t30_amp + t30_len, 0, sizeof(int16_t)*(SAMPLES_PER_CHUNK - t30_len)); t30_len = SAMPLES_PER_CHUNK; } if (log_audio) { for (k = 0; k < t30_len; k++) out_amp[2*k] = t30_amp[k]; } if (t31_rx(t31_state, t30_amp, t30_len)) break; if (countdown) { if (answered) { countdown = 0; t31_call_event(t31_state, AT_CALL_EVENT_ANSWERED); } else if (--countdown == 0) { t31_call_event(t31_state, AT_CALL_EVENT_ALERTING); countdown = 250; } } t31_len = t31_tx(t31_state, t31_amp, SAMPLES_PER_CHUNK); if (t31_len < SAMPLES_PER_CHUNK) { memset(t31_amp + t31_len, 0, sizeof(int16_t)*(SAMPLES_PER_CHUNK - t31_len)); t31_len = SAMPLES_PER_CHUNK; } if (log_audio) { for (k = 0; k < t31_len; k++) out_amp[2*k + 1] = t31_amp[k]; } if (fax_rx(fax_state, t31_amp, SAMPLES_PER_CHUNK)) break; logging = fax_get_logging_state(fax_state); span_log_bump_samples(logging, SAMPLES_PER_CHUNK); logging = t30_get_logging_state(t30); span_log_bump_samples(logging, SAMPLES_PER_CHUNK); logging = t31_get_logging_state(t31_state); span_log_bump_samples(logging, SAMPLES_PER_CHUNK); if (log_audio) { outframes = sf_writef_short(wave_handle, out_amp, SAMPLES_PER_CHUNK); if (outframes != SAMPLES_PER_CHUNK) break; } } if (decode_test_file) { if (sf_close_telephony(in_handle)) { fprintf(stderr, " Cannot close audio file '%s'\n", decode_test_file); exit(2); } } if (log_audio) { if (sf_close_telephony(wave_handle)) { fprintf(stderr, " Cannot close audio file '%s'\n", OUTPUT_WAVE_FILE_NAME); exit(2); } } return 0; }
static int non_v8_calls_v8_tests(SNDFILE *outhandle) { silence_gen_state_t *non_v8_caller_tx; modem_connect_tones_rx_state_t *non_v8_caller_rx; v8_state_t *v8_answerer; logging_state_t *answerer_logging; int answerer_available_modulations; int i; int samples; int remnant; int outframes; int tone; int16_t amp[SAMPLES_PER_CHUNK]; int16_t out_amp[2*SAMPLES_PER_CHUNK]; v8_parms_t v8_answer_parms; answerer_available_modulations = V8_MOD_V17 | V8_MOD_V21 | V8_MOD_V22 | V8_MOD_V23HDX | V8_MOD_V23 | V8_MOD_V26BIS | V8_MOD_V26TER | V8_MOD_V27TER | V8_MOD_V29 | V8_MOD_V32 | V8_MOD_V34HDX | V8_MOD_V34 | V8_MOD_V90 | V8_MOD_V92; negotiations_ok = 0; non_v8_caller_tx = silence_gen_init(NULL, 10*SAMPLE_RATE); non_v8_caller_rx = modem_connect_tones_rx_init(NULL, MODEM_CONNECT_TONES_ANS_PR, NULL, NULL); v8_answer_parms.modem_connect_tone = MODEM_CONNECT_TONES_ANSAM_PR; v8_answer_parms.send_ci = true; v8_answer_parms.v92 = -1; v8_answer_parms.call_function = V8_CALL_V_SERIES; v8_answer_parms.modulations = answerer_available_modulations; v8_answer_parms.protocol = V8_PROTOCOL_LAPM_V42; v8_answer_parms.pcm_modem_availability = 0; v8_answer_parms.pstn_access = 0; v8_answer_parms.nsf = -1; v8_answer_parms.t66 = -1; v8_answerer = v8_init(NULL, false, &v8_answer_parms, handler, (void *) "answerer"); answerer_logging = v8_get_logging_state(v8_answerer); span_log_set_level(answerer_logging, SPAN_LOG_FLOW | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(answerer_logging, "answerer"); for (i = 0; i < 1000; i++) { samples = silence_gen(non_v8_caller_tx, amp, SAMPLES_PER_CHUNK); if (samples < SAMPLES_PER_CHUNK) { vec_zeroi16(amp + samples, SAMPLES_PER_CHUNK - samples); samples = SAMPLES_PER_CHUNK; } /*endif*/ remnant = v8_rx(v8_answerer, amp, samples); if (remnant) break; /*endif*/ for (i = 0; i < samples; i++) out_amp[2*i] = amp[i]; /*endfor*/ samples = v8_tx(v8_answerer, amp, SAMPLES_PER_CHUNK); if (samples < SAMPLES_PER_CHUNK) { vec_zeroi16(amp + samples, SAMPLES_PER_CHUNK - samples); samples = SAMPLES_PER_CHUNK; } /*endif*/ span_log_bump_samples(answerer_logging, samples); modem_connect_tones_rx(non_v8_caller_rx, amp, samples); if ((tone = modem_connect_tones_rx_get(non_v8_caller_rx)) != MODEM_CONNECT_TONES_NONE) { printf("Detected %s (%d)\n", modem_connect_tone_to_str(tone), tone); if (tone == MODEM_CONNECT_TONES_ANSAM_PR) negotiations_ok++; /*endif*/ } /*endif*/ for (i = 0; i < samples; i++) out_amp[2*i + 1] = amp[i]; /*endfor*/ if (outhandle) { outframes = sf_writef_short(outhandle, out_amp, samples); if (outframes != samples) { fprintf(stderr, " Error writing audio file\n"); exit(2); } /*endif*/ } /*endif*/ } /*endfor*/ silence_gen_free(non_v8_caller_tx); modem_connect_tones_rx_free(non_v8_caller_rx); v8_free(v8_answerer); if (negotiations_ok != 1) { printf("Tests failed.\n"); exit(2); } /*endif*/ return 0; }
int psuedo_terminal_create(modem_t *modem) { #if defined(WIN32) COMMTIMEOUTS timeouts = {0}; #endif memset(modem, 0, sizeof(*modem)); span_log_init(&modem->logging, SPAN_LOG_NONE, NULL); span_log_set_protocol(&modem->logging, "PTY"); span_log_set_level(&modem->logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); span_log_set_tag(&modem->logging, "PTY"); modem->master = -1; modem->slave = -1; #if USE_OPENPTY if (openpty(&modem->master, &modem->slave, NULL, NULL, NULL)) { span_log(&modem->logging, SPAN_LOG_ERROR, "Fatal error: failed to initialize pty\n"); return -1; } modem->stty = ttyname(modem->slave); #else #if defined(WIN32) modem->slot = 4 + next_id++; /* need work here we start at COM4 for now*/ snprintf(modem->devlink, sizeof(modem->devlink), "COM%d", modem->slot); modem->master = CreateFile(modem->devlink, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0); if (modem->master == INVALID_HANDLE_VALUE) { if (GetLastError() == ERROR_FILE_NOT_FOUND) span_log(&modem->logging, SPAN_LOG_ERROR, "Fatal error: Serial port does not exist\n"); else span_log(&modem->logging, SPAN_LOG_ERROR, "Fatal error: Serial port open error\n"); return -1; } #elif !defined(HAVE_POSIX_OPENPT) modem->master = open("/dev/ptmx", O_RDWR); #else modem->master = posix_openpt(O_RDWR | O_NOCTTY); #endif #if !defined(WIN32) if (modem->master < 0) span_log(&modem->logging, SPAN_LOG_ERROR, "Fatal error: failed to initialize UNIX98 master pty\n"); if (grantpt(modem->master) < 0) span_log(&modem->logging, SPAN_LOG_ERROR, "Fatal error: failed to grant access to slave pty\n"); if (unlockpt(modem->master) < 0) span_log(&modem->logging, SPAN_LOG_ERROR, "Fatal error: failed to unlock slave pty\n"); if ((modem->stty = ptsname(modem->master)) == NULL) span_log(&modem->logging, SPAN_LOG_ERROR, "Fatal error: failed to obtain slave pty filename\n"); if ((modem->slave = open(modem->stty, O_RDWR)) < 0) span_log(&modem->logging, SPAN_LOG_ERROR, "Fatal error: failed to open slave pty %s\n", modem->stty); #endif #if defined(SOLARIS) ioctl(modem->slave, I_PUSH, "ptem"); ioctl(modem->slave, I_PUSH, "ldterm"); #endif #endif #if defined(WIN32) timeouts.ReadIntervalTimeout = 50; timeouts.ReadTotalTimeoutConstant = 50; timeouts.ReadTotalTimeoutMultiplier = 10; timeouts.WriteTotalTimeoutConstant = 50; timeouts.WriteTotalTimeoutMultiplier = 10; SetCommMask(modem->master, EV_RXCHAR); if (!SetCommTimeouts(modem->master, &timeouts)) { span_log(&modem->logging, SPAN_LOG_ERROR, "Cannot set up non-blocking read on %s\n", modem->devlink); psuedo_terminal_close(modem); return -1; } modem->threadAbort = CreateEvent(NULL, true, false, NULL); #else modem->slot = next_id++; snprintf(modem->devlink, sizeof(modem->devlink), "%s/%d", device_root_name, modem->slot); /* Remove any stale link which might be present */ unlink(modem->devlink); if (symlink(modem->stty, modem->devlink)) { span_log(&modem->logging, SPAN_LOG_ERROR, "Fatal error: failed to create %s symbolic link\n", modem->devlink); psuedo_terminal_close(modem); return -1; } if (fcntl(modem->master, F_SETFL, fcntl(modem->master, F_GETFL, 0) | O_NONBLOCK)) { span_log(&modem->logging, SPAN_LOG_ERROR, "Cannot set up non-blocking read on %s\n", ttyname(modem->master)); psuedo_terminal_close(modem); return -1; } #endif return 0; }
int main(int argc, char *argv[]) { int16_t caller_amp[BLOCK_LEN]; int16_t answerer_amp[BLOCK_LEN]; int16_t caller_model_amp[BLOCK_LEN]; int16_t answerer_model_amp[BLOCK_LEN]; int16_t out_amp[2*BLOCK_LEN]; AFfilehandle outhandle; AFfilesetup filesetup; int outframes; int samples; int i; int test_bps; int line_model_no; int bits_per_test; int noise_level; int signal_level; int log_audio; int channel_codec; int opt; channel_codec = MUNGE_CODEC_NONE; test_bps = 2400; line_model_no = 0; noise_level = -70; signal_level = -13; bits_per_test = 50000; log_audio = FALSE; while ((opt = getopt(argc, argv, "b:c:glm:n:s:")) != -1) { switch (opt) { case 'b': bits_per_test = atoi(optarg); break; case 'c': channel_codec = atoi(optarg); break; case 'g': #if defined(ENABLE_GUI) use_gui = TRUE; #else fprintf(stderr, "Graphical monitoring not available\n"); exit(2); #endif break; case 'l': log_audio = TRUE; break; case 'm': line_model_no = atoi(optarg); break; case 'n': noise_level = atoi(optarg); break; case 's': signal_level = atoi(optarg); break; default: //usage(); exit(2); break; } } argc -= optind; argv += optind; if (argc > 0) { if (strcmp(argv[0], "2400") == 0) test_bps = 2400; else if (strcmp(argv[0], "1200") == 0) test_bps = 1200; else { fprintf(stderr, "Invalid bit rate\n"); exit(2); } } filesetup = AF_NULL_FILESETUP; outhandle = AF_NULL_FILEHANDLE; if (log_audio) { if ((filesetup = afNewFileSetup()) == AF_NULL_FILESETUP) { fprintf(stderr, " Failed to create file setup\n"); exit(2); } afInitSampleFormat(filesetup, AF_DEFAULT_TRACK, AF_SAMPFMT_TWOSCOMP, 16); afInitRate(filesetup, AF_DEFAULT_TRACK, (float) SAMPLE_RATE); afInitFileFormat(filesetup, AF_FILE_WAVE); afInitChannels(filesetup, AF_DEFAULT_TRACK, 2); if ((outhandle = afOpenFile(OUT_FILE_NAME, "w", filesetup)) == AF_NULL_FILEHANDLE) { fprintf(stderr, " Cannot create wave file '%s'\n", OUT_FILE_NAME); exit(2); } } v22bis_init(&caller, test_bps, 2, TRUE, v22bis_getbit, v22bis_putbit, &caller); v22bis_tx_power(&caller, signal_level); /* Move the carrier off a bit */ caller.tx.carrier_phase_rate = dds_phase_ratef(1207.0f); v22bis_init(&answerer, test_bps, 2, FALSE, v22bis_getbit, v22bis_putbit, &answerer); v22bis_tx_power(&answerer, signal_level); answerer.tx.carrier_phase_rate = dds_phase_ratef(2407.0f); v22bis_set_qam_report_handler(&caller, qam_report, (void *) &qam_caller); v22bis_set_qam_report_handler(&answerer, qam_report, (void *) &qam_answerer); span_log_set_level(&caller.logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_FLOW); span_log_set_tag(&caller.logging, "caller"); span_log_set_level(&answerer.logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_FLOW); span_log_set_tag(&answerer.logging, "answerer"); qam_caller.s = &caller; qam_caller.smooth_power = 0.0f; qam_caller.symbol_no = 0; qam_answerer.s = &answerer; qam_answerer.smooth_power = 0.0f; qam_answerer.symbol_no = 0; #if defined(ENABLE_GUI) if (use_gui) { qam_caller.qam_monitor = qam_monitor_init(6.0f, "Calling modem"); qam_answerer.qam_monitor = qam_monitor_init(6.0f, "Answering modem"); } #endif if ((model = both_ways_line_model_init(line_model_no, (float) noise_level, line_model_no, (float) noise_level, channel_codec, 0)) == NULL) { fprintf(stderr, " Failed to create line model\n"); exit(2); } for (;;) { samples = v22bis_tx(&caller, caller_amp, BLOCK_LEN); #if defined(ENABLE_GUI) if (use_gui) qam_monitor_update_audio_level(qam_caller.qam_monitor, caller_amp, samples); #endif if (samples == 0) { printf("Restarting on zero output\n"); v22bis_restart(&caller, test_bps); rx_ptr = 0; tx_ptr = 0; } samples = v22bis_tx(&answerer, answerer_amp, BLOCK_LEN); #if defined(ENABLE_GUI) if (use_gui) qam_monitor_update_audio_level(qam_answerer.qam_monitor, answerer_amp, samples); #endif if (samples == 0) { printf("Restarting on zero output\n"); v22bis_restart(&answerer, test_bps); rx_ptr = 0; tx_ptr = 0; } both_ways_line_model(model, caller_model_amp, caller_amp, answerer_model_amp, answerer_amp, samples); v22bis_rx(&answerer, caller_model_amp, samples); for (i = 0; i < samples; i++) out_amp[2*i] = caller_model_amp[i]; for ( ; i < BLOCK_LEN; i++) out_amp[2*i] = 0; v22bis_rx(&caller, answerer_model_amp, samples); for (i = 0; i < samples; i++) out_amp[2*i + 1] = answerer_model_amp[i]; for ( ; i < BLOCK_LEN; i++) out_amp[2*i + 1] = 0; if (log_audio) { outframes = afWriteFrames(outhandle, AF_DEFAULT_TRACK, out_amp, BLOCK_LEN); if (outframes != BLOCK_LEN) { fprintf(stderr, " Error writing wave file\n"); exit(2); } } } if (log_audio) { if (afCloseFile(outhandle) != 0) { fprintf(stderr, " Cannot close wave file '%s'\n", OUT_FILE_NAME); exit(2); } afFreeFileSetup(filesetup); } return 0; }
int main(int argc, char *argv[]) { int msg_len; uint8_t msg[1024]; int t38_version; int i; int seq_no; int use_ecm; int without_pacing; const char *input_file_name; t38_version = 1; without_pacing = FALSE; input_file_name = INPUT_FILE_NAME; use_ecm = FALSE; simulate_incrementing_repeats = FALSE; for (i = 1; i < argc; i++) { if (strcmp(argv[i], "-e") == 0) { use_ecm = TRUE; continue; } if (strcmp(argv[i], "-i") == 0) { i++; input_file_name = argv[i]; continue; } if (strcmp(argv[i], "-I") == 0) { simulate_incrementing_repeats = TRUE; continue; } if (strcmp(argv[i], "-p") == 0) { without_pacing = TRUE; continue; } if (strcmp(argv[i], "-v") == 0) { i++; t38_version = atoi(argv[i]); continue; } } printf("Using T.38 version %d\n", t38_version); if (use_ecm) printf("Using ECM\n"); if ((path_a_to_b = ip_network_model_init(800, 2000, 0)) == NULL) { fprintf(stderr, "Failed to start IP network path model\n"); exit(2); } if ((path_b_to_a = ip_network_model_init(800, 2000, 0)) == NULL) { fprintf(stderr, "Failed to start IP network path model\n"); exit(2); } if (t38_terminal_init(&t38_state_a, TRUE, tx_packet_handler_a, &t38_state_b) == NULL) { fprintf(stderr, "Cannot start the T.38 channel\n"); exit(2); } t38_set_t38_version(&t38_state_a.t38, t38_version); t38_terminal_set_config(&t38_state_a, without_pacing); span_log_set_level(&t38_state_a.logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(&t38_state_a.logging, "T.38-A"); span_log_set_level(&t38_state_a.t38.logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(&t38_state_a.t38.logging, "T.38-A"); span_log_set_level(&t38_state_a.t30_state.logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(&t38_state_a.t30_state.logging, "T.38-A"); t30_set_local_ident(&t38_state_a.t30_state, "11111111"); t30_set_tx_file(&t38_state_a.t30_state, input_file_name, -1, -1); t30_set_phase_b_handler(&t38_state_a.t30_state, phase_b_handler, (void *) (intptr_t) 'A'); t30_set_phase_d_handler(&t38_state_a.t30_state, phase_d_handler, (void *) (intptr_t) 'A'); t30_set_phase_e_handler(&t38_state_a.t30_state, phase_e_handler, (void *) (intptr_t) 'A'); t30_set_ecm_capability(&t38_state_a.t30_state, use_ecm); if (use_ecm) t30_set_supported_compressions(&t38_state_a.t30_state, T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION | T30_SUPPORT_T6_COMPRESSION); if (t38_terminal_init(&t38_state_b, FALSE, tx_packet_handler_b, &t38_state_a) == NULL) { fprintf(stderr, "Cannot start the T.38 channel\n"); exit(2); } t38_set_t38_version(&t38_state_b.t38, t38_version); t38_terminal_set_config(&t38_state_b, without_pacing); span_log_set_level(&t38_state_b.logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(&t38_state_b.logging, "T.38-B"); span_log_set_level(&t38_state_b.t38.logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(&t38_state_b.t38.logging, "T.38-B"); span_log_set_level(&t38_state_b.t30_state.logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(&t38_state_b.t30_state.logging, "T.38-B"); t30_set_local_ident(&t38_state_b.t30_state, "22222222"); t30_set_rx_file(&t38_state_b.t30_state, OUTPUT_FILE_NAME, -1); t30_set_phase_b_handler(&t38_state_b.t30_state, phase_b_handler, (void *) (intptr_t) 'B'); t30_set_phase_d_handler(&t38_state_b.t30_state, phase_d_handler, (void *) (intptr_t) 'B'); t30_set_phase_e_handler(&t38_state_b.t30_state, phase_e_handler, (void *) (intptr_t) 'B'); t30_set_ecm_capability(&t38_state_b.t30_state, use_ecm); if (use_ecm) t30_set_supported_compressions(&t38_state_b.t30_state, T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION | T30_SUPPORT_T6_COMPRESSION); for (;;) { span_log_bump_samples(&t38_state_a.logging, SAMPLES_PER_CHUNK); span_log_bump_samples(&t38_state_a.t38.logging, SAMPLES_PER_CHUNK); span_log_bump_samples(&t38_state_a.t30_state.logging, SAMPLES_PER_CHUNK); span_log_bump_samples(&t38_state_b.logging, SAMPLES_PER_CHUNK); span_log_bump_samples(&t38_state_b.t38.logging, SAMPLES_PER_CHUNK); span_log_bump_samples(&t38_state_b.t30_state.logging, SAMPLES_PER_CHUNK); done[0] = t38_terminal_send_timeout(&t38_state_a, SAMPLES_PER_CHUNK); done[1] = t38_terminal_send_timeout(&t38_state_b, SAMPLES_PER_CHUNK); while ((msg_len = ip_network_model_get(path_a_to_b, SAMPLES_PER_CHUNK, msg, 1024, &seq_no)) >= 0) { t38_core_rx_ifp_packet(&t38_state_b.t38, seq_no, msg, msg_len); } while ((msg_len = ip_network_model_get(path_b_to_a, SAMPLES_PER_CHUNK, msg, 1024, &seq_no)) >= 0) { t38_core_rx_ifp_packet(&t38_state_a.t38, seq_no, msg, msg_len); } if (done[0] && done[1]) break; } if (!succeeded[0] || !succeeded[1]) { printf("Tests failed\n"); exit(2); } printf("Tests passed\n"); return 0; }
static int t30_tests(int t38_mode, int use_ecm, int use_gui, int log_audio, int test_sending, int g1050_model_no, int g1050_speed_pattern_no) { t38_terminal_state_t *t38_state; fax_state_t *fax_state; uint8_t msg[1024]; char buf[1024]; int len; int msg_len; int t30_len; int t31_len; int t38_version; int without_pacing; int use_tep; int seq_no; double tx_when; double rx_when; t30_state_t *t30; t38_core_state_t *t38_core; logging_state_t *logging; int k; int outframes; int ret; int16_t t30_amp[SAMPLES_PER_CHUNK]; int16_t t31_amp[SAMPLES_PER_CHUNK]; int16_t silence[SAMPLES_PER_CHUNK]; int16_t out_amp[2*SAMPLES_PER_CHUNK]; SNDFILE *wave_handle; SNDFILE *in_handle; at_state_t *at_state; #if defined(WIN32) DWORD read_bytes; OVERLAPPED o; #endif /* Test the T.31 modem against the full FAX machine in spandsp */ /* Set up the test environment */ t38_version = 1; without_pacing = FALSE; use_tep = FALSE; wave_handle = NULL; if (log_audio) { if ((wave_handle = sf_open_telephony_write(OUTPUT_WAVE_FILE_NAME, 2)) == NULL) { fprintf(stderr, " Cannot create audio file '%s'\n", OUTPUT_WAVE_FILE_NAME); exit(2); } } in_handle = NULL; if (decode_test_file) { if ((in_handle = sf_open_telephony_read(decode_test_file, 1)) == NULL) { fprintf(stderr, " Cannot create audio file '%s'\n", decode_test_file); exit(2); } } srand48(0x1234567); if ((path_a_to_b = g1050_init(g1050_model_no, g1050_speed_pattern_no, 100, 33)) == NULL) { fprintf(stderr, "Failed to start IP network path model\n"); exit(2); } if ((path_b_to_a = g1050_init(g1050_model_no, g1050_speed_pattern_no, 100, 33)) == NULL) { fprintf(stderr, "Failed to start IP network path model\n"); exit(2); } t38_state = NULL; fax_state = NULL; if (test_sending) { if (t38_mode) { if ((t38_state = t38_terminal_init(NULL, FALSE, t38_tx_packet_handler, t31_state)) == NULL) { fprintf(stderr, "Cannot start the T.38 channel\n"); exit(2); } t30 = t38_terminal_get_t30_state(t38_state); } else { fax_state = fax_init(NULL, FALSE); t30 = fax_get_t30_state(fax_state); } t30_set_rx_file(t30, OUTPUT_FILE_NAME, -1); countdown = 0; } else { if (t38_mode) { if ((t38_state = t38_terminal_init(NULL, TRUE, t38_tx_packet_handler, t31_state)) == NULL) { fprintf(stderr, "Cannot start the T.38 channel\n"); exit(2); } t30 = t38_terminal_get_t30_state(t38_state); } else { fax_state = fax_init(NULL, TRUE); t30 = fax_get_t30_state(fax_state); } t30_set_tx_file(t30, INPUT_FILE_NAME, -1, -1); countdown = 250; } t30_set_ecm_capability(t30, use_ecm); if (t38_mode) { t38_core = t38_terminal_get_t38_core_state(t38_state); t38_set_t38_version(t38_core, t38_version); t38_terminal_set_config(t38_state, without_pacing); t38_terminal_set_tep_mode(t38_state, use_tep); } t30_set_tx_ident(t30, "11111111"); t30_set_supported_modems(t30, T30_SUPPORT_V27TER | T30_SUPPORT_V29 | T30_SUPPORT_V17); //t30_set_tx_nsf(t30, (const uint8_t *) "\x50\x00\x00\x00Spandsp\x00", 12); t30_set_phase_b_handler(t30, phase_b_handler, (void *) 'A'); t30_set_phase_d_handler(t30, phase_d_handler, (void *) 'A'); t30_set_phase_e_handler(t30, phase_e_handler, (void *) 'A'); if (t38_mode) logging = t38_terminal_get_logging_state(t38_state); else logging = t30_get_logging_state(t30); span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(logging, (t38_mode) ? "T.38" : "FAX"); if (t38_mode) { t38_core = t38_terminal_get_t38_core_state(t38_state); logging = t38_core_get_logging_state(t38_core); span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(logging, "T.38"); logging = t30_get_logging_state(t30); span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(logging, "T.38"); } else { logging = fax_get_logging_state(fax_state); span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(logging, "FAX"); } memset(silence, 0, sizeof(silence)); memset(t30_amp, 0, sizeof(t30_amp)); /* Now set up and run the T.31 modem */ if ((t31_state = t31_init(NULL, at_tx_handler, &modem[0], t31_call_control, &modem[0], t31_tx_packet_handler, NULL)) == NULL) { fprintf(stderr, " Cannot start the T.31 modem\n"); exit(2); } at_state = t31_get_at_state(t31_state); logging = t31_get_logging_state(t31_state); span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(logging, "T.31"); logging = at_get_logging_state(at_state); span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(logging, "T.31"); if (t38_mode) { t38_core = t31_get_t38_core_state(t31_state); logging = t38_core_get_logging_state(t38_core); span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(logging, "T.31"); t31_set_mode(t31_state, TRUE); t38_set_t38_version(t38_core, t38_version); } at_reset_call_info(at_state); at_set_call_info(at_state, "DATE", "1231"); at_set_call_info(at_state, "TIME", "1200"); at_set_call_info(at_state, "NAME", "Name"); at_set_call_info(at_state, "NMBR", "123456789"); at_set_call_info(at_state, "ANID", "987654321"); at_set_call_info(at_state, "USER", "User"); at_set_call_info(at_state, "CDID", "234567890"); at_set_call_info(at_state, "NDID", "345678901"); #if defined(ENABLE_GUI) if (use_gui) start_media_monitor(); #endif while (!done) { /* Deal with call setup, through the AT interface. */ if (test_sending) { } else { if (answered == 0) { if (--countdown == 0) { t31_call_event(t31_state, AT_CALL_EVENT_ALERTING); countdown = 250; } } else if (answered == 1) { printf("ZZZ\n"); answered = 2; t31_call_event(t31_state, AT_CALL_EVENT_ANSWERED); } } ret = modem_wait_sock(modem[0].master, 20, MODEM_POLL_READ); if ((ret & MODEM_POLL_READ)) { #if defined(WIN32) o.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); /* Initialize the rest of the OVERLAPPED structure to zero. */ o.Internal = 0; o.InternalHigh = 0; o.Offset = 0; o.OffsetHigh = 0; assert(o.hEvent); if (!ReadFile(modem->master, buf, avail, &read_bytes, &o)) GetOverlappedResult(modem->master, &o, &read_bytes, TRUE); CloseHandle (o.hEvent); if ((len = read_bytes)) #else if ((len = read(modem[0].master, buf, 1024))) #endif { int i; printf("YYY %d - ", len); for (i = 0; i < len; i++) printf(" 0x%02x", buf[i] & 0xFF); printf("\n"); t31_at_rx(t31_state, buf, len); } } if (answered == 2) { if (t38_mode) { while ((msg_len = g1050_get(path_a_to_b, msg, 1024, when, &seq_no, &tx_when, &rx_when)) >= 0) { #if defined(ENABLE_GUI) if (use_gui) media_monitor_rx(seq_no, tx_when, rx_when); #endif t38_core = t31_get_t38_core_state(t31_state); t38_core_rx_ifp_packet(t38_core, msg, msg_len, seq_no); } while ((msg_len = g1050_get(path_b_to_a, msg, 1024, when, &seq_no, &tx_when, &rx_when)) >= 0) { #if defined(ENABLE_GUI) if (use_gui) media_monitor_rx(seq_no, tx_when, rx_when); #endif t38_core = t38_terminal_get_t38_core_state(t38_state); t38_core_rx_ifp_packet(t38_core, msg, msg_len, seq_no); } #if defined(ENABLE_GUI) if (use_gui) media_monitor_update_display(); #endif /* Bump the G.1050 models along */ when += (float) SAMPLES_PER_CHUNK/(float) SAMPLE_RATE; /* Bump things along on the t38_terminal side */ span_log_bump_samples(t38_terminal_get_logging_state(t38_state), SAMPLES_PER_CHUNK); t38_core = t38_terminal_get_t38_core_state(t38_state); span_log_bump_samples(t38_core_get_logging_state(t38_core), SAMPLES_PER_CHUNK); t38_terminal_send_timeout(t38_state, SAMPLES_PER_CHUNK); t31_t38_send_timeout(t31_state, SAMPLES_PER_CHUNK); } else { t30_len = fax_tx(fax_state, t30_amp, SAMPLES_PER_CHUNK); /* The receive side always expects a full block of samples, but the transmit side may not be sending any when it doesn't need to. We may need to pad with some silence. */ if (t30_len < SAMPLES_PER_CHUNK) { memset(t30_amp + t30_len, 0, sizeof(int16_t)*(SAMPLES_PER_CHUNK - t30_len)); t30_len = SAMPLES_PER_CHUNK; } if (log_audio) { for (k = 0; k < t30_len; k++) out_amp[2*k] = t30_amp[k]; } if (t31_rx(t31_state, t30_amp, t30_len)) break; t31_len = t31_tx(t31_state, t31_amp, SAMPLES_PER_CHUNK); if (t31_len < SAMPLES_PER_CHUNK) { memset(t31_amp + t31_len, 0, sizeof(int16_t)*(SAMPLES_PER_CHUNK - t31_len)); t31_len = SAMPLES_PER_CHUNK; } if (log_audio) { for (k = 0; k < t31_len; k++) out_amp[2*k + 1] = t31_amp[k]; } if (fax_rx(fax_state, t31_amp, SAMPLES_PER_CHUNK)) break; if (log_audio) { outframes = sf_writef_short(wave_handle, out_amp, SAMPLES_PER_CHUNK); if (outframes != SAMPLES_PER_CHUNK) break; } /* Bump things along on the FAX machine side */ span_log_bump_samples(fax_get_logging_state(fax_state), SAMPLES_PER_CHUNK); } /* Bump things along on the FAX machine side */ span_log_bump_samples(t30_get_logging_state(t30), SAMPLES_PER_CHUNK); /* Bump things along on the T.31 modem side */ t38_core = t31_get_t38_core_state(t31_state); span_log_bump_samples(t38_core_get_logging_state(t38_core), SAMPLES_PER_CHUNK); span_log_bump_samples(t31_get_logging_state(t31_state), SAMPLES_PER_CHUNK); span_log_bump_samples(at_get_logging_state(t31_get_at_state(t31_state)), SAMPLES_PER_CHUNK); } } if (t38_mode) t38_terminal_release(t38_state); if (decode_test_file) { if (sf_close_telephony(in_handle)) { fprintf(stderr, " Cannot close audio file '%s'\n", decode_test_file); exit(2); } } if (log_audio) { if (sf_close_telephony(wave_handle)) { fprintf(stderr, " Cannot close audio file '%s'\n", OUTPUT_WAVE_FILE_NAME); exit(2); } } if (!done) { printf("Tests failed\n"); return 2; } return 0; }
static void exchange(faxtester_state_t *s) { int16_t amp[SAMPLES_PER_CHUNK]; int16_t out_amp[2*SAMPLES_PER_CHUNK]; int len; int i; int total_audio_time; logging_state_t *logging; output_tiff_file_name = OUTPUT_TIFF_FILE_NAME; if (log_audio) { if ((out_handle = sf_open_telephony_write(OUTPUT_WAVE_FILE_NAME, 2)) == NULL) { fprintf(stderr, " Cannot create audio file '%s'\n", OUTPUT_WAVE_FILE_NAME); printf("Test failed\n"); exit(2); } /*endif*/ } /*endif*/ total_audio_time = 0; faxtester_set_transmit_on_idle(s, true); s->far_fax = fax_init(NULL, false); s->far_t30 = fax_get_t30_state(s->far_fax); s->far_tag = 'A'; if (s->far_fax) logging = fax_get_logging_state(s->far_fax); else logging = t38_terminal_get_logging_state(s->far_t38); span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME | SPAN_LOG_FLOW); span_log_set_tag(logging, "A"); logging = t30_get_logging_state(s->far_t30); span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME | SPAN_LOG_FLOW); span_log_set_tag(logging, "A"); #if 0 span_log_set_level(&fax.modems.v27ter_rx.logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME | SPAN_LOG_FLOW); span_log_set_tag(&fax.modems.v27ter_rx.logging, "A"); span_log_set_level(&fax.modems.v29_rx.logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME | SPAN_LOG_FLOW); span_log_set_tag(&fax.modems.v29_rx.logging, "A"); span_log_set_level(&fax.modems.v17_rx.logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME | SPAN_LOG_FLOW); span_log_set_tag(&fax.modems.v17_rx.logging, "A"); #endif while (faxtester_next_step(s) == 0) ; /*endwhile*/ for (;;) { len = fax_tx(s->far_fax, amp, SAMPLES_PER_CHUNK); faxtester_rx(s, amp, len); if (log_audio) { for (i = 0; i < len; i++) out_amp[2*i + 0] = amp[i]; /*endfor*/ } /*endif*/ total_audio_time += SAMPLES_PER_CHUNK; logging = t30_get_logging_state(s->far_t30); span_log_bump_samples(logging, len); #if 0 span_log_bump_samples(&fax.modems.v27ter_rx.logging, len); span_log_bump_samples(&fax.modems.v29_rx.logging, len); span_log_bump_samples(&fax.modems.v17_rx.logging, len); #endif logging = fax_get_logging_state(s->far_fax); span_log_bump_samples(logging, len); logging = faxtester_get_logging_state(s); span_log_bump_samples(logging, len); len = faxtester_tx(s, amp, SAMPLES_PER_CHUNK); if (fax_rx(s->far_fax, amp, len)) break; /*endif*/ if (log_audio) { for (i = 0; i < len; i++) out_amp[2*i + 1] = amp[i]; /*endfor*/ if (sf_writef_short(out_handle, out_amp, SAMPLES_PER_CHUNK) != SAMPLES_PER_CHUNK) break; /*endif*/ } /*endif*/ if (s->test_for_call_clear && !s->far_end_cleared_call) { s->call_clear_timer += len; if (!t30_call_active(s->far_t30)) { span_log(faxtester_get_logging_state(s), SPAN_LOG_FLOW, "Far end cleared after %dms (limits %dms to %dms)\n", s->call_clear_timer/8, s->timein_x, s->timeout); if (s->call_clear_timer/8 < s->timein_x || s->call_clear_timer/8 > s->timeout_x) { printf("Test failed\n"); exit(2); } span_log(faxtester_get_logging_state(s), SPAN_LOG_FLOW, "Clear time OK\n"); s->far_end_cleared_call = true; s->test_for_call_clear = false; while (faxtester_next_step(s) == 0) ; /*endwhile*/ } /*endif*/ } /*endif*/ } /*endfor*/ if (log_audio) { if (sf_close_telephony(out_handle)) { fprintf(stderr, " Cannot close audio file '%s'\n", OUTPUT_WAVE_FILE_NAME); printf("Test failed\n"); exit(2); } /*endif*/ } /*endif*/ }
static int t30_tests(int t38_mode, int use_gui, int log_audio, int test_sending, int g1050_model_no, int g1050_speed_pattern_no) { t38_terminal_state_t *t38_state; fax_state_t *fax_state; int fast_send; int fast_send_tcf; int fast_blocks; int msg_len; int t30_len; int t31_len; int t38_version; int without_pacing; int use_tep; int seq_no; int i; int k; int outframes; uint8_t fast_buf[1000]; uint8_t msg[1024]; double tx_when; double rx_when; t30_state_t *t30; t38_core_state_t *t38_core; logging_state_t *logging; int16_t t30_amp[SAMPLES_PER_CHUNK]; int16_t t31_amp[SAMPLES_PER_CHUNK]; int16_t silence[SAMPLES_PER_CHUNK]; int16_t out_amp[2*SAMPLES_PER_CHUNK]; SNDFILE *wave_handle; SNDFILE *in_handle; /* Test the T.31 modem against the full FAX machine in spandsp */ /* Set up the test environment */ t38_version = 1; without_pacing = false; use_tep = false; wave_handle = NULL; if (log_audio) { if ((wave_handle = sf_open_telephony_write(OUTPUT_WAVE_FILE_NAME, 2)) == NULL) { fprintf(stderr, " Cannot create audio file '%s'\n", OUTPUT_WAVE_FILE_NAME); exit(2); } } in_handle = NULL; if (decode_test_file) { if ((in_handle = sf_open_telephony_read(decode_test_file, 1)) == NULL) { fprintf(stderr, " Cannot create audio file '%s'\n", decode_test_file); exit(2); } } srand48(0x1234567); if ((path_a_to_b = g1050_init(g1050_model_no, g1050_speed_pattern_no, 100, 33)) == NULL) { fprintf(stderr, "Failed to start IP network path model\n"); exit(2); } if ((path_b_to_a = g1050_init(g1050_model_no, g1050_speed_pattern_no, 100, 33)) == NULL) { fprintf(stderr, "Failed to start IP network path model\n"); exit(2); } t38_state = NULL; fax_state = NULL; if (test_sending) { if (t38_mode) { if ((t38_state = t38_terminal_init(NULL, false, t38_tx_packet_handler, t31_state)) == NULL) { fprintf(stderr, "Cannot start the T.38 channel\n"); exit(2); } t30 = t38_terminal_get_t30_state(t38_state); } else { fax_state = fax_init(NULL, false); t30 = fax_get_t30_state(fax_state); } t30_set_rx_file(t30, OUTPUT_FILE_NAME, -1); fax_test_seq = fax_send_test_seq; countdown = 0; } else { if (t38_mode) { if ((t38_state = t38_terminal_init(NULL, true, t38_tx_packet_handler, t31_state)) == NULL) { fprintf(stderr, "Cannot start the T.38 channel\n"); exit(2); } t30 = t38_terminal_get_t30_state(t38_state); } else { fax_state = fax_init(NULL, true); t30 = fax_get_t30_state(fax_state); } t30_set_tx_file(t30, INPUT_FILE_NAME, -1, -1); fax_test_seq = fax_receive_test_seq; countdown = 250; } if (t38_mode) { t38_core = t38_terminal_get_t38_core_state(t38_state); t38_set_t38_version(t38_core, t38_version); t38_terminal_set_config(t38_state, without_pacing); t38_terminal_set_tep_mode(t38_state, use_tep); } t30_set_tx_ident(t30, "11111111"); t30_set_supported_modems(t30, T30_SUPPORT_V27TER | T30_SUPPORT_V29 | T30_SUPPORT_V17); //t30_set_tx_nsf(t30, (const uint8_t *) "\x50\x00\x00\x00Spandsp\x00", 12); t30_set_phase_b_handler(t30, phase_b_handler, (void *) 'A'); t30_set_phase_d_handler(t30, phase_d_handler, (void *) 'A'); t30_set_phase_e_handler(t30, phase_e_handler, (void *) 'A'); if (t38_mode) logging = t38_terminal_get_logging_state(t38_state); else logging = t30_get_logging_state(t30); span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(logging, (t38_mode) ? "T.38" : "FAX"); if (t38_mode) { t38_core = t38_terminal_get_t38_core_state(t38_state); span_log_set_level(&t38_core->logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(&t38_core->logging, "T.38"); logging = t30_get_logging_state(t30); span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(logging, "T.38"); } else { logging = fax_get_logging_state(fax_state); span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(logging, "FAX"); } memset(silence, 0, sizeof(silence)); memset(t30_amp, 0, sizeof(t30_amp)); /* Now set up and run the T.31 modem */ if ((t31_state = t31_init(NULL, at_tx_handler, NULL, modem_call_control, NULL, t31_tx_packet_handler, NULL)) == NULL) { fprintf(stderr, " Cannot start the T.31 modem\n"); exit(2); } logging = t31_get_logging_state(t31_state); span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(logging, "T.31"); logging = at_get_logging_state(t31_get_at_state(t31_state)); span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(logging, "T.31"); if (t38_mode) { t38_core = t31_get_t38_core_state(t31_state); logging = t38_core_get_logging_state(t38_core); span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(logging, "T.31"); t31_set_mode(t31_state, true); t38_set_t38_version(t38_core, t38_version); } fast_send = false; fast_send_tcf = true; fast_blocks = 0; kick = true; #if defined(ENABLE_GUI) if (use_gui) start_media_monitor(); #endif while (!done) { if (countdown) { /* Deal with call setup, through the AT interface. */ if (answered) { countdown = 0; t31_call_event(t31_state, AT_CALL_EVENT_ANSWERED); } else if (--countdown == 0) { t31_call_event(t31_state, AT_CALL_EVENT_ALERTING); countdown = 250; } } if (kick) { /* Work through the script */ kick = false; if (fax_test_seq[test_seq_ptr].command > (const char *) 2) { if (fax_test_seq[test_seq_ptr].command[0]) { printf("%s\n", fax_test_seq[test_seq_ptr].command); t31_at_rx(t31_state, fax_test_seq[test_seq_ptr].command, fax_test_seq[test_seq_ptr].len_command); } } else { if (fax_test_seq[test_seq_ptr].command == (const char *) 2) { printf("Fast send TCF\n"); fast_send = true; fast_send_tcf = true; fast_blocks = 100; } else { printf("Fast send image\n"); fast_send = true; fast_send_tcf = false; fast_blocks = 100; } } } if (fast_send) { /* Send fast modem data */ if (fast_send_tcf) { /* If we are sending TCF, its simply zeros */ memset(fast_buf, 0, 36); if (fast_blocks == 1) { /* Tell the modem this is the end of the TCF data */ fast_buf[34] = DLE; fast_buf[35] = ETX; } } else { /* If we are sending image data, we need to make it look like genuine image data, with proper EOL and RTC markers. */ if (fast_blocks > 1) { /* Create a chunk of white page, 1728 pixels wide. */ for (i = 0; i < 36; i += 4) { fast_buf[i] = 0x00; fast_buf[i + 1] = 0x80; fast_buf[i + 2] = 0xB2; fast_buf[i + 3] = 0x01; } } else { /* Create the end of page condition. */ for (i = 0; i < 36; i += 3) { fast_buf[i] = 0x00; fast_buf[i + 1] = 0x08; fast_buf[i + 2] = 0x80; } /* Tell the modem this is the end of the image data. */ fast_buf[34] = DLE; fast_buf[35] = ETX; } } t31_at_rx(t31_state, (char *) fast_buf, 36); if (--fast_blocks == 0) fast_send = false; } if (t38_mode) { while ((msg_len = g1050_get(path_a_to_b, msg, 1024, when, &seq_no, &tx_when, &rx_when)) >= 0) { #if defined(ENABLE_GUI) if (use_gui) media_monitor_rx(seq_no, tx_when, rx_when); #endif t38_core = t31_get_t38_core_state(t31_state); t38_core_rx_ifp_packet(t38_core, msg, msg_len, seq_no); } while ((msg_len = g1050_get(path_b_to_a, msg, 1024, when, &seq_no, &tx_when, &rx_when)) >= 0) { #if defined(ENABLE_GUI) if (use_gui) media_monitor_rx(seq_no, tx_when, rx_when); #endif t38_core = t38_terminal_get_t38_core_state(t38_state); t38_core_rx_ifp_packet(t38_core, msg, msg_len, seq_no); } #if defined(ENABLE_GUI) if (use_gui) media_monitor_update_display(); #endif /* Bump the G.1050 models along */ when += (float) SAMPLES_PER_CHUNK/(float) SAMPLE_RATE; /* Bump things along on the t38_terminal side */ span_log_bump_samples(t38_terminal_get_logging_state(t38_state), SAMPLES_PER_CHUNK); t38_core = t38_terminal_get_t38_core_state(t38_state); span_log_bump_samples(t38_core_get_logging_state(t38_core), SAMPLES_PER_CHUNK); t38_terminal_send_timeout(t38_state, SAMPLES_PER_CHUNK); t31_t38_send_timeout(t31_state, SAMPLES_PER_CHUNK); } else { t30_len = fax_tx(fax_state, t30_amp, SAMPLES_PER_CHUNK); /* The receive side always expects a full block of samples, but the transmit side may not be sending any when it doesn't need to. We may need to pad with some silence. */ if (t30_len < SAMPLES_PER_CHUNK) { memset(t30_amp + t30_len, 0, sizeof(int16_t)*(SAMPLES_PER_CHUNK - t30_len)); t30_len = SAMPLES_PER_CHUNK; } if (log_audio) { for (k = 0; k < t30_len; k++) out_amp[2*k] = t30_amp[k]; } if (t31_rx(t31_state, t30_amp, t30_len)) break; t31_len = t31_tx(t31_state, t31_amp, SAMPLES_PER_CHUNK); if (t31_len < SAMPLES_PER_CHUNK) { memset(t31_amp + t31_len, 0, sizeof(int16_t)*(SAMPLES_PER_CHUNK - t31_len)); t31_len = SAMPLES_PER_CHUNK; } if (log_audio) { for (k = 0; k < t31_len; k++) out_amp[2*k + 1] = t31_amp[k]; } if (fax_rx(fax_state, t31_amp, SAMPLES_PER_CHUNK)) break; if (log_audio) { outframes = sf_writef_short(wave_handle, out_amp, SAMPLES_PER_CHUNK); if (outframes != SAMPLES_PER_CHUNK) break; } /* Bump things along on the FAX machine side */ span_log_bump_samples(fax_get_logging_state(fax_state), SAMPLES_PER_CHUNK); } /* Bump things along on the FAX machine side */ span_log_bump_samples(t30_get_logging_state(t30), SAMPLES_PER_CHUNK); /* Bump things along on the T.31 modem side */ t38_core = t31_get_t38_core_state(t31_state); span_log_bump_samples(t38_core_get_logging_state(t38_core), SAMPLES_PER_CHUNK); span_log_bump_samples(t31_get_logging_state(t31_state), SAMPLES_PER_CHUNK); span_log_bump_samples(at_get_logging_state(t31_get_at_state(t31_state)), SAMPLES_PER_CHUNK); } if (t38_mode) t38_terminal_release(t38_state); if (decode_test_file) { if (sf_close_telephony(in_handle)) { fprintf(stderr, " Cannot close audio file '%s'\n", decode_test_file); exit(2); } } if (log_audio) { if (sf_close_telephony(wave_handle)) { fprintf(stderr, " Cannot close audio file '%s'\n", OUTPUT_WAVE_FILE_NAME); exit(2); } } if (!done || !sequence_terminated) { printf("Tests failed\n"); return -1; } return 0; }
static int t38_tx_packet_handler(t38_core_state_t *s, void *user_data, const uint8_t *buf, int len, int count) { struct ast_channel *chan = (struct ast_channel *) user_data; struct ast_frame outf = { .frametype = AST_FRAME_MODEM, .subclass.integer = AST_MODEM_T38, .src = __FUNCTION__, }; /* TODO: Asterisk does not provide means of resending the same packet multiple times so count is ignored at the moment */ AST_FRAME_SET_BUFFER(&outf, buf, 0, len); if (ast_write(chan, &outf) < 0) { ast_log(LOG_WARNING, "Unable to write frame to channel; %s\n", strerror(errno)); return -1; } return 0; } static void phase_e_handler(t30_state_t *f, void *user_data, int result) { const char *local_ident; const char *far_ident; char buf[20]; fax_session *s = (fax_session *) user_data; t30_stats_t stat; int pages_transferred; ast_debug(1, "Fax phase E handler. result=%d\n", result); t30_get_transfer_statistics(f, &stat); s = (fax_session *) user_data; if (result != T30_ERR_OK) { s->finished = -1; /* FAXSTATUS is already set to FAILED */ pbx_builtin_setvar_helper(s->chan, "FAXERROR", t30_completion_code_to_str(result)); ast_log(LOG_WARNING, "Error transmitting fax. result=%d: %s.\n", result, t30_completion_code_to_str(result)); return; } s->finished = 1; local_ident = S_OR(t30_get_tx_ident(f), ""); far_ident = S_OR(t30_get_rx_ident(f), ""); pbx_builtin_setvar_helper(s->chan, "FAXSTATUS", "SUCCESS"); pbx_builtin_setvar_helper(s->chan, "FAXERROR", NULL); pbx_builtin_setvar_helper(s->chan, "REMOTESTATIONID", far_ident); #if SPANDSP_RELEASE_DATE >= 20090220 pages_transferred = (s->direction) ? stat.pages_tx : stat.pages_rx; #else pages_transferred = stat.pages_transferred; #endif snprintf(buf, sizeof(buf), "%d", pages_transferred); pbx_builtin_setvar_helper(s->chan, "FAXPAGES", buf); snprintf(buf, sizeof(buf), "%d", stat.y_resolution); pbx_builtin_setvar_helper(s->chan, "FAXRESOLUTION", buf); snprintf(buf, sizeof(buf), "%d", stat.bit_rate); pbx_builtin_setvar_helper(s->chan, "FAXBITRATE", buf); ast_debug(1, "Fax transmitted successfully.\n"); ast_debug(1, " Remote station ID: %s\n", far_ident); ast_debug(1, " Pages transferred: %d\n", pages_transferred); ast_debug(1, " Image resolution: %d x %d\n", stat.x_resolution, stat.y_resolution); ast_debug(1, " Transfer Rate: %d\n", stat.bit_rate); ast_manager_event(s->chan, EVENT_FLAG_CALL, s->direction ? "FaxSent" : "FaxReceived", "Channel: %s\r\n" "Exten: %s\r\n" "CallerID: %s\r\n" "CallerIDName: %s\r\n" "ConnectedLineNum: %s\r\n" "ConnectedLineName: %s\r\n" "RemoteStationID: %s\r\n" "LocalStationID: %s\r\n" "PagesTransferred: %d\r\n" "Resolution: %d\r\n" "TransferRate: %d\r\n" "FileName: %s\r\n", ast_channel_name(s->chan), ast_channel_exten(s->chan), S_COR(ast_channel_caller(s->chan)->id.number.valid, ast_channel_caller(s->chan)->id.number.str, ""), S_COR(ast_channel_caller(s->chan)->id.name.valid, ast_channel_caller(s->chan)->id.name.str, ""), S_COR(ast_channel_connected(s->chan)->id.number.valid, ast_channel_connected(s->chan)->id.number.str, ""), S_COR(ast_channel_connected(s->chan)->id.name.valid, ast_channel_connected(s->chan)->id.name.str, ""), far_ident, local_ident, pages_transferred, stat.y_resolution, stat.bit_rate, s->file_name); } /* === Helper functions to configure fax === */ /* Setup SPAN logging according to Asterisk debug level */ static int set_logging(logging_state_t *state) { int level = SPAN_LOG_WARNING + option_debug; span_log_set_message_handler(state, span_message); span_log_set_level(state, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | level); return 0; }
int main(int argc, char *argv[]) { int16_t t38_amp_b[SAMPLES_PER_CHUNK]; int16_t t30_amp_b[SAMPLES_PER_CHUNK]; int16_t out_amp[2*SAMPLES_PER_CHUNK]; int t38_len_b; int t30_len_b; int msg_len; uint8_t msg[1024]; int log_audio; int outframes; SNDFILE *wave_handle; int t38_version; int use_ecm; int use_tep; int feedback_audio; int use_transmit_on_idle; const char *input_file_name; int i; int seq_no; int g1050_model_no; int g1050_speed_pattern_no; double tx_when; double rx_when; int use_gui; int supported_modems; int opt; t30_state_t *t30; t38_core_state_t *t38_core; logging_state_t *logging; log_audio = false; t38_version = 1; use_ecm = false; input_file_name = INPUT_FILE_NAME; simulate_incrementing_repeats = false; g1050_model_no = 0; g1050_speed_pattern_no = 1; use_gui = false; use_tep = false; feedback_audio = false; use_transmit_on_idle = true; supported_modems = T30_SUPPORT_V27TER | T30_SUPPORT_V29 | T30_SUPPORT_V17; while ((opt = getopt(argc, argv, "efgi:Ilm:M:s:tv:")) != -1) { switch (opt) { case 'e': use_ecm = true; break; case 'f': feedback_audio = true; break; case 'g': #if defined(ENABLE_GUI) use_gui = true; #else fprintf(stderr, "Graphical monitoring not available\n"); exit(2); #endif break; case 'i': input_file_name = optarg; break; case 'I': simulate_incrementing_repeats = true; break; case 'l': log_audio = true; break; case 'm': supported_modems = atoi(optarg); break; case 'M': g1050_model_no = optarg[0] - 'A' + 1; break; case 's': g1050_speed_pattern_no = atoi(optarg); break; case 't': use_tep = true; break; case 'v': t38_version = atoi(optarg); break; default: //usage(); exit(2); break; } } printf("Using T.38 version %d\n", t38_version); if (use_ecm) printf("Using ECM\n"); wave_handle = NULL; if (log_audio) { if ((wave_handle = sf_open_telephony_write(OUTPUT_FILE_NAME_WAVE, 2)) == NULL) { fprintf(stderr, " Cannot create audio file '%s'\n", OUTPUT_FILE_NAME_WAVE); exit(2); } } srand48(0x1234567); if ((path_a_to_b = g1050_init(g1050_model_no, g1050_speed_pattern_no, 100, 33)) == NULL) { fprintf(stderr, "Failed to start IP network path model\n"); exit(2); } if ((path_b_to_a = g1050_init(g1050_model_no, g1050_speed_pattern_no, 100, 33)) == NULL) { fprintf(stderr, "Failed to start IP network path model\n"); exit(2); } if ((t38_state_a = t38_terminal_init(NULL, true, tx_packet_handler_a, &t38_state_b)) == NULL) { fprintf(stderr, "Cannot start the T.38 channel\n"); exit(2); } t30 = t38_terminal_get_t30_state(t38_state_a); t38_core = t38_terminal_get_t38_core_state(t38_state_a); t38_set_t38_version(t38_core, t38_version); logging = t38_terminal_get_logging_state(t38_state_a); span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(logging, "T.38-A"); logging = t38_core_get_logging_state(t38_core); span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(logging, "T.38-A"); logging = t30_get_logging_state(t30); span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(logging, "T.38-A"); t30_set_supported_modems(t30, supported_modems); t30_set_tx_ident(t30, "11111111"); t30_set_tx_file(t30, input_file_name, -1, -1); t30_set_phase_b_handler(t30, phase_b_handler, (void *) (intptr_t) 'A'); t30_set_phase_d_handler(t30, phase_d_handler, (void *) (intptr_t) 'A'); t30_set_phase_e_handler(t30, phase_e_handler, (void *) (intptr_t) 'A'); t30_set_ecm_capability(t30, use_ecm); if (use_ecm) t30_set_supported_compressions(t30, T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION | T30_SUPPORT_T6_COMPRESSION); if ((t38_state_b = t38_gateway_init(NULL, tx_packet_handler_b, &t38_state_a)) == NULL) { fprintf(stderr, "Cannot start the T.38 channel\n"); exit(2); } t38_core = t38_gateway_get_t38_core_state(t38_state_b); t38_gateway_set_transmit_on_idle(t38_state_b, use_transmit_on_idle); t38_set_t38_version(t38_core, t38_version); t38_gateway_set_ecm_capability(t38_state_b, use_ecm); logging = t38_gateway_get_logging_state(t38_state_b); span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(logging, "T.38-B"); logging = t38_core_get_logging_state(t38_core); span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(logging, "T.38-B"); memset(t38_amp_b, 0, sizeof(t38_amp_b)); if ((fax_state_b = fax_init(NULL, false)) == NULL) { fprintf(stderr, "Cannot start FAX\n"); exit(2); } t30 = fax_get_t30_state(fax_state_b); fax_set_transmit_on_idle(fax_state_b, use_transmit_on_idle); fax_set_tep_mode(fax_state_b, use_tep); t30_set_supported_modems(t30, supported_modems); t30_set_tx_ident(t30, "22222222"); t30_set_tx_nsf(t30, (const uint8_t *) "\x50\x00\x00\x00Spandsp\x00", 12); t30_set_rx_file(t30, OUTPUT_FILE_NAME, -1); t30_set_phase_b_handler(t30, phase_b_handler, (void *) (intptr_t) 'B'); t30_set_phase_d_handler(t30, phase_d_handler, (void *) (intptr_t) 'B'); t30_set_phase_e_handler(t30, phase_e_handler, (void *) (intptr_t) 'B'); t30_set_ecm_capability(t30, use_ecm); if (use_ecm) t30_set_supported_compressions(t30, T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION | T30_SUPPORT_T6_COMPRESSION); logging = fax_get_logging_state(fax_state_b); span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(logging, "FAX-B "); logging = t30_get_logging_state(t30); span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_tag(logging, "FAX-B "); memset(t30_amp_b, 0, sizeof(t30_amp_b)); #if defined(ENABLE_GUI) if (use_gui) start_media_monitor(); #endif for (;;) { logging = t38_terminal_get_logging_state(t38_state_a); span_log_bump_samples(logging, SAMPLES_PER_CHUNK); t38_core = t38_terminal_get_t38_core_state(t38_state_a); logging = t38_core_get_logging_state(t38_core); span_log_bump_samples(logging, SAMPLES_PER_CHUNK); t30 = t38_terminal_get_t30_state(t38_state_a); logging = t30_get_logging_state(t30); span_log_bump_samples(logging, SAMPLES_PER_CHUNK); logging = t38_gateway_get_logging_state(t38_state_b); span_log_bump_samples(logging, SAMPLES_PER_CHUNK); t38_core = t38_gateway_get_t38_core_state(t38_state_b); logging = t38_core_get_logging_state(t38_core); span_log_bump_samples(logging, SAMPLES_PER_CHUNK); logging = fax_get_logging_state(fax_state_b); span_log_bump_samples(logging, SAMPLES_PER_CHUNK); t30 = fax_get_t30_state(fax_state_b); logging = t30_get_logging_state(t30); span_log_bump_samples(logging, SAMPLES_PER_CHUNK); memset(out_amp, 0, sizeof(out_amp)); t38_terminal_send_timeout(t38_state_a, SAMPLES_PER_CHUNK); t30_len_b = fax_tx(fax_state_b, t30_amp_b, SAMPLES_PER_CHUNK); if (!use_transmit_on_idle) { /* The receive side always expects a full block of samples, but the transmit side may not be sending any when it doesn't need to. We may need to pad with some silence. */ if (t30_len_b < SAMPLES_PER_CHUNK) { memset(t30_amp_b + t30_len_b, 0, sizeof(int16_t)*(SAMPLES_PER_CHUNK - t30_len_b)); t30_len_b = SAMPLES_PER_CHUNK; } } if (feedback_audio) { for (i = 0; i < t30_len_b; i++) t30_amp_b[i] += t38_amp_b[i] >> 1; } if (log_audio) { for (i = 0; i < t30_len_b; i++) out_amp[2*i + 1] = t30_amp_b[i]; } if (t38_gateway_rx(t38_state_b, t30_amp_b, t30_len_b)) break; t38_len_b = t38_gateway_tx(t38_state_b, t38_amp_b, SAMPLES_PER_CHUNK); if (!use_transmit_on_idle) { if (t38_len_b < SAMPLES_PER_CHUNK) { memset(t38_amp_b + t38_len_b, 0, sizeof(int16_t)*(SAMPLES_PER_CHUNK - t38_len_b)); t38_len_b = SAMPLES_PER_CHUNK; } } if (log_audio) { for (i = 0; i < t38_len_b; i++) out_amp[2*i] = t38_amp_b[i]; } if (fax_rx(fax_state_b, t38_amp_b, SAMPLES_PER_CHUNK)) break; when += (float) SAMPLES_PER_CHUNK/(float) SAMPLE_RATE; while ((msg_len = g1050_get(path_a_to_b, msg, 1024, when, &seq_no, &tx_when, &rx_when)) >= 0) { #if defined(ENABLE_GUI) if (use_gui) media_monitor_rx(seq_no, tx_when, rx_when); #endif t38_core = t38_gateway_get_t38_core_state(t38_state_b); t38_core_rx_ifp_packet(t38_core, msg, msg_len, seq_no); } while ((msg_len = g1050_get(path_b_to_a, msg, 1024, when, &seq_no, &tx_when, &rx_when)) >= 0) { #if defined(ENABLE_GUI) if (use_gui) media_monitor_rx(seq_no, tx_when, rx_when); #endif t38_core = t38_terminal_get_t38_core_state(t38_state_a); t38_core_rx_ifp_packet(t38_core, msg, msg_len, seq_no); } if (log_audio) { outframes = sf_writef_short(wave_handle, out_amp, SAMPLES_PER_CHUNK); if (outframes != SAMPLES_PER_CHUNK) break; } if (done[0] && done[1]) break; #if defined(ENABLE_GUI) if (use_gui) media_monitor_update_display(); #endif } t38_terminal_release(t38_state_a); fax_release(fax_state_b); if (log_audio) { if (sf_close(wave_handle) != 0) { fprintf(stderr, " Cannot close audio file '%s'\n", OUTPUT_FILE_NAME_WAVE); exit(2); } } if (!succeeded[0] || !succeeded[1]) { printf("Tests failed\n"); exit(2); } printf("Tests passed\n"); return 0; }