From: drowe67 Date: Mon, 23 Aug 2010 06:38:44 +0000 (+0000) Subject: LSP quantiser unit tests passing X-Git-Url: http://git.whiteaudio.com/gitweb/?a=commitdiff_plain;h=7424cb4b51887ed7e94d0b81be3715341a446ea3;p=freetel-svn-tracking.git LSP quantiser unit tests passing git-svn-id: https://svn.code.sf.net/p/freetel/code@182 01035d8c-6547-0410-b346-abe4f91aad63 --- diff --git a/codec2/src/c2sim.c b/codec2/src/c2sim.c index 26ac63ec..a84ea591 100644 --- a/codec2/src/c2sim.c +++ b/codec2/src/c2sim.c @@ -291,7 +291,7 @@ int main(int argc, char *argv[]) /* option decimation to 20ms rate, which enables interpolation routine to synthesise in between frame */ - +#ifdef FIX_ME_FOR_NEW_INTERP_ROUTINE if (decimate) { if (frames%2) { @@ -316,7 +316,7 @@ int main(int argc, char *argv[]) model_1 = model; model = model_synth; } - +#endif /* Simulate Wo quantisation noise model.Wo += 2.0*(PI/8000)*(1.0 - 2.0*(float)rand()/RAND_MAX); diff --git a/codec2/src/quantise.c b/codec2/src/quantise.c index 3e87344c..a21a4735 100644 --- a/codec2/src/quantise.c +++ b/codec2/src/quantise.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include "defines.h" @@ -44,6 +45,7 @@ typedef struct { int k; /* dimension of vector */ + int log2k; /* number of bits in dimension */ int m; /* elements in codebook */ char *fn; /* file name of text file storing the VQ */ } LSP_CB; @@ -63,23 +65,38 @@ LSP_CB lsp_q[] = { #endif LSP_CB lsp_q[] = { - {1, 16, "../unittest/lsp1.txt"}, - {1, 16, "../unittest/lsp2.txt"}, - {1, 16, "../unittest/lsp3.txt"}, - {1, 16, "../unittest/lsp4.txt"}, - {1, 16, "../unittest/lsp5.txt"}, - {1, 16, "../unittest/lsp6.txt"}, - {1, 16, "../unittest/lsp7.txt"}, - {1, 8, "../unittest/lsp8.txt"}, - {1, 8, "../unittest/lsp9.txt"}, - {1, 4, "../unittest/lsp10.txt"}, - {0, 0, ""} + {1,4,16, "../unittest/lsp1.txt"}, + {1,4,16, "../unittest/lsp2.txt"}, + {1,4,16, "../unittest/lsp3.txt"}, + {1,4,16, "../unittest/lsp4.txt"}, + {1,4,16, "../unittest/lsp5.txt"}, + {1,4,16, "../unittest/lsp6.txt"}, + {1,4,16, "../unittest/lsp7.txt"}, + {1,3,8, "../unittest/lsp8.txt"}, + {1,3,8, "../unittest/lsp9.txt"}, + {1,3,4, "../unittest/lsp10.txt"}, + {0,0,0, ""} }; /* ptr to each codebook */ static float *plsp_cb[MAX_CB]; +/*---------------------------------------------------------------------------*\ + + FUNCTION HEADERS + +\*---------------------------------------------------------------------------*/ + +float speech_to_uq_lsps(float lsp[], float ak[], float Sn[], float w[], + int order); + +/*---------------------------------------------------------------------------*\ + + FUNCTIONS + +\*---------------------------------------------------------------------------*/ + /*---------------------------------------------------------------------------*\ quantise_uniform @@ -212,7 +229,7 @@ void quantise_init() i = 0; while(lsp_q[i].k) { k = lsp_q[i].k; - m = lsp_q[i].m; + m = lsp_q[i].m; plsp_cb[i] = (float*)malloc(sizeof(float)*k*m); assert(plsp_cb[i] != NULL); load_cb(lsp_q[i].fn, plsp_cb[i], k, m); @@ -445,9 +462,6 @@ void aks_to_M2( float Em; /* energy in band */ float Am; /* spectral amplitude sample */ float signal, noise; - float E1,Am1; - - Am1 = model->A[1]; r = TWO_PI/(FFT_DEC); @@ -455,7 +469,8 @@ void aks_to_M2( for(i=0; iA[m] = Am; } *snr = 10.0*log10(signal/noise); - - /* - Attenuate fundamental by 30dB if F0 < 150 Hz and LPC modelling - error for A[1] is larger than 6dB. - - LPC modelling often makes big errors on 1st harmonic, for example - when the fundamental has been removed by analog high pass - filtering before sampling. However on unfiltered speech from - high quality sources we would like to keep the fundamental to - maintain the speech quality. So we check the error in A[1] and - attenuate it if the error is large to avoid annoying low - frequency energy after LPC modelling. - - This will require a single bit to quantise, on top of the other - spectral magnitude bits (i.e. LSP bits + 1 total). - */ - - E1 = fabs(20.0*log10(Am1) - 20.0*log10(model->A[1])); - if (E1 > 6.0) - if (model->Wo < (PI*150.0/4000)) { - model->A[1] *= 0.032; - } - } /*---------------------------------------------------------------------------*\ @@ -515,29 +507,23 @@ void aks_to_M2( AUTHOR......: David Rowe DATE CREATED: 22/8/2010 - Encodes Wo using a WO_BITS code and stuffs into bits[] array. + Encodes Wo using a WO_LEVELS quantiser. \*---------------------------------------------------------------------------*/ -void encode_Wo(char *bits, int *nbits, float Wo) +int encode_Wo(float Wo) { - int code, bit; + int index; float Wo_min = TWO_PI/P_MAX; float Wo_max = TWO_PI/P_MIN; float norm; - int i; norm = (Wo - Wo_min)/(Wo_max - Wo_min); - code = floor(WO_LEVELS * norm + 0.5); - if (code < 0 ) code = 0; - if (code > (WO_LEVELS-1)) code = WO_LEVELS-1; - - for(i=0; i> (WO_BITS-i-1)) & 0x1; - bits[*nbits+i] = bit; - } + index = floor(WO_LEVELS * norm + 0.5); + if (index < 0 ) index = 0; + if (index > (WO_LEVELS-1)) index = WO_LEVELS-1; - *nbits += WO_BITS; + return index; } /*---------------------------------------------------------------------------*\ @@ -546,43 +532,383 @@ void encode_Wo(char *bits, int *nbits, float Wo) AUTHOR......: David Rowe DATE CREATED: 22/8/2010 - Decodes Wo using a WO_BITS quantiser. + Decodes Wo using a WO_LEVELS quantiser. \*---------------------------------------------------------------------------*/ -float decode_Wo(char *bits, int *nbits) +float decode_Wo(int index) { - int code; float Wo_min = TWO_PI/P_MAX; float Wo_max = TWO_PI/P_MIN; float step; float Wo; - int i; - code = 0; - for(i=0; iA[1]) - 20.0*log10(tmp.A[1])); + if (E1 > 6.0) + return 1; + else + return 0; } -void decode_voicing(int *voiced1, int *voiced2, char bits[], int *nbits); +/*---------------------------------------------------------------------------*\ + + FUNCTION....: apply_lpc_correction() + AUTHOR......: David Rowe + DATE CREATED: 22/8/2010 + + Apply first harmonic LPC correction at decoder. + +\*---------------------------------------------------------------------------*/ + +void apply_lpc_correction(MODEL *model, int lpc_correction) { - *voiced1 = bits[0]; - *voiced2 = bits[1]; - *nbits += 2; + if (lpc_correction) { + if (model->Wo < (PI*150.0/4000)) { + model->A[1] *= 0.032; + } + } +} + +/*---------------------------------------------------------------------------*\ + + FUNCTION....: encode_energy() + AUTHOR......: David Rowe + DATE CREATED: 22/8/2010 + + Encodes LPC energy using an E_LEVELS quantiser. + +\*---------------------------------------------------------------------------*/ + +int encode_energy(float e) +{ + int index; + float e_min = E_MIN_DB; + float e_max = E_MAX_DB; + float norm; + + norm = (e - e_min)/(e_max - e_min); + index = floor(E_LEVELS * norm + 0.5); + if (index < 0 ) index = 0; + if (index > (E_LEVELS-1)) index = E_LEVELS-1; + + return index; +} + +/*---------------------------------------------------------------------------*\ + + FUNCTION....: decode_energy() + AUTHOR......: David Rowe + DATE CREATED: 22/8/2010 + + Decodes energy using a WO_BITS quantiser. + +\*---------------------------------------------------------------------------*/ + +float decode_energy(int index) +{ + float e_min = E_MIN_DB; + float e_max = E_MAX_DB; + float step; + float e; + + step = (e_max - e_min)/E_LEVELS; + e = e_min + step*(index); + + return e; +} + +/*---------------------------------------------------------------------------*\ + + FUNCTION....: encode_amplitudes() + AUTHOR......: David Rowe + DATE CREATED: 22/8/2010 + + Time domain LPC is used model the amplitudes which are then + converted to LSPs and quantised. So we don't actually encode the + amplitudes directly, rather we derive an equivalent representation + from the time domain speech. + +\*---------------------------------------------------------------------------*/ + +void encode_amplitudes(int lsp_indexes[], + int *lpc_correction, + int *energy_index, + MODEL *model, + float Sn[], + float w[]) +{ + float lsps[LPC_ORD]; + float ak[LPC_ORD+1]; + float e; + + e = speech_to_uq_lsps(lsps, ak, Sn, w, LPC_ORD); + encode_lsps(lsp_indexes, lsps, LPC_ORD); + *lpc_correction = need_lpc_correction(model, ak, e); + *energy_index = encode_energy(e); +} + +/*---------------------------------------------------------------------------*\ + + FUNCTION....: decode_amplitudes() + AUTHOR......: David Rowe + DATE CREATED: 22/8/2010 + + Given the amplitude quantiser indexes recovers the harmonic + amplitudes. + +\*---------------------------------------------------------------------------*/ + +float decode_amplitudes(MODEL *model, + int lsp_indexes[], + int lpc_correction, + int energy_index +) +{ + float lsps[LPC_ORD]; + float ak[LPC_ORD+1]; + float e; + float snr; + + decode_lsps(lsps, lsp_indexes, LPC_ORD); + bw_expand_lsps(lsps, LPC_ORD); + e = decode_energy(energy_index); + aks_to_M2(ak, LPC_ORD, model, e, &snr); + 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-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 max_error_rads) { + printf("%d error: %f %f\n", lsp_number+1, error, max_error_rads); + exit(0); + } + } + + fclose(flsp); + + return 0; +} + +int test_Wo_quant() { + int c; FILE *f; float Wo,Wo_dec, error, step_size; - char bits[WO_BITS]; - int code, nbits, code_in, code_out; + int index, index_in, index_out; /* output pitch quant curve for plotting */ f = fopen("quant_pitch.txt","wt"); for(Wo=0.9*(TWO_PI/P_MAX); Wo<=1.1*(TWO_PI/P_MIN); Wo += 0.001) { - nbits = 0; - encode_Wo(bits, &nbits, Wo); - code = 0; - for(i=0; i> (WO_BITS-1-i)) & 0x1; - bits[i] = bit; - } - nbits = 0; - Wo = decode_Wo(bits, &nbits); - nbits = 0; - - memset(bits, sizeof(bits), 0); - encode_Wo(bits, &nbits, Wo); - code_out = 0; - for(i=0; i (step_size/2.0)) { + if (fabs(error) > (step_size/2.0)) { printf("error: %f step_size/2: %f\n", error, step_size/2.0); exit(0); }