diff options
Diffstat (limited to 'gr-vocoder/lib/codec2/c2dec.c')
-rw-r--r-- | gr-vocoder/lib/codec2/c2dec.c | 199 |
1 files changed, 179 insertions, 20 deletions
diff --git a/gr-vocoder/lib/codec2/c2dec.c b/gr-vocoder/lib/codec2/c2dec.c index 3123e96fbc..df4e82f77a 100644 --- a/gr-vocoder/lib/codec2/c2dec.c +++ b/gr-vocoder/lib/codec2/c2dec.c @@ -27,54 +27,213 @@ #include "codec2.h" +#include <assert.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> -#define BITS_SIZE ((CODEC2_BITS_PER_FRAME + 7) / 8) +#define NONE 0 /* no bit errors */ +#define UNIFORM 1 /* random bit errors */ +#define TWO_STATE 2 /* Two state error model */ +#define UNIFORM_RANGE 3 /* random bit errors over a certain range */ 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]); + 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], "-") == 0) fin = stdin; - else if ( (fin = fopen(argv[1],"rb")) == NULL ) { + 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[1], strerror(errno)); + argv[2], strerror(errno)); exit(1); } - if (strcmp(argv[2], "-") == 0) fout = stdout; - else if ( (fout = fopen(argv[2],"wb")) == NULL ) { + 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[2], strerror(errno)); + argv[3], strerror(errno)); exit(1); } - codec2 = codec2_create(); + 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; + } - while(fread(bits, sizeof(char), BITS_SIZE, fin) == BITS_SIZE) { - codec2_decode(codec2, buf, bits); - fwrite(buf, sizeof(short), CODEC2_SAMPLES_PER_FRAME, fout); + 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); |