From c23e4326af2b1c61d1a8e247b43159a3523de45b Mon Sep 17 00:00:00 2001 From: drowe67 Date: Mon, 20 Sep 2010 22:44:42 +0000 Subject: [PATCH] proper packing an grey coding, thanks Bruce git-svn-id: https://svn.code.sf.net/p/freetel/code@191 01035d8c-6547-0410-b346-abe4f91aad63 --- codec2/src/Makefile | 8 ++-- codec2/src/c2dec.c | 6 +-- codec2/src/c2enc.c | 5 +- codec2/src/codec2.c | 16 +++---- codec2/src/codec2.h | 5 +- codec2/src/lsp.c | 13 ++---- codec2/src/pack.c | 104 ++++++++++++++++++++++++++++++++++++++++++ codec2/src/quantise.c | 65 ++++---------------------- codec2/src/quantise.h | 7 +-- 9 files changed, 144 insertions(+), 85 deletions(-) create mode 100644 codec2/src/pack.c diff --git a/codec2/src/Makefile b/codec2/src/Makefile index a207c6f0..f192954c 100644 --- a/codec2/src/Makefile +++ b/codec2/src/Makefile @@ -2,13 +2,13 @@ CC=gcc CFLAGS=-g -Wall -I. -I../src -Wall -g -DFLOATING_POINT -DVAR_ARRAYS C2SIM_OBJ = sine.o nlp.o four1.o dump.o quantise.o lpc.o lsp.o phase.o \ - postfilter.o interp.o codec2.o c2sim.o + pack.o postfilter.o interp.o codec2.o c2sim.o C2ENC_OBJ = sine.o nlp.o four1.o dump.o quantise.o lpc.o lsp.o phase.o \ - postfilter.o interp.o codec2.o c2enc.o + pack.o postfilter.o interp.o codec2.o c2enc.o C2DEC_OBJ = sine.o nlp.o four1.o dump.o quantise.o lpc.o lsp.o phase.o \ - postfilter.o interp.o codec2.o c2dec.o + pack.o postfilter.o interp.o codec2.o c2dec.o all: c2sim c2enc c2dec @@ -25,4 +25,4 @@ c2dec: $(C2DEC_OBJ) $(CC) -c $(CFLAGS) $< -o $@ clean : - rm -f *.o *~ src/*~ + rm -f *.o *~ src/*~ c2enc c2dec c2sim diff --git a/codec2/src/c2dec.c b/codec2/src/c2dec.c index 6c5ecbdd..3b876bca 100644 --- a/codec2/src/c2dec.c +++ b/codec2/src/c2dec.c @@ -40,11 +40,12 @@ int main(int argc, char *argv[]) { + static const int bitsSize = ((CODEC2_BITS_PER_FRAME + 7) / 8); void *codec2; FILE *fin; FILE *fout; short buf[CODEC2_SAMPLES_PER_FRAME]; - char bits[CODEC2_BITS_PER_FRAME]; + unsigned char bits[bitsSize]; if (argc != 3) { printf("usage: %s InputBitFile OutputRawSpeechFile\n", argv[0]); @@ -65,8 +66,7 @@ int main(int argc, char *argv[]) codec2 = codec2_create(); - while(fread(bits, sizeof(char), CODEC2_BITS_PER_FRAME, fin) == - CODEC2_BITS_PER_FRAME) { + while(fread(bits, sizeof(char), bitsSize, fin) == bitsSize) { codec2_decode(codec2, buf, bits); fwrite(buf, sizeof(short), CODEC2_SAMPLES_PER_FRAME, fout); } diff --git a/codec2/src/c2enc.c b/codec2/src/c2enc.c index 36cf7b86..8fd7c777 100644 --- a/codec2/src/c2enc.c +++ b/codec2/src/c2enc.c @@ -41,11 +41,12 @@ int main(int argc, char *argv[]) { + static const int bitsSize = ((CODEC2_BITS_PER_FRAME + 7) / 8); void *codec2; FILE *fin; FILE *fout; short buf[CODEC2_SAMPLES_PER_FRAME]; - char bits[CODEC2_BITS_PER_FRAME]; + unsigned char bits[bitsSize]; if (argc != 3) { printf("usage: %s InputRawspeechFile OutputBitFile\n", argv[0]); @@ -69,7 +70,7 @@ int main(int argc, char *argv[]) while(fread(buf, sizeof(short), CODEC2_SAMPLES_PER_FRAME, fin) == CODEC2_SAMPLES_PER_FRAME) { codec2_encode(codec2, bits, buf); - fwrite(bits, sizeof(char), CODEC2_BITS_PER_FRAME, fout); + fwrite(bits, sizeof(char), bitsSize, fout); } codec2_destroy(codec2); diff --git a/codec2/src/codec2.c b/codec2/src/codec2.c index f498cea6..30142fec 100644 --- a/codec2/src/codec2.c +++ b/codec2/src/codec2.c @@ -147,9 +147,6 @@ void codec2_destroy(void *codec2_state) Encodes 160 speech samples (20ms of speech) into 51 bits. - The bits[] array is not packed, each bit is stored in the LSB of - each byte in the bits[] array. - The codec2 algorithm actually operates internally on 10ms (80 sample) frames, so we run the encoding algorithm twice. On the first frame we just send the voicing bit. One the second frame we @@ -168,7 +165,7 @@ void codec2_destroy(void *codec2_state) \*---------------------------------------------------------------------------*/ -void codec2_encode(void *codec2_state, char bits[], short speech[]) +void codec2_encode(void *codec2_state, unsigned char * bits, short speech[]) { CODEC2 *c2; MODEL model; @@ -177,7 +174,8 @@ void codec2_encode(void *codec2_state, char bits[], short speech[]) int lpc_correction; int energy_index; int Wo_index; - int i, nbit = 0; + int i; + unsigned int nbit = 0; assert(codec2_state != NULL); c2 = (CODEC2*)codec2_state; @@ -199,7 +197,7 @@ void codec2_encode(void *codec2_state, char bits[], short speech[]) &model, c2->Sn, c2->w); - + memset(bits, '\0', ((CODEC2_BITS_PER_FRAME + 7) / 8)); pack(bits, &nbit, Wo_index, WO_BITS); for(i=0; i + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + */ +#include "defines.h" +#include "quantise.h" +#include + +/* Compile-time constants */ +/* Size of unsigned char in bits. Assumes 8 bits-per-char. */ +static const unsigned int WordSize = 8; + +/* Mask to pick the bit component out of bitIndex. */ +static const unsigned int IndexMask = 0x7; + +/* Used to pick the word component out of bitIndex. */ +static const unsigned int ShiftRight = 3; + +/** Pack a bit field into a bit string, encoding the field in Gray code. + * + * The output is an array of unsigned char data. The fields are efficiently + * packed into the bit string. The Gray coding is a naive attempt to reduce + * the effect of single-bit errors, we expect to do a better job as the + * codec develops. + * + * This code would be simpler if it just set one bit at a time in the string, + * but would hit the same cache line more often. I'm not sure the complexity + * gains us anything here. + * + * Although field is currently of int type rather than unsigned for + * compatibility with the rest of the code, indices are always expected to + * be >= 0. + */ +void +pack( + unsigned char * bitArray, /* The output bit string. */ + unsigned int * bitIndex, /* Index into the string in BITS, not bytes.*/ + int field, /* The bit field to be packed. */ + unsigned int fieldWidth/* Width of the field in BITS, not bytes. */ + ) +{ + /* Convert the field to Gray code */ + field = (field >> 1) ^ field; + + do { + unsigned int bI = *bitIndex; + unsigned int bitsLeft = WordSize - (bI & IndexMask); + unsigned int sliceWidth = + bitsLeft < fieldWidth ? bitsLeft : fieldWidth; + unsigned int wordIndex = bI >> ShiftRight; + + bitArray[wordIndex] |= + ((unsigned char)((field >> (fieldWidth - sliceWidth)) + << (bitsLeft - sliceWidth))); + + *bitIndex = bI + sliceWidth; + fieldWidth -= sliceWidth; + } while ( fieldWidth != 0 ); +} + +/** Unpack a field from a bit string, converting from Gray code to binary. + * + */ +int +unpack( + const unsigned char * bitArray, /* The input bit string. */ + unsigned int * bitIndex, /* Index into the string in BITS, not bytes.*/ + unsigned int fieldWidth/* Width of the field in BITS, not bytes. */ + ) +{ + unsigned int field = 0; + + do { + unsigned int bI = *bitIndex; + unsigned int bitsLeft = WordSize - (bI & IndexMask); + unsigned int sliceWidth = + bitsLeft < fieldWidth ? bitsLeft : fieldWidth; + + field |= (((bitArray[bI >> ShiftRight] >> (bitsLeft - sliceWidth)) & ((1 << sliceWidth) - 1)) << (fieldWidth - sliceWidth)); + + *bitIndex = bI + sliceWidth; + fieldWidth -= sliceWidth; + } while ( fieldWidth != 0 ); + + /* Convert from Gray code to binary. Works for maximum 8-bit fields. */ + unsigned int t = field ^ (field >> 8); + t ^= (t >> 4); + t ^= (t >> 2); + t ^= (t >> 1); + return t; +} diff --git a/codec2/src/quantise.c b/codec2/src/quantise.c index 4cc3815f..90a25131 100644 --- a/codec2/src/quantise.c +++ b/codec2/src/quantise.c @@ -436,7 +436,7 @@ float lpc_model_amplitudes( } #endif - aks_to_M2(ak,order,model,E,&snr); /* {ak} -> {Am} LPC decode */ + aks_to_M2(ak,order,model,E,&snr, 1); /* {ak} -> {Am} LPC decode */ return snr; } @@ -452,11 +452,12 @@ float lpc_model_amplitudes( \*---------------------------------------------------------------------------*/ void aks_to_M2( - float ak[], /* LPC's */ - int order, + float ak[], /* LPC's */ + int order, MODEL *model, /* sinusoidal model parameters for this frame */ - float E, /* energy term */ - float *snr /* signal to noise ratio for this frame in dB */ + float E, /* energy term */ + float *snr, /* signal to noise ratio for this frame in dB */ + int dump /* true to dump sample to dump file */ ) { COMP Pw[FFT_DEC]; /* power spectrum */ @@ -484,7 +485,8 @@ void aks_to_M2( for(i=0; i> (index_bits-i-1)) & 0x1; - bits[*nbit+i] = bit; - } - - *nbit += index_bits; -} - -/*---------------------------------------------------------------------------*\ - - FUNCTION....: unpack() - AUTHOR......: David Rowe - DATE CREATED: 23/8/2010 - - Unpack a qunatiser index from an array of bits. - -\*---------------------------------------------------------------------------*/ - -int unpack(char bits[], int *nbit, int index_bits) -{ - int index = 0; - int i; - - for(i=0; i