コード例 #1
0
ファイル: fsk_tests.c プロジェクト: mfpgt/xuggle-xuggler
int main(int argc, char *argv[])
{
    fsk_tx_state_t *caller_tx;
    fsk_rx_state_t *caller_rx;
    fsk_tx_state_t *answerer_tx;
    fsk_rx_state_t *answerer_rx;
    bert_state_t caller_bert;
    bert_state_t answerer_bert;
    bert_results_t bert_results;
    power_meter_t caller_meter;
    power_meter_t answerer_meter;
    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 inhandle;
    AFfilehandle outhandle;
    int outframes;    
    int i;
    int j;
    int samples;
    int test_bps;
    int noise_level;
    int noise_sweep;
    int bits_per_test;
    int line_model_no;
    int modem_under_test_1;
    int modem_under_test_2;
    int modems_set;
    int log_audio;
    int channel_codec;
    int rbs_pattern;
    int on_at;
    int off_at;
    tone_gen_descriptor_t tone_desc;
    tone_gen_state_t tone_tx;
    int opt;

    channel_codec = MUNGE_CODEC_NONE;
    rbs_pattern = 0;
    line_model_no = 0;
    decode_test_file = NULL;
    noise_sweep = FALSE;
    modem_under_test_1 = FSK_V21CH1;
    modem_under_test_2 = FSK_V21CH2;
    log_audio = FALSE;
    modems_set = 0;
    while ((opt = getopt(argc, argv, "c:dlm:nr:s:")) != -1)
    {
        switch (opt)
        {
        case 'c':
            channel_codec = atoi(optarg);
            break;
        case 'd':
            decode_test_file = optarg;
            break;
        case 'l':
            log_audio = TRUE;
            break;
        case 'm':
            line_model_no = atoi(optarg);
            break;
        case 'n':
            noise_sweep = TRUE;
            break;
        case 'r':
            rbs_pattern = atoi(optarg);
            break;
        case 's':
            switch (modems_set++)
            {
            case 0:
                modem_under_test_1 = atoi(optarg);
                break;
            case 1:
                modem_under_test_2 = atoi(optarg);
                break;
            }
            break;
        default:
            //usage();
            exit(2);
            break;
        }
    }

    if (modem_under_test_1 >= 0)
        printf("Modem channel 1 is '%s'\n", preset_fsk_specs[modem_under_test_1].name);
    if (modem_under_test_2 >= 0)
        printf("Modem channel 2 is '%s'\n", preset_fsk_specs[modem_under_test_2].name);

    outhandle = AF_NULL_FILEHANDLE;

    if (log_audio)
    {
        if ((outhandle = afOpenFile_telephony_write(OUTPUT_FILE_NAME, 2)) == AF_NULL_FILEHANDLE)
        {
            fprintf(stderr, "    Cannot create wave file '%s'\n", OUTPUT_FILE_NAME);
            exit(2);
        }
    }
    noise_level = -200;
    bits_per_test = 0;
    inhandle = NULL;

    memset(caller_amp, 0, sizeof(*caller_amp));
    memset(answerer_amp, 0, sizeof(*answerer_amp));
    memset(caller_model_amp, 0, sizeof(*caller_model_amp));
    memset(answerer_model_amp, 0, sizeof(*answerer_model_amp));
    power_meter_init(&caller_meter, 7);
    power_meter_init(&answerer_meter, 7);

    if (decode_test_file)
    {
        if ((inhandle = afOpenFile_telephony_read(decode_test_file, 1)) == AF_NULL_FILEHANDLE)
        {
            fprintf(stderr, "    Cannot open wave file '%s'\n", decode_test_file);
            exit(2);
        }
        caller_rx = fsk_rx_init(NULL, &preset_fsk_specs[modem_under_test_1], TRUE, put_bit, NULL);
        fsk_rx_set_modem_status_handler(caller_rx, rx_status, (void *) &caller_rx);
        test_bps = preset_fsk_specs[modem_under_test_1].baud_rate;

        for (;;)
        {
            samples = afReadFrames(inhandle,
                                   AF_DEFAULT_TRACK,
                                   caller_model_amp,
                                   BLOCK_LEN);
            if (samples < BLOCK_LEN)
                break;
            for (i = 0;  i < samples;  i++)
                power_meter_update(&caller_meter, caller_model_amp[i]);
            fsk_rx(caller_rx, caller_model_amp, samples);
        }

        if (afCloseFile(inhandle) != 0)
        {
            fprintf(stderr, "    Cannot close wave file '%s'\n", decode_test_file);
            exit(2);
        }
    }
    else
    {
        printf("Test cutoff level\n");
        caller_rx = fsk_rx_init(NULL, &preset_fsk_specs[modem_under_test_1], TRUE, cutoff_test_put_bit, NULL);
        fsk_rx_signal_cutoff(caller_rx, -30.0f);
        fsk_rx_set_modem_status_handler(caller_rx, cutoff_test_rx_status, (void *) &caller_rx);
        on_at = 0;
        for (i = -40;  i < -25;  i++)
        {
            make_tone_gen_descriptor(&tone_desc,
                                     1500,
                                     i,
                                     0,
                                     0,
                                     1,
                                     0,
                                     0,
                                     0,
                                     TRUE);
            tone_gen_init(&tone_tx, &tone_desc);
            for (j = 0;  j < 10;  j++)
            {
                samples = tone_gen(&tone_tx, caller_model_amp, 160);
                fsk_rx(caller_rx, caller_model_amp, samples);
            }
            if (cutoff_test_carrier)
               break;
        }
        on_at = i;
        off_at = 0;
        for (  ;  i > -40;  i--)
        {
            make_tone_gen_descriptor(&tone_desc,
                                     1500,
                                     i,
                                     0,
                                     0,
                                     1,
                                     0,
                                     0,
                                     0,
                                     TRUE);
            tone_gen_init(&tone_tx, &tone_desc);
            for (j = 0;  j < 10;  j++)
            {
                samples = tone_gen(&tone_tx, caller_model_amp, 160);
                fsk_rx(caller_rx, caller_model_amp, samples);
            }
            if (!cutoff_test_carrier)
                break;
        }
        off_at = i;
        printf("Carrier on at %d, off at %d\n", on_at, off_at);
        if (on_at < -29  ||  on_at > -26  
            ||
            off_at < -35  ||  off_at > -31)
        {
            printf("Tests failed.\n");
            exit(2);
        }
                
        printf("Test with BERT\n");
        test_bps = preset_fsk_specs[modem_under_test_1].baud_rate;
        if (modem_under_test_1 >= 0)
        {
            caller_tx = fsk_tx_init(NULL, &preset_fsk_specs[modem_under_test_1], (get_bit_func_t) bert_get_bit, &caller_bert);
            fsk_tx_set_modem_status_handler(caller_tx, tx_status, (void *) &caller_tx);
            answerer_rx = fsk_rx_init(NULL, &preset_fsk_specs[modem_under_test_1], TRUE, (put_bit_func_t) bert_put_bit, &answerer_bert);
            fsk_rx_set_modem_status_handler(answerer_rx, rx_status, (void *) &answerer_rx);
        }
        if (modem_under_test_2 >= 0)
        {
            answerer_tx = fsk_tx_init(NULL, &preset_fsk_specs[modem_under_test_2], (get_bit_func_t) bert_get_bit, &answerer_bert);
            fsk_tx_set_modem_status_handler(answerer_tx, tx_status, (void *) &answerer_tx);
            caller_rx = fsk_rx_init(NULL, &preset_fsk_specs[modem_under_test_2], TRUE, (put_bit_func_t) bert_put_bit, &caller_bert);
            fsk_rx_set_modem_status_handler(caller_rx, rx_status, (void *) &caller_rx);
        }
        test_bps = preset_fsk_specs[modem_under_test_1].baud_rate;

        bits_per_test = 500000;
        noise_level = -24;

        bert_init(&caller_bert, bits_per_test, BERT_PATTERN_ITU_O152_11, test_bps, 20);
        bert_set_report(&caller_bert, 100000, reporter, (void *) (intptr_t) 1);
        bert_init(&answerer_bert, bits_per_test, BERT_PATTERN_ITU_O152_11, test_bps, 20);
        bert_set_report(&answerer_bert, 100000, reporter, (void *) (intptr_t) 2);
        if ((model = both_ways_line_model_init(line_model_no, (float) noise_level, line_model_no, (float) noise_level, channel_codec, rbs_pattern)) == NULL)
        {
            fprintf(stderr, "    Failed to create line model\n");
            exit(2);
        }

        for (;;)
        {
            samples = fsk_tx(caller_tx, caller_amp, BLOCK_LEN);
            for (i = 0;  i < samples;  i++)
                power_meter_update(&caller_meter, caller_amp[i]);
            samples = fsk_tx(answerer_tx, answerer_amp, BLOCK_LEN);
            for (i = 0;  i < samples;  i++)
                power_meter_update(&answerer_meter, answerer_amp[i]);
            both_ways_line_model(model,
                                 caller_model_amp,
                                 caller_amp,
                                 answerer_model_amp,
                                 answerer_amp,
                                 samples);

            //printf("Powers %10.5fdBm0 %10.5fdBm0\n", power_meter_current_dbm0(&caller_meter), power_meter_current_dbm0(&answerer_meter));

            fsk_rx(answerer_rx, 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;

            fsk_rx(caller_rx, 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 (samples < BLOCK_LEN)
            {
                bert_result(&caller_bert, &bert_results);
                fprintf(stderr, "%ddB AWGN, %d bits, %d bad bits, %d resyncs\n", noise_level, bert_results.total_bits, bert_results.bad_bits, bert_results.resyncs);
                if (!noise_sweep)
                {
                    if (bert_results.total_bits != bits_per_test - 43
                        ||
                        bert_results.bad_bits != 0
                        ||
                        bert_results.resyncs != 0)
                    {
                        printf("Tests failed.\n");
                        exit(2);
                    }
                }
                bert_result(&answerer_bert, &bert_results);
                fprintf(stderr, "%ddB AWGN, %d bits, %d bad bits, %d resyncs\n", noise_level, bert_results.total_bits, bert_results.bad_bits, bert_results.resyncs);
                if (!noise_sweep)
                {
                    if (bert_results.total_bits != bits_per_test - 43
                        ||
                        bert_results.bad_bits != 0
                        ||
                        bert_results.resyncs != 0)
                    {
                        printf("Tests failed.\n");
                        exit(2);
                    }
                    break;
                }
    
                /* Put a little silence between the chunks in the file. */
                memset(out_amp, 0, sizeof(out_amp));
                if (log_audio)
                {
                    for (i = 0;  i < 200;  i++)
                    {
                        outframes = afWriteFrames(outhandle,
                                                  AF_DEFAULT_TRACK,
                                                  out_amp,
                                                  BLOCK_LEN);
                    }
                }
                if (modem_under_test_1 >= 0)
                {
                    caller_tx = fsk_tx_init(NULL, &preset_fsk_specs[modem_under_test_1], (get_bit_func_t) bert_get_bit, &caller_bert);
                    fsk_tx_set_modem_status_handler(caller_tx, tx_status, (void *) &caller_tx);
                    answerer_rx = fsk_rx_init(NULL, &preset_fsk_specs[modem_under_test_1], TRUE, (put_bit_func_t) bert_put_bit, &answerer_bert);
                    fsk_rx_set_modem_status_handler(answerer_rx, rx_status, (void *) &answerer_rx);
                }
                if (modem_under_test_2 >= 0)
                {
                    answerer_tx = fsk_tx_init(NULL, &preset_fsk_specs[modem_under_test_2], (get_bit_func_t) bert_get_bit, &answerer_bert);
                    fsk_tx_set_modem_status_handler(answerer_tx, tx_status, (void *) &answerer_tx);
                    caller_rx = fsk_rx_init(NULL, &preset_fsk_specs[modem_under_test_2], TRUE, (put_bit_func_t) bert_put_bit, &caller_bert);
                    fsk_rx_set_modem_status_handler(caller_rx, rx_status, (void *) &caller_rx);
                }
                noise_level++;
                if ((model = both_ways_line_model_init(line_model_no, (float) noise_level, line_model_no, noise_level, channel_codec, 0)) == NULL)
                {
                    fprintf(stderr, "    Failed to create line model\n");
                    exit(2);
                }
                bert_init(&caller_bert, bits_per_test, BERT_PATTERN_ITU_O152_11, test_bps, 20);
                bert_set_report(&caller_bert, 100000, reporter, (void *) (intptr_t) 1);
                bert_init(&answerer_bert, bits_per_test, BERT_PATTERN_ITU_O152_11, test_bps, 20);
                bert_set_report(&answerer_bert, 100000, reporter, (void *) (intptr_t) 2);
            }
        }
        printf("Tests passed.\n");
    }
    if (log_audio)
    {
        if (afCloseFile(outhandle) != 0)
        {
            fprintf(stderr, "    Cannot close wave file '%s'\n", OUTPUT_FILE_NAME);
            exit(2);
        }
    }
    return  0;
}
コード例 #2
0
ファイル: sig_tone.c プロジェクト: yallo/plcify
SPAN_DECLARE(int) sig_tone_rx(sig_tone_rx_state_t *s, int16_t amp[], int len)
{
#if defined(SPANDSP_USE_FIXED_POINT)
    int16_t x;
    int32_t v;
    int16_t notched_signal[3];
    int16_t bandpass_signal;
    int16_t signal;
#else
    float x;
    float v;
    float notched_signal[3];
    float bandpass_signal;
    float signal;
#endif
    int i;
    int j;
    int k;
    int l;
    int m;
    int32_t notch_power[3];
    int32_t flat_power;
    int immediate;

    l = s->desc->tones;
    if (l == 2)
        l = 3;
    notch_power[1] =
    notch_power[2] = INT32_MAX;
    for (i = 0;  i < len;  i++)
    {
        if (s->signalling_state_duration < INT_MAX)
            s->signalling_state_duration++;
        /*endif*/
        signal = amp[i];
        for (j = 0;  j < l;  j++)
        {
            k = coeff_sets[j];
            /* The notch filter is two cascaded biquads. */
#if defined(SPANDSP_USE_FIXED_POINT)
            v = ((int32_t) signal*s->desc->notch[k]->a1[0])
              + ((int32_t) s->tone[j].notch_z1[0]*s->desc->notch[k]->b1[1])
              + ((int32_t) s->tone[j].notch_z1[1]*s->desc->notch[k]->b1[2]);
            x = v >> 15;
            v +=   ((int32_t) s->tone[j].notch_z1[0]*s->desc->notch[k]->a1[1])
                 + ((int32_t) s->tone[j].notch_z1[1]*s->desc->notch[k]->a1[2]);
            s->tone[j].notch_z1[1] = s->tone[j].notch_z1[0];
            s->tone[j].notch_z1[0] = x;
            v +=   ((int32_t) s->tone[j].notch_z2[0]*s->desc->notch[k]->b2[1])
                 + ((int32_t) s->tone[j].notch_z2[1]*s->desc->notch[k]->b2[2]);
            x = v >> 15;
            v +=   ((int32_t) s->tone[j].notch_z2[0]*s->desc->notch[k]->a2[1])
                 + ((int32_t) s->tone[j].notch_z2[1]*s->desc->notch[k]->a2[2]);
            s->tone[j].notch_z2[1] = s->tone[j].notch_z2[0];
            s->tone[j].notch_z2[0] = x;
            notched_signal[j] = v >> s->desc->notch[k]->postscale;
#else
            v = signal*s->desc->notch[k]->a1[0]
              + s->tone[j].notch_z1[0]*s->desc->notch[k]->b1[1]
              + s->tone[j].notch_z1[1]*s->desc->notch[k]->b1[2];
            x = v;
            v +=   s->tone[j].notch_z1[0]*s->desc->notch[k]->a1[1]
                 + s->tone[j].notch_z1[1]*s->desc->notch[k]->a1[2];
            s->tone[j].notch_z1[1] = s->tone[j].notch_z1[0];
            s->tone[j].notch_z1[0] = x;
            v +=   s->tone[j].notch_z2[0]*s->desc->notch[k]->b2[1]
                 + s->tone[j].notch_z2[1]*s->desc->notch[k]->b2[2];
            x = v;
            v +=   s->tone[j].notch_z2[0]*s->desc->notch[k]->a2[1]
                 + s->tone[j].notch_z2[1]*s->desc->notch[k]->a2[2];
            s->tone[j].notch_z2[1] = s->tone[j].notch_z2[0];
            s->tone[j].notch_z2[0] = x;
            notched_signal[j] = v;
#endif
            /* Modulus and leaky integrate the notched data. The result of
               this isn't used in low tone detect mode, but we must keep the
               power measurement rolling along. */
            notch_power[j] = power_meter_update(&s->tone[j].power, notched_signal[j]);
            if (j == 1)
                signal = notched_signal[j];
        }
        if ((s->signalling_state & (SIG_TONE_1_PRESENT | SIG_TONE_2_PRESENT)))
        {
            if (s->flat_mode_timeout  &&  --s->flat_mode_timeout == 0)
                s->flat_mode = TRUE;
            /*endif*/
        }
        else
        {
            s->flat_mode_timeout = s->desc->sharp_flat_timeout;
            s->flat_mode = FALSE;
        }
        /*endif*/

        immediate = -1;
        if (s->flat_mode)
        {
            //printf("Flat mode %d %d\n", s->flat_mode_timeout, s->desc->sharp_flat_timeout);
            /* Flat mode */
            bandpass_signal = amp[i];
            if (s->desc->flat)
            {
                /* The bandpass filter is a single bi-quad stage */
#if defined(SPANDSP_USE_FIXED_POINT)
                v = ((int32_t) amp[i]*s->desc->flat->a[0])
                  + ((int32_t) s->flat_z[0]*s->desc->flat->b[1])
                  + ((int32_t) s->flat_z[1]*s->desc->flat->b[2]);
                x = v >> 15;
                v +=   ((int32_t) s->flat_z[0]*s->desc->flat->a[1])
                     + ((int32_t) s->flat_z[1]*s->desc->flat->a[2]);
                s->flat_z[1] = s->flat_z[0];
                s->flat_z[0] = x;
                bandpass_signal = v >> s->desc->flat->postscale;
#else
                v = amp[i]*s->desc->flat->a[0]
                  + s->flat_z[0]*s->desc->flat->b[1]
                  + s->flat_z[1]*s->desc->flat->b[2];
                x = v;
                v +=   s->flat_z[0]*s->desc->flat->a[1]
                     + s->flat_z[1]*s->desc->flat->a[2];
                s->flat_z[1] = s->flat_z[0];
                s->flat_z[0] = x;
                bandpass_signal = v;
#endif
            }
            flat_power = power_meter_update(&s->flat_power, bandpass_signal);
    
            /* For the flat receiver we use a simple power threshold! */
            if ((s->signalling_state & (SIG_TONE_1_PRESENT | SIG_TONE_2_PRESENT)))
            {
                if (flat_power < s->flat_detection_threshold)
                {
                    s->signalling_state &= ~tone_present_bits[0];
                    s->signalling_state |= tone_change_bits[0];
                }
                /*endif*/
            }
            else
            {
                if (flat_power > s->flat_detection_threshold)
                    s->signalling_state |= (tone_present_bits[0] | tone_change_bits[0]);
                /*endif*/
            }
            /*endif*/

            /* Notch insertion logic */
            /* tone_present and tone_on are equivalent in flat mode */
            if ((s->signalling_state & (SIG_TONE_1_PRESENT | SIG_TONE_2_PRESENT)))
            {
                s->notch_insertion_timeout = s->desc->notch_lag_time;
            }
            else
            {
                if (s->notch_insertion_timeout)
                    s->notch_insertion_timeout--;
                /*endif*/
            }
            /*endif*/
        }
コード例 #3
0
static void compliance_tests(int log_audio)
{
    SNDFILE *outhandle;
    power_meter_t power_meter;
    int outframes;
    int i;
    int block;
    int pre;
    int post;
    int post_post;
    int alaw_failures;
    int ulaw_failures;
    float worst_alaw;
    float worst_ulaw;
    float tmp;
    int len;
    g711_state_t *enc_state;
    g711_state_t *transcode;
    g711_state_t *dec_state;

    outhandle = NULL;
    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);
        }
    }

    printf("Conversion accuracy tests.\n");
    alaw_failures = 0;
    ulaw_failures = 0;
    worst_alaw = 0.0;
    worst_ulaw = 0.0;
    for (block = 0;  block < 1;  block++)
    {
        for (i = 0;  i < 65536;  i++)
        {
            pre = i - 32768;
            post = alaw_to_linear(linear_to_alaw(pre));
            if (abs(pre) > 140)
            {
                tmp = (float) abs(post - pre)/(float) abs(pre);
                if (tmp > 0.10)
                {
                    printf("A-law: Excessive error at %d (%d)\n", pre, post);
                    alaw_failures++;
                }
                if (tmp > worst_alaw)
                    worst_alaw = tmp;
            }
            else
            {
                /* Small values need different handling for sensible measurement */
                if (abs(post - pre) > 15)
                {
                    printf("A-law: Excessive error at %d (%d)\n", pre, post);
                    alaw_failures++;
                }
            }
            amp[i] = post;
        }
        if (log_audio)
        {
            outframes = sf_writef_short(outhandle, amp, 65536);
            if (outframes != 65536)
            {
                fprintf(stderr, "    Error writing audio file\n");
                exit(2);
            }
        }
        for (i = 0;  i < 65536;  i++)
        {
            pre = i - 32768;
            post = ulaw_to_linear(linear_to_ulaw(pre));
            if (abs(pre) > 40)
            {
                tmp = (float) abs(post - pre)/(float) abs(pre);
                if (tmp > 0.10)
                {
                    printf("u-law: Excessive error at %d (%d)\n", pre, post);
                    ulaw_failures++;
                }
                if (tmp > worst_ulaw)
                    worst_ulaw = tmp;
            }
            else
            {
                /* Small values need different handling for sensible measurement */
                if (abs(post - pre) > 4)
                {
                    printf("u-law: Excessive error at %d (%d)\n", pre, post);
                    ulaw_failures++;
                }
            }
            amp[i] = post;
        }
        if (log_audio)
        {
            outframes = sf_writef_short(outhandle, amp, 65536);
            if (outframes != 65536)
            {
                fprintf(stderr, "    Error writing audio file\n");
                exit(2);
            }
        }
    }
    printf("Worst A-law error (ignoring small values) %f%%\n", worst_alaw*100.0);
    printf("Worst u-law error (ignoring small values) %f%%\n", worst_ulaw*100.0);
    if (alaw_failures  ||  ulaw_failures)
    {
        printf("%d A-law values with excessive error\n", alaw_failures);
        printf("%d u-law values with excessive error\n", ulaw_failures);
        printf("Tests failed\n");
        exit(2);
    }

    printf("Cyclic conversion repeatability tests.\n");
    /* Find what happens to every possible linear value after a round trip. */
    for (i = 0;  i < 65536;  i++)
    {
        pre = i - 32768;
        /* Make a round trip */
        post = alaw_to_linear(linear_to_alaw(pre));
        /* A second round trip should cause no further change */
        post_post = alaw_to_linear(linear_to_alaw(post));
        if (post_post != post)
        {
            printf("A-law second round trip mismatch - at %d, %d != %d\n", pre, post, post_post);
            printf("Tests failed\n");
            exit(2);
        }
        /* Make a round trip */
        post = ulaw_to_linear(linear_to_ulaw(pre));
        /* A second round trip should cause no further change */
        post_post = ulaw_to_linear(linear_to_ulaw(post));
        if (post_post != post)
        {
            printf("u-law round trip mismatch - at %d, %d != %d\n", pre, post, post_post);
            printf("Tests failed\n");
            exit(2);
        }
    }

    printf("Reference power level tests.\n");
    power_meter_init(&power_meter, 7);

    for (i = 0;  i < 8000;  i++)
    {
        amp[i] = ulaw_to_linear(ulaw_1khz_sine[i & 7]);
        power_meter_update(&power_meter, amp[i]);
    }
    printf("Reference u-law 1kHz tone is %fdBm0\n", power_meter_current_dbm0(&power_meter));
    if (log_audio)
    {
        outframes = sf_writef_short(outhandle, amp, 8000);
        if (outframes != 8000)
        {
            fprintf(stderr, "    Error writing audio file\n");
            exit(2);
        }
    }
    if (0.1f < fabs(power_meter_current_dbm0(&power_meter)))
    {
        printf("Test failed.\n");
        exit(2);
    }

    for (i = 0;  i < 8000;  i++)
    {
        amp[i] = alaw_to_linear(alaw_1khz_sine[i & 7]);
        power_meter_update(&power_meter, amp[i]);
    }
    printf("Reference A-law 1kHz tone is %fdBm0\n", power_meter_current_dbm0(&power_meter));
    if (log_audio)
    {
        outframes = sf_writef_short(outhandle, amp, 8000);
        if (outframes != 8000)
        {
            fprintf(stderr, "    Error writing audio file\n");
            exit(2);
        }
    }
    if (0.1f < fabs(power_meter_current_dbm0(&power_meter)))
    {
        printf("Test failed.\n");
        exit(2);
    }

    /* Check the transcoding functions. */
    printf("Testing transcoding A-law -> u-law -> A-law\n");
    for (i = 0;  i < 256;  i++)
    {
        if (alaw_to_ulaw(ulaw_to_alaw(i)) != i)
        {
            if (abs(alaw_to_ulaw(ulaw_to_alaw(i)) - i) > 1)
            {
                printf("u-law -> A-law -> u-law gave %d -> %d\n", i, alaw_to_ulaw(ulaw_to_alaw(i)));
                printf("Test failed\n");
                exit(2);
            }
        }
    }

    printf("Testing transcoding u-law -> A-law -> u-law\n");
    for (i = 0;  i < 256;  i++)
    {
        if (ulaw_to_alaw(alaw_to_ulaw(i)) != i)
        {
            if (abs(alaw_to_ulaw(ulaw_to_alaw(i)) - i) > 1)
            {
                printf("A-law -> u-law -> A-law gave %d -> %d\n", i, ulaw_to_alaw(alaw_to_ulaw(i)));
                printf("Test failed\n");
                exit(2);
            }
        }
    }

    enc_state = g711_init(NULL, G711_ALAW);
    transcode = g711_init(NULL, G711_ALAW);
    dec_state = g711_init(NULL, G711_ULAW);

    len = 65536;
    for (i = 0;  i < len;  i++)
        amp[i] = i - 32768;
    len = g711_encode(enc_state, alaw_data, amp, len);
    len = g711_transcode(transcode, ulaw_data, alaw_data, len);
    len = g711_decode(dec_state, amp, ulaw_data, len);
    if (len != 65536)
    {
        printf("Block coding gave the wrong length - %d instead of %d\n", len, 65536);
        printf("Test failed\n");
        exit(2);
    }
    for (i = 0;  i < len;  i++)
    {
        pre = i - 32768;
        post = amp[i];
        if (abs(pre) > 140)
        {
            tmp = (float) abs(post - pre)/(float) abs(pre);
            if (tmp > 0.10)
            {
                printf("Block: Excessive error at %d (%d)\n", pre, post);
                exit(2);
            }
        }
        else
        {
            /* Small values need different handling for sensible measurement */
            if (abs(post - pre) > 15)
            {
                printf("Block: Excessive error at %d (%d)\n", pre, post);
                exit(2);
            }
        }
    }
    g711_release(enc_state);
    g711_release(transcode);
    g711_release(dec_state);

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

    printf("Tests passed.\n");
}
コード例 #4
0
static int power_meter_tests(void)
{
    awgn_state_t noise_source;
    power_meter_t meter;
    tone_gen_descriptor_t tone_desc;
    tone_gen_state_t gen;
    int i;
    int idum = 1234567;
    int16_t amp[1000];
    int len;
    int32_t level;

    power_meter_init(&meter, 7);
    printf("Testing with zero in the power register\n");
    printf("Power: expected %fdBm0, got %fdBm0\n", -90.169f, power_meter_current_dbm0(&meter));
    printf("Power: expected %fdBOv, got %fdBOv\n", -96.329f, power_meter_current_dbov(&meter));

    printf("Testing with a square wave 10dB from maximum\n");
    for (i = 0;  i < 1000;  i++)
    {
        amp[i] = (i & 1)  ?  10362  :  -10362;
        level = power_meter_update(&meter, amp[i]);
        //printf("%12d %fdBm0 %fdBov\n", level, power_meter_current_dbm0(&meter), power_meter_current_dbov(&meter));
    }
    printf("Level: expected %" PRId32 "/%" PRId32 ", got %" PRId32 "\n", power_meter_level_dbov(-10.0f), power_meter_level_dbm0(-10.0f + DBM0_MAX_POWER), level);
    printf("Power: expected %fdBm0, got %fdBm0\n", -10.0f + DBM0_MAX_POWER, power_meter_current_dbm0(&meter));
    printf("Power: expected %fdBOv, got %fdBOv\n", -10.0f, power_meter_current_dbov(&meter));
    if (level < power_meter_level_dbov(-10.0f)*0.99f
        ||
        level > power_meter_level_dbov(-10.0f)*1.01f)
    {
        printf("Test failed (level)\n");
        exit(2);
    }
    if (0.1f < fabsf(power_meter_current_dbm0(&meter) + 10.0f - DBM0_MAX_POWER))
    {
        printf("Test failed (dBm0)\n");
        exit(2);
    }
    if (0.1f < fabsf(power_meter_current_dbov(&meter) + 10.0))
    {
        printf("Test failed (dBOv)\n");
        exit(2);
    }

    printf("Testing with a sine wave tone 10dB from maximum\n");
    tone_gen_descriptor_init(&tone_desc,
                             1000,
                             -4,
                             0,
                             1,
                             1,
                             0,
                             0,
                             0,
                             true);
    tone_gen_init(&gen, &tone_desc);
    len = tone_gen(&gen, amp, 1000);
    for (i = 0;  i < len;  i++)
    {
        level = power_meter_update(&meter, amp[i]);
        //printf("%12d %fdBm0 %fdBov\n", level, power_meter_current_dbm0(&meter), power_meter_current_dbov(&meter));
    }
    printf("Level: expected %" PRId32 "/%" PRId32 ", got %" PRId32 "\n", power_meter_level_dbov(-10.0f), power_meter_level_dbm0(-10.0f + DBM0_MAX_POWER), level);
    printf("Power: expected %fdBm0, got %fdBm0\n", -10.0f + DBM0_MAX_POWER, power_meter_current_dbm0(&meter));
    printf("Power: expected %fdBOv, got %fdBOv\n", -10.0f, power_meter_current_dbov(&meter));
    if (level < power_meter_level_dbov(-10.0f)*0.95f
        ||
        level > power_meter_level_dbov(-10.0f)*1.05f)
    {
        printf("Test failed (level)\n");
        exit(2);
    }
    if (0.2f < fabsf(power_meter_current_dbm0(&meter) + 10.0f - DBM0_MAX_POWER))
    {
        printf("Test failed (dBm0)\n");
        exit(2);
    }
    if (0.2f < fabsf(power_meter_current_dbov(&meter) + 10.0))
    {
        printf("Test failed (dBOv)\n");
        exit(2);
    }

    printf("Testing with AWGN 10dB from maximum\n");
    awgn_init_dbov(&noise_source, idum, -10.0f);
    for (i = 0;  i < 1000;  i++)
        amp[i] = awgn(&noise_source);
    for (i = 0;  i < 1000;  i++)
    {
        level = power_meter_update(&meter, amp[i]);
        //printf("%12d %fdBm0 %fdBov\n", level, power_meter_current_dbm0(&meter), power_meter_current_dbov(&meter));
    }
    printf("Level: expected %" PRId32 "/%" PRId32 ", got %" PRId32 "\n", power_meter_level_dbov(-10.0f), power_meter_level_dbm0(-10.0f + DBM0_MAX_POWER), level);
    printf("Power: expected %fdBm0, got %fdBm0\n", -10.0f + DBM0_MAX_POWER, power_meter_current_dbm0(&meter));
    printf("Power: expected %fdBOv, got %fdBOv\n", -10.0f, power_meter_current_dbov(&meter));
    if (level < power_meter_level_dbov(-10.0f)*0.95f
        ||
        level > power_meter_level_dbov(-10.0f)*1.05f)
    {
        printf("Test failed (level)\n");
        exit(2);
    }
    if (0.2f < fabsf(power_meter_current_dbm0(&meter) + 10.0f - DBM0_MAX_POWER))
    {
        printf("Test failed (dBm0)\n");
        exit(2);
    }
    if (0.2f < fabsf(power_meter_current_dbov(&meter) + 10.0f))
    {
        printf("Test failed (dBOv)\n");
        exit(2);
    }
    return 0;
}
コード例 #5
0
ファイル: g711_tests.c プロジェクト: avesus/guruchat
int main(int argc, char *argv[])
{
    AFfilehandle outhandle;
    AFfilesetup filesetup;
    power_meter_t power_meter;
    int outframes;
    int i;
    int block;
    int pre;
    int post;
    int alaw_failures;
    int ulaw_failures;
    float worst_alaw;
    float worst_ulaw;
    float tmp;
    
    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);
    }

    printf("Conversion accuracy tests.\n");
    alaw_failures = 0;
    ulaw_failures = 0;
    worst_alaw = 0.0;
    worst_ulaw = 0.0;
    for (block = 0;  block < 1;  block++)
    {
        for (i = 0;  i < 65536;  i++)
        {
            pre = i - 32768;
            post = alaw_to_linear(linear_to_alaw(pre));
            if (abs(pre) > 140)
            {
                tmp = (float) abs(post - pre)/(float) abs(pre);
                if (tmp > 0.10)
                {
                    printf("A-law: Excessive error at %d (%d)\n", pre, post);
                    alaw_failures++;
                }
                if (tmp > worst_alaw)
                    worst_alaw = tmp;
            }
            else
            {
                /* Small values need different handling for sensible measurement */
                if (abs(post - pre) > 15)
                {
                    printf("A-law: Excessive error at %d (%d)\n", pre, post);
                    alaw_failures++;
                }
            }
            amp[i] = post;
        }
        outframes = afWriteFrames(outhandle,
                                  AF_DEFAULT_TRACK,
                                  amp,
                                  65536);
        if (outframes != 65536)
        {
            fprintf(stderr, "    Error writing wave file\n");
            exit(2);
        }
        for (i = 0;  i < 65536;  i++)
        {
            pre = i - 32768;
            post = ulaw_to_linear(linear_to_ulaw(pre));
            if (abs(pre) > 40)
            {
                tmp = (float) abs(post - pre)/(float) abs(pre);
                if (tmp > 0.10)
                {
                    printf("u-law: Excessive error at %d (%d)\n", pre, post);
                    ulaw_failures++;
                }
                if (tmp > worst_ulaw)
                    worst_ulaw = tmp;
            }
            else
            {
                /* Small values need different handling for sensible measurement */
                if (abs(post - pre) > 4)
                {
                    printf("u-law: Excessive error at %d (%d)\n", pre, post);
                    ulaw_failures++;
                }
            }
            amp[i] = post;
        }
        outframes = afWriteFrames(outhandle,
                                  AF_DEFAULT_TRACK,
                                  amp,
                                  65536);
        if (outframes != 65536)
        {
            fprintf(stderr, "    Error writing wave file\n");
            exit(2);
        }
    }
    printf("Worst A-law error (ignoring small values) %f%%\n", worst_alaw*100.0);
    printf("Worst u-law error (ignoring small values) %f%%\n", worst_ulaw*100.0);
    if (alaw_failures  ||  ulaw_failures)
    {
        printf("%d A-law values with excessive error\n", alaw_failures);
        printf("%d u-law values with excessive error\n", ulaw_failures);
        printf("Tests failed\n");
        exit(2);
    }
    
    printf("Reference power level tests.\n");
    power_meter_init(&power_meter, 7);

    for (i = 0;  i < 8000;  i++)
    {
        amp[i] = ulaw_to_linear(ulaw_1khz_sine[i & 7]);
        power_meter_update(&power_meter, amp[i]);
    }
    printf("Reference u-law 1kHz tone is %fdBm0\n", power_meter_dbm0(&power_meter));
    outframes = afWriteFrames(outhandle,
                              AF_DEFAULT_TRACK,
                              amp,
                              8000);
    if (outframes != 8000)
    {
        fprintf(stderr, "    Error writing wave file\n");
        exit(2);
    }
    if (0.1f < fabs(power_meter_dbm0(&power_meter)))
    {
        printf("Test failed.\n");
        exit(2);
    }

    for (i = 0;  i < 8000;  i++)
    {
        amp[i] = alaw_to_linear(alaw_1khz_sine[i & 7]);
        power_meter_update(&power_meter, amp[i]);
    }
    printf("Reference A-law 1kHz tone is %fdBm0\n", power_meter_dbm0(&power_meter));
    outframes = afWriteFrames(outhandle,
                              AF_DEFAULT_TRACK,
                              amp,
                              8000);
    if (outframes != 8000)
    {
        fprintf(stderr, "    Error writing wave file\n");
        exit(2);
    }
    if (0.1f < fabs(power_meter_dbm0(&power_meter)))
    {
        printf("Test failed.\n");
        exit(2);
    }

    /* Check the transcoding functions. */
    printf("Testing transcoding A-law -> u-law -> A-law\n");
    for (i = 0;  i < 256;  i++)
    {
        if (alaw_to_ulaw(ulaw_to_alaw(i)) != i)
        {
            if (abs(alaw_to_ulaw(ulaw_to_alaw(i)) - i) > 1)
            {
                printf("u-law -> A-law -> u-law gave %d -> %d\n", i, alaw_to_ulaw(ulaw_to_alaw(i)));
                printf("Test failed\n");
                exit(2);
            }
        }
    }

    printf("Testing transcoding u-law -> A-law -> u-law\n");
    for (i = 0;  i < 256;  i++)
    {
        if (ulaw_to_alaw(alaw_to_ulaw(i)) != i)
        {
            if (abs(alaw_to_ulaw(ulaw_to_alaw(i)) - i) > 1)
            {
                printf("A-law -> u-law -> A-law gave %d -> %d\n", i, ulaw_to_alaw(alaw_to_ulaw(i)));
                printf("Test failed\n");
                exit(2);
            }
        }
    }
    
    if (afCloseFile(outhandle))
    {
        fprintf(stderr, "    Cannot close wave file '%s'\n", OUT_FILE_NAME);
        exit(2);
    }
    afFreeFileSetup(filesetup);

    printf("Tests passed.\n");
    return 0;
}
コード例 #6
0
int fsk_rx(fsk_rx_state_t *s, const int16_t *amp, int len)
{
    int buf_ptr;
    int baudstate;
    int i;
    int j;
    int16_t x;
    int32_t dot;
    int32_t sum;
    int32_t power;
    complexi_t ph;

    buf_ptr = s->buf_ptr;

    for (i = 0;  i < len;  i++)
    {
        /* If there isn't much signal, don't demodulate - it will only produce
           useless junk results. */
        /* There should be no DC in the signal, but sometimes there is.
           We need to measure the power with the DC blocked, but not using
           a slow to respond DC blocker. Use the most elementary HPF. */
        x = amp[i] >> 1;
        power = power_meter_update(&(s->power), x - s->last_sample);
        s->last_sample = x;
        if (s->signal_present)
        {
            /* Look for power below turn-off threshold to turn the carrier off */
            if (power < s->carrier_off_power)
            {
                if (--s->signal_present <= 0)
                {
                    /* Count down a short delay, to ensure we push the last
                       few bits through the filters before stopping. */
                    s->put_bit(s->user_data, PUTBIT_CARRIER_DOWN);
                    continue;
                }
            }
        }
        else
        {
            /* Look for power exceeding turn-on threshold to turn the carrier on */
            if (power < s->carrier_on_power)
                continue;
            s->signal_present = 1;
            s->put_bit(s->user_data, PUTBIT_CARRIER_UP);
        }
        /* Non-coherent FSK demodulation by correlation with the target tones
           over a one baud interval. The slow V.xx specs. are too open ended
           to allow anything fancier to be used. The dot products are calculated
           using a sliding window approach, so the compute load is not that great. */
        /* The *totally* asynchronous character to character behaviour of these
           modems, when carrying async. data, seems to force a sample by sample
           approach. */
        for (j = 0;  j < 2;  j++)
        {
            s->dot_i[j] -= s->window_i[j][buf_ptr];
            s->dot_q[j] -= s->window_q[j][buf_ptr];

            ph = dds_complexi(&(s->phase_acc[j]), s->phase_rate[j]);
            s->window_i[j][buf_ptr] = (ph.re*amp[i]) >> s->scaling_shift;
            s->window_q[j][buf_ptr] = (ph.im*amp[i]) >> s->scaling_shift;

            s->dot_i[j] += s->window_i[j][buf_ptr];
            s->dot_q[j] += s->window_q[j][buf_ptr];
        }
        dot = s->dot_i[0] >> 15;
        sum = dot*dot;
        dot = s->dot_q[0] >> 15;
        sum += dot*dot;
        dot = s->dot_i[1] >> 15;
        sum -= dot*dot;
        dot = s->dot_q[1] >> 15;
        sum -= dot*dot;
        baudstate = (sum < 0);

        if (s->lastbit != baudstate)
        {
            s->lastbit = baudstate;
            if (s->sync_mode)
            {
                /* For synchronous use (e.g. HDLC channels in FAX modems), nudge
                   the baud phase gently, trying to keep it centred on the bauds. */
                if (s->baud_pll < 0x8000)
                    s->baud_pll += (s->baud_inc >> 3);
                else
                    s->baud_pll -= (s->baud_inc >> 3);
            }
            else
            {