FreeCalypso > hg > gsm-codec-lib
diff libgsmefr/d_plsf_5.c @ 53:49dd1ac8e75b
libgsmefr: import most *.c files from ETSI source
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Fri, 25 Nov 2022 16:18:21 +0000 |
parents | |
children | 6a623cb57d07 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libgsmefr/d_plsf_5.c Fri Nov 25 16:18:21 2022 +0000 @@ -0,0 +1,289 @@ +/************************************************************************* + * + * FUNCTION: D_plsf_5() + * + * PURPOSE: Decodes the 2 sets of LSP parameters in a frame using the + * received quantization indices. + * + * DESCRIPTION: + * The two sets of LSFs are quantized using split by 5 matrix + * quantization (split-MQ) with 1st order MA prediction. + * + * See "q_plsf_5.c" for more details about the quantization procedure + * + *************************************************************************/ + +#include "typedef.h" +#include "basic_op.h" +#include "count.h" +#include "sig_proc.h" + +#include "q_plsf_5.tab" /* Codebooks of LSF prediction residual */ + +#include "cnst.h" +#include "dtx.h" + +/* M ->order of linear prediction filter */ +/* LSF_GAP -> Minimum distance between LSF after quantization */ +/* 50 Hz = 205 */ +/* PRED_FAC -> Prediction factor = 0.65 */ +/* ALPHA -> 0.9 */ +/* ONE_ALPHA-> (1.0-ALPHA) */ + +#define M 10 +#define LSF_GAP 205 +#define PRED_FAC 21299 +#define ALPHA 31128 +#define ONE_ALPHA 1639 + +/* Past quantized prediction error */ + +Word16 past_r2_q[M]; + +/* Past dequantized lsfs */ + +Word16 past_lsf_q[M]; + +/* Reference LSF parameter vector (comfort noise) */ + +Word16 lsf_p_CN[M]; + +/* LSF memories for comfort noise interpolation */ + +Word16 lsf_old_CN[M], lsf_new_CN[M]; + + /* LSF parameter buffer */ + +extern Word16 lsf_old_rx[DTX_HANGOVER][M]; + +void D_plsf_5 ( + Word16 *indice, /* input : quantization indices of 5 submatrices */ + Word16 *lsp1_q, /* output: quantized 1st LSP vector */ + Word16 *lsp2_q, /* output: quantized 2nd LSP vector */ + Word16 bfi, /* input : bad frame indicator (set to 1 if a bad + frame is received) */ + Word16 rxdtx_ctrl, /* input : RX DTX control word */ + Word16 rx_dtx_state /* input : state of the comfort noise insertion + period */ +) +{ + Word16 i; + const Word16 *p_dico; + Word16 temp, sign; + Word16 lsf1_r[M], lsf2_r[M]; + Word16 lsf1_q[M], lsf2_q[M]; + + /* Update comfort noise LSF quantizer memory */ + test (); logic16 (); + if ((rxdtx_ctrl & RX_UPD_SID_QUANT_MEM) != 0) + { + update_lsf_p_CN (lsf_old_rx, lsf_p_CN); + } + /* Handle cases of comfort noise LSF decoding in which past + valid SID frames are repeated */ + + test (); logic16 (); + test (); logic16 (); + test (); logic16 (); + if (((rxdtx_ctrl & RX_NO_TRANSMISSION) != 0) + || ((rxdtx_ctrl & RX_INVALID_SID_FRAME) != 0) + || ((rxdtx_ctrl & RX_LOST_SID_FRAME) != 0)) + { + + test (); logic16 (); + if ((rxdtx_ctrl & RX_NO_TRANSMISSION) != 0) + { + /* DTX active: no transmission. Interpolate LSF values in memory */ + interpolate_CN_lsf (lsf_old_CN, lsf_new_CN, lsf2_q, rx_dtx_state); + } + else + { /* Invalid or lost SID frame: use LSFs + from last good SID frame */ + for (i = 0; i < M; i++) + { + lsf_old_CN[i] = lsf_new_CN[i]; move16 (); + lsf2_q[i] = lsf_new_CN[i]; move16 (); + past_r2_q[i] = 0; move16 (); + } + } + + for (i = 0; i < M; i++) + { + past_lsf_q[i] = lsf2_q[i]; move16 (); + } + + /* convert LSFs to the cosine domain */ + Lsf_lsp (lsf2_q, lsp2_q, M); + + return; + } + + test (); + if (bfi != 0) /* if bad frame */ + { + /* use the past LSFs slightly shifted towards their mean */ + + for (i = 0; i < M; i++) + { + /* lsfi_q[i] = ALPHA*past_lsf_q[i] + ONE_ALPHA*mean_lsf[i]; */ + + lsf1_q[i] = add (mult (past_lsf_q[i], ALPHA), + mult (mean_lsf[i], ONE_ALPHA)); + move16 (); + + lsf2_q[i] = lsf1_q[i]; move16 (); + } + + /* estimate past quantized residual to be used in next frame */ + + for (i = 0; i < M; i++) + { + /* temp = mean_lsf[i] + past_r2_q[i] * PRED_FAC; */ + + temp = add (mean_lsf[i], mult (past_r2_q[i], PRED_FAC)); + + past_r2_q[i] = sub (lsf2_q[i], temp); + move16 (); + } + } + else + /* if good LSFs received */ + { + /* decode prediction residuals from 5 received indices */ + + p_dico = &dico1_lsf[shl (indice[0], 2)]; + lsf1_r[0] = *p_dico++; move16 (); + lsf1_r[1] = *p_dico++; move16 (); + lsf2_r[0] = *p_dico++; move16 (); + lsf2_r[1] = *p_dico++; move16 (); + + p_dico = &dico2_lsf[shl (indice[1], 2)]; + lsf1_r[2] = *p_dico++; move16 (); + lsf1_r[3] = *p_dico++; move16 (); + lsf2_r[2] = *p_dico++; move16 (); + lsf2_r[3] = *p_dico++; move16 (); + + sign = indice[2] & 1; logic16 (); + i = shr (indice[2], 1); + p_dico = &dico3_lsf[shl (i, 2)]; move16 (); + + test (); + if (sign == 0) + { + lsf1_r[4] = *p_dico++; move16 (); + lsf1_r[5] = *p_dico++; move16 (); + lsf2_r[4] = *p_dico++; move16 (); + lsf2_r[5] = *p_dico++; move16 (); + } + else + { + lsf1_r[4] = negate (*p_dico++); move16 (); + lsf1_r[5] = negate (*p_dico++); move16 (); + lsf2_r[4] = negate (*p_dico++); move16 (); + lsf2_r[5] = negate (*p_dico++); move16 (); + } + + p_dico = &dico4_lsf[shl (indice[3], 2)];move16 (); + lsf1_r[6] = *p_dico++; move16 (); + lsf1_r[7] = *p_dico++; move16 (); + lsf2_r[6] = *p_dico++; move16 (); + lsf2_r[7] = *p_dico++; move16 (); + + p_dico = &dico5_lsf[shl (indice[4], 2)];move16 (); + lsf1_r[8] = *p_dico++; move16 (); + lsf1_r[9] = *p_dico++; move16 (); + lsf2_r[8] = *p_dico++; move16 (); + lsf2_r[9] = *p_dico++; move16 (); + + /* Compute quantized LSFs and update the past quantized residual */ + /* Use lsf_p_CN as predicted LSF vector in case of no speech + activity */ + + test (); logic16 (); + if ((rxdtx_ctrl & RX_SP_FLAG) != 0) + { + for (i = 0; i < M; i++) + { + temp = add (mean_lsf[i], mult (past_r2_q[i], PRED_FAC)); + lsf1_q[i] = add (lsf1_r[i], temp); + move16 (); + lsf2_q[i] = add (lsf2_r[i], temp); + move16 (); + past_r2_q[i] = lsf2_r[i]; move16 (); + } + } + else + { /* Valid SID frame */ + for (i = 0; i < M; i++) + { + lsf2_q[i] = add (lsf2_r[i], lsf_p_CN[i]); + move16 (); + + /* Use the dequantized values of lsf2 also for lsf1 */ + lsf1_q[i] = lsf2_q[i]; move16 (); + + past_r2_q[i] = 0; move16 (); + } + } + } + + /* verification that LSFs have minimum distance of LSF_GAP Hz */ + + Reorder_lsf (lsf1_q, LSF_GAP, M); + Reorder_lsf (lsf2_q, LSF_GAP, M); + + test (); logic16 (); + if ((rxdtx_ctrl & RX_FIRST_SID_UPDATE) != 0) + { + for (i = 0; i < M; i++) + { + lsf_new_CN[i] = lsf2_q[i]; move16 (); + } + } + test (); logic16 (); + if ((rxdtx_ctrl & RX_CONT_SID_UPDATE) != 0) + { + for (i = 0; i < M; i++) + { + lsf_old_CN[i] = lsf_new_CN[i]; move16 (); + lsf_new_CN[i] = lsf2_q[i]; move16 (); + } + } + test (); logic16 (); + if ((rxdtx_ctrl & RX_SP_FLAG) != 0) + { + /* Update lsf history with quantized LSFs + when speech activity is present. If the current frame is + a bad one, update with most recent good comfort noise LSFs */ + + if (bfi==0) + { + update_lsf_history (lsf1_q, lsf2_q, lsf_old_rx); + } + else + { + update_lsf_history (lsf_new_CN, lsf_new_CN, lsf_old_rx); + } + + for (i = 0; i < M; i++) + { + lsf_old_CN[i] = lsf2_q[i]; move16 (); + } + } + else + { + interpolate_CN_lsf (lsf_old_CN, lsf_new_CN, lsf2_q, rx_dtx_state); + } + + for (i = 0; i < M; i++) + { + past_lsf_q[i] = lsf2_q[i]; move16 (); + } + + /* convert LSFs to the cosine domain */ + + Lsf_lsp (lsf1_q, lsp1_q, M); + Lsf_lsp (lsf2_q, lsp2_q, M); + + return; +}