proper packing an grey coding, thanks Bruce
authordrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Mon, 20 Sep 2010 22:44:42 +0000 (22:44 +0000)
committerdrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Mon, 20 Sep 2010 22:44:42 +0000 (22:44 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@191 01035d8c-6547-0410-b346-abe4f91aad63

codec2/src/Makefile
codec2/src/c2dec.c
codec2/src/c2enc.c
codec2/src/codec2.c
codec2/src/codec2.h
codec2/src/lsp.c
codec2/src/pack.c [new file with mode: 0644]
codec2/src/quantise.c
codec2/src/quantise.h

index a207c6f0b72a7234e21d1b14077002fc9e7684e0..f192954cf67e6c44344d86d4f5e314c5ae73f374 100644 (file)
@@ -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
index 6c5ecbdd7c6ffb64b5c1682ef32ff26817cfcd21..3b876bcac035d6778eaa952d1a9cf1e0b6977c70 100644 (file)
 
 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);
     }
index 36cf7b8681ce07ce12e087b575eb04188b432e71..8fd7c7778d20698bc7554a7d2b886139632fcb62 100644 (file)
 
 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);
index f498cea65f4dc425b66cfa86972b91bd1d296b0b..30142fec1da27448d7c44a998eafc48d87750b48 100644 (file)
@@ -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<LPC_ORD; i++) {
        pack(bits, &nbit, lsp_indexes[i], lsp_bits(i));
@@ -222,7 +220,8 @@ void codec2_encode(void *codec2_state, char bits[], short speech[])
 
 \*---------------------------------------------------------------------------*/
 
-void codec2_decode(void *codec2_state, short speech[], char bits[])
+void codec2_decode(void *codec2_state, short speech[],
+                   const unsigned char * bits)
 {
     CODEC2 *c2;
     MODEL   model;
@@ -232,7 +231,8 @@ void codec2_decode(void *codec2_state, short speech[], char bits[])
     int     energy_index;
     int     Wo_index;
     float   ak[LPC_ORD+1];
-    int     i, nbit = 0;
+    int     i;
+    unsigned int nbit = 0;
     MODEL   model_interp;
 
     assert(codec2_state != NULL);
index 0af3332aaa8f5febcfd4a711fc8033e054f81eb9..131b94e03b0092319f620e6548030eb780dd0e4a 100644 (file)
@@ -35,7 +35,8 @@
 
 void *codec2_create();
 void codec2_destroy(void *codec2_state);
-void codec2_encode(void *codec2_state, char bits[], short speech_in[]);
-void codec2_decode(void *codec2_state, short speech_out[], char bits[]);
+void codec2_encode(void *codec2_state, unsigned char * bits, short speech_in[]);
+void codec2_decode(void *codec2_state, short speech_out[],
+      const unsigned char * bits);
 
 #endif
index 029a5c8a310574eeb3a9ecb0af1698dd9a180137..feab4219abc7ecc38fe22b1d8170cc7a4aa620bc 100644 (file)
@@ -79,7 +79,7 @@ float cheb_poly_eva(float *coef,float x,int m)
     /* Allocate memory for chebyshev series formulation */\r
 \r
     if((T = (float *)malloc((m/2+1)*sizeof(float))) == NULL){\r
-       printf("not enough memory to allocate buffer\n");\r
+       fprintf(stderr, "not enough memory to allocate buffer\n");\r
        exit(1);\r
     }\r
 \r
@@ -143,13 +143,10 @@ int lpc_to_lsp (float *a, int lpcrdr, float *freq, int nb, float delta)
 \r
     /* Allocate memory space for polynomials */\r
 \r
-    if((Q = (float *) malloc((m+1)*sizeof(float))) == NULL){\r
-       printf("not enough memory to allocate buffer\n");\r
-       exit(1);\r
-    }\r
-\r
-    if((P = (float *) malloc((m+1)*sizeof(float))) == NULL){\r
-       printf("not enough memory to allocate buffer\n");\r
+    Q = (float *) malloc((m+1)*sizeof(float));\r
+    P = (float *) malloc((m+1)*sizeof(float));\r
+    if( (P == NULL) || (Q == NULL) ) {\r
+       fprintf(stderr,"not enough memory to allocate buffer\n");\r
        exit(1);\r
     }\r
 \r
diff --git a/codec2/src/pack.c b/codec2/src/pack.c
new file mode 100644 (file)
index 0000000..2cbff44
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+  Copyright (C) 2010 Perens LLC <bruce@perens.com>
+
+  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 <http://www.gnu.org/licenses/>.
+
+ */
+#include "defines.h"
+#include "quantise.h"
+#include <stdio.h>
+
+/* 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;
+}
index 4cc3815f30c7a672931b3b43a008d472fef3e626..90a251311ec38ac5b8b438ec9bc13f4b04b3099f 100644 (file)
@@ -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<FFT_DEC/2; i++)
     Pw[i].real = E/(Pw[i].real*Pw[i].real + Pw[i].imag*Pw[i].imag);
-  dump_Pw(Pw);
+  if (dump) 
+      dump_Pw(Pw);
 
   /* Determine magnitudes by linear interpolation of P(w) -------------------*/
 
@@ -717,7 +719,7 @@ int need_lpc_correction(MODEL *model, float ak[], float E)
     */
 
     memcpy(&tmp, model, sizeof(MODEL));
-    aks_to_M2(ak, LPC_ORD, &tmp, E, &snr);   
+    aks_to_M2(ak, LPC_ORD, &tmp, E, &snr, 0);   
 
     /* 
        Attenuate fundamental by 30dB if F0 < 150 Hz and LPC modelling
@@ -867,55 +869,8 @@ float decode_amplitudes(MODEL *model,
     bw_expand_lsps(lsps, LPC_ORD);
     lsp_to_lpc(lsps, ak, LPC_ORD);
     e = decode_energy(energy_index);
-    aks_to_M2(ak, LPC_ORD, model, e, &snr); 
+    aks_to_M2(ak, LPC_ORD, model, e, &snr, 1); 
     apply_lpc_correction(model, lpc_correction);
 
     return snr;
 }
-
-/*---------------------------------------------------------------------------*\
-                                                       
-  FUNCTION....: pack()      
-  AUTHOR......: David Rowe                           
-  DATE CREATED: 23/8/2010 
-
-  Pack a quantiser index into an array of bits.
-
-\*---------------------------------------------------------------------------*/
-
-void pack(char bits[], int *nbit, int index, int index_bits)
-{
-    int i, bit;
-
-    for(i=0; i<index_bits; i++) {
-       bit = (index >> (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<index_bits; i++) {
-       index <<= 1;
-       index |= bits[*nbit+i];
-    }
-    
-    *nbit += index_bits;
-
-    return index;    
-}
index 981e96a19339d289579aa0f3ffea570c3b3363af..ded7645381fe41ba6e9d9ef51f65340b9faaf9e6 100644 (file)
@@ -37,7 +37,8 @@
 void quantise_init();
 float lpc_model_amplitudes(float Sn[], float w[], MODEL *model, int order,
                           int lsp,float ak[]);
-void aks_to_M2(float ak[], int order, MODEL *model, float E, float *snr);
+void aks_to_M2(float ak[], int order, MODEL *model, float E, float *snr, 
+              int dump);
 float get_gmin(void);
 
 int   encode_Wo(float Wo);
@@ -62,8 +63,8 @@ float decode_amplitudes(MODEL *model,
                        int lpc_correction, 
                        int energy_index);
 
-void pack(char bits[], int *nbit, int index, int index_bits);
-int  unpack(char bits[], int *nbit, int index_bits);
+void pack(unsigned char * bits, unsigned int *nbit, int index, unsigned int index_bits);
+int  unpack(const unsigned char * bits, unsigned int *nbit, unsigned int index_bits);
 
 int lsp_bits(int i);