FreeCalypso > hg > gsm-codec-lib
diff libtwamr/q_plsf_3.c @ 372:9cca139a20a8
libtwamr: integrate q_plsf_3.c
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Mon, 06 May 2024 04:00:14 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libtwamr/q_plsf_3.c Mon May 06 04:00:14 2024 +0000 @@ -0,0 +1,312 @@ +/* +***************************************************************************** +* +* GSM AMR-NB speech codec R98 Version 7.6.0 December 12, 2001 +* R99 Version 3.3.0 +* REL-4 Version 4.1.0 +* +**************************************************************************** +* +* File : q_plsf_3.c +* Purpose : Quantization of LSF parameters with 1st order MA +* prediction and split by 3 vector quantization +* (split-VQ) +* +***************************************************************************** +*/ + +/* +***************************************************************************** +* MODULE INCLUDE FILE AND VERSION ID +***************************************************************************** +*/ +#include "namespace.h" +#include "q_plsf.h" + +/* +***************************************************************************** +* INCLUDE FILES +***************************************************************************** +*/ +#include "typedef.h" +#include "basic_op.h" +#include "no_count.h" +#include "lsp_lsf.h" +#include "reorder.h" +#include "lsfwt.h" +#include "memops.h" +#include "q_plsf3_tab.h" + +/* +***************************************************************************** +* LOCAL VARIABLES AND TABLES +***************************************************************************** +*/ +#define PAST_RQ_INIT_SIZE 8 +/* +***************************************************************************** +* LOCAL PROGRAM CODE +***************************************************************************** +*/ +/* Quantization of a 4 dimensional subvector */ + +static Word16 +Vq_subvec4( /* o: quantization index, Q0 */ + Word16 * lsf_r1, /* i/o: 1st LSF residual vector, Q15 */ + const Word16 * dico, /* i: quantization codebook, Q15 */ + const Word16 * wf1, /* i: 1st LSF weighting factors, Q13 */ + Word16 dico_size) /* i: size of quantization codebook, Q0 */ +{ + Word16 i, index = 0, temp; + const Word16 *p_dico; + Word32 dist_min, dist; + + dist_min = MAX_32; move32 (); + p_dico = dico; move16 (); + + for (i = 0; i < dico_size; i++) + { + temp = sub (lsf_r1[0], *p_dico++); + temp = mult (wf1[0], temp); + dist = L_mult (temp, temp); + + temp = sub (lsf_r1[1], *p_dico++); + temp = mult (wf1[1], temp); + dist = L_mac (dist, temp, temp); + + temp = sub (lsf_r1[2], *p_dico++); + temp = mult (wf1[2], temp); + dist = L_mac (dist, temp, temp); + + temp = sub (lsf_r1[3], *p_dico++); + temp = mult (wf1[3], temp); + dist = L_mac (dist, temp, temp); + + test (); + if (L_sub (dist, dist_min) < (Word32) 0) + { + dist_min = dist; move32 (); + index = i; move16 (); + } + } + + /* Reading the selected vector */ + + p_dico = &dico[shl (index, 2)]; move16 (); + lsf_r1[0] = *p_dico++; move16 (); + lsf_r1[1] = *p_dico++; move16 (); + lsf_r1[2] = *p_dico++; move16 (); + lsf_r1[3] = *p_dico++; move16 (); + + return index; +} + +/* Quantization of a 3 dimensional subvector */ + +static Word16 +Vq_subvec3( /* o: quantization index, Q0 */ + Word16 * lsf_r1, /* i/o: 1st LSF residual vector, Q15 */ + const Word16 * dico, /* i: quantization codebook, Q15 */ + const Word16 * wf1, /* i: 1st LSF weighting factors, Q13 */ + Word16 dico_size, /* i: size of quantization codebook, Q0 */ + Flag use_half) /* i: use every second entry in codebook */ +{ + Word16 i, index = 0, temp; + const Word16 *p_dico; + Word32 dist_min, dist; + + dist_min = MAX_32; move32 (); + p_dico = dico; move16 (); + + test (); + if (use_half == 0) { + for (i = 0; i < dico_size; i++) + { + temp = sub(lsf_r1[0], *p_dico++); + temp = mult(wf1[0], temp); + dist = L_mult(temp, temp); + + temp = sub(lsf_r1[1], *p_dico++); + temp = mult(wf1[1], temp); + dist = L_mac(dist, temp, temp); + + temp = sub(lsf_r1[2], *p_dico++); + temp = mult(wf1[2], temp); + dist = L_mac(dist, temp, temp); + + test (); + if (L_sub(dist, dist_min) < (Word32) 0) { + dist_min = dist; move32 (); + index = i; move16 (); + } + } + p_dico = &dico[add(index, add(index, index))]; move16 (); + } + else + { + for (i = 0; i < dico_size; i++) + { + temp = sub(lsf_r1[0], *p_dico++); + temp = mult(wf1[0], temp); + dist = L_mult(temp, temp); + + temp = sub(lsf_r1[1], *p_dico++); + temp = mult(wf1[1], temp); + dist = L_mac(dist, temp, temp); + + temp = sub(lsf_r1[2], *p_dico++); + temp = mult(wf1[2], temp); + dist = L_mac(dist, temp, temp); + + test (); + if (L_sub(dist, dist_min) < (Word32) 0) + { + dist_min = dist; move32 (); + index = i; move16 (); + } + p_dico = p_dico + 3; add(0,0); + } + p_dico = &dico[shl(add(index, add(index, index)),1)]; move16 (); + } + + /* Reading the selected vector */ + lsf_r1[0] = *p_dico++; move16 (); + lsf_r1[1] = *p_dico++; move16 (); + lsf_r1[2] = *p_dico++; move16 (); + + return index; +} + +/* +***************************************************************************** +* PUBLIC PROGRAM CODE +***************************************************************************** +*/ + +/*********************************************************************** + * + * routine: Q_plsf_3() + * + * Quantization of LSF parameters with 1st order MA prediction and + * split by 3 vector quantization (split-VQ) + * + ***********************************************************************/ +void Q_plsf_3( + Q_plsfState *st, /* i/o: state struct */ + enum Mode mode, /* i : coder mode */ + Word16 *lsp1, /* i : 1st LSP vector Q15 */ + Word16 *lsp1_q, /* o : quantized 1st LSP vector Q15 */ + Word16 *indice, /* o : quantization indices of 3 vectors Q0 */ + Word16 *pred_init_i /* o : init index for MA prediction in DTX mode */ +) +{ + Word16 i, j; + Word16 lsf1[M], wf1[M], lsf_p[M], lsf_r1[M]; + Word16 lsf1_q[M]; + + Word32 L_pred_init_err; + Word32 L_min_pred_init_err; + Word16 temp_r1[M]; + Word16 temp_p[M]; + + /* convert LSFs to normalize frequency domain 0..16384 */ + + Lsp_lsf(lsp1, lsf1, M); + + /* compute LSF weighting factors (Q13) */ + + Lsf_wt(lsf1, wf1); + + /* Compute predicted LSF and prediction error */ + if (test(), sub(mode, MRDTX) != 0) + { + for (i = 0; i < M; i++) + { + lsf_p[i] = add(mean_lsf3[i], + mult(st->past_rq[i], + pred_fac[i])); move16 (); + lsf_r1[i] = sub(lsf1[i], lsf_p[i]); move16 (); + } + } + else + { + /* DTX mode, search the init vector that yields */ + /* lowest prediction resuidual energy */ + *pred_init_i = 0; move16 (); + L_min_pred_init_err = 0x7fffffff; /* 2^31 - 1 */ move32 (); + for (j = 0; j < PAST_RQ_INIT_SIZE; j++) + { + L_pred_init_err = 0; move32 (); + for (i = 0; i < M; i++) + { + temp_p[i] = add(mean_lsf3[i], past_rq_init[j*M+i]); + temp_r1[i] = sub(lsf1[i],temp_p[i]); + L_pred_init_err = L_mac(L_pred_init_err, temp_r1[i], temp_r1[i]); + } /* next i */ + + test (); + if (L_sub(L_pred_init_err, L_min_pred_init_err) < (Word32) 0) + { + L_min_pred_init_err = L_pred_init_err; move32 (); + Copy(temp_r1, lsf_r1, M); + Copy(temp_p, lsf_p, M); + + /* Set zerom */ + Copy(&past_rq_init[j*M], st->past_rq, M); + *pred_init_i = j; move16 (); + } /* endif */ + } /* next j */ + } /* endif MRDTX */ + + /*---- Split-VQ of prediction error ----*/ + if (sub (mode, MR475) == 0 || sub (mode, MR515) == 0) + { /* MR475, MR515 */ + test (); test (); + + indice[0] = Vq_subvec3(&lsf_r1[0], dico1_lsf3, &wf1[0], DICO31_SIZE, 0); + move16 (); + indice[1] = Vq_subvec3(&lsf_r1[3], dico2_lsf3, &wf1[3], DICO32_SIZE/2, 1); + move16 (); + indice[2] = Vq_subvec4(&lsf_r1[6], mr515_3_lsf, &wf1[6], MR515_3_SIZE); + move16 (); + } + else if (sub (mode, MR795) == 0) + { /* MR795 */ + test (); test (); test (); + + indice[0] = Vq_subvec3(&lsf_r1[0], mr795_1_lsf, &wf1[0], MR795_1_SIZE, 0); + move16 (); + indice[1] = Vq_subvec3(&lsf_r1[3], dico2_lsf3, &wf1[3], DICO32_SIZE, 0); + move16 (); + indice[2] = Vq_subvec4(&lsf_r1[6], dico3_lsf3, &wf1[6], DICO33_SIZE); + move16 (); + } + else + { /* MR59, MR67, MR74, MR102 , MRDTX */ + test (); test (); test (); + + indice[0] = Vq_subvec3(&lsf_r1[0], dico1_lsf3, &wf1[0], DICO31_SIZE, 0); + move16 (); + indice[1] = Vq_subvec3(&lsf_r1[3], dico2_lsf3, &wf1[3], DICO32_SIZE, 0); + move16 (); + indice[2] = Vq_subvec4(&lsf_r1[6], dico3_lsf3, &wf1[6], DICO33_SIZE); + move16 (); + } + + + /* Compute quantized LSFs and update the past quantized residual */ + + for (i = 0; i < M; i++) + { + lsf1_q[i] = add(lsf_r1[i], lsf_p[i]); move16 (); + st->past_rq[i] = lsf_r1[i]; move16 (); + } + + /* verification that LSFs has mimimum distance of LSF_GAP Hz */ + + Reorder_lsf(lsf1_q, LSF_GAP, M); + + /* convert LSFs to the cosine domain */ + + Lsf_lsp(lsf1_q, lsp1_q, M); +}