Line data Source code
1 : /*====================================================================================
2 : EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
3 : ====================================================================================*/
4 : #include <stdint.h>
5 : #include "options.h" /* Compilation switches */
6 : #include "cnst.h" /* Common constants */
7 : #include "prot_fx.h" /* Function prototypes */
8 : #include "rom_com_fx.h" /* Static table prototypes */
9 : #include "rom_com.h" /* Static table prototypes */
10 : #include "prot_fx_enc.h"
11 :
12 : /*---------------------------------------------------------------------*
13 : * Local function prototype
14 : *---------------------------------------------------------------------*/
15 : static void find_cn_fx( const Word16 xn[], const Word16 Ap[], const Word16 *p_Aq, Word16 cn[] );
16 :
17 : /*-----------------------------------------------------------------*
18 : * Transform domain contribution encoding
19 : *-----------------------------------------------------------------*/
20 : #define Q_MINUS 4
21 3370 : void transf_cdbk_enc_fx(
22 : Encoder_State *st_fx, /* i/o: encoder state structure */
23 : const Word16 harm_flag_acelp, /* i : harmonic flag for higher rates ACELP Q0*/
24 : const Word16 i_subfr, /* i : subframe index Q0*/
25 : Word16 cn[], /* i/o: target vector in residual domain Q_new*/
26 : Word16 exc[], /* i/o: pointer to excitation signal frame Q_new*/
27 : const Word16 *p_Aq, /* i : 12k8 Lp coefficient Q12*/
28 : const Word16 Ap[], /* i : weighted LP filter coefficients Q12*/
29 : const Word16 h1[], /* i : weighted filter input response Q15*/
30 : Word16 xn[], /* i/o: target vector Q_new + shift -1*/
31 : Word16 xn2[], /* i/o: target vector for innovation search Q_new + shift -1*/
32 : Word16 y1[], /* i/o: zero-memory filtered adaptive excitation Q_new + shift -1*/
33 : const Word16 y2[], /* i : zero-memory filtered innovative excitation Q9*/
34 : const Word16 Es_pred, /* i : predicited scaled innovation energy Q8*/
35 : Word16 *gain_pit, /* i/o: adaptive excitation gain Q14*/
36 : const Word32 gain_code, /* i : innovative excitation gain Q16*/
37 : Word16 g_corr[], /* o : ACELP correlation values Q15*/
38 : const Word16 clip_gain, /* i : adaptive gain clipping flag Q0*/
39 : Word16 *gain_preQ, /* o : prequantizer excitation gain Q2*/
40 : Word16 code_preQ[], /* o : prequantizer excitation Q_AVQ_OUT_DEC*/
41 : Word16 *unbits, /* o : number of AVQ unused bits Q0*/
42 : const Word16 Q_new, /* i : Current frame scaling */
43 : const Word16 shift /* i : shifting applied to y1, xn,... */
44 : )
45 : {
46 : Word16 i, index, nBits, Nsv, Es_pred_loc;
47 : Word16 x_in[L_SUBFR], x_tran[L_SUBFR], gcode16, stmp;
48 : Word16 e_corr, m_corr, e_ener, m_ener, m_den, e_den;
49 : Word16 x_norm[L_SUBFR + L_SUBFR / WIDTH_BAND];
50 : Word32 L_corr, L_ener, Ltmp, Ltmp1;
51 : Word16 nq[L_SUBFR / WIDTH_BAND];
52 : Word32 out32[L_SUBFR];
53 : Word16 Qdct;
54 : Word16 avq_bit_sFlag;
55 : Word16 trgtSvPos;
56 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
57 3370 : Flag Overflow = 0;
58 3370 : move32();
59 : #endif
60 :
61 3370 : avq_bit_sFlag = 0;
62 3370 : move16();
63 3370 : if ( st_fx->element_mode > EVS_MONO )
64 : {
65 0 : avq_bit_sFlag = 1;
66 0 : move16();
67 : }
68 :
69 : /*--------------------------------------------------------------*
70 : * Set bit-allocation
71 : *--------------------------------------------------------------*/
72 :
73 3370 : Nsv = 8;
74 3370 : move16();
75 3370 : nBits = st_fx->acelp_cfg.AVQ_cdk_bits[shr( i_subfr, 6 )]; /* Q0 */
76 3370 : move16();
77 :
78 : /* increase # of AVQ allocated bits by unused bits from the previous subframe */
79 3370 : nBits = add( nBits, *unbits );
80 :
81 : /*--------------------------------------------------------------*
82 : * Compute/Update target
83 : * For inactive frame, find target in residual domain
84 : * Deemphasis
85 : *--------------------------------------------------------------*/
86 3370 : IF( EQ_16( st_fx->coder_type, INACTIVE ) )
87 : {
88 : #ifdef ISSUE_1867_replace_overflow_libenc
89 0 : gcode16 = round_fx_sat( L_shl_sat( gain_code, Q_new ) );
90 : #else
91 : gcode16 = round_fx_o( L_shl_o( gain_code, Q_new, &Overflow ), &Overflow );
92 : #endif
93 0 : FOR( i = 0; i < L_SUBFR; i++ )
94 : {
95 : /*x_tran[i] = xn[i] - *gain_pit * y1[i] - gain_code * y2[i];*/
96 0 : Ltmp = L_mult( gcode16, y2[i] );
97 0 : Ltmp = L_shl( Ltmp, add( 5, shift ) );
98 0 : Ltmp = L_negate( Ltmp );
99 0 : Ltmp = L_mac( Ltmp, xn[i], 16384 );
100 0 : Ltmp = L_msu( Ltmp, y1[i], *gain_pit ); /* Q_new + 14 + shift */
101 0 : Ltmp = L_shl_sat( Ltmp, sub( 1, shift ) ); /* Q_new + 15 */
102 0 : x_tran[i] = round_fx_sat( Ltmp ); /*Q_new-1 */
103 0 : move16();
104 : }
105 0 : find_cn_fx( x_tran, Ap, p_Aq, x_in );
106 : }
107 : ELSE
108 : {
109 3370 : updt_tar_fx( cn, x_in, &exc[i_subfr], *gain_pit, L_SUBFR );
110 : }
111 3370 : Deemph2( x_in, FAC_PRE_AVQ_FX, L_SUBFR, &( st_fx->mem_deemp_preQ_fx ) );
112 :
113 : /*--------------------------------------------------------------*
114 : * DCT-II
115 : *--------------------------------------------------------------*/
116 :
117 3370 : test();
118 3370 : test();
119 3370 : test();
120 3370 : IF( NE_16( st_fx->coder_type, INACTIVE ) && LE_32( st_fx->core_brate, MAX_BRATE_AVQ_EXC_TD ) && GE_32( st_fx->core_brate, MIN_BRATE_AVQ_EXC ) && !harm_flag_acelp )
121 : {
122 0 : Copy_Scale_sig( x_in, x_tran, L_SUBFR, -Q_MINUS + 1 ); /*Q_new-1 -> Q_new-4*/
123 : /*Copy( x_in, x_tran, L_SUBFR );*/
124 0 : Qdct = sub( Q_new, Q_MINUS );
125 : }
126 : ELSE
127 : {
128 3370 : Qdct = 0;
129 3370 : move16();
130 3370 : edct2_fx( L_SUBFR, -1, x_in, out32, &Qdct, ip_edct2_64, w_edct2_64_fx );
131 3370 : Qdct = negate( Qdct );
132 3370 : Copy_Scale_sig_32_16( out32, x_tran, L_SUBFR, sub( Qdct, Q_MINUS - 1 ) ); /* Output in Q_new-4 */
133 3370 : Qdct = sub( Q_new, Q_MINUS );
134 : }
135 :
136 : /*--------------------------------------------------------------*
137 : * Split algebraic vector quantizer based on RE8 lattice
138 : *--------------------------------------------------------------*/
139 3370 : AVQ_cod_fx( x_tran, x_norm, nBits, Nsv, 0 );
140 :
141 : /*--------------------------------------------------------------*
142 : * Find prequantizer excitation gain
143 : * Quantize the gain
144 : *--------------------------------------------------------------*/
145 3370 : L_corr = L_deposit_l( 0 );
146 3370 : L_ener = L_deposit_l( 0 );
147 219050 : FOR( i = 0; i < Nsv * 8; i++ )
148 : {
149 : /*fcorr += fx_tran[i]*(float)ix_norm[i];*/
150 : /*fener += (float)ix_norm[i]*(float)ix_norm[i];*/
151 215680 : stmp = shl_sat( x_norm[i], Q_AVQ_OUT );
152 215680 : L_corr = L_mac_sat( L_corr, x_tran[i], stmp );
153 215680 : L_ener = L_mac_sat( L_ener, stmp, stmp );
154 : }
155 3370 : L_ener = L_max( L_ener, 1 );
156 :
157 : /* No negative gains allowed in the quantizer*/
158 3370 : L_corr = L_max( L_corr, 0 );
159 :
160 3370 : e_corr = norm_l( L_corr );
161 3370 : m_corr = extract_h( L_shl( L_corr, e_corr ) );
162 3370 : e_corr = sub( 30, add( e_corr, sub( Qdct, Q_AVQ_OUT ) ) );
163 3370 : e_ener = norm_l( L_ener );
164 3370 : m_ener = extract_h( L_shl( L_ener, e_ener ) );
165 3370 : e_ener = sub( 30, e_ener );
166 :
167 3370 : IF( GT_16( m_corr, m_ener ) )
168 : {
169 2319 : m_corr = shr( m_corr, 1 );
170 2319 : e_corr = add( e_corr, 1 );
171 : }
172 3370 : m_corr = div_s( m_corr, m_ener ); /* e_corr - e_ener */
173 3370 : e_corr = sub( e_corr, e_ener );
174 3370 : Ltmp = L_shl_sat( m_corr, s_min( add( e_corr, 1 ), 31 ) ); /* Lgain in Q16 */
175 3370 : IF( EQ_16( st_fx->coder_type, INACTIVE ) )
176 : {
177 0 : Ltmp1 = L_max( gain_code, 1 );
178 0 : e_den = norm_l( Ltmp1 );
179 0 : m_den = extract_h( L_shl_sat( Ltmp1, e_den ) );
180 : /* ensure m_corr < m_den */
181 0 : test();
182 0 : IF( m_corr > 0 && m_den > 0 )
183 : {
184 0 : m_corr = div_s( 16384, m_den );
185 0 : e_corr = sub( 14 + 4, e_den );
186 0 : Ltmp = L_shr( Mult_32_16( Ltmp, m_corr ), e_corr ); /*Q12*/
187 : #ifdef ISSUE_1867_replace_overflow_libenc
188 0 : stmp = round_fx_sat( L_shl_sat( Ltmp, 16 ) ); /* Q12 */
189 : #else
190 : stmp = round_fx_o( L_shl_o( Ltmp, 16, &Overflow ), &Overflow ); /* Q12 */
191 : #endif
192 : }
193 : ELSE
194 : {
195 0 : stmp = 0;
196 0 : move16();
197 : }
198 0 : IF( GT_32( st_fx->core_brate, 56000 ) )
199 : {
200 0 : index = usquant_fx( stmp, &stmp, G_AVQ_MIN_INACT_64k_Q12, G_AVQ_DELTA_INACT_64k_Q12 >> 1, ( 1 << G_AVQ_BITS ) ); /* Q0 */
201 : }
202 0 : ELSE IF( GT_32( st_fx->core_brate, 42000 ) )
203 : {
204 0 : index = usquant_fx( stmp, &stmp, G_AVQ_MIN_INACT_48k_Q12, G_AVQ_DELTA_INACT_48k_Q12 >> 1, ( 1 << G_AVQ_BITS ) ); /* Q0 */
205 : }
206 : ELSE
207 : {
208 0 : index = usquant_fx( stmp, &stmp, G_AVQ_MIN_INACT_Q12, G_AVQ_DELTA_INACT_Q12 >> 1, ( 1 << G_AVQ_BITS ) ); /* Q0 */
209 : }
210 0 : Ltmp = Mult_32_16( gain_code, stmp ); /* Q16 * Q12 - 15 -> Q13*/
211 0 : Ltmp = L_shl_sat( Ltmp, 5 ); /* Q13 -> Q18*/
212 0 : *gain_preQ = round_fx_sat( Ltmp ); /* Q2*/
213 : }
214 : ELSE
215 : {
216 3370 : IF( Es_pred < 0 )
217 : {
218 35 : Es_pred_loc = shr( negate( Es_pred ), 2 ); /* Q8 */
219 : }
220 : ELSE
221 : {
222 3335 : Es_pred_loc = Es_pred; /* Q8 */
223 3335 : move16();
224 : }
225 :
226 3370 : e_den = norm_s( Es_pred_loc );
227 3370 : m_den = shl( Es_pred_loc, e_den );
228 : /* ensure m_corr < m_den */
229 3370 : test();
230 3370 : IF( m_corr > 0 && m_den > 0 )
231 : {
232 3369 : m_corr = div_s( 16384, m_den ); /* 14 - 8 - e_den */
233 3369 : e_corr = sub( 14 - 8, e_den );
234 3369 : Ltmp = L_shr( Mult_32_16( Ltmp, m_corr ), e_corr ); /* Q18 */
235 : }
236 : ELSE
237 : {
238 1 : Ltmp = L_deposit_l( 0 );
239 : }
240 3370 : test();
241 3370 : IF( LE_32( st_fx->core_brate, 42000 ) && GT_32( st_fx->core_brate, ACELP_24k40 ) )
242 : {
243 0 : index = gain_quant_fx( &Ltmp, &stmp, LG10_G_AVQ_MIN_32kbps_Q14, LG10_G_AVQ_MAX_Q13, G_AVQ_BITS, &e_den ); /* Q0 */
244 : }
245 : ELSE
246 : {
247 3370 : index = gain_quant_fx( &Ltmp, &stmp, LG10_G_AVQ_MIN_Q14, LG10_G_AVQ_MAX_Q13, G_AVQ_BITS, &e_den ); /* Q0 */
248 : }
249 3370 : Ltmp = L_mult( stmp, Es_pred_loc ); /* Q0*Q8 -> Q9*/
250 3370 : Ltmp = L_shl( Ltmp, add( e_den, 9 ) ); /* Q18*/
251 3370 : *gain_preQ = round_fx( Ltmp ); /* Q2*/
252 : }
253 3370 : push_indice( st_fx->hBstr, IND_AVQ_GAIN, index, G_AVQ_BITS );
254 :
255 : /*--------------------------------------------------------------*
256 : * Encode and multiplex subvectors into bit-stream
257 : *--------------------------------------------------------------*/
258 3370 : trgtSvPos = Nsv - 1;
259 3370 : move16();
260 3370 : test();
261 3370 : test();
262 3370 : test();
263 3370 : test();
264 3370 : test();
265 3370 : IF( avq_bit_sFlag && GT_16( nBits, 85 ) && !harm_flag_acelp && ( EQ_16( st_fx->coder_type, GENERIC ) || EQ_16( st_fx->coder_type, TRANSITION ) || EQ_16( st_fx->coder_type, INACTIVE ) ) )
266 : {
267 0 : trgtSvPos = 2;
268 0 : avq_bit_sFlag = 2;
269 0 : move16();
270 0 : move16();
271 : }
272 :
273 3370 : AVQ_encmux_fx( st_fx->hBstr, -1, x_norm, &nBits, Nsv, nq, avq_bit_sFlag, trgtSvPos );
274 :
275 : /* save # of AVQ unused bits for next subframe */
276 3370 : *unbits = nBits; /* Q0 */
277 3370 : move16();
278 :
279 : /* at the last subframe, write AVQ unused bits */
280 3370 : test();
281 3370 : test();
282 3370 : IF( EQ_16( i_subfr, 4 * L_SUBFR ) && NE_16( st_fx->extl, SWB_BWE_HIGHRATE ) && NE_16( st_fx->extl, FB_BWE_HIGHRATE ) )
283 : {
284 0 : WHILE( *unbits > 0 )
285 : {
286 0 : i = s_min( *unbits, 16 );
287 0 : push_indice( st_fx->hBstr, IND_UNUSED, 0, i );
288 0 : *unbits -= i;
289 : }
290 : }
291 :
292 : /*--------------------------------------------------------------*
293 : * DCT transform
294 : *--------------------------------------------------------------*/
295 :
296 219050 : FOR( i = 0; i < Nsv * WIDTH_BAND; i++ )
297 : {
298 215680 : x_tran[i] = shl_sat( x_norm[i], Q_AVQ_OUT_DEC );
299 215680 : move16();
300 : }
301 :
302 3370 : test();
303 3370 : test();
304 3370 : test();
305 3370 : IF( NE_16( st_fx->coder_type, INACTIVE ) && LE_32( st_fx->core_brate, MAX_BRATE_AVQ_EXC_TD ) && GE_32( st_fx->core_brate, MIN_BRATE_AVQ_EXC ) && !harm_flag_acelp )
306 : {
307 0 : Copy( x_tran, code_preQ, L_SUBFR ); /* Q_AVQ_OUT_DEC */
308 : }
309 : ELSE
310 : {
311 3370 : Qdct = 0;
312 3370 : move16();
313 3370 : edct2_fx( L_SUBFR, 1, x_tran, out32, &Qdct, ip_edct2_64, w_edct2_64_fx );
314 : /*qdct = sub(Q_AVQ_OUT_DEC,qdct+Q_AVQ_OUT_DEC);*/
315 3370 : Qdct = negate( Qdct );
316 3370 : Copy_Scale_sig_32_16( out32, code_preQ, L_SUBFR, Qdct ); /* Output in Q_AVQ_OUT_DEC */
317 : /*qdct = Q_AVQ_OUT_DEC;*/
318 : }
319 :
320 : /*--------------------------------------------------------------*
321 : * Preemphasise
322 : *--------------------------------------------------------------*/
323 : /* in extreme cases at subframe boundaries, lower the preemphasis memory to avoid a saturation */
324 3370 : test();
325 3370 : if ( ( nq[7] != 0 ) && ( GT_16( sub( st_fx->last_nq_preQ, nq[0] ), 7 ) ) )
326 : {
327 : /* *mem_preemp /= 16; */
328 0 : st_fx->mem_preemp_preQ_fx = shr( st_fx->mem_preemp_preQ_fx, 4 );
329 0 : move16();
330 : }
331 3370 : st_fx->last_nq_preQ = nq[7];
332 3370 : move16();
333 :
334 3370 : PREEMPH_FX( code_preQ, FAC_PRE_AVQ_FX, L_SUBFR, &( st_fx->mem_preemp_preQ_fx ) );
335 :
336 : /*--------------------------------------------------------------*
337 : * For inactive segments
338 : * - Zero-memory filtered pre-filter excitation
339 : * - Update of targets and gain_pit
340 : * For inactive segments
341 : * - Update xn[L_subfr-1] for updating the memory of the weighting filter
342 : *--------------------------------------------------------------*/
343 :
344 3370 : IF( EQ_16( st_fx->coder_type, INACTIVE ) )
345 : {
346 : /*ftemp = fcode_preQ[0] *fh1[L_SUBFR-1];*/
347 0 : Ltmp = L_mult( code_preQ[0], h1[L_SUBFR - 1] ); /*1+14+shift + Q_AVQ_OUT */
348 0 : FOR( i = 1; i < L_SUBFR; i++ )
349 : {
350 : /*ftemp += fcode_preQ[i] * fh1[L_SUBFR-1-i];*/
351 0 : Ltmp = L_mac( Ltmp, code_preQ[i], h1[L_SUBFR - 1 - i] );
352 : }
353 : /*fxn[L_SUBFR-1] -= *fgain_preQ * ftemp;*/
354 0 : Ltmp = L_shr( Mult_32_16( Ltmp, *gain_preQ ), sub( add( Q_AVQ_OUT_DEC, 2 ), Q_new ) ); /* (2 + 1 + 14 +shift+Q_AVQ_OUT)-(Q_AVQ_OUT+2-Q_new) = 15 + Q_new + shift */
355 0 : xn[L_SUBFR - 1] = round_fx( L_sub( L_mult( xn[L_SUBFR - 1], 32767 ), Ltmp ) ); /* -> Q_new + shift -1 */
356 : }
357 : ELSE
358 : {
359 3370 : conv_fx( code_preQ, h1, x_tran, L_SUBFR );
360 3370 : updt_tar_HR_fx( cn, cn, code_preQ, *gain_preQ, sub( Q_new, add( -15 + 2, Q_AVQ_OUT_DEC ) ), L_SUBFR );
361 :
362 3370 : updt_tar_HR_fx( xn, xn, x_tran, *gain_preQ, sub( Q_new, add( -15 + 2, Q_AVQ_OUT_DEC ) ), L_SUBFR );
363 3370 : *gain_pit = corr_xy1_fx( xn, y1, g_corr, L_SUBFR, 0, &Overflow ); /* Q14 */
364 : /* clip gain if necessary to avoid problems at decoder */
365 3370 : test();
366 3370 : if ( EQ_16( clip_gain, 1 ) && GT_16( *gain_pit, 15565 ) )
367 : {
368 37 : *gain_pit = 15565; /* 0.95 in Q15 */
369 37 : move16();
370 : }
371 3370 : updt_tar_fx( xn, xn2, y1, *gain_pit, L_SUBFR );
372 : }
373 :
374 3370 : st_fx->use_acelp_preq = 1;
375 3370 : move16();
376 :
377 3370 : return;
378 : }
379 70640 : void transf_cdbk_enc_ivas_fx(
380 : Encoder_State *st_fx, /* i/o: encoder state structure */
381 : const Word16 harm_flag_acelp, /* i : harmonic flag for higher rates ACELP Q0*/
382 : const Word16 i_subfr, /* i : subframe index Q0*/
383 : Word16 cn[], /* i/o: target vector in residual domain Q_new*/
384 : Word16 exc[], /* i/o: pointer to excitation signal frame Q_new*/
385 : const Word16 *p_Aq, /* i : 12k8 Lp coefficient Q12*/
386 : const Word16 Ap[], /* i : weighted LP filter coefficients Q12*/
387 : const Word16 h1[], /* i : weighted filter input response Q15*/
388 : Word16 xn[], /* i/o: target vector Q_new + shift -1*/
389 : Word16 xn2[], /* i/o: target vector for innovation search Q_new + shift -1*/
390 : Word16 y1[], /* i/o: zero-memory filtered adaptive excitation Q_new + shift -1*/
391 : const Word16 y2[], /* i : zero-memory filtered innovative excitation Q9*/
392 : const Word16 Es_pred, /* i : predicited scaled innovation energy Q8*/
393 : Word16 *gain_pit, /* i/o: adaptive excitation gain Q14*/
394 : const Word32 gain_code, /* i : innovative excitation gain Q16*/
395 : Word16 g_corr[], /* o : ACELP correlation values Q15*/
396 : const Word16 clip_gain, /* i : adaptive gain clipping flag Q0*/
397 : Word16 *gain_preQ, /* o : prequantizer excitation gain Q2*/
398 : Word16 code_preQ[], /* o : prequantizer excitation Q_AVQ_OUT_DEC*/
399 : Word16 *unbits, /* o : number of AVQ unused bits Q0*/
400 : const Word16 Q_new, /* i : Current frame scaling */
401 : const Word16 shift /* i : shifting applied to y1, xn,... */
402 : )
403 : {
404 : Word16 i, index, nBits, Nsv, Es_pred_loc;
405 : Word16 x_in[L_SUBFR], x_tran[L_SUBFR], gcode16, stmp;
406 : Word16 e_corr, m_corr, e_ener, m_ener, m_den, e_den;
407 : Word16 x_norm[L_SUBFR + L_SUBFR / WIDTH_BAND];
408 : Word32 L_corr, L_ener, Ltmp, Ltmp1;
409 : Word16 nq[L_SUBFR / WIDTH_BAND];
410 : Word32 out32[L_SUBFR];
411 : Word16 Qdct;
412 : Word16 avq_bit_sFlag;
413 : Word16 trgtSvPos;
414 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
415 70640 : Flag Overflow = 0;
416 70640 : move32();
417 : #endif
418 :
419 70640 : avq_bit_sFlag = 0;
420 70640 : move16();
421 70640 : if ( st_fx->element_mode > EVS_MONO )
422 : {
423 70640 : avq_bit_sFlag = 1;
424 70640 : move16();
425 : }
426 :
427 : /*--------------------------------------------------------------*
428 : * Set bit-allocation
429 : *--------------------------------------------------------------*/
430 :
431 70640 : Nsv = 8;
432 70640 : move16();
433 70640 : nBits = st_fx->acelp_cfg.AVQ_cdk_bits[i_subfr >> 6]; /* Q0 */
434 70640 : move16();
435 :
436 : /* increase # of AVQ allocated bits by unused bits from the previous subframe */
437 70640 : nBits = add( nBits, *unbits );
438 :
439 : /*--------------------------------------------------------------*
440 : * Compute/Update target
441 : * For inactive frame, find target in residual domain
442 : * Deemphasis
443 : *--------------------------------------------------------------*/
444 70640 : IF( EQ_16( st_fx->coder_type, INACTIVE ) )
445 : {
446 : #ifdef ISSUE_1867_replace_overflow_libenc
447 13030 : gcode16 = round_fx_sat( L_shl_sat( gain_code, Q_new ) );
448 : #else
449 : gcode16 = round_fx_o( L_shl_o( gain_code, Q_new, &Overflow ), &Overflow );
450 : #endif
451 846950 : FOR( i = 0; i < L_SUBFR; i++ )
452 : {
453 : /*x_tran[i] = xn[i] - *gain_pit * y1[i] - gain_code * y2[i];*/
454 833920 : Ltmp = L_mult( gcode16, y2[i] );
455 833920 : Ltmp = L_shl( Ltmp, add( 5, shift ) );
456 833920 : Ltmp = L_negate( Ltmp );
457 833920 : Ltmp = L_mac( Ltmp, xn[i], 16384 );
458 833920 : Ltmp = L_msu( Ltmp, y1[i], *gain_pit ); /* Q_new + 14 + shift */
459 833920 : Ltmp = L_shl_sat( Ltmp, sub( 1, shift ) ); /* Q_new + 15 */
460 833920 : x_tran[i] = round_fx_sat( Ltmp ); /*Q_new-1 */
461 : }
462 13030 : find_cn_fx( x_tran, Ap, p_Aq, x_in );
463 : }
464 : ELSE
465 : {
466 57610 : updt_tar_fx( cn, x_in, &exc[i_subfr], *gain_pit, L_SUBFR );
467 : }
468 70640 : Deemph2( x_in, FAC_PRE_AVQ_FX, L_SUBFR, &( st_fx->mem_deemp_preQ_fx ) );
469 :
470 : /*--------------------------------------------------------------*
471 : * DCT-II
472 : *--------------------------------------------------------------*/
473 :
474 70640 : test();
475 70640 : test();
476 70640 : test();
477 70640 : IF( NE_16( st_fx->coder_type, INACTIVE ) && LE_32( st_fx->core_brate, MAX_BRATE_AVQ_EXC_TD ) && GE_32( st_fx->core_brate, MIN_BRATE_AVQ_EXC ) && !harm_flag_acelp )
478 : {
479 41240 : Copy_Scale_sig( x_in, x_tran, L_SUBFR, -Q_MINUS + 1 ); /*Q_new-1 -> Q_new-4*/
480 : /*Copy( x_in, x_tran, L_SUBFR );*/
481 41240 : Qdct = sub( Q_new, Q_MINUS );
482 : }
483 : ELSE
484 : {
485 29400 : Qdct = 0;
486 29400 : move16();
487 29400 : edct2_fx( L_SUBFR, -1, x_in, out32, &Qdct, ip_edct2_64, w_edct2_64_fx );
488 29400 : Qdct = negate( Qdct );
489 29400 : Copy_Scale_sig_32_16( out32, x_tran, L_SUBFR, sub( Qdct, Q_MINUS - 1 ) ); /* Output in Q_new-4 */
490 29400 : Qdct = sub( Q_new, Q_MINUS );
491 : }
492 :
493 : /*--------------------------------------------------------------*
494 : * Split algebraic vector quantizer based on RE8 lattice
495 : *--------------------------------------------------------------*/
496 70640 : AVQ_cod_fx( x_tran, x_norm, nBits, Nsv, 0 );
497 :
498 : /*--------------------------------------------------------------*
499 : * Find prequantizer excitation gain
500 : * Quantize the gain
501 : *--------------------------------------------------------------*/
502 70640 : L_corr = L_deposit_l( 0 );
503 70640 : L_ener = L_deposit_l( 0 );
504 4591600 : FOR( i = 0; i < Nsv * 8; i++ )
505 : {
506 : /*fcorr += fx_tran[i]*(float)ix_norm[i];*/
507 : /*fener += (float)ix_norm[i]*(float)ix_norm[i];*/
508 4520960 : stmp = shl_sat( x_norm[i], Q_AVQ_OUT );
509 4520960 : L_corr = L_mac_sat( L_corr, x_tran[i], stmp );
510 4520960 : L_ener = L_mac_sat( L_ener, stmp, stmp );
511 : }
512 70640 : L_ener = L_max( L_ener, 1 );
513 :
514 : /* No negative gains allowed in the quantizer*/
515 70640 : L_corr = L_max( L_corr, 0 );
516 :
517 70640 : e_corr = norm_l( L_corr );
518 70640 : m_corr = extract_h( L_shl( L_corr, e_corr ) );
519 70640 : e_corr = sub( 30, add( e_corr, sub( Qdct, Q_AVQ_OUT ) ) );
520 70640 : e_ener = norm_l( L_ener );
521 70640 : m_ener = extract_h( L_shl( L_ener, e_ener ) ); /* 30 - e-ener */
522 70640 : e_ener = sub( 30, e_ener );
523 :
524 70640 : IF( GT_16( m_corr, m_ener ) )
525 : {
526 40661 : m_corr = shr( m_corr, 1 ); /* e_corr + 1 */
527 40661 : e_corr = add( e_corr, 1 );
528 : }
529 70640 : m_corr = div_s( m_corr, m_ener ); /* e_corr - e_ener */
530 70640 : e_corr = sub( e_corr, e_ener );
531 70640 : Ltmp = L_shl_sat( m_corr, s_min( add( e_corr, 1 ), 31 ) ); /* Lgain in Q16 */
532 70640 : IF( EQ_16( st_fx->coder_type, INACTIVE ) )
533 : {
534 13030 : Ltmp1 = L_max( gain_code, 1 );
535 13030 : e_den = norm_l( Ltmp1 );
536 13030 : m_den = extract_h( L_shl_sat( Ltmp1, e_den ) );
537 : /* ensure m_corr < m_den */
538 13030 : test();
539 13030 : IF( m_corr > 0 && m_den > 0 )
540 : {
541 13030 : m_corr = div_s( 16384, m_den );
542 13030 : e_corr = sub( 14 + 4, e_den );
543 13030 : Ltmp = L_shr( Mult_32_16( Ltmp, m_corr ), e_corr ); /*Q12*/
544 : #ifdef ISSUE_1867_replace_overflow_libenc
545 13030 : stmp = round_fx_sat( L_shl_sat( Ltmp, 16 ) ); /* Q12 */
546 : #else
547 : stmp = round_fx_o( L_shl_o( Ltmp, 16, &Overflow ), &Overflow ); /* Q12 */
548 : #endif
549 : }
550 : ELSE
551 : {
552 0 : stmp = 0;
553 0 : move16();
554 : }
555 13030 : IF( GT_32( st_fx->core_brate, 56000 ) )
556 : {
557 0 : index = usquant_fx( stmp, &stmp, G_AVQ_MIN_INACT_64k_Q12, G_AVQ_DELTA_INACT_64k_Q12 >> 1, ( 1 << G_AVQ_BITS ) ); /* Q0 */
558 : }
559 13030 : ELSE IF( GT_32( st_fx->core_brate, 42000 ) )
560 : {
561 1570 : index = usquant_fx( stmp, &stmp, G_AVQ_MIN_INACT_48k_Q12, G_AVQ_DELTA_INACT_48k_Q12 >> 1, ( 1 << G_AVQ_BITS ) ); /* Q0 */
562 : }
563 : ELSE
564 : {
565 11460 : index = usquant_fx( stmp, &stmp, G_AVQ_MIN_INACT_Q12, G_AVQ_DELTA_INACT_Q12 >> 1, ( 1 << G_AVQ_BITS ) ); /* Q0 */
566 : }
567 13030 : Ltmp = Mult_32_16( gain_code, stmp ); /* Q16 * Q12 - 15 -> Q13*/
568 13030 : Ltmp = L_shl_sat( Ltmp, 5 ); /* Q13 -> Q18*/
569 13030 : *gain_preQ = round_fx_sat( Ltmp ); /* Q2*/
570 13030 : move16();
571 : }
572 : ELSE
573 : {
574 57610 : IF( Es_pred < 0 )
575 : {
576 160 : Es_pred_loc = shr( negate( Es_pred ), 2 );
577 : }
578 : ELSE
579 : {
580 57450 : Es_pred_loc = Es_pred;
581 57450 : move16();
582 : }
583 :
584 57610 : e_den = norm_s( Es_pred_loc );
585 57610 : m_den = shl( Es_pred_loc, e_den );
586 : /* ensure m_corr < m_den */
587 57610 : test();
588 57610 : IF( m_corr > 0 && m_den > 0 )
589 : {
590 56815 : m_corr = div_s( 16384, m_den );
591 56815 : e_corr = sub( 14 - 8, e_den );
592 56815 : Ltmp = L_shr( Mult_32_16( Ltmp, m_corr ), e_corr ); /* Q16 */
593 : }
594 : ELSE
595 : {
596 795 : Ltmp = L_deposit_l( 0 );
597 : }
598 57610 : test();
599 57610 : IF( LE_32( st_fx->core_brate, 42000 ) && GT_32( st_fx->core_brate, ACELP_24k40 ) )
600 : {
601 51960 : index = gain_quant_fx( &Ltmp, &stmp, LG10_G_AVQ_MIN_32kbps_Q14, LG10_G_AVQ_MAX_Q13, G_AVQ_BITS, &e_den ); /* Q0 */
602 : }
603 : ELSE
604 : {
605 5650 : index = gain_quant_fx( &Ltmp, &stmp, LG10_G_AVQ_MIN_Q14, LG10_G_AVQ_MAX_Q13, G_AVQ_BITS, &e_den ); /* Q0 */
606 : }
607 57610 : Ltmp = L_mult( stmp, Es_pred_loc ); /* Q0*Q8 -> Q9*/
608 57610 : Ltmp = L_shl( Ltmp, add( e_den, 9 ) ); /* Q18*/
609 57610 : *gain_preQ = round_fx( Ltmp ); /* Q2*/
610 57610 : move16();
611 : }
612 70640 : push_indice( st_fx->hBstr, IND_AVQ_GAIN, index, G_AVQ_BITS );
613 :
614 : /*--------------------------------------------------------------*
615 : * Encode and multiplex subvectors into bit-stream
616 : *--------------------------------------------------------------*/
617 70640 : trgtSvPos = sub( Nsv, 1 );
618 70640 : move16();
619 70640 : test();
620 70640 : test();
621 70640 : test();
622 70640 : test();
623 70640 : test();
624 70640 : IF( avq_bit_sFlag && GT_16( nBits, 85 ) && !harm_flag_acelp && ( EQ_16( st_fx->coder_type, GENERIC ) || EQ_16( st_fx->coder_type, TRANSITION ) || EQ_16( st_fx->coder_type, INACTIVE ) ) )
625 : {
626 19950 : trgtSvPos = 2;
627 19950 : avq_bit_sFlag = 2;
628 19950 : move16();
629 19950 : move16();
630 : }
631 70640 : AVQ_encmux_fx( st_fx->hBstr, -1, x_norm, &nBits, Nsv, nq, avq_bit_sFlag, trgtSvPos );
632 : /* save # of AVQ unused bits for next subframe */
633 70640 : *unbits = nBits;
634 70640 : move16();
635 :
636 : /* at the last subframe, write AVQ unused bits */
637 70640 : test();
638 70640 : test();
639 70640 : IF( EQ_16( i_subfr, 4 * L_SUBFR ) && NE_16( st_fx->extl, SWB_BWE_HIGHRATE ) && NE_16( st_fx->extl, FB_BWE_HIGHRATE ) )
640 : {
641 26568 : WHILE( *unbits > 0 )
642 : {
643 12440 : i = s_min( *unbits, 16 );
644 12440 : push_indice( st_fx->hBstr, IND_UNUSED, 0, i );
645 12440 : *unbits = sub( *unbits, i );
646 12440 : move16();
647 : }
648 : }
649 :
650 : /*--------------------------------------------------------------*
651 : * DCT transform
652 : *--------------------------------------------------------------*/
653 :
654 4591600 : FOR( i = 0; i < Nsv * WIDTH_BAND; i++ )
655 : {
656 4520960 : x_tran[i] = shl_sat( x_norm[i], Q_AVQ_OUT_DEC );
657 4520960 : move16();
658 : }
659 :
660 70640 : test();
661 70640 : test();
662 70640 : test();
663 70640 : IF( NE_16( st_fx->coder_type, INACTIVE ) && LE_32( st_fx->core_brate, MAX_BRATE_AVQ_EXC_TD ) && GE_32( st_fx->core_brate, MIN_BRATE_AVQ_EXC ) && !harm_flag_acelp )
664 : {
665 41240 : Copy( x_tran, code_preQ, L_SUBFR ); /* Q_AVQ_OUT_DEC */
666 : }
667 : ELSE
668 : {
669 29400 : Qdct = 0;
670 29400 : move16();
671 29400 : edct2_fx( L_SUBFR, 1, x_tran, out32, &Qdct, ip_edct2_64, w_edct2_64_fx );
672 : /*qdct = sub(Q_AVQ_OUT_DEC,qdct+Q_AVQ_OUT_DEC);*/
673 29400 : Qdct = negate( Qdct );
674 29400 : Copy_Scale_sig_32_16( out32, code_preQ, L_SUBFR, Qdct ); /* Output in Q_AVQ_OUT_DEC */
675 : /*qdct = Q_AVQ_OUT_DEC;*/
676 : }
677 :
678 : /*--------------------------------------------------------------*
679 : * Preemphasise
680 : *--------------------------------------------------------------*/
681 : /* in extreme cases at subframe boundaries, lower the preemphasis memory to avoid a saturation */
682 70640 : test();
683 70640 : if ( ( nq[7] != 0 ) && ( GT_16( sub( st_fx->last_nq_preQ, nq[0] ), 7 ) ) )
684 : {
685 : /* *mem_preemp /= 16; */
686 1 : st_fx->mem_preemp_preQ_fx = shr( st_fx->mem_preemp_preQ_fx, 4 );
687 1 : move16();
688 : }
689 70640 : st_fx->last_nq_preQ = nq[7];
690 70640 : move16();
691 :
692 : /* TD pre-quantizer: in extreme cases at subframe boundaries, lower the preemphasis memory to avoid a saturation */
693 70640 : test();
694 70640 : test();
695 70640 : test();
696 70640 : test();
697 70640 : test();
698 70640 : IF( GT_16( st_fx->element_mode, EVS_MONO ) && NE_16( st_fx->coder_type, INACTIVE ) && GE_32( st_fx->core_brate, MIN_BRATE_AVQ_EXC ) && LE_32( st_fx->core_brate, MAX_BRATE_AVQ_EXC_TD ) && !harm_flag_acelp && code_preQ[0] != 0 )
699 : {
700 18547 : IF( GT_16( abs_s( st_fx->last_code_preq ), shl_sat( abs_s( code_preQ[0] ), 4 ) ) )
701 : {
702 0 : st_fx->mem_preemp_preQ_fx = shr( st_fx->mem_preemp_preQ_fx, 4 );
703 0 : move16();
704 : }
705 18547 : ELSE IF( GT_16( abs_s( st_fx->last_code_preq ), shl_sat( abs_s( code_preQ[0] ), 3 ) ) )
706 : {
707 0 : st_fx->mem_preemp_preQ_fx = shr( st_fx->mem_preemp_preQ_fx, 3 );
708 0 : move16();
709 : }
710 : }
711 :
712 70640 : st_fx->last_code_preq = shr( code_preQ[L_SUBFR - 1], 9 ); // Q0
713 70640 : move16();
714 :
715 70640 : PREEMPH_FX( code_preQ, FAC_PRE_AVQ_FX, L_SUBFR, &( st_fx->mem_preemp_preQ_fx ) );
716 :
717 : /*--------------------------------------------------------------*
718 : * For inactive segments
719 : * - Zero-memory filtered pre-filter excitation
720 : * - Update of targets and gain_pit
721 : * For inactive segments
722 : * - Update xn[L_subfr-1] for updating the memory of the weighting filter
723 : *--------------------------------------------------------------*/
724 :
725 70640 : IF( EQ_16( st_fx->coder_type, INACTIVE ) )
726 : {
727 : /*ftemp = fcode_preQ[0] *fh1[L_SUBFR-1];*/
728 13030 : Ltmp = L_mult( code_preQ[0], h1[L_SUBFR - 1] ); /*1+14+shift + Q_AVQ_OUT */
729 833920 : FOR( i = 1; i < L_SUBFR; i++ )
730 : {
731 : /*ftemp += fcode_preQ[i] * fh1[L_SUBFR-1-i];*/
732 820890 : Ltmp = L_mac( Ltmp, code_preQ[i], h1[L_SUBFR - 1 - i] );
733 : }
734 : /*fxn[L_SUBFR-1] -= *fgain_preQ * ftemp;*/
735 13030 : Ltmp = L_shr( Mult_32_16( Ltmp, *gain_preQ ), sub( add( Q_AVQ_OUT_DEC, 2 ), Q_new ) ); /* (2 + 1 + 14 +shift+Q_AVQ_OUT)-(Q_AVQ_OUT+2-Q_new) = 15 + Q_new + shift */
736 13030 : xn[L_SUBFR - 1] = round_fx( L_sub( L_mult( xn[L_SUBFR - 1], 32767 ), Ltmp ) ); /* -> Q_new + shift -1 */
737 : }
738 : ELSE
739 : {
740 57610 : conv_fx( code_preQ, h1, x_tran, L_SUBFR );
741 57610 : updt_tar_HR_fx( cn, cn, code_preQ, *gain_preQ, sub( Q_new, add( -15 + 2, Q_AVQ_OUT_DEC ) ), L_SUBFR );
742 :
743 57610 : updt_tar_HR_fx( xn, xn, x_tran, *gain_preQ, sub( Q_new, add( -15 + 2, Q_AVQ_OUT_DEC ) ), L_SUBFR );
744 57610 : *gain_pit = corr_xy1_fx( xn, y1, g_corr, L_SUBFR, 0, &Overflow ); /* Q14 */
745 57610 : move16();
746 : /* clip gain if necessary to avoid problems at decoder */
747 57610 : test();
748 57610 : if ( EQ_16( clip_gain, 1 ) && GT_16( *gain_pit, 15565 ) )
749 : {
750 78 : *gain_pit = 15565; /* 0.95 in Q14 */
751 78 : move16();
752 : }
753 57610 : updt_tar_fx( xn, xn2, y1, *gain_pit, L_SUBFR );
754 : }
755 :
756 70640 : st_fx->use_acelp_preq = 1;
757 70640 : move16();
758 :
759 70640 : return;
760 : }
761 : /*-------------------------------------------------------------------*
762 : * Find target in residual domain - cn[]
763 : *-------------------------------------------------------------------*/
764 :
765 13030 : static void find_cn_fx(
766 : const Word16 xn[], /* i : target signal Qx*/
767 : const Word16 Ap[], /* i : weighted LP filter coefficients Q12*/
768 : const Word16 *p_Aq, /* i : 12k8 LP coefficients Q12*/
769 : Word16 cn[] /* o : target signal in residual domain Qx*/
770 : )
771 : {
772 : Word16 tmp, tmp_fl[L_SUBFR + M];
773 :
774 13030 : set16_fx( tmp_fl, 0, M );
775 13030 : Copy( xn, tmp_fl + M, L_SUBFR ); /* Qx */
776 13030 : tmp = 0;
777 13030 : move16();
778 13030 : PREEMPH_FX( tmp_fl + M, PREEMPH_FAC_16k, L_SUBFR, &tmp );
779 13030 : syn_filt_s_lc_fx( 0, Ap, tmp_fl + M, tmp_fl + M, L_SUBFR );
780 13030 : Residu3_lc_fx( p_Aq, M, tmp_fl + M, cn, L_SUBFR, 1 );
781 :
782 13030 : return;
783 : }
784 :
785 :
786 : /*-----------------------------------------------------------------*
787 : * Transform domain contribution encoding
788 : *-----------------------------------------------------------------*/
789 114081 : Word16 gain_quant_fx( /* o: quantization index Q0*/
790 : Word32 *gain, /* i: quantized gain Q16*/
791 : Word16 *gain16, /* o: quantized gain expg*/
792 : const Word16 c_min, /* i: log10 of lower limit in Q14*/
793 : const Word16 c_max, /* i: log10 of upper limit in Q13*/
794 : const Word16 bits, /* i: number of bits to quantize Q0*/
795 : Word16 *expg /* o: output exponent of gain16 */
796 : )
797 : {
798 : Word16 index, levels;
799 : Word16 c_gain;
800 : Word16 e_tmp, f_tmp, exp;
801 : Word16 tmp, tmp1, tmp2, frac;
802 : Word32 L_tmp;
803 :
804 114081 : levels = shl( 1, bits );
805 : /* Prevent gain to be smaller than 0.0003. */
806 : /* This is to avoid an overflow when the gain is very small */
807 : /* the log10 give a high negative value in Q13 that overflow */
808 : /* on this code (the resulting value of 'index' is not affected. */
809 : /* tmp2 = msu_r(L_deposit_h(c_gain),c_min,16384) */
810 114081 : L_tmp = L_max( *gain, 20 );
811 :
812 : /*c_min = (float)log10(min);*/
813 : /*c_mult = (float) ((levels-1)/(log10(max)-c_min));*/
814 :
815 : /*tmp = c_mult * ((float)log10(*gain) - c_min);
816 : = ((levels-1)/(log10(max)-log10(min)))*((float)log10(*gain) - log10(min));*/
817 :
818 114081 : e_tmp = norm_l( L_tmp );
819 114081 : f_tmp = Log2_norm_lc( L_shl( L_tmp, e_tmp ) );
820 114081 : e_tmp = sub( 30 - 16, e_tmp ); /*Q(min)=16*/
821 114081 : L_tmp = Mpy_32_16( e_tmp, f_tmp, 9864 ); /* Q16 */ /*log10(2) in Q15*/
822 114081 : c_gain = round_fx( L_shl( L_tmp, 13 ) ); /* Q13 */
823 :
824 : /*tmp1 = sub(c_max,c_min); Q14*/
825 : /*tmp2 = sub(c_gain,c_min); Q14*/
826 :
827 114081 : tmp1 = msu_r_sat( L_deposit_h( c_max /*in Q13 already*/ ), c_min, 16384 ); /*Q13*/
828 114081 : tmp2 = msu_r_sat( L_deposit_h( c_gain /*in Q13 already*/ ), c_min, 16384 ); /*Q13*/
829 114081 : IF( tmp1 != 0 )
830 : {
831 114081 : exp = norm_s( tmp1 );
832 114081 : frac = div_s( shl( 1, sub( 14, exp ) ), tmp1 ); /*Q(15-exp)*/
833 114081 : L_tmp = L_mult( tmp2, frac ); /*Q(30-exp)*/
834 114081 : L_tmp = Mult_32_16( L_tmp, sub( levels, 1 ) ); /*Q(15-exp)*/
835 114081 : index = extract_l( L_shr( L_add( L_tmp, shr( 1 << 14, exp ) ), sub( 15, exp ) ) ); /* Q0 */
836 : }
837 : ELSE
838 : {
839 0 : L_tmp = L_mult( tmp2, sub( levels, 1 ) ); /*Q15*/
840 0 : index = extract_l( L_shr( L_add( L_tmp, 1 << 14 ), 15 ) ); /* Q0 */
841 : }
842 :
843 114081 : index = s_max( index, 0 );
844 114081 : index = s_min( index, sub( levels, 1 ) );
845 :
846 : /**gain = (float)pow( 10.0, (((float)index)/c_mult) + c_min );
847 : y = index/c_mult + c_min;
848 : = (index/(levels-1))*(log10(max) - log10(min)) + log10(min);
849 : = z*log10(max) + (1-z)*log10(min)
850 : z = (index/(levels-1))*/
851 114081 : tmp = div_s( index, sub( levels, 1 ) ); /*Q15*/
852 114081 : L_tmp = L_mult( tmp, c_max ); /*Q29*/
853 114081 : L_tmp = L_mac0( L_tmp, sub( 32767, tmp ), c_min ); /*Q29*/
854 :
855 114081 : L_tmp = Mult_32_16( L_tmp, 27213 ); /*Q27, 3.321928 in Q13*/
856 114081 : L_tmp = L_shr( L_tmp, 11 ); /*Q27->Q16*/
857 :
858 114081 : frac = L_Extract_lc( L_tmp, expg ); /* Extract exponent of gcode0 */
859 :
860 114081 : *gain16 = extract_l( Pow2( 14, frac ) ); /* Put 14 as exponent so that */
861 : /* output of Pow2() will be: */
862 : /* 16384 < Pow2() <= 32767 */
863 114081 : *expg = sub( *expg, 14 );
864 114081 : move16();
865 :
866 114081 : return ( index );
867 : }
|