SPAN_DECLARE_NONSTD(int) fax_rx_fillin(fax_state_t *s, int len) { /* To mitigate the effect of lost packets on a packet network we should try to sustain the status quo. If there is no receive modem running, keep things that way. If there is a receive modem running, try to sustain its operation, without causing a phase hop, or letting its adaptive functions diverge. */ #if defined(LOG_FAX_AUDIO) if (s->modems.audio_rx_log >= 0) { int i; #if defined(_MSC_VER) int16_t *amp = (int16_t *) _alloca(sizeof(int16_t)*len); #else int16_t amp[len]; #endif vec_zeroi16(amp, len); write(s->modems.audio_rx_log, amp, len*sizeof(int16_t)); } #endif /* Call the fillin function of the current modem (if there is one). */ s->modems.rx_fillin_handler(s->modems.rx_fillin_user_data, len); t30_timer_update(&s->t30, len); return 0; }
SPAN_DECLARE(int) fax_rx(fax_state_t *s, int16_t *amp, int len) { int i; #if defined(LOG_FAX_AUDIO) if (s->modems.audio_rx_log >= 0) write(s->modems.audio_rx_log, amp, len*sizeof(int16_t)); #endif for (i = 0; i < len; i++) amp[i] = dc_restore(&s->modems.dc_restore, amp[i]); s->modems.rx_handler(s->modems.rx_user_data, amp, len); t30_timer_update(&s->t30, len); return 0; }
int fax_rx(fax_state_t *s, int16_t *amp, int len) { int i; #if defined(LOG_FAX_AUDIO) if (s->fax_audio_rx_log >= 0) write(s->fax_audio_rx_log, amp, len*sizeof(int16_t)); #endif for (i = 0; i < len; i++) amp[i] = dc_restore(&(s->dc_restore), amp[i]); s->rx_handler(s->rx_user_data, amp, len); t30_timer_update(&(s->t30_state), len); return 0; }
SPAN_DECLARE(int) fax_rx_fillin(fax_state_t *s, int len) { /* To mitigate the effect of lost packets on a packet network we should try to sustain the status quo. If there is no receive modem running, keep things that way. If there is a receive modem running, try to sustain its operation, without causing a phase hop, or letting its adaptive functions diverge. */ #if defined(LOG_FAX_AUDIO) if (s->modems.audio_rx_log >= 0) { int i; #if defined(_MSC_VER) int16_t *amp = (int16_t *) _alloca(sizeof(int16_t)*len); #else int16_t amp[len]; #endif vec_zeroi16(amp, len); write(s->modems.audio_rx_log, amp, len*sizeof(int16_t)); } #endif t30_timer_update(&s->t30, len); /* Call the fillin function of the current modem (if there is one). */ switch (s->modems.current_rx_type) { case T30_MODEM_V21: len = fsk_rx_fillin(&s->modems.v21_rx, len); break; case T30_MODEM_V27TER: /* TODO: what about FSK in the early stages */ len = v27ter_rx_fillin(&s->modems.v27ter_rx, len); break; case T30_MODEM_V29: /* TODO: what about FSK in the early stages */ len = v29_rx_fillin(&s->modems.v29_rx, len); break; case T30_MODEM_V17: /* TODO: what about FSK in the early stages */ len = v17_rx_fillin(&s->modems.v17_rx, len); break; } return len; }
int t38_terminal_send_timeout(t38_terminal_state_t *s, int samples) { int len; int i; int previous; uint8_t buf[MAX_OCTETS_PER_UNPACED_CHUNK + 50]; /* Training times for all the modem options, with and without TEP */ static const int training_time[] = { 0, 0, /* T38_IND_NO_SIGNAL */ 0, 0, /* T38_IND_CNG */ 0, 0, /* T38_IND_CED */ 1000, 1000, /* T38_IND_V21_PREAMBLE */ /* TODO: 850 should be OK for this, but it causes trouble with some ATAs. Why? */ 943, 1158, /* T38_IND_V27TER_2400_TRAINING */ 708, 923, /* T38_IND_V27TER_4800_TRAINING */ 234, 454, /* T38_IND_V29_7200_TRAINING */ 234, 454, /* T38_IND_V29_9600_TRAINING */ 142, 367, /* T38_IND_V17_7200_SHORT_TRAINING */ 1393, 1618, /* T38_IND_V17_7200_LONG_TRAINING */ 142, 367, /* T38_IND_V17_9600_SHORT_TRAINING */ 1393, 1618, /* T38_IND_V17_9600_LONG_TRAINING */ 142, 367, /* T38_IND_V17_12000_SHORT_TRAINING */ 1393, 1618, /* T38_IND_V17_12000_LONG_TRAINING */ 142, 367, /* T38_IND_V17_14400_SHORT_TRAINING */ 1393, 1618, /* T38_IND_V17_14400_LONG_TRAINING */ 0, 0, /* T38_IND_V8_ANSAM */ 0, 0, /* T38_IND_V8_SIGNAL */ 0, 0, /* T38_IND_V34_CNTL_CHANNEL_1200 */ 0, 0, /* T38_IND_V34_PRI_CHANNEL */ 0, 0, /* T38_IND_V34_CC_RETRAIN */ 0, 0, /* T38_IND_V33_12000_TRAINING */ 0, 0 /* T38_IND_V33_14400_TRAINING */ }; if (s->current_rx_type == T30_MODEM_DONE || s->current_tx_type == T30_MODEM_DONE) return TRUE; s->samples += samples; t30_timer_update(&s->t30_state, samples); if (s->timeout_rx_samples && s->samples > s->timeout_rx_samples) { span_log(&s->logging, SPAN_LOG_FLOW, "Timeout mid-receive\n"); s->timeout_rx_samples = 0; t30_receive_complete(&(s->t30_state)); } if (s->timed_step == T38_TIMED_STEP_NONE) return FALSE; if (s->samples < s->next_tx_samples) return FALSE; /* Its time to send something */ switch (s->timed_step) { case T38_TIMED_STEP_NON_ECM_MODEM: /* Create a 75ms silence */ if (s->t38.current_tx_indicator != T38_IND_NO_SIGNAL) t38_core_send_indicator(&s->t38, T38_IND_NO_SIGNAL, s->indicator_tx_count); s->timed_step = T38_TIMED_STEP_NON_ECM_MODEM_2; s->next_tx_samples += ms_to_samples(75); break; case T38_TIMED_STEP_NON_ECM_MODEM_2: /* Switch on a fast modem, and give the training time to complete */ t38_core_send_indicator(&s->t38, s->next_tx_indicator, s->indicator_tx_count); s->timed_step = T38_TIMED_STEP_NON_ECM_MODEM_3; s->next_tx_samples += ms_to_samples(training_time[s->next_tx_indicator << 1]); break; case T38_TIMED_STEP_NON_ECM_MODEM_3: /* Send a chunk of non-ECM image data */ /* T.38 says it is OK to send the last of the non-ECM data in the signal end message. However, I think the early versions of T.38 said the signal end message should not contain data. Hopefully, following the current spec will not cause compatibility issues. */ len = t30_non_ecm_get_chunk(&s->t30_state, buf, s->octets_per_data_packet); bit_reverse(buf, buf, len); if (len >= s->octets_per_data_packet) { s->next_tx_samples += ms_to_samples(s->ms_per_tx_chunk); t38_core_send_data(&s->t38, s->current_tx_data_type, T38_FIELD_T4_NON_ECM_DATA, buf, len, DATA_TX_COUNT); } else { t38_core_send_data(&s->t38, s->current_tx_data_type, T38_FIELD_T4_NON_ECM_SIG_END, buf, len, s->data_end_tx_count); /* This should not be needed, since the message above indicates the end of the signal, but it seems like it can improve compatibility with quirky implementations. */ t38_core_send_indicator(&s->t38, T38_IND_NO_SIGNAL, s->indicator_tx_count); s->timed_step = T38_TIMED_STEP_NONE; t30_send_complete(&(s->t30_state)); } break; case T38_TIMED_STEP_HDLC_MODEM: /* Send HDLC preambling */ t38_core_send_indicator(&s->t38, s->next_tx_indicator, s->indicator_tx_count); s->next_tx_samples += ms_to_samples(training_time[s->next_tx_indicator << 1]); s->timed_step = T38_TIMED_STEP_HDLC_MODEM_2; break; case T38_TIMED_STEP_HDLC_MODEM_2: /* Send a chunk of HDLC data */ i = s->octets_per_data_packet; if (i >= (s->tx_len - s->tx_ptr)) { i = s->tx_len - s->tx_ptr; s->timed_step = T38_TIMED_STEP_HDLC_MODEM_3; } t38_core_send_data(&s->t38, s->current_tx_data_type, T38_FIELD_HDLC_DATA, &s->tx_buf[s->tx_ptr], i, DATA_TX_COUNT); s->tx_ptr += i; s->next_tx_samples += ms_to_samples(s->ms_per_tx_chunk); break; case T38_TIMED_STEP_HDLC_MODEM_3: /* End of HDLC frame */ previous = s->current_tx_data_type; s->tx_ptr = 0; s->tx_len = 0; t30_send_complete(&s->t30_state); if (s->tx_len < 0) { t38_core_send_data(&s->t38, previous, T38_FIELD_HDLC_FCS_OK_SIG_END, NULL, 0, s->data_end_tx_count); /* We have already sent T38_FIELD_HDLC_FCS_OK_SIG_END. It seems some boxes may not like us sending a T38_FIELD_HDLC_SIG_END at this point. Just say there is no signal. */ t38_core_send_indicator(&s->t38, T38_IND_NO_SIGNAL, s->indicator_tx_count); s->tx_len = 0; t30_send_complete(&s->t30_state); if (s->tx_len) s->timed_step = T38_TIMED_STEP_HDLC_MODEM; } else { t38_core_send_data(&s->t38, previous, T38_FIELD_HDLC_FCS_OK, NULL, 0, DATA_TX_COUNT); if (s->tx_len) s->timed_step = T38_TIMED_STEP_HDLC_MODEM_2; } s->next_tx_samples += ms_to_samples(s->ms_per_tx_chunk); break; case T38_TIMED_STEP_CED: /* It seems common practice to start with a no signal indicator, though this is not a specified requirement. Since we should be sending 200ms of silence, starting the delay with a no signal indication makes sense. We do need a 200ms delay, as that is a specification requirement. */ s->timed_step = T38_TIMED_STEP_CED_2; s->next_tx_samples = s->samples + ms_to_samples(200); t38_core_send_indicator(&s->t38, T38_IND_NO_SIGNAL, s->indicator_tx_count); s->current_tx_data_type = T38_DATA_NONE; break; case T38_TIMED_STEP_CED_2: /* Initial 200ms delay over. Send the CED indicator */ s->next_tx_samples = s->samples + ms_to_samples(3000); s->timed_step = T38_TIMED_STEP_PAUSE; t38_core_send_indicator(&s->t38, T38_IND_CED, s->indicator_tx_count); s->current_tx_data_type = T38_DATA_NONE; break; case T38_TIMED_STEP_CNG: /* It seems common practice to start with a no signal indicator, though this is not a specified requirement. Since we should be sending 200ms of silence, starting the delay with a no signal indication makes sense. We do need a 200ms delay, as that is a specification requirement. */ s->timed_step = T38_TIMED_STEP_CNG_2; s->next_tx_samples = s->samples + ms_to_samples(200); t38_core_send_indicator(&s->t38, T38_IND_NO_SIGNAL, s->indicator_tx_count); s->current_tx_data_type = T38_DATA_NONE; break; case T38_TIMED_STEP_CNG_2: /* Initial short delay over. Send the CNG indicator */ s->timed_step = T38_TIMED_STEP_NONE; t38_core_send_indicator(&s->t38, T38_IND_CNG, s->indicator_tx_count); s->current_tx_data_type = T38_DATA_NONE; break; case T38_TIMED_STEP_PAUSE: /* End of timed pause */ s->timed_step = T38_TIMED_STEP_NONE; t30_send_complete(&s->t30_state); break; } return FALSE; }