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 "cnst.h" /* Common constants */
8 : #include "rom_com.h" /* Static table prototypes */
9 : #include "rom_enc.h" /* Static table prototypes */
10 : #include "prot_fx.h" /* Function prototypes */
11 : #include "prot_fx_enc.h" /* Function prototypes */
12 :
13 :
14 : /*-------------------------------------------------------------------*
15 : * Local constants
16 : *-------------------------------------------------------------------*/
17 :
18 : #define NMAX 8 /* Control of the routine's complexity */
19 : /* #define FAC_DELTA 16.0f */
20 : #define SFAC_DELTA 11
21 :
22 :
23 : /*-------------------------------------------------------------------*
24 : * Local functions
25 : *-------------------------------------------------------------------*/
26 :
27 : static Word16 cod_2pos_fx( const Word16 ind1, const Word16 ind2, const Word16 sign1, const Word16 sign2, const Word16 n );
28 :
29 : static void gauss2v_fx( BSTR_ENC_HANDLE hBstr, const Word16 h[], const Word16 xn[], const Word16 dn[], Word16 code[], Word16 y1[], Word32 *gain, const Word16 lg, const Word16 shift, const Word16 Q_new, const Word16 nb_bits );
30 :
31 :
32 : /*-------------------------------------------------------------------*
33 : * Gaus_encode
34 : *
35 : * Encoder UnVoiced excitation coding using Gaussian codebooks
36 : * - ACELP quantized Gaussian excitation
37 : * - gain quantization
38 : * - Total excitation for UnVoiced coders
39 : * - Updates
40 : *-------------------------------------------------------------------*/
41 0 : Word16 gaus_encode_fx(
42 : Encoder_State *st_fx, /* i/o: encoder state structure */
43 : const Word16 i_subfr, /* i : subframe index Q0*/
44 : const Word16 *h1, /* i : weighted filter input response Q14*/
45 : const Word16 *xn, /* i : target vector Q12*/
46 : Word16 *exc, /* o : pointer to excitation signal frame Q_new*/
47 : Word16 *mem_w0, /* o : weighting filter denominator memory Q_new*/
48 : Word16 *clip_gain, /* o : memory of gain of pitch clipping algorithm [2.56x,Q14,Q8,Q0,Q14,Q14]*/
49 : Word16 *tilt_code, /* o : synthesis excitation spectrum tilt Q15*/
50 : Word16 *code, /* o : algebraic excitation Q9*/
51 : Word32 *gain_code, /* o : Code gain. Q16*/
52 : Word16 *y2, /* o : zero-memory filtered adaptive excitation Q9*/
53 : Word16 *gain_inov, /* o : innovation gain Q12*/
54 : Word16 *voice_fac, /* o : voicing factor Q15*/
55 : Word16 *gain_pit, /* o : adaptive excitation gain Q14*/
56 : const Word16 Q_new, /* i : scaling factor */
57 : const Word16 shift, /* i : scaling factor */
58 : Word32 *norm_gain_code /* o : normalized innovative cb. gain Q16*/
59 : )
60 : {
61 : Word16 nb_bits, idx;
62 0 : Word16 i = 0;
63 : Word32 Ltmp;
64 : Word16 dn[L_SUBFR], exp_code, gcode; /* Correlation between xn and h1 */
65 : Word16 exp, tmp, tmp_idx;
66 :
67 : /*----------------------------------------------------------------*
68 : * Encode gaussian excitation
69 : *----------------------------------------------------------------*/
70 :
71 : /* Correlation between target xn2[] and impulse response h1[] */
72 0 : corr_xh_fx( xn, dn, h1 );
73 :
74 0 : tmp_idx = shr( i_subfr, 6 );
75 0 : nb_bits = st_fx->acelp_cfg.fixed_cdk_index[tmp_idx]; /* Q0 */
76 0 : move16();
77 :
78 0 : gauss2v_fx( st_fx->hBstr, h1, xn, dn, code, y2, gain_code, L_SUBFR, shift, Q_new, shr( nb_bits, 1 ) );
79 :
80 : /*----------------------------------------------------------------*
81 : * Encode gaussian gain
82 : *----------------------------------------------------------------*/
83 :
84 : /* codeword energy computation */
85 0 : Ltmp = Dot_product12( code, code, L_SUBFR, &exp_code );
86 :
87 0 : exp_code = sub( exp_code, 18 + 6 ); /* exp: -18 (code in Q9), -6 (L_subfr = 64) */
88 0 : Ltmp = Isqrt_lc( Ltmp, &exp_code );
89 0 : *gain_inov = extract_h( L_shl_sat( Ltmp, sub( exp_code, 3 ) ) ); /* g_code_inov in Q12 */
90 :
91 0 : nb_bits = st_fx->acelp_cfg.gains_mode[tmp_idx]; /* Q0 */
92 0 : move16();
93 : /* low bound = -30; stepSize = 1.71875; inv_stepSize = 0.5818181 */
94 0 : idx = gain_enc_gaus_fx( gain_code, nb_bits, -7680, 28160, 19065 ); /* Q0 */
95 0 : push_indice( st_fx->hBstr, IND_GAIN, idx, nb_bits );
96 :
97 : /*----------------------------------------------------------------*
98 : * Total excitation for Unvoiced coders
99 : *----------------------------------------------------------------*/
100 :
101 0 : gcode = round_fx_sat( L_shl_sat( *gain_code, Q_new ) ); /* scaled gain_code with Qnew */
102 :
103 0 : FOR( i = 0; i < L_SUBFR; i++ )
104 : {
105 0 : exc[i + i_subfr] = round_fx( L_shl( L_mult( gcode, code[i] ), 15 - 9 ) ); /* Q_new */
106 : }
107 :
108 : /*----------------------------------------------------------------*
109 : * Updates: last value of new target is stored in mem_w0
110 : *----------------------------------------------------------------*/
111 :
112 0 : Ltmp = L_mult( gcode, y2[L_SUBFR - 1] ); /* Q_new + 10 */
113 0 : Ltmp = L_shl( Ltmp, add( 5, shift ) ); /* Q_new + 15 + shift */
114 0 : Ltmp = L_negate( Ltmp );
115 0 : Ltmp = L_mac( Ltmp, xn[L_SUBFR - 1], 16384 ); /* Q_new + 15 + shift */
116 0 : Ltmp = L_shl_sat( Ltmp, sub( 1, shift ) ); /* Q_new + 16 */
117 0 : *mem_w0 = round_fx_sat( Ltmp ); /* Q_new */
118 0 : move16();
119 0 : init_gp_clip_fx( clip_gain ); /* reset pitch clipping parameters */
120 :
121 0 : *gain_pit = 0;
122 0 : *tilt_code = 0;
123 0 : move16(); /* purely unvoiced */
124 0 : *voice_fac = -32768; /* -1 in Q31 */
125 0 : move16(); /* purely unvoiced */
126 0 : exp = sub( norm_s( *gain_inov ), 1 );
127 0 : exp = s_max( exp, 0 );
128 :
129 0 : tmp = div_s( shr( 8192, exp ), *gain_inov );
130 0 : *norm_gain_code = L_shr( Mult_32_16( *gain_code, tmp ), sub( 1, exp ) ); /* Q16 */
131 0 : move16();
132 :
133 0 : return ( L_SUBFR << 6 );
134 : }
135 : /*-------------------------------------------------------------------*
136 : * gauss2v()
137 : *
138 : * encoder of Gaussian Codebook for unvoiced
139 : * consisting of addition of 2 Gaussian vectors
140 : *
141 : * One Gaussian vector of 192 values vectors delayed by 2
142 : *-------------------------------------------------------------------*/
143 0 : void gauss2v_fx(
144 : BSTR_ENC_HANDLE hBstr, /* i/o: encoder state structure */
145 : const Word16 h[], /* i : weighted LP filter impulse response Q15 */
146 : const Word16 xn[], /* i : target signal Q12 */
147 : const Word16 dn[], /* i : backward filtered target Q12 */
148 : Word16 code[], /* o : gaussian excitation Q9 */
149 : Word16 y1[], /* o : zero-memory filtered gauss. excitation Q8 */
150 : Word32 *gain, /* o : excitation gain. 32-bit number in Q16 */
151 : const Word16 lg, /* i : subframe size Q0 */
152 : const Word16 shift, /* i : Scaling factor Q0 */
153 : const Word16 Q_new, /* i : Scaling factor Q0 */
154 : const Word16 nb_bits /* i : nb ob bits per track (max 6) Q0 */
155 : )
156 : {
157 : Word16 i, j, ind1, ind2;
158 : Word16 nvec, step;
159 : Word32 cor, cora, dotprod;
160 : Word16 enerw;
161 : Word32 eneri, cor2;
162 : Word32 enerw32, cor2w32;
163 : Word16 *cpt1;
164 : Word16 *pt1, *pt2;
165 : Word32 max_val[NMAX + 1];
166 : Word16 *pos[NMAX + 1];
167 : Word32 sign[NMAX + 1];
168 : Word32 ener[NMAX + 1], corr[NMAX + 1], ener1;
169 : Word16 dico2[L_SUBFR * NMAX];
170 : Word16 exp_num;
171 : Word16 exp_den;
172 : Word16 Num;
173 : Word16 Den;
174 : Word32 GainPortion1;
175 : Word32 GainPortion2;
176 : Word32 cor_abs;
177 : Word16 cor_neg;
178 : Word16 div_result;
179 : Word32 ener_sqrt;
180 : Word32 Portion;
181 : Word16 sign1, sign2;
182 : Word16 enerw_norm, enerw_mantissa;
183 : Word16 cor2w_norm, cor2w_mantissa;
184 : Word16 eneri_norm, eneri_mantissa;
185 : Word16 cor2_norm, cor2_mantissa;
186 : Word16 difference_norm;
187 : Word32 cor32; /* 32-bit intermediate value*/
188 : Word16 hi1, lo1;
189 : Word16 update_best;
190 : Word16 idx;
191 : Word32 Lc0, Lc1, Lnum, Lden;
192 : Word16 gxx, gcc, index_delta, delta, m_sign, inv_delta;
193 : Word16 hg[190], Gaus_dico2[190];
194 : Word16 shiftP3;
195 :
196 : /*----------------------------------------------------------------*
197 : * Encode the tilt of gaussian excitation
198 : *----------------------------------------------------------------*/
199 :
200 : /* Compute spectral tilt of target */
201 0 : Lc0 = L_mult( xn[1], xn[1] ); /* Q25 */
202 0 : Lc1 = L_mult( xn[1], xn[0] ); /* Q25 */
203 0 : FOR( i = 2; i < L_SUBFR; i++ )
204 : {
205 : /* fc0 += xn[i]*xn[i] */
206 : /* fc1 += xn[i]*xn[i-1] */
207 0 : Lc0 = L_mac_sat( Lc0, xn[i], xn[i] ); /* Q25 */
208 0 : Lc1 = L_mac_sat( Lc1, xn[i], xn[i - 1] ); /* Q25 */
209 : }
210 : /* fgxx = fc1/fc0 */
211 0 : exp_num = sub( norm_l( Lc1 ), 1 );
212 0 : Num = extract_h( L_shl( Lc1, exp_num ) );
213 0 : m_sign = s_or( shr( Num, 16 ), 1 ); /* Remove sign */
214 0 : Num = abs_s( Num );
215 0 : Lc0 = L_max( Lc0, 1 );
216 0 : exp_den = norm_l( Lc0 );
217 0 : Den = extract_h( L_shl( Lc0, exp_den ) ); /* Q9 + exp_den */
218 0 : gxx = shr( div_s( Num, Den ), sub( exp_num, sub( exp_den, 2 ) ) ); /* Q13 */
219 0 : gxx = i_mult2( gxx, m_sign ); /* Apply sign */
220 :
221 0 : set16_fx( hg, 0, 190 ); /* Compute spectral tilt of filtered codebook */
222 0 : Copy( h, hg, L_SUBFR ); // Q15
223 0 : conv_fx( gaus_dico_fx, hg, Gaus_dico2, 190 ); // Q12
224 :
225 0 : Lc0 = L_mult( Gaus_dico2[1], Gaus_dico2[1] ); /* Q25 */
226 0 : Lc1 = L_mult( Gaus_dico2[1], Gaus_dico2[0] ); /* Q25 */
227 0 : FOR( i = 2; i < 190; i++ )
228 : {
229 : /* fc0 += fgaus_dico2[i]*fgaus_dico2[i] */
230 : /* fc1 += fgaus_dico2[i]*fgaus_dico2[i-1] */
231 0 : Lc0 = L_mac( Lc0, Gaus_dico2[i], Gaus_dico2[i] ); /* Q25 */
232 0 : Lc1 = L_mac( Lc1, Gaus_dico2[i], Gaus_dico2[i - 1] ); /* Q25 */
233 : }
234 :
235 : /* fgcc = fc1/fc0 */
236 :
237 0 : exp_num = sub( norm_l( Lc1 ), 1 );
238 0 : Num = extract_h( L_shl( Lc1, exp_num ) );
239 0 : m_sign = s_or( shr( Num, 16 ), 1 ); /* Remove sign */
240 0 : Num = abs_s( Num );
241 :
242 0 : Lc0 = L_max( Lc0, 1 );
243 0 : exp_den = norm_l( Lc0 );
244 0 : Den = extract_h( L_shl( Lc0, exp_den ) );
245 0 : gcc = shr( div_s( Num, Den ), sub( exp_num, sub( exp_den, 2 ) ) ); /* Q13 */
246 0 : gcc = i_mult2( gcc, m_sign ); /* Apply sign */
247 :
248 : /* fdelta = (1-fgcc*fgxx) / (2*fgcc+fgxx) Compute and quantize spectral tilt modification factor */
249 0 : Lnum = L_sub( 134217728L, L_mult( gcc, gxx ) ); /* Q30 */
250 0 : Lden = L_mac( L_mult( gxx, 8192 ), gcc, 16384 ); /* Q30 */
251 :
252 0 : exp_num = sub( norm_l( Lnum ), 1 );
253 0 : Num = extract_h( L_shl( Lnum, exp_num ) ); /* Q14 + exp_den */
254 0 : m_sign = s_or( shr( Num, 16 ), 1 ); /* Remove sign */
255 0 : Num = abs_s( Num );
256 :
257 0 : Lden = L_max( Lden, 1 );
258 0 : exp_den = norm_l( Lden );
259 0 : Den = extract_h( L_shl( Lden, exp_den ) );
260 :
261 0 : delta = shr_sat( div_s( Num, Den ), sub( exp_num, exp_den ) ); /* Q15 */
262 0 : delta = i_mult2( delta, m_sign ); /* Apply sign Q0*/
263 : /* index_delta = (short)(FAC_DELTA * fdelta) */
264 0 : index_delta = shr( delta, SFAC_DELTA );
265 :
266 : /* index_delta [0,7] */
267 0 : index_delta = s_max( index_delta, 0 );
268 0 : index_delta = s_min( index_delta, 7 );
269 :
270 : /* fdelta = STEP_DELTA * (float)index_delta */
271 0 : delta = shl( index_delta, 11 ); /* delta in Q15 */
272 :
273 0 : IF( delta > 0 ) /* Adapt spectral tilt of initial codebook */
274 : {
275 : /* Computation of 1 / (1+fdelta*fdelta) */
276 0 : inv_delta = inv_delta_tab[sub( index_delta, 1 )];
277 0 : move16(); /* Q15 */
278 :
279 : /* fgaus_dico2[0] = gaus_dico[0] */
280 0 : Gaus_dico2[0] = gaus_dico_fx[0]; /* Q12 */
281 0 : move16();
282 0 : FOR( i = 1; i < 190; i++ )
283 : {
284 : /* fgaus_dico2[i] = (gaus_dico[i] - fdelta*gaus_dico[i-1]) / (1 + fdelta*fdelta) */
285 0 : Lnum = L_msu( L_deposit_h( gaus_dico_fx[i] ), delta, gaus_dico_fx[i - 1] );
286 0 : Gaus_dico2[i] = round_fx( Mpy_32_16_1( Lnum, inv_delta ) );
287 : }
288 : }
289 : ELSE
290 : {
291 0 : FOR( i = 0; i < 190; i++ )
292 : {
293 : /* fgaus_dico2[i] = gaus_dico[i] */
294 0 : Gaus_dico2[i] = gaus_dico_fx[i]; /* Q12 */
295 0 : move16();
296 : }
297 : }
298 :
299 : /*----------------------------------------------------------------*
300 : * Initializations
301 : *----------------------------------------------------------------*/
302 :
303 0 : ind1 = 0;
304 0 : move16();
305 0 : ind2 = 0;
306 0 : move16();
307 :
308 0 : nvec = shl( 1, nb_bits );
309 0 : step = shr( 0x80, nb_bits );
310 :
311 : /*----------------------------------------------------------------*
312 : * dot product between dn and gaussian codevectors,
313 : * keep NMAX best vectors
314 : *----------------------------------------------------------------*/
315 :
316 0 : set32_fx( max_val, 0, NMAX + 1 );
317 0 : set32_fx( sign, 0, NMAX + 1 );
318 :
319 0 : FOR( i = 0; i < NMAX + 1; i++ )
320 : {
321 0 : pos[i] = (Word16 *) Gaus_dico2;
322 : }
323 :
324 0 : cpt1 = Gaus_dico2;
325 0 : move16();
326 :
327 0 : FOR( i = 0; i < nvec; i++ )
328 : {
329 : /* Dot product without normalization, because values are compared with each other afterwards. */
330 0 : cor = Dot_product( cpt1, dn, lg ); /* Q12 * Q12 * length of 64 + 1 left shift ==> Q31*/
331 0 : cora = L_abs( cor );
332 0 : j = NMAX - 1;
333 0 : move16();
334 :
335 : DO
336 : {
337 0 : IF( GE_32( cora, max_val[j] ) )
338 : {
339 0 : max_val[j + 1] = max_val[j];
340 0 : move32(); /*Q31*/
341 0 : pos[j + 1] = pos[j];
342 0 : move16(); /*Pointer*/
343 0 : sign[j + 1] = sign[j];
344 0 : move32(); /*Q31*/
345 0 : max_val[j] = cora;
346 0 : move32(); /*Q31*/
347 0 : pos[j] = cpt1;
348 0 : move16(); /*Pointer*/
349 0 : sign[j] = cor;
350 0 : move32(); /*Q31*/
351 : }
352 0 : j--;
353 : }
354 0 : WHILE( j >= 0 );
355 0 : cpt1 += step;
356 : }
357 :
358 : /*----------------------------------------------------------------*
359 : * filter selected vectors
360 : * put sign
361 : * compute energy
362 : *----------------------------------------------------------------*/
363 :
364 0 : pt1 = dico2;
365 0 : move16();
366 0 : FOR( i = 0; i < NMAX; i++ )
367 : {
368 : /* Input vector (pos) Q12, filter coefs in Q15, result in same format as input vector (Q12) */
369 0 : conv_fx( pos[i], h, pt1, lg );
370 :
371 : /* put sign and compute energy */
372 0 : IF( sign[i] < 0 )
373 : {
374 0 : FOR( j = 0; j < lg; j++ )
375 : {
376 0 : pt1[j] = negate( pt1[j] );
377 0 : move16(); /*Store into dico2*/
378 : }
379 : }
380 0 : ener[i] = Dot_product( pt1, pt1, lg ); /* pt1 points to filtered vector in dico2, in Q12 */
381 0 : move32(); /* Result is for Q12 * Q12 with length of 64 (6 bits) + 1 left shift => Q31 */
382 0 : corr[i] = Dot_product( pt1, xn, lg ); /* must be equal to sign[i] !! */
383 0 : move32(); /* pt1 points into dico2, in Q12. xn is in Q12 */
384 : /* Result is for Q12 * Q12 with length of 64 (6 bits) + 1 left shift => Q31 */
385 0 : pt1 += L_SUBFR;
386 : }
387 :
388 : /*------------------------------------------------------------------------*
389 : * try all combinations of NMAX best vectors
390 : *------------------------------------------------------------------------*/
391 :
392 0 : pt1 = dico2;
393 0 : move16();
394 :
395 : /* Initial values for search algorithm */
396 0 : enerw32 = L_deposit_h( 0x80 );
397 0 : cor2w32 = L_deposit_l( -2 );
398 0 : enerw_norm = norm_l( enerw32 );
399 0 : cor2w_norm = norm_l( cor2w32 );
400 0 : cor2w_mantissa = round_fx( L_shl( cor2w32, cor2w_norm ) );
401 0 : enerw_mantissa = round_fx( L_shl( enerw32, enerw_norm ) );
402 :
403 0 : FOR( i = 0; i < NMAX; i++ )
404 : {
405 0 : pt2 = pt1;
406 0 : move16();
407 0 : FOR( j = i; j < NMAX; j++ )
408 : {
409 0 : cor32 = L_add( corr[i], corr[j] ); /* Q31 */
410 :
411 0 : dotprod = Dot_product( pt1, pt2, lg ); /* Q12 * Q12 * length of 64 + 1 left shift ==> Q31 */
412 :
413 : /* eneri = round_fx(ener[i]) + round_fx(ener[j]) + 2*round_fx(dotprod) */
414 : /* Use ScalingShift to stay aligned with ener[] */
415 0 : eneri = L_shl( dotprod, 1 ); /* One left shift added for factor of 2 */
416 0 : eneri = L_add( ener[i], eneri );
417 0 : eneri = L_add( ener[j], eneri ); /* Q31 */
418 :
419 0 : lo1 = L_Extract_lc( cor32, &hi1 );
420 0 : cor2 = Sad_32( 0, hi1, lo1 ); /* Square + Add */
421 :
422 0 : cor2_norm = norm_l( cor2 );
423 0 : eneri_norm = norm_l( eneri );
424 0 : cor2_mantissa = round_fx_sat( L_shl_sat( cor2, cor2_norm ) );
425 0 : eneri_mantissa = round_fx_sat( L_shl_sat( eneri, eneri_norm ) );
426 0 : difference_norm = sub( add( cor2_norm, enerw_norm ), add( cor2w_norm, eneri_norm ) );
427 :
428 0 : update_best = 0;
429 0 : move16();
430 :
431 0 : IF( difference_norm > 0 )
432 : {
433 0 : if ( GT_32( L_shr( L_mult( cor2_mantissa, enerw_mantissa ), difference_norm ),
434 : L_mult( cor2w_mantissa, eneri_mantissa ) ) )
435 : {
436 0 : update_best = 1;
437 0 : move16();
438 : }
439 : }
440 : ELSE
441 : {
442 0 : if ( L_msu_sat( L_shl( L_mult( cor2w_mantissa, eneri_mantissa ), difference_norm ), cor2_mantissa, enerw_mantissa ) < 0 ) // Saturation to be revisited
443 : {
444 0 : update_best = 1;
445 0 : move16();
446 : }
447 : }
448 0 : IF( update_best != 0 )
449 : {
450 0 : cor2w_mantissa = cor2_mantissa;
451 0 : move16();
452 0 : cor2w_norm = cor2_norm;
453 0 : move16();
454 0 : enerw_mantissa = eneri_mantissa;
455 0 : move16();
456 0 : enerw_norm = eneri_norm;
457 0 : move16();
458 0 : ind1 = i;
459 0 : move16();
460 0 : ind2 = j;
461 0 : move16();
462 : }
463 0 : pt2 += L_SUBFR;
464 : }
465 0 : pt1 += L_SUBFR;
466 : }
467 :
468 0 : enerw = round_fx( L_shr( L_deposit_h( enerw_mantissa ), enerw_norm ) );
469 :
470 : /*----------------------------------------------------------------*
471 : * Compute zero-memory filtered gauss. excitation y
472 : *----------------------------------------------------------------*/
473 :
474 0 : pt1 = dico2 + ind1 * L_SUBFR;
475 0 : move16(); /*Pointer arithmetic*/
476 0 : pt2 = dico2 + ind2 * L_SUBFR;
477 0 : move16();
478 :
479 0 : shiftP3 = add( shift, 3 );
480 0 : FOR( i = 0; i < lg; i++ )
481 : {
482 : /* Sum of 2 Q12 values, must give a Q1.8 */
483 0 : y1[i] = shr( add( pt1[i], pt2[i] ), shiftP3 );
484 0 : move16(); /* Compensate for "shift" */
485 : }
486 :
487 : /*----------------------------------------------------------------*
488 : * signs of vectors
489 : *----------------------------------------------------------------*/
490 :
491 0 : sign1 = ( -32768 );
492 0 : move16();
493 0 : if ( sign[ind1] >= 0 )
494 : {
495 0 : sign1 = 32767;
496 0 : move16();
497 : }
498 :
499 0 : sign2 = ( -32768 );
500 0 : move16();
501 0 : if ( sign[ind2] >= 0 )
502 : {
503 0 : sign2 = 32767;
504 0 : move16();
505 : }
506 :
507 : /*----------------------------------------------------------------*
508 : * Compute code
509 : *----------------------------------------------------------------*/
510 :
511 0 : pt1 = pos[ind1];
512 0 : move16(); /* Points to gaussian vector (gaus_dico_fx) in Q12 */
513 0 : pt2 = pos[ind2];
514 0 : move16(); /* Points to gaussian vector (gaus_dico_fx) in Q12 */
515 :
516 : /* sign[ind1] and sign[ind2] */
517 0 : FOR( i = 0; i < lg; i++ )
518 : {
519 : /* code[i]=(pt1[i]*sign1 + pt2[i]*sign2) /8 */
520 : /* Division by 8 (shift by 3) is for scaling (Q12 to Q0.9 output) */
521 0 : code[i] = shr( add( mult( pt1[i], sign1 ), mult( pt2[i], sign2 ) ), 3 );
522 0 : move16();
523 : }
524 :
525 0 : cor = L_add( corr[ind1], corr[ind2] );
526 :
527 : /*----------------------------------------------------------------*
528 : * Compute index
529 : *----------------------------------------------------------------*/
530 :
531 0 : i = (Word16) ( ( pos[ind1] - Gaus_dico2 ) / step ); /* Division by step can be replaced by shift. Pointer arithmetic */
532 0 : j = (Word16) ( ( pos[ind2] - Gaus_dico2 ) / step ); /* Division by step can be replaced by shift. Pointer arithmetic */
533 :
534 0 : idx = cod_2pos_fx( i, j, sign1, sign2, nvec ); /* Q0 */
535 0 : move16();
536 :
537 0 : push_indice( hBstr, IND_GAUS_CDBK_INDEX, idx, 2 * nb_bits + 1 );
538 0 : push_indice( hBstr, IND_TILT_FACTOR, index_delta, 3 );
539 :
540 : /*----------------------------------------------------------------*
541 : * Find quantized gain
542 : *----------------------------------------------------------------*/
543 :
544 : /* Divide cor/enerw: intermediate result stored into GainPortion1 */
545 0 : cor_neg = 0;
546 0 : move16();
547 0 : if ( cor < 0 ) /* Make Num positive. */
548 : {
549 0 : cor_neg = 1;
550 0 : move16();
551 : }
552 0 : cor_abs = L_abs( cor );
553 :
554 0 : exp_num = sub( norm_l( cor_abs ), 1 );
555 0 : exp_den = norm_s( enerw );
556 0 : Num = round_fx( L_shl( cor_abs, exp_num ) );
557 0 : Den = shl( enerw, exp_den );
558 :
559 0 : GainPortion1 = L_deposit_l( 0 ); /* Unexpected division by zero. Eliminate this gain contribution */
560 0 : IF( Den != 0 ) /* Protection against division by zero */
561 : {
562 0 : div_result = div_s( Num, Den ); /* Q15 */
563 0 : IF( cor_neg != 0 )
564 : {
565 0 : div_result = negate( div_result ); /* Retrieve sign */
566 : }
567 : /* Re-scale to compensate for normalization*/
568 0 : GainPortion1 = L_shr( L_deposit_l( div_result ), sub( exp_num, exp_den ) );
569 : }
570 :
571 0 : ener1 = Dot_product( xn, xn, lg ); /* Q12 * Q12 * length of 64 + 1 left shift ==> Q31 */
572 :
573 0 : exp_num = sub( norm_s( enerw ), 1 );
574 0 : exp_den = norm_l( ener1 );
575 0 : Num = shl( enerw, exp_num );
576 0 : Den = round_fx_sat( L_shl_sat( ener1, exp_den ) );
577 0 : GainPortion2 = L_deposit_l( 0 ); /* Unexpected division by zero. Eliminate this gain contribution */
578 0 : IF( Den != 0 ) /* Protection against division by zero */
579 : {
580 0 : div_result = div_s( Num, Den ); /* Q15 */
581 :
582 : /* Re-scale to compensate for normalization*/
583 0 : GainPortion2 = L_shr_sat( L_deposit_l( div_result ), sub( exp_num, exp_den ) );
584 : }
585 :
586 0 : ener_sqrt = Isqrt( L_shl_sat( GainPortion2, 1 ) ); /* Make value a Q16 prior to division (align on power of 4) */
587 0 : ener_sqrt = L_shr( ener_sqrt, 8 ); /* Left-shift Q23 result to make a Q15 result */
588 :
589 0 : Portion = Mult_32_16( GainPortion1, 19661 ); /* Performs GainPortion1*.6 */
590 0 : Portion = Madd_32_16( Portion, ener_sqrt, 13107 ); /* Performs ener_sqrt*.4 */
591 :
592 : /* Gain must be output in a 32-bit variable as a Q16 */
593 : /* Compensate for Q_new */
594 0 : *gain = L_shl_sat( Portion, sub( 13, Q_new ) ); /* Q16 */
595 0 : move32();
596 :
597 0 : return;
598 : }
599 :
600 :
601 : /*---------------------------------------------------------------------*
602 : * Put selected codevector positions and signs into quantization index
603 : *---------------------------------------------------------------------*/
604 0 : static Word16 cod_2pos_fx( /* o : codebook quantization index */
605 : const Word16 ind1, /* i : index of 1st gaussian vector Q0*/
606 : const Word16 ind2, /* i : index of 2nd gaussian vector Q0*/
607 : const Word16 sign1, /* i : sign of 1st gaussian vector Qx*/
608 : const Word16 sign2, /* i : sign of 2nd gaussian vector Qx*/
609 : const Word16 n /* i : nb. of codebook vectors Q0*/
610 : )
611 : {
612 : Word16 i1, i2, index, s1, s2;
613 0 : s1 = 1;
614 0 : move16();
615 :
616 0 : if ( sign1 > 0 )
617 : {
618 0 : s1 = 0;
619 0 : move16();
620 : }
621 0 : s2 = 1;
622 0 : move16();
623 0 : if ( sign2 > 0 )
624 : {
625 0 : s2 = 0;
626 0 : move16();
627 : }
628 :
629 0 : IF( EQ_16( s1, s2 ) )
630 : {
631 0 : IF( LE_16( ind1, ind2 ) )
632 : {
633 0 : i1 = ind1; /* Q0 */
634 0 : move16();
635 0 : i2 = ind2; /* Q0 */
636 0 : move16();
637 : }
638 : ELSE
639 : {
640 0 : i1 = ind2; /* Q0 */
641 0 : move16();
642 0 : i2 = ind1; /* Q0 */
643 0 : move16();
644 : }
645 : }
646 : ELSE
647 : {
648 0 : IF( GT_16( ind1, ind2 ) )
649 : {
650 0 : i1 = ind1; /* Q0 */
651 0 : move16();
652 0 : i2 = ind2; /* Q0 */
653 0 : move16();
654 : }
655 : ELSE
656 : {
657 0 : i1 = ind2; /* Q0 */
658 0 : move16();
659 0 : i2 = ind1; /* Q0 */
660 0 : move16();
661 0 : s1 = s2;
662 0 : move16();
663 : }
664 : }
665 :
666 0 : index = extract_l( L_mult( i1, n ) );
667 0 : index = add( index, shl( i2, 1 ) );
668 0 : index = add( index, s1 );
669 :
670 0 : return index;
671 : }
|