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
$(CC) -c $(CFLAGS) $< -o $@
clean :
- rm -f *.o *~ src/*~
+ rm -f *.o *~ src/*~ c2enc c2dec c2sim
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]);
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);
}
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]);
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);
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
\*---------------------------------------------------------------------------*/
-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;
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;
&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));
\*---------------------------------------------------------------------------*/
-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;
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);
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
/* 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
\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
--- /dev/null
+/*
+ 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;
+}
}
#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;
}
\*---------------------------------------------------------------------------*/
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 */
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) -------------------*/
*/
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
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;
-}
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);
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);