Line data Source code
1 : /*====================================================================================
2 : EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
3 : ====================================================================================*/
4 :
5 : #include <stdint.h>
6 : #include "options.h" /* Compilation switches */
7 : #include "prot_fx.h"
8 : #include "rom_com.h"
9 :
10 : /*-------------------------------------------------------------------*
11 : * Function pvq_decode_fx() *
12 : * *
13 : * PVQ subvector decoding algorithm *
14 : *-------------------------------------------------------------------*/
15 :
16 273683 : void pvq_decode_fx(
17 : Decoder_State *st_fx,
18 : PVQ_DEC_HANDLE hPVQ, /* i/o: PVQ decoder handle */
19 : Word16 *xq, /* o: decoded vector (Q15) */
20 : Word16 *y, /* o: decoded vector (non-scaled int) */
21 : const Word16 k_val, /* i: number of allocated pulses */
22 : const Word16 dim, /* i: Length of vector */
23 : const Word16 neg_gain /* i: Gain (negated to fit 1.0 in Q15 as -1.0) */
24 : )
25 : {
26 : Word16 i;
27 :
28 : UWord32 h_mem[1 + KMAX_NON_DIRECT_FX + 1]; /* allocate max offset memory for dim 6 */
29 :
30 : PvqEntry entry;
31 :
32 : Word16 neg_gain_norm, shift_num, shift_den, shift_tot;
33 : Word32 L_yy, L_isqrt, L_tmp;
34 :
35 : UWord16 u16_tmp;
36 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
37 273683 : Flag Overflow = 0;
38 273683 : move16();
39 : #endif
40 :
41 273683 : entry = get_size_mpvq_calc_offset_fx( dim, k_val, h_mem ); /* get size & prepare H(adaptive table for entry.size=N_MPVQ(dim,k_val) */
42 :
43 :
44 273683 : IF( NE_16( dim, 1 ) )
45 : {
46 273641 : entry.lead_sign_ind = (Word16) rc_dec_bits_fx( st_fx, hPVQ, 1 );
47 273641 : entry.index = rc_dec_uniform_fx( st_fx, hPVQ, entry.size );
48 273641 : move16();
49 273641 : move32();
50 :
51 273641 : IF( st_fx->hHQ_core != NULL )
52 : {
53 : /* safety check in case of bit errors */
54 273514 : test();
55 273514 : IF( GE_32( entry.index, entry.size ) || st_fx->hHQ_core->ber_occured_in_pvq != 0 )
56 : {
57 0 : st_fx->hHQ_core->ber_occured_in_pvq = 1;
58 0 : move16();
59 0 : st_fx->BER_detect = 1;
60 0 : move16();
61 0 : entry.index = 0;
62 0 : move16(); /* a zero index will essentially disable PVQ index decompostion complexity */
63 : }
64 : }
65 : }
66 : ELSE
67 : {
68 42 : entry.lead_sign_ind = (Word16) rc_dec_bits_fx( st_fx, hPVQ, 1 ); /* always a single sign bit */
69 42 : entry.index = L_deposit_l( 0 );
70 42 : move16();
71 42 : move32();
72 : }
73 :
74 273683 : mpvq_decode_vec_fx( &entry, h_mem, y );
75 :
76 273683 : IF( neg_gain == 0 )
77 : {
78 5614 : FOR( i = 0; i < dim; i++ )
79 : {
80 5210 : xq[i] = 0;
81 5210 : move16();
82 : }
83 : }
84 : ELSE
85 : {
86 273279 : L_yy = L_deposit_l( 0 );
87 3753879 : FOR( i = 0; i < dim; i++ )
88 : {
89 3480600 : L_yy = L_mac( L_yy, y[i], y[i] ); /* Q1 */
90 : }
91 :
92 273279 : L_isqrt = Isqrt( L_shr( L_yy, 1 ) ); /*Q31*/ /* one single gain fac as in flt not computed for now */
93 :
94 273279 : shift_num = norm_s( k_val ); /* account for max possible pulseamp in y */
95 273279 : shift_den = norm_s( neg_gain ); /* account for downscaling shift */
96 273279 : neg_gain_norm = shl( neg_gain, shift_den ); /* 10 db loss in minSNR without this in L_qx , at HQ128 FB*/
97 273279 : shift_tot = sub( add( shift_num, shift_den ), 15 );
98 :
99 273279 : L_isqrt = L_negate( L_isqrt );
100 3753879 : FOR( i = 0; i < dim; i++ )
101 : {
102 : /* upshifted y[i] used */
103 :
104 3480600 : Mpy_32_16_ss( L_isqrt, shl( y[i], shift_num ), &L_tmp, &u16_tmp ); /* Q31*Q(0+x) *2*/
105 3480600 : Mpy_32_16_ss( L_tmp, neg_gain_norm, &L_tmp, &u16_tmp ); /* Q31*Q(0+x) *Q15 *2*/
106 3480600 : L_tmp = L_shr_o( L_tmp, shift_tot, &Overflow );
107 3480600 : xq[i] = round_fx_o( L_tmp, &Overflow ); /* Q15 , array move */
108 3480600 : move16();
109 : }
110 : }
111 :
112 :
113 273683 : return;
114 : }
|