示例#1
0
int r2_mf_tx(r2_mf_tx_state_t *s, int16_t amp[], int samples, int fwd, char digit)
{
    int len;
    char *cp;

    len = 0;
    if ((digit & 0x80))
    {
        /* Continue generating the tone we started earlier. */
        len = tone_gen(&s->tone, amp, samples);
    }
    else if (digit == 0)
    {
        len = samples;
        memset(amp, 0, len*sizeof(int16_t));
    }
    else
    {
        if ((cp = strchr(r2_mf_tone_codes, digit)))
        {
            if (fwd)
                tone_gen_init(&s->tone, &r2_mf_fwd_digit_tones[cp - r2_mf_tone_codes]);
            else
                tone_gen_init(&s->tone, &r2_mf_back_digit_tones[cp - r2_mf_tone_codes]);
            len = tone_gen(&s->tone, amp, samples);
        }
        else
        {
            len = samples;
            memset(amp, 0, len*sizeof(int16_t));
            
        }
    }
    return len;
}
示例#2
0
SPAN_DECLARE(int) dtmf_tx(dtmf_tx_state_t *s, int16_t amp[], int max_samples)
{
    int len;
    const char *cp;
    int digit;

    len = 0;
    if (s->tones.current_section >= 0)
    {
        /* Deal with the fragment left over from last time */
        len = tone_gen(&(s->tones), amp, max_samples);
    }
    while (len < max_samples  &&  (digit = queue_read_byte(&s->queue.queue)) >= 0)
    {
        /* Step to the next digit */
        if (digit == 0)
            continue;
        if ((cp = strchr(dtmf_positions, digit)) == NULL)
            continue;
        tone_gen_init(&(s->tones), &dtmf_digit_tones[cp - dtmf_positions]);
        s->tones.tone[0].gain = s->low_level;
        s->tones.tone[1].gain = s->high_level;
        s->tones.duration[0] = s->on_time;
        s->tones.duration[1] = s->off_time;
        len += tone_gen(&(s->tones), amp + len, max_samples - len);
    }
    return len;
}
示例#3
0
int bell_mf_tx(bell_mf_tx_state_t *s, int16_t amp[], int max_samples)
{
    int len;
    size_t dig;
    char *cp;

    len = 0;
    if (s->tones.current_section >= 0)
    {
        /* Deal with the fragment left over from last time */
        len = tone_gen(&(s->tones), amp, max_samples);
    }
    dig = 0;
    while (dig < s->current_digits  &&  len < max_samples)
    {
        /* Step to the next digit */
        if ((cp = strchr(bell_mf_tone_codes, s->digits[dig++])) == NULL)
            continue;
        tone_gen_init(&(s->tones), &(s->tone_descriptors[cp - bell_mf_tone_codes]));
        len += tone_gen(&(s->tones), amp + len, max_samples - len);
    }
    if (dig)
    {
        /* Shift out the consumed digits */
        s->current_digits -= dig;
        memmove(s->digits, s->digits + dig, s->current_digits);
    }
    return len;
}
SPAN_DECLARE(int) bell_mf_tx(bell_mf_tx_state_t *s, int16_t amp[], int max_samples)
{
    int len;
    const char *cp;
    int digit;

    len = 0;
    if (s->tones.current_section >= 0)
    {
        /* Deal with the fragment left over from last time */
        len = tone_gen(&(s->tones), amp, max_samples);
    }
    while (len < max_samples  &&  (digit = queue_read_byte(&s->queue.queue)) >= 0)
    {
        /* Step to the next digit */
        if ((cp = strchr(bell_mf_tone_codes, digit)) == NULL)
            continue;
        tone_gen_init(&(s->tones), &bell_mf_digit_tones[cp - bell_mf_tone_codes]);
        len += tone_gen(&(s->tones), amp + len, max_samples - len);
    }
    return len;
}
示例#5
0
static int my_mf_generate(int16_t amp[], char digit)
{
    int len;
    char *cp;
    tone_gen_state_t tone;

    len = 0;
    if ((cp = strchr(r2_mf_tone_codes, digit)))
    {
        tone_gen_init(&tone, &my_mf_digit_tones[cp - r2_mf_tone_codes]);
        len += tone_gen(&tone, amp + len, 9999);
    }
    return len;
}
示例#6
0
static int playtones_generator(struct cw_channel *chan, void *data, int samples)
{
	struct playtones_state *ps = data;
	struct playtones_item *pi;
	int len;
    int x;

	/*
	 * We need to prepare a frame with 16 * timelen samples as we're 
	 * generating SLIN audio
	 */
	len = samples + samples;
	if (len > sizeof(ps->data)/sizeof(int16_t) - 1)
    {
		cw_log(LOG_WARNING, "Can't generate that much data!\n");
		return -1;
	}

    x = tone_gen(&ps->tone_state, ps->data, samples);
	pi = &ps->items[ps->npos];

	/* Assemble frame */
	cw_fr_init_ex(&ps->f, CW_FRAME_VOICE, CW_FORMAT_SLINEAR, NULL);
	ps->f.datalen = len;
	ps->f.samples = samples;
	ps->f.offset = CW_FRIENDLY_OFFSET;
	ps->f.data = ps->data;
	cw_write(chan, &ps->f);

	ps->pos += x;
	if (pi->duration  &&  ps->pos >= pi->duration*8)
    {
    	/* item finished? */
		ps->pos = 0;					/* start new item */
		ps->npos++;
		if (ps->npos >= ps->nitems)
        {
            /* last item */
			if (ps->reppos == -1)			/* repeat set? */
				return -1;
			ps->npos = ps->reppos;			/* redo from top */
		}

		/* Prepare the tone generator for more */
		pi = &ps->items[ps->npos];
		tone_setup(ps, pi);
	}
	return 0;
}
SPAN_DECLARE(int) r2_mf_tx(r2_mf_tx_state_t *s, int16_t amp[], int samples)
{
    int len;

    if (s->digit == 0)
    {
        len = samples;
        memset(amp, 0, len*sizeof(int16_t));
    }
    else
    {
        len = tone_gen(&s->tone, amp, samples);
    }
    return len;
}
示例#8
0
static int my_mf_generate(int16_t amp[], const char *digits)
{
    int len;
    char *cp;
    tone_gen_state_t tone;

    len = 0;
    while (*digits)
    {
        if ((cp = strchr(bell_mf_tone_codes, *digits)))
        {
            tone_gen_init(&tone, &my_mf_digit_tones[cp - bell_mf_tone_codes]);
            len += tone_gen(&tone, amp + len, 9999);
        }
        digits++;
    }
    return len;
}
示例#9
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;
}
示例#10
0
void one_way_line_model(one_way_line_model_state_t *s, 
                        int16_t output[],
                        const int16_t input[],
                        int samples)
{
    int i;
    float in;
    float out;
    float out1;
    int16_t amp[1];

    /* The path being modelled is:
        terminal
          | < hybrid
          |
          | < noise and filtering
          |
          | < hybrid
         CO
          |
          | < A-law distortion + bulk delay
          |
         CO
          | < hybrid
          |
          | < noise and filtering
          |
          | < hybrid
        terminal
     */
    for (i = 0;  i < samples;  i++)
    {
        in = input[i];

        /* Near end analogue section */
        
        /* Line model filters & noise */
        out = calc_near_line_filter(s, in);
    
        /* Long distance digital section */

        amp[0] = out;
        codec_munge(s->munge, amp, 1);
        out = amp[0];
        /* Introduce the bulk delay of the long distance link. */
        out1 = s->bulk_delay_buf[s->bulk_delay_ptr];
        s->bulk_delay_buf[s->bulk_delay_ptr] = out;
        out = out1;
        if (++s->bulk_delay_ptr >= s->bulk_delay)
            s->bulk_delay_ptr = 0;

        /* Far end analogue section */
        
        /* Line model filters & noise */
        out = calc_far_line_filter(s, out);
    
        if (s->mains_interference)
        {
            tone_gen(&s->mains_tone, amp, 1);
            out += amp[0];
        }
        output[i] = out + s->dc_offset;
    }
}
示例#11
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;
}
示例#12
0
int main(int argc, char *argv[])
{
    int f;
    int i;
    int16_t amp[8000];
    int16_t value;
    int signal;
    float power[10];
    tone_gen_descriptor_t tone_desc;
    tone_gen_state_t tone_state;
    awgn_state_t noise_source;
    fir32_state_t line_model_d2;
    fir32_state_t line_model_d3;
    fir32_state_t line_model_d4;
    fir32_state_t line_model_d5;
    fir32_state_t line_model_d6;
    fir32_state_t line_model_d7;
    fir32_state_t line_model_d8;
    fir32_state_t line_model_d9;
    fir_float_state_t level_measurement_bp;

    signal_load(&local_css, "sound_c1_8k.wav");
    signal_load(&far_css, "sound_c3_8k.wav");

    fir32_create(&line_model_d2,
                 line_model_d2_coeffs,
                 sizeof(line_model_d2_coeffs)/sizeof(int32_t));
    fir32_create(&line_model_d3,
                 line_model_d3_coeffs,
                 sizeof(line_model_d3_coeffs)/sizeof(int32_t));
    fir32_create(&line_model_d4,
                 line_model_d4_coeffs,
                 sizeof(line_model_d4_coeffs)/sizeof(int32_t));
    fir32_create(&line_model_d5,
                 line_model_d5_coeffs,
                 sizeof(line_model_d5_coeffs)/sizeof(int32_t));
    fir32_create(&line_model_d6,
                 line_model_d6_coeffs,
                 sizeof(line_model_d6_coeffs)/sizeof(int32_t));
    fir32_create(&line_model_d7,
                 line_model_d7_coeffs,
                 sizeof(line_model_d7_coeffs)/sizeof(int32_t));
    fir32_create(&line_model_d8,
                 line_model_d8_coeffs,
                 sizeof(line_model_d8_coeffs)/sizeof(int32_t));
    fir32_create(&line_model_d9,
                 line_model_d9_coeffs,
                 sizeof(line_model_d9_coeffs)/sizeof(int32_t));
    fir_float_create(&level_measurement_bp,
                     level_measurement_bp_coeffs,
                     sizeof(level_measurement_bp_coeffs)/sizeof(float));

    for (f = 10;  f < 4000;  f++)
    {
         tone_gen_descriptor_init(&tone_desc,
                                  f,
                                  -10,
                                  0,
                                  0,
                                  1,
                                  0,
                                  0,
                                  0,
                                  true);
        tone_gen_init(&tone_state, &tone_desc);
        tone_gen(&tone_state, amp, 8000);
        for (i = 0;  i < 10;  i++)
            power[i] = 0.0f;
        for (i = 0;  i < 800;  i++)
        {
            signal = fir32(&line_model_d2, amp[i]);
            power[0] += ((signal*signal - power[0])/32.0f);
            signal = fir32(&line_model_d3, amp[i]);
            power[1] += ((signal*signal - power[1])/32.0f);
            signal = fir32(&line_model_d4, amp[i]);
            power[2] += ((signal*signal - power[2])/32.0f);
            signal = fir32(&line_model_d5, amp[i]);
            power[3] += ((signal*signal - power[3])/32.0f);
            signal = fir32(&line_model_d6, amp[i]);
            power[4] += ((signal*signal - power[4])/32.0f);
            signal = fir32(&line_model_d7, amp[i]);
            power[5] += ((signal*signal - power[5])/32.0f);
            signal = fir32(&line_model_d8, amp[i]);
            power[6] += ((signal*signal - power[6])/32.0f);
            signal = fir32(&line_model_d9, amp[i]);
            power[7] += ((signal*signal - power[7])/32.0f);
            signal = fir_float(&level_measurement_bp, amp[i]);
            power[8] += ((signal*signal - power[8])/32.0f);
            signal = amp[i];
            power[9] += ((signal*signal - power[9])/32.0f);
        }
        printf("%d %f %f %f %f %f %f %f %f %f %f\n",
               f,
               sqrt(power[0])*LINE_MODEL_D2_GAIN,
               sqrt(power[1])*LINE_MODEL_D3_GAIN,
               sqrt(power[2])*LINE_MODEL_D4_GAIN,
               sqrt(power[3])*LINE_MODEL_D5_GAIN,
               sqrt(power[4])*LINE_MODEL_D6_GAIN,
               sqrt(power[5])*LINE_MODEL_D7_GAIN,
               sqrt(power[6])*LINE_MODEL_D8_GAIN,
               sqrt(power[7])*LINE_MODEL_D9_GAIN,
               sqrt(power[8]),
               sqrt(power[9]));
    }
    awgn_init_dbm0(&noise_source, 1234567, -20.0f);
    for (i = 0;  i < 10;  i++)
        power[i] = 0.0f;
    signal_restart(&local_css, 0.0f);
    signal_restart(&far_css, 0.0f);
    for (i = 0;  i < SAMPLE_RATE;  i++)
    {
        value = signal_amp(&local_css);
        //value = awgn(&noise_source);
        signal = fir32(&line_model_d2, value);
        power[0] += ((signal*signal - power[0])/32.0f);
        signal = fir32(&line_model_d3, value);
        power[1] += ((signal*signal - power[1])/32.0f);
        signal = fir32(&line_model_d4, value);
        power[2] += ((signal*signal - power[2])/32.0f);
        signal = fir32(&line_model_d5, value);
        power[3] += ((signal*signal - power[3])/32.0f);
        signal = fir32(&line_model_d6, value);
        power[4] += ((signal*signal - power[4])/32.0f);
        signal = fir32(&line_model_d7, value);
        power[5] += ((signal*signal - power[5])/32.0f);
        signal = fir32(&line_model_d8, value);
        power[6] += ((signal*signal - power[6])/32.0f);
        signal = fir32(&line_model_d9, value);
        power[7] += ((signal*signal - power[7])/32.0f);
        signal = fir_float(&level_measurement_bp, value);
        power[8] += ((signal*signal - power[8])/32.0f);
        signal = value;
        power[9] += ((signal*signal - power[9])/32.0f);
    }
    for (i = 0;  i < 10;  i++)
        power[i] = 0.0f;
    for (i = 0;  i < SAMPLE_RATE;  i++)
    {
        value = signal_amp(&local_css);
        //value = awgn(&noise_source);
        signal = fir32(&line_model_d2, value);
        power[0] += ((signal*signal - power[0])/32.0f);
        signal = fir32(&line_model_d3, value);
        power[1] += ((signal*signal - power[1])/32.0f);
        signal = fir32(&line_model_d4, value);
        power[2] += ((signal*signal - power[2])/32.0f);
        signal = fir32(&line_model_d5, value);
        power[3] += ((signal*signal - power[3])/32.0f);
        signal = fir32(&line_model_d6, value);
        power[4] += ((signal*signal - power[4])/32.0f);
        signal = fir32(&line_model_d7, value);
        power[5] += ((signal*signal - power[5])/32.0f);
        signal = fir32(&line_model_d8, value);
        power[6] += ((signal*signal - power[6])/32.0f);
        signal = fir32(&line_model_d9, value);
        power[7] += ((signal*signal - power[7])/32.0f);
        signal = fir_float(&level_measurement_bp, value);
        power[8] += ((signal*signal - power[8])/32.0f);
        signal = value;
        power[9] += ((signal*signal - power[9])/32.0f);
    }
    printf("%d %f %f %f %f %f %f %f %f %f %f\n",
           0,
           sqrt(power[0])*LINE_MODEL_D2_GAIN,
           sqrt(power[1])*LINE_MODEL_D3_GAIN,
           sqrt(power[2])*LINE_MODEL_D4_GAIN,
           sqrt(power[3])*LINE_MODEL_D5_GAIN,
           sqrt(power[4])*LINE_MODEL_D6_GAIN,
           sqrt(power[5])*LINE_MODEL_D7_GAIN,
           sqrt(power[6])*LINE_MODEL_D8_GAIN,
           sqrt(power[7])*LINE_MODEL_D9_GAIN,
           sqrt(power[8]),
           sqrt(power[9]));
    printf("%d %f %f %f %f %f %f %f %f %f %f\n",
           0,
           sqrt(power[0]),
           sqrt(power[1]),
           sqrt(power[2]),
           sqrt(power[3]),
           sqrt(power[4]),
           sqrt(power[5]),
           sqrt(power[6]),
           sqrt(power[7]),
           sqrt(power[8]),
           sqrt(power[9]));
    printf("%d %f %f %f %f %f %f %f %f %f %f\n",
           0,
           sqrt(power[0])/sqrt(power[9]),
           sqrt(power[1])/sqrt(power[9]),
           sqrt(power[2])/sqrt(power[9]),
           sqrt(power[3])/sqrt(power[9]),
           sqrt(power[4])/sqrt(power[9]),
           sqrt(power[5])/sqrt(power[9]),
           sqrt(power[6])/sqrt(power[9]),
           sqrt(power[7])/sqrt(power[9]),
           sqrt(power[8]),
           sqrt(power[9]));
    printf("%d %f %f %f %f %f %f %f %f %f %f\n",
           0,
           sqrt(power[0])*LINE_MODEL_D2_GAIN/sqrt(power[9]),
           sqrt(power[1])*LINE_MODEL_D3_GAIN/sqrt(power[9]),
           sqrt(power[2])*LINE_MODEL_D4_GAIN/sqrt(power[9]),
           sqrt(power[3])*LINE_MODEL_D5_GAIN/sqrt(power[9]),
           sqrt(power[4])*LINE_MODEL_D6_GAIN/sqrt(power[9]),
           sqrt(power[5])*LINE_MODEL_D7_GAIN/sqrt(power[9]),
           sqrt(power[6])*LINE_MODEL_D8_GAIN/sqrt(power[9]),
           sqrt(power[7])*LINE_MODEL_D9_GAIN/sqrt(power[9]),
           sqrt(power[8]),
           sqrt(power[9]));

    for (i = 0;  i < (int) (sizeof(css_c1)/sizeof(css_c1[0]));  i++)
        printf("%d\n", css_c1[i]);
    printf("\n");
    for (i = 0;  i < (int) (sizeof(css_c1)/sizeof(css_c3[0]));  i++)
        printf("%d\n", css_c3[i]);
    signal_free(&local_css);
    signal_free(&far_css);
    fir32_free(&line_model_d2);
    fir32_free(&line_model_d3);
    fir32_free(&line_model_d4);
    fir32_free(&line_model_d5);
    fir32_free(&line_model_d6);
    fir32_free(&line_model_d7);
    fir32_free(&line_model_d8);
    fir32_free(&line_model_d9);
    fir_float_free(&level_measurement_bp);
    return 0;
}
示例#13
0
int main(int argc, char *argv[])
{
    tone_gen_descriptor_t tone_desc;
    tone_gen_state_t tone_state;
    int i;
    int16_t amp[16384];
    int len;
    SNDFILE *outhandle;
    int outframes;

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

    /* Try a tone pair */
    tone_gen_descriptor_init(&tone_desc,
                             440,
                             -10,
                             620,
                             -15,
                             100,
                             200,
                             300,
                             400,
                             FALSE);
    tone_gen_init(&tone_state, &tone_desc);

    for (i = 0;  i < 1000;  i++)
    {
        len = tone_gen(&tone_state, amp, 160);
        printf("Generated %d samples\n", len);
        if (len <= 0)
            break;
        outframes = sf_writef_short(outhandle, amp, len);
    }
    
    /* Try a different tone pair */
    tone_gen_descriptor_init(&tone_desc,
                             350,
                             -10,
                             440,
                             -15,
                             400,
                             300,
                             200,
                             100,
                             TRUE);
    tone_gen_init(&tone_state, &tone_desc);

    for (i = 0;  i < 1000;  i++)
    {
        len = tone_gen(&tone_state, amp, 160);
        printf("Generated %d samples\n", len);
        if (len <= 0)
            break;
        outframes = sf_writef_short(outhandle, amp, len);
    }

    /* Try a different tone pair */
    tone_gen_descriptor_init(&tone_desc,
                             400,
                             -10,
                             450,
                             -10,
                             100,
                             200,
                             300,
                             400,
                             TRUE);
    tone_gen_init(&tone_state, &tone_desc);

    for (i = 0;  i < 1000;  i++)
    {
        len = tone_gen(&tone_state, amp, 160);
        printf("Generated %d samples\n", len);
        if (len <= 0)
            break;
        outframes = sf_writef_short(outhandle, amp, len);
    }

    /* Try a single tone */
    tone_gen_descriptor_init(&tone_desc,
                             400,
                             -10,
                             0,
                             0,
                             100,
                             200,
                             300,
                             400,
                             TRUE);
    tone_gen_init(&tone_state, &tone_desc);

    for (i = 0;  i < 1000;  i++)
    {
        len = tone_gen(&tone_state, amp, 160);
        printf("Generated %d samples\n", len);
        if (len <= 0)
            break;
        outframes = sf_writef_short(outhandle, amp, len);
    }

    /* Try a single non-repeating tone */
    tone_gen_descriptor_init(&tone_desc,
                             820,
                             -10,
                             0,
                             0,
                             2000,
                             0,
                             0,
                             0,
                             FALSE);
    tone_gen_init(&tone_state, &tone_desc);

    for (i = 0;  i < 1000;  i++)
    {
        len = tone_gen(&tone_state, amp, 160);
        printf("Generated %d samples\n", len);
        if (len <= 0)
            break;
        outframes = sf_writef_short(outhandle, amp, len);
    }

    /* Try a single non-repeating tone at 0dBm0 */
    tone_gen_descriptor_init(&tone_desc,
                             820,
                             0,
                             0,
                             0,
                             2000,
                             0,
                             0,
                             0,
                             FALSE);
    tone_gen_init(&tone_state, &tone_desc);

    for (i = 0;  i < 1000;  i++)
    {
        len = tone_gen(&tone_state, amp, 160);
        printf("Generated %d samples\n", len);
        if (len <= 0)
            break;
        outframes = sf_writef_short(outhandle, amp, len);
    }

    /* Try an AM modulated tone at a modest modulation level (25%) */
    tone_gen_descriptor_init(&tone_desc,
                             425,
                             -10,
                             -50,
                             25,
                             100,
                             200,
                             300,
                             400,
                             TRUE);
    tone_gen_init(&tone_state, &tone_desc);

    for (i = 0;  i < 1000;  i++)
    {
        len = tone_gen(&tone_state, amp, 160);
        printf("Generated %d samples\n", len);
        if (len <= 0)
            break;
        outframes = sf_writef_short(outhandle, amp, len);
    }
    
    /* Try an AM modulated tone at maximum modulation level (100%) */
    tone_gen_descriptor_init(&tone_desc,
                             425,
                             -10,
                             -50,
                             100,
                             100,
                             200,
                             300,
                             400,
                             TRUE);
    tone_gen_init(&tone_state, &tone_desc);

    for (i = 0;  i < 1000;  i++)
    {
        len = tone_gen(&tone_state, amp, 160);
        printf("Generated %d samples\n", len);
        if (len <= 0)
            break;
        outframes = sf_writef_short(outhandle, amp, len);
    }
    
    if (sf_close(outhandle) != 0)
    {
        fprintf(stderr, "    Cannot close audio file '%s'\n", OUTPUT_FILE_NAME);
        exit (2);
    }

    return  0;
}
示例#14
0
int main(int argc, char *argv[])
{
    echo_can_state_t *ctx;
    awgn_state_t local_noise_source;
    awgn_state_t far_noise_source;
    int i;
    int clean;
    int residue;
    int16_t rx;
    int16_t tx;
    int j;
    int k;
    tone_gen_descriptor_t tone_desc;
    tone_gen_state_t tone_state;
    int16_t local_sound[40000];
    int local_max;
    int local_cur;
    int16_t hoth_noise;
    //int16_t far_sound[SAMPLE_RATE];
    //int16_t result_sound[64000];
    //int32_t coeffs[200][128];
    //int coeff_index;
    int far_cur;
    int result_cur;
    //int far_tx;
    AFfilehandle resulthandle;
    AFfilesetup filesetup;
    AFfilesetup filesetup2;
    //int outframes;
    time_t now;
    int tone_burst_step;
    level_measurement_device_t *power_meter_1;
    level_measurement_device_t *power_meter_2;
    float pp1;
    float pp2;
    int model_number;
    int use_gui;

    power_meter_1 = NULL;
    power_meter_2 = NULL;
    /* Check which tests we should run */
    if (argc < 2)
        fprintf(stderr, "Usage: echo tests <list of test numbers>\n");
    test_list = 0;
    model_number = 0;
    use_gui = FALSE;
    for (i = 1;  i < argc;  i++)
    {
        if (strcasecmp(argv[i], "2a") == 0)
            test_list |= PERFORM_TEST_2A;
        else if (strcasecmp(argv[i], "2b") == 0)
            test_list |= PERFORM_TEST_2B;
        else if (strcasecmp(argv[i], "2c") == 0)
            test_list |= PERFORM_TEST_2C;
        else if (strcasecmp(argv[i], "3a") == 0)
            test_list |= PERFORM_TEST_3A;
        else if (strcasecmp(argv[i], "3b") == 0)
            test_list |= PERFORM_TEST_3B;
        else if (strcasecmp(argv[i], "3c") == 0)
            test_list |= PERFORM_TEST_3C;
        else if (strcasecmp(argv[i], "4") == 0)
            test_list |= PERFORM_TEST_4;
        else if (strcasecmp(argv[i], "5") == 0)
            test_list |= PERFORM_TEST_5;
        else if (strcasecmp(argv[i], "6") == 0)
            test_list |= PERFORM_TEST_6;
        else if (strcasecmp(argv[i], "7") == 0)
            test_list |= PERFORM_TEST_7;
        else if (strcasecmp(argv[i], "8") == 0)
            test_list |= PERFORM_TEST_8;
        else if (strcasecmp(argv[i], "9") == 0)
            test_list |= PERFORM_TEST_9;
        else if (strcasecmp(argv[i], "10a") == 0)
            test_list |= PERFORM_TEST_10A;
        else if (strcasecmp(argv[i], "10b") == 0)
            test_list |= PERFORM_TEST_10B;
        else if (strcasecmp(argv[i], "10c") == 0)
            test_list |= PERFORM_TEST_10C;
        else if (strcasecmp(argv[i], "11") == 0)
            test_list |= PERFORM_TEST_11;
        else if (strcasecmp(argv[i], "12") == 0)
            test_list |= PERFORM_TEST_12;
        else if (strcasecmp(argv[i], "13") == 0)
            test_list |= PERFORM_TEST_13;
        else if (strcasecmp(argv[i], "14") == 0)
            test_list |= PERFORM_TEST_14;
        else if (strcasecmp(argv[i], "15") == 0)
            test_list |= PERFORM_TEST_15;
        else if (strcmp(argv[i], "-m") == 0)
        {
            if (++i < argc)
                model_number = atoi(argv[i]);
        }
        else if (strcmp(argv[i], "-g") == 0)
        {
            use_gui = TRUE;
        }
        else
        {
            fprintf(stderr, "Unknown test '%s' specified\n", argv[i]);
            exit(2);
        }
    }
    if (test_list == 0)
    {
        fprintf(stderr, "No tests have been selected\n");
        exit(2);
    }
    time(&now);
    tone_burst_step = 0;
    ctx = echo_can_create(TEST_EC_TAPS, 0);
    awgn_init_dbm0(&far_noise_source, 7162534, -50.0f);

    signal_load(&local_css, "sound_c1_8k.wav");
    signal_load(&far_css, "sound_c3_8k.wav");

    filesetup = afNewFileSetup();
    if (filesetup == 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, 6);

    filesetup2 = afNewFileSetup();
    if (filesetup2 == AF_NULL_FILESETUP)
    {
        fprintf(stderr, "    Failed to create file setup\n");
        exit(2);
    }
    afInitSampleFormat(filesetup2, AF_DEFAULT_TRACK, AF_SAMPFMT_TWOSCOMP, 16);
    afInitRate(filesetup2, AF_DEFAULT_TRACK, (float) SAMPLE_RATE);
    afInitFileFormat(filesetup2, AF_FILE_WAVE);
    afInitChannels(filesetup2, AF_DEFAULT_TRACK, 1);

    resulthandle = afOpenFile("result_sound.wav", "w", filesetup);
    if (resulthandle == AF_NULL_FILEHANDLE)
    {
        fprintf(stderr, "    Failed to open result file\n");
        exit(2);
    }

    residuehandle = afOpenFile("residue_sound.wav", "w", filesetup2);
    if (residuehandle == AF_NULL_FILEHANDLE)
    {
        fprintf(stderr, "    Failed to open residue file\n");
        exit(2);
    }
    local_cur = 0;
    far_cur = 0;
    result_cur = 0;
    if (channel_model_create(model_number))
    {
        fprintf(stderr, "    Failed to create line model\n");
        exit(2);
    }
#if defined(ENABLE_GUI)
    if (use_gui)
    {
        start_echo_can_monitor(TEST_EC_TAPS);
        echo_can_monitor_line_model_update(line_model.coeffs, line_model.taps);
    }
#endif
    power_meter_1 = level_measurement_device_create(0);
    power_meter_2 = level_measurement_device_create(0);

    level_measurement_device(power_meter_1, 0);

#if 0
    echo_can_flush(ctx);
    /* Converge the canceller */
    signal_restart(&local_css);
    for (i = 0;  i < 800*2;  i++)
    {
        clean = echo_can_update(ctx, 0, 0);
        put_residue(clean);
    }
    for (i = 0;  i < SAMPLE_RATE*5;  i++)
    {
        tx = signal_amp(&local_css);
        channel_model(&tx, &rx, tx, 0);
        clean = echo_can_update(ctx, tx, rx);
        put_residue(clean);
    }
    echo_can_adaption_mode(ctx, ECHO_CAN_USE_ADAPTION | ECHO_CAN_USE_NLP | ECHO_CAN_USE_CNG);
    for (i = 0;  i < SAMPLE_RATE*5;  i++)
    {
        tx = signal_amp(&local_css);
        channel_model(&tx, &rx, tx, 0);
        clean = echo_can_update(ctx, tx, rx);
        put_residue(clean);
    }
    echo_can_adaption_mode(ctx, ECHO_CAN_USE_ADAPTION);
    
    for (i = 0;  i < SAMPLE_RATE*10;  i++)
    {
        tx = signal_amp(&local_css);
#if 0
        if ((i/10000)%10 == 9)
        {
            /* Inject a burst of far sound */
            if (far_cur >= far_max)
            {
                far_max = afReadFrames(farhandle, AF_DEFAULT_TRACK, far_sound, SAMPLE_RATE);
                if (far_max < 0)
                {
                    fprintf(stderr, "    Error reading far sound\n");
                    exit(2);
                }
                if (far_max == 0)
                    break;
                far_cur = 0;
            }
            far_tx = far_sound[far_cur++];
        }
        else
        {
            far_tx = 0;
        }
#else
        far_sound[0] = 0;
        far_tx = 0;
#endif
        channel_model(&tx, &rx, tx, far_tx);
        //rx += awgn(&far_noise_source);
        //tx += awgn(&far_noise_source);
        clean = echo_can_update(ctx, tx, rx);

#if defined(XYZZY)
        if (i%SAMPLE_RATE == 0)
        {
            if (coeff_index < 200)
            {
                for (j = 0;  j < ctx->taps;  j++)
                    coeffs[coeff_index][j] = ctx->fir_taps32[j];
                coeff_index++;
            }
        }
#endif
        result_sound[result_cur++] = tx;
        result_sound[result_cur++] = rx;
        result_sound[result_cur++] = clean - far_tx;
        //result_sound[result_cur++] = ctx->tx_power[2];
        //result_sound[result_cur++] = ctx->tx_power[1];
        result_sound[result_cur++] = (ctx->tx_power[1] > 64)  ?  SAMPLE_RATE  :  -SAMPLE_RATE;
        //result_sound[result_cur++] = ctx->tap_set*SAMPLE_RATE;
        //result_sound[result_cur++] = (ctx->nonupdate_dwell > 0)  ?  SAMPLE_RATE  :  -SAMPLE_RATE;
        //result_sound[result_cur++] = ctx->latest_correction >> 8;
        //result_sound[result_cur++] = level_measurement_device(tx)/(16.0*65536.0);
        //result_sound[result_cur++] = level_measurement_device(tx)/4096.0;
        result_sound[result_cur++] = (ctx->tx_power[1] > ctx->rx_power[0])  ?  SAMPLE_RATE  :  -SAMPLE_RATE;
        //result_sound[result_cur++] = (ctx->tx_power[1] > ctx->rx_power[0])  ?  SAMPLE_RATE  :  -SAMPLE_RATE;
        //result_sound[result_cur++] = (ctx->narrowband_score)*5; //  ?  SAMPLE_RATE  :  -SAMPLE_RATE;
        //result_sound[result_cur++] = ctx->tap_rotate_counter*10;
        result_sound[result_cur++] = ctx->vad;
        
        put_residue(clean - far_tx);
        if (result_cur >= 6*SAMPLE_RATE)
        {
            outframes = afWriteFrames(resulthandle,
                                      AF_DEFAULT_TRACK,
                                      result_sound,
                                      result_cur/6);
            if (outframes != result_cur/6)
            {
                fprintf(stderr, "    Error writing result sound\n");
                exit(2);
            }
            result_cur = 0;
        }
    }
    if (result_cur > 0)
    {
        outframes = afWriteFrames(resulthandle,
                                  AF_DEFAULT_TRACK,
                                  result_sound,
                                  result_cur/6);
        if (outframes != result_cur/4)
        {
            fprintf(stderr, "    Error writing result sound\n");
            exit(2);
        }
    }
#endif

    /* Test 1 - Steady state residual and returned echo level test */
    /* This functionality has been merged with test 2 in newer versions of G.168,
       so test 1 no longer exists. */

    /* Test 2 - Convergence and steady state residual and returned echo level test */
    if ((test_list & PERFORM_TEST_2A))
    {
        printf("Performing test 2A - Convergence with NLP enabled\n");
        /* Test 2A - Convergence with NLP enabled */
        echo_can_flush(ctx);
        echo_can_adaption_mode(ctx, ECHO_CAN_USE_ADAPTION | ECHO_CAN_USE_NLP);
        /* Converge the canceller */
        signal_restart(&local_css);
        for (i = 0;  i < 800*2;  i++)
        {
            clean = echo_can_update(ctx, 0, 0);
            put_residue(clean);
        }
        for (i = 0;  i < SAMPLE_RATE*50;  i++)
        {
            tx = signal_amp(&local_css);
            channel_model(&tx, &rx, tx, 0);
            clean = echo_can_update(ctx, tx, rx);
            pp1 = level_measurement_device(power_meter_1, rx);
            pp2 = level_measurement_device(power_meter_2, clean);
            residue = 100.0*pp1/pp2;
            put_residue(residue);
#if defined(ENABLE_GUI)
            if (use_gui)
                echo_can_monitor_can_update(ctx->fir_taps16[ctx->tap_set], TEST_EC_TAPS);
#endif
        }
#if defined(ENABLE_GUI)
        if (use_gui)
            echo_can_monitor_can_update(ctx->fir_taps16[ctx->tap_set], TEST_EC_TAPS);
#endif
    }

    if ((test_list & PERFORM_TEST_2B))
    {
        printf("Performing test 2B - Convergence with NLP disabled\n");
        /* Test 2B - Convergence with NLP disabled */
        echo_can_flush(ctx);
        echo_can_adaption_mode(ctx, ECHO_CAN_USE_ADAPTION);
        /* Converge a canceller */
        signal_restart(&local_css);
        for (i = 0;  i < 800*2;  i++)
        {
            clean = echo_can_update(ctx, 0, 0);
            put_residue(clean);
        }
        for (i = 0;  i < SAMPLE_RATE*5;  i++)
        {
            tx = signal_amp(&local_css);
            channel_model(&tx, &rx, tx, 0);
            clean = echo_can_update(ctx, tx, rx);
            put_residue(clean);
#if defined(ENABLE_GUI)
            if (use_gui)
                echo_can_monitor_can_update(ctx->fir_taps16[ctx->tap_set], TEST_EC_TAPS);
#endif
        }
#if defined(ENABLE_GUI)
        if (use_gui)
            echo_can_monitor_can_update(ctx->fir_taps16[ctx->tap_set], TEST_EC_TAPS);
#endif
    }

    if ((test_list & PERFORM_TEST_2C))
    {
        printf("Performing test 2C - Convergence with background noise present\n");
        /* Test 2C - Convergence with background noise present */
        echo_can_flush(ctx);
        echo_can_adaption_mode(ctx, ECHO_CAN_USE_ADAPTION);
        /* Converge a canceller */
        signal_restart(&local_css);
        for (i = 0;  i < 800*2;  i++)
        {
            clean = echo_can_update(ctx, 0, 0);
            put_residue(clean);
        }
        /* TODO: This uses a crude approx. to Hoth noise. We need the real thing. */
        awgn_init_dbm0(&far_noise_source, 7162534, -40.0f);
        hoth_noise = 0;
        for (i = 0;  i < SAMPLE_RATE*5;  i++)
        {
            hoth_noise = hoth_noise*0.625 + awgn(&far_noise_source)*0.375;
            tx = signal_amp(&local_css);
            channel_model(&tx, &rx, tx, hoth_noise);
            clean = echo_can_update(ctx, tx, rx);
            put_residue(clean);
        }
        /* Now freeze adaption, and measure the echo. */
        echo_can_adaption_mode(ctx, 0);
        for (i = 0;  i < SAMPLE_RATE*5;  i++)
        {
            tx = signal_amp(&local_css);
            channel_model(&tx, &rx, tx, 0);
            clean = echo_can_update(ctx, tx, rx);
            put_residue(clean);
        }
        echo_can_adaption_mode(ctx, ECHO_CAN_USE_ADAPTION);
#if defined(ENABLE_GUI)
        if (use_gui)
            echo_can_monitor_can_update(ctx->fir_taps16[ctx->tap_set], TEST_EC_TAPS);
#endif
    }

    /* Test 3 - Performance under double talk conditions */
    if ((test_list & PERFORM_TEST_3A))
    {
        printf("Performing test 3A - Double talk test with low cancelled-end levels\n");
        /* Test 3A - Double talk test with low cancelled-end levels */
        echo_can_flush(ctx);
        echo_can_adaption_mode(ctx, ECHO_CAN_USE_ADAPTION);
        signal_restart(&local_css);
        signal_restart(&far_css);
        /* Apply double talk, with a weak far end signal */
        for (i = 0;  i < SAMPLE_RATE*5;  i++)
        {
            tx = signal_amp(&local_css);
            rx = signal_amp(&far_css)/20;
            channel_model(&tx, &rx, tx, rx);
            clean = echo_can_update(ctx, tx, rx);
            put_residue(clean - rx);
        }
        /* Now freeze adaption. */
        echo_can_adaption_mode(ctx, 0);
        for (i = 0;  i < 800*5;  i++)
        {
            tx = signal_amp(&local_css);
            channel_model(&tx, &rx, tx, 0);
            clean = echo_can_update(ctx, tx, rx);
            put_residue(clean);
        }
        /* Now measure the echo */
        for (i = 0;  i < SAMPLE_RATE*5;  i++)
        {
            tx = signal_amp(&local_css);
            channel_model(&tx, &rx, tx, 0);
            clean = echo_can_update(ctx, tx, rx);
            put_residue(clean);
        }
        echo_can_adaption_mode(ctx, ECHO_CAN_USE_ADAPTION);
#if defined(ENABLE_GUI)
        if (use_gui)
            echo_can_monitor_can_update(ctx->fir_taps16[ctx->tap_set], TEST_EC_TAPS);
#endif
    }

    if ((test_list & PERFORM_TEST_3B))
    {
        printf("Performing test 3B - Double talk test with high cancelled-end levels\n");
        /* Test 3B - Double talk test with high cancelled-end levels */
        echo_can_flush(ctx);
        echo_can_adaption_mode(ctx, ECHO_CAN_USE_ADAPTION);
        signal_restart(&local_css);
        signal_restart(&far_css);
        /* Converge the canceller */
        for (i = 0;  i < SAMPLE_RATE*5;  i++)
        {
            tx = signal_amp(&local_css);
            channel_model(&tx, &rx, tx, 0);
            clean = echo_can_update(ctx, tx, rx);
            put_residue(clean);
        }
        /* Apply double talk */
        for (i = 0;  i < SAMPLE_RATE*5;  i++)
        {
            tx = signal_amp(&local_css);
            rx = signal_amp(&far_css);
            channel_model(&tx, &rx, tx, rx);
            clean = echo_can_update(ctx, tx, rx);
            put_residue(clean - rx);
        }
        /* Now freeze adaption. */
        echo_can_adaption_mode(ctx, 0);
        for (i = 0;  i < 800*5;  i++)
        {
            tx = signal_amp(&local_css);
            channel_model(&tx, &rx, tx, 0);
            clean = echo_can_update(ctx, tx, rx);
            put_residue(clean);
        }
        /* Now measure the echo */
        for (i = 0;  i < SAMPLE_RATE*5;  i++)
        {
            tx = signal_amp(&local_css);
            channel_model(&tx, &rx, tx, 0);
            clean = echo_can_update(ctx, tx, rx);
            put_residue(clean);
        }
        echo_can_adaption_mode(ctx, ECHO_CAN_USE_ADAPTION);
#if defined(ENABLE_GUI)
        if (use_gui)
            echo_can_monitor_can_update(ctx->fir_taps16[ctx->tap_set], TEST_EC_TAPS);
#endif
    }

    if ((test_list & PERFORM_TEST_3C))
    {
        printf("Performing test 3C - Double talk test with simulated conversation\n");
        /* Test 3C - Double talk test with simulated conversation */
        echo_can_flush(ctx);
        echo_can_adaption_mode(ctx, ECHO_CAN_USE_ADAPTION);
        signal_restart(&local_css);
        signal_restart(&far_css);
        /* Apply double talk */
        for (i = 0;  i < 800*56;  i++)
        {
            tx = signal_amp(&local_css);
            rx = signal_amp(&far_css);
            channel_model(&tx, &rx, tx, rx);
            clean = echo_can_update(ctx, tx, rx);
            put_residue(clean - rx);
        }
        /* Stop the far signal */
        for (i = 0;  i < 800*14;  i++)
        {
            tx = signal_amp(&local_css);
            channel_model(&tx, &rx, tx, 0);
            clean = echo_can_update(ctx, tx, rx);
            put_residue(clean);
        }
        /* Continue measuring the resulting echo */
        for (i = 0;  i < 800*50;  i++)
        {
            tx = signal_amp(&local_css);
            channel_model(&tx, &rx, tx, 0);
            clean = echo_can_update(ctx, tx, rx);
            put_residue(clean);
        }
        /* Reapply double talk */
        signal_restart(&far_css);
        for (i = 0;  i < 800*56;  i++)
        {
            tx = signal_amp(&local_css);
            rx = signal_amp(&far_css);
            channel_model(&tx, &rx, tx, rx);
            clean = echo_can_update(ctx, tx, rx);
            put_residue(clean - rx);
        }
        /* Now the far signal only */
        for (i = 0;  i < 800*56;  i++)
        {
            tx = 0;
            rx = signal_amp(&far_css);
            channel_model(&tx, &rx, 0, rx);
            clean = echo_can_update(ctx, tx, rx);
            put_residue(clean - rx);
        }
#if defined(ENABLE_GUI)
        if (use_gui)
            echo_can_monitor_can_update(ctx->fir_taps16[ctx->tap_set], TEST_EC_TAPS);
#endif
    }

    if ((test_list & PERFORM_TEST_4))
    {
        printf("Performing test 4 - Leak rate test\n");
        /* Test 4 - Leak rate test */
        echo_can_flush(ctx);
        echo_can_adaption_mode(ctx, ECHO_CAN_USE_ADAPTION);
        /* Converge a canceller */
        signal_restart(&local_css);
        for (i = 0;  i < SAMPLE_RATE*5;  i++)
        {
            tx = signal_amp(&local_css);
            channel_model(&tx, &rx, tx, 0);
            clean = echo_can_update(ctx, tx, rx);
            put_residue(clean);
        }
        /* Put 2 minutes of silence through it */
        for (i = 0;  i < SAMPLE_RATE*120;  i++)
        {
            clean = echo_can_update(ctx, 0, 0);
            put_residue(clean);
        }
        /* Now freeze it, and check if it is still well adapted. */
        echo_can_adaption_mode(ctx, 0);
        for (i = 0;  i < SAMPLE_RATE*5;  i++)
        {
            tx = signal_amp(&local_css);
            channel_model(&tx, &rx, tx, 0);
            clean = echo_can_update(ctx, tx, rx);
            put_residue(clean);
        }
        echo_can_adaption_mode(ctx, ECHO_CAN_USE_ADAPTION);
#if defined(ENABLE_GUI)
        if (use_gui)
            echo_can_monitor_can_update(ctx->fir_taps16[ctx->tap_set], TEST_EC_TAPS);
#endif
    }

    if ((test_list & PERFORM_TEST_5))
    {
        printf("Performing test 5 - Infinite return loss convergence test\n");
        /* Test 5 - Infinite return loss convergence test */
        echo_can_flush(ctx);
        echo_can_adaption_mode(ctx, ECHO_CAN_USE_ADAPTION);
        /* Converge the canceller */
        signal_restart(&local_css);
        for (i = 0;  i < SAMPLE_RATE*5;  i++)
        {
            tx = signal_amp(&local_css);
            channel_model(&tx, &rx, tx, 0);
            clean = echo_can_update(ctx, tx, rx);
            put_residue(clean);
        }
        /* Now stop echoing, and see we don't do anything unpleasant as the
           echo path is open looped. */
        for (i = 0;  i < SAMPLE_RATE*5;  i++)
        {
            tx = signal_amp(&local_css);
            rx = 0;
            tx = codec_munge(tx);
            clean = echo_can_update(ctx, tx, rx);
            put_residue(clean);
        }
#if defined(ENABLE_GUI)
        if (use_gui)
            echo_can_monitor_can_update(ctx->fir_taps16[ctx->tap_set], TEST_EC_TAPS);
#endif
    }

    if ((test_list & PERFORM_TEST_6))
    {
        printf("Performing test 6 - Non-divergence on narrow-band signals\n");
        /* Test 6 - Non-divergence on narrow-band signals */
        echo_can_flush(ctx);
        echo_can_adaption_mode(ctx, ECHO_CAN_USE_ADAPTION);
        /* Converge the canceller */
        signal_restart(&local_css);
        for (i = 0;  i < SAMPLE_RATE*5;  i++)
        {
            tx = signal_amp(&local_css);
            channel_model(&tx, &rx, tx, 0);
            clean = echo_can_update(ctx, tx, rx);
            put_residue(clean);
        }
        /* Now put 5s bursts of a list of tones through the converged canceller, and check
           that bothing unpleasant happens. */
        for (k = 0;  tones_6_4_2_7[k][0];  k++)
        {
            make_tone_gen_descriptor(&tone_desc,
                                     tones_6_4_2_7[k][0],
                                     -11,
                                     tones_6_4_2_7[k][1],
                                     -9,
                                     1,
                                     0,
                                     0,
                                     0,
                                     1);
            tone_gen_init(&tone_state, &tone_desc);
            j = 0;
            for (i = 0;  i < 5;  i++)
            {
                local_max = tone_gen(&tone_state, local_sound, SAMPLE_RATE);
                for (j = 0;  j < SAMPLE_RATE;  j++)
                {
                    tx = local_sound[j];
                    channel_model(&tx, &rx, tx, 0);
                    clean = echo_can_update(ctx, tx, rx);
                    put_residue(clean);
                }
#if defined(ENABLE_GUI)
                if (use_gui)
                {
                    echo_can_monitor_can_update(ctx->fir_taps16[ctx->tap_set], TEST_EC_TAPS);
                    echo_can_monitor_update_display();
                    usleep(100000);
                }
#endif
            }
        }
#if defined(ENABLE_GUI)
        if (use_gui)
            echo_can_monitor_can_update(ctx->fir_taps16[ctx->tap_set], TEST_EC_TAPS);
#endif
    }

    if ((test_list & PERFORM_TEST_7))
    {
        printf("Performing test 7 - Stability\n");
        /* Test 7 - Stability */
        /* Put tones through an unconverged canceller, and check nothing unpleasant
           happens. */
        echo_can_flush(ctx);
        echo_can_adaption_mode(ctx, ECHO_CAN_USE_ADAPTION);
        make_tone_gen_descriptor(&tone_desc,
                                 tones_6_4_2_7[0][0],
                                 -11,
                                 tones_6_4_2_7[0][1],
                                 -9,
                                 1,
                                 0,
                                 0,
                                 0,
                                 1);
        tone_gen_init(&tone_state, &tone_desc);
        j = 0;
        for (i = 0;  i < 120;  i++)
        {
            local_max = tone_gen(&tone_state, local_sound, SAMPLE_RATE);
            for (j = 0;  j < SAMPLE_RATE;  j++)
            {
                tx = local_sound[j];
                channel_model(&tx, &rx, tx, 0);
                clean = echo_can_update(ctx, tx, rx);
                put_residue(clean);
            }
#if defined(ENABLE_GUI)
            if (use_gui)
            {
                echo_can_monitor_can_update(ctx->fir_taps16[ctx->tap_set], TEST_EC_TAPS);
                echo_can_monitor_update_display();
                usleep(100000);
            }
#endif
        }
#if defined(ENABLE_GUI)
        if (use_gui)
            echo_can_monitor_can_update(ctx->fir_taps16[ctx->tap_set], TEST_EC_TAPS);
#endif
    }

    if ((test_list & PERFORM_TEST_8))
    {
        printf("Performing test 8 - Non-convergence on No 5, 6, and 7 in-band signalling\n");
        /* Test 8 - Non-convergence on No 5, 6, and 7 in-band signalling */
        fprintf(stderr, "Test 8 not yet implemented\n");
    }

    if ((test_list & PERFORM_TEST_9))
    {
        printf("Performing test 9 - Comfort noise test\n");
        /* Test 9 - Comfort noise test */
        /* Test 9 part 1 - matching */
        echo_can_flush(ctx);
        echo_can_adaption_mode(ctx, ECHO_CAN_USE_ADAPTION);
        /* Converge the canceller */
        signal_restart(&local_css);
        for (i = 0;  i < SAMPLE_RATE*5;  i++)
        {
            tx = signal_amp(&local_css);
            channel_model(&tx, &rx, tx, 0);
            clean = echo_can_update(ctx, tx, rx);
            put_residue(clean);
        }
        echo_can_adaption_mode(ctx, ECHO_CAN_USE_ADAPTION | ECHO_CAN_USE_NLP | ECHO_CAN_USE_CNG);
        awgn_init_dbm0(&far_noise_source, 7162534, -45.0f);
        for (i = 0;  i < SAMPLE_RATE*30;  i++)
        {
            tx = 0;
            rx = awgn(&far_noise_source);
            channel_model(&tx, &rx, tx, rx);
            clean = echo_can_update(ctx, tx, rx);
            put_residue(clean);
        }
        awgn_init_dbm0(&local_noise_source, 1234567, -10.0f);
        for (i = 0;  i < SAMPLE_RATE*2;  i++)
        {
            tx = awgn(&local_noise_source);
            rx = awgn(&far_noise_source);
            channel_model(&tx, &rx, tx, rx);
            clean = echo_can_update(ctx, tx, rx);
            put_residue(clean);
        }

        /* Test 9 part 2 - adjust down */
        awgn_init_dbm0(&far_noise_source, 7162534, -55.0f);
        for (i = 0;  i < SAMPLE_RATE*10;  i++)
        {
            tx = 0;
            rx = awgn(&far_noise_source);
            channel_model(&tx, &rx, tx, rx);
            clean = echo_can_update(ctx, tx, rx);
            put_residue(clean);
        }
        for (i = 0;  i < SAMPLE_RATE*2;  i++)
        {
            tx = awgn(&local_noise_source);
            rx = awgn(&far_noise_source);
            channel_model(&tx, &rx, tx, rx);
            clean = echo_can_update(ctx, tx, rx);
            put_residue(clean);
        }
#if defined(ENABLE_GUI)
        if (use_gui)
            echo_can_monitor_can_update(ctx->fir_taps16[ctx->tap_set], TEST_EC_TAPS);
#endif
    }

    /* Test 10 - FAX test during call establishment phase */
    if ((test_list & PERFORM_TEST_10A))
    {
        printf("Performing test 10A - Canceller operation on the calling station side\n");
        /* Test 10A - Canceller operation on the calling station side */
        fprintf(stderr, "Test 10A not yet implemented\n");
    }

    if ((test_list & PERFORM_TEST_10B))
    {
        printf("Performing test 10B - Canceller operation on the called station side\n");
        /* Test 10B - Canceller operation on the called station side */
        fprintf(stderr, "Test 10B not yet implemented\n");
    }

    if ((test_list & PERFORM_TEST_10C))
    {
        printf("Performing test 10C - Canceller operation on the calling station side during page\n"
               "transmission and page breaks (for further study)\n");
        /* Test 10C - Canceller operation on the calling station side during page
                      transmission and page breaks (for further study) */
        fprintf(stderr, "Test 10C not yet implemented\n");
    }

    if ((test_list & PERFORM_TEST_11))
    {
        printf("Performing test 11 - Tandem echo canceller test (for further study)\n");
        /* Test 11 - Tandem echo canceller test (for further study) */
        fprintf(stderr, "Test 11 not yet implemented\n");
    }

    if ((test_list & PERFORM_TEST_12))
    {
        printf("Performing test 12 - Residual acoustic echo test (for further study)\n");
        /* Test 12 - Residual acoustic echo test (for further study) */
        fprintf(stderr, "Test 12 not yet implemented\n");
    }

    if ((test_list & PERFORM_TEST_13))
    {
        printf("Performing test 13 - Performance with ITU-T low-bit rate coders in echo path (Optional, under study)\n");
        /* Test 13 - Performance with ITU-T low-bit rate coders in echo path
                     (Optional, under study) */
        fprintf(stderr, "Test 13 not yet implemented\n");
    }

    if ((test_list & PERFORM_TEST_14))
    {
        printf("Performing test 14 - Performance with V-series low-speed data modems\n");
        /* Test 14 - Performance with V-series low-speed data modems */
        fprintf(stderr, "Test 14 not yet implemented\n");
    }

    if ((test_list & PERFORM_TEST_15))
    {
        printf("Performing test 15 - PCM offset test (Optional)\n");
        /* Test 15 - PCM offset test (Optional) */
        fprintf(stderr, "Test 15 not yet implemented\n");
    }

    echo_can_free(ctx);

    signal_free(&local_css);
    signal_free(&far_css);

    if (afCloseFile(resulthandle) != 0)
    {
        fprintf(stderr, "    Cannot close speech file '%s'\n", "result_sound.wav");
        exit(2);
    }
    if (afCloseFile(residuehandle) != 0)
    {
        fprintf(stderr, "    Cannot close speech file '%s'\n", "residue_sound.wav");
        exit(2);
    }
    afFreeFileSetup(filesetup);
    afFreeFileSetup(filesetup2);

#if defined(XYZZY)
    for (j = 0;  j < ctx->taps;  j++)
    {
        for (i = 0;  i < coeff_index;  i++)
            fprintf(stderr, "%d ", coeffs[i][j]);
        fprintf(stderr, "\n");
    }
#endif
    printf("Run time %lds\n", time(NULL) - now);
    
#if defined(ENABLE_GUI)
    if (use_gui)
        echo_can_monitor_wait_to_end();
#endif

    if (power_meter_1)
        level_measurement_device_release(power_meter_1);
    if (power_meter_2)
        level_measurement_device_release(power_meter_2);

    printf("Tests passed.\n");
    return  0;
}
示例#15
0
/*------------------------------------------------------------------
*                       tty_gen()
*-------------------------------------------------------------------*/
Word16 tty_gen(
    Word16   outbuf[],           /* (o): output buffer                   */
    Word16   length,             /* (i): length of buffer                */
    Word16   subframe,           /* (i): subframe counter                */
    Word16   num_subfr,          /* (i): number of subframes/frame       */
    Word16   counter_hist[],     /* (i/o): tty counter history           */
    Word16   char_hist[],        /* (i/o): tty character history         */
    Word16   tty_rate_hist[]     /* (i/o): tty baud rate history         */
)
{
    Word16   i;
    Word16   num;
    Word16   bit;
    Word16   *p_buf;
    Word16   write_flag;



    bit = 0;    /* eliminates compiler warning */

                                                            
    /* Change onset to silence */
    if( sub(counter_hist[CURRENT_FRAME],TTY_ONSET) == 0 )
    {
        counter_hist[CURRENT_FRAME] = TTY_SILENCE;          
        char_hist[CURRENT_FRAME] = TTY_SILENCE_CHAR;        
    }

                                                            
    /* If transition from silence to anything else */
    if( (current_counter & (TTY_SILENCE|NON_TTY)) != 0
        && sub(counter_hist[CURRENT_FRAME],TTY_SILENCE) != 0
      )
    {
        init_tty_gen( counter_hist[CURRENT_FRAME],
                      char_hist[CURRENT_FRAME],
                      tty_rate_hist[CURRENT_FRAME]);
    }

    /* else if transition from NON_TTY to TTY_SILENCE */

    else if( sub(current_counter,NON_TTY) == 0
             && sub(counter_hist[CURRENT_FRAME],TTY_SILENCE) == 0
           )
    {
                                                            
        init_tty_gen( TTY_SILENCE, TTY_SILENCE_CHAR, 0);
    }

    /* else if a new character is coming before the old one is finished */
    else if( subframe == 0
             && sub(current_counter,counter_hist[CURRENT_FRAME]) != 0
             && (counter_hist[CURRENT_FRAME] & COUNTER_BETWEEN_START_STOP) != 0
           )
    {

#if TTY_HALF_DUPLEX_FIX
        if( sub(bit_num,MARK_HOLD_BIT_NUM) >= 0 )
#else
        if( sub(bit_num,MARK_HOLD_BIT_NUM) == 0 )
#endif
        {
            /* Cut short the mark hold tone to start new character */
            init_tty_gen( counter_hist[CURRENT_FRAME],
                          char_hist[CURRENT_FRAME],
                          tty_rate_hist[CURRENT_FRAME]);
        }
        else if( sub(bit_num,STOP_BIT_NUM) == 0
                 && sub(bit_size,FRAMESIZE) >= 0
               )
        {
            /* Shorten the stop bit to 1 bit length if it will be done this frame */

#if TTY_GEN_50_BAUD_FIX
#if TTY_NOMINAL_BIT_LEN_FIX
            data_bit_len[TTY_45_BAUD] = DATA_BIT_LEN_45_BAUD-3; 
            data_bit_len[TTY_50_BAUD] = DATA_BIT_LEN_50_BAUD-3; 
#else
            data_bit_len[TTY_45_BAUD] = DATA_BIT_LEN_45_BAUD-4; 
            data_bit_len[TTY_50_BAUD] = DATA_BIT_LEN_50_BAUD-4; 
#endif /* TTY_NOMINAL_BIT_LEN_FIX */
#endif /* TTY_GEN_50_BAUD_FIX */
            bit_size = add(bit_size,data_bit_len[tty_rate_hist[CURRENT_FRAME]]);
            bit_size = sub(bit_size,stop_bit_len[tty_rate_hist[CURRENT_FRAME]]);

        }
        else if( sub(bit_num,STOP_BIT_NUM) < 0 )
        {
            /*
            *  Shorten to 1 stop bit if next character comes before
            *  generating stop bit of current character.
            */

#if TTY_GEN_50_BAUD_FIX
#if TTY_NOMINAL_BIT_LEN_FIX
            data_bit_len[TTY_45_BAUD] = DATA_BIT_LEN_45_BAUD-3; 
            data_bit_len[TTY_50_BAUD] = DATA_BIT_LEN_50_BAUD-3; 
#else
            data_bit_len[TTY_45_BAUD] = DATA_BIT_LEN_45_BAUD-4; 
            data_bit_len[TTY_50_BAUD] = DATA_BIT_LEN_50_BAUD-4; 
#endif /* TTY_NOMINAL_BIT_LEN_FIX */
#endif /* TTY_GEN_50_BAUD_FIX */
            stop_bit_len[tty_rate_hist[CURRENT_FRAME]] = data_bit_len[tty_rate_hist[CURRENT_FRAME]];
        }

    } /* end if( falling behind) */

    p_buf = outbuf;                                         
    num = length;                                           
                                                            
    if( sub(bit_size,length) < 0 )
    {
        num = bit_size;                                     
    }

#if TTY_HALF_DUPLEX_FIX
    write_flag = 1;
#else
    write_flag = 0;
#endif

    while( num > 0 )
    {

        /*-----------------------------------------------------------------------*/
        /*-----------------------------------------------------------------------*/
                                                            
        /* If current character non_tty, get out of loop */
        if( sub(current_counter,NON_TTY) == 0 )
        {
              init_tty_gen(NON_TTY,0,0);
#if TTY_HALF_DUPLEX_FIX
              write_flag = 0;
#endif
              break;
        }

        /* else if silence, generate silence */
        else if( sub(current_counter,TTY_SILENCE) == 0 )
        {
                                                            
            for( i=0 ; i < num ; i++ )
            {
                p_buf[i] = 0;                               
            }
            init_tty_gen(TTY_SILENCE,TTY_SILENCE_CHAR,0);         /* init in preparation for next char */
#if !TTY_HALF_DUPLEX_FIX
            write_flag = 1;
#endif
        }
        else
        {
#if TTY_HALF_DUPLEX_FIX
            if( bit_num == SILENCE_HANGOVER_BIT_NUM )
            {
                for( i=0 ; i < num ; i++ )
                {
                    p_buf[i] = 0;
                }
            }
            else
            {
                bit = current_char & shl(1,bit_num);            
                                                           
                if( bit == 0 )
                {
                    bit = SPACE_FREQ;
                }
                else
                {
                    bit = MARK_FREQ;
                }

#if TTY_CONT_PHASE_FIX
                tty_continuous_phase_tone_gen(p_buf,bit,num);
#else
                if( sub(bit,prev_bit) != 0 )
                {
                    init_tone_gen(tone_param,bit);
                }

                tone_gen(p_buf,bit,BAUDOT_GAIN,num,tone_param);
#endif /* TTY_CONT_PHASE_FIX */
            }
            write_flag = 2;

#else /* !TTY_HALF_DUPLEX_FIX */
            bit = current_char & shl(1,bit_num);            
                                                            
            if( bit == 0 )
            {
                bit = SPACE_FREQ;                           
            }
            else
            {
                bit = MARK_FREQ;                            
            }

#if TTY_CONT_PHASE_FIX
            tty_continuous_phase_tone_gen(p_buf,bit,num);
#else /* TTY_CONT_PHASE_FIX */
            if( sub(bit,prev_bit) != 0 )
            {
                init_tone_gen(tone_param,bit);
            }

            tone_gen(p_buf,bit,BAUDOT_GAIN,num,tone_param);
#endif /* TTY_CONT_PHASE_FIX */
            write_flag = 1;
#endif /* HALF_DUPLEX_FIX */

            /* Update for next iteration */

            p_buf += num; 
            bit_size = sub(bit_size,num);                                
                                                            
            if( sub(bit_size,1) < 0 )                 /* if end of bit */
            {
                bit_num = add(bit_num,1);                                  

                /*
                *  If a new character immediately follows the
                *  current character, eliminate the mark hold tone.
                */
#if TTY_HALF_DUPLEX_FIX
                if( sub(bit_num,MARK_HOLD_BIT_NUM) >= 0 )
#else
                if( sub(bit_num,MARK_HOLD_BIT_NUM) == 0 )
#endif
                {
                    /* Reset stop bit to 1.5 bits */

                    stop_bit_len[TTY_45_BAUD] = STOP_BIT_LEN_45_BAUD;
                    stop_bit_len[TTY_50_BAUD] = STOP_BIT_LEN_50_BAUD;

                    if( sub(current_counter,counter_hist[CURRENT_FRAME]) != 0
                        && (counter_hist[CURRENT_FRAME] & COUNTER_BETWEEN_START_STOP) != 0
                    )
                    {
#if TTY_HALF_DUPLEX_FIX
                        bit_num = SILENCE_HANGOVER_BIT_NUM+1;
#else
                        bit_num = add(bit_num,1);
#endif
                    }
#if TTY_HALF_DUPLEX_FIX
                    else
                    {
                        /* Remove current_counter from history */
                        for( i=CURRENT_FRAME-1 ; i >= 0 ; i-- )
                        {
                            if( current_counter == counter_hist[i] )
                            {
                                /* Replace with TTY_FER so that a vote will be taken */
                                counter_hist[i] = TTY_FER; 
                                char_hist[i] = 0; 
                            }
                            else
                            {
                                break;
                            }                                
                        }
                    }
#endif
                }

#if TTY_HALF_DUPLEX_FIX
                if( sub(bit_num,SILENCE_HANGOVER_BIT_NUM) > 0 )        /* if end of character */
#else
                if( sub(bit_num,MARK_HOLD_BIT_NUM) > 0 )               /* if end of character */
#endif
                {
                                                            
                    /* if start of silence */
                    if( sub(current_counter,counter_hist[CURRENT_FRAME]) == 0
                        || sub(counter_hist[CURRENT_FRAME],NON_TTY) == 0 )
                    {
                        counter_hist[CURRENT_FRAME] = TTY_SILENCE;      
                        char_hist[CURRENT_FRAME] = TTY_SILENCE_CHAR;    

                        init_tty_gen(TTY_SILENCE,TTY_SILENCE_CHAR,0);
                    }

                    /* else... next character begins right away. */
                    else                        /* else start next character */
                    {
                        init_tty_gen( counter_hist[CURRENT_FRAME],
                                      char_hist[CURRENT_FRAME],
                                      tty_rate_hist[CURRENT_FRAME]);
                    }
                }
                else                            /* start of next bit */
                {
                                                            
                    if( sub(bit_num,STOP_BIT_NUM) == 0 )
                    {
                        bit_size = stop_bit_len[tty_rate_hist[CURRENT_FRAME+1]];            
                    }
                    else if( sub(bit_num,MARK_HOLD_BIT_NUM) == 0 )
                    {
                                                            
                        bit_size = MARK_HOLD_LEN;           
                    }
#if TTY_HALF_DUPLEX_FIX
                    else if( sub(bit_num,SILENCE_HANGOVER_BIT_NUM) == 0 )
                    {
                        bit_size = SILENCE_HANGOVER_LEN;
                    }
#endif
                    else
                    {
                                                            
                        bit_size = data_bit_len[tty_rate_hist[CURRENT_FRAME+1]]; 
                    }

                }
            }
        } /* end if */


        /* Update for next iteration */
#if !TTY_CONT_PHASE_FIX
        prev_bit = bit;
#endif
        length = sub(length,num); 
        num = length;                                       
                                                            
        if( sub(bit_size,length) < 0 )
        {
            num = bit_size;                                 
        }

    } /* end while */


    /* Update history buffers for next iteration at the end of the frame */
                                                            
    if( sub(subframe,sub(num_subfr,1)) == 0 )
    {

        /* Put last generated character in history buffers */
                                                            
        if( sub(counter_hist[CURRENT_FRAME],current_counter) != 0 )
        {
            tty_rate_hist[CURRENT_FRAME] = tty_rate_hist[CURRENT_FRAME+1];  
        }
        counter_hist[CURRENT_FRAME] = current_counter;      
        char_hist[CURRENT_FRAME] = shr(current_char,1) & DATA_BIT_MASK;     

        for( i=TTY_BUF_SIZE-1 ; i > 0 ; i-- )
        {
            counter_hist[i] = counter_hist[i-1];            
            char_hist[i] = char_hist[i-1];                  
            tty_rate_hist[i] = tty_rate_hist[i-1];          
        }

        /* During the mark hold, allow the next character to be generated */
#if TTY_HALF_DUPLEX_FIX
        if( sub(bit_num,MARK_HOLD_BIT_NUM) >= 0 )
#else
        if( sub(bit_num,MARK_HOLD_BIT_NUM) == 0 )
#endif
        {
#if TTY_GEN_50_BAUD_FIX
            stop_bit_len[TTY_45_BAUD] = STOP_BIT_LEN_45_BAUD;
            data_bit_len[TTY_45_BAUD] = DATA_BIT_LEN_45_BAUD;
            stop_bit_len[TTY_50_BAUD] = STOP_BIT_LEN_50_BAUD;
            data_bit_len[TTY_50_BAUD] = DATA_BIT_LEN_50_BAUD;
#endif
            for( i=CURRENT_FRAME ; i >= 0 ; i-- )
            {
                                                            
                /* Remove current_counter from history */
                if( current_counter == counter_hist[i] )
                {                                                            
                    counter_hist[i] = TTY_FER;      
                    char_hist[i] = 0;    
                }
                else
                {
                    break;
                }                                
            }
        }

    }



    return(write_flag);
        
} /* end tty_gen() */