FreeCalypso > hg > gsm-codec-lib
view libtwamr/q_plsf_3.c @ 477:4c9222d95647
libtwamr encoder: always emit frame->mode = mode;
In the original implementation of amr_encode_frame(), the 'mode' member
of the output struct was set to 0xFF if the output frame type is TX_NO_DATA.
This design was made to mimic the mode field (16-bit word) being set to
0xFFFF (or -1) in 3GPP test sequence format - but nothing actually depends
on this struct member being set in any way, and amr_frame_to_tseq()
generates the needed 0xFFFF on its own, based on frame->type being equal
to TX_NO_DATA.
It is simpler and more efficient to always set frame->mode to the actual
encoding mode in amr_encode_frame(), and this new behavior has already
been documented in doc/AMR-library-API description in anticipation of
the present change.
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sat, 18 May 2024 22:30:42 +0000 |
parents | 9cca139a20a8 |
children |
line wrap: on
line source
/* ***************************************************************************** * * 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); }