Beispiel #1
0
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;
}
Beispiel #2
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;
}
Beispiel #3
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;
}
Beispiel #4
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;
}
Beispiel #5
0
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;
}