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 <assert.h>
7 : #include "prot_fx.h"
8 : #include "basop_util.h"
9 : #include "stl.h"
10 : #include "rom_com.h"
11 : /*-------------------------------------------------------------------*
12 : * Decoding of pitch and codebook gains (see q_gain2_plus.c) *
13 : *-------------------------------------------------------------------*/
14 :
15 : /*********************
16 : * private functions *
17 : *********************/
18 3050 : static Word32 calc_gcode0_fx(
19 : Word16 *gcode0, // Q8
20 : Word16 *exp_gcode0 // Q0
21 : )
22 : {
23 : Word32 L_tmp;
24 :
25 : /*gcode0 = (float)pow(10.0,(gcode0)*0.05);*/ /* predicted gain */
26 :
27 3050 : L_tmp = L_mult( *gcode0, 5443 /*0.166096f Q15*/ ); // Q24
28 3050 : *exp_gcode0 = add( 1, extract_l( L_shr( L_tmp, 24 ) ) ); // Q0
29 3050 : move16();
30 3050 : L_tmp = L_lshl( L_tmp, 7 ); // Q31
31 3050 : L_tmp = L_and( 0x7FFFFFFF, L_tmp ); // 0x7FFFFFFF-> 1 in Q31
32 :
33 3050 : L_tmp = Pow2( 30, round_fx( L_tmp ) );
34 3050 : *gcode0 = round_fx( L_tmp );
35 3050 : move16();
36 :
37 3050 : return L_tmp;
38 : }
39 :
40 3050 : static Word32 calc_gain_code_fx( Word16 g_code, Word16 gcode0, Word16 exp_gcode0 )
41 : {
42 : Word32 L_tmp;
43 :
44 3050 : L_tmp = L_mult( g_code, gcode0 ); /* Q11*Q15 -> Q27 */
45 3050 : exp_gcode0 = add( exp_gcode0, -11 );
46 3050 : L_tmp = L_shl_sat( L_tmp, exp_gcode0 ); /* Q27 -> Q16 */
47 :
48 3050 : return L_tmp;
49 : }
50 :
51 : /*--------------------------------------------------------------------------*
52 : * Mode2_gain_dec_mless_fx
53 : *
54 : * Decoding of pitch and codebook gains without updating long term energies
55 : *-------------------------------------------------------------------------*/
56 :
57 3050 : static void Mode2_gain_dec_mless_fx(
58 : Word16 index, /* i : Quantization index vector Q0 */
59 : Word16 *code, /* i : algebraic code excitation Q9 */
60 : Word16 lcode, /* i : Subframe size Q0 */
61 : Word16 *gain_pit, /* o : Quantized pitch gain 1Q14 */
62 : Word32 *gain_code, /* o : Quantized codebook gain Q16 */
63 : Word16 mean_ener, /* i : mean_ener defined in open-loop Q8 */
64 : Word16 *past_gpit, /* i/o: past gain of pitch 1Q14 */
65 : Word32 *past_gcode, /* i/o: past energy of code Q16 */
66 : Word16 *gain_inov, /* o : unscaled innovation gain 3Q12 */
67 : Word16 coder_type /* i : coder type for number of bits */
68 : )
69 : {
70 :
71 : Word16 ener_code;
72 : const Word16 *t_qua_gain;
73 : Word16 exp_L_tmp1;
74 : Word16 gcode0, exp_gcode0;
75 : Word32 L_tmp, L_tmp1;
76 :
77 :
78 : /**gain_inov = 1.0f / (float)sqrt( ( dot_product( code, code, lcode ) + 0.01f ) / lcode);*/
79 3050 : L_tmp = calc_gain_inov( code, lcode, &L_tmp1, &exp_L_tmp1 );
80 3050 : *gain_inov = round_fx_sat( L_shl_sat( L_tmp, 15 - 3 ) ); /* gain_inov in Q12 */
81 3050 : move16();
82 : /*-----------------------------------------------------------------*
83 : * Select the gains quantization table
84 : *-----------------------------------------------------------------*/
85 3050 : t_qua_gain = E_ROM_qua_gain7b_const;
86 3050 : move16();
87 3050 : if ( coder_type == 0 )
88 : {
89 0 : t_qua_gain = E_ROM_qua_gain5b_const;
90 0 : move16();
91 : }
92 :
93 3050 : if ( EQ_16( coder_type, 1 ) )
94 : {
95 130 : t_qua_gain = E_ROM_qua_gain6b_const;
96 130 : move16();
97 : }
98 :
99 : /*-----------------------------------------------------------------*
100 : * decode pitch gain
101 : *-----------------------------------------------------------------*/
102 3050 : *gain_pit = t_qua_gain[shl( index, 1 )];
103 3050 : move16();
104 : /*-----------------------------------------------------------------*
105 : * calculate the predicted gain code
106 : *-----------------------------------------------------------------*/
107 : /*ener_code = 10 * log10((dot_product(code, code, lcode) + 0.01) / lcode) */
108 3050 : L_tmp = BASOP_Util_Log2( L_tmp1 );
109 3050 : L_tmp = L_add( L_tmp, L_shl( L_deposit_l( exp_L_tmp1 ), 31 - LD_DATA_SCALE ) );
110 :
111 3050 : L_tmp = Mpy_32_16_1( L_tmp, 24660 /*(10.0f/3.3219280948873623478703194294894f)/4.0f Q15*/ );
112 : /* exponent of L_tmp = 6+2 */
113 3050 : ener_code = round_fx( L_shl( L_tmp, 6 + 2 - 7 ) ); /* Q8 */
114 :
115 : /* predicted codebook gain */
116 3050 : gcode0 = sub( mean_ener, ener_code ); /* Q8 */
117 :
118 : /*gcode0 = (float)pow(10.0,(gcode0)*0.05);*/ /* predicted gain */
119 :
120 3050 : calc_gcode0_fx( &gcode0, &exp_gcode0 );
121 :
122 : /*-----------------------------------------------------------------*
123 : * decode normalized codebook gain
124 : *-----------------------------------------------------------------*/
125 : /* *gain_code = t_qua_gain[index*2+1] * gcode0;*/
126 : Word16 tmp_idx;
127 3050 : tmp_idx = add( shl( index, 1 ), 1 );
128 3050 : L_tmp = calc_gain_code_fx( t_qua_gain[tmp_idx], gcode0, exp_gcode0 );
129 :
130 3050 : *gain_code = L_tmp;
131 3050 : move32();
132 3050 : *past_gpit = *gain_pit;
133 3050 : move16();
134 : /**past_gcode = *gain_code / *gain_inov; */
135 : /* Q16/Q12 => Q5 */
136 3050 : L_tmp1 = L_deposit_h( BASOP_Util_Divide3216_Scale( L_tmp, *gain_inov, &exp_L_tmp1 ) );
137 3050 : *past_gcode = L_shl( L_tmp1, sub( exp_L_tmp1, 15 - 12 ) );
138 3050 : move32();
139 :
140 :
141 3050 : return;
142 : }
143 :
144 : /*---------------------------------------------------------------------*
145 : * gain_dec_uv_fx
146 : *
147 : * Decoding of pitch and codebook gains for Unvoiced mode
148 : *---------------------------------------------------------------------*/
149 :
150 0 : static void gain_dec_uv_fx(
151 : Word16 index, /* i : Quantization index vector Q0 */
152 : Word16 *code, /* i : algebraic code excitation Q9 */
153 : Word16 lcode, /* i : Subframe size Q0 */
154 : Word16 *gain_pit, /* o : Quantized pitch gain 1Q14 */
155 : Word32 *gain_code, /* o : Quantized codebook gain Q16 */
156 : Word16 *past_gpit, /* i/o: past gain of pitch 1Q14 */
157 : Word32 *past_gcode, /* i/o: past energy of code Q16 */
158 : Word16 *gain_inov /* o : unscaled innovation gain 3Q12 */
159 : )
160 : {
161 : Word16 i, exp_L_tmp1;
162 : Word32 L_tmp, L_tmp1;
163 :
164 :
165 : /*-----------------------------------------------------------------*
166 : * Innovation energy (without gain)
167 : *-----------------------------------------------------------------*/
168 : /* *gain_inov = 1.0f / (float)sqrt( ( dot_product( code, code, lcode ) + 0.01f ) / lcode );*/
169 0 : L_tmp = calc_gain_inov( code, lcode, &L_tmp1, &exp_L_tmp1 );
170 0 : *gain_inov = round_fx( L_shl( L_tmp, 15 - 3 ) ); /* gain_inov in Q12 */
171 0 : move16();
172 : /*-----------------------------------------------------------------*
173 : * Decode pitch gain
174 : *-----------------------------------------------------------------*/
175 0 : *gain_pit = 0;
176 0 : move16();
177 :
178 : /*-----------------------------------------------------------------*
179 : * Decode codebook gain
180 : *-----------------------------------------------------------------*/
181 : /* *gain_code= (float)pow(10.f,(((index*1.9f)-30.f)/20.f));*/
182 0 : L_tmp = L_mac( -167197708l /*-0.166096*30.0f Q25*/, shl( index, 16 - 7 ), 10341 /*0.166096f*1.9f Q15*/ );
183 0 : i = add( 1, extract_l( L_shr( L_tmp, 25 ) ) );
184 0 : L_tmp = L_lshl( L_tmp, 6 );
185 0 : L_tmp = L_and( 0x7FFFFFFF, L_tmp ); // 0x7FFFFFFF ->1 in Q31
186 :
187 0 : L_tmp = Pow2( 30, round_fx( L_tmp ) );
188 0 : L_tmp = L_shl( L_tmp, sub( i, ( 31 - 16 ) ) ); /* Q16 */
189 :
190 :
191 : /*-----------------------------------------------------------------*
192 : * past gains for error concealment
193 : *-----------------------------------------------------------------*/
194 0 : *past_gpit = *gain_pit;
195 0 : move16();
196 0 : *past_gcode = L_tmp;
197 0 : move32();
198 0 : L_tmp = L_shl_sat( Mpy_32_16_1( L_tmp, *gain_inov ), 3 ); /* Q16*Q12 -> Q13 -> Q16 */
199 0 : *gain_code = L_tmp;
200 0 : move32();
201 :
202 :
203 0 : return;
204 : }
205 :
206 : /*---------------------------------------------------------------------*
207 : * gain_dec_gacelp_uv_fx
208 : *
209 : * Decoding of pitch and codebook gains for Unvoiced mode
210 : *---------------------------------------------------------------------*/
211 :
212 0 : static void gain_dec_gacelp_uv_fx(
213 : Word16 index, /* i : Quantization index vector Q0 */
214 : Word16 *code, /* i : algebraic code excitation Q9 */
215 : Word16 *code2, /* i : algebraic code excitation Q9 */
216 : Word16 mean_ener, /* i : Q8 */
217 : Word16 lcode, /* i : Subframe size Q0 */
218 : Word16 *gain_pit, /* o : Quantized pitch gain 1Q14 */
219 : Word32 *gain_code, /* o : Quantized codebook gain Q16 */
220 : Word32 *gain_code2, /* o : Quantized codebook gain Q16 */
221 : Word16 *past_gpit, /* i/o: past gain of pitch 1Q14 */
222 : Word32 *past_gcode, /* i/o: past energy of code Q16 */
223 : Word16 *gain_inov /* o : unscaled innovation gain 3Q12 */
224 : )
225 : {
226 : Word16 i, exp_L_tmp1;
227 : Word16 exp_gcode;
228 : Word16 g_code;
229 : Word32 L_tmp, L_tmp1;
230 : Word32 pred_nrg_frame;
231 : Word16 exp_gcode2, g_code2, norm_code2;
232 : Word16 index2, s;
233 :
234 :
235 : /* pred_nrg_frame = (float)pow(10.0,mean_ener/20.0); */
236 0 : L_tmp = L_mult( mean_ener, 10885 /*0.166096f * 2 Q15*/ ); /* 6Q25 */
237 0 : pred_nrg_frame = BASOP_Util_InvLog2( L_sub( L_tmp, 503316480l /*15.f Q25*/ ) ); /* 15Q16 */
238 :
239 : /*-----------------------------------------------------------------*
240 : * Prediction gains
241 : *-----------------------------------------------------------------*/
242 : /* gain_inov = 1.0f / sqrt((dot_product(code, code, L_SUBFR) + 0.01) / L_SUBFR) */
243 0 : L_tmp = calc_gain_inov( code, lcode, NULL, NULL );
244 0 : *gain_inov = round_fx( L_shl( L_tmp, 15 - 3 ) ); /* gain_inov in Q12 */
245 0 : move16();
246 :
247 : /* gcode = pred_nrg_frame * (*gain_inov); */
248 0 : L_tmp = Mpy_32_16_1( pred_nrg_frame, *gain_inov ); /* 18Q13 */
249 0 : i = norm_l( L_tmp );
250 0 : g_code = round_fx( L_shl( L_tmp, i ) );
251 0 : exp_gcode = sub( 18, i );
252 :
253 : /* norm_code2 = 1.0f / sqrt((dot_product(code2, code2, lcode) + 0.01f) / lcode); */
254 0 : L_tmp = calc_gain_inov( code2, lcode, NULL, NULL );
255 0 : norm_code2 = round_fx( L_shl( L_tmp, 15 - 3 ) ); /* Q12 */
256 :
257 : /* g_code2 = pred_nrg_frame * norm_code2; */
258 0 : L_tmp = Mpy_32_16_1( pred_nrg_frame, norm_code2 ); /* 18Q13 */
259 0 : i = norm_l( L_tmp );
260 0 : g_code2 = round_fx_sat( L_shl_sat( L_tmp, i ) );
261 0 : exp_gcode2 = sub( 18, i );
262 :
263 : /*-----------------------------------------------------------------*
264 : * Decode pitch gain
265 : *-----------------------------------------------------------------*/
266 0 : *gain_pit = 0;
267 0 : move16();
268 0 : *past_gpit = *gain_pit;
269 0 : move16();
270 :
271 : /*-----------------------------------------------------------------*
272 : * past gains for error concealment
273 : *-----------------------------------------------------------------*/
274 0 : index2 = shr( index, 5 );
275 0 : index = s_and( index, 0x1F ); // 0x1F -> 31
276 :
277 : /**gain_code= (float)pow(10.f,(((index*1.25f)-20.f)/20.f))*gcode;*/
278 :
279 0 : L_tmp = L_mac( -111465139l /*-0.166096*20.0f Q25*/, shl( index, 16 - 7 ), 6803 /*0.166096f*1.25f Q15*/ );
280 :
281 0 : i = add( 1, extract_l( L_shr( L_tmp, 25 ) ) );
282 0 : L_tmp = L_lshl( L_tmp, 6 );
283 0 : L_tmp = L_and( 0x7FFFFFFF, L_tmp ); // 0x7FFFFFFF-> 1 in Q31
284 :
285 0 : L_tmp = Pow2( 30, round_fx( L_tmp ) );
286 0 : L_tmp = L_shl( L_tmp, sub( i, ( 31 - 16 ) ) ); /* Q16 */
287 :
288 : /* *past_gcode = L_tmp * pred_nrg_frame; */
289 0 : i = norm_l( L_tmp );
290 0 : L_tmp1 = L_shl( L_tmp, i );
291 0 : exp_L_tmp1 = sub( 15, i );
292 :
293 0 : i = norm_l( pred_nrg_frame );
294 0 : L_tmp1 = Mpy_32_32( L_tmp1, L_shl( pred_nrg_frame, i ) );
295 0 : exp_L_tmp1 = add( exp_L_tmp1, sub( 15, i ) );
296 :
297 0 : *past_gcode = L_shl( L_tmp1, sub( exp_L_tmp1, 15 ) ); /* Q16 */
298 0 : move32();
299 :
300 0 : *gain_code = L_shl_sat( Mpy_32_16_1( *past_gcode, *gain_inov ), 3 );
301 0 : move32();
302 :
303 :
304 0 : L_tmp = Mpy_32_16_1( *gain_code, BASOP_Util_Divide1616_Scale( g_code2, g_code, &s ) );
305 0 : L_tmp = L_shl( L_tmp, sub( sub( add( s, exp_gcode2 ), exp_gcode ), 2 ) ); /* Q16 */
306 0 : L_tmp1 = L_add( L_tmp, 0 );
307 0 : FOR( i = 0; i < index2; i++ )
308 : {
309 0 : L_tmp1 = L_add( L_tmp1, L_tmp );
310 : }
311 0 : *gain_code2 = L_tmp1;
312 0 : move32();
313 :
314 :
315 0 : return;
316 : }
317 :
318 : /*********************
319 : * public functions *
320 : *********************/
321 :
322 3050 : void decode_acelp_gains_fx(
323 : Word16 *code, /* i : algebraic code excitation Q9 */
324 : Word16 gains_mode,
325 : Word16 mean_ener_code, /* i : mean_ener defined in open-loop Q8 */
326 : Word16 *gain_pit, /* o : Quantized pitch gain 1Q14 */
327 : Word32 *gain_code, /* o : Quantized codebook gain Q16 */
328 : Word16 **pt_indice,
329 : Word16 *past_gpit, /* i/o: past gain of pitch 1Q14 */
330 : Word32 *past_gcode, /* i/o: past energy of code Q16 */
331 : Word16 *gain_inov, /* o : unscaled innovation gain 3Q12 */
332 : Word16 L_subfr, /* i : Subframe size Q0 */
333 : Word16 *code2, /* i : algebraic code excitation Q9 */
334 : Word32 *gain_code2 /* o : Quantized codebook gain Q16 */
335 : )
336 : {
337 3050 : Word16 index = 0;
338 3050 : move16();
339 :
340 3050 : index = **pt_indice;
341 3050 : ( *pt_indice )++;
342 :
343 3050 : IF( s_and( gains_mode > 0, (Word16) LT_16( gains_mode, 4 ) ) )
344 : {
345 : /* ACELP gains quantizer (5bits/subfr) */
346 3050 : Mode2_gain_dec_mless_fx( index, code, L_subfr, gain_pit, gain_code, mean_ener_code, past_gpit, past_gcode, gain_inov, gains_mode - 1 );
347 : }
348 0 : ELSE IF( s_or( (Word16) EQ_16( gains_mode, 4 ), (Word16) EQ_16( gains_mode, 5 ) ) )
349 : {
350 : /* AMR-WB gains quantizer (6bits/subfr (mode 2) or 7bits/subfr (mode 3)) */
351 0 : assert( 0 );
352 : }
353 0 : ELSE IF( EQ_16( gains_mode, 6 ) )
354 : {
355 : /* UV gains quantizer (6bits/subfr) */
356 0 : gain_dec_uv_fx( index, code, L_subfr, gain_pit, gain_code, past_gpit, past_gcode, gain_inov );
357 : }
358 0 : ELSE IF( EQ_16( gains_mode, 7 ) )
359 : {
360 : /* GACELP_UV gains quantizer (7=5-2bits/subfr) */
361 0 : gain_dec_gacelp_uv_fx( index, code, code2, mean_ener_code, L_subfr, gain_pit, gain_code, gain_code2, past_gpit, past_gcode, gain_inov );
362 : }
363 : ELSE
364 : {
365 0 : IVAS_ERROR( IVAS_ERR_INTERNAL, "invalid gains coding for acelp!" );
366 : }
367 3050 : }
368 :
369 :
370 : /*---------------------------------------------------------------------*
371 : * d_gain_pred_fx :
372 : *
373 : * decode the predicted value for the scaled
374 : * innovation energy in all subframes
375 : *---------------------------------------------------------------------*/
376 610 : void d_gain_pred_fx(
377 : Word16 nrg_mode, /* i : NRG moe */
378 : Word16 *Es_pred, /* o : predicted scaled innovation energy Q8 */
379 : Word16 **pt_indice /* i/o: pointer to the buffer of indices */
380 : )
381 : {
382 : Word16 indice;
383 :
384 610 : indice = ( Word16 ) * *pt_indice;
385 610 : ( *pt_indice )++;
386 :
387 610 : *Es_pred = 0;
388 610 : move16();
389 :
390 610 : if ( EQ_16( nrg_mode, 1 ) )
391 : {
392 610 : *Es_pred = Es_pred_qua[indice];
393 610 : move16();
394 : }
395 :
396 610 : if ( EQ_16( nrg_mode, 2 ) )
397 : {
398 0 : *Es_pred = Es_pred_qua_2[indice];
399 0 : move16();
400 : }
401 :
402 610 : IF( GT_16( nrg_mode, 2 ) )
403 : {
404 0 : *Es_pred = extract_l( L_mac( -335544320l /* -20.f Q24*/, indice, 224 /* 1.75f Q7*/ ) ); /*(Q8 - ((Q0*Q7)=Q8))*/
405 0 : move16();
406 : }
407 :
408 610 : return;
409 : }
|