Esempio n. 1
0
SPAN_DECLARE(int) ademco_contactid_sender_put(ademco_contactid_sender_state_t *s, const ademco_contactid_report_t *report)
{
    if (s->busy)
        return -1;
    if ((s->tx_digits_len = encode_msg(s->tx_digits, report)) < 0)
        return -1;
    s->busy = true;
    return dtmf_tx_put(&s->dtmf, s->tx_digits, s->tx_digits_len);
}
Esempio n. 2
0
SPAN_DECLARE(int) ademco_contactid_sender_rx(ademco_contactid_sender_state_t *s, const int16_t amp[], int samples)
{
#if defined(SPANDSP_USE_FIXED_POINT)
    int32_t energy_1400;
    int32_t energy_2300;
    int16_t xamp;
#else
    float energy_1400;
    float energy_2300;
    float xamp;
#endif
    int sample;
    int limit;
    int hit;
    int j;

    for (sample = 0;  sample < samples;  sample = limit)
    {
        if ((samples - sample) >= (GOERTZEL_SAMPLES_PER_BLOCK - s->current_sample))
            limit = sample + (GOERTZEL_SAMPLES_PER_BLOCK - s->current_sample);
        else
            limit = samples;
        for (j = sample;  j < limit;  j++)
        {
            xamp = amp[j];
            xamp = goertzel_preadjust_amp(xamp);
#if defined(SPANDSP_USE_FIXED_POINT)
            s->energy += ((int32_t) xamp*xamp);
#else
            s->energy += xamp*xamp;
#endif
            goertzel_samplex(&s->tone_1400, xamp);
            goertzel_samplex(&s->tone_2300, xamp);
        }
        s->current_sample += (limit - sample);
        if (s->current_sample < GOERTZEL_SAMPLES_PER_BLOCK)
            continue;

        energy_1400 = goertzel_result(&s->tone_1400);
        energy_2300 = goertzel_result(&s->tone_2300);
        hit = 0;
        if (energy_1400 > DETECTION_THRESHOLD  ||  energy_2300 > DETECTION_THRESHOLD)
        {
            if (energy_1400 > energy_2300)
            {
                if (energy_1400 > TONE_TO_TOTAL_ENERGY*s->energy)
                    hit = 1;
            }
            else
            {
                if (energy_2300 > TONE_TO_TOTAL_ENERGY*s->energy)
                    hit = 2;
            }
        }
        if (hit != s->in_tone  &&  hit == s->last_hit)
        {
            /* We have two successive indications that something has changed to a
               specific new state. */
            switch (s->tone_state)
            {
            case 0:
                if (hit == 1)
                {
                    span_log(&s->logging, SPAN_LOG_FLOW, "Receiving initial 1400Hz\n");
                    s->in_tone = hit;
                    s->tone_state = 1;
                    s->duration = 0;
                }
                break;
            case 1:
                /* We are looking for a burst of 1400Hz which is 100ms +- 5% long */
                if (hit == 0)
                {
                    if (s->duration < ms_to_samples(70)  ||  s->duration > ms_to_samples(130))
                    {
                        span_log(&s->logging, SPAN_LOG_FLOW, "Bad initial 1400Hz tone duration\n");
                        s->tone_state = 0;
                    }
                    else
                    {
                        span_log(&s->logging, SPAN_LOG_FLOW, "Received 1400Hz tone\n");
                        s->tone_state = 2;
                    }
                    s->in_tone = hit;
                    s->duration = 0;
                }
                break;
            case 2:
                /* We are looking for 100ms +-5% of silence after the 1400Hz tone */
                if (s->duration < ms_to_samples(70)  ||  s->duration > ms_to_samples(130))
                {
                    span_log(&s->logging, SPAN_LOG_FLOW, "Bad silence length\n");
                    s->tone_state = 0;
                    s->in_tone = hit;
                }
                else if (hit == 2)
                {
                    span_log(&s->logging, SPAN_LOG_FLOW, "Received silence\n");
                    s->tone_state = 3;
                    s->in_tone = hit;
                }
                else
                {
                    s->tone_state = 0;
                    s->in_tone = 0;
                }
                s->duration = 0;
                break;
            case 3:
                /* We are looking for a burst of 2300Hz which is 100ms +- 5% long */
                if (hit == 0)
                {
                    if (s->duration < ms_to_samples(70)  ||  s->duration > ms_to_samples(130))
                    {
                        span_log(&s->logging, SPAN_LOG_FLOW, "Bad initial 2300Hz tone duration\n");
                        s->tone_state = 0;
                    }
                    else
                    {
                        span_log(&s->logging, SPAN_LOG_FLOW, "Received 2300Hz\n");
                        if (s->callback)
                            s->callback(s->callback_user_data, -1, 0, 0);
                        s->tone_state = 4;
                        /* Release the transmit side, and it will time the 250ms post tone delay */
                        s->clear_to_send = true;
                        s->tries = 0;
                        if (s->tx_digits_len)
                            s->timer = ms_to_samples(3000);
                    }
                    s->in_tone = hit;
                    s->duration = 0;
                }
                break;
            case 4:
                if (hit == 1)
                {
                    span_log(&s->logging, SPAN_LOG_FLOW, "Receiving kissoff\n");
                    s->tone_state = 5;
                    s->in_tone = hit;
                    s->duration = 0;
                }
                break;
            case 5:
                if (hit == 0)
                {
                    s->busy = false;
                    if (s->duration < ms_to_samples(400)  ||  s->duration > ms_to_samples(1500))
                    {
                        span_log(&s->logging, SPAN_LOG_FLOW, "Bad kissoff duration %d\n", s->duration);
                        if (++s->tries < 4)
                        {
                            dtmf_tx_put(&s->dtmf, s->tx_digits, s->tx_digits_len);
                            s->timer = ms_to_samples(3000);
                            s->tone_state = 4;
                        }
                        else
                        {
                            s->timer = 0;
                            if (s->callback)
                                s->callback(s->callback_user_data, false, 0, 0);
                        }
                    }
                    else
                    {
                        span_log(&s->logging, SPAN_LOG_FLOW, "Received good kissoff\n");
                        s->clear_to_send = true;
                        s->tx_digits_len = 0;
                        if (s->callback)
                            s->callback(s->callback_user_data, true, 0, 0);
                        s->tone_state = 4;
                        s->clear_to_send = true;
                        s->tries = 0;
                        if (s->tx_digits_len)
                            s->timer = ms_to_samples(3000);
                    }
                    s->in_tone = hit;
                    s->duration = 0;
                }
                break;
            }
        }
        s->last_hit = hit;
        s->duration += GOERTZEL_SAMPLES_PER_BLOCK;
        if (s->timer > 0)
        {
            s->timer -= GOERTZEL_SAMPLES_PER_BLOCK;
            if (s->timer <= 0)
            {
                span_log(&s->logging, SPAN_LOG_FLOW, "Timer expired\n");
                if (s->tone_state == 4  &&  s->tx_digits_len)
                {
                    if (++s->tries < 4)
                    {
                        dtmf_tx_put(&s->dtmf, s->tx_digits, s->tx_digits_len);
                        s->timer = ms_to_samples(3000);
                    }
                    else
                    {
                        s->timer = 0;
                        if (s->callback)
                            s->callback(s->callback_user_data, false, 0, 0);
                    }
                }
            }
        }
        s->energy = 0;
        s->current_sample = 0;
    }
    return 0;
}
Esempio n. 3
0
int main(int argc, char *argv[])
{
    dtmf_tx_state_t *gen;
    int16_t amp[16384];
    int len;
    SNDFILE *outhandle;
    int add_digits;

    if ((outhandle = sf_open_telephony_write(OUTPUT_FILE_NAME, 1)) == NULL)
    {
        fprintf(stderr, "    Cannot open audio file '%s'\n", OUTPUT_FILE_NAME);
        exit(2);
    }

    gen = dtmf_tx_init(NULL, NULL, NULL);
    len = dtmf_tx(gen, amp, 16384);
    printf("Generated %d samples\n", len);
    sf_writef_short(outhandle, amp, len);
    if (dtmf_tx_put(gen, "123", -1))
    {
        printf("Ooops\n");
        exit(2);
    }
    len = dtmf_tx(gen, amp, 16384);
    printf("Generated %d samples\n", len);
    sf_writef_short(outhandle, amp, len);
    if (dtmf_tx_put(gen, "456", -1))
    {
        printf("Ooops\n");
        exit(2);
    }
    len = dtmf_tx(gen, amp, 160);
    printf("Generated %d samples\n", len);
    sf_writef_short(outhandle, amp, len);
    if (dtmf_tx_put(gen, "789", -1))
    {
        printf("Ooops\n");
        exit(2);
    }
    len = dtmf_tx(gen, amp, 160);
    printf("Generated %d samples\n", len);
    sf_writef_short(outhandle, amp, len);
    if (dtmf_tx_put(gen, "*#", -1))
    {
        printf("Ooops\n");
        exit(2);
    }
    len = dtmf_tx(gen, amp, 160);
    printf("Generated %d samples\n", len);
    sf_writef_short(outhandle, amp, len);
    add_digits = 1;
    do
    {
        len = dtmf_tx(gen, amp, 160);
        printf("Generated %d samples\n", len);
        if (len > 0)
            sf_writef_short(outhandle, amp, len);
        if (add_digits)
        {
            if (dtmf_tx_put(gen, "1234567890", -1))
            {
                printf("Digit buffer full\n");
                add_digits = 0;
            }
        }
    }
    while (len > 0);

    dtmf_tx_init(gen, NULL, NULL);
    len = dtmf_tx(gen, amp, 16384);
    printf("Generated %d samples\n", len);
    sf_writef_short(outhandle, amp, len);
    if (dtmf_tx_put(gen, "123", -1))
    {
        printf("Ooops\n");
        exit(2);
    }
    len = dtmf_tx(gen, amp, 16384);
    printf("Generated %d samples\n", len);
    sf_writef_short(outhandle, amp, len);
    if (dtmf_tx_put(gen, "456", -1))
    {
        printf("Ooops\n");
        exit(2);
    }
    len = dtmf_tx(gen, amp, 160);
    printf("Generated %d samples\n", len);
    sf_writef_short(outhandle, amp, len);
    if (dtmf_tx_put(gen, "789", -1))
    {
        printf("Ooops\n");
        exit(2);
    }
    len = dtmf_tx(gen, amp, 160);
    printf("Generated %d samples\n", len);
    sf_writef_short(outhandle, amp, len);
    if (dtmf_tx_put(gen, "0*#", -1))
    {
        printf("Ooops\n");
        exit(2);
    }
    len = dtmf_tx(gen, amp, 160);
    printf("Generated %d samples\n", len);
    sf_writef_short(outhandle, amp, len);
    if (dtmf_tx_put(gen, "ABCD", -1))
    {
        printf("Ooops\n");
        exit(2);
    }
    len = dtmf_tx(gen, amp, 160);
    printf("Generated %d samples\n", len);
    sf_writef_short(outhandle, amp, len);

    /* Try modifying the level and length of the digits */
    printf("Try different levels and timing\n");
    dtmf_tx_set_level(gen, -20, 5);
    dtmf_tx_set_timing(gen, 100, 200);
    if (dtmf_tx_put(gen, "123", -1))
    {
        printf("Ooops\n");
        exit(2);
    }
    do
    {
        len = dtmf_tx(gen, amp, 160);
        printf("Generated %d samples\n", len);
        if (len > 0)
            sf_writef_short(outhandle, amp, len);
    }
    while (len > 0);
    printf("Restore normal levels and timing\n");
    dtmf_tx_set_level(gen, -10, 0);
    dtmf_tx_set_timing(gen, 50, 55);
    if (dtmf_tx_put(gen, "A", -1))
    {
        printf("Ooops\n");
        exit(2);
    }

    add_digits = TRUE;
    do
    {
        len = dtmf_tx(gen, amp, 160);
        printf("Generated %d samples\n", len);
        if (len > 0)
            sf_writef_short(outhandle, amp, len);
        if (add_digits)
        {
            if (dtmf_tx_put(gen, "1234567890", -1))
            {
                printf("Digit buffer full\n");
                add_digits = FALSE;
            }
        }
    }
    while (len > 0);

    if (sf_close_telephony(outhandle))
    {
        fprintf(stderr, "    Cannot close audio file '%s'\n", OUTPUT_FILE_NAME);
        exit(2);
    }

    return 0;
}