From: drowe67 Date: Wed, 1 Oct 2014 06:55:54 +0000 (+0000) Subject: experimental 450 bit/s mode X-Git-Url: http://git.whiteaudio.com/gitweb/?a=commitdiff_plain;h=d36e1ce6dcad55f83b3ac3d908380166f44475d2;p=freetel-svn-tracking.git experimental 450 bit/s mode git-svn-id: https://svn.code.sf.net/p/freetel/code@1868 01035d8c-6547-0410-b346-abe4f91aad63 --- diff --git a/codec2-dev/src/c2dec.c b/codec2-dev/src/c2dec.c index 641e4019..0c5103a7 100644 --- a/codec2-dev/src/c2dec.c +++ b/codec2-dev/src/c2dec.c @@ -88,8 +88,10 @@ int main(int argc, char *argv[]) mode = CODEC2_MODE_1300; else if (strcmp(argv[1],"1200") == 0) mode = CODEC2_MODE_1200; + else if (strcmp(argv[1],"450") == 0) + mode = CODEC2_MODE_450; else { - fprintf(stderr, "Error in mode: %s. Must be 3200, 2400, 1600, 1400, 1300 or 1200\n", argv[1]); + fprintf(stderr, "Error in mode: %s. Must be 3200, 2400, 1600, 1400, 1300, 1200, or 450\n", argv[1]); exit(1); } bit_rate = atoi(argv[1]); diff --git a/codec2-dev/src/c2enc.c b/codec2-dev/src/c2enc.c index f0d9bca1..a457a8f9 100644 --- a/codec2-dev/src/c2enc.c +++ b/codec2-dev/src/c2enc.c @@ -44,7 +44,7 @@ int main(int argc, char *argv[]) int nsam, nbit, nbyte, gray; if (argc < 4) { - printf("usage: c2enc 3200|2400|1600|1400|1300|1200 InputRawspeechFile OutputBitFile [--natural]\n"); + printf("usage: c2enc 3200|2400|1600|1400|1300|1200|450 InputRawspeechFile OutputBitFile [--natural]\n"); printf("e.g c2enc 1400 ../raw/hts1a.raw hts1a.c2\n"); printf("e.g c2enc 1300 ../raw/hts1a.raw hts1a.c2 --natural\n"); exit(1); @@ -62,8 +62,10 @@ int main(int argc, char *argv[]) mode = CODEC2_MODE_1300; else if (strcmp(argv[1],"1200") == 0) mode = CODEC2_MODE_1200; + else if (strcmp(argv[1],"450") == 0) + mode = CODEC2_MODE_450; else { - fprintf(stderr, "Error in mode: %s. Must be 3200, 2400, 1600, 1400, 1300 or 1200\n", argv[1]); + fprintf(stderr, "Error in mode: %s. Must be 3200, 2400, 1600, 1400, 1300, 1200 or 450\n", argv[1]); exit(1); } diff --git a/codec2-dev/src/c2sim.c b/codec2-dev/src/c2sim.c index dc258ea1..5dc1f400 100644 --- a/codec2-dev/src/c2sim.c +++ b/codec2-dev/src/c2sim.c @@ -676,14 +676,14 @@ int main(int argc, char *argv[]) if (scalar_quant_Wo_e) { - e = decode_energy(encode_energy(e)); + e = decode_energy(encode_energy(e, E_BITS), E_BITS); if (!decimate) { /* we send params every 10ms, delta-time every 20ms */ if (dt && (frames % 2)) model.Wo = decode_Wo_dt(encode_Wo_dt(model.Wo, prev_Wo),prev_Wo); else - model.Wo = decode_Wo(encode_Wo(model.Wo)); + model.Wo = decode_Wo(encode_Wo(model.Wo, WO_BITS), WO_BITS); } if (decimate) { @@ -693,7 +693,7 @@ int main(int argc, char *argv[]) model.Wo = decode_Wo_dt(encode_Wo_dt(model.Wo, prev__Wo),prev__Wo); } else - model.Wo = decode_Wo(encode_Wo(model.Wo)); + model.Wo = decode_Wo(encode_Wo(model.Wo, WO_BITS), WO_BITS); } model.L = PI/model.Wo; /* if we quantise Wo re-compute L */ diff --git a/codec2-dev/src/codec2.c b/codec2-dev/src/codec2.c index 60489e1c..08604a55 100644 --- a/codec2-dev/src/codec2.c +++ b/codec2-dev/src/codec2.c @@ -67,6 +67,8 @@ void codec2_encode_1300(struct CODEC2 *c2, unsigned char * bits, short speech[]) void codec2_decode_1300(struct CODEC2 *c2, short speech[], const unsigned char * bits, float ber_est); void codec2_encode_1200(struct CODEC2 *c2, unsigned char * bits, short speech[]); void codec2_decode_1200(struct CODEC2 *c2, short speech[], const unsigned char * bits); +void codec2_encode_450(struct CODEC2 *c2, unsigned char * bits, short speech[]); +void codec2_decode_450(struct CODEC2 *c2, short speech[], const unsigned char * bits); static void ear_protection(float in_out[], int n); /*---------------------------------------------------------------------------*\ @@ -104,7 +106,8 @@ struct CODEC2 * CODEC2_WIN32SUPPORT codec2_create(int mode) (mode == CODEC2_MODE_1600) || (mode == CODEC2_MODE_1400) || (mode == CODEC2_MODE_1300) || - (mode == CODEC2_MODE_1200) + (mode == CODEC2_MODE_1200) || + (mode == CODEC2_MODE_450) ); c2->mode = mode; for(i=0; imode == CODEC2_MODE_1200) return 48; + if (c2->mode == CODEC2_MODE_450) + return 18; return 0; /* shouldn't get here */ } @@ -203,7 +208,7 @@ int CODEC2_WIN32SUPPORT codec2_bits_per_frame(struct CODEC2 *c2) { AUTHOR......: David Rowe DATE CREATED: Nov 14 2011 - Returns the number of bits per frame. + Returns the number of speech samples per frame. \*---------------------------------------------------------------------------*/ @@ -220,6 +225,8 @@ int CODEC2_WIN32SUPPORT codec2_samples_per_frame(struct CODEC2 *c2) { return 320; if (c2->mode == CODEC2_MODE_1200) return 320; + if (c2->mode == CODEC2_MODE_450) + return 320; return 0; /* shouldnt get here */ } @@ -233,7 +240,8 @@ void CODEC2_WIN32SUPPORT codec2_encode(struct CODEC2 *c2, unsigned char *bits, s (c2->mode == CODEC2_MODE_1600) || (c2->mode == CODEC2_MODE_1400) || (c2->mode == CODEC2_MODE_1300) || - (c2->mode == CODEC2_MODE_1200) + (c2->mode == CODEC2_MODE_1200) || + (c2->mode == CODEC2_MODE_450) ); if (c2->mode == CODEC2_MODE_3200) @@ -248,6 +256,8 @@ void CODEC2_WIN32SUPPORT codec2_encode(struct CODEC2 *c2, unsigned char *bits, s codec2_encode_1300(c2, bits, speech); if (c2->mode == CODEC2_MODE_1200) codec2_encode_1200(c2, bits, speech); + if (c2->mode == CODEC2_MODE_450) + codec2_encode_450(c2, bits, speech); } void CODEC2_WIN32SUPPORT codec2_decode(struct CODEC2 *c2, short speech[], const unsigned char *bits) @@ -264,7 +274,8 @@ void CODEC2_WIN32SUPPORT codec2_decode_ber(struct CODEC2 *c2, short speech[], co (c2->mode == CODEC2_MODE_1600) || (c2->mode == CODEC2_MODE_1400) || (c2->mode == CODEC2_MODE_1300) || - (c2->mode == CODEC2_MODE_1200) + (c2->mode == CODEC2_MODE_1200) || + (c2->mode == CODEC2_MODE_450) ); if (c2->mode == CODEC2_MODE_3200) @@ -279,6 +290,8 @@ void CODEC2_WIN32SUPPORT codec2_decode_ber(struct CODEC2 *c2, short speech[], co codec2_decode_1300(c2, speech, bits, ber_est); if (c2->mode == CODEC2_MODE_1200) codec2_decode_1200(c2, speech, bits); + if (c2->mode == CODEC2_MODE_450) + codec2_decode_450(c2, speech, bits); } @@ -332,11 +345,11 @@ void codec2_encode_3200(struct CODEC2 *c2, unsigned char * bits, short speech[]) analyse_one_frame(c2, &model, &speech[N]); pack(bits, &nbit, model.voiced, 1); - Wo_index = encode_Wo(model.Wo); + Wo_index = encode_Wo(model.Wo, WO_BITS); pack(bits, &nbit, Wo_index, WO_BITS); e = speech_to_uq_lsps(lsps, ak, c2->Sn, c2->w, LPC_ORD); - e_index = encode_energy(e); + e_index = encode_energy(e, E_BITS); pack(bits, &nbit, e_index, E_BITS); encode_lspds_scalar(lspd_indexes, lsps, LPC_ORD); @@ -387,11 +400,11 @@ void codec2_decode_3200(struct CODEC2 *c2, short speech[], const unsigned char * model[1].voiced = unpack(bits, &nbit, 1); Wo_index = unpack(bits, &nbit, WO_BITS); - model[1].Wo = decode_Wo(Wo_index); + model[1].Wo = decode_Wo(Wo_index, WO_BITS); model[1].L = PI/model[1].Wo; e_index = unpack(bits, &nbit, E_BITS); - e[1] = decode_energy(e_index); + e[1] = decode_energy(e_index, E_BITS); for(i=0; iSn, c2->w, LPC_ORD); - e_index = encode_energy(e); + e_index = encode_energy(e, E_BITS); pack(bits, &nbit, e_index, E_BITS); /* frame 3: - voicing ---------------------------------------------*/ @@ -641,11 +654,11 @@ void codec2_encode_1600(struct CODEC2 *c2, unsigned char * bits, short speech[]) analyse_one_frame(c2, &model, &speech[3*N]); pack(bits, &nbit, model.voiced, 1); - Wo_index = encode_Wo(model.Wo); + Wo_index = encode_Wo(model.Wo, WO_BITS); pack(bits, &nbit, Wo_index, WO_BITS); e = speech_to_uq_lsps(lsps, ak, c2->Sn, c2->w, LPC_ORD); - e_index = encode_energy(e); + e_index = encode_energy(e, E_BITS); pack(bits, &nbit, e_index, E_BITS); encode_lsps_scalar(lsp_indexes, lsps, LPC_ORD); @@ -698,21 +711,21 @@ void codec2_decode_1600(struct CODEC2 *c2, short speech[], const unsigned char * model[1].voiced = unpack(bits, &nbit, 1); Wo_index = unpack(bits, &nbit, WO_BITS); - model[1].Wo = decode_Wo(Wo_index); + model[1].Wo = decode_Wo(Wo_index, WO_BITS); model[1].L = PI/model[1].Wo; e_index = unpack(bits, &nbit, E_BITS); - e[1] = decode_energy(e_index); + e[1] = decode_energy(e_index, E_BITS); model[2].voiced = unpack(bits, &nbit, 1); model[3].voiced = unpack(bits, &nbit, 1); Wo_index = unpack(bits, &nbit, WO_BITS); - model[3].Wo = decode_Wo(Wo_index); + model[3].Wo = decode_Wo(Wo_index, WO_BITS); model[3].L = PI/model[3].Wo; e_index = unpack(bits, &nbit, E_BITS); - e[3] = decode_energy(e_index); + e[3] = decode_energy(e_index, E_BITS); for(i=0; igray); - Wo_index = encode_Wo(model.Wo); + Wo_index = encode_Wo(model.Wo, WO_BITS); pack_natural_or_gray(bits, &nbit, Wo_index, WO_BITS, c2->gray); #ifdef PROFILE quant_start = machdep_profile_sample(); #endif e = speech_to_uq_lsps(lsps, ak, c2->Sn, c2->w, LPC_ORD); - e_index = encode_energy(e); + e_index = encode_energy(e, E_BITS); pack_natural_or_gray(bits, &nbit, e_index, E_BITS, c2->gray); encode_lsps_scalar(lsp_indexes, lsps, LPC_ORD); @@ -1056,11 +1069,11 @@ void codec2_decode_1300(struct CODEC2 *c2, short speech[], const unsigned char * model[3].voiced = unpack_natural_or_gray(bits, &nbit, 1, c2->gray); Wo_index = unpack_natural_or_gray(bits, &nbit, WO_BITS, c2->gray); - model[3].Wo = decode_Wo(Wo_index); + model[3].Wo = decode_Wo(Wo_index, WO_BITS); model[3].L = PI/model[3].Wo; e_index = unpack_natural_or_gray(bits, &nbit, E_BITS, c2->gray); - e[3] = decode_energy(e_index); + e[3] = decode_energy(e_index, E_BITS); for(i=0; igray); @@ -1071,7 +1084,7 @@ void codec2_decode_1300(struct CODEC2 *c2, short speech[], const unsigned char * if (ber_est > 0.15) { model[0].voiced = model[1].voiced = model[2].voiced = model[3].voiced = 0; - e[3] = decode_energy(10); + e[3] = decode_energy(10, E_BITS); bw_expand_lsps(&lsps[3][0], LPC_ORD, 200.0, 200.0); fprintf(stderr, "soft mute\n"); } @@ -1250,7 +1263,7 @@ void codec2_decode_1200(struct CODEC2 *c2, short speech[], const unsigned char * for(i=0; igray); + + e = speech_to_uq_lsps(lsps, ak, c2->Sn, c2->w, LPC_ORD); + e_index = encode_energy(e, 3); + pack_natural_or_gray(bits, &nbit, e_index, 3, c2->gray); + + encode_lsps_vq(lsp_indexes, lsps, lsps_, LPC_ORD); + pack(bits, &nbit, lsp_indexes[0], lsp_pred_vq_bits(0)); + + assert(nbit == (unsigned)codec2_bits_per_frame(c2)); +} + + +/*---------------------------------------------------------------------------*\ + + FUNCTION....: codec2_decode_450 + AUTHOR......: David Rowe + DATE CREATED: Oct 1 2014 + + Decodes frames of 18 bits into 320 samples (40ms) of speech. + +\*---------------------------------------------------------------------------*/ + +void codec2_decode_450(struct CODEC2 *c2, short speech[], const unsigned char * bits) +{ + MODEL model[4]; + int lsp_indexes[LPC_ORD]; + float lsps[4][LPC_ORD]; + int Wo_index, e_index; + float e[4]; + float snr; + float ak[4][LPC_ORD+1]; + int i,j; + unsigned int nbit = 0; + float weight; + COMP Aw[FFT_ENC]; + + assert(c2 != NULL); + + /* only need to zero these out due to (unused) snr calculation */ + + for(i=0; i<4; i++) + for(j=1; j<=MAX_AMP; j++) + model[i].A[j] = 0.0; + + /* unpack bits from channel ------------------------------------*/ + + model[3].voiced = unpack(bits, &nbit, 1); + model[0].voiced = model[1].voiced = model[2].voiced = model[3].voiced; + + Wo_index = unpack_natural_or_gray(bits, &nbit, 5, c2->gray); + model[3].Wo = decode_log_Wo(Wo_index, 5); + model[3].L = PI/model[3].Wo; + + e_index = unpack_natural_or_gray(bits, &nbit, 3, c2->gray); + e[3] = decode_energy(e_index, 3); + + lsp_indexes[0] = unpack(bits, &nbit, lsp_pred_vq_bits(0)); + decode_lsps_vq(lsp_indexes, &lsps[3][0], LPC_ORD, 1); + check_lsp_order(&lsps[3][0], LPC_ORD); + bw_expand_lsps(&lsps[3][0], LPC_ORD, 50.0, 100.0); + + /* interpolate ------------------------------------------------*/ + + /* LSPs, Wo, and energy are sampled every 40ms so we interpolate + the 3 frames in between, then recover spectral amplitudes */ + + for(i=0, weight=0.25; i<3; i++, weight += 0.25) { + interpolate_lsp_ver2(&lsps[i][0], c2->prev_lsps_dec, &lsps[3][0], weight); + interp_Wo2(&model[i], &c2->prev_model_dec, &model[3], weight); + e[i] = interp_energy2(c2->prev_e_dec, e[3],weight); + } + for(i=0; i<4; i++) { + lsp_to_lpc(&lsps[i][0], &ak[i][0], LPC_ORD); + aks_to_M2(c2->fft_fwd_cfg, &ak[i][0], LPC_ORD, &model[i], e[i], &snr, 0, 0, + c2->lpc_pf, c2->bass_boost, c2->beta, c2->gamma, Aw); + apply_lpc_correction(&model[i]); + synthesise_one_frame(c2, &speech[N*i], &model[i], Aw); + } + + /* update memories for next frame ----------------------------*/ + + c2->prev_model_dec = model[3]; + c2->prev_e_dec = e[3]; + for(i=0; iprev_lsps_dec[i] = lsps[3][i]; +} + + /*---------------------------------------------------------------------------*\ FUNCTION....: synthesise_one_frame() diff --git a/codec2-dev/src/codec2.h b/codec2-dev/src/codec2.h index ea007065..ac888d7b 100644 --- a/codec2-dev/src/codec2.h +++ b/codec2-dev/src/codec2.h @@ -52,6 +52,7 @@ #define CODEC2_MODE_1400 3 #define CODEC2_MODE_1300 4 #define CODEC2_MODE_1200 5 +#define CODEC2_MODE_450 6 struct CODEC2; diff --git a/codec2-dev/src/freedv_api.c b/codec2-dev/src/freedv_api.c index b5491cef..c20f5709 100644 --- a/codec2-dev/src/freedv_api.c +++ b/codec2-dev/src/freedv_api.c @@ -140,9 +140,10 @@ void freedv_close(struct freedv *freedv) { a frame of modem samples that can be sent to the transmitter. speech_in[] and mod_out[] are sampled at 8 kHz, 16 bit shorts, and - FREEDV_NSAMPLES long. The speech_in[] level should be such that the - peak speech level is between +/16384 and +/- 32767. mod_out[] will - be scaled such that the peak level is just less than +/-32767. + are always FREEDV_NSAMPLES long. The speech_in[] level should be + such that the peak speech level is between +/16384 and +/- 32767. + mod_out[] will be scaled such that the peak level is just less than + +/-32767. The FDM modem signal mod_out[] has a high crest factor (around 12dB), however the energy and duration of the peaks is small. diff --git a/codec2-dev/src/quantise.c b/codec2-dev/src/quantise.c index 23f2660e..acf2a1a5 100644 --- a/codec2-dev/src/quantise.c +++ b/codec2-dev/src/quantise.c @@ -1007,17 +1007,17 @@ void aks_to_M2( \*---------------------------------------------------------------------------*/ -int encode_Wo(float Wo) +int encode_Wo(float Wo, int bits) { - int index; + int index, Wo_levels = 1< (WO_LEVELS-1)) index = WO_LEVELS-1; + if (index > (Wo_levels-1)) index = Wo_levels-1; return index; } @@ -1032,19 +1032,69 @@ int encode_Wo(float Wo) \*---------------------------------------------------------------------------*/ -float decode_Wo(int index) +float decode_Wo(int index, int bits) { float Wo_min = TWO_PI/P_MAX; float Wo_max = TWO_PI/P_MIN; float step; float Wo; + int Wo_levels = 1< (Wo_levels-1)) index = Wo_levels-1; + + return index; +} + +/*---------------------------------------------------------------------------*\ + + FUNCTION....: decode_log_Wo() + AUTHOR......: David Rowe + DATE CREATED: 22/8/2010 + + Decodes Wo using a WO_LEVELS quantiser in the log domain. + +\*---------------------------------------------------------------------------*/ + +float decode_log_Wo(int index, int bits) +{ + float Wo_min = TWO_PI/P_MAX; + float Wo_max = TWO_PI/P_MIN; + float step; + float Wo; + int Wo_levels = 1< (E_LEVELS-1)) index = E_LEVELS-1; + if (index > (e_levels-1)) index = e_levels-1; return index; } @@ -1701,14 +1753,15 @@ int encode_energy(float e) \*---------------------------------------------------------------------------*/ -float decode_energy(int index) +float decode_energy(int index, int bits) { float e_min = E_MIN_DB; float e_max = E_MAX_DB; float step; float e; + int e_levels = 1<