Пример #1
0
static switch_status_t switch_codec2_destroy(switch_codec_t *codec)
{
	struct codec2_context *context = codec->private_info;
	
	codec2_destroy(context->encoder);
	codec2_destroy(context->decoder);

	context->encoder = NULL;
	context->decoder = NULL;

#ifdef LOG_DATA
	if (context->encoder_in) {
		fclose(context->encoder_in);
	}
	if (context->encoder_out) {
		fclose(context->encoder_out);
	}
	if (context->encoder_out_unpacked) {
		fclose(context->encoder_out_unpacked);
	}
	if (context->decoder_in) {
		fclose(context->decoder_in);
	}
	if (context->decoder_in_unpacked) {
		fclose(context->decoder_in_unpacked);
	}
	if (context->decoder_out) {
		fclose(context->decoder_out);
	}
#endif

	return SWITCH_STATUS_SUCCESS;
}
Пример #2
0
static void decode_destructor(void *data)
{
	struct audec_state *st = data;

	if (st->c2)
		codec2_destroy(st->c2);
}
Пример #3
0
static void
freectx(PaCtx *ctx) {
    /* Destroy mutex */
    pthread_mutex_destroy(&ctx->mtx);
    
    /* Free SRC resources */
    if (ctx->src != NULL)
	src_delete(ctx->src);

    /* Free echo caneller */
    if (ctx->echocan != NULL)
	echo_can_free(ctx->echocan);

    /* Free codec2 */
    if (ctx->codec2 != NULL)
	codec2_destroy(ctx->codec2);

    /* Free FIFOs */
    if (ctx->incoming != NULL)
	fifo_free(ctx->incoming);
    if (ctx->incrate != NULL)
	fifo_free(ctx->incrate);
    if (ctx->outgoing != NULL)
	fifo_free(ctx->outgoing);
}
Пример #4
0
int main(int argc, char *argv[])
{
    struct CODEC2 *codec2;
    FILE          *fin;
    FILE          *fout;
    short         *buf;
    unsigned char *bits;
    int            nsam, nbit, i, r;

    for(i=0; i<10; i++) {
        r = codec2_rand();
        printf("[%d] r = %d\n", i, r);
    }

    if (argc != 3) {
	printf("usage: %s InputRawSpeechFile OutputRawSpeechFile\n", argv[0]);
	exit(1);
    }

    if ( (fin = fopen(argv[1],"rb")) == NULL ) {
	fprintf(stderr, "Error opening input speech file: %s: %s.\n",
         argv[1], strerror(errno));
	exit(1);
    }

    if ( (fout = fopen(argv[2],"wb")) == NULL ) {
	fprintf(stderr, "Error opening output speech file: %s: %s.\n",
         argv[2], strerror(errno));
	exit(1);
    }

    #ifdef DUMP
    dump_on("c2demo");
    #endif

    /* Note only one set of Codec 2 states is required for an encoder
       and decoder pair. */

    codec2 = codec2_create(CODEC2_MODE_1300);
    nsam = codec2_samples_per_frame(codec2);
    buf = (short*)malloc(nsam*sizeof(short));
    nbit = codec2_bits_per_frame(codec2);
    bits = (unsigned char*)malloc(nbit*sizeof(char));

    while(fread(buf, sizeof(short), nsam, fin) == (size_t)nsam) {
	codec2_encode(codec2, bits, buf);
	codec2_decode(codec2, buf, bits);
	fwrite(buf, sizeof(short), nsam, fout);
    }

    free(buf);
    free(bits);
    codec2_destroy(codec2);

    fclose(fin);
    fclose(fout);

    return 0;
}
Пример #5
0
/*
 * Close codec.
 */
