Exemplo n.º 1
0
void make_tone_gen_descriptor(tone_gen_descriptor_t *s,
                              int f1,
                              int l1,
                              int f2,
                              int l2,
                              int d1,
                              int d2,
                              int d3,
                              int d4,
                              int repeat)
{
    memset(s, 0, sizeof(*s));
    if (f1 >= 1)
    {
        s->phase_rate[0] = dds_phase_ratef((float) f1);
        s->gain[0] = dds_scaling_dbm0f((float) l1);
    }
    s->modulate = (f2 < 0);
    if (f2)
    {
        s->phase_rate[1] = dds_phase_ratef((float) abs(f2));
        s->gain[1] = (s->modulate)  ?  (float) l2/100.0f  :  dds_scaling_dbm0f((float) l2);
    }

    s->duration[0] = d1*8;
    s->duration[1] = d2*8;
    s->duration[2] = d3*8;
    s->duration[3] = d4*8;

    s->repeat = repeat;
}
Exemplo n.º 2
0
void make_tone_gen_descriptor(tone_gen_descriptor_t *s,
                              int f1,
                              int l1,
                              int f2,
                              int l2,
                              int d1,
                              int d2,
                              int d3,
                              int d4,
                              int repeat)
{
    memset(s, 0, sizeof(*s));
    if (f1)
    {
        s->tone[0].phase_rate = dds_phase_ratef((float) f1);
        if (f2 < 0)
            s->tone[0].phase_rate = -s->tone[0].phase_rate;
        s->tone[0].gain = dds_scaling_dbm0f((float) l1);
    }
    if (f2)
    {
        s->tone[1].phase_rate = dds_phase_ratef((float) abs(f2));
        s->tone[1].gain = (f2 < 0)  ?  (float) l2/100.0f  :  dds_scaling_dbm0f((float) l2);
    }

    s->duration[0] = d1*SAMPLE_RATE/1000;
    s->duration[1] = d2*SAMPLE_RATE/1000;
    s->duration[2] = d3*SAMPLE_RATE/1000;
    s->duration[3] = d4*SAMPLE_RATE/1000;

    s->repeat = repeat;
}
Exemplo n.º 3
0
SPAN_DECLARE(tone_gen_descriptor_t *) tone_gen_descriptor_init(tone_gen_descriptor_t *s,
        int f1,
        int l1,
        int f2,
        int l2,
        int d1,
        int d2,
        int d3,
        int d4,
        int repeat)
{
    if (s == NULL)
    {
        if ((s = (tone_gen_descriptor_t *) span_alloc(sizeof(*s))) == NULL)
        {
            return NULL;
        }
    }
    memset(s, 0, sizeof(*s));

    if (f1)
    {
#if defined(SPANDSP_USE_FIXED_POINT)
        s->tone[0].phase_rate = dds_phase_rate((float) f1);
        if (f2 < 0)
            s->tone[0].phase_rate = -s->tone[0].phase_rate;
        s->tone[0].gain = dds_scaling_dbm0((float) l1);
#else
        s->tone[0].phase_rate = dds_phase_ratef((float) f1);
        if (f2 < 0)
            s->tone[0].phase_rate = -s->tone[0].phase_rate;
        s->tone[0].gain = dds_scaling_dbm0f((float) l1);
#endif
    }
    if (f2)
    {
#if defined(SPANDSP_USE_FIXED_POINT)
        s->tone[1].phase_rate = dds_phase_rate((float) abs(f2));
        s->tone[1].gain = (f2 < 0)  ?  (float) 32767.0f*l2/100.0f  :  dds_scaling_dbm0((float) l2);
#else
        s->tone[1].phase_rate = dds_phase_ratef((float) abs(f2));
        s->tone[1].gain = (f2 < 0)  ?  (float) l2/100.0f  :  dds_scaling_dbm0f((float) l2);
#endif
    }

    s->duration[0] = d1*SAMPLE_RATE/1000;
    s->duration[1] = d2*SAMPLE_RATE/1000;
    s->duration[2] = d3*SAMPLE_RATE/1000;
    s->duration[3] = d4*SAMPLE_RATE/1000;

    s->repeat = repeat;

    return s;
}
Exemplo n.º 4
0
super_tone_tx_step_t *super_tone_tx_make_step(super_tone_tx_step_t *s,
        float f1,
        float l1,
        float f2,
        float l2,
        int length,
        int cycles)
{
    if (s == NULL)
    {
        s = (super_tone_tx_step_t *) malloc(sizeof(super_tone_tx_step_t));
        if (s == NULL)
            return NULL;
    }
    if (f1 >= 1.0)
    {
        s->phase_rate[0] = dds_phase_ratef(f1);
        s->gain[0] = dds_scaling_dbm0f(l1);
    }
    else
    {
        s->phase_rate[0] = 0;
        s->gain[0] = 0;
    }
    if (f2 >= 1.0)
    {
        s->phase_rate[1] = dds_phase_ratef(f2);
        s->gain[1] = dds_scaling_dbm0f(l2);
    }
    else
    {
        s->phase_rate[1] = 0;
        s->gain[1] = 0;
    }
    s->tone = (f1 > 0.0);
    s->length = length*8;
    s->cycles = cycles;
    s->next = NULL;
    s->nest = NULL;
    return  s;
}
Exemplo n.º 5
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;
}
Exemplo n.º 6
0
int main(int argc, char *argv[])
{
    AFfilehandle inhandle;
    AFfilehandle outhandle;
    AFfilesetup filesetup;
    plc_state_t plc;
    int inframes;
    int outframes;
    int16_t amp[1024];
    int block_no;
    int lost_blocks;
    int block_len;
    int loss_rate;
    int dropit;
    int block_real;
    int block_synthetic;
    int tone;
    int i;
    uint32_t phase_acc;
    int32_t phase_rate;

    loss_rate = 25;
    block_len = 160;
    block_real = FALSE;
    block_synthetic = FALSE;
    tone = -1;
    for (i = 1;  i < argc;  i++)
    {
        if (strcmp(argv[i], "-l") == 0)
        {
            loss_rate = atoi(argv[++i]);
            continue;
        }
        if (strcmp(argv[i], "-b") == 0)
        {
            block_len = atoi(argv[++i]);
            continue;
        }
        if (strcmp(argv[i], "-t") == 0)
        {
            tone = atoi(argv[++i]);
            continue;
        }
        if (strcmp(argv[i], "-r") == 0)
            block_real = TRUE;
        if (strcmp(argv[i], "-s") == 0)
            block_synthetic = TRUE;
    }
    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);

    phase_rate = 0;
    inhandle = NULL;
    if (tone < 0)
    {
        if ((inhandle = afOpenFile(INPUT_FILE_NAME, "r", NULL)) == AF_NULL_FILEHANDLE)
        {
            fprintf(stderr, "    Failed to open wave file '%s'\n", INPUT_FILE_NAME);
            exit(2);
        }
    }
    else
    {
        phase_rate = dds_phase_ratef((float) tone);
    }
    if ((outhandle = afOpenFile(OUTPUT_FILE_NAME, "w", filesetup)) == AF_NULL_FILEHANDLE)
    {
        fprintf(stderr, "    Failed to open wave file '%s'\n", OUTPUT_FILE_NAME);
        exit(2);
    }
    plc_init(&plc);
    lost_blocks = 0;
    for (block_no = 0;  ;  block_no++)
    {
        if (tone < 0)
        {
            inframes = afReadFrames(inhandle,
                                    AF_DEFAULT_TRACK,
                                    amp,
                                    block_len);
            if (inframes != block_len)
                break;
        }
        else
        {
            if (block_no > 10000)
                break;
            for (i = 0;  i < block_len;  i++)
                amp[i] = (int16_t) dds_modf(&phase_acc, phase_rate, 10000.0, 0);
            inframes = block_len;
        }
        dropit = rand()/(RAND_MAX/100);
        if (dropit > loss_rate)
        {
            plc_rx(&plc, amp, inframes);
            if (block_real)
                memset(amp, 0, sizeof(int16_t)*inframes);
        }
        else
        {
            lost_blocks++;
            plc_fillin(&plc, amp, inframes);
            if (block_synthetic)
                memset(amp, 0, sizeof(int16_t)*inframes);
        }
        outframes = afWriteFrames(outhandle,
                                  AF_DEFAULT_TRACK,
                                  amp,
                                  inframes);
        if (outframes != inframes)
        {
            fprintf(stderr, "    Error writing out sound\n");
            exit(2);
        }
    }
    printf("Dropped %d of %d blocks\n", lost_blocks, block_no);
    if (tone < 0)
    {
        if (afCloseFile(inhandle) != 0)
        {
            fprintf(stderr, "    Cannot close wave file '%s'\n", INPUT_FILE_NAME);
            exit(2);
        }
    }
    if (afCloseFile(outhandle) != 0)
    {
        fprintf(stderr, "    Cannot close wave file '%s'\n", OUTPUT_FILE_NAME);
        exit(2);
    }
    afFreeFileSetup(filesetup);
    return 0;
}
Exemplo n.º 7
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;
}
Exemplo n.º 8
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;
}
Exemplo n.º 9
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;
}
Exemplo n.º 10
0
static int periodogram_tests(void)
{
    int i;
    int j;
    int k;
    int len;
    complexf_t coeffs[PG_WINDOW/2];
    complexf_t camp[BLOCK_LEN];
    complexf_t last_result;
    complexf_t result;
    complexf_t phase_offset;
    float freq_error;
    float pg_scale;
    float level;
    float scale1;
    float scale2;
    int32_t phase_rate1;
    int32_t phase_rate2;
    uint32_t phase_acc1;
    uint32_t phase_acc2;
    awgn_state_t noise_source_re;
    awgn_state_t noise_source_im;

    phase_rate1 = DEC_RATIO*dds_phase_ratef(FREQ1 - 5.0f);
    phase_rate2 = DEC_RATIO*dds_phase_ratef(FREQ2);
    phase_acc1 = 0;
    phase_acc2 = 0;
    len = periodogram_generate_coeffs(coeffs, FREQ1, DEC_SAMPLE_RATE, PG_WINDOW);
    if (len != PG_WINDOW/2)
    {
        printf("Test failed\n");
        return -1;
    }
    pg_scale = periodogram_generate_phase_offset(&phase_offset, FREQ1, DEC_SAMPLE_RATE, PG_WINDOW);
    scale1 = dds_scaling_dbm0f(-6.0f);
    scale2 = dds_scaling_dbm0f(-6.0f);

    for (k = -50;  k < 0;  k++)
    {
        printf("Setting noise to %ddBm0\n", k);
        awgn_init_dbm0(&noise_source_re, 1234567, (float) k);
        awgn_init_dbm0(&noise_source_im, 7654321, (float) k);
        last_result = complex_setf(0.0f, 0.0f);
        for (i = 0;  i < 100;  i++)
        {
            for (j = 0;  j < PG_WINDOW;  j++)
            {
                result = dds_complexf(&phase_acc1, phase_rate1);
                camp[j].re = result.re*scale1;
                camp[j].im = result.im*scale1;
                result = dds_complexf(&phase_acc2, phase_rate2);
                camp[j].re += result.re*scale2;
                camp[j].im += result.im*scale2;
                camp[j].re += awgn(&noise_source_re);
                camp[j].im += awgn(&noise_source_im);
            }
            result = periodogram(coeffs, camp, PG_WINDOW);
            level = sqrtf(result.re*result.re + result.im*result.im);
            freq_error = periodogram_freq_error(&phase_offset, pg_scale, &last_result, &result);
            last_result = result;
            if (i == 0)
                continue;

            printf("Signal level = %.5f, freq error = %.5f\n", level, freq_error);
            if (level < scale1*0.8f  ||  level > scale1*1.2f)
            {
                printf("Test failed - %ddBm0 of noise, signal is %f (%f)\n", k, level, scale1);
                return -1;
            }
            if (freq_error < -10.0f  ||  freq_error > 10.0f)
            {
                printf("Test failed - %ddBm0 of noise, %fHz error\n", k, freq_error);
                return -1;
            }
        }
    }
    return 0;
}
Exemplo n.º 11
0
int main(int argc, char *argv[])
{
    v29_rx_state_t *rx;
    v29_tx_state_t *tx;
    bert_results_t bert_results;
    int16_t gen_amp[BLOCK_LEN];
    int16_t amp[BLOCK_LEN];
    AFfilehandle inhandle;
    AFfilehandle outhandle;
    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;
    int opt;
    logging_state_t *logging;
    
    channel_codec = MUNGE_CODEC_NONE;
    rbs_pattern = 0;
    test_bps = 9600;
    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 != 9600  &&  test_bps != 7200  &&  test_bps != 4800)
            {
                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 (log_audio)
    {
        if ((outhandle = afOpenFile_telephony_write(OUT_FILE_NAME, 1)) == 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. */
        tx = NULL;
        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);
        }
    }
    else
    {
        /* We will generate V.29 audio, and add some noise to it. */
        tx = v29_tx_init(NULL, test_bps, tep, v29getbit, NULL);
        v29_tx_power(tx, signal_level);
        v29_tx_set_modem_status_handler(tx, v29_tx_status, (void *) tx);
#if defined(WITH_SPANDSP_INTERNALS)
        /* Move the carrier off a bit */
        tx->carrier_phase_rate = dds_phase_ratef(1710.0f);
        tx->carrier_phase = 0;
#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);
        }
    }

    rx = v29_rx_init(NULL, test_bps, v29putbit, NULL);
    v29_rx_signal_cutoff(rx, -45.5f);
    v29_rx_set_modem_status_handler(rx, v29_rx_status, (void *) rx);
    v29_rx_set_qam_report_handler(rx, qam_report, (void *) rx);
#if defined(WITH_SPANDSP_INTERNALS)
    /* Rotate the starting phase */
    rx->carrier_phase = 0x80000000;
#endif
    logging = v29_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.29-rx");

#if defined(ENABLE_GUI)
    if (use_gui)
    {
        qam_monitor = qam_monitor_init(6.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 = v29_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)
            {
                /* Push a little silence through, to ensure all the data bits get out of the buffers */
                memset(amp, 0, BLOCK_LEN*sizeof(int16_t));
                v29_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));
                signal_level--;
                v29_tx_restart(tx, test_bps, tep);
                v29_tx_power(tx, signal_level);
                v29_rx_restart(rx, test_bps, FALSE);
#if defined(WITH_SPANDSP_INTERNALS)
                rx->eq_put_step = rand()%(48*10/3);
#endif
                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
        v29_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 (log_audio)
    {
        if (afCloseFile(outhandle))
        {
            fprintf(stderr, "    Cannot close wave file '%s'\n", OUT_FILE_NAME);
            exit(2);
        }
    }
    return  0;
}