Esempio n. 1
0
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;
}
Esempio n. 2
0
int main(int argc, char *argv[])
{
    AFfilehandle inhandle;
    AFfilehandle outhandle;
    int frames;
    int outframes;
    int bytes;
    int16_t pre_amp[HIST_LEN];
    int16_t post_amp[HIST_LEN];
    uint8_t gsm0610_data[HIST_LEN];
    gsm0610_state_t *gsm0610_enc_state;
    gsm0610_state_t *gsm0610_dec_state;
    int opt;
    int etsitests;
    int packing;

    etsitests = TRUE;
    packing = GSM0610_PACKING_NONE;
    while ((opt = getopt(argc, argv, "lp:")) != -1)
    {
        switch (opt)
        {
        case 'l':
            etsitests = FALSE;
            break;
        case 'p':
            packing = atoi(optarg);
            break;
        default:
            //usage();
            exit(2);
        }
    }

    if (etsitests)
    {
        perform_linear_test(TRUE, 1, "Seq01");
        perform_linear_test(TRUE, 1, "Seq02");
        perform_linear_test(TRUE, 1, "Seq03");
        perform_linear_test(TRUE, 1, "Seq04");
        perform_linear_test(FALSE, 1, "Seq05");
        perform_law_test(TRUE, 'a', "Seq01");
        perform_law_test(TRUE, 'a', "Seq02");
        perform_law_test(TRUE, 'a', "Seq03");
        perform_law_test(TRUE, 'a', "Seq04");
        perform_law_test(FALSE, 'a', "Seq05");
        perform_law_test(TRUE, 'u', "Seq01");
        perform_law_test(TRUE, 'u', "Seq02");
        perform_law_test(TRUE, 'u', "Seq03");
        perform_law_test(TRUE, 'u', "Seq04");
        perform_law_test(FALSE, 'u', "Seq05");
        /* This is not actually an ETSI test */
        perform_pack_unpack_test();

        printf("Tests passed.\n");
    }
    else
    {
        if ((inhandle = afOpenFile_telephony_read(IN_FILE_NAME, 1)) == AF_NULL_FILEHANDLE)
        {
            fprintf(stderr, "    Cannot open wave file '%s'\n", IN_FILE_NAME);
            exit(2);
        }
        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 ((gsm0610_enc_state = gsm0610_init(NULL, packing)) == NULL)
        {
            fprintf(stderr, "    Cannot create encoder\n");
            exit(2);
        }
            
        if ((gsm0610_dec_state = gsm0610_init(NULL, packing)) == NULL)
        {
            fprintf(stderr, "    Cannot create decoder\n");
            exit(2);
        }

        while ((frames = afReadFrames(inhandle, AF_DEFAULT_TRACK, pre_amp, 2*BLOCK_LEN)))
        {
            bytes = gsm0610_encode(gsm0610_enc_state, gsm0610_data, pre_amp, frames);
            gsm0610_decode(gsm0610_dec_state, post_amp, gsm0610_data, bytes);
            outframes = afWriteFrames(outhandle, AF_DEFAULT_TRACK, post_amp, frames);
        }
    
        if (afCloseFile(inhandle) != 0)
        {
            fprintf(stderr, "    Cannot close wave file '%s'\n", IN_FILE_NAME);
            exit(2);
        }
        if (afCloseFile(outhandle) != 0)
        {
            fprintf(stderr, "    Cannot close wave file '%s'\n", OUT_FILE_NAME);
            exit(2);
        }
        gsm0610_release(gsm0610_enc_state);
        gsm0610_release(gsm0610_dec_state);
    }
    return 0;
}
Esempio n. 3
0
int main(int argc, char *argv[])
{
    AFfilehandle inhandle;
    AFfilehandle outhandle;
    int outframes;
    int opt;
    int samples;
    int len2;
    int len3;
    int basic_tests;
    int law;
    int encode;
    int decode;
    int file;
    const char *in_file;
    const char *out_file;
    g711_state_t *enc_state;
    g711_state_t *dec_state;
    int16_t indata[BLOCK_LEN];
    int16_t outdata[BLOCK_LEN];
    uint8_t g711data[BLOCK_LEN];

    basic_tests = TRUE;
    law = G711_ALAW;
    encode = FALSE;
    decode = FALSE;
    in_file = NULL;
    out_file = NULL;
    while ((opt = getopt(argc, argv, "ad:e:l:u")) != -1)
    {
        switch (opt)
        {
        case 'a':
            law = G711_ALAW;
            basic_tests = FALSE;
            break;
        case 'd':
            in_file = optarg;
            basic_tests = FALSE;
            decode = TRUE;
            break;
        case 'e':
            in_file = optarg;
            basic_tests = FALSE;
            encode = TRUE;
            break;
        case 'l':
            out_file = optarg;
            break;
        case 'u':
            law = G711_ULAW;
            basic_tests = FALSE;
            break;
        default:
            //usage();
            exit(2);
        }
    }

    if (basic_tests)
    {
        compliance_tests(TRUE);
    }
    else
    {
        if (!decode  &&  !encode)
        {
            decode =
            encode = TRUE;
        }
        if (in_file == NULL)
        {
            in_file = (encode)  ?  IN_FILE_NAME  :  ENCODED_FILE_NAME;
        }
        if (out_file == NULL)
        {
            out_file = (decode)  ?  OUT_FILE_NAME  :  ENCODED_FILE_NAME;
        }
        inhandle = AF_NULL_FILEHANDLE;
        outhandle = AF_NULL_FILEHANDLE;
        file = -1;
        enc_state = NULL;
        dec_state = NULL;
        if (encode)
        {
            if ((inhandle = afOpenFile_telephony_read(in_file, 1)) == AF_NULL_FILEHANDLE)
            {
                fprintf(stderr, "    Cannot open wave file '%s'\n", in_file);
                exit(2);
            }
            enc_state = g711_init(NULL, law);
        }
        else
        {
            if ((file = open(in_file, O_RDONLY)) < 0)
            {
                fprintf(stderr, "    Failed to open '%s'\n", in_file);
                exit(2);
            }
        }
        if (decode)
        {
            if ((outhandle = afOpenFile_telephony_write(out_file, 1)) == AF_NULL_FILEHANDLE)
            {
                fprintf(stderr, "    Cannot create wave file '%s'\n", out_file);
                exit(2);
            }
            dec_state = g711_init(NULL, law);
        }
        else
        {
            if ((file = open(out_file, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0)
            {
                fprintf(stderr, "    Failed to open '%s'\n", out_file);
                exit(2);
            }
        }
        for (;;)
        {
            if (encode)
            {
                samples = afReadFrames(inhandle,
                                       AF_DEFAULT_TRACK,
                                       indata,
                                       BLOCK_LEN);
                if (samples <= 0)
                    break;
                len2 = g711_encode(enc_state, g711data, indata, samples);
            }
            else
            {
                len2 = read(file, g711data, BLOCK_LEN);
                if (len2 <= 0)
                    break;
            }
            if (decode)
            {
                len3 = g711_decode(dec_state, outdata, g711data, len2);
                outframes = afWriteFrames(outhandle,
                                          AF_DEFAULT_TRACK,
                                          outdata,
                                          len3);
                if (outframes != len3)
                {
                    fprintf(stderr, "    Error writing wave file\n");
                    exit(2);
                }
            }
            else
            {
                len3 = write(file, g711data, len2);
                if (len3 <= 0)
                    break;
            }
        }
        if (encode)
        {
            if (afCloseFile(inhandle))
            {
                fprintf(stderr, "    Cannot close wave file '%s'\n", IN_FILE_NAME);
                exit(2);
            }
        }
        else
        {
            close(file);
        }
        if (decode)
        {
            if (afCloseFile(outhandle))
            {
                fprintf(stderr, "    Cannot close wave file '%s'\n", OUT_FILE_NAME);
                exit(2);
            }
        }
        else
        {
            close(file);
        }
        printf("'%s' translated to '%s' using %s.\n", in_file, out_file, (law == G711_ALAW)  ?  "A-law"  :  "u-law");
    }
    return 0;
}
Esempio n. 4
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;
}