static pj_status_t codec2_codec_close( pjmedia_codec *codec )
{
    struct codec2_data *codec2_data = (struct codec2_data*) codec->codec_data;

    pj_assert(codec2_data != NULL);

    if (codec2_data->encoder) {
    codec2_destroy(codec2_data->encoder);
	codec2_data->encoder = NULL;
    }
    if (codec2_data->decoder) {
    codec2_destroy(codec2_data->decoder);
	codec2_data->decoder = NULL;
    }

    return PJ_SUCCESS;
}
Пример #6
0
static void codec2_destroy_stuff(struct ast_trans_pvt *pvt)
{
	struct codec2_translator_pvt *tmp = pvt->pvt;

	if (tmp->state) {
		codec2_destroy(tmp->state);
	}
}
Пример #7
0
static void c2demo(int mode, char inputfile[], char outputfile[])
{
    struct CODEC2 *codec2;
    short         *inbuf, *outbuf;
    unsigned char *bits;
    int            nsam, nbit;
    FILE          *fin, *fout;
    int            frame;
    PROFILE_VAR(enc_start, dec_start);

    codec2 = codec2_create(mode);
    nsam = codec2_samples_per_frame(codec2);
    outbuf = (short*)malloc(nsam*sizeof(short));
    inbuf = (short*)malloc(nsam*sizeof(short));
    nbit = codec2_bits_per_frame(codec2);
    bits = (unsigned char*)malloc(nbit*sizeof(char));

    fin = fopen(inputfile, "rb");
    if (fin == NULL) {
        printf("Error opening input file: %s\n\nTerminating....\n",inputfile);
        exit(1);
    }

    fout = fopen(outputfile, "wb");
    if (fout == NULL) {
        printf("Error opening output file: %s\n\nTerminating....\n",outputfile);
        exit(1);
    }

#ifdef DUMP
    dump_on("stm32f4");
#endif
    frame = 0;

    while (fread(inbuf, sizeof(short), nsam, fin) == nsam) {
        PROFILE_SAMPLE(enc_start);
        codec2_encode(codec2, bits, inbuf);
        PROFILE_SAMPLE_AND_LOG(dec_start, enc_start, "  enc");
        codec2_decode(codec2, outbuf, bits);
        PROFILE_SAMPLE_AND_LOG2(dec_start, "  dec");
        PROFILE_SAMPLE_AND_LOG2(enc_start, "  enc & dec");
        fwrite((char*)outbuf, sizeof(short), nsam, fout);
        printf("frame: %d\n", ++frame);
        machdep_profile_print_logged_samples();
    }

#ifdef DUMP
    dump_off("sm32f4");
#endif

    fclose(fin);
    fclose(fout);
    free(inbuf);
    free(outbuf);
    free(bits);
    codec2_destroy(codec2);
}
Пример #8
0
void fdmdv_close() {
    if (fdmdv)
        fdmdv_destroy(fdmdv);
    if (codec2)
        codec2_destroy(codec2);
    if (output_buf)
        free(output_buf);
    if (insrc1)
        free(insrc1);
}
Пример #9
0
static void c2speedtest(int mode, char inputfile[])
{
    struct CODEC2 *codec2;
    short         *inbuf, *outbuf, *pinbuf, *dummy_buf;
    unsigned char *bits;
    int            nsam, nbit, nframes;
    FILE          *fin;
    int            f, nread;

    codec2 = codec2_create(mode);
    nsam = codec2_samples_per_frame(codec2);
    nframes = SPEED_TEST_SAMPLES/nsam;
    outbuf = (short*)malloc(nsam*sizeof(short));
    inbuf = (short*)malloc(SPEED_TEST_SAMPLES*sizeof(short));
    nbit = codec2_bits_per_frame(codec2);
    bits = (unsigned char*)malloc(nbit*sizeof(char));
    dummy_buf = (short*)malloc(2*nsam*sizeof(short));

    fin = fopen(inputfile, "rb");
    if (fin == NULL) {
        printf("Error opening input file: %s\nTerminating....\n",inputfile);
        exit(1);
    }

    printf("reading samples ....\n");
    nread = fread(inbuf, sizeof(short), SPEED_TEST_SAMPLES, fin);
    if (nread != SPEED_TEST_SAMPLES) {
        printf("error reading %s, %d samples reqd, %d read\n", 
               inputfile, SPEED_TEST_SAMPLES, nread);
    }
    fclose(fin);
    
    pinbuf = inbuf;
    for(f=0; f<nframes; f++) {
        //printf("read ADC\n");
        while(adc1_read(dummy_buf, nsam*2) == -1);  /* runs at Fs = 16kHz */

        //printf("Codec 2 enc\n");
	GPIOD->ODR = (1 << 13);
        codec2_encode(codec2, bits, pinbuf);
        pinbuf += nsam;
	GPIOD->ODR &= ~(1 << 13);
        //printf("Codec 2 dec\n");
	codec2_decode(codec2, outbuf, bits);
        
        //printf("write to DAC\n");
        while(dac1_write(dummy_buf, nsam*2) == -1); /* runs at Fs = 16kHz */
        //printf(".");
    }

    free(inbuf);
    free(outbuf);
    free(bits);
    codec2_destroy(codec2);
}
Пример #10
0
int main(int argc, char *argv[])
{
    void *codec2;
    FILE *fin;
    FILE *fout;
    short buf[CODEC2_SAMPLES_PER_FRAME];
    unsigned char  bits[BITS_SIZE];

    if (argc != 3) {
	printf("usage: %s InputBitFile OutputRawSpeechFile\n", argv[0]);
	exit(1);
    }

    if (strcmp(argv[1], "-")  == 0) fin = stdin;
    else if ( (fin = fopen(argv[1],"rb")) == NULL ) {
	fprintf(stderr, "Error opening input bit file: %s: %s.\n",
         argv[1], strerror(errno));
	exit(1);
    }

    if (strcmp(argv[2], "-") == 0) fout = stdout;
    else if ( (fout = fopen(argv[2],"wb")) == NULL ) {
	fprintf(stderr, "Error opening output speech file: %s: %s.\n",
         argv[2], strerror(errno));
	exit(1);
    }

    codec2 = codec2_create();

    while(fread(bits, sizeof(char), BITS_SIZE, fin) == BITS_SIZE) {
	codec2_decode(codec2, buf, bits);
 	fwrite(buf, sizeof(short), CODEC2_SAMPLES_PER_FRAME, fout);
	//if this is in a pipeline, we probably don't want the usual
        //buffering to occur
        if (fout == stdout) fflush(stdout);
        if (fin == stdin) fflush(stdin);

 }

    codec2_destroy(codec2);

    fclose(fin);
    fclose(fout);

    return 0;
}
Пример #11
0
int main(void)
{
  PaStreamParameters inputParameters, outputParameters;
  PaStream *stream;
  PaError err;
  callbackData data;
  Transmitter transmitter(FRAMES_PER_BUFFER);
  err = Pa_Initialize();
  if( err != paNoError ) goto error;

  data.codec2 = codec2_create(CODEC2_MODE);
  data.transmitter = &transmitter;
  data.bufferCounter = 0;

  inputParameters.device = Pa_GetDefaultInputDevice(); /* default input device */
  if (inputParameters.device == paNoDevice) {
    fprintf(stderr,"Error: No default input device.\n");
    goto error;
  }
  inputParameters.channelCount = 1;
  inputParameters.sampleFormat = PA_SAMPLE_TYPE;
  inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency;
  inputParameters.hostApiSpecificStreamInfo = NULL;

  outputParameters.device = 3; //Pa_GetDefaultOutputDevice(); /* default output device */
  if (outputParameters.device == paNoDevice) {
    fprintf(stderr,"Error: No default output device.\n");
    goto error;
  }
  outputParameters.channelCount = 1;
  outputParameters.sampleFormat = PA_SAMPLE_TYPE;
  outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
  outputParameters.hostApiSpecificStreamInfo = NULL;

  err = Pa_OpenStream(
      &stream,
      &inputParameters,
      &outputParameters,
      SAMPLE_RATE,
      FRAMES_PER_BUFFER,
      0, /* paClipOff, */  /* we won't output out of range samples so don't bother clipping them */
      localToRemoteCallback,
      &data );
  if( err != paNoError ) goto error;

  err = Pa_StartStream( stream );
  if( err != paNoError ) goto error;

  printf("Hit ENTER to stop program.\n");
  getchar();
  err = Pa_CloseStream( stream );
  if( err != paNoError ) goto error;

  printf("Finished.\n");
  Pa_Terminate();
  codec2_destroy(data.codec2);
  if(DEBUG_MODE > 0)
  {
    cout << "transmitted data:" << endl;
    for(int i=0; i < data.recordedBits.size(); i++)
    {
      for(int j=0; j < data.recordedBits.at(i).size(); j++)
      {
        cout << data.recordedBits.at(i).at(j);
      }
      cout << endl;
    }
  }
  return 0;

error:
  Pa_Terminate();
  codec2_destroy(data.codec2);
  fprintf( stderr, "An error occured while using the portaudio stream\n" );
  fprintf( stderr, "Error number: %d\n", err );
  fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
  return -1;
}
Пример #12
0
float run_a_test(char raw_file_name[], int bit_to_corrupt)
{
    FILE   *fin;
    short   buf[N];
    struct  CODEC2 *c2;
    kiss_fft_cfg  fft_fwd_cfg;
    MODEL   model;
    float   ak[LPC_ORD+1];
    float   lsps[LPC_ORD], e;
    int     lsp_indexes[LPC_ORD], found_bit;
    float   snr, snr_sum;
    int     frames, i, mask, index;

    c2 = codec2_create(CODEC2_MODE_2400);
    fft_fwd_cfg = kiss_fft_alloc(FFT_ENC, 0, NULL, NULL);

    fin = fopen(raw_file_name, "rb");
    assert(fin != NULL);

    /* find bit we are corrupting */

    found_bit = 0;
    for(i=0; i<LSP_SCALAR_INDEXES; i++) {
	if (!found_bit) {
	    if (bit_to_corrupt > lsp_bits(i))
		bit_to_corrupt -= lsp_bits(i);
	    else {
		index = i;
		mask = (1 << bit_to_corrupt);
		printf(" index: %d bit: %d mask: 0x%x ", index, bit_to_corrupt, mask);
		found_bit = 1;
	    }
	}
    }
    assert(found_bit == 1);

    /* OK test a sample file, flipping bit */

    snr_sum = 0.0;
    frames = 0;
    while(fread(buf, sizeof(short), N, fin) == N) {
	analyse_one_frame(c2, &model, buf);
	e = speech_to_uq_lsps(lsps, ak, c2->Sn, c2->w, LPC_ORD);
	encode_lsps_scalar(lsp_indexes, lsps, LPC_ORD);

	/* find and flip bit we are testing */

	lsp_indexes[index] ^= mask;

	/* decode LSPs and measure SNR */

	decode_lsps_scalar(lsps, lsp_indexes, LPC_ORD);
	check_lsp_order(lsps, LPC_ORD);
	bw_expand_lsps(lsps, LPC_ORD);
	lsp_to_lpc(lsps, ak, LPC_ORD);
	aks_to_M2(fft_fwd_cfg, ak, LPC_ORD, &model, e, &snr, 0, 0, 1, 1, LPCPF_BETA, LPCPF_GAMMA); 
	snr_sum += snr;
	frames++;
    }

    codec2_destroy(c2);

    fclose(fin);

    return snr_sum/frames;
}
Пример #13
0
int main(int argc, char *argv[])
{
    int            mode;
    void          *codec2;
    FILE          *fin;
    FILE          *fout;
    FILE          *fber = NULL;
    short         *buf;
    unsigned char *bits;
    float         *softdec_bits;
    int            nsam, nbit, nbyte, i, byte, frames, bits_proc, bit_errors, error_mode;
    int            nstart_bit, nend_bit, bit_rate;
    int            state, next_state;
    float          ber, r, burst_length, burst_period, burst_timer, ber_est;
    unsigned char  mask;
    int            natural, dump, softdec, bit, ret;

    char* opt_string = "h:";
    struct option long_options[] = {
        { "ber", required_argument, NULL, 0 },
        { "startbit", required_argument, NULL, 0 },
        { "endbit", required_argument, NULL, 0 },
        { "berfile", required_argument, NULL, 0 },
        { "natural", no_argument, &natural, 1 },
        { "softdec", no_argument, &softdec, 1 },
        #ifdef DUMP
        { "dump", required_argument, &dump, 1 },
        #endif
        { "help", no_argument, NULL, 'h' },
        { NULL, no_argument, NULL, 0 }
    };
    int num_opts=sizeof(long_options)/sizeof(struct option);
 
    if (argc < 4)
        print_help(long_options, num_opts, argv);
    
    if (strcmp(argv[1],"3200") == 0)
	mode = CODEC2_MODE_3200;
    else if (strcmp(argv[1],"2400") == 0)
	mode = CODEC2_MODE_2400;
    else if (strcmp(argv[1],"1600") == 0)
	mode = CODEC2_MODE_1600;
    else if (strcmp(argv[1],"1400") == 0)
	mode = CODEC2_MODE_1400;
    else if (strcmp(argv[1],"1300") == 0)
	mode = CODEC2_MODE_1300;
    else if (strcmp(argv[1],"1200") == 0)
	mode = CODEC2_MODE_1200;
    else if (strcmp(argv[1],"700") == 0)
	mode = CODEC2_MODE_700;
    else {
	fprintf(stderr, "Error in mode: %s.  Must be 3200, 2400, 1600, 1400, 1300, 1200, or 700\n", argv[1]);
	exit(1);
    }
    bit_rate = atoi(argv[1]);

    if (strcmp(argv[2], "-")  == 0) fin = stdin;
    else if ( (fin = fopen(argv[2],"rb")) == NULL ) {
	fprintf(stderr, "Error opening input bit file: %s: %s.\n",
         argv[2], strerror(errno));
	exit(1);
    }

    if (strcmp(argv[3], "-") == 0) fout = stdout;
    else if ( (fout = fopen(argv[3],"wb")) == NULL ) {
	fprintf(stderr, "Error opening output speech file: %s: %s.\n",
         argv[3], strerror(errno));
	exit(1);
    }

    error_mode = NONE;
    ber = 0.0;
    burst_length = burst_period = 0.0;
    burst_timer = 0.0;
    dump = natural = softdec = 0;

    codec2 = codec2_create(mode);
    nsam = codec2_samples_per_frame(codec2);
    nbit = codec2_bits_per_frame(codec2);
    buf = (short*)malloc(nsam*sizeof(short));
    nbyte = (nbit + 7) / 8;
    bits = (unsigned char*)malloc(nbyte*sizeof(char));
    softdec_bits = (float*)malloc(nbit*sizeof(float));
    frames = bit_errors = bits_proc = 0;
    nstart_bit = 0;
    nend_bit = nbit-1;

    while(1) {
        int option_index = 0;
        int opt = getopt_long(argc, argv, opt_string, 
                    long_options, &option_index);
        if (opt == -1)
            break;

        switch (opt) {
        case 0:
            if(strcmp(long_options[option_index].name, "ber") == 0) {
                ber = atof(optarg);
                error_mode = UNIFORM;
            } else if(strcmp(long_options[option_index].name, "startbit") == 0) {
	        nstart_bit = atoi(optarg);
            } else if(strcmp(long_options[option_index].name, "endbit") == 0) {
	        nend_bit = atoi(optarg);
             } else if(strcmp(long_options[option_index].name, "berfile") == 0) {
	        if ((fber = fopen(optarg,"wt")) == NULL) {
	            fprintf(stderr, "Error opening BER file: %s %s.\n",
                            optarg, strerror(errno));
                    exit(1);
                }
            
            } 
            #ifdef DUMP
            else if(strcmp(long_options[option_index].name, "dump") == 0) {
                if (dump) 
	            dump_on(optarg);
            }
            #endif
            break;

        case 'h':
            print_help(long_options, num_opts, argv);
            break;

        default:
            /* This will never be reached */
            break;
        }
    }
    assert(nend_bit <= nbit);
    codec2_set_natural_or_gray(codec2, !natural);
    //printf("%d %d\n", nstart_bit, nend_bit);
 
    //fprintf(stderr, "softdec: %d natural: %d\n", softdec, natural);
    if (softdec)
        ret = (fread(softdec_bits, sizeof(float), nbit, fin) == (size_t)nbit);
    else
        ret = (fread(bits, sizeof(char), nbyte, fin) == (size_t)nbyte);
      
    while(ret) {
	frames++;

        // apply bit errors, MSB of byte 0 is bit 0 in frame, only works in packed mode
        
	if ((error_mode == UNIFORM) || (error_mode == UNIFORM_RANGE)) {
            assert(softdec == 0);
	    for(i=nstart_bit; i<nend_bit+1; i++) {
		r = (float)rand()/RAND_MAX;
		if (r < ber) {
		    byte = i/8;
		    //printf("nbyte %d nbit %d i %d byte %d bits[%d] 0x%0x ", nbyte, nbit, i, byte, byte, bits[byte]);
		    mask = 1 << (7 - i + byte*8);
                    bits[byte] ^= mask;
		    //printf("shift: %d mask: 0x%0x bits[%d] 0x%0x\n", 7 - i + byte*8, mask, byte, bits[byte] );
		    bit_errors++;
 		}
                bits_proc++;
	    }
	}

	if (error_mode == TWO_STATE) {
            assert(softdec == 0);
            burst_timer += (float)nbit/bit_rate;
            fprintf(stderr, "burst_timer: %f  state: %d\n", burst_timer, state);

            next_state = state;
            switch(state) {
            case 0:

                /* clear channel state - no bit errors */

                if (burst_timer > (burst_period - burst_length))
                    next_state = 1;
                break;

            case 1:
                
                /* burst error state - 50% bit error rate */

                for(i=nstart_bit; i<nend_bit+1; i++) {
                    r = (float)rand()/RAND_MAX;
                    if (r < 0.5) {
                        byte = i/8;
                        bits[byte] ^= 1 << (7 - i + byte*8);
                        bit_errors++;
                    }
                    bits_proc++;
		}

                if (burst_timer > burst_period) {
                    burst_timer = 0.0;
                    next_state = 0;
                }
                break;

	    }
               
            state = next_state;
        }

        if (fber != NULL) {
            if (fread(&ber_est, sizeof(float), 1, fber) != 1) {
                fprintf(stderr, "ran out of BER estimates!\n");
                exit(1);
            }
            //fprintf(stderr, "ber_est: %f\n", ber_est);
        }
        else
            ber_est = 0.0;
            
        if (softdec) {
            /* pack bits, MSB received first  */

            bit = 7; byte = 0;
            memset(bits, 0, nbyte);
            for(i=0; i<nbit; i++) {
                bits[byte] |= ((softdec_bits[i] < 0.0) << bit);
                bit--;
                if (bit < 0) {
                    bit = 7;
                    byte++;
                }
            }
            codec2_set_softdec(codec2, softdec_bits);
        }

	codec2_decode_ber(codec2, buf, bits, ber_est);
 	fwrite(buf, sizeof(short), nsam, fout);

	//if this is in a pipeline, we probably don't want the usual
        //buffering to occur

        if (fout == stdout) fflush(stdout);
        if (fin == stdin) fflush(stdin);         

        if (softdec)
            ret = (fread(softdec_bits, sizeof(float), nbit, fin) == (size_t)nbit);
        else
            ret = (fread(bits, sizeof(char), nbyte, fin) == (size_t)nbyte);
    }

    if (error_mode)
	fprintf(stderr, "actual BER: %1.3f\n", (float)bit_errors/bits_proc);

    codec2_destroy(codec2);

    free(buf);
    free(bits);
    free(softdec_bits);
    fclose(fin);
    fclose(fout);

    return 0;
}
Пример #14
0
int main(int argc, char *argv[])
{
    int            mode;
    void          *codec2;
    FILE          *fin;
    FILE          *fout;
    FILE          *fber = NULL;
    short         *buf;
    unsigned char *bits, *prev_bits;
    int            nsam, nbit, nbyte, i, byte, frames, bits_proc, bit_errors, error_mode;
    int            nstart_bit, nend_bit, bit_rate;
    int            state, next_state;
    float          ber, r, burst_length, burst_period, burst_timer, ber_est;
    unsigned char  mask;

    if ((argc != 4) && (argc != 5) && (argc != 6) && (argc != 7)) {
	printf("basic usage.................: c2dec 3200|2400|1600|1400|1300|1200 InputBitFile OutputRawSpeechFile\n");
	printf("uniform errors usage........: c2dec 3200|2400|1600|1400|1300|1200 InputBitFile OutputRawSpeechFile uniformBER startBit endBit\n");
	printf("uniform error on range usage: c2dec 3200|2400|1600|1400|1300|1200 InputBitFile OutputRawSpeechFile uniformBER\n");
	printf("demod BER estimate..........: c2dec 3200|2400|1600|1400|1300|1200 InputBitFile OutputRawSpeechFile BERfile\n");
	printf("two state fading usage......: c2dec 3200|2400|1600|1400|1300|1200 InputBitFile OutputRawSpeechFile burstLength burstPeriod\n");
	printf("e.g    c2dec 1400 hts1a.c2 hts1a_1400.raw\n");
	printf("e.g    c2dec 1400 hts1a.c2 hts1a_1400.raw 0.9\n");
	printf("e.g    c2dec 1400 hts1a.c2 hts1a_1400.raw 0.99 0.9\n");
	exit(1);
    }

    if (strcmp(argv[1],"3200") == 0)
	mode = CODEC2_MODE_3200;
    else if (strcmp(argv[1],"2400") == 0)
	mode = CODEC2_MODE_2400;
    else if (strcmp(argv[1],"1600") == 0)
	mode = CODEC2_MODE_1600;
    else if (strcmp(argv[1],"1400") == 0)
	mode = CODEC2_MODE_1400;
    else if (strcmp(argv[1],"1300") == 0)
	mode = CODEC2_MODE_1300;
    else if (strcmp(argv[1],"1200") == 0)
	mode = CODEC2_MODE_1200;
    else {
	fprintf(stderr, "Error in mode: %s.  Must be 3200, 2400, 1600, 1400, 1300 or 1200\n", argv[1]);
	exit(1);
    }
    bit_rate = atoi(argv[1]);

    if (strcmp(argv[2], "-")  == 0) fin = stdin;
    else if ( (fin = fopen(argv[2],"rb")) == NULL ) {
	fprintf(stderr, "Error opening input bit file: %s: %s.\n",
         argv[2], strerror(errno));
	exit(1);
    }

    if (strcmp(argv[3], "-") == 0) fout = stdout;
    else if ( (fout = fopen(argv[3],"wb")) == NULL ) {
	fprintf(stderr, "Error opening output speech file: %s: %s.\n",
         argv[3], strerror(errno));
	exit(1);
    }

    error_mode = NONE;
    ber = 0.0;
    burst_length = burst_period = 0.0;
    burst_timer = 0.0;

    codec2 = codec2_create(mode);
    nsam = codec2_samples_per_frame(codec2);
    nbit = codec2_bits_per_frame(codec2);
    buf = (short*)malloc(nsam*sizeof(short));
    nbyte = (nbit + 7) / 8;
    bits = (unsigned char*)malloc(nbyte*sizeof(char));
    prev_bits = (unsigned char*)malloc(nbyte*sizeof(char));
    frames = bit_errors = bits_proc = 0;
    nstart_bit = 0;
    nend_bit = nbit-1;

    if (argc == 5) {
        /* see if 4th argument is a valid file name */
        if ( (fber = fopen(argv[4],"rb")) == NULL ) {
            /* otherwise it must be BER value for uniform errors */
            ber = atof(argv[4]);
	    error_mode = UNIFORM;
        }
    }

    if (argc == 6) {
        error_mode = TWO_STATE;
	burst_length = atof(argv[4]);
	burst_period = atof(argv[5]);
	nstart_bit = 0;
	nend_bit = 2;
        state = 0;
    }
    
    if (argc == 7) {
        error_mode = UNIFORM_RANGE;
	ber = atof(argv[4]);
	nstart_bit = atoi(argv[5]);
	nend_bit = atoi(argv[6]);
        fprintf(stderr, "ber: %f nstart_bit: %d nend_bit: %d\n", ber, nstart_bit, nend_bit);
        state = 0;
    }

    assert(nend_bit <= nbit);

    while(fread(bits, sizeof(char), nbyte, fin) == (size_t)nbyte) {
	frames++;

        // apply bit errors, MSB of byte 0 is bit 0 in frame */
        
	if ((error_mode == UNIFORM) || (error_mode == UNIFORM_RANGE)) {
	    for(i=nstart_bit; i<nend_bit+1; i++) {
		r = (float)rand()/RAND_MAX;
		if (r < ber) {
		    byte = i/8;
		    //printf("nbyte %d nbit %d i %d byte %d bits[%d] 0x%0x ", nbyte, nbit, i, byte, byte, bits[byte]);
		    mask = 1 << (7 - i + byte*8);
                    bits[byte] ^= mask;
		    //printf("shift: %d mask: 0x%0x bits[%d] 0x%0x\n", 7 - i + byte*8, mask, byte, bits[byte] );
		    bit_errors++;
 		}
                bits_proc++;
	    }
	}

	if (error_mode == TWO_STATE) {
            burst_timer += (float)nbit/bit_rate;
            fprintf(stderr, "burst_timer: %f  state: %d\n", burst_timer, state);

            next_state = state;
            switch(state) {
            case 0:

                /* clear channel state - no bit errors */

                if (burst_timer > (burst_period - burst_length))
                    next_state = 1;
                break;

            case 1:
                
                /* burst error state - 50% bit error rate */

                for(i=nstart_bit; i<nend_bit+1; i++) {
                    r = (float)rand()/RAND_MAX;
                    if (r < 0.5) {
                        byte = i/8;
                        bits[byte] ^= 1 << (7 - i + byte*8);
                        bit_errors++;
                    }
                    bits_proc++;
		}

                if (burst_timer > burst_period) {
                    burst_timer = 0.0;
                    next_state = 0;
                }
                break;

	    }
               
            state = next_state;
        }

        if (fber != NULL) {
            if (fread(&ber_est, sizeof(float), 1, fber) != 1) {
                fprintf(stderr, "ran out of BER estimates!\n");
                exit(1);
            }
            //fprintf(stderr, "ber_est: %f\n", ber_est);
        }
        else
            ber_est = 0.0;

        /* frame repeat logic */
        if (ber_est > 0.15) {
            //memcpy(bits, prev_bits, nbyte);
            // fprintf(stderr, "repeat\n");
        }
            
	codec2_decode(codec2, buf, bits, ber_est);
 	fwrite(buf, sizeof(short), nsam, fout);
	//if this is in a pipeline, we probably don't want the usual
        //buffering to occur
        if (fout == stdout) fflush(stdout);
        if (fin == stdin) fflush(stdin);         

        memcpy(prev_bits, bits, nbyte);
    }

    if (error_mode)
	fprintf(stderr, "actual BER: %1.3f\n", (float)bit_errors/bits_proc);

    codec2_destroy(codec2);

    free(buf);
    free(bits);
    fclose(fin);
    fclose(fout);

    return 0;
}