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"
7 : #include "prot_fx.h"
8 : #include "rom_com.h"
9 : #include "log2.h"
10 :
11 : /*-------------------------------------------------------------------*
12 : * Local constants
13 : *-------------------------------------------------------------------*/
14 : #define WARP_OS_RATE 8
15 : #define LL 256
16 : #define LL_OS ( WARP_OS_RATE * LL )
17 : #define OSLENGTH 12
18 : #define CUTFREE_ABS_RANGE 6
19 : #define CUTFREE_REL_RANGE 0.25
20 : #define CUTFREE_ABS_RANGE_Q3 48
21 : #define CUTFREE_REL_RANGE_Q2 1
22 : #define WI_THRESHLD 0.8
23 : #define WI_SAMPLE_THLD 20
24 :
25 : /*#define _POLY1(x, c) ((c)[0] * (x) + (c)[1]) */
26 : /*#define _POLY2(x, c) (_POLY1((x), (c)) * (x) + (c)[2]) */
27 : /*#define _POLY3(x, c) (_POLY2((x), (c)) * (x) + (c)[3]) */
28 :
29 : /*-------------------------------------------------------------------*
30 : * Local functions
31 : *--------------------------------------------------------------------*/
32 :
33 : static Word32 DTFS_setEngy_fx( DTFS_STRUCTURE *X_DTFS_FX, Word32 en2_fx );
34 :
35 : /*-------------------------------------------------------------------*
36 : * DTFS_new_fx()
37 : *
38 : * DTFS structure initialization.
39 : *-------------------------------------------------------------------*/
40 0 : ivas_error DTFS_new_fx(
41 : DTFS_STRUCTURE **dtfs_out )
42 : {
43 :
44 : Word16 i;
45 :
46 0 : DTFS_STRUCTURE *dtfs_fx = NULL;
47 0 : dtfs_fx = (DTFS_STRUCTURE *) calloc( 1, sizeof( DTFS_STRUCTURE ) );
48 : // PMT("verif mem alloc")
49 0 : IF( dtfs_fx == NULL )
50 : {
51 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DTFS (SC-VBR) structure\n" ) );
52 : }
53 :
54 0 : dtfs_fx->lag_fx = 0;
55 0 : move16();
56 0 : dtfs_fx->nH_fx = 0;
57 0 : move16();
58 0 : dtfs_fx->nH_4kHz_fx = 0;
59 0 : move16();
60 0 : dtfs_fx->upper_cut_off_freq_of_interest_fx = 3300; // Q0
61 0 : move16();
62 0 : dtfs_fx->upper_cut_off_freq_fx = 4000; // Q0
63 0 : move16();
64 0 : dtfs_fx->Q = 0;
65 0 : move16();
66 :
67 0 : FOR( i = 0; i < MAXLAG_WI; i++ )
68 : {
69 0 : dtfs_fx->a_fx[i] = 0; // dtfs_fx->Q
70 0 : move16();
71 0 : dtfs_fx->b_fx[i] = 0; // dtfs_fx->Q
72 0 : move16();
73 : }
74 0 : *dtfs_out = dtfs_fx;
75 0 : return IVAS_ERR_OK;
76 : }
77 : /*-------------------------------------------------------------------*
78 : * DTFS_copy_fx()
79 : *
80 : * Copy from one DTFS STRUCTURE to another.
81 : *-------------------------------------------------------------------*/
82 :
83 0 : void DTFS_copy_fx(
84 : DTFS_STRUCTURE *Xout_fx, /* o: DTFS structure */
85 : DTFS_STRUCTURE Xinp_fx /* i: DTFS structure */
86 : )
87 :
88 : {
89 :
90 : Word16 k;
91 0 : FOR( k = 0; k < MAXLAG_WI; k++ )
92 : {
93 0 : Xout_fx->a_fx[k] = Xinp_fx.a_fx[k]; /* Q(DTFS_STRUCTURE.Q) */
94 0 : move16();
95 : }
96 :
97 0 : FOR( k = 0; k < MAXLAG_WI; k++ )
98 : {
99 0 : Xout_fx->b_fx[k] = Xinp_fx.b_fx[k]; /* Q(DTFS_STRUCTURE.Q) */
100 0 : move16();
101 : }
102 :
103 0 : Xout_fx->lag_fx = Xinp_fx.lag_fx;
104 0 : move16();
105 0 : Xout_fx->nH_fx = Xinp_fx.nH_fx;
106 0 : move16();
107 0 : Xout_fx->nH_4kHz_fx = Xinp_fx.nH_4kHz_fx;
108 0 : move16();
109 0 : Xout_fx->upper_cut_off_freq_of_interest_fx = Xinp_fx.upper_cut_off_freq_of_interest_fx; // Q0
110 0 : move16();
111 0 : Xout_fx->upper_cut_off_freq_fx = Xinp_fx.upper_cut_off_freq_fx; // Q0
112 0 : move16();
113 0 : Xout_fx->Q = Xinp_fx.Q;
114 0 : move16();
115 0 : return;
116 : }
117 :
118 :
119 : /*-------------------------------------------------------------------*
120 : * DTFS_sub_fx()
121 : *
122 : * Subtract one DTFS STRUCTURE from another.
123 : *-------------------------------------------------------------------*/
124 0 : void DTFS_sub_fx(
125 : DTFS_STRUCTURE *tmp, /* o: X1 - X2 */
126 : DTFS_STRUCTURE X1, /* i: DTFS input 1 */
127 : DTFS_STRUCTURE X2 /* i: DTFS input 2 */
128 : )
129 : {
130 : Word16 i, sft, tmp_loop;
131 0 : sft = sub( X1.Q, X2.Q );
132 :
133 0 : IF( sft > 0 )
134 : {
135 0 : tmp_loop = shr( X1.lag_fx, 1 );
136 0 : FOR( i = 0; i <= tmp_loop; i++ )
137 : {
138 :
139 0 : tmp->a_fx[i] = sub( shr( X1.a_fx[i], sft ), X2.a_fx[i] );
140 0 : move16();
141 0 : tmp->b_fx[i] = sub( shr( X1.b_fx[i], sft ), X2.b_fx[i] );
142 0 : move16();
143 : }
144 0 : tmp->Q = X2.Q;
145 0 : move16();
146 : }
147 : ELSE
148 : {
149 0 : tmp_loop = shr( X1.lag_fx, 1 );
150 0 : FOR( i = 0; i <= tmp_loop; i++ )
151 : {
152 :
153 0 : tmp->a_fx[i] = sub( X1.a_fx[i], shl( X2.a_fx[i], sft ) );
154 0 : move16();
155 0 : tmp->b_fx[i] = sub( X1.b_fx[i], shl( X2.b_fx[i], sft ) );
156 0 : move16();
157 : }
158 0 : tmp->Q = X1.Q;
159 0 : move16();
160 : }
161 0 : tmp->lag_fx = s_max( X1.lag_fx, X2.lag_fx );
162 0 : move16();
163 0 : tmp->nH_fx = s_max( X1.nH_fx, X2.nH_fx );
164 0 : move16();
165 0 : tmp->nH_4kHz_fx = s_max( X1.nH_4kHz_fx, X2.nH_4kHz_fx );
166 0 : move16();
167 0 : tmp->upper_cut_off_freq_of_interest_fx = X1.upper_cut_off_freq_of_interest_fx;
168 0 : move16();
169 0 : tmp->upper_cut_off_freq_fx = X1.upper_cut_off_freq_fx;
170 0 : move16();
171 0 : return;
172 : }
173 : /*-------------------------------------------------------------------*
174 : * DTFS_fast_fs_inv()
175 : *
176 : * DTFS inverse.
177 : *-------------------------------------------------------------------*/
178 :
179 0 : static void DTFS_fast_fs_inv_fx( DTFS_STRUCTURE *X_fx, Word16 *out_fx /* Q0 */, Word16 N_fx, Word16 LOG2N )
180 : {
181 : Word16 i, M_2, N_2, s;
182 : Word16 dbuf_fx[256 + 1];
183 :
184 0 : M_2 = s_min( shr( X_fx->lag_fx, 1 ), X_fx->nH_fx );
185 0 : N_2 = shr( N_fx, 1 );
186 0 : s = negate( X_fx->Q );
187 :
188 0 : dbuf_fx[0] = X_fx->a_fx[0];
189 0 : move16();
190 0 : dbuf_fx[1] = 0;
191 0 : move16();
192 :
193 0 : FOR( i = 1; i <= M_2; i++ )
194 : {
195 0 : dbuf_fx[2 * i] = shl_r( X_fx->a_fx[i], s );
196 0 : move16();
197 0 : dbuf_fx[( 2 * i + 1 )] = shl_r( X_fx->b_fx[i], s );
198 0 : move16();
199 : }
200 :
201 0 : FOR( ; i < N_2; i++ )
202 : {
203 0 : dbuf_fx[2 * i] = 0;
204 0 : move16();
205 0 : dbuf_fx[( 2 * i + 1 )] = 0;
206 0 : move16();
207 : }
208 :
209 : /* do IFFT */
210 0 : r_fft_4_fx( dbuf_fx, N_fx, sub( LOG2N, 1 ), -1 );
211 :
212 0 : FOR( i = 0; i < N_fx; i++ )
213 : {
214 0 : out_fx[i] = dbuf_fx[i]; /* Q0 */
215 0 : move16();
216 : }
217 0 : }
218 :
219 :
220 : /*===================================================================*/
221 : /* FUNCTION : DTFS_alignment_weight_fx () */
222 : /*-------------------------------------------------------------------*/
223 : /* PURPOSE : search for alignment */
224 : /*-------------------------------------------------------------------*/
225 : /* INPUT ARGUMENTS : */
226 : /* _ (struct DTFS_STRUCTURE) X1_fx : a/b in X1.Q */
227 : /* _ (struct DTFS_STRUCTURE) X2_fx : a/b in X2.Q */
228 : /* _ (Word16) Eshift: Q7 */
229 : /* _ (Word16 *) LPC1: lpc coefficients. Q12 */
230 : /* _ (Word16 *) LPC2: lpc coefficients. Q12 */
231 : /* _ (Word16 *) S_fx: sin(2pi*n/(4*lag)) table, Q15 */
232 : /* _ (Word16 *) C_fx: cos(2pi*n/(4*lag)) table, Q15 */
233 : /*-------------------------------------------------------------------*/
234 : /* OUTPUT ARGUMENTS : */
235 : /* _ (Word16) fshift_fx : Q7 */
236 : /*-------------------------------------------------------------------*/
237 : /* INPUT/OUTPUT ARGUMENTS : */
238 : /* _ None */
239 : /*-------------------------------------------------------------------*/
240 : /* RETURN ARGUMENTS : _ None. */
241 : /*-------------------------------------------------------------------*/
242 : /* CALLED FROM : TX/RX */
243 : /*===================================================================*/
244 :
245 0 : static Word16 DTFS_alignment_weight_fx(
246 : DTFS_STRUCTURE *X_fx, /* i : X1 the reference DTFS to keep fixed */
247 : DTFS_STRUCTURE X2, /* i : X2 the test DTFS to shift to find best match */
248 : Word16 Eshift, /* i : Expected shift - coarse value */
249 : const Word16 *LPC1, /* i : LPC to filter to find correlation in spch */
250 : const Word16 *LPC2, /* i : LPC to filter to find correlation in spch */
251 : Word16 *S_fx,
252 : Word16 *C_fx,
253 : Word16 *pf_temp1,
254 : Word16 *pf_temp2,
255 : Word16 *pf_temp,
256 : Word16 *pf_n2 )
257 : {
258 : /* Eshift is w.r.t X2 */
259 : Word16 k, HalfLag, start, end, ab1[MAXLAG_WI], ab2[MAXLAG_WI];
260 : Word32 corr_fx;
261 : Word32 maxcorr_fx, wcorr_fx, diff_corr;
262 : DTFS_STRUCTURE X1;
263 : Word16 temp, temp1, Qcorr, Qmaxcorr, inv_lag, n_fx, diff_fx, fshift_fx, Adiff_fx;
264 : Word16 tmplpc_fx[M + 1];
265 : Word16 exp, tmp;
266 : Word32 L_tmp;
267 : #ifndef ISSUE_1836_replace_overflow_libcom__remnant
268 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
269 : Flag Overflow = 0;
270 : move32();
271 : #endif
272 : #endif
273 0 : diff_fx = 0; /* to avoid compilation warnings */
274 0 : move16();
275 :
276 0 : DTFS_copy_fx( &X1, *X_fx ); /* X1 = *X_fx ; */
277 0 : DTFS_adjustLag_fx( &X1, X2.lag_fx );
278 :
279 : /* PORTING: Handling the functions with variable no. of arguments */
280 0 : poleFilter_setup_fx( LPC1, add( M, 1 ), X1, S_fx, C_fx, pf_temp1, pf_temp2, pf_temp, pf_n2 );
281 0 : DTFS_poleFilter_fx_9( &X1, pf_temp1, pf_temp2, pf_temp, pf_n2 );
282 0 : FOR( k = 0; k < M + 1; k++ )
283 : {
284 0 : tmplpc_fx[k] = mult_r( LPC1[k], pwf_fx[k] ); /* Q12 */
285 0 : move16();
286 : }
287 0 : DTFS_zeroFilter_fx( &X1, tmplpc_fx, M + 1, S_fx, C_fx );
288 :
289 : /* PORTING: Handling the functions with variable no. of arguments */
290 0 : poleFilter_setup_fx( LPC2, add( M, 1 ), X2, S_fx, C_fx, pf_temp1, pf_temp2, pf_temp, pf_n2 );
291 0 : DTFS_poleFilter_fx_9( &X2, pf_temp1, pf_temp2, pf_temp, pf_n2 );
292 0 : FOR( k = 0; k < M + 1; k++ )
293 : {
294 0 : tmplpc_fx[k] = mult_r( LPC2[k], pwf_fx[k] ); /* Q12 */
295 0 : move16();
296 : }
297 0 : DTFS_zeroFilter_fx( &X2, tmplpc_fx, M + 1, S_fx, C_fx );
298 :
299 0 : maxcorr_fx = L_add( MIN_32, 0 );
300 0 : Qmaxcorr = 0;
301 0 : move16();
302 0 : fshift_fx = Eshift;
303 0 : move16();
304 0 : Adiff_fx = s_max( 768, mult_r( 4915, shl( X2.lag_fx, 7 ) ) ); /* Q7, 768=6*128, 4915 = 0.15*32768 */
305 :
306 0 : if ( LT_16( X2.lag_fx, 60 ) )
307 : {
308 0 : diff_fx = 32;
309 0 : move16(); /* Q7 of 0.25 */
310 : }
311 0 : if ( GE_16( X2.lag_fx, 60 ) )
312 : {
313 0 : diff_fx = 64;
314 0 : move16(); /* Q7 of 0.5 */
315 : }
316 :
317 0 : HalfLag = s_min( shr( X2.lag_fx, 1 ), X2.nH_4kHz_fx );
318 0 : exp = norm_s( X2.lag_fx );
319 0 : tmp = div_s( shl( 1, sub( 14, exp ) ), X2.lag_fx );
320 0 : L_tmp = L_shl( tmp, add( exp, 6 ) );
321 0 : inv_lag = round_fx( L_tmp );
322 :
323 0 : FOR( k = 0; k <= HalfLag; k++ )
324 : {
325 : #ifdef ISSUE_1836_replace_overflow_libcom__remnant
326 0 : ab1[k] = round_fx_sat( L_mac0_sat( L_mult0( X1.a_fx[k], X2.a_fx[k] ), X1.b_fx[k], X2.b_fx[k] ) ); /* Q(-15) */
327 0 : ab2[k] = round_fx_sat( L_msu0_sat( L_mult0( X1.a_fx[k], X2.b_fx[k] ), X1.b_fx[k], X2.a_fx[k] ) ); /* Q(-15) */
328 0 : move16();
329 0 : move16();
330 : #else
331 : ab1[k] = round_fx_o( L_mac0_o( L_mult0( X1.a_fx[k], X2.a_fx[k] ), X1.b_fx[k], X2.b_fx[k], &Overflow ), &Overflow ); /* Q(-15) */
332 : ab2[k] = round_fx_o( L_msu0_o( L_mult0( X1.a_fx[k], X2.b_fx[k] ), X1.b_fx[k], X2.a_fx[k], &Overflow ), &Overflow ); /* Q(-15) */
333 : move16();
334 : move16();
335 : #endif
336 : }
337 :
338 0 : start = sub( Eshift, Adiff_fx );
339 0 : end = add( Eshift, Adiff_fx );
340 :
341 0 : FOR( n_fx = start; n_fx <= end; n_fx += diff_fx )
342 : {
343 : /* Q7 */
344 0 : corr_fx = L_deposit_l( 0 );
345 0 : temp = 0;
346 0 : move16();
347 0 : temp1 = round_fx( L_shr( L_mult( inv_lag, n_fx ), 2 ) ); /* Q(19+7+1-2-16)=Q9 of n/X2.lag */
348 :
349 0 : if ( temp1 < 0 )
350 : {
351 0 : temp1 = add( temp1, 0x200 ); /* avoid negative, 0x200 is Q9 of 1 ( 2*pi ) */
352 : }
353 :
354 0 : FOR( k = 0; k <= HalfLag; k++ )
355 : {
356 : #ifdef ISSUE_1836_replace_overflow_libcom__remnant
357 0 : corr_fx = L_mac0_sat( corr_fx, ab1[k], cos_table[s_and( temp, 511 )] );
358 0 : corr_fx = L_mac0_sat( corr_fx, ab2[k], cos_table[s_and( add( temp, 128 ), 511 )] );
359 : #else
360 : corr_fx = L_mac0_o( corr_fx, ab1[k], cos_table[s_and( temp, 511 )], &Overflow );
361 : corr_fx = L_mac0_o( corr_fx, ab2[k], cos_table[s_and( add( temp, 128 ), 511 )], &Overflow );
362 : #endif
363 0 : move32();
364 0 : move32();
365 0 : temp = add( temp, temp1 );
366 : }
367 0 : temp = sub( 8192, mult_r( 20972, abs_s( sub( n_fx, Eshift ) ) ) ); /* Q13, 20972 = Q21 of 0.01. */
368 0 : Qcorr = norm_l( corr_fx );
369 0 : if ( corr_fx == 0 )
370 : {
371 0 : Qcorr = 31;
372 0 : move16();
373 : }
374 :
375 : #ifdef ISSUE_1836_replace_overflow_libcom__remnant
376 0 : temp1 = round_fx_sat( (Word32) L_shl_sat( corr_fx, Qcorr ) ); /* Q(Qcorr-16) */
377 0 : wcorr_fx = L_mult_sat( temp1, shl_sat( temp, 2 ) ); /* Q(Qcorr-16+13+2+1)=Q(Qcorr) */ //!!sat
378 0 : IF( GE_16( Qmaxcorr, Qcorr ) )
379 : {
380 0 : diff_corr = L_sub_sat( wcorr_fx, L_shl_sat( maxcorr_fx, sub( Qcorr, Qmaxcorr ) ) ); /* Qcorr */
381 : }
382 : ELSE
383 : {
384 0 : diff_corr = L_sub_sat( L_shl_sat( wcorr_fx, sub( Qmaxcorr, Qcorr ) ), maxcorr_fx ); /* Qmaxcorr */
385 : }
386 : #else
387 : temp1 = round_fx_o( (Word32) L_shl_o( corr_fx, Qcorr, &Overflow ), &Overflow ); /* Q(Qcorr-16) */
388 : wcorr_fx = L_mult_o( temp1, shl_o( temp, 2, &Overflow ), &Overflow ); /* Q(Qcorr-16+13+2+1)=Q(Qcorr) */
389 : IF( GE_16( Qmaxcorr, Qcorr ) )
390 : {
391 : diff_corr = L_sub_o( wcorr_fx, L_shl_o( maxcorr_fx, sub( Qcorr, Qmaxcorr ), &Overflow ), &Overflow ); /* Qcorr */
392 : }
393 : ELSE
394 : {
395 : diff_corr = L_sub_o( L_shl_o( wcorr_fx, sub( Qmaxcorr, Qcorr ), &Overflow ), maxcorr_fx, &Overflow ); /* Qmaxcorr */
396 : }
397 : #endif
398 :
399 0 : IF( diff_corr > 0 )
400 : {
401 0 : fshift_fx = n_fx;
402 0 : move16();
403 0 : maxcorr_fx = L_add( wcorr_fx, 0 );
404 0 : Qmaxcorr = Qcorr;
405 0 : move16();
406 : }
407 : }
408 :
409 0 : return fshift_fx;
410 : }
411 :
412 :
413 : /*===========================================================================*/
414 : /* FUNCTION : DTFS_alignment_full_fx () */
415 : /*---------------------------------------------------------------------------*/
416 : /* PURPOSE : search for alignment */
417 : /*---------------------------------------------------------------------------*/
418 : /* INPUT ARGUMENTS : */
419 : /* _ (struct DTFS_STRUCTURE) X1_DTFS_fx : a_fx/b_fx in X1_DTFS_fx.Q */
420 : /* _ (struct DTFS_STRUCTURE) X2_DTFS_fx : a_fx/b_fx in X2_DTFS_fx.Q */
421 : /* _ (Word16 *) S_fx: sin(2pi*n/(4*lag)) table, Q15 */
422 : /* _ (Word16 *) C_fx: cos(2pi*n/(4*lag)) table, Q15 */
423 : /*---------------------------------------------------------------------------*/
424 : /* OUTPUT ARGUMENTS : */
425 : /* _ (Word16) fshift_fx : Q1 */
426 : /*---------------------------------------------------------------------------*/
427 : /* INPUT/OUTPUT ARGUMENTS : */
428 : /* _ None */
429 : /*---------------------------------------------------------------------------*/
430 : /* RETURN ARGUMENTS : _ None. */
431 : /*---------------------------------------------------------------------------*/
432 : /* CALLED FROM : TX */
433 : /*===========================================================================*/
434 :
435 0 : Word16 DTFS_alignment_full_fx(
436 : DTFS_STRUCTURE X1_DTFS_fx,
437 : DTFS_STRUCTURE X2_DTFS_fx,
438 : Word16 ph_offset_fx,
439 : Word16 *S_fx,
440 : Word16 *C_fx,
441 : Word16 FR_flag )
442 : {
443 : Word16 temp, temp1, k, start, end, HalfLag, ab1[MAXLAG_WI], ab2[MAXLAG_WI];
444 : Word16 n, fshift_fx;
445 : Word32 corr_fx, maxcorr_fx;
446 : Word16 Eshift, Adiff_fx;
447 : #ifndef ISSUE_1836_replace_overflow_libcom__remnant
448 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
449 : Flag Overflow = 0;
450 : move32();
451 : #endif
452 : #endif
453 :
454 : /* Calculating the expected alignment shift */
455 0 : Eshift = mult_r( ph_offset_fx, shl( X2_DTFS_fx.lag_fx, 7 ) ); /* confirmed I<2 by smv12.org, Q7 */
456 0 : find_rem( (Word16) L_FRAME, shr( add( X2_DTFS_fx.lag_fx, X1_DTFS_fx.lag_fx ), 1 ), &temp );
457 0 : temp = add_sat( shl( temp, 7 ), Eshift ); /* Q7 */
458 0 : IF( temp < 0 )
459 : {
460 0 : temp = add_sat( temp, shl_sat( X1_DTFS_fx.lag_fx, 7 ) ); /* Q7 */
461 : }
462 0 : find_rem( temp, shl( X1_DTFS_fx.lag_fx, 7 ), &Eshift ); /* Q7 */
463 0 : Eshift = shl( shr( Eshift, 7 ), 1 ); /* Q1 but integer */
464 :
465 0 : IF( GT_16( X2_DTFS_fx.lag_fx, 60 ) )
466 : {
467 0 : Adiff_fx = shl( X2_DTFS_fx.lag_fx, 1 - 3 ); /* lag_fx/8 in Q1 */
468 : }
469 : ELSE
470 : {
471 0 : Adiff_fx = shl( X2_DTFS_fx.lag_fx, 1 - 2 ); /* lag_fx/4 in Q1 */
472 : }
473 :
474 :
475 0 : IF( LT_16( X1_DTFS_fx.lag_fx, X2_DTFS_fx.lag_fx ) )
476 : {
477 0 : DTFS_zeroPadd_fx( X2_DTFS_fx.lag_fx, &X1_DTFS_fx );
478 : }
479 :
480 0 : maxcorr_fx = L_add( MIN_32, 0 );
481 0 : HalfLag = s_min( shr( X2_DTFS_fx.lag_fx, 1 ), X2_DTFS_fx.nH_4kHz_fx );
482 :
483 0 : FOR( k = 0; k <= HalfLag; k++ )
484 : {
485 : #ifdef ISSUE_1836_replace_overflow_libcom__remnant
486 0 : ab1[k] = round_fx_sat( L_mac_sat( L_mult_sat( X1_DTFS_fx.a_fx[k], X2_DTFS_fx.a_fx[k] ), X1_DTFS_fx.b_fx[k], X2_DTFS_fx.b_fx[k] ) ); /* Q(-15); */
487 0 : ab2[k] = round_fx_sat( L_msu_sat( L_mult_sat( X1_DTFS_fx.b_fx[k], X2_DTFS_fx.a_fx[k] ), X1_DTFS_fx.a_fx[k], X2_DTFS_fx.b_fx[k] ) ); /* Q(-15); */
488 : #else
489 : ab1[k] = round_fx_o( L_mac_o( L_mult_o( X1_DTFS_fx.a_fx[k], X2_DTFS_fx.a_fx[k], &Overflow ), X1_DTFS_fx.b_fx[k], X2_DTFS_fx.b_fx[k], &Overflow ), &Overflow ); /* Q(-15); */
490 : ab2[k] = round_fx_o( L_msu_o( L_mult_o( X1_DTFS_fx.b_fx[k], X2_DTFS_fx.a_fx[k], &Overflow ), X1_DTFS_fx.a_fx[k], X2_DTFS_fx.b_fx[k], &Overflow ), &Overflow ); /* Q(-15); */
491 : #endif
492 : }
493 0 : IF( FR_flag == 0 )
494 : {
495 0 : start = sub( Eshift, Adiff_fx ); /*Q1*/
496 0 : end = add( Eshift, Adiff_fx ); /*Q1*/
497 : }
498 : ELSE
499 : {
500 : /*
501 : in FR mode, we cannot save and cary forward ph_offset as in VBR mode encoder "ph_offset_E_fx",
502 : so we set ph_offset_fx = 0, as a result we cannot accurately estimate the expected alignment shift Eshift to limit the search,
503 : so we search the full range [0 to X2_DTFS_fx.lag_fx] similar to FL
504 : */
505 0 : start = 0; /*Q1*/
506 0 : end = shl( X2_DTFS_fx.lag_fx, 1 ); /*Q1*/
507 : }
508 :
509 0 : fshift_fx = start;
510 0 : move16(); /*Q1*/
511 :
512 0 : FOR( n = start; n <= end; n++ ) /*n in Q1*/
513 : {
514 : /* Q1 */
515 0 : corr_fx = L_deposit_l( 0 );
516 0 : temp = 0;
517 0 : move16();
518 0 : temp1 = add( n, shl( X2_DTFS_fx.lag_fx, 1 ) ); /* add lag_fx in Q1to make positive */
519 0 : FOR( k = 0; k <= HalfLag; k++ )
520 : {
521 : #ifdef ISSUE_1836_replace_overflow_libcom__remnant
522 0 : corr_fx = L_mac_sat( corr_fx, ab1[k], C_fx[( 2 * temp ) % ( 4 * X2_DTFS_fx.lag_fx )] );
523 0 : corr_fx = L_mac_sat( corr_fx, ab2[k], S_fx[( 2 * temp ) % ( 4 * X2_DTFS_fx.lag_fx )] );
524 0 : temp = add_sat( temp, temp1 );
525 : #else
526 : corr_fx = L_mac_o( corr_fx, ab1[k], C_fx[( 2 * temp ) % ( 4 * X2_DTFS_fx.lag_fx )], &Overflow );
527 : corr_fx = L_mac_o( corr_fx, ab2[k], S_fx[( 2 * temp ) % ( 4 * X2_DTFS_fx.lag_fx )], &Overflow );
528 : temp = add_o( temp, temp1, &Overflow );
529 : #endif
530 : }
531 :
532 0 : IF( GT_32( corr_fx, maxcorr_fx ) )
533 : {
534 0 : fshift_fx = n; /* Q1 */
535 0 : move16();
536 0 : maxcorr_fx = L_add( corr_fx, 0 );
537 : }
538 : }
539 :
540 0 : return fshift_fx; /*Q1*/
541 : }
542 : /*===================================================================*/
543 : /* FUNCTION : DTFS_phaseShift_fx () */
544 : /*-------------------------------------------------------------------*/
545 : /* PURPOSE : Phase is shifted by 2pi*ph/Lag */
546 : /*-------------------------------------------------------------------*/
547 : /* INPUT ARGUMENTS : */
548 : /* _ (Word16) ph: shift index, Q7 */
549 : /* _ (Word16) Lag: Pitch Lag value as for shift */
550 : /* _ (Word16 *) S_fx: sin(2pi*n/(4*lag)) table, Q15 */
551 : /* _ (Word16 *) C_fx: cos(2pi*n/(4*lag)) table, Q15 */
552 : /*-------------------------------------------------------------------*/
553 : /* OUTPUT ARGUMENTS : */
554 : /* _ None. */
555 : /*-------------------------------------------------------------------*/
556 : /* INPUT/OUTPUT ARGUMENTS : */
557 : /* _ (struct DTFS_fx) X1 : a/b in X1.Q */
558 : /*-------------------------------------------------------------------*/
559 : /* RETURN ARGUMENTS : _ None. */
560 : /*-------------------------------------------------------------------*/
561 : /* CALLED FROM : TX/RX */
562 : /*===================================================================*/
563 :
564 0 : void DTFS_phaseShift_fx( DTFS_STRUCTURE *X_fx, Word16 ph, Word16 Lag, Word16 *S_fx, Word16 *C_fx )
565 : {
566 : Word16 k;
567 : Word16 temp, HalfLag;
568 : Word32 L_temp, L_temp2;
569 :
570 0 : L_temp2 = L_deposit_l( 0 );
571 0 : HalfLag = s_min( shr( X_fx->lag_fx, 1 ), X_fx->nH_fx );
572 :
573 0 : IF( ph > 0 )
574 : {
575 0 : FOR( k = 0; k <= HalfLag; k++ )
576 : {
577 0 : temp = X_fx->a_fx[k];
578 0 : L_temp = L_shr( L_temp2, 5 ); /* Q2 */
579 0 : X_fx->a_fx[k] = round_fx( L_msu( L_mult( temp, C_fx[L_temp % ( 4 * Lag )] ), X_fx->b_fx[k], S_fx[L_temp % ( 4 * Lag )] ) ); /* X.Q */
580 0 : move16();
581 0 : X_fx->b_fx[k] = round_fx( L_mac( L_mult( X_fx->b_fx[k], C_fx[L_temp % ( 4 * Lag )] ), temp, S_fx[L_temp % ( 4 * Lag )] ) );
582 0 : move16();
583 0 : L_temp2 = L_add( L_temp2, ph );
584 : }
585 : }
586 :
587 0 : IF( ph < 0 )
588 : {
589 0 : FOR( k = 0; k <= HalfLag; k++ )
590 : {
591 0 : temp = X_fx->a_fx[k];
592 0 : L_temp = L_shr( L_negate( L_temp2 ), 5 ); /* Q2 */
593 0 : X_fx->a_fx[k] = round_fx( L_mac( L_mult( temp, C_fx[L_temp % ( 4 * Lag )] ), X_fx->b_fx[k], S_fx[L_temp % ( 4 * Lag )] ) ); /* X.Q */
594 0 : move16();
595 0 : X_fx->b_fx[k] = round_fx( L_msu( L_mult( X_fx->b_fx[k], C_fx[L_temp % ( 4 * Lag )] ), temp, S_fx[L_temp % ( 4 * Lag )] ) );
596 0 : move16();
597 0 : L_temp2 = L_add( L_temp2, ph );
598 : }
599 : }
600 0 : return;
601 : }
602 :
603 : /*===================================================================*/
604 : /* FUNCTION : Q2phaseShift_fx () */
605 : /*-------------------------------------------------------------------*/
606 : /* PURPOSE : Phase is shifted by 2pi*ph/Lag */
607 : /*-------------------------------------------------------------------*/
608 : /* INPUT ARGUMENTS : */
609 : /* _ (Word16) ph: shift index, Q2 */
610 : /* _ (Word16) Lag: Pitch Lag value as for shift */
611 : /* _ (Word16 *) S_fx: sin(2pi*n/(4*lag)) table, Q15 */
612 : /* _ (Word16 *) C_fx: cos(2pi*n/(4*lag)) table, Q15 */
613 : /*-------------------------------------------------------------------*/
614 : /* OUTPUT ARGUMENTS : */
615 : /* _ None. */
616 : /*-------------------------------------------------------------------*/
617 : /* INPUT/OUTPUT ARGUMENTS : */
618 : /* _ (struct DTFS_STRUCTURE) X_fx : a/b in X_fx->Q */
619 : /*-------------------------------------------------------------------*/
620 : /* RETURN ARGUMENTS : _ None. */
621 : /*-------------------------------------------------------------------*/
622 : /* CALLED FROM : TX/RX */
623 : /*===================================================================*/
624 :
625 0 : void Q2phaseShift_fx(
626 : DTFS_STRUCTURE *X_fx,
627 : Word16 ph,
628 : Word16 Lag,
629 : Word16 *S_fx,
630 : Word16 *C_fx )
631 : {
632 : Word16 k;
633 : Word16 temp, HalfLag;
634 : Word32 temp2;
635 : #ifndef ISSUE_1836_replace_overflow_libcom__remnant
636 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
637 : Flag Overflow = 0;
638 : move32();
639 : #endif
640 : #endif
641 0 : temp2 = L_deposit_l( 0 );
642 :
643 0 : HalfLag = s_min( shr( X_fx->lag_fx, 1 ), X_fx->nH_fx );
644 :
645 :
646 0 : IF( ph > 0 )
647 : {
648 0 : FOR( k = 0; k <= HalfLag; k++ )
649 : {
650 0 : temp = X_fx->a_fx[k];
651 : #ifdef ISSUE_1836_replace_overflow_libcom__remnant
652 0 : X_fx->a_fx[k] = round_fx_sat( L_msu_sat( L_mult_sat( temp, C_fx[temp2 % ( 4 * Lag )] ), X_fx->b_fx[k], S_fx[temp2 % ( 4 * Lag )] ) ); /* X.Q */
653 0 : X_fx->b_fx[k] = round_fx_sat( L_mac_sat( L_mult_sat( X_fx->b_fx[k], C_fx[temp2 % ( 4 * Lag )] ), temp, S_fx[temp2 % ( 4 * Lag )] ) );
654 0 : temp2 = L_add_sat( temp2, (Word32) ph );
655 : #else
656 : X_fx->a_fx[k] = round_fx_o( L_msu_o( L_mult_o( temp, C_fx[temp2 % ( 4 * Lag )], &Overflow ), X_fx->b_fx[k], S_fx[temp2 % ( 4 * Lag )], &Overflow ), &Overflow ); /* X.Q */
657 : X_fx->b_fx[k] = round_fx_o( L_mac_o( L_mult_o( X_fx->b_fx[k], C_fx[temp2 % ( 4 * Lag )], &Overflow ), temp, S_fx[temp2 % ( 4 * Lag )], &Overflow ), &Overflow );
658 : temp2 = L_add_o( temp2, (Word32) ph, &Overflow );
659 : #endif
660 0 : move16();
661 0 : move16();
662 : }
663 : }
664 :
665 :
666 0 : IF( ph < 0 )
667 : {
668 0 : FOR( k = 0; k <= HalfLag; k++ )
669 : {
670 0 : temp = X_fx->a_fx[k];
671 : #ifdef ISSUE_1836_replace_overflow_libcom__remnant
672 0 : X_fx->a_fx[k] = round_fx_sat( L_mac_sat( L_mult_sat( temp, C_fx[temp2 % ( 4 * Lag )] ), X_fx->b_fx[k], S_fx[temp2 % ( 4 * Lag )] ) ); /* X.Q */
673 0 : X_fx->b_fx[k] = round_fx_sat( L_msu_sat( L_mult_sat( X_fx->b_fx[k], C_fx[temp2 % ( 4 * Lag )] ), temp, S_fx[temp2 % ( 4 * Lag )] ) );
674 0 : temp2 = add_sat( (Word16) temp2, negate( ph ) );
675 : #else
676 : X_fx->a_fx[k] = round_fx_o( L_mac_o( L_mult_o( temp, C_fx[temp2 % ( 4 * Lag )], &Overflow ), X_fx->b_fx[k], S_fx[temp2 % ( 4 * Lag )], &Overflow ), &Overflow ); /* X.Q */
677 : X_fx->b_fx[k] = round_fx_o( L_msu_o( L_mult_o( X_fx->b_fx[k], C_fx[temp2 % ( 4 * Lag )], &Overflow ), temp, S_fx[temp2 % ( 4 * Lag )], &Overflow ), &Overflow );
678 : temp2 = add_o( (Word16) temp2, negate( ph ), &Overflow );
679 : #endif
680 0 : move16();
681 0 : move16();
682 : }
683 : }
684 0 : }
685 : /*===================================================================*/
686 : /* FUNCTION : DTFS_zeroPadd_fx () */
687 : /*-------------------------------------------------------------------*/
688 : /* PURPOSE : zeroPadding */
689 : /*-------------------------------------------------------------------*/
690 : /* INPUT ARGUMENTS : */
691 : /* _ (Word16) N_fx: length , Q0 */
692 : /*-------------------------------------------------------------------*/
693 : /* OUTPUT ARGUMENTS : */
694 : /* _ None. */
695 : /*-------------------------------------------------------------------*/
696 : /* INPUT/OUTPUT ARGUMENTS : */
697 : /* _ (struct DTFS_STRUCTURE) X_fx : a/b in X_fx.Q i.e Q6 */
698 : /* _ (Word16) lag: pitch lag of *X_fx, Q0 */
699 : /*-------------------------------------------------------------------*/
700 : /* RETURN ARGUMENTS : _ None. */
701 : /*-------------------------------------------------------------------*/
702 : /* CALLED FROM : TX/RX */
703 : /*===================================================================*/
704 :
705 0 : void DTFS_zeroPadd_fx(
706 : Word16 N_fx,
707 : DTFS_STRUCTURE *X_fx )
708 : {
709 : Word16 i, start, end, diff_fx, rem_fx;
710 :
711 0 : IF( EQ_16( N_fx, X_fx->lag_fx ) )
712 : {
713 0 : return;
714 : }
715 0 : start = add( shr( X_fx->lag_fx, 1 ), 1 );
716 0 : end = shr( N_fx, 1 );
717 :
718 0 : move16();
719 0 : FOR( i = start; i <= end; i++ )
720 : {
721 0 : X_fx->a_fx[i] = 0;
722 0 : move16();
723 0 : X_fx->b_fx[i] = 0;
724 0 : move16();
725 : }
726 :
727 0 : X_fx->lag_fx = N_fx;
728 0 : move16();
729 :
730 : /* recompute nH for new lag */
731 0 : diff_fx = find_rem( 12800, X_fx->lag_fx, &rem_fx );
732 0 : X_fx->nH_fx = find_rem( X_fx->upper_cut_off_freq_fx, diff_fx, &rem_fx );
733 0 : move16();
734 :
735 0 : if ( GE_16( sub( X_fx->upper_cut_off_freq_fx, shr( extract_l( L_mult( diff_fx, X_fx->nH_fx ) ), 1 ) ), diff_fx ) )
736 : {
737 0 : X_fx->nH_fx = add( X_fx->nH_fx, 1 );
738 0 : move16();
739 : }
740 : }
741 : /*===================================================================*/
742 : /* FUNCTION : to_fs_fx () */
743 : /*-------------------------------------------------------------------*/
744 : /* PURPOSE : */
745 : /*-------------------------------------------------------------------*/
746 : /* INPUT ARGUMENTS : */
747 : /* _ (Word16 *) x: input time domain series. Q0 */
748 : /* _ (Word16) N: Lag */
749 : /* _ (struct DTFS_STRUCTURE) PREVCW_FX: a/b in PREVCW_FX.Q */
750 : /* _ (Word16 *) S_fx: sin(2pi*n/(4*lag)) table, Q15 */
751 : /* _ (Word16 *) C_fx: cos(2pi*n/(4*lag)) table, Q15 */
752 : /*-------------------------------------------------------------------*/
753 : /* OUTPUT ARGUMENTS : */
754 : /* _ (struct DTFS_STRUCTURE) (Word16 a[]) : in Q */
755 : /* _ (struct DTFS_STRUCTURE) (Word16 b[]) : in Q */
756 : /* _ (struct DTFS_STRUCTURE) (Word16 lag) : Q0 */
757 : /* _ (struct DTFS_STRUCTURE) (Word16 Q ) : Q value of a/b */
758 : /*-------------------------------------------------------------------*/
759 : /* INPUT/OUTPUT ARGUMENTS : */
760 : /* _ None. */
761 : /*-------------------------------------------------------------------*/
762 : /* RETURN ARGUMENTS : _ None. */
763 : /*-------------------------------------------------------------------*/
764 : /* CALLED FROM : TX/RX */
765 : /*===================================================================*/
766 0 : void DTFS_to_fs_fx(
767 : const Word16 *x, /* i : time domain signal */
768 : Word16 N, /* i : Length of input vector */
769 : DTFS_STRUCTURE *X_fx, /* o : DTFS structure with a, b, lag */
770 : const Word16 Fs, /* i : sampling rate */
771 : const Word16 FR_flag, /* i : FR flag */
772 : Word16 *S_fx,
773 : Word16 *C_fx )
774 :
775 : {
776 : Word16 n, temp, temp_neg, inv_lag, sum, diff_fx;
777 : Word16 nH, k, nH_band, nH_4kHz;
778 : Word32 L_temp, Lx0;
779 : Word32 L_a, L_b, L_tmp;
780 : Word32 La[MAXLAG_WI], Lb[MAXLAG_WI], Labmax;
781 : Word16 exp, tmp;
782 : Word32 L_tmp1;
783 : #ifndef ISSUE_1836_replace_overflow_libcom__remnant
784 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
785 : Flag Overflow = 0;
786 : move32();
787 : #endif
788 : #endif
789 :
790 0 : IF( !FR_flag )
791 : {
792 0 : IF( EQ_16( Fs, 16000 ) )
793 : {
794 0 : X_fx->upper_cut_off_freq_of_interest_fx = 4000;
795 0 : move16();
796 0 : X_fx->upper_cut_off_freq_fx = 6400;
797 0 : move16();
798 0 : X_fx->Fs_fx = INT_FS_FX;
799 0 : move16();
800 : }
801 0 : ELSE IF( EQ_16( Fs, 8000 ) )
802 : {
803 0 : X_fx->upper_cut_off_freq_of_interest_fx = 3300;
804 0 : move16();
805 0 : X_fx->upper_cut_off_freq_fx = 4000;
806 0 : move16();
807 0 : X_fx->Fs_fx = INT_FS_FX;
808 0 : move16();
809 : }
810 : }
811 : ELSE
812 : {
813 0 : X_fx->upper_cut_off_freq_of_interest_fx = 8000;
814 0 : move16();
815 0 : X_fx->upper_cut_off_freq_fx = 8000;
816 0 : move16();
817 0 : X_fx->Fs_fx = 16000;
818 0 : move16();
819 : }
820 0 : X_fx->lag_fx = N;
821 0 : move16();
822 :
823 0 : exp = norm_s( X_fx->lag_fx );
824 0 : tmp = div_s( shl( 1, sub( 14, exp ) ), X_fx->lag_fx ); /* Q29-exp */
825 : #ifdef ISSUE_1836_replace_overflow_libcom__remnant
826 0 : L_tmp1 = L_mult( 12800, tmp ); /* Q(30-exp) */
827 0 : diff_fx = extract_h( L_shl_sat( L_tmp1, sub( exp, 14 ) ) ); /* Q0 */
828 :
829 0 : exp = norm_s( diff_fx );
830 0 : tmp = div_s( shl( 1, sub( 14, exp ) ), diff_fx ); /* Q29-exp */
831 0 : L_tmp1 = L_mult_sat( X_fx->upper_cut_off_freq_fx, tmp ); /* Q(30-exp) */
832 0 : nH_band = extract_h( L_shl_sat( L_tmp1, sub( exp, 14 ) ) ); /* Q0 */
833 : #else
834 : L_tmp1 = L_mult_o( 12800, tmp, &Overflow ); /* Q(30-exp) */
835 : diff_fx = extract_h( L_shl_o( L_tmp1, sub( exp, 14 ), &Overflow ) ); /* Q0 */
836 :
837 : exp = norm_s( diff_fx );
838 : tmp = div_s( shl( 1, sub( 14, exp ) ), diff_fx ); /* Q29-exp */
839 : L_tmp1 = L_mult_o( X_fx->upper_cut_off_freq_fx, tmp, &Overflow ); /* Q(30-exp) */
840 : nH_band = extract_h( L_shl_o( L_tmp1, sub( exp, 14 ), &Overflow ) ); /* Q0 */
841 : #endif
842 0 : nH_4kHz = mult( 10240, ( X_fx->lag_fx ) ); /* 4000/12800 in Q15 */
843 :
844 0 : if ( GE_16( sub( X_fx->upper_cut_off_freq_fx, shr( (Word16) L_mult( diff_fx, nH_band ), 1 ) ), diff_fx ) )
845 : {
846 0 : nH_band = add( nH_band, 1 );
847 : }
848 :
849 0 : if ( GE_16( sub( 4000, shr( (Word16) L_mult( diff_fx, nH_4kHz ), 1 ) ), diff_fx ) )
850 : {
851 0 : nH_4kHz = add( nH_4kHz, 1 );
852 : }
853 :
854 : /* Number of harmonics excluding the ones at 0 and at pi */
855 0 : nH = shr( sub( N, 1 ), 1 );
856 :
857 : /* The DC component */
858 0 : X_fx->a_fx[0] = 0;
859 0 : move16();
860 0 : X_fx->b_fx[0] = 0;
861 0 : move16();
862 :
863 0 : exp = norm_s( N );
864 0 : tmp = div_s( shl( 1, ( sub( 14, exp ) ) ), N );
865 : #ifdef ISSUE_1836_replace_overflow_libcom__remnant
866 0 : L_tmp = L_shl_sat( tmp, add( exp, 6 ) );
867 0 : inv_lag = round_fx_sat( L_tmp );
868 : #else
869 : L_tmp = L_shl_o( tmp, add( exp, 6 ), &Overflow );
870 : inv_lag = round_fx_o( L_tmp, &Overflow );
871 : #endif
872 0 : Lx0 = L_deposit_h( x[0] );
873 0 : Labmax = L_deposit_l( 0 );
874 0 : FOR( k = 1; k <= nH; k++ )
875 : {
876 0 : L_a = L_shr( Lx0, 1 ); /* Q16 */
877 :
878 0 : L_b = L_deposit_l( 0 );
879 0 : sum = k;
880 0 : move16();
881 0 : temp = k;
882 0 : move16();
883 0 : FOR( n = 1; n < N; n++ )
884 : {
885 : #ifdef ISSUE_1836_replace_overflow_libcom__remnant
886 0 : L_a = L_mac0_sat( L_a, x[n], C_fx[( 4 * sum ) % ( 4 * N )] ); /* Q16 of x[n]*cos(sum) */
887 0 : L_b = L_mac0_sat( L_b, x[n], S_fx[( 4 * sum ) % ( 4 * N )] ); /* Q16 of x[n]*sin(sum) */
888 : #else
889 : L_a = L_mac0_o( L_a, x[n], C_fx[( 4 * sum ) % ( 4 * N )], &Overflow ); /* Q16 of x[n]*cos(sum) */
890 : L_b = L_mac0_o( L_b, x[n], S_fx[( 4 * sum ) % ( 4 * N )], &Overflow ); /* Q16 of x[n]*sin(sum) */
891 : #endif
892 0 : sum = add( sum, temp );
893 : }
894 0 : La[k] = L_shr( L_a, 6 ); /* Q8 of a[k]*2.0 */
895 0 : move32();
896 0 : Lb[k] = L_shr( L_b, 6 ); /* Q8 of b[k]*2.0 */
897 0 : move32();
898 :
899 0 : L_temp = L_abs( La[k] );
900 :
901 0 : if ( GT_32( L_temp, Labmax ) )
902 : {
903 0 : Labmax = L_temp;
904 0 : move32();
905 : }
906 0 : L_temp = L_abs( Lb[k] );
907 :
908 0 : if ( GT_32( L_temp, Labmax ) )
909 : {
910 0 : Labmax = L_temp;
911 0 : move32();
912 : }
913 : }
914 :
915 :
916 : /* The harmonic at 'pi' */
917 :
918 : /* IF ( N%2 == 0 ) */
919 0 : IF( s_and( N, 1 ) == 0 )
920 : {
921 :
922 0 : L_a = L_deposit_l( 0 );
923 0 : temp = 1;
924 0 : move16();
925 0 : temp_neg = negate( temp );
926 0 : FOR( n = 0; n < N - 1; n += 2 )
927 : {
928 : #ifdef ISSUE_1836_replace_overflow_libcom__remnant
929 0 : L_a = L_mac_sat( L_a, x[n], temp ); /* Q1 */
930 0 : L_a = L_mac_sat( L_a, x[n + 1], temp_neg );
931 : #else
932 : L_a = L_mac_o( L_a, x[n], temp, &Overflow ); /* Q1 */
933 : L_a = L_mac_o( L_a, x[n + 1], temp_neg, &Overflow );
934 : #endif
935 : /*temp= negate(temp); */
936 : }
937 0 : if ( s_and( N, 1 ) ) /*if N is odd we need to calculate last */
938 : {
939 : #ifdef ISSUE_1836_replace_overflow_libcom__remnant
940 0 : L_a = L_mac_sat( L_a, x[n], temp ); /* Q1 */
941 : #else
942 : L_a = L_mac_o( L_a, x[n], temp, &Overflow ); /* Q1 */
943 : #endif
944 : }
945 :
946 0 : La[k] = L_shl( L_a, 7 );
947 0 : move32(); /* Q8 of a[k]*1.0 */
948 :
949 :
950 0 : L_temp = L_abs( La[k] );
951 :
952 0 : if ( GT_32( L_temp, Labmax ) )
953 : {
954 0 : Labmax = L_add( L_temp, 0 );
955 : }
956 :
957 0 : X_fx->b_fx[k] = 0;
958 0 : move16();
959 : }
960 :
961 0 : temp = norm_l( Labmax );
962 0 : if ( Labmax == 0 )
963 : {
964 0 : temp = 31;
965 0 : move16();
966 : }
967 :
968 : #ifdef ISSUE_1836_replace_overflow_libcom__remnant
969 0 : FOR( k = 1; k <= nH; k++ )
970 : {
971 0 : X_fx->a_fx[k] = round_fx_sat( L_shl_sat( La[k], temp ) ); /* Q(8+temp-16)=Q(temp-8) */
972 0 : move16();
973 0 : X_fx->a_fx[k] = mult_r_sat( X_fx->a_fx[k], inv_lag );
974 0 : move16(); /* Q(temp-8+19+1-16)=Q(temp-4) of a[k]*2.0/N */
975 0 : X_fx->b_fx[k] = round_fx_sat( L_shl_sat( Lb[k], temp ) ); /* Q(8+temp-16)=Q(temp-8) */
976 0 : move16();
977 0 : X_fx->b_fx[k] = mult_r_sat( X_fx->b_fx[k], inv_lag );
978 0 : move16(); /* Q(temp-8+19+1-16)=Q(temp-4) of b[k]*2.0/N */
979 : }
980 :
981 : /* IF ( N%2 == 0 ) */
982 0 : IF( s_and( N, 1 ) == 0 )
983 : {
984 0 : X_fx->a_fx[k] = round_fx_sat( L_shl_sat( La[k], temp ) ); /* Q(8+temp-16)=Q(temp-8) */
985 0 : X_fx->a_fx[k] = mult_r_sat( X_fx->a_fx[k], inv_lag );
986 0 : move16();
987 0 : move16(); /* Q(temp-8+19+1-16)=Q(temp-4) of a[k]*1.0/N */
988 0 : X_fx->b_fx[k] = 0;
989 0 : move16();
990 : }
991 : #else
992 : FOR( k = 1; k <= nH; k++ )
993 : {
994 : X_fx->a_fx[k] = round_fx_o( L_shl_o( La[k], temp, &Overflow ), &Overflow ); /* Q(8+temp-16)=Q(temp-8) */
995 : move16();
996 : X_fx->a_fx[k] = mult_ro( X_fx->a_fx[k], inv_lag, &Overflow );
997 : move16(); /* Q(temp-8+19+1-16)=Q(temp-4) of a[k]*2.0/N */
998 : X_fx->b_fx[k] = round_fx_o( L_shl_o( Lb[k], temp, &Overflow ), &Overflow ); /* Q(8+temp-16)=Q(temp-8) */
999 : move16();
1000 : X_fx->b_fx[k] = mult_ro( X_fx->b_fx[k], inv_lag, &Overflow );
1001 : move16(); /* Q(temp-8+19+1-16)=Q(temp-4) of b[k]*2.0/N */
1002 : }
1003 :
1004 : /* IF ( N%2 == 0 ) */
1005 : IF( s_and( N, 1 ) == 0 )
1006 : {
1007 : X_fx->a_fx[k] = round_fx_o( L_shl_o( La[k], temp, &Overflow ), &Overflow ); /* Q(8+temp-16)=Q(temp-8) */
1008 : X_fx->a_fx[k] = mult_ro( X_fx->a_fx[k], inv_lag, &Overflow );
1009 : move16();
1010 : move16(); /* Q(temp-8+19+1-16)=Q(temp-4) of a[k]*1.0/N */
1011 : X_fx->b_fx[k] = 0;
1012 : move16();
1013 : }
1014 : #endif
1015 :
1016 0 : X_fx->Q = sub( temp, 4 );
1017 0 : move16();
1018 :
1019 0 : tmp = s_min( shr( X_fx->lag_fx, 1 ), sub( MAXLAG_WI, 1 ) );
1020 0 : FOR( k = ( nH_band + 1 ); k <= tmp; k++ )
1021 : {
1022 0 : X_fx->a_fx[k] = 0;
1023 0 : move16();
1024 0 : X_fx->b_fx[k] = 0;
1025 0 : move16();
1026 : }
1027 0 : X_fx->nH_fx = nH_band;
1028 0 : move16();
1029 0 : X_fx->nH_4kHz_fx = nH_4kHz;
1030 0 : move16();
1031 0 : return;
1032 : }
1033 :
1034 :
1035 : /*===================================================================*/
1036 : /* FUNCTION : DTFS_transform_fx () */
1037 : /*-------------------------------------------------------------------*/
1038 : /* PURPOSE : */
1039 : /*-------------------------------------------------------------------*/
1040 : /* INPUT ARGUMENTS : */
1041 : /* _ (struct DTFS_STRUCTURE) X_fx: a/b in X1.Q, lag in Q0 */
1042 : /* _ (struct DTFS_STRUCTURE) X2_fx. a/b in X2.Q, lag in Q0 */
1043 : /* _ (Word16 *) phase_fx: 2pi normalized, Q12 */
1044 : /* _ (Word16) N: length of series. */
1045 : /*-------------------------------------------------------------------*/
1046 : /* OUTPUT ARGUMENTS : */
1047 : /* _ (Word16 *) out_fx: output transformed series. Q0. */
1048 : /*-------------------------------------------------------------------*/
1049 : /* INPUT/OUTPUT ARGUMENTS : */
1050 : /* _ None. */
1051 : /*-------------------------------------------------------------------*/
1052 : /* RETURN ARGUMENTS : _ None. */
1053 : /*-------------------------------------------------------------------*/
1054 : /* CALLED FROM : TX/RX */
1055 : /*===================================================================*/
1056 0 : static void DTFS_transform_fx(
1057 : DTFS_STRUCTURE X_fx, /* i : Starting DTFS to use in WI */
1058 : DTFS_STRUCTURE X2_fx, /* i : Ending DTFS to use in WI */
1059 : const Word32 *phase_fx, /* i : Phase contour */
1060 : Word16 *out_fx, /* o : Output time domain waveform */
1061 : Word16 N, /* i : Number of samples to generate */
1062 : const Word16 FR_flag /* i : Flag to indicate called in FR context */
1063 : )
1064 : {
1065 :
1066 : Word16 i, j;
1067 : Word32 L_temp_fx;
1068 : Word16 w_fx;
1069 : Word16 inv1_fx, inv2_fx, inv_fx, q1, q2;
1070 : Word32 Lw_fx, temp32_fx;
1071 : Word16 x2_256_fx[256], x1_256_fx[256];
1072 : Word16 k, m, l1;
1073 : Word32 x_r_fx[256];
1074 : Word32 tmptmp3_40_fx;
1075 : Word16 temp_w;
1076 : Word16 N1;
1077 0 : Word16 nrg_flag = 0;
1078 0 : move16();
1079 : Word32 L_tmp;
1080 : Word16 tmp, tmp1, tmp2, frac, exp1, exp2;
1081 : Word16 expa, expb, fraca, fracb, scale;
1082 :
1083 : ivas_error error;
1084 :
1085 : DTFS_STRUCTURE *tmp1_dtfs_fx;
1086 : DTFS_STRUCTURE *tmp2_dtfs_fx;
1087 : DTFS_STRUCTURE *tmp3_dtfs_fx;
1088 :
1089 0 : error = IVAS_ERR_OK;
1090 0 : move16();
1091 0 : set32_fx( x_r_fx, 0, 256 );
1092 :
1093 0 : IF( ( error = DTFS_new_fx( &tmp1_dtfs_fx ) ) != IVAS_ERR_OK )
1094 : {
1095 0 : IVAS_ERROR( error, "Error creating DTFS structure 1" );
1096 : }
1097 0 : IF( ( error = DTFS_new_fx( &tmp2_dtfs_fx ) ) != IVAS_ERR_OK )
1098 : {
1099 0 : IVAS_ERROR( error, "Error creating DTFS structure 2" );
1100 : }
1101 0 : IF( ( error = DTFS_new_fx( &tmp3_dtfs_fx ) ) != IVAS_ERR_OK )
1102 : {
1103 0 : IVAS_ERROR( error, "Error creating DTFS structure 3" );
1104 : }
1105 :
1106 0 : DTFS_copy_fx( tmp1_dtfs_fx, X_fx );
1107 0 : DTFS_copy_fx( tmp2_dtfs_fx, X2_fx );
1108 :
1109 0 : tmp2 = 0; /* to avoid compilation warnings */
1110 0 : move16();
1111 :
1112 0 : DTFS_fast_fs_inv_fx( tmp1_dtfs_fx, x1_256_fx, 256, 8 );
1113 0 : DTFS_fast_fs_inv_fx( tmp2_dtfs_fx, x2_256_fx, 256, 8 );
1114 :
1115 :
1116 : /* L_temp_fx=invert_dp((Word40)N,4,&n,1); = 1/M, Q(61-n) */
1117 : /* inv1_fx=round_fx(L_temp_fx); = 1/M in Q(45-n) */
1118 : /* q1=sub(n,15); */
1119 0 : exp1 = norm_s( N );
1120 0 : inv1_fx = div_s( shl( 1, sub( 14, exp1 ) ), N ); /* 29-exp1 */
1121 0 : q1 = add( exp1, 1 );
1122 :
1123 0 : tmp1 = sub( X_fx.lag_fx, N );
1124 0 : exp2 = norm_s( tmp1 );
1125 :
1126 0 : if ( tmp1 < 0 )
1127 : {
1128 0 : tmp2 = negate( tmp1 );
1129 : }
1130 0 : tmp = div_s( shl( 1, sub( 14, exp2 ) ), tmp2 ); /* 29-exp2 */
1131 0 : L_tmp = L_shl( tmp, 16 );
1132 :
1133 0 : if ( tmp1 < 0 )
1134 : {
1135 0 : L_tmp = L_negate( L_tmp );
1136 : }
1137 :
1138 0 : q2 = sub( exp2, 3 );
1139 :
1140 :
1141 : /*L_temp_fx=(Word32) Mpy_32_16(extract_h(L_tmp),extract_l(L_tmp),22904); move32(); */ /* L_temp=log(0.2)*log10(e)/(lag-M), Q(61-n) */
1142 0 : L_temp_fx = Mult_32_16( L_tmp, 22904 ); /* L_temp=log(0.2)*log10(e)/(lag-M), Q(61-n) */
1143 0 : inv2_fx = round_fx( L_temp_fx ); /* log(0.2)*log10(e)/(lag-M), Q(45-n) */
1144 : /* q2=sub(n,19); */ /* adjust Q factor to Q26 */
1145 :
1146 :
1147 0 : IF( GT_16( sub( N, WI_SAMPLE_THLD ), X_fx.lag_fx ) )
1148 : {
1149 0 : inv_fx = inv2_fx;
1150 0 : move16();
1151 : }
1152 : ELSE
1153 : {
1154 0 : inv_fx = inv1_fx;
1155 0 : move16();
1156 0 : exp2 = exp1;
1157 0 : move16();
1158 : }
1159 :
1160 0 : Lw_fx = L_deposit_l( inv_fx );
1161 :
1162 0 : FOR( i = 0; i < N; i++ )
1163 : {
1164 0 : IF( FR_flag == 0 )
1165 : {
1166 0 : IF( GT_16( sub( N, WI_SAMPLE_THLD ), X_fx.lag_fx ) )
1167 : {
1168 :
1169 0 : L_tmp = L_shl( Lw_fx, q2 ); /* Q29-exp2+q2 */
1170 0 : L_tmp = Mult_32_16( L_tmp, 27213 ); /* 3.321928 in Q13 -> 16+13+1 */ /*27-exp2 */
1171 0 : L_tmp = L_shl( L_tmp, sub( exp2, add( q2, 11 ) ) );
1172 0 : frac = L_Extract_lc( L_tmp, &exp1 ); /* Extract exponent */
1173 0 : L_temp_fx = Pow2( 14, frac );
1174 0 : exp1 = sub( exp1, 14 );
1175 0 : L_temp_fx = L_shl( L_temp_fx, add( exp1, 15 ) ); /* Q15 */
1176 :
1177 0 : w_fx = sub( 16384, extract_h( L_shl( L_temp_fx, 15 ) ) ); /* w_fx in Q14 1- exp(- (i+1) * log(.2)/(lag-M)) */
1178 : }
1179 : ELSE
1180 : {
1181 0 : w_fx = round_fx( L_shl( Lw_fx, q1 ) ); /* Q14 */
1182 : }
1183 : }
1184 : ELSE
1185 : {
1186 0 : IF( nrg_flag )
1187 : {
1188 0 : w_fx = round_fx( L_shl( Lw_fx, q1 ) ); /* Q14 */
1189 : }
1190 : ELSE
1191 : {
1192 :
1193 0 : N1 = sub( N, tmp2_dtfs_fx->lag_fx );
1194 :
1195 0 : IF( LT_16( i, N1 ) )
1196 : /* w = (i+1)/N1; */
1197 : {
1198 :
1199 : /* w = (i+1)/N1; */
1200 0 : IF( N1 )
1201 : {
1202 0 : expa = norm_s( N1 );
1203 0 : fraca = shl( N1, expa );
1204 0 : expa = sub( 14, expa );
1205 :
1206 0 : tmp = add( i, 1 );
1207 0 : expb = norm_s( tmp );
1208 0 : fracb = shl( tmp, expb );
1209 0 : expb = sub( 14, expb );
1210 :
1211 0 : scale = shr( sub( fraca, fracb ), 15 );
1212 0 : fracb = shl( fracb, scale );
1213 0 : expb = sub( expb, scale );
1214 :
1215 0 : w_fx = div_s( fracb, fraca );
1216 0 : exp1 = sub( expb, expa );
1217 0 : w_fx = shl( w_fx, sub( exp1, 1 ) ); /*Q14*/
1218 : }
1219 : ELSE
1220 : {
1221 0 : w_fx = 0;
1222 0 : move16();
1223 : }
1224 :
1225 0 : Lw_fx = L_deposit_h( w_fx );
1226 : }
1227 : ELSE
1228 : {
1229 0 : w_fx = 16384; // 1.Q14
1230 0 : move16();
1231 : }
1232 : }
1233 : }
1234 :
1235 0 : Lw_fx = L_add( Lw_fx, inv_fx ); /* (i+1)*inv */
1236 : /* mapping phase to 8x256 length signal */
1237 0 : temp32_fx = phase_fx[i]; /* Q(27-11)=Q16 due to multiplication by pow(2.0,11) */
1238 0 : move32();
1239 0 : j = rint_new_fx( temp32_fx );
1240 0 : j = s_and( j, 0x07ff );
1241 :
1242 : /* k=j%8; */
1243 0 : k = s_and( j, 7 );
1244 0 : l1 = shr( j, 3 ); /* reminder and quotient */
1245 :
1246 0 : temp_w = sub( 16384, w_fx );
1247 0 : tmptmp3_40_fx = L_deposit_l( 0 );
1248 :
1249 0 : FOR( j = 0; j < 12; j++ )
1250 : {
1251 0 : m = L_add( 1000 * LL - OSLENGTH / 2, add( l1, j ) ) % LL; /* use circular addressing */
1252 0 : x_r_fx[m] = L_mac( L_mult( x1_256_fx[m], temp_w ), x2_256_fx[m], w_fx );
1253 0 : move32();
1254 : }
1255 0 : tmptmp3_40_fx = L_deposit_l( 0 );
1256 :
1257 :
1258 0 : FOR( j = 0; j < 12; j++ )
1259 : {
1260 0 : m = L_add( 1000 * LL - OSLENGTH / 2, add( l1, j ) ) % LL; /* use circular addressing */
1261 0 : tmptmp3_40_fx = L_add( tmptmp3_40_fx, Mult_32_16( x_r_fx[m], sinc_fx[k][j] ) );
1262 : }
1263 0 : out_fx[i] = round_fx_sat( L_shl_sat( tmptmp3_40_fx, 2 ) );
1264 0 : move16();
1265 : }
1266 :
1267 :
1268 0 : free( tmp1_dtfs_fx );
1269 0 : free( tmp2_dtfs_fx );
1270 0 : free( tmp3_dtfs_fx );
1271 0 : return;
1272 : }
1273 : /*===================================================================*/
1274 : /* FUNCTION : zeroFilter_fx() */
1275 : /*-------------------------------------------------------------------*/
1276 : /* PURPOSE : zero filtering */
1277 : /*-------------------------------------------------------------------*/
1278 : /* INPUT ARGUMENTS : */
1279 : /* _ (Word16) lpc[] : lpc coefficients in Q12 */
1280 : /* _ (Word16) N : lpc order */
1281 : /* _ (Word16) this->lag: in Q0 */
1282 : /* _ (Word16 *) S_fx: sin(2pi*n/(4*lag)) table, Q15 */
1283 : /* _ (Word16 *) C_fx: cos(2pi*n/(4*lag)) table, Q15 */
1284 : /*-------------------------------------------------------------------*/
1285 : /* OUTPUT ARGUMENTS : */
1286 : /* _ None. */
1287 : /*-------------------------------------------------------------------*/
1288 : /* INPUT/OUTPUT ARGUMENTS : */
1289 : /* _ (Word16) this->a[] : in Q(this->Q) */
1290 : /* _ (Word16) this->b[] : in Q(this->Q) */
1291 : /* _ (Word16) this->Q: in Q0 */
1292 : /*-------------------------------------------------------------------*/
1293 : /* RETURN ARGUMENTS : _ None. */
1294 : /*-------------------------------------------------------------------*/
1295 : /* CALLED FROM : TX/RX */
1296 : /*===================================================================*/
1297 :
1298 0 : void DTFS_zeroFilter_fx(
1299 : DTFS_STRUCTURE *X_fx,
1300 : Word16 *LPC,
1301 : Word16 N,
1302 : Word16 *S_fx,
1303 : Word16 *C_fx )
1304 : {
1305 : Word32 sum1_fx, sum2_fx;
1306 : Word16 k, n, HalfLag;
1307 : Word16 temp, temp1, temp2;
1308 : Word32 L_temp1, L_temp2;
1309 : Word16 Qmin, Qab[MAXLAG_WI], na, nb;
1310 : #ifndef ISSUE_1836_replace_overflow_libcom__remnant
1311 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
1312 : Flag Overflow = 0;
1313 : move32();
1314 : #endif
1315 : #endif
1316 0 : Qmin = 32767;
1317 0 : move16();
1318 0 : HalfLag = s_min( shr( X_fx->lag_fx, 1 ), X_fx->nH_fx );
1319 0 : FOR( k = 0; k <= HalfLag; k++ )
1320 : {
1321 0 : temp = k;
1322 0 : move16();
1323 0 : temp2 = k;
1324 0 : move16();
1325 :
1326 : /* Calculate sum1 and sum2 */
1327 0 : sum1_fx = L_deposit_h( 4096 ); /* 1: Q(12+15+1) */
1328 0 : sum2_fx = L_deposit_l( 0 );
1329 :
1330 0 : FOR( n = 0; n < N; n++ )
1331 : {
1332 : #ifdef ISSUE_1836_replace_overflow_libcom__remnant
1333 0 : sum1_fx = L_mac_sat( sum1_fx, LPC[n], C_fx[( 4 * temp2 ) % ( 4 * X_fx->lag_fx )] ); /* Q(12+15+1) */
1334 0 : sum2_fx = L_mac_sat( sum2_fx, LPC[n], S_fx[( 4 * temp2 ) % ( 4 * X_fx->lag_fx )] );
1335 0 : temp2 = add( temp2, temp );
1336 : }
1337 :
1338 0 : temp1 = round_fx_sat( sum1_fx ); /* Q(12+15+1-16)=Q(12) */
1339 0 : temp2 = round_fx_sat( sum2_fx ); /* Q(12) */
1340 :
1341 : /* Calculate the circular convolution */
1342 0 : L_temp1 = L_mult( temp1, X_fx->a_fx[k] );
1343 0 : L_temp1 = L_msu_sat( L_temp1, temp2, X_fx->b_fx[k] ); /* Q(12+Q+1) */
1344 0 : L_temp2 = L_mult( temp1, X_fx->b_fx[k] );
1345 :
1346 0 : L_temp2 = L_mac_sat( L_temp2, temp2, X_fx->a_fx[k] ); /* Q(12+Q+1) */
1347 : #else
1348 : sum1_fx = L_mac_o( sum1_fx, LPC[n], C_fx[( 4 * temp2 ) % ( 4 * X_fx->lag_fx )], &Overflow ); /* Q(12+15+1) */
1349 : sum2_fx = L_mac_o( sum2_fx, LPC[n], S_fx[( 4 * temp2 ) % ( 4 * X_fx->lag_fx )], &Overflow );
1350 : temp2 = add( temp2, temp );
1351 : }
1352 :
1353 : temp1 = round_fx_o( sum1_fx, &Overflow ); /* Q(12+15+1-16)=Q(12) */
1354 : temp2 = round_fx_o( sum2_fx, &Overflow ); /* Q(12) */
1355 :
1356 : /* Calculate the circular convolution */
1357 : L_temp1 = L_mult_o( temp1, X_fx->a_fx[k], &Overflow );
1358 : L_temp1 = L_msu_o( L_temp1, temp2, X_fx->b_fx[k], &Overflow ); /* Q(12+Q+1) */
1359 : L_temp2 = L_mult_o( temp1, X_fx->b_fx[k], &Overflow );
1360 : L_temp2 = L_mac_o( L_temp2, temp2, X_fx->a_fx[k], &Overflow ); /* Q(12+Q+1) */
1361 : #endif
1362 : /* normalization */
1363 0 : na = norm_l( L_temp1 );
1364 0 : if ( L_temp1 == 0 )
1365 : {
1366 0 : na = 31;
1367 0 : move16();
1368 : }
1369 0 : nb = norm_l( L_temp2 );
1370 0 : if ( L_temp2 == 0 )
1371 : {
1372 0 : nb = 31;
1373 0 : move16();
1374 : }
1375 :
1376 0 : if ( LT_16( na, nb ) )
1377 : {
1378 0 : nb = na;
1379 0 : move16();
1380 : }
1381 : #ifdef ISSUE_1836_replace_overflow_libcom__remnant
1382 0 : X_fx->a_fx[k] = round_fx_sat( (Word32) L_shl_sat( L_temp1, nb ) ); /* Q(13+Q+nb-16)=Q(Q+nb-3) */
1383 0 : X_fx->b_fx[k] = round_fx_sat( (Word32) L_shl_sat( L_temp2, nb ) ); /* Q(Q+nb-3) */
1384 : #else
1385 : X_fx->a_fx[k] = round_fx_o( (Word32) L_shl_o( L_temp1, nb, &Overflow ), &Overflow ); /* Q(13+Q+nb-16)=Q(Q+nb-3) */
1386 : X_fx->b_fx[k] = round_fx_o( (Word32) L_shl_o( L_temp2, nb, &Overflow ), &Overflow ); /* Q(Q+nb-3) */
1387 : #endif
1388 0 : move32();
1389 0 : move32();
1390 :
1391 0 : Qab[k] = sub( nb, 3 );
1392 0 : move16();
1393 :
1394 0 : if ( LT_16( Qab[k], Qmin ) )
1395 : {
1396 0 : Qmin = Qab[k];
1397 0 : move16();
1398 : }
1399 : }
1400 : /* bring to the same Q */
1401 0 : FOR( k = 0; k <= HalfLag; k++ )
1402 : {
1403 : #ifdef ISSUE_1836_replace_overflow_libcom__remnant
1404 0 : X_fx->a_fx[k] = shl_sat( X_fx->a_fx[k], sub( Qmin, Qab[k] ) );
1405 : #else
1406 : X_fx->a_fx[k] = shl_o( X_fx->a_fx[k], sub( Qmin, Qab[k] ), &Overflow );
1407 : #endif
1408 0 : move16(); /* Q(Q+Qab[k]+Qmin-Qab[k]=Q(Q+Qmin) */
1409 : #ifdef ISSUE_1836_replace_overflow_libcom__remnant
1410 0 : X_fx->b_fx[k] = shl_sat( X_fx->b_fx[k], sub( Qmin, Qab[k] ) );
1411 : #else
1412 : X_fx->b_fx[k] = shl_o( X_fx->b_fx[k], sub( Qmin, Qab[k] ), &Overflow );
1413 : #endif
1414 0 : move16(); /* Q(Q+Qmin) */
1415 : }
1416 :
1417 0 : X_fx->Q = add( X_fx->Q, Qmin );
1418 0 : move16();
1419 0 : return;
1420 : }
1421 : /*===================================================================*/
1422 : /* FUNCTION : DTFS_poleFilter_fx() */
1423 : /*-------------------------------------------------------------------*/
1424 : /* PURPOSE : pole filtering */
1425 : /*-------------------------------------------------------------------*/
1426 : /* INPUT ARGUMENTS : */
1427 : /* _ (Word16) lpc[] : lpc coefficients in Q12 */
1428 : /* _ (Word16) N : lpc order */
1429 : /* _ (Word16) lag: in Q0 */
1430 : /* _ (Word16 *) C_fx: cos(2pi*n/(4*lag)) table, Q15 */
1431 : /* _ (Word16 *) S_fx: sin(2pi*n/(4*lag)) table, Q15 */
1432 : /* _ (Word16 *) C_fx: cos(2pi*n/(4*lag)) table, Q15 */
1433 : /*-------------------------------------------------------------------*/
1434 : /* OUTPUT ARGUMENTS : */
1435 : /* _ None */
1436 : /*-------------------------------------------------------------------*/
1437 : /* INPUT/OUTPUT ARGUMENTS : */
1438 : /* _ (Word16) this->a[] : in Q(this->Q) */
1439 : /* _ (Word16) this->b[] : in Q(this->Q) */
1440 : /* _ (Word16) this->Q: in Q0 */
1441 : /*-------------------------------------------------------------------*/
1442 : /* RETURN ARGUMENTS : _ None. */
1443 : /*-------------------------------------------------------------------*/
1444 : /* CALLED FROM : TX/RX */
1445 : /*===================================================================*/
1446 :
1447 : /* PORTING: Handling the functions with variable no. of arguments */
1448 :
1449 0 : void DTFS_poleFilter_fx_9(
1450 : DTFS_STRUCTURE *X_fx,
1451 : Word16 *pf_temp1,
1452 : Word16 *pf_temp2,
1453 : Word16 *pf_temp,
1454 : Word16 *pf_n2_temp1 )
1455 : {
1456 : Word16 temp, temp1, temp2, HalfLag;
1457 : Word32 sum1_fx, sum2_fx;
1458 : Word32 L_temp1, L_temp2;
1459 : Word16 k, n2_temp1, na, nb;
1460 : Word16 Qmin, Qab[MAXLAG_WI];
1461 :
1462 0 : Qmin = 32767;
1463 0 : move16();
1464 0 : HalfLag = s_min( shr( X_fx->lag_fx, 1 ), X_fx->nH_fx );
1465 0 : FOR( k = 0; k <= HalfLag; k++ )
1466 : {
1467 0 : temp = temp2 = k;
1468 0 : move16();
1469 0 : move16();
1470 : /* Calculate sum1 and sum2 */
1471 :
1472 0 : n2_temp1 = pf_n2_temp1[k];
1473 0 : move16();
1474 :
1475 0 : temp1 = pf_temp1[k];
1476 0 : move16(); /* Q(12+15+1+n2-16)=Q(12+n2) */
1477 0 : temp2 = pf_temp2[k];
1478 0 : move16(); /* Q(12+n2) */
1479 :
1480 : /* Calculate the circular convolution */
1481 :
1482 0 : L_temp1 = L_mac( L_mult( temp1, X_fx->a_fx[k] ), temp2, X_fx->b_fx[k] ); /* Q(12+n2+Q+1)=Q(13+n2+Q) */
1483 0 : L_temp2 = L_msu( L_mult( temp1, X_fx->b_fx[k] ), temp2, X_fx->a_fx[k] ); /* Q(12+n2+Q+1)=Q(13+n2+Q) */
1484 :
1485 0 : temp = pf_temp[k];
1486 0 : move16(); /* Q(61-25-2*n2-temp1-16)=Q(20-2*n2-temp1) */
1487 :
1488 0 : sum1_fx = Mult_32_16( L_temp1, temp ); /* Q(13+n2+Q+15+exp-15) = Q(13+n2+Q+exp) */
1489 0 : sum2_fx = Mult_32_16( L_temp2, temp );
1490 : /* normalization */
1491 0 : na = norm_l( sum1_fx );
1492 0 : if ( sum1_fx == 0 )
1493 : {
1494 0 : na = 31;
1495 0 : move16();
1496 : }
1497 0 : nb = norm_l( sum2_fx );
1498 0 : if ( sum2_fx == 0 )
1499 : {
1500 0 : nb = 31;
1501 0 : move16();
1502 : }
1503 :
1504 0 : if ( LT_16( na, nb ) )
1505 : {
1506 0 : nb = na;
1507 0 : move16();
1508 : }
1509 0 : nb = sub( nb, 1 ); /* leave one more sign bit */
1510 0 : X_fx->a_fx[k] = round_fx( (Word32) L_shl( sum1_fx, nb ) ); /* Q(-3+n2+Q+exp+nb ) */
1511 0 : move16();
1512 0 : X_fx->b_fx[k] = round_fx( (Word32) L_shl( sum2_fx, nb ) );
1513 0 : move16();
1514 :
1515 0 : Qab[k] = add( sub( nb, 3 ), n2_temp1 );
1516 0 : move16();
1517 :
1518 0 : if ( LT_16( Qab[k], Qmin ) )
1519 : {
1520 0 : Qmin = Qab[k];
1521 0 : move16();
1522 : }
1523 : }
1524 : /* bring to the same Q */
1525 :
1526 0 : FOR( k = 0; k <= HalfLag; k++ )
1527 : {
1528 0 : X_fx->a_fx[k] = shl( X_fx->a_fx[k], sub( Qmin, Qab[k] ) );
1529 0 : move16(); /* Q(Q+Qab[k]+Qmin-Qab[k])=Q(Q+Qmin) */
1530 0 : X_fx->b_fx[k] = shl( X_fx->b_fx[k], sub( Qmin, Qab[k] ) );
1531 0 : move16(); /* Q(Q+Qab[k]+Qmin-Qab[k])=Q(Q+Qmin) */
1532 : }
1533 :
1534 0 : X_fx->Q = add( X_fx->Q, Qmin );
1535 0 : move16();
1536 0 : return;
1537 : }
1538 : /*===================================================================*/
1539 : /* FUNCTION : DTFS_adjustLag_fx () */
1540 : /*-------------------------------------------------------------------*/
1541 : /* PURPOSE : */
1542 : /*-------------------------------------------------------------------*/
1543 : /* INPUT ARGUMENTS : */
1544 : /* _ (Word16) N_fx: lag value, Q0 */
1545 : /*-------------------------------------------------------------------*/
1546 : /* OUTPUT ARGUMENTS : */
1547 : /* _ (struct DTFS_fx) : a/b in X1.Q */
1548 : /*-------------------------------------------------------------------*/
1549 : /* INPUT/OUTPUT ARGUMENTS : */
1550 : /* _ (struct DTFS_fx) X1 : lag in Q0 */
1551 : /*-------------------------------------------------------------------*/
1552 : /* RETURN ARGUMENTS : _ None. */
1553 : /*-------------------------------------------------------------------*/
1554 : /* CALLED FROM : TX/RX */
1555 : /*===================================================================*/
1556 :
1557 0 : void DTFS_adjustLag_fx(
1558 : DTFS_STRUCTURE *X_DTFS_FX, /* i/o : DTFS to adjust lag for */
1559 : Word16 N_fx /* i : Target lag */
1560 : )
1561 : {
1562 : Word32 en_fx;
1563 : Word32 temp32_fx, tempnH_fx, mul1_fx, mul2_fx;
1564 : Word16 k, diff_fx;
1565 : Word16 exp, tmp;
1566 : Word32 L_tmp;
1567 :
1568 0 : IF( EQ_16( N_fx, X_DTFS_FX->lag_fx ) )
1569 : {
1570 0 : return;
1571 : }
1572 :
1573 0 : IF( GT_16( N_fx, X_DTFS_FX->lag_fx ) )
1574 : {
1575 0 : DTFS_zeroPadd_fx( N_fx, X_DTFS_FX );
1576 : }
1577 : ELSE
1578 : {
1579 0 : en_fx = DTFS_getEngy_fx( X_DTFS_FX ); /* Q = 2*(X_DTFS_FX->Q) */
1580 :
1581 0 : tmp = s_min( shr( X_DTFS_FX->lag_fx, 1 ), X_DTFS_FX->nH_fx );
1582 0 : FOR( k = ( ( N_fx >> 1 ) + 1 ); k <= tmp; k++ )
1583 : {
1584 0 : X_DTFS_FX->a_fx[k] = 0;
1585 0 : move16();
1586 0 : X_DTFS_FX->b_fx[k] = 0;
1587 0 : move16();
1588 : }
1589 0 : DTFS_setEngy_fx( X_DTFS_FX, en_fx );
1590 0 : X_DTFS_FX->lag_fx = N_fx;
1591 0 : move16();
1592 :
1593 :
1594 : /* recompute nH for new lag */
1595 0 : exp = norm_s( X_DTFS_FX->lag_fx );
1596 0 : tmp = div_s( shl( 1, sub( 14, exp ) ), X_DTFS_FX->lag_fx ); /* 29 - exp */
1597 0 : L_tmp = L_mult0( 12800, tmp );
1598 0 : temp32_fx = L_shl( L_tmp, sub( exp, 23 ) );
1599 0 : diff_fx = extract_l( L_shl( L_tmp, sub( exp, 29 ) ) );
1600 :
1601 :
1602 0 : exp = norm_s( diff_fx );
1603 0 : tmp = div_s( shl( 1, sub( 14, exp ) ), diff_fx ); /* 29 - exp */
1604 0 : L_tmp = L_mult0( X_DTFS_FX->upper_cut_off_freq_fx, tmp );
1605 0 : X_DTFS_FX->nH_fx = extract_l( L_shl( L_tmp, sub( exp, 29 ) ) );
1606 0 : move16();
1607 :
1608 0 : L_tmp = L_mult0( 4000, tmp );
1609 0 : tempnH_fx = L_shl( L_tmp, sub( exp, 23 ) );
1610 0 : X_DTFS_FX->nH_4kHz_fx = extract_l( L_shl( L_tmp, sub( exp, 29 ) ) );
1611 0 : move16();
1612 :
1613 0 : IF( GE_16( sub( X_DTFS_FX->upper_cut_off_freq_fx, shr( extract_l( L_mult( diff_fx, X_DTFS_FX->nH_fx ) ), 1 ) ), diff_fx ) )
1614 : {
1615 0 : X_DTFS_FX->nH_fx = add( X_DTFS_FX->nH_fx, 1 );
1616 0 : move16();
1617 : }
1618 :
1619 0 : mul1_fx = L_shl( temp32_fx, 13 ); /* Q19 */
1620 0 : mul2_fx = L_shl( (Word32) X_DTFS_FX->nH_4kHz_fx, 18 ); /* Q18 */
1621 0 : tempnH_fx = Mult_32_32( mul1_fx, mul2_fx ); /* Q6 */
1622 0 : tempnH_fx = L_sub( (Word32) 256000, tempnH_fx ); /* Q6 */
1623 :
1624 0 : IF( GE_32( tempnH_fx, temp32_fx ) )
1625 : {
1626 0 : X_DTFS_FX->nH_4kHz_fx = add( X_DTFS_FX->nH_4kHz_fx, 1 );
1627 0 : move16();
1628 : }
1629 : }
1630 0 : return;
1631 : }
1632 : /*===================================================================*/
1633 : /* FUNCTION : DTFS_getEngy_fx () */
1634 : /*-------------------------------------------------------------------*/
1635 : /* PURPOSE : */
1636 : /*-------------------------------------------------------------------*/
1637 : /* INPUT ARGUMENTS : */
1638 : /* _ (struct DTFS_STRUCTURE) : a/b in X_fx.Q i.e Q6, lag in Q0*/
1639 : /*-------------------------------------------------------------------*/
1640 : /* OUTPUT ARGUMENTS : _ None */
1641 : /*-------------------------------------------------------------------*/
1642 : /* INPUT/OUTPUT ARGUMENTS : _ None */
1643 : /*-------------------------------------------------------------------*/
1644 : /* RETURN ARGUMENTS : */
1645 : /* _ (Word40) en_fx: output energy, 2*X1.Q */
1646 : /*-------------------------------------------------------------------*/
1647 : /* CALLED FROM : TX/RX */
1648 : /*===================================================================*/
1649 :
1650 :
1651 0 : Word32 DTFS_getEngy_fx(
1652 : DTFS_STRUCTURE *X_fx )
1653 : {
1654 : Word16 k, HalfLag_fx;
1655 0 : Word32 en_fx = 0;
1656 0 : move32();
1657 : Word16 temp_a_fx, temp_b_fx;
1658 : #ifndef ISSUE_1836_replace_overflow_libcom__remnant
1659 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
1660 : Flag Overflow = 0;
1661 : move32();
1662 : #endif
1663 : #endif
1664 0 : HalfLag_fx = shr( sub( X_fx->lag_fx, 1 ), 1 );
1665 0 : HalfLag_fx = s_min( HalfLag_fx, X_fx->nH_fx );
1666 0 : FOR( k = 1; k <= HalfLag_fx; k++ )
1667 : {
1668 0 : temp_a_fx = X_fx->a_fx[k];
1669 0 : move16();
1670 0 : temp_b_fx = X_fx->b_fx[k];
1671 0 : move16();
1672 : #ifdef ISSUE_1836_replace_overflow_libcom__remnant
1673 0 : en_fx = L_mac0_sat( en_fx, temp_a_fx, temp_a_fx );
1674 0 : en_fx = L_mac0_sat( en_fx, temp_b_fx, temp_b_fx );
1675 : #else
1676 : en_fx = L_mac0_o( en_fx, temp_a_fx, temp_a_fx, &Overflow );
1677 : en_fx = L_mac0_o( en_fx, temp_b_fx, temp_b_fx, &Overflow );
1678 : #endif
1679 : }
1680 :
1681 0 : en_fx = L_shr( en_fx, 1 );
1682 0 : temp_a_fx = X_fx->a_fx[0];
1683 0 : move16();
1684 : #ifdef ISSUE_1836_replace_overflow_libcom__remnant
1685 0 : en_fx = L_mac0_sat( en_fx, temp_a_fx, temp_a_fx );
1686 : #else
1687 : en_fx = L_mac0_o( en_fx, temp_a_fx, temp_a_fx, &Overflow );
1688 : #endif
1689 : /* IF (X_fx->lag_fx%2 == 0) */
1690 0 : IF( s_and( X_fx->lag_fx, 1 ) == 0 )
1691 : {
1692 0 : temp_a_fx = X_fx->a_fx[k];
1693 0 : move16();
1694 0 : temp_b_fx = X_fx->b_fx[k];
1695 0 : move16();
1696 : #ifdef ISSUE_1836_replace_overflow_libcom__remnant
1697 0 : en_fx = L_mac0_sat( en_fx, temp_a_fx, temp_a_fx );
1698 0 : en_fx = L_mac0_sat( en_fx, temp_b_fx, temp_b_fx );
1699 : #else
1700 : en_fx = L_mac0_o( en_fx, temp_a_fx, temp_a_fx, &Overflow );
1701 : en_fx = L_mac0_o( en_fx, temp_b_fx, temp_b_fx, &Overflow );
1702 : #endif
1703 : }
1704 :
1705 0 : return en_fx; /* 2*X1.Q+1=Q13 */
1706 : }
1707 :
1708 :
1709 : /*===================================================================*/
1710 : /* FUNCTION : DTFS_getEngy_P2A_fx () */
1711 : /*-------------------------------------------------------------------*/
1712 : /* PURPOSE : */
1713 : /*-------------------------------------------------------------------*/
1714 : /* INPUT ARGUMENTS : */
1715 : /* _ (struct DTFS_STRUCTURE) : a/b in X_fx.Q, lag in Q0 */
1716 : /*-------------------------------------------------------------------*/
1717 : /* OUTPUT ARGUMENTS : _ None */
1718 : /*-------------------------------------------------------------------*/
1719 : /* INPUT/OUTPUT ARGUMENTS : _ None */
1720 : /*-------------------------------------------------------------------*/
1721 : /* RETURN ARGUMENTS : */
1722 : /* _ (Word40) en_fx: output energy, 2*X1.Q */
1723 : /*-------------------------------------------------------------------*/
1724 : /* CALLED FROM : TX/RX */
1725 : /*===================================================================*/
1726 :
1727 0 : Word32 DTFS_getEngy_P2A_fx(
1728 : DTFS_STRUCTURE *X_fx )
1729 : {
1730 : Word16 k, HalfLag_fx;
1731 0 : Word32 en_fx = 0;
1732 0 : move32();
1733 : #ifdef ISSUE_1836_replace_overflow_libcom__remnant
1734 0 : HalfLag_fx = shr( sub( X_fx->lag_fx, 1 ), 1 );
1735 0 : HalfLag_fx = s_min( HalfLag_fx, X_fx->nH_fx );
1736 0 : FOR( k = 1; k <= HalfLag_fx; k++ )
1737 : {
1738 0 : en_fx = L_mac0_sat( en_fx, X_fx->a_fx[k], X_fx->a_fx[k] );
1739 0 : en_fx = L_mac0_sat( en_fx, X_fx->b_fx[k], X_fx->b_fx[k] );
1740 : }
1741 0 : en_fx = L_shr( en_fx, 1 );
1742 0 : en_fx = L_mac0_sat( en_fx, X_fx->a_fx[0], X_fx->a_fx[0] );
1743 : /* IF (X_fx->lag_fx%2 == 0) */
1744 0 : IF( s_and( X_fx->lag_fx, 1 ) == 0 )
1745 : {
1746 0 : en_fx = L_mac0_sat( en_fx, X_fx->a_fx[k], X_fx->a_fx[k] );
1747 0 : en_fx = L_mac0_sat( en_fx, X_fx->b_fx[k], X_fx->b_fx[k] );
1748 : }
1749 : #else
1750 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
1751 : Flag Overflow = 0;
1752 : move32();
1753 : #endif
1754 : HalfLag_fx = shr( sub( X_fx->lag_fx, 1 ), 1 );
1755 : HalfLag_fx = s_min( HalfLag_fx, X_fx->nH_fx );
1756 : FOR( k = 1; k <= HalfLag_fx; k++ )
1757 : {
1758 : en_fx = L_mac0_o( en_fx, X_fx->a_fx[k], X_fx->a_fx[k], &Overflow );
1759 : en_fx = L_mac0_o( en_fx, X_fx->b_fx[k], X_fx->b_fx[k], &Overflow );
1760 : }
1761 : en_fx = L_shr( en_fx, 1 );
1762 : en_fx = L_mac0_o( en_fx, X_fx->a_fx[0], X_fx->a_fx[0], &Overflow );
1763 : /* IF (X_fx->lag_fx%2 == 0) */
1764 : IF( s_and( X_fx->lag_fx, 1 ) == 0 )
1765 : {
1766 : en_fx = L_mac0_o( en_fx, X_fx->a_fx[k], X_fx->a_fx[k], &Overflow );
1767 : en_fx = L_mac0_o( en_fx, X_fx->b_fx[k], X_fx->b_fx[k], &Overflow );
1768 : }
1769 : #endif
1770 0 : return en_fx; /* 2*X1.Q */
1771 : }
1772 :
1773 :
1774 : /*===================================================================*/
1775 : /* FUNCTION : DTFS_setEngy_fx ( ) */
1776 : /*-------------------------------------------------------------------*/
1777 : /* PURPOSE : */
1778 : /*-------------------------------------------------------------------*/
1779 : /* INPUT ARGUMENTS : */
1780 : /* _ (Word40) en2_fx: 2*X1.Q+1 i.e. Q13 */
1781 : /*-------------------------------------------------------------------*/
1782 : /* OUTPUT ARGUMENTS : */
1783 : /* _ (Word40) en1_fx : 2*X1.Q+1 i.e. Q13 */
1784 : /*-------------------------------------------------------------------*/
1785 : /* INPUT/OUTPUT ARGUMENTS : */
1786 : /* _ (struct DTFS_STRUCTURE) X_DTFS_FX : a/b in X1.Q i.e. Q6, */
1787 : /* lag in Q0 */
1788 : /*-------------------------------------------------------------------*/
1789 : /* RETURN ARGUMENTS : _ None. */
1790 : /*-------------------------------------------------------------------*/
1791 : /* CALLED FROM : TX/RX */
1792 : /*===================================================================*/
1793 :
1794 0 : static Word32 DTFS_setEngy_fx(
1795 : DTFS_STRUCTURE *X_DTFS_FX,
1796 : Word32 en2_fx )
1797 : {
1798 : Word16 k, HalfLag_fx;
1799 : Word32 en1_fx;
1800 : Word32 L_temp_fx;
1801 : Word16 expa, expb, fraca, fracb, scale, tmp, exp;
1802 : Word32 L_tmp, factor_fx;
1803 :
1804 0 : HalfLag_fx = s_min( shr( X_DTFS_FX->lag_fx, 1 ), X_DTFS_FX->nH_fx );
1805 0 : move16();
1806 0 : en1_fx = DTFS_getEngy_fx( X_DTFS_FX );
1807 0 : move16();
1808 :
1809 0 : IF( en1_fx == 0 )
1810 : {
1811 0 : return 0;
1812 : }
1813 :
1814 0 : IF( en2_fx == 0 )
1815 : {
1816 0 : factor_fx = 0;
1817 0 : move32();
1818 : }
1819 : ELSE
1820 : {
1821 0 : expa = norm_l( en2_fx );
1822 0 : fraca = extract_h( L_shl( en2_fx, expa ) );
1823 0 : expa = sub( 30, add( expa, shl( X_DTFS_FX->Q, 1 ) ) );
1824 :
1825 :
1826 0 : expb = norm_l( en1_fx );
1827 0 : fracb = round_fx_sat( L_shl_sat( en1_fx, expb ) );
1828 0 : expb = sub( 30, add( expb, shl( X_DTFS_FX->Q, 1 ) ) );
1829 :
1830 :
1831 0 : scale = shr( sub( fraca, fracb ), 15 );
1832 0 : fracb = shl( fracb, scale );
1833 0 : expb = sub( expb, scale );
1834 :
1835 0 : tmp = div_s( fracb, fraca );
1836 0 : exp = sub( expb, expa );
1837 :
1838 0 : L_tmp = Isqrt_lc( L_deposit_h( tmp ), &exp ); /* Q(31-exp) */
1839 0 : factor_fx = L_shr( L_tmp, 1 );
1840 : }
1841 :
1842 0 : FOR( k = 0; k <= HalfLag_fx; k++ )
1843 : {
1844 0 : L_temp_fx = Mult_32_16( factor_fx, X_DTFS_FX->a_fx[k] ); /* Q(temp+X1.Q-15) */
1845 0 : X_DTFS_FX->a_fx[k] = round_fx( L_temp_fx ); /* Q(temp+X1.Q-15-16)=Q(temp+X1.Q-31); */
1846 0 : move16();
1847 :
1848 0 : L_temp_fx = Mult_32_16( factor_fx, X_DTFS_FX->b_fx[k] ); /* Q(temp+X1.Q-15) */
1849 0 : X_DTFS_FX->b_fx[k] = round_fx( L_temp_fx ); /* Q(temp+X1.Q-15-16)=Q(temp+X1.Q-31); */
1850 0 : move16();
1851 : }
1852 :
1853 :
1854 0 : return en1_fx; /* 2*X1.Q+1 = Q13 */
1855 : }
1856 :
1857 : /*===================================================================*/
1858 : /* FUNCTION : struct DTFS_car2pol_fx () */
1859 : /*-------------------------------------------------------------------*/
1860 : /* PURPOSE : Cartesian to polar representation */
1861 : /* returning amplitudes and 0 phases */
1862 : /*-------------------------------------------------------------------*/
1863 : /* INPUT ARGUMENTS : */
1864 : /* _ (struct DTFS_STRUCTURE) X_fx : prototype in Cartesian domain*/
1865 : /* (Word16) lag: length of prototype in time domain */
1866 : /* (Word16 []) a,b: re/im of harmonics, normalized */
1867 : /* (Word16) Q: norm factor of a/b */
1868 : /*-------------------------------------------------------------------*/
1869 : /* OUTPUT ARGUMENTS : */
1870 : /* _ (struct DTFS_STRUCTURE) X_fx : prototype in polar domain */
1871 : /* (Word16) lag: length of prototype in time domain */
1872 : /* (Word16 []) a: amplitude of harmonics, normalized */
1873 : /* (Word16 []) b: phase of harmonics,cleared to 0 */
1874 : /* (Word16) Q: norm factor of a */
1875 : /*-------------------------------------------------------------------*/
1876 : /* INPUT/OUTPUT ARGUMENTS : */
1877 : /* _ None */
1878 : /*-------------------------------------------------------------------*/
1879 : /* RETURN ARGUMENTS : _ None. */
1880 : /*-------------------------------------------------------------------*/
1881 : /* CALLED FROM : TX/RX */
1882 : /*===================================================================*/
1883 : /* NOTE: output X.b (angle) is not computed and should be ignored */
1884 : /* When phases are needed, such as in QPPP, instead uses the */
1885 : /* Cartesian representation to avoid computing phases by arctan*/
1886 : /*===================================================================*/
1887 0 : void DTFS_car2pol_fx(
1888 : DTFS_STRUCTURE *X_fx /* i/o : DTFS structure a, b, lag */
1889 : )
1890 :
1891 : {
1892 : Word16 k, HalfLag_fx;
1893 : Word32 Ltemp_fx;
1894 : Word32 Lacc_fx;
1895 : Word16 exp, tmp, frac;
1896 : #ifndef ISSUE_1836_replace_overflow_libcom__remnant
1897 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
1898 : Flag Overflow = 0;
1899 : move32();
1900 : #endif
1901 : #endif
1902 0 : HalfLag_fx = s_min( shr( sub( X_fx->lag_fx, 1 ), 1 ), X_fx->nH_fx );
1903 0 : FOR( k = 1; k <= HalfLag_fx; k++ )
1904 : {
1905 :
1906 0 : Lacc_fx = L_mult( X_fx->a_fx[k], X_fx->a_fx[k] ); /* a[k]^2, 2Q+1 */
1907 : #ifdef ISSUE_1836_replace_overflow_libcom__remnant
1908 0 : Lacc_fx = L_mac_sat( Lacc_fx, X_fx->b_fx[k], X_fx->b_fx[k] ); /* a[k]^2+b[k]^2, 2Q+1 */
1909 : #else
1910 : Lacc_fx = L_mac_o( Lacc_fx, X_fx->b_fx[k], X_fx->b_fx[k], &Overflow ); /* a[k]^2+b[k]^2, 2Q+1 */
1911 : #endif
1912 0 : Lacc_fx = L_shr( Lacc_fx, 3 ); /* Lacc=(a[k]^2+b[k]^2)/4, 2Q */
1913 :
1914 0 : IF( Lacc_fx )
1915 : {
1916 0 : exp = norm_l( Lacc_fx );
1917 0 : frac = extract_h( L_shl( Lacc_fx, exp ) ); /* Q14 */
1918 0 : exp = sub( exp, sub( 30, ( 2 * X_fx->Q ) ) );
1919 :
1920 0 : tmp = div_s( 16384, frac ); /* Q15 */
1921 0 : Ltemp_fx = Isqrt_lc( L_deposit_h( tmp ), &exp ); /* Q(31-exp) */
1922 :
1923 0 : X_fx->a_fx[k] = extract_h( L_shl( Ltemp_fx, sub( add( X_fx->Q, exp ), 15 ) ) ); /* Q */
1924 0 : move16();
1925 : }
1926 : ELSE
1927 : {
1928 0 : X_fx->a_fx[k] = 0;
1929 0 : move16();
1930 : }
1931 :
1932 0 : X_fx->b_fx[k] = 0;
1933 0 : move16(); /* clear b[k] */
1934 : }
1935 :
1936 :
1937 0 : IF( s_and( X_fx->lag_fx, 1 ) == 0 )
1938 : {
1939 0 : IF( X_fx->a_fx[k] )
1940 : {
1941 0 : Lacc_fx = L_mult0( X_fx->a_fx[k], X_fx->a_fx[k] ); /* a[k]^2, 2Q+1 */
1942 0 : Lacc_fx = L_mac0( Lacc_fx, X_fx->b_fx[k], X_fx->b_fx[k] ); /* a[k]^2+b[k]^2, 2Q+1 */
1943 :
1944 0 : exp = norm_l( Lacc_fx );
1945 0 : frac = extract_h( L_shl( Lacc_fx, exp ) ); /* Q14 */
1946 0 : exp = sub( exp, sub( 30, shl( X_fx->Q, 1 ) ) );
1947 :
1948 0 : tmp = div_s( 16384, frac ); /* Q15 */
1949 0 : Ltemp_fx = Isqrt_lc( L_deposit_h( tmp ), &exp ); /* Q(31-exp) */
1950 :
1951 0 : X_fx->a_fx[k] = extract_h( L_shl( Ltemp_fx, sub( add( X_fx->Q, exp ), 15 ) ) ); /* Q */
1952 0 : move16();
1953 : }
1954 : ELSE
1955 : {
1956 0 : X_fx->a_fx[k] = 0;
1957 0 : move16();
1958 : }
1959 :
1960 0 : X_fx->b_fx[k] = 0;
1961 0 : move16(); /* clear b[k]; */
1962 : }
1963 0 : return;
1964 : }
1965 :
1966 :
1967 : /*==============================================================================*/
1968 : /* FUNCTION : DTFS_setEngyHarm_fx ( ) */
1969 : /*------------------------------------------------------------------------------*/
1970 : /* PURPOSE : Set a band of harmonics to specified energy */
1971 : /*----------------------------------------------------------------------- ------*/
1972 : /* INPUT ARGUMENTS : */
1973 : /* _ (struct DTFS_fx) : lag in Q0 */
1974 : /* _ (Word16) f1_fx: lower bound of input, normalized by 12800, Q15 */
1975 : /* _ (Word16) f2_fx: upper bound of input, normalized by 12800, Q15 */
1976 : /* _ (Word16) g1_fx: lower bound of output, normalized by 12800, Q15 */
1977 : /* _ (Word16) g2_fx: upper bound of output, normalized by 12800, Q15 */
1978 : /* _ (Word32) en2_fx: in Q(Qen2) */
1979 : /* _ (Word16) Qen2_fx: Q value of en2 */
1980 : /*---------------------------------------------------------------------------- --*/
1981 : /* OUTPUT ARGUMENTS : */
1982 : /* _ (Word16) Qa_fx: Q value of output a[]. */
1983 : /*----------------------------------------------------------------------------- -*/
1984 : /* INPUT/OUTPUT ARGUMENTS : */
1985 : /* _(struct DTFS_STRUCTURE) : a_fx[] in X1_fx.Q at start, then changed to */
1986 : /* *Qa later. */
1987 : /*---------------------------------------------------------------------------- --*/
1988 : /* RETURN ARGUMENTS : _ None. */
1989 : /* _ (Word32) en1_fx: Q(2*X1.Q) */
1990 : /*----------------------------------------------------------------------------- -*/
1991 : /* CALLED FROM : TX/RX */
1992 : /*============================================================================== */
1993 : /* NOTE: This function cannot change Q because it works on a band */
1994 : /* of harmonics, instead of the whole DTFS */
1995 : /*============================================================================== */
1996 0 : Word32 DTFS_setEngyHarm_fx(
1997 : Word16 f1_fx, /* i : lower band freq of input to control energy */
1998 : Word16 f2_fx, /* i : upper band freq of input to control energy */
1999 : Word16 g1_fx, /* i : lower band freq of output to control energy */
2000 : Word16 g2_fx, /* i : upper band freq of output to control energy */
2001 : Word32 en2_fx, /* i : Target Energy to set the DTFS to */
2002 : Word16 Qen2_fx, /* i : Input Q format for en2 */
2003 : Word16 *Qa_fx, /* i : Output Q format for x->a */
2004 : DTFS_STRUCTURE *X_fx /* i/o: DTFS to adjust the energy of */
2005 : )
2006 : {
2007 :
2008 0 : Word16 k, count = 0, HalfLag_fx;
2009 : Word16 f_low_fx, f_high_fx, g_low_fx, g_high_fx;
2010 : Word32 L_temp_fx, factor_fx;
2011 : Word32 en1_fx;
2012 : Word32 Lacc;
2013 : Word16 exp, tmp, expa, expb, fraca, fracb, scale;
2014 : Word32 L_tmp;
2015 0 : Word32 Lacc_max = 0;
2016 0 : move32();
2017 0 : Word16 expp = 0;
2018 0 : move16();
2019 : #ifndef ISSUE_1836_replace_overflow_libcom__remnant
2020 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
2021 : Flag Overflow = 0;
2022 : move32();
2023 : #endif
2024 : #endif
2025 :
2026 :
2027 0 : f_low_fx = mult( f1_fx, X_fx->lag_fx ); /* Q0 */
2028 0 : f_high_fx = mult( f2_fx, X_fx->lag_fx ); /* Q0 */
2029 0 : g_low_fx = mult( g1_fx, X_fx->lag_fx ); /* Q0 */
2030 0 : g_high_fx = mult( g2_fx, X_fx->lag_fx ); /* Q0 */
2031 0 : HalfLag_fx = s_min( f_high_fx, shl( X_fx->nH_fx, 1 ) );
2032 :
2033 0 : Lacc = L_deposit_l( 0 );
2034 0 : FOR( k = f_low_fx + 1; k <= HalfLag_fx; k++ )
2035 : {
2036 : #ifdef ISSUE_1836_replace_overflow_libcom__remnant
2037 0 : Lacc = L_mac0_sat( Lacc, X_fx->a_fx[k], X_fx->a_fx[k] ); /* 2*X1.Q */
2038 : #else
2039 : Lacc = L_mac0_o( Lacc, X_fx->a_fx[k], X_fx->a_fx[k], &Overflow ); /* 2*X1.Q */
2040 : #endif
2041 0 : Lacc_max = L_max( Lacc_max, Lacc );
2042 :
2043 0 : count = add( count, 1 );
2044 : }
2045 :
2046 0 : IF( GE_32( Lacc_max, 2147483647 /*1.Q31*/ ) )
2047 : {
2048 0 : tmp = sub( HalfLag_fx, f_low_fx );
2049 0 : exp = norm_s( tmp );
2050 0 : expp = sub( 15, exp );
2051 :
2052 0 : Lacc = L_deposit_l( 0 );
2053 0 : FOR( k = f_low_fx + 1; k <= HalfLag_fx; k++ )
2054 : {
2055 : #ifdef ISSUE_1836_replace_overflow_libcom__remnant
2056 0 : L_tmp = L_mult_sat( X_fx->a_fx[k], X_fx->a_fx[k] );
2057 0 : Lacc = L_add_sat( Lacc, L_shr( L_tmp, expp ) ); /* 2*X1.Q-expp */
2058 : #else
2059 : L_tmp = L_mult_o( X_fx->a_fx[k], X_fx->a_fx[k], &Overflow );
2060 : Lacc = L_add_o( Lacc, L_shr( L_tmp, expp ), &Overflow ); /* 2*X1.Q-expp */
2061 : #endif
2062 0 : count = add( count, 1 );
2063 : }
2064 : }
2065 :
2066 0 : if ( count <= 0 )
2067 : {
2068 0 : count = 1;
2069 0 : move16();
2070 : }
2071 :
2072 0 : exp = norm_s( count );
2073 0 : tmp = div_s( shl( 1, sub( 14, exp ) ), count ); /* 29 - exp */
2074 : #ifdef ISSUE_1836_replace_overflow_libcom__remnant
2075 0 : en1_fx = L_shl_sat( Mult_32_16( Lacc, tmp ), sub( exp, 14 ) );
2076 : #else
2077 : en1_fx = L_shl_o( Mult_32_16( Lacc, tmp ), sub( exp, 14 ), &Overflow );
2078 : #endif
2079 0 : test();
2080 0 : IF( en1_fx > 0 && en2_fx > 0 )
2081 : {
2082 : /* factor_fx = sqrt_divide_dp((Word40)en2_fx, en1_fx, sub(Qen2_fx, shl(X_fx->Q, 1)), &temp_fx,1); : Q(temp) */
2083 0 : expa = norm_l( en2_fx );
2084 0 : fraca = extract_h( L_shl( en2_fx, expa ) );
2085 0 : expa = sub( 30, add( expa, Qen2_fx ) );
2086 :
2087 :
2088 0 : expb = norm_l( en1_fx );
2089 : #ifdef ISSUE_1836_replace_overflow_libcom__remnant
2090 0 : fracb = round_fx_sat( L_shl( en1_fx, expb ) );
2091 : #else
2092 : fracb = round_fx_o( L_shl_o( en1_fx, expb, &Overflow ), &Overflow );
2093 : #endif
2094 0 : IF( GE_32( Lacc_max, 2147483647 /*1.Q31*/ ) )
2095 : {
2096 0 : expb = sub( 30, add( expb, sub( shl( X_fx->Q, 1 ), expp ) ) );
2097 : }
2098 : ELSE
2099 : {
2100 0 : expb = sub( 30, add( expb, shl( X_fx->Q, 1 ) ) );
2101 : }
2102 :
2103 0 : scale = shr( sub( fraca, fracb ), 15 );
2104 0 : fracb = shl( fracb, scale );
2105 0 : expb = sub( expb, scale );
2106 :
2107 0 : tmp = div_s( fracb, fraca );
2108 0 : exp = sub( expb, expa );
2109 :
2110 0 : L_tmp = Isqrt_lc( L_deposit_h( tmp ), &exp ); /* Q(31-exp) */
2111 :
2112 0 : IF( GE_32( Lacc_max, 2147483647 ) )
2113 : {
2114 0 : factor_fx = L_shr( L_tmp, add( 1, s_min( 2, expp ) ) );
2115 : }
2116 : ELSE
2117 : {
2118 0 : factor_fx = L_shr( L_tmp, 1 );
2119 : }
2120 : }
2121 : ELSE
2122 : {
2123 0 : factor_fx = L_deposit_l( 0 );
2124 : }
2125 :
2126 0 : HalfLag_fx = s_min( g_high_fx, shl( X_fx->nH_fx, 1 ) );
2127 0 : FOR( k = g_low_fx + 1; k <= HalfLag_fx; k++ )
2128 : {
2129 : /*L_temp_fx =(Word32)Mpy_32_16(extract_h(factor_fx),extract_l(factor_fx), X_fx->a_fx[k]); move32(); */ /* Q(temp+X1.Q-15) */
2130 0 : L_temp_fx = Mult_32_16( factor_fx, X_fx->a_fx[k] ); /* Q(temp+X1.Q-15) */
2131 : #ifdef ISSUE_1836_replace_overflow_libcom__remnant
2132 0 : X_fx->a_fx[k] = round_fx_sat( L_temp_fx ); /* Q(temp+X1.Q-15-16)=Q(temp+X1.Q-31); */
2133 : #else
2134 : X_fx->a_fx[k] = round_fx_o( L_temp_fx, &Overflow ); /* Q(temp+X1.Q-15-16)=Q(temp+X1.Q-31); */
2135 : #endif
2136 0 : move16();
2137 : }
2138 :
2139 0 : IF( GE_32( Lacc_max, 2147483647 /*1.Q31*/ ) )
2140 : {
2141 0 : *Qa_fx = sub( sub( X_fx->Q, add( 1, s_min( 2, expp ) ) ), exp );
2142 0 : move16();
2143 : }
2144 : ELSE
2145 : {
2146 0 : *Qa_fx = sub( sub( X_fx->Q, 1 ), exp );
2147 0 : move16();
2148 : }
2149 :
2150 0 : return en1_fx; /* Q(2*X1.Q) */
2151 : }
2152 : /*===================================================================*/
2153 : /* FUNCTION : cubicPhase_fx () */
2154 : /*-------------------------------------------------------------------*/
2155 : /* PURPOSE : Compute cubic phase track for WI synthesis */
2156 : /*-------------------------------------------------------------------*/
2157 : /* INPUT ARGUMENTS : */
2158 : /* _ (Word16) ph1_fx : initial phase, Q15 (normalized by 2pi) */
2159 : /* _ (Word16) ph2_fx : final phase, Q15 (normalized by 2pi) */
2160 : /* _ (Word16) L1 : previous pitch lag, Q0 */
2161 : /* _ (Word16) L2 : current pitch lag, Q0 */
2162 : /* _ (Word16) N : length of phase track, Q0 */
2163 : /*-------------------------------------------------------------------*/
2164 : /* OUTPUT ARGUMENTS : */
2165 : /* _ (Word32 []) phOut_fx : phase track, Q27 (normalized by 2pi) */
2166 : /*-------------------------------------------------------------------*/
2167 : /* INPUT/OUTPUT ARGUMENTS : */
2168 : /* _ None */
2169 : /*-------------------------------------------------------------------*/
2170 : /* RETURN ARGUMENTS : _ None. */
2171 : /*-------------------------------------------------------------------*/
2172 : /* CALLED FROM : TX/RX */
2173 : /*===================================================================*/
2174 : /* NOTE: This function outputs phase in (-1,1) */
2175 : /*===================================================================*/
2176 0 : static void cubicPhase_fx(
2177 : Word16 ph1_fx, /* i : phase offset */
2178 : Word16 ph2_fx, /* i : phase 2 */
2179 : const Word16 L1, /* i : previous lag */
2180 : const Word16 L2, /* i : current lag */
2181 : Word16 N, /* i : input length */
2182 : Word32 *phOut_fx /* o : cubic phase output */
2183 : )
2184 : {
2185 : Word16 n;
2186 : Word16 n2;
2187 : Word16 f1, f2; /* invert of L1, L2, Q19 */
2188 : Word16 factor, temp;
2189 : Word16 c0, c1, c2, c3; /* cubic polynomial coefficients */
2190 : /* Q33, Q27, Q19, Q15 respectively */
2191 : Word32 Ltemp1, Ltemp2, Ltemp3, Ltemp4, Ltemp;
2192 : Word16 tmp, exp;
2193 : Word32 Lacc;
2194 : Word16 expa, expb, fraca, fracb, scale;
2195 : Word32 L_tmp, L_tmp1;
2196 : Word16 num_flag, den_flag;
2197 : Word32 N2;
2198 : Word16 dbgshft;
2199 : #ifndef ISSUE_1836_replace_overflow_libcom__remnant
2200 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
2201 : Flag Overflow = 0;
2202 : move32();
2203 : #endif
2204 : #endif
2205 0 : num_flag = 0;
2206 0 : move16();
2207 0 : den_flag = 0;
2208 0 : move16();
2209 :
2210 0 : N = sub( N, L2 );
2211 :
2212 0 : exp = norm_s( L1 );
2213 0 : tmp = div_s( shl( 1, sub( 14, exp ) ), L1 );
2214 0 : L_tmp = L_shl( tmp, add( exp, 6 ) );
2215 0 : f1 = round_fx( L_tmp );
2216 :
2217 0 : exp = norm_s( L2 );
2218 0 : tmp = div_s( shl( 1, sub( 14, exp ) ), L2 );
2219 0 : L_tmp = L_shl( tmp, add( exp, 6 ) );
2220 0 : Ltemp4 = inverse_table[L2];
2221 0 : f2 = round_fx( L_tmp );
2222 :
2223 0 : c3 = ph1_fx;
2224 0 : move16(); /* c3 in Q15 */
2225 0 : c2 = f1;
2226 0 : move16(); /* c2 in Q19 */
2227 :
2228 0 : Ltemp1 = L_sub( ph1_fx, ph2_fx ); /* Ltemp1=ph1_fx-ph2_fx, Q15 */
2229 0 : Ltemp2 = L_add( f1, f2 ); /* Ltemp2=0.5*(f1+f2), Q20 */
2230 0 : temp = extract_l( Ltemp2 ); /* Q20 */
2231 :
2232 0 : IF( temp < 0 )
2233 : {
2234 0 : L_tmp1 = L_shl( L_add( 65536, temp ), 14 ); /* Q30 */
2235 0 : L_tmp = Mult_32_16( L_tmp1, N ); /* 30-15=15 */
2236 0 : Ltemp2 = L_shl( L_tmp, 1 );
2237 : }
2238 : ELSE
2239 : {
2240 0 : Ltemp2 = (Word32) L_mult0( N, temp ); /* Ltemp2=0.5*N*(f1+f2), Q20 */
2241 : }
2242 :
2243 0 : Ltemp1 = L_add( L_shl( Ltemp1, 5 ), Ltemp2 ); /* Ltemp1=ph1_fx - ph2_fx + 0.5*N*(f2+f1), Q16, Q20 */
2244 :
2245 0 : factor = round_fx( L_shr( Ltemp1, 4 ) ); /* factor in Q0 */
2246 :
2247 0 : c1 = sub( f2, f1 ); /* c1=f2-f1, Q19 */
2248 0 : Ltemp1 = L_sub( ph2_fx, ph1_fx ); /* Q15 */
2249 0 : Ltemp2 = L_mult( N, f1 ); /* Ltemp2=N*f1, Q20 */
2250 0 : Ltemp2 = L_sub( L_shl( L_deposit_h( factor ), 4 ), Ltemp2 ); /* Ltemp2=factor-N*f1, Q20 */
2251 0 : Ltemp1 = L_add( Ltemp2, L_shl( Ltemp1, 5 ) ); /* Ltemp1 in Q20 */
2252 :
2253 0 : IF( GT_16( N, 180 ) )
2254 : {
2255 0 : Ltemp2 = L_shl( L_mult0( N, N ), 14 );
2256 0 : Ltemp2 = L_shl( Mult_32_16( Ltemp2, N ), 1 );
2257 :
2258 : /* IF(N%2) */
2259 0 : if ( EQ_16( s_and( N, 1 ), 1 ) )
2260 : {
2261 0 : Ltemp2 = L_add( Ltemp2, 1 );
2262 : }
2263 : }
2264 : ELSE
2265 : {
2266 0 : Ltemp2 = L_shr( L_mult( N, N ), 1 );
2267 0 : Ltemp2 = L_mult0( N, extract_l( Ltemp2 ) ); /* Ltemp2=N^3 */
2268 : }
2269 0 : Ltemp3 = L_mult( N, c1 ); /* Q20 */
2270 0 : Ltemp3 = L_sub( Ltemp3, L_shl( Ltemp1, 1 ) ); /* Ltemp3=N*c1-2*Ltemp1, Q20 */
2271 :
2272 : #ifdef ISSUE_1836_replace_overflow_libcom__remnant
2273 0 : IF( GE_32( L_abs( Ltemp3 ), L_shl_sat( Ltemp2, 8 ) ) )
2274 : #else
2275 : IF( GE_32( L_abs( Ltemp3 ), L_shl_o( Ltemp2, 8, &Overflow ) ) )
2276 : #endif
2277 : {
2278 0 : Lacc = L_add( MIN_32, 0 );
2279 0 : if ( Ltemp3 > 0 )
2280 : {
2281 0 : Lacc = L_add( MAX_32, 0 );
2282 : }
2283 :
2284 0 : c0 = extract_h( Lacc ); /* c0 in Q33 */
2285 : }
2286 : ELSE
2287 : {
2288 0 : expa = norm_l( Ltemp3 );
2289 : #ifdef ISSUE_1836_replace_overflow_libcom__remnant
2290 0 : fraca = extract_h( L_shl( Ltemp3, expa ) );
2291 : #else
2292 : fraca = extract_h( L_shl_o( Ltemp3, expa, &Overflow ) );
2293 : #endif
2294 0 : expa = sub( 30, add( expa, 20 ) );
2295 0 : if ( fraca < 0 )
2296 : {
2297 0 : num_flag = 1;
2298 0 : move16();
2299 : }
2300 :
2301 0 : expb = norm_l( Ltemp2 );
2302 : #ifdef ISSUE_1836_replace_overflow_libcom__remnant
2303 0 : fracb = extract_h( L_shl( Ltemp2, expb ) );
2304 : #else
2305 : fracb = extract_h( L_shl_o( Ltemp2, expb, &Overflow ) );
2306 : #endif
2307 0 : expb = sub( 30, expb );
2308 0 : if ( fracb < 0 )
2309 : {
2310 0 : den_flag = 1;
2311 0 : move16();
2312 : }
2313 :
2314 0 : if ( num_flag )
2315 : {
2316 0 : fraca = negate( fraca );
2317 : }
2318 0 : if ( den_flag )
2319 : {
2320 0 : fracb = negate( fracb );
2321 : }
2322 0 : scale = shr( sub( fracb, fraca ), 15 );
2323 : #ifdef ISSUE_1836_replace_overflow_libcom__remnant
2324 0 : fraca = shl_sat( fraca, scale );
2325 : #else
2326 : fraca = shl_o( fraca, scale, &Overflow );
2327 : #endif
2328 0 : expa = sub( expa, scale );
2329 :
2330 0 : tmp = div_s( fraca, fracb ); /* 15-exp */
2331 0 : exp = sub( expa, expb );
2332 0 : test();
2333 0 : if ( num_flag && !den_flag )
2334 : {
2335 0 : tmp = negate( tmp );
2336 : }
2337 0 : test();
2338 0 : if ( den_flag && !num_flag )
2339 : {
2340 0 : tmp = negate( tmp );
2341 : }
2342 :
2343 : #ifdef ISSUE_1836_replace_overflow_libcom__remnant
2344 0 : Lacc = L_shl_sat( tmp, add( exp, 34 ) );
2345 0 : Lacc = L_add_sat( Lacc, 0x08000 );
2346 : #else
2347 : Lacc = L_shl_o( tmp, add( exp, 34 ), &Overflow );
2348 : Lacc = L_add_o( Lacc, 0x08000, &Overflow );
2349 : #endif
2350 0 : c0 = extract_h( Lacc ); /* c0 in Q33 */
2351 : }
2352 :
2353 0 : Ltemp1 = L_mult( N, N ); /* Ltemp1=2*N*N */
2354 0 : Ltemp1 = L_add( Ltemp1, L_shr( Ltemp1, 1 ) ); /* Ltemp1=3*N*N, max is 3*140*140 */
2355 :
2356 : /* patch added for time warping support, where N can be more than 140 */
2357 0 : dbgshft = norm_l( Ltemp1 );
2358 0 : Ltemp1 = L_shl( Ltemp1, dbgshft );
2359 0 : temp = extract_h( Ltemp1 );
2360 0 : Ltemp1 = (Word32) L_shl( (Word32) L_mult0( c0, temp ), sub( 16, dbgshft ) ); /* Ltemp1=3*N*N*c0, Q33 */
2361 : /* Patch end */
2362 :
2363 0 : num_flag = den_flag = 0;
2364 0 : move16();
2365 0 : move16();
2366 0 : Ltemp1 = L_sub( L_shr( L_deposit_h( c1 ), 2 ), Ltemp1 ); /* Ltemp1=c1-3*N*N*c0, Q33 */
2367 :
2368 0 : expa = norm_l( Ltemp1 );
2369 0 : fraca = extract_h( L_shl( Ltemp1, expa ) );
2370 0 : expa = sub( 30, add( expa, 33 ) );
2371 0 : if ( fraca < 0 )
2372 : {
2373 0 : num_flag = 1;
2374 0 : move16();
2375 : }
2376 :
2377 0 : expb = norm_l( N );
2378 0 : fracb = extract_h( L_shl( N, expb ) );
2379 0 : expb = sub( 30, expb );
2380 0 : if ( fracb < 0 )
2381 : {
2382 0 : den_flag = 1;
2383 0 : move16();
2384 : }
2385 :
2386 0 : if ( num_flag )
2387 : {
2388 0 : fraca = negate( fraca );
2389 : }
2390 0 : if ( den_flag )
2391 : {
2392 0 : fracb = negate( fracb );
2393 : }
2394 0 : scale = shr( sub( fracb, fraca ), 15 );
2395 0 : fraca = shl( fraca, scale );
2396 0 : expa = sub( expa, scale );
2397 :
2398 0 : tmp = div_s( fraca, fracb ); /* 15-exp */
2399 0 : exp = sub( expa, expb );
2400 0 : test();
2401 0 : if ( num_flag && !den_flag )
2402 : {
2403 0 : tmp = negate( tmp );
2404 : }
2405 0 : test();
2406 0 : if ( den_flag && !num_flag )
2407 : {
2408 0 : tmp = negate( tmp );
2409 : }
2410 :
2411 0 : Lacc = L_shl( tmp, add( exp, 27 ) );
2412 0 : Lacc = L_add( Lacc, 0x08000 );
2413 0 : c1 = extract_h( Lacc ); /* c1 in Q27 */
2414 :
2415 :
2416 : /* Computation of the phase value at each sample point */
2417 : /* ph[n]= c0*n^3+c1*n^2+c2*n+c3, Q15 */
2418 0 : phOut_fx[0] = L_shl( ph1_fx, 11 ); /* Q27 */
2419 0 : move32();
2420 :
2421 0 : IF( LT_16( N, 181 ) )
2422 : {
2423 0 : FOR( n = 1; n < N; n++ )
2424 : {
2425 : /* phOut_fx[n] = _POLY3(n,coef) ; */
2426 0 : n2 = i_mult2( n, n ); /* n2=n^2 */
2427 0 : Ltemp3 = (Word32) L_mult0( n, (UNS_Word16) n2 ); /* Ltemp3=n^3 */
2428 :
2429 0 : Ltemp3 = L_shl( Mult_32_16( L_shl( Ltemp3, 7 ), c0 ), 2 ); /* Ltemp3=c0*n^3, Q27 */
2430 0 : Ltemp2 = (Word32) L_mult0( c1, (UNS_Word16) n2 ); /* Ltemp2=c1*n^2, Q27 */
2431 0 : Ltemp1 = L_shl( L_mult( c2, n ), 7 ); /* Ltemp1=c2*n, Q27 */
2432 :
2433 0 : Ltemp = L_shl( (Word32) c3, 12 ); /* Q27 */
2434 0 : Ltemp = L_add( Ltemp1, Ltemp ); /* Q27 */
2435 0 : Ltemp = L_add( Ltemp2, Ltemp ); /* Q27 */
2436 0 : Ltemp = L_add( Ltemp3, Ltemp ); /* Q27 */
2437 :
2438 0 : phOut_fx[n] = Ltemp;
2439 0 : move32(); /* Q27 */
2440 : }
2441 : }
2442 : ELSE
2443 : {
2444 :
2445 0 : FOR( n = 1; n < 181; n++ )
2446 : {
2447 : /* phOut_fx[n] = _POLY3(n,coef) ; */
2448 0 : n2 = i_mult2( n, n ); /* n2=n^2 */
2449 0 : Ltemp3 = (Word32) L_mult0( n, (UNS_Word16) n2 ); /* Ltemp3=n^3 */
2450 :
2451 0 : Ltemp3 = L_shl( Mult_32_16( L_shl( Ltemp3, 7 ), c0 ), 2 ); /* Ltemp3=c0*n^3, Q27 */
2452 0 : Ltemp2 = (Word32) L_mult0( c1, (UNS_Word16) n2 ); /* Ltemp2=c1*n^2, Q27 */
2453 0 : Ltemp1 = L_shl( L_mult( c2, n ), 7 ); /* Ltemp1=c2*n, Q27 */
2454 :
2455 0 : Ltemp = L_shl( (Word32) c3, 12 ); /* Q27 */
2456 0 : Ltemp = L_add( Ltemp1, Ltemp ); /* Q27 */
2457 0 : Ltemp = L_add( Ltemp2, Ltemp ); /* Q27 */
2458 0 : Ltemp = L_add( Ltemp3, Ltemp ); /* Q27 */
2459 :
2460 0 : phOut_fx[n] = Ltemp;
2461 0 : move32(); /* Q27 */
2462 : }
2463 :
2464 0 : FOR( n = 181; n < N; n++ )
2465 : {
2466 : /* phOut_fx[n] = _POLY3(n,coef) ; */
2467 0 : N2 = L_shl( L_mult0( n, n ), 14 );
2468 0 : Ltemp3 = L_shl( Mult_32_16( N2, n ), 1 );
2469 :
2470 0 : if ( EQ_16( s_and( N, 1 ), 1 ) )
2471 : {
2472 0 : Ltemp3 = L_add( Ltemp3, 1 );
2473 : }
2474 :
2475 : #ifdef ISSUE_1836_replace_overflow_libcom__remnant
2476 0 : Ltemp3 = L_shl_sat( Mult_32_16( L_shl_sat( Ltemp3, 7 ), c0 ), 2 ); /* Ltemp3=c0*n^3, Q27 */ //?sat
2477 : #else
2478 : Ltemp3 = L_shl_o( Mult_32_16( L_shl_o( Ltemp3, 7, &Overflow ), c0 ), 2, &Overflow ); /* Ltemp3=c0*n^3, Q27 */
2479 : #endif
2480 0 : Ltemp2 = L_shl( Mult_32_16( N2, c1 ), 1 );
2481 : /* Ltemp2 = (Word32)L_mult_su(c1,(UNS_Word16)n2); : Ltemp2=c1*n^2, Q27 */
2482 0 : Ltemp1 = L_shl( L_mult( c2, n ), 7 ); /* Ltemp1=c2*n, Q27 */
2483 :
2484 0 : Ltemp = L_shl( (Word32) c3, 12 ); /* Q27 */
2485 0 : Ltemp = L_add( Ltemp1, Ltemp ); /* Q27 */
2486 0 : Ltemp = L_add( Ltemp2, Ltemp ); /* Q27 */
2487 0 : Ltemp = L_add( Ltemp3, Ltemp ); /* Q27 */
2488 :
2489 0 : phOut_fx[n] = Ltemp;
2490 0 : move32(); /* Q27 */
2491 : }
2492 : }
2493 :
2494 0 : tmp = add( N, L2 );
2495 0 : FOR( ; n < tmp; n++ )
2496 : {
2497 0 : Ltemp = L_add( phOut_fx[n - 1], Ltemp4 ); /* Q27 */
2498 0 : phOut_fx[n] = Ltemp;
2499 0 : move32(); /* Q27 */
2500 : }
2501 0 : return;
2502 : }
2503 :
2504 : /*===================================================================*/
2505 : /* FUNCTION : DTFS_to_erb_fx () */
2506 : /*-------------------------------------------------------------------*/
2507 : /* PURPOSE : Convert harmonics to erb bands */
2508 : /*-------------------------------------------------------------------*/
2509 : /* INPUT ARGUMENTS : */
2510 : /* _ (struct DTFS_STRUCTURE) X_fx : prototype in polar domain */
2511 : /* (Word16) lag_fx: length of prototype in time domain*/
2512 : /* (Word16 []) a_fx: amplitude, normalized */
2513 : /* (Word16) Q_fx: norm factor of a */
2514 : /*-------------------------------------------------------------------*/
2515 : /* OUTPUT ARGUMENTS : */
2516 : /* _ (Word16 []) out_fx : erb output, Q13 */
2517 : /*-------------------------------------------------------------------*/
2518 : /* INPUT/OUTPUT ARGUMENTS : */
2519 : /* _ None */
2520 : /*-------------------------------------------------------------------*/
2521 : /* RETURN ARGUMENTS : _ None. */
2522 : /*-------------------------------------------------------------------*/
2523 : /* CALLED FROM : TX/RX */
2524 : /*===================================================================*/
2525 0 : void DTFS_to_erb_fx(
2526 : const DTFS_STRUCTURE X_fx, /* i : DTFS input */
2527 : Word16 *out_fx /* o : ERB output */
2528 : )
2529 :
2530 : {
2531 : Word16 num_erb_fx;
2532 : Word16 i, j, n, count[NUM_ERB_WB];
2533 : Word16 diff_fx;
2534 : Word32 sum_a_fx[NUM_ERB_WB], Ltemp_fx, L_tmp, L_temp;
2535 : Word16 exp, tmp;
2536 : Word16 expa, expb, fraca, fracb, scale;
2537 : #ifndef ISSUE_1836_replace_overflow_libcom__remnant
2538 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
2539 : Flag Overflow = 0;
2540 : move32();
2541 : #endif
2542 : #endif
2543 0 : const Word16 *erb_fx = NULL;
2544 0 : num_erb_fx = NUM_ERB_NB;
2545 0 : move16();
2546 :
2547 0 : test();
2548 0 : test();
2549 0 : IF( EQ_16( X_fx.upper_cut_off_freq_fx, 0x02800 ) || EQ_16( X_fx.upper_cut_off_freq_fx, 4000 ) ) /* 0x2800=0.3125 in Q15 (4000Hz) */
2550 : {
2551 0 : num_erb_fx = NUM_ERB_NB;
2552 0 : move16();
2553 0 : erb_fx = &( erb_NB_fx[0] );
2554 0 : move16();
2555 : }
2556 0 : ELSE IF( EQ_16( X_fx.upper_cut_off_freq_fx, 0x04000 ) || EQ_16( X_fx.upper_cut_off_freq_fx, 6400 ) ) /* 0x4000=0.5 in Q15 (6400Hz) */
2557 : {
2558 0 : num_erb_fx = NUM_ERB_WB;
2559 0 : move16();
2560 0 : erb_fx = &( erb_WB_fx[0] );
2561 0 : move16();
2562 : }
2563 :
2564 :
2565 0 : FOR( i = 0; i < num_erb_fx; i++ )
2566 : {
2567 :
2568 :
2569 0 : count[i] = 0;
2570 0 : move16();
2571 0 : sum_a_fx[i] = L_deposit_l( 0 );
2572 0 : move32();
2573 : }
2574 :
2575 0 : exp = norm_s( X_fx.lag_fx );
2576 0 : tmp = div_s( shl( 1, sub( 14, exp ) ), X_fx.lag_fx ); /* 29-exp */
2577 :
2578 0 : L_tmp = L_shl( tmp, add( exp, 6 ) );
2579 0 : diff_fx = round_fx( L_tmp );
2580 :
2581 0 : n = s_min( shr( X_fx.lag_fx, 1 ), X_fx.nH_fx );
2582 :
2583 0 : j = 0;
2584 0 : move16();
2585 0 : FOR( i = 0; i <= n; i++ )
2586 : {
2587 0 : Ltemp_fx = L_mult( diff_fx, i ); /* Ltemp=i*diff, Q20 */
2588 0 : FOR( ; j < num_erb_fx; j++ )
2589 : {
2590 0 : IF( LT_32( Ltemp_fx, L_shl( erb_fx[j + 1], 5 ) ) )
2591 : {
2592 0 : sum_a_fx[j] = L_add( sum_a_fx[j], L_deposit_l( X_fx.a_fx[i] ) );
2593 0 : move32(); /* X_fx.Q */
2594 0 : count[j] = add( count[j], 1 );
2595 0 : move16();
2596 0 : BREAK;
2597 : }
2598 : }
2599 : }
2600 : /* Make output in Q13 */
2601 0 : n = sub( 29, X_fx.Q );
2602 0 : j = negate( X_fx.Q );
2603 :
2604 :
2605 0 : FOR( i = 0; i < num_erb_fx; i++ )
2606 : {
2607 : #ifdef ISSUE_1836_replace_overflow_libcom__remnant
2608 0 : out_fx[i] = round_fx_sat( L_shl_sat( sum_a_fx[i], n ) ); /* Q13 */ //?�sat
2609 : #else
2610 : out_fx[i] = round_fx_o( L_shl_o( sum_a_fx[i], n, &Overflow ), &Overflow ); /* Q13 */
2611 : #endif
2612 0 : move16();
2613 0 : IF( GT_16( count[i], 1 ) )
2614 : {
2615 0 : IF( sum_a_fx[i] < 0 )
2616 : {
2617 0 : L_temp = L_negate( sum_a_fx[i] );
2618 : }
2619 : ELSE
2620 : {
2621 0 : L_temp = L_add( sum_a_fx[i], 0 );
2622 : }
2623 :
2624 0 : expb = norm_l( L_temp );
2625 0 : fracb = round_fx( L_shl( L_temp, expb ) );
2626 0 : expb = sub( 30, add( expb, X_fx.Q ) );
2627 :
2628 :
2629 0 : expa = norm_l( count[i] );
2630 0 : fraca = extract_h( L_shl( count[i], expa ) );
2631 0 : expa = sub( 30, expa );
2632 :
2633 0 : scale = shr( sub( fraca, fracb ), 15 );
2634 0 : fracb = shl( fracb, scale );
2635 0 : expb = sub( expb, scale );
2636 :
2637 0 : tmp = div_s( fracb, fraca );
2638 0 : exp = sub( expb, expa );
2639 0 : L_tmp = L_shl_sat( tmp, add( exp, 14 ) );
2640 0 : out_fx[i] = round_fx_sat( L_tmp );
2641 0 : move16();
2642 : }
2643 : }
2644 0 : return;
2645 : }
2646 : /*===================================================================*/
2647 : /* FUNCTION : erb_slot_fx () */
2648 : /*-------------------------------------------------------------------*/
2649 : /* PURPOSE : Allocate harmonics in ERB bins */
2650 : /*-------------------------------------------------------------------*/
2651 : /* INPUT ARGUMENTS : */
2652 : /* _ (Word16) lag_fx : pitch lag, Q0 */
2653 : /*-------------------------------------------------------------------*/
2654 : /* OUTPUT ARGUMENTS : */
2655 : /* _ (Word16 []) out_fx : number of harmonics in the ERB bins, Q0 */
2656 : /* _ (Word16 []) mfreq_fx : frequency bounds of the ERB bins, Q15 */
2657 : /*-------------------------------------------------------------------*/
2658 : /* INPUT/OUTPUT ARGUMENTS : */
2659 : /* _ None */
2660 : /*-------------------------------------------------------------------*/
2661 : /* RETURN ARGUMENTS : _ None. */
2662 : /*-------------------------------------------------------------------*/
2663 : /* CALLED FROM : TX/RX */
2664 : /*===================================================================*/
2665 : /* NOTE: Frequency is normalized by 12800, i.e. 1=12800Hz */
2666 : /*===================================================================*/
2667 0 : void erb_slot_fx(
2668 : Word16 lag_fx, /* i : input lag */
2669 : Word16 *out_fx, /* o : ERB slots */
2670 : Word16 *mfreq_fx, /* o : ERB frequencies */
2671 : Word16 num_erb_fx /* i : number of ERBs */
2672 : )
2673 : {
2674 : Word16 i, j, n;
2675 : Word16 diff_fx;
2676 : Word16 upper_cut_off_freq_fx;
2677 : Word32 Ltemp_fx;
2678 : Word32 mf_fx[NUM_ERB_WB];
2679 : Word16 nH_band_fx;
2680 : Word16 exp, tmp;
2681 : Word32 L_tmp1, L_tmp;
2682 : Word16 fraca, fracb, expa, expb, scale;
2683 : #ifndef ISSUE_1836_replace_overflow_libcom__remnant
2684 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
2685 : Flag Overflow = 0;
2686 : move32();
2687 : #endif
2688 : #endif
2689 0 : const Word16 *erb_fx = NULL; /*move16(); */
2690 :
2691 0 : upper_cut_off_freq_fx = 4000;
2692 0 : move16();
2693 :
2694 0 : IF( EQ_16( num_erb_fx, NUM_ERB_NB ) )
2695 : {
2696 0 : upper_cut_off_freq_fx = 4000;
2697 0 : move16();
2698 0 : erb_fx = &( erb_NB_fx[0] );
2699 : }
2700 0 : ELSE IF( EQ_16( num_erb_fx, NUM_ERB_WB ) )
2701 : {
2702 0 : upper_cut_off_freq_fx = 6400;
2703 0 : move16();
2704 0 : erb_fx = &( erb_WB_fx[0] );
2705 : }
2706 :
2707 0 : exp = norm_s( lag_fx );
2708 0 : tmp = div_s( shl( 1, sub( 14, exp ) ), lag_fx ); /* Q29-exp */
2709 0 : L_tmp1 = L_mult( 12800, tmp ); /* Q(30-exp) */
2710 0 : diff_fx = extract_h( L_shl( L_tmp1, sub( exp, 14 ) ) ); /* Q0 */
2711 :
2712 0 : exp = norm_s( diff_fx );
2713 0 : tmp = div_s( shl( 1, sub( 14, exp ) ), diff_fx ); /* Q29-exp */
2714 0 : L_tmp1 = L_mult( upper_cut_off_freq_fx, tmp ); /* Q(30-exp) */
2715 0 : nH_band_fx = round_fx( L_shl( L_tmp1, sub( exp, 14 ) ) ); /* Q0 */
2716 :
2717 0 : FOR( i = 0; i < num_erb_fx; i++ )
2718 : {
2719 0 : out_fx[i] = 0;
2720 0 : move16();
2721 0 : mf_fx[i] = 0;
2722 0 : move16();
2723 : }
2724 :
2725 :
2726 0 : L_tmp = L_mult0( diff_fx, nH_band_fx ); /* Q0 */
2727 :
2728 :
2729 0 : IF( GE_32( L_sub( upper_cut_off_freq_fx, L_tmp ), L_deposit_l( diff_fx ) ) ) /* Q0 compare */
2730 : {
2731 0 : nH_band_fx = add( nH_band_fx, 1 ); /* Q0 */
2732 : }
2733 :
2734 0 : n = s_min( shr( lag_fx, 1 ), nH_band_fx );
2735 0 : exp = norm_s( lag_fx );
2736 0 : tmp = div_s( shl( 1, sub( 14, exp ) ), lag_fx ); /* Q29-exp */
2737 0 : L_tmp = L_shl( tmp, add( exp, 6 ) );
2738 0 : diff_fx = round_fx( L_tmp );
2739 :
2740 0 : j = 0;
2741 0 : move16();
2742 0 : FOR( i = 0; i <= n; i++ )
2743 : {
2744 0 : Ltemp_fx = L_mult( diff_fx, i ); /* Ltemp=i*diff, Q20 */
2745 : /* freq=round32_16(L_shl(Ltemp,11)); : freq=i*diff, Q15 */
2746 :
2747 0 : IF( EQ_16( num_erb_fx, NUM_ERB_NB ) )
2748 : {
2749 0 : Ltemp_fx = L_min( Ltemp_fx, 0x050000 ); /* 0x50000=0.3125 in Q20 (4000Hz) */
2750 : }
2751 0 : ELSE IF( EQ_16( num_erb_fx, NUM_ERB_WB ) )
2752 : {
2753 0 : Ltemp_fx = L_min( Ltemp_fx, 0x080000 ); /* 0x80000=0.5 in Q20 (6400Hz) */
2754 : }
2755 :
2756 0 : FOR( ; j < num_erb_fx; j++ )
2757 : {
2758 0 : IF( LT_32( Ltemp_fx, L_shl( erb_fx[j + 1], 5 ) ) )
2759 : {
2760 0 : mf_fx[j] = L_add( mf_fx[j], Ltemp_fx );
2761 0 : move32();
2762 0 : out_fx[j] = add( out_fx[j], 1 );
2763 0 : move16();
2764 0 : BREAK;
2765 : }
2766 : }
2767 : }
2768 0 : FOR( j = 0; j < num_erb_fx; j++ )
2769 : {
2770 : #ifdef ISSUE_1836_replace_overflow_libcom__remnant
2771 0 : mfreq_fx[j] = round_fx_sat( L_shl_sat( mf_fx[j], 11 ) ); /* Q15 */
2772 0 : move16();
2773 0 : IF( GT_16( out_fx[j], 1 ) )
2774 : {
2775 0 : expb = norm_l( mf_fx[j] );
2776 0 : fracb = round_fx_sat( L_shl_sat( mf_fx[j], expb ) );
2777 0 : expb = sub( 30, add( expb, 20 ) );
2778 :
2779 :
2780 0 : expa = norm_l( out_fx[j] );
2781 0 : fraca = extract_h( L_shl( out_fx[j], expa ) );
2782 0 : expa = sub( 30, expa );
2783 :
2784 0 : scale = shr( sub( fraca, fracb ), 15 );
2785 0 : fracb = shl( fracb, scale );
2786 0 : expb = sub( expb, scale );
2787 :
2788 0 : tmp = div_s( fracb, fraca );
2789 0 : exp = sub( expb, expa );
2790 0 : L_tmp = L_shl_sat( tmp, add( exp, 16 ) );
2791 :
2792 0 : mfreq_fx[j] = round_fx_sat( L_tmp );
2793 0 : move16();
2794 : }
2795 : #else
2796 : mfreq_fx[j] = round_fx_o( L_shl_o( mf_fx[j], 11, &Overflow ), &Overflow ); /* Q15 */
2797 : move16();
2798 : IF( GT_16( out_fx[j], 1 ) )
2799 : {
2800 : expb = norm_l( mf_fx[j] );
2801 : fracb = round_fx_o( L_shl_o( mf_fx[j], expb, &Overflow ), &Overflow );
2802 : expb = sub( 30, add( expb, 20 ) );
2803 :
2804 :
2805 : expa = norm_l( out_fx[j] );
2806 : fraca = extract_h( L_shl_o( out_fx[j], expa, &Overflow ) );
2807 : expa = sub( 30, expa );
2808 :
2809 : scale = shr( sub( fraca, fracb ), 15 );
2810 : fracb = shl( fracb, scale );
2811 : expb = sub( expb, scale );
2812 :
2813 : tmp = div_s( fracb, fraca );
2814 : exp = sub( expb, expa );
2815 : L_tmp = L_shl_o( tmp, add( exp, 16 ), &Overflow );
2816 :
2817 : mfreq_fx[j] = round_fx_o( L_tmp, &Overflow );
2818 : move16();
2819 : }
2820 : #endif
2821 : }
2822 0 : return;
2823 : }
2824 : /*===================================================================*/
2825 : /* FUNCTION : DTFS_erb_inv_fx () */
2826 : /*-------------------------------------------------------------------*/
2827 : /* PURPOSE : Convert erb into harmonics */
2828 : /*-------------------------------------------------------------------*/
2829 : /* INPUT ARGUMENTS : */
2830 : /* _ (Word16 []) in_fx : erb output, Q13 */
2831 : /* _ (Word16 []) slot_fx : number of harmonics in the ERB bins, Q0 */
2832 : /* _ (Word16 []) mfreq_fx : frequency bounds of the ERB bins, Q15 */
2833 : /* _ (struct DTFS_STRUCTURE) (Word16) lag_fx: length of */
2834 : /* prototype in time domain */
2835 : /*-------------------------------------------------------------------*/
2836 : /* OUTPUT ARGUMENTS : */
2837 : /* _ (struct DTFS_STRUCTURE) : prototype in polar domain */
2838 : /* (Word16 []) a_fx: amplitude, normalized */
2839 : /* (Word16) Q: norm factor of a */
2840 : /*-------------------------------------------------------------------*/
2841 : /* INPUT/OUTPUT ARGUMENTS : */
2842 : /* _ None */
2843 : /*-------------------------------------------------------------------*/
2844 : /* RETURN ARGUMENTS : _ None. */
2845 : /*-------------------------------------------------------------------*/
2846 : /* CALLED FROM : TX/RX */
2847 : /*===================================================================*/
2848 :
2849 0 : void DTFS_erb_inv_fx(
2850 : Word16 *in_fx, /* i : ERB inpt */
2851 : Word16 *slot_fx, /* i : ERB slots filled based on lag */
2852 : Word16 *mfreq_fx, /* i : erb frequence edges */
2853 : DTFS_STRUCTURE *X_fx, /* o : DTFS after erb-inv */
2854 : Word16 num_erb_fx /* i : Number of ERB bands */
2855 : )
2856 : {
2857 :
2858 0 : Word16 i, j, m_fx = 0, n, HalfLag_fx;
2859 : Word16 diff_fx; /* 1/lag, Q19 */
2860 0 : Word16 d1, d2, q[MAXLAG_WI], min_q = 0;
2861 : Word16 d1h, d1l, d2h, d2l;
2862 : Word16 freq_fx, f_fx[NUM_ERB_WB + 2], amp_fx[NUM_ERB_WB + 2];
2863 0 : Word16 upper_cut_off_freq_fx = 0;
2864 : Word32 Ltemp_fx, Ltemp2_fx;
2865 : Word32 Lacc_fx;
2866 : Word16 exp, tmp;
2867 0 : move16();
2868 0 : move16();
2869 0 : move16();
2870 : #ifndef ISSUE_1836_replace_overflow_libcom__remnant
2871 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
2872 : Flag Overflow = 0;
2873 : move32();
2874 : #endif
2875 : #endif
2876 :
2877 0 : IF( EQ_16( num_erb_fx, NUM_ERB_NB ) )
2878 : {
2879 0 : upper_cut_off_freq_fx = 0x02800;
2880 0 : move16(); /* 0x2800=0.3125 in Q15 (4000Hz) */
2881 : }
2882 0 : ELSE IF( EQ_16( num_erb_fx, NUM_ERB_WB ) )
2883 : {
2884 0 : upper_cut_off_freq_fx = 0x04000;
2885 0 : move16(); /* 0x4000=0.5 in Q15 (6400Hz) */
2886 : }
2887 :
2888 0 : f_fx[m_fx] = 0;
2889 0 : move16();
2890 0 : amp_fx[m_fx] = 0;
2891 0 : move16();
2892 0 : m_fx = add( m_fx, 1 );
2893 :
2894 0 : FOR( i = 0; i < num_erb_fx; i++ )
2895 : {
2896 0 : IF( slot_fx[i] != 0 )
2897 : {
2898 0 : f_fx[m_fx] = mfreq_fx[i];
2899 0 : move16();
2900 0 : amp_fx[m_fx] = in_fx[i];
2901 0 : move16();
2902 0 : m_fx = add( m_fx, 1 );
2903 : }
2904 : }
2905 0 : f_fx[m_fx] = upper_cut_off_freq_fx;
2906 0 : move16();
2907 0 : amp_fx[m_fx] = 0;
2908 0 : move16();
2909 0 : m_fx = add( m_fx, 1 );
2910 :
2911 0 : exp = norm_s( X_fx->lag_fx );
2912 0 : tmp = div_s( shl( 1, sub( 14, exp ) ), X_fx->lag_fx ); /* 29-exp */
2913 0 : diff_fx = shl( tmp, sub( exp, 10 ) ); /* Q19 */
2914 :
2915 0 : min_q = EVS_SW_MAX;
2916 0 : move16();
2917 0 : X_fx->a_fx[0] = 0;
2918 0 : move16();
2919 :
2920 0 : HalfLag_fx = s_min( shr( X_fx->lag_fx, 1 ), X_fx->nH_fx );
2921 :
2922 0 : j = 1;
2923 0 : move16();
2924 0 : FOR( i = 1; i <= HalfLag_fx; i++ )
2925 : {
2926 0 : Ltemp_fx = L_mult( diff_fx, i ); /* Ltemp=i*diff, Q20 */
2927 0 : freq_fx = round_fx( L_shl( Ltemp_fx, 11 ) ); /* Q15 */
2928 :
2929 0 : freq_fx = s_min( freq_fx, upper_cut_off_freq_fx ); /* 0x4000 is 0.5 in Q15 */
2930 :
2931 0 : FOR( ; j < m_fx; j++ )
2932 : {
2933 0 : d1 = sub( f_fx[j], freq_fx );
2934 :
2935 0 : IF( d1 >= 0 )
2936 : {
2937 0 : d2 = sub( freq_fx, f_fx[j - 1] );
2938 0 : Ltemp_fx = L_mac( L_mult( amp_fx[j], d2 ), amp_fx[j - 1], d1 ); /* Q29 */
2939 0 : d2 = sub( f_fx[j], f_fx[j - 1] ); /* Q15 */
2940 : /* Ltemp2_fx=invert_dp((Word40)d2, 4, &n,1); : Ltemp2=1/d2, Q(61-15-n) */
2941 0 : exp = norm_s( d2 );
2942 0 : tmp = div_s( shl( 1, sub( 14, exp ) ), d2 ); /* 29-exp */
2943 : /* L_tmp = L_shr(tmp,8); */
2944 0 : Ltemp2_fx = L_shl( tmp, 16 );
2945 0 : n = add( exp, 16 );
2946 :
2947 0 : d1h = extract_h( Ltemp_fx );
2948 0 : d1l = extract_l( Ltemp_fx );
2949 0 : d2h = extract_h( Ltemp2_fx );
2950 0 : d2l = extract_l( Ltemp2_fx );
2951 0 : Ltemp_fx = (Word32) L_mult0( d1h, d2l );
2952 0 : Lacc_fx = L_mac0( (Word32) Ltemp_fx, d2h, d1l );
2953 0 : Ltemp_fx = L_add( (Word32) L_shr( Lacc_fx, 15 ), L_mult( d1h, d2h ) ); /* 46-n+29-31 */
2954 0 : d2h = norm_l( Ltemp_fx ); /* d2h is 0 IF Ltemp=0 */
2955 0 : if ( Ltemp_fx == 0 )
2956 : {
2957 0 : d2h = 31;
2958 0 : move16();
2959 : }
2960 : #ifdef ISSUE_1836_replace_overflow_libcom__remnant
2961 0 : X_fx->a_fx[i] = round_fx_sat( L_shl_sat( Ltemp_fx, d2h ) ); /* Q(28-n+d2h) */
2962 : #else
2963 : X_fx->a_fx[i] = round_fx_o( L_shl_o( Ltemp_fx, d2h, &Overflow ), &Overflow ); /* Q(28-n+d2h) */
2964 : #endif
2965 0 : move16();
2966 0 : q[i] = add( sub( 28, n ), d2h );
2967 0 : move16();
2968 0 : min_q = s_min( min_q, q[i] );
2969 :
2970 0 : BREAK;
2971 : }
2972 : }
2973 : }
2974 : /* block normalize a[i] */
2975 0 : FOR( i = 1; i <= HalfLag_fx; i++ )
2976 : {
2977 0 : X_fx->a_fx[i] = shl( X_fx->a_fx[i], sub( min_q, q[i] ) );
2978 0 : move16();
2979 : }
2980 :
2981 0 : X_fx->Q = min_q;
2982 0 : move16();
2983 0 : return;
2984 : }
2985 :
2986 :
2987 : /*===================================================================*/
2988 : /* FUNCTION : erb_add_fx () */
2989 : /*-------------------------------------------------------------------*/
2990 : /* PURPOSE : Reconstruct current erb amplitude for QPPP */
2991 : /*-------------------------------------------------------------------*/
2992 : /* INPUT ARGUMENTS : */
2993 : /* _ (Word16) pl_fx : previous pitch lag, Q0 */
2994 : /* _ (Word16) l_fx : current pitch lag, Q0 */
2995 : /* _ (Word16 []) prev_erb_fx : Previous erb amplitude, Q13 */
2996 : /* _ (Word16 []) index_fx: quantized differential erb index */
2997 : /*-------------------------------------------------------------------*/
2998 : /* OUTPUT ARGUMENTS : */
2999 : /* _ (Word16 []) curr_erb_fx : Current erb amplitude, Q13 */
3000 : /*-------------------------------------------------------------------*/
3001 : /* INPUT/OUTPUT ARGUMENTS : */
3002 : /* _ None */
3003 : /*-------------------------------------------------------------------*/
3004 : /* RETURN ARGUMENTS : _ None. */
3005 : /*-------------------------------------------------------------------*/
3006 : /* CALLED FROM : TX/RX */
3007 : /*===================================================================*/
3008 0 : void erb_add_fx(
3009 : Word16 *curr_erb_fx, /* i/o: current ERB */
3010 : Word16 l_fx, /* i : current lag */
3011 : const Word16 *prev_erb_fx, /* i : previous ERB */
3012 : Word16 pl_fx, /* i : previous lag */
3013 : const Word16 *index_fx, /* i : ERB index */
3014 : Word16 num_erb_fx /* i : number of ERBs */
3015 : )
3016 : {
3017 : Word16 i;
3018 : Word16 pslot_fx[NUM_ERB_WB], cslot_fx[NUM_ERB_WB], t_prev_erb_fx[NUM_ERB_WB];
3019 : Word16 tmp_fx, tmp2_fx, tmp_loop;
3020 0 : const Word16 *AmpCB1_fx = NULL; /*move16(); */
3021 :
3022 0 : IF( EQ_16( num_erb_fx, NUM_ERB_NB ) )
3023 : {
3024 0 : AmpCB1_fx = AmpCB1_NB_fx;
3025 0 : move16();
3026 : }
3027 0 : ELSE IF( EQ_16( num_erb_fx, NUM_ERB_WB ) )
3028 : {
3029 0 : AmpCB1_fx = AmpCB1_WB_fx;
3030 0 : move16();
3031 : }
3032 :
3033 0 : erb_slot_fx( l_fx, cslot_fx, t_prev_erb_fx, num_erb_fx );
3034 0 : erb_slot_fx( pl_fx, pslot_fx, t_prev_erb_fx, num_erb_fx );
3035 :
3036 0 : FOR( i = 0; i < num_erb_fx; i++ )
3037 : {
3038 0 : t_prev_erb_fx[i] = prev_erb_fx[i];
3039 0 : move16(); /* Q13 */
3040 : }
3041 :
3042 :
3043 0 : IF( GT_16( pl_fx, l_fx ) )
3044 : {
3045 0 : tmp_fx = t_prev_erb_fx[0];
3046 0 : move16(); /* Q13 */
3047 0 : FOR( i = 0; i < num_erb_fx; i++ )
3048 : {
3049 :
3050 0 : IF( pslot_fx[i] != 0 )
3051 : {
3052 0 : tmp_fx = t_prev_erb_fx[i];
3053 0 : move16(); /* Q13 */
3054 : }
3055 : ELSE
3056 : {
3057 0 : t_prev_erb_fx[i] = tmp_fx;
3058 0 : move16(); /* Q13 */
3059 : }
3060 : }
3061 : }
3062 0 : ELSE IF( GT_16( l_fx, pl_fx ) )
3063 : {
3064 0 : tmp_fx = t_prev_erb_fx[( num_erb_fx - 1 )]; /* Q13 */
3065 0 : FOR( i = ( num_erb_fx - 1 ); i >= 0; i-- )
3066 : {
3067 :
3068 0 : IF( pslot_fx[i] != 0 )
3069 : {
3070 0 : tmp_fx = t_prev_erb_fx[i];
3071 0 : move16(); /* Q13 */
3072 : }
3073 : ELSE
3074 : {
3075 0 : t_prev_erb_fx[i] = tmp_fx;
3076 0 : move16(); /* Q13 */
3077 : }
3078 : }
3079 : }
3080 :
3081 0 : tmp_fx = add( shl( index_fx[0], 3 ), shl( index_fx[0], 1 ) ); /* tmp_fx=10*index_fx[0] */
3082 0 : FOR( i = 1; i < 11; i++ )
3083 : {
3084 :
3085 0 : IF( cslot_fx[i] != 0 )
3086 : {
3087 0 : curr_erb_fx[i] = add( AmpCB1_fx[( ( tmp_fx + i ) - 1 )], t_prev_erb_fx[i] );
3088 0 : move16(); /* Q13+Q13=Q13 */
3089 0 : curr_erb_fx[i] = s_max( 0, curr_erb_fx[i] );
3090 0 : move16();
3091 : }
3092 : ELSE
3093 : {
3094 0 : curr_erb_fx[i] = 0;
3095 0 : move16();
3096 : }
3097 : }
3098 :
3099 0 : tmp_fx = add( shl( index_fx[1], 3 ), index_fx[1] ); /* tmp=9*index[1] */
3100 0 : tmp2_fx = mult( shl( index_fx[1], 6 ), 5632 ); /* temp=11*index_fx[1] */
3101 0 : tmp_loop = sub( num_erb_fx, 2 );
3102 0 : FOR( i = 11; i < tmp_loop; i++ )
3103 : {
3104 :
3105 0 : IF( cslot_fx[i] != 0 )
3106 : {
3107 0 : IF( EQ_16( num_erb_fx, NUM_ERB_NB ) )
3108 : {
3109 0 : curr_erb_fx[i] = add( AmpCB2_NB_fx[( ( tmp_fx + i ) - 11 )], t_prev_erb_fx[i] ); /* Q13+Q13=Q13 */
3110 0 : move16();
3111 0 : curr_erb_fx[i] = s_max( 0, curr_erb_fx[i] );
3112 0 : move16();
3113 : }
3114 0 : ELSE IF( EQ_16( num_erb_fx, NUM_ERB_WB ) )
3115 : {
3116 0 : curr_erb_fx[i] = add( AmpCB2_WB_fx[( ( tmp2_fx + i ) - 11 )], t_prev_erb_fx[i] ); /* Q13 */
3117 0 : move16();
3118 0 : curr_erb_fx[i] = s_max( 0, curr_erb_fx[i] );
3119 0 : move16();
3120 : }
3121 : }
3122 : ELSE
3123 : {
3124 0 : curr_erb_fx[i] = 0;
3125 0 : move16();
3126 : }
3127 : }
3128 0 : return;
3129 : }
3130 :
3131 :
3132 : /*===================================================================*/
3133 : /* FUNCTION : struct quant_target_fx() */
3134 : /*-------------------------------------------------------------------*/
3135 : /* PURPOSE : Get weighting and target for power quantization */
3136 : /*-------------------------------------------------------------------*/
3137 : /* INPUT ARGUMENTS : */
3138 : /* _ (Word16 []) curr_lpc: LPC coefficients, Q12 */
3139 : /* _ (Word16 []) sin_tab: sine table based on lag, Q15 */
3140 : /* _ (Word16 []) cos_tab: cosine table based on lag, Q15 */
3141 : /*-------------------------------------------------------------------*/
3142 : /* OUTPUT ARGUMENTS : */
3143 : /* _ (Word16[]) w: Weighting for power quantization, Q15 */
3144 : /* _ (Word16[]) target: Power of 2 bands for quantization, Q11 */
3145 : /*-------------------------------------------------------------------*/
3146 : /* INPUT/OUTPUT ARGUMENTS : */
3147 : /* _ (struct DTFS_fx) X : prototype in polar domain */
3148 : /* (Word16) lag: length of prototype in time domain */
3149 : /* (Word16 []) a: amplitude of harmonics, normalized */
3150 : /* (Word16) Q: norm factor of a */
3151 : /*-------------------------------------------------------------------*/
3152 : /* RETURN ARGUMENTS : */
3153 : /* _ None */
3154 : /*-------------------------------------------------------------------*/
3155 : /* CALLED FROM : TX */
3156 : /*===================================================================*/
3157 : /* NOTE: This function is used by quant_cw_fx and quant_cw_memless_fx*/
3158 : /*===================================================================*/
3159 0 : void quant_target_fx( DTFS_STRUCTURE *X_fx, const Word16 *curr_lpc, Word16 *w, Word16 *target, Word16 *sin_tab, Word16 *cos_tab )
3160 : {
3161 : Word16 tmp, n, exp;
3162 : Word16 Ql, Qh;
3163 : Word32 Ltemp1, Ltemp, Ltemp2, logLag, Ltemp3, Lacc;
3164 :
3165 0 : tmp = sub( shl( X_fx->Q, 1 ), 13 ); /* tmp=2Q-13, Q factor of getSpEngy... output */
3166 0 : Ltemp3 = L_shl( L_mult( tmp, 24660 ), 9 ); /* Ltemp3=(2Q-13)*10log10(2), Q23, 24660=10log10(2) in Q13 */
3167 :
3168 0 : Ltemp1 = getSpEngyFromResAmp_fx( X_fx, 0, 2828, curr_lpc, sin_tab, cos_tab );
3169 0 : Ltemp1 = log10_fx( Ltemp1 );
3170 :
3171 : /* subtract 10log10(2)*(2Q-13), Q23 */
3172 0 : Ltemp1 = L_sub_sat( Ltemp1, Ltemp3 );
3173 0 : Ltemp1 = L_max( 0, Ltemp1 );
3174 0 : Ltemp2 = getSpEngyFromResAmp_fx( X_fx, 2828, X_fx->upper_cut_off_freq_fx, curr_lpc, sin_tab, cos_tab );
3175 0 : Ltemp2 = log10_fx( Ltemp2 ); /* Ltemp1=10log10(eng_hb), Q23, need to adjust for Q factor of energy (2Q-13) */
3176 0 : Ltemp2 = L_sub_sat( Ltemp2, Ltemp3 ); /* Ltemp2 in Q23 */
3177 :
3178 0 : Ltemp2 = L_max( 0, Ltemp2 );
3179 :
3180 : /* Getting the Speech Domain Energy LOG Ratio */
3181 :
3182 0 : Lacc = L_add( Ltemp1, Ltemp2 );
3183 0 : exp = norm_l( Lacc );
3184 0 : tmp = round_fx( L_shl( Lacc, exp ) );
3185 0 : exp = sub( sub( 30, exp ), 23 );
3186 0 : IF( tmp )
3187 : {
3188 0 : tmp = div_s( 16384, tmp ); /* 15+exp1 */
3189 : }
3190 : ELSE
3191 : {
3192 0 : tmp = 0;
3193 0 : move16();
3194 : }
3195 0 : Ltemp = L_deposit_h( tmp );
3196 :
3197 0 : tmp = round_fx( Ltemp ); /* tmp in Q(22-n) */
3198 0 : Ltemp1 = Mult_32_16( Ltemp1, tmp ); /* Q(30-n) */
3199 0 : n = sub( 8, exp );
3200 0 : w[0] = round_fx_sat( L_shl_sat( Ltemp1, n ) ); /* w[0] in Q15 */
3201 0 : move16();
3202 0 : Ltemp2 = Mult_32_16( Ltemp2, tmp );
3203 0 : w[1] = round_fx_sat( L_shl_sat( Ltemp2, n ) ); /* w[1] in Q15 */
3204 0 : move16();
3205 :
3206 0 : logLag = log10_fx( X_fx->lag_fx ); /* logLag=10*log10(lag), Q23 */
3207 0 : Ltemp3 = L_shl( L_mult( shl( X_fx->Q, 1 ), 24660 ), 9 ); /* Ltemp3=2Q*10log10(2), Q23 */
3208 : /* Process low band */
3209 0 : Ltemp = DTFS_setEngyHarm_fx( 236, 2828, 0, 2828, 1, 0, &Ql, X_fx ); /* Ql is norm factor of low band a[], Ltemp is energy in 2Q */
3210 : /* Compensate for Q factor of energy to get log10(lag*eng) */
3211 0 : Ltemp = log10_fx( Ltemp ); /* Ltemp=10log10(eng), Q23 */
3212 0 : Ltemp = L_add( L_sub( Ltemp, Ltemp3 ), logLag ); /* Ltemp=10*log10(lag*eng), Q23 */
3213 :
3214 0 : target[0] = round_fx( L_shl( Mult_32_16( Ltemp, 0x6666 ), 1 ) ); /* Q11 */
3215 0 : move16();
3216 :
3217 : /* Process high band */
3218 0 : Ltemp = DTFS_setEngyHarm_fx( 2828, X_fx->upper_cut_off_freq_of_interest_fx, 2828, X_fx->upper_cut_off_freq_fx, 1, 0, &Qh, X_fx );
3219 0 : Ltemp = log10_fx( Ltemp );
3220 0 : Ltemp = L_add( L_sub( Ltemp, Ltemp3 ), logLag ); /* Ltemp=10*log10(lag*eng), Q23 */
3221 0 : target[1] = round_fx( L_shl( Mult_32_16( Ltemp, 0x6666 ), 1 ) ); /* Q11 */
3222 0 : move16();
3223 :
3224 : /* Need to unify the Q factors of both bands */
3225 0 : X_fx->Q = s_min( Ql, Qh ); /* set Q factor to be the smaller one */
3226 0 : move16();
3227 0 : n = sub( Ql, Qh ); /* compare band Q factors */
3228 :
3229 0 : IF( n < 0 )
3230 : {
3231 0 : rshiftHarmBand_fx( X_fx, 2828, X_fx->upper_cut_off_freq_fx, n );
3232 : }
3233 0 : ELSE IF( n > 0 )
3234 : {
3235 0 : rshiftHarmBand_fx( X_fx, 0, 2828, sub( Qh, Ql ) );
3236 : }
3237 0 : }
3238 :
3239 : /*==========================================================================*/
3240 : /* FUNCTION : WIsyn_fx () */
3241 : /*--------------------------------------------------------------------------*/
3242 : /* PURPOSE : */
3243 : /*--------------------------------------------------------------------------*/
3244 : /* INPUT ARGUMENTS : */
3245 : /* _ (struct DTFS_STRUCTURE) PREVCW_FX: a/b in PREVCW_FX.Q */
3246 : /* _ (struct DTFS_fx *) CURRCW_DTFS_out: a/b in CURRCW_DTFS_out->Q */
3247 : /* _ (Word16 *) curr_lpc_fx: lpc coefficients in Q12 */
3248 : /* _ (Word16 *) ph_offset_fx: in Q15, normalized by 2pi */
3249 : /* _ (Word16 *) S_fx: sin(2pi*n/(4*lag)) table, Q15 */
3250 : /* _ (Word16 *) C_fx: cos(2pi*n/(4*lag)) table, Q15 */
3251 : /* _ (Word16 *) N: length, Q0 */
3252 : /*--------------------------------------------------------------------------*/
3253 : /* OUTPUT ARGUMENTS : */
3254 : /* _ (Word16 *) out_fx: Q0 */
3255 : /*--------------------------------------------------------------------------*/
3256 : /* INPUT/OUTPUT ARGUMENTS : */
3257 : /* _ (struct DTFS_STRUCTURE *) CURRCW_DTFS_out: a/b in CURRCW_DTFS_out->Q*/
3258 : /* _ (Word16 *) ph_offset_fx: in Q15, normalized by 2pi */
3259 : /*--------------------------------------------------------------------------*/
3260 : /* RETURN ARGUMENTS : _ None. */
3261 : /*==========================================================================*/
3262 0 : ivas_error WIsyn_fx(
3263 : DTFS_STRUCTURE PREVCW_FX, /* i : Prev frame DTFS */
3264 : DTFS_STRUCTURE *CURRCW_DTFS_out, /* i/o: Curr frame DTFS */
3265 : const Word16 *curr_lpc_fx, /* i : LPC */
3266 : Word16 *ph_offset_fx, /* i/o: Phase offset to line up at end of frame */
3267 : Word16 *out_fx, /* o : Waveform Interpolated time domain signal */
3268 : const Word16 N, /* i : Number of output samples to generate */
3269 : const Word16 FR_flag, /* i : called for post-smoothing in FR */
3270 : Word16 *S_fx,
3271 : Word16 *C_fx,
3272 : Word16 *pf_temp1,
3273 : Word16 *pf_temp2,
3274 : Word16 *pf_temp,
3275 : Word16 *pf_n2 )
3276 : {
3277 : Word16 i;
3278 0 : UWord16 I = 1, flag = 0;
3279 0 : move16();
3280 0 : move16();
3281 : /* Word16 *phase_fx = (Word16*)malloc(sizeof(Word16) * (2*N)); new operator used size 2*N */
3282 : Word32 phase_fx[WI_FX_phase_fx];
3283 : Word16 alignment_fx;
3284 : Word16 tmp_fx, temp;
3285 : Word32 L_temp;
3286 : Word16 exp, tmp;
3287 : Word32 L_tmp;
3288 : /* prev_lsp_fx; */
3289 :
3290 :
3291 : DTFS_STRUCTURE *CURRCW_DTFS_FX;
3292 : ivas_error error;
3293 :
3294 0 : error = IVAS_ERR_OK;
3295 0 : move16();
3296 :
3297 0 : IF( ( error = DTFS_new_fx( &CURRCW_DTFS_FX ) ) != IVAS_ERR_OK )
3298 : {
3299 0 : return IVAS_ERROR( error, "Error creating new DTFS structure\n" );
3300 : }
3301 0 : IF( LT_16( PREVCW_FX.Q, CURRCW_DTFS_out->Q ) )
3302 : {
3303 0 : temp = sub( CURRCW_DTFS_out->Q, PREVCW_FX.Q );
3304 0 : tmp = s_min( shr( CURRCW_DTFS_out->lag_fx, 1 ), CURRCW_DTFS_out->nH_fx );
3305 0 : FOR( i = 0; i <= tmp; i++ )
3306 : {
3307 0 : CURRCW_DTFS_out->a_fx[i] = shr( CURRCW_DTFS_out->a_fx[i], temp );
3308 0 : move16();
3309 0 : CURRCW_DTFS_out->b_fx[i] = shr( CURRCW_DTFS_out->b_fx[i], temp );
3310 0 : move16();
3311 : }
3312 0 : CURRCW_DTFS_out->Q = PREVCW_FX.Q;
3313 0 : move16();
3314 : }
3315 :
3316 :
3317 0 : IF( LT_16( CURRCW_DTFS_out->Q, PREVCW_FX.Q ) )
3318 : {
3319 0 : temp = sub( PREVCW_FX.Q, CURRCW_DTFS_out->Q );
3320 0 : tmp = s_min( shr( PREVCW_FX.lag_fx, 1 ), PREVCW_FX.nH_fx );
3321 0 : FOR( i = 0; i <= tmp; i++ )
3322 : {
3323 0 : PREVCW_FX.a_fx[i] = shr( PREVCW_FX.a_fx[i], temp );
3324 0 : move16();
3325 0 : PREVCW_FX.b_fx[i] = shr( PREVCW_FX.b_fx[i], temp );
3326 0 : move16();
3327 : }
3328 0 : PREVCW_FX.Q = CURRCW_DTFS_out->Q;
3329 0 : move16();
3330 : }
3331 :
3332 0 : DTFS_copy_fx( CURRCW_DTFS_FX, *CURRCW_DTFS_out );
3333 :
3334 : /* Calculating the expected alignment shift */
3335 0 : alignment_fx = mult_r( *ph_offset_fx, shl( PREVCW_FX.lag_fx, 7 ) ); /* confirmed I<2 by smv12.org, Q7 */
3336 :
3337 :
3338 0 : IF( EQ_16( flag, 1 ) )
3339 0 : alignment_fx = extract_l( L_shr( L_mult( alignment_fx, I ), 1 ) ); /* Q7 */
3340 :
3341 : /* Calculating the expected alignment shift */
3342 0 : find_rem( (Word16) N, shr( add( PREVCW_FX.lag_fx, CURRCW_DTFS_FX->lag_fx ), 1 ), &temp );
3343 0 : temp = add( shl( temp, 7 ), alignment_fx ); /* Q7 */
3344 :
3345 :
3346 0 : IF( temp < 0 )
3347 : {
3348 0 : temp = add( temp, shl( CURRCW_DTFS_FX->lag_fx, 7 ) ); /* Q7 */
3349 : }
3350 :
3351 0 : find_rem( temp, shl( CURRCW_DTFS_FX->lag_fx, 7 ), &tmp_fx ); /* Q7 */
3352 0 : IF( FR_flag == 0 )
3353 : {
3354 0 : alignment_fx = DTFS_alignment_weight_fx( &PREVCW_FX, *CURRCW_DTFS_FX, tmp_fx, curr_lpc_fx, curr_lpc_fx, S_fx,
3355 : C_fx, pf_temp1, pf_temp2, pf_temp, pf_n2 ); /* Q7 */
3356 : }
3357 : ELSE
3358 : {
3359 0 : alignment_fx = DTFS_alignment_full_fx( PREVCW_FX, *CURRCW_DTFS_FX, *ph_offset_fx, S_fx, C_fx, FR_flag );
3360 :
3361 : /*alignment_fx is in Q1, we make it Q7*/
3362 0 : alignment_fx = shl( alignment_fx, 6 );
3363 : }
3364 :
3365 :
3366 0 : IF( GE_16( alignment_fx, shl( CURRCW_DTFS_FX->lag_fx, 7 ) ) )
3367 : {
3368 0 : temp = sub( alignment_fx, shl( CURRCW_DTFS_FX->lag_fx, 7 ) );
3369 0 : tmp = shl( CURRCW_DTFS_FX->lag_fx, 7 );
3370 0 : exp = norm_s( tmp );
3371 0 : tmp = div_s( shl( 1, sub( 14, exp ) ), tmp ); /* 22-exp */
3372 0 : L_tmp = L_shl( L_mult( temp, tmp ), add( exp, 1 ) );
3373 0 : tmp_fx = round_fx( L_tmp );
3374 : }
3375 0 : ELSE IF( alignment_fx < 0 )
3376 : {
3377 0 : temp = negate( alignment_fx );
3378 0 : tmp = shl( CURRCW_DTFS_FX->lag_fx, 7 );
3379 0 : exp = norm_s( tmp );
3380 0 : tmp = div_s( shl( 1, sub( 14, exp ) ), tmp ); /* 22-exp */
3381 0 : L_tmp = L_shl( L_mult( temp, tmp ), add( exp, 1 ) );
3382 0 : tmp_fx = negate( round_fx( L_tmp ) );
3383 : }
3384 : ELSE
3385 : {
3386 0 : temp = alignment_fx;
3387 0 : move16();
3388 0 : tmp = shl( CURRCW_DTFS_FX->lag_fx, 7 );
3389 0 : exp = norm_s( tmp );
3390 0 : tmp = div_s( shl( 1, sub( 14, exp ) ), tmp ); /* 22-exp */
3391 0 : L_tmp = L_shl( L_mult( temp, tmp ), add( exp, 1 ) );
3392 0 : tmp_fx = round_fx( L_tmp );
3393 : }
3394 :
3395 0 : DTFS_phaseShift_fx( CURRCW_DTFS_FX, alignment_fx, CURRCW_DTFS_FX->lag_fx, S_fx, C_fx ); /* Qmin */
3396 0 : DTFS_phaseShift_fx( CURRCW_DTFS_out, alignment_fx, CURRCW_DTFS_out->lag_fx, S_fx, C_fx ); /* Qmin */
3397 :
3398 : /* Compute the cubic phase track and transform to 1-D signal */
3399 0 : cubicPhase_fx( *ph_offset_fx, tmp_fx, PREVCW_FX.lag_fx, CURRCW_DTFS_FX->lag_fx, N, phase_fx );
3400 :
3401 0 : temp = shr( add( PREVCW_FX.lag_fx, CURRCW_DTFS_FX->lag_fx ), 1 ); /* Q0 */
3402 :
3403 0 : IF( FR_flag == 0 )
3404 : {
3405 0 : DTFS_transform_fx( PREVCW_FX, *CURRCW_DTFS_FX, phase_fx, out_fx, N, 0 );
3406 : }
3407 : ELSE
3408 : {
3409 0 : DTFS_transform_fx( PREVCW_FX, *CURRCW_DTFS_FX, phase_fx, out_fx, N, 1 );
3410 : }
3411 :
3412 :
3413 : /* Adjust the phase offset and wrap it between 0 and 2pi */
3414 :
3415 : // PMT("NEED a complete verification of mem flow and assignment")
3416 :
3417 :
3418 0 : IF( EQ_16( flag, 2 ) )
3419 : {
3420 0 : L_temp = L_shr( L_mult( tmp_fx, I ), 1 ); /* Q15 */
3421 : }
3422 : ELSE
3423 : {
3424 0 : L_temp = L_deposit_l( tmp_fx ); /* Q15 */
3425 : }
3426 :
3427 :
3428 0 : FOR( ; L_temp < 0; L_temp += 0x8000L )
3429 : {
3430 : /* empty loop */
3431 : }
3432 0 : L_temp = L_and( L_temp, 0x7fff );
3433 0 : move16(); /* fraction part */
3434 0 : *ph_offset_fx = extract_l( L_temp );
3435 0 : move16();
3436 :
3437 : /* free(phase_fx) ; */
3438 0 : free( CURRCW_DTFS_FX );
3439 0 : return error;
3440 : }
3441 :
3442 :
3443 : /*===================================================================*/
3444 : /* FUNCTION : ppp_extract_pitch_period_fx () */
3445 : /*-------------------------------------------------------------------*/
3446 : /* PURPOSE : Update background noise estimate, signal energy */
3447 : /* estimate, and band snrs */
3448 : /*-------------------------------------------------------------------*/
3449 : /* INPUT ARGUMENTS : */
3450 : /* _ (Word16 []) in : residual input, Q0 */
3451 : /* _ (Word16) l : pitch lag, Q0 */
3452 : /*-------------------------------------------------------------------*/
3453 : /* OUTPUT ARGUMENTS : */
3454 : /* _ (Word16 []) out : pitch period prototype, Q0 */
3455 : /* _ (Word16*) out_of_bound : pitch lag, Q0 */
3456 : /*-------------------------------------------------------------------*/
3457 : /* INPUT/OUTPUT ARGUMENTS : */
3458 : /* _ None */
3459 : /*-------------------------------------------------------------------*/
3460 : /* RETURN ARGUMENTS : */
3461 : /* _ (Word16) spike_near_edge : Q0 */
3462 : /*===================================================================*/
3463 0 : Word16 ppp_extract_pitch_period_fx(
3464 : const Word16 *in, /* i : input residual */
3465 : Word16 *out, /* o : output residual */
3466 : Word16 l, /* i : lag */
3467 : Word16 *out_of_bound, /* o : out of bound flag */
3468 : Word16 Qres
3469 :
3470 : )
3471 : {
3472 : Word16 i, j, k;
3473 0 : Word16 spike = 0, range;
3474 0 : move16();
3475 0 : Word16 max = 0;
3476 0 : move16();
3477 0 : const Word16 *ptr = in + L_FRAME - l;
3478 0 : Word32 en1 = 0, Lacc, L_tmp;
3479 0 : move32();
3480 0 : Word16 spike_near_edge = 0, scale;
3481 0 : move16();
3482 : Word16 pos_max, neg_max;
3483 0 : Word16 spike_pos = 0, spike_neg = 0;
3484 0 : move16();
3485 0 : move16();
3486 : Word16 x, tmp, expa, fraca, expb, fracb, scale1, exp;
3487 :
3488 0 : pos_max = -0x8000L;
3489 0 : move16();
3490 0 : neg_max = 0;
3491 0 : move16();
3492 0 : *out_of_bound = 0;
3493 0 : move16();
3494 :
3495 0 : en1 = L_deposit_l( 0 );
3496 0 : FOR( i = 0; i < l; i++ )
3497 : {
3498 0 : x = abs_s( ptr[i] );
3499 :
3500 0 : IF( GT_16( x, max ) )
3501 : {
3502 0 : max = x;
3503 0 : move16();
3504 0 : spike = i;
3505 0 : move16();
3506 : }
3507 0 : en1 = L_mac0_sat( en1, ptr[i], ptr[i] ); /* Q0 */
3508 : }
3509 :
3510 0 : IF( ptr[spike] > 0 )
3511 : {
3512 0 : spike_pos = spike;
3513 0 : move16();
3514 : /* search for neg spike around the pos spike */
3515 0 : FOR( j = spike - 10; j < spike + 10; j++ )
3516 : {
3517 0 : k = add( j, l ) % l;
3518 0 : move16();
3519 :
3520 0 : IF( LT_16( ptr[k], neg_max ) )
3521 : {
3522 0 : neg_max = ptr[k];
3523 0 : move16();
3524 0 : spike_neg = k;
3525 0 : move16();
3526 : }
3527 : }
3528 : }
3529 0 : ELSE IF( ptr[spike] < 0 )
3530 : {
3531 0 : spike_neg = spike;
3532 0 : move16();
3533 : /* search for pos spike around the neg spike */
3534 0 : FOR( j = spike - 10; j < spike + 10; j++ )
3535 : {
3536 0 : k = add( j, l ) % l;
3537 0 : move16();
3538 :
3539 0 : IF( GT_16( ptr[k], pos_max ) )
3540 : {
3541 0 : pos_max = ptr[k];
3542 0 : move16();
3543 0 : spike_pos = k;
3544 0 : move16();
3545 : }
3546 : }
3547 : }
3548 :
3549 0 : test();
3550 0 : IF( ( LE_16( sub( sub( l, 1 ), s_max( spike_pos, spike_neg ) ), 2 ) ) || ( LE_16( s_min( spike_pos, spike_neg ), 2 ) ) )
3551 : {
3552 0 : *out_of_bound = 1;
3553 0 : move16();
3554 0 : return spike_near_edge;
3555 : }
3556 :
3557 :
3558 0 : tmp = extract_l( ( L_max( L_mult( CUTFREE_REL_RANGE_Q2, l ), CUTFREE_ABS_RANGE_Q3 ) ) ); /* Q3 */
3559 :
3560 0 : IF( tmp > 0 )
3561 : {
3562 0 : tmp = add( tmp, 4 ); /* Q3 */
3563 : }
3564 : ELSE
3565 : {
3566 0 : tmp = sub( tmp, 4 ); /* Q3 */
3567 : }
3568 0 : range = shr( tmp, 3 ); /* Q0 */
3569 :
3570 0 : test();
3571 0 : IF( ( LT_16( spike, range ) ) || ( GE_16( add( spike, range ), l ) ) )
3572 : {
3573 : /* need to grab from one lag before
3574 : ensure that there is no array bound read */
3575 :
3576 0 : IF( LT_16( sub( L_FRAME, l ), l ) )
3577 : {
3578 0 : *out_of_bound = 1;
3579 0 : move16();
3580 0 : return spike_near_edge;
3581 : }
3582 0 : spike_near_edge = 1;
3583 0 : move16();
3584 : }
3585 :
3586 0 : IF( LT_16( spike, range ) )
3587 : {
3588 0 : tmp = add( l, sub( spike, range ) );
3589 0 : FOR( i = 0; i < tmp; i++ )
3590 : {
3591 0 : out[i] = ptr[i];
3592 0 : move16();
3593 : }
3594 : /* Grab Remaining From One Lag Before */
3595 0 : ptr -= l;
3596 0 : FOR( ; i < l; i++ )
3597 : {
3598 0 : out[i] = ptr[i];
3599 0 : move16();
3600 : }
3601 : }
3602 0 : ELSE IF( GE_16( add( spike, range ), l ) )
3603 : {
3604 0 : tmp = sub( spike, range );
3605 0 : FOR( i = 0; i < tmp; i++ )
3606 : {
3607 0 : out[i] = ptr[i];
3608 0 : move16();
3609 : }
3610 : /* Grab Remaining From One Lag Before */
3611 0 : IF( ptr - l + i >= in )
3612 : {
3613 0 : FOR( ptr -= l; i < l; i++ )
3614 : {
3615 0 : out[i] = ptr[i];
3616 0 : move16();
3617 : }
3618 : }
3619 : ELSE
3620 : {
3621 0 : FOR( ; i < l; i++ )
3622 : {
3623 0 : out[i] = ptr[i];
3624 0 : move16();
3625 : }
3626 : }
3627 : }
3628 : ELSE
3629 : {
3630 0 : FOR( i = 0; i < l; i++ )
3631 : {
3632 0 : out[i] = ptr[i];
3633 0 : move16();
3634 : }
3635 : }
3636 : /* Energy adjustment added to eliminate artifacts at the end of voicing */
3637 0 : Lacc = L_deposit_l( 0 );
3638 0 : FOR( i = 0; i < l; i++ )
3639 : {
3640 0 : Lacc = L_mac0_sat( Lacc, out[i], out[i] ); /* Q0 */
3641 : }
3642 :
3643 :
3644 0 : IF( LT_32( en1, Lacc ) )
3645 : {
3646 : /* Ltmp=sqrt_divide_dp(en1, Lacc, 0, &n,1); */
3647 : /* scale=round_fx(L_shl(Ltmp,sub(31,n))); in Q15 */
3648 0 : expa = norm_l( en1 );
3649 0 : fraca = extract_h( L_shl( en1, expa ) );
3650 0 : expa = sub( 30, add( expa, Qres ) );
3651 :
3652 :
3653 0 : expb = norm_l( Lacc );
3654 0 : fracb = round_fx_sat( L_shl_sat( Lacc, expb ) );
3655 0 : expb = sub( 30, add( expb, Qres ) );
3656 :
3657 0 : scale1 = shr( sub( fraca, fracb ), 15 );
3658 0 : fracb = shl( fracb, scale1 );
3659 0 : expb = sub( expb, scale1 );
3660 :
3661 0 : tmp = div_s( fracb, fraca );
3662 0 : exp = sub( expb, expa );
3663 :
3664 0 : L_tmp = Isqrt_lc( L_deposit_h( tmp ), &exp ); /* Q(31-exp) */
3665 0 : scale = round_fx( L_tmp ); /* Q15 */
3666 :
3667 0 : FOR( i = 0; i < l; i++ )
3668 : {
3669 0 : out[i] = mult_r( out[i], scale );
3670 0 : move16();
3671 : }
3672 : }
3673 0 : return spike_near_edge;
3674 : }
3675 : /*===========================================================================*/
3676 : /* FUNCTION : DTFS_peaktoaverage_fx () */
3677 : /*---------------------------------------------------------------------------*/
3678 : /* PURPOSE : */
3679 : /*---------------------------------------------------------------------------*/
3680 : /* INPUT ARGUMENTS : */
3681 : /* _ (struct DTFS_STRUCTURE) X_fx: a_fx/b_fx in Q(X_fx.Q), lag in Q0 */
3682 : /*---------------------------------------------------------------------------*/
3683 : /* OUTPUT ARGUMENTS : */
3684 : /* _ (Word32 *) pos_fx : in *Qpos */
3685 : /* _ (Word32 *) neg_fx : in *Qneg */
3686 : /* _ (Word16 *) Qpos: Q valule of output *pos_fx */
3687 : /* _ (Word16 *) Qneg: Q valule of output *neg_fx */
3688 : /*---------------------------------------------------------------------------*/
3689 : /* INPUT/OUTPUT ARGUMENTS : */
3690 : /* _ None */
3691 : /*---------------------------------------------------------------------------*/
3692 : /* RETURN ARGUMENTS : _ None. */
3693 : /*===========================================================================*/
3694 0 : void DTFS_peaktoaverage_fx( DTFS_STRUCTURE X_fx, Word32 *pos_fx, Word16 *Qpos, Word32 *neg_fx, Word16 *Qneg )
3695 : {
3696 : Word32 L_sum;
3697 0 : Word32 maxPosEn_fx = 0, maxNegEn_fx = 0, L_temp;
3698 0 : move32();
3699 0 : move32();
3700 : Word16 i;
3701 : Word16 time_fx[256];
3702 : Word16 expa, expb, fraca, fracb, scale;
3703 : Word16 exp, tmp;
3704 : Word32 L_tmp;
3705 : #ifndef ISSUE_1836_replace_overflow_libcom__remnant
3706 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
3707 : Flag Overflow = 0;
3708 : move32();
3709 : #endif
3710 : #endif
3711 0 : L_sum = DTFS_getEngy_P2A_fx( &X_fx ); /* 2Q */
3712 0 : DTFS_fast_fs_inv_fx( &X_fx, time_fx, 256, 8 );
3713 :
3714 0 : FOR( i = 0; i < 256; i++ )
3715 : {
3716 0 : L_temp = L_mult_sat( time_fx[i], time_fx[i] ); /* Q(1) */
3717 0 : IF( time_fx[i] >= 0 )
3718 : {
3719 0 : if ( GT_32( L_temp, maxPosEn_fx ) )
3720 : {
3721 0 : maxPosEn_fx = L_temp; /* Q(1) */
3722 0 : move32();
3723 : }
3724 : }
3725 : ELSE
3726 : {
3727 0 : if ( GT_32( L_temp, maxNegEn_fx ) )
3728 : {
3729 0 : maxNegEn_fx = L_temp; /* Q(1) */
3730 0 : move32();
3731 : }
3732 : }
3733 : }
3734 :
3735 :
3736 0 : IF( L_sum == 0 )
3737 : {
3738 0 : *pos_fx = *neg_fx = 0;
3739 0 : move32();
3740 0 : move32();
3741 : }
3742 : ELSE
3743 : {
3744 0 : IF( maxPosEn_fx == 0 )
3745 : {
3746 0 : *pos_fx = 0;
3747 0 : move32();
3748 0 : *Qpos = 31;
3749 0 : move16();
3750 : }
3751 : ELSE
3752 : {
3753 0 : expa = norm_l( maxPosEn_fx );
3754 : #ifdef ISSUE_1836_replace_overflow_libcom__remnant
3755 0 : fraca = extract_h( L_shl( maxPosEn_fx, expa ) );
3756 0 : expa = sub( 30, add( expa, 1 ) );
3757 :
3758 :
3759 0 : expb = norm_l( L_sum );
3760 0 : fracb = round_fx_sat( L_shl( L_sum, expb ) );
3761 : #else
3762 : fraca = extract_h( L_shl_o( maxPosEn_fx, expa, &Overflow ) );
3763 : expa = sub( 30, add( expa, 1 ) );
3764 :
3765 :
3766 : expb = norm_l( L_sum );
3767 : fracb = round_fx_o( L_shl_o( L_sum, expb, &Overflow ), &Overflow );
3768 : #endif
3769 :
3770 0 : expb = sub( 30, add( expb, shl( X_fx.Q, 1 ) ) );
3771 :
3772 :
3773 0 : scale = shr( sub( fraca, fracb ), 15 );
3774 : #ifdef ISSUE_1836_replace_overflow_libcom__remnant
3775 0 : fracb = shl_sat( fracb, scale );
3776 : #else
3777 : fracb = shl_o( fracb, scale, &Overflow );
3778 : #endif
3779 0 : expb = sub( expb, scale );
3780 :
3781 0 : tmp = div_s( fracb, fraca );
3782 0 : exp = sub( expb, expa );
3783 :
3784 0 : L_tmp = Isqrt_lc( L_deposit_h( tmp ), &exp ); /* Q(31-exp) */
3785 0 : *pos_fx = L_tmp;
3786 0 : move32();
3787 0 : *Qpos = sub( 31, exp );
3788 0 : move16();
3789 : }
3790 :
3791 0 : IF( maxNegEn_fx == 0 )
3792 : {
3793 0 : *neg_fx = 0;
3794 0 : move32();
3795 0 : *Qneg = 31;
3796 0 : move16();
3797 : }
3798 : ELSE
3799 : {
3800 :
3801 0 : expa = norm_l( maxNegEn_fx );
3802 : #ifdef ISSUE_1836_replace_overflow_libcom__remnant
3803 0 : fraca = extract_h( L_shl( maxNegEn_fx, expa ) );
3804 0 : expa = sub( Q29, expa ); // 30 - expa - 1;
3805 :
3806 :
3807 0 : expb = norm_l( L_sum );
3808 0 : fracb = round_fx_sat( L_shl( L_sum, expb ) );
3809 : #else
3810 : fraca = extract_h( L_shl_o( maxNegEn_fx, expa, &Overflow ) );
3811 : expa = sub( Q29, expa ); // 30 - expa - 1;
3812 :
3813 :
3814 : expb = norm_l( L_sum );
3815 : fracb = round_fx_o( L_shl_o( L_sum, expb, &Overflow ), &Overflow );
3816 : #endif
3817 0 : expb = sub( 30, add( expb, shl( X_fx.Q, 1 ) ) );
3818 :
3819 :
3820 0 : scale = shr( sub( fraca, fracb ), 15 );
3821 : #ifdef ISSUE_1836_replace_overflow_libcom__remnant
3822 0 : fracb = shl_sat( fracb, scale );
3823 : #else
3824 : fracb = shl_o( fracb, scale, &Overflow );
3825 : #endif
3826 0 : expb = sub( expb, scale );
3827 :
3828 0 : tmp = div_s( fracb, fraca );
3829 0 : exp = sub( expb, expa );
3830 :
3831 0 : L_tmp = Isqrt_lc( L_deposit_h( tmp ), &exp ); /* Q(31-exp) */
3832 0 : *neg_fx = L_tmp;
3833 0 : move32();
3834 0 : *Qneg = sub( Q31, exp );
3835 0 : move16();
3836 : }
3837 : }
3838 0 : }
3839 :
3840 : /*===================================================================*/
3841 : /* FUNCTION : struct DTFS_fx:: rshiftHarmBand_fx() */
3842 : /*-------------------------------------------------------------------*/
3843 : /* PURPOSE : Right-shift harmonics in band to align Q factor */
3844 : /*-------------------------------------------------------------------*/
3845 : /* INPUT ARGUMENTS : */
3846 : /* _ (Word16) lband: lower band boundary, Q15 */
3847 : /* _ (Word16) hband: upper band boundary, Q15 */
3848 : /* _ (Word16) shift: right shift value, Q0 (must be <0) */
3849 : /*-------------------------------------------------------------------*/
3850 : /* OUTPUT ARGUMENTS : */
3851 : /* _ None */
3852 : /*-------------------------------------------------------------------*/
3853 : /* INPUT/OUTPUT ARGUMENTS : */
3854 : /* _ (struct DTFS_fx) X : prototype in polar domain */
3855 : /* (Word16) lag: length of prototype in time domain */
3856 : /* (Word16 []) a: amplitude of harmonics, normalized */
3857 : /*-------------------------------------------------------------------*/
3858 : /* RETURN ARGUMENTS : _ None. */
3859 : /*-------------------------------------------------------------------*/
3860 : /* CALLED FROM : TX/RX */
3861 : /*===================================================================*/
3862 : /* NOTE: This function should be called after two consecutive calls */
3863 : /* to setEngyHarm_fx, because the norm factor outputs from */
3864 : /* the two previous calls might be different */
3865 : /*===================================================================*/
3866 0 : void rshiftHarmBand_fx( DTFS_STRUCTURE *X_fx, Word16 lband_fx, Word16 hband_fx, Word16 shift_fx )
3867 : {
3868 : Word16 k_fx, HalfLag_fx;
3869 : Word16 low_fx, high_fx;
3870 :
3871 0 : low_fx = mult( lband_fx, X_fx->lag_fx ); /* low=lband*lag, Q0 */
3872 0 : high_fx = mult( hband_fx, X_fx->lag_fx ); /* high=hband*lag, Q0 */
3873 0 : HalfLag_fx = s_min( high_fx, shl( X_fx->nH_fx, 1 ) );
3874 :
3875 0 : FOR( k_fx = low_fx + 1; k_fx <= HalfLag_fx; k_fx++ )
3876 : {
3877 0 : X_fx->a_fx[k_fx] = shl_r( X_fx->a_fx[k_fx], shift_fx );
3878 0 : move16(); /* right shift and round */
3879 : }
3880 0 : }
3881 :
3882 : /*===================================================================*/
3883 : /* FUNCTION : GetSinCosTab_fx () */
3884 : /*-------------------------------------------------------------------*/
3885 : /* PURPOSE : Compute sine & cosine table given pitch lag, */
3886 : /* by interpolating the 512-entry cosine table. */
3887 : /* sin(2pi/4L*n) & cos(2pi/4L*n) for n=0,1,... 4L-1 */
3888 : /*-------------------------------------------------------------------*/
3889 : /* INPUT ARGUMENTS : */
3890 : /* _ (Word16) L : Pitch lag, Q0 */
3891 : /*-------------------------------------------------------------------*/
3892 : /* OUTPUT ARGUMENTS : */
3893 : /* _ (Word16 []) sinTab, Q15 : sin(2pi/4L*n), n=0,1,...,4L-1 */
3894 : /* _ (Word16 []) cosTab, Q15 : cos(2pi/4L*n), n=0,1,...,4L-1 */
3895 : /*-------------------------------------------------------------------*/
3896 : /* INPUT/OUTPUT ARGUMENTS : */
3897 : /* _ None */
3898 : /*-------------------------------------------------------------------*/
3899 : /* RETURN ARGUMENTS : _ None. */
3900 : /*-------------------------------------------------------------------*/
3901 : /* CALLED FROM : TX/RX */
3902 : /*===================================================================*/
3903 : /* NOTE: This function interpolates cos_table for better accuracy */
3904 : /*===================================================================*/
3905 0 : void GetSinCosTab_fx( Word16 L, Word16 *sinTab, Word16 *cosTab )
3906 : {
3907 : Word16 i, L4;
3908 : Word16 dl, t1, w, dt;
3909 : /* Word16 t2; */
3910 : Word32 invL; /* 1/4L in Q25 */
3911 : Word32 Ltemp, Lw;
3912 : Word32 L_tmp;
3913 :
3914 0 : invL = L_shr( inverse_table[L], 4 );
3915 :
3916 0 : L4 = shl( L, 2 );
3917 0 : Lw = L_deposit_l( 0 );
3918 0 : FOR( i = 0; i < L4; i++ )
3919 : {
3920 0 : w = extract_h( Lw ); /* w in Q9 */
3921 0 : dl = extract_l( Lw ); /* dl has 16 bits left-over */
3922 0 : w = s_and( w, 511 );
3923 : /* t1=cos_table[w%512]; */
3924 0 : t1 = cos_table[w];
3925 0 : move16();
3926 : /* t2=cos_table[add(w,1)%512]; */
3927 0 : dt = cos_diff_table[w];
3928 0 : move16();
3929 : /*t2=cos_table[s_and(add(w,1),511)]; */
3930 : /*dt = sub(t2,t1); */ /* Q15 */
3931 :
3932 0 : IF( dl < 0 )
3933 : {
3934 0 : L_tmp = L_add( 65536, dl );
3935 0 : Ltemp = imult3216( L_tmp, dt );
3936 : }
3937 : ELSE
3938 : {
3939 0 : Ltemp = (Word32) L_mult0( dt, dl ); /* Ltemp in Q31 */
3940 : }
3941 0 : cosTab[i] = add( t1, (Word16) L_shr( Ltemp, 16 ) );
3942 0 : move16(); /* interpolated cos(i*2pi/4L) */
3943 :
3944 0 : Ltemp = L_add( Lw, 0x1800000 ); /* add 0.75 in Q25, which is 3pi/2 to convert sin to cos */
3945 0 : w = extract_h( Ltemp ); /* w is equivalent cos index */
3946 : /*dl = extract_l(Ltemp); */ /* dl is 16 bit left-over for interpolation */
3947 0 : w = s_and( w, 511 );
3948 :
3949 :
3950 : /* t1=cos_table[w%512]; */
3951 0 : t1 = cos_table[w];
3952 0 : move16();
3953 : /* t2=cos_table[add(w,1)%512]; */
3954 0 : dt = cos_diff_table[w];
3955 0 : move16();
3956 : /*t2=cos_table[s_and(add(w,1),511)];move16(); */
3957 : /*dt = sub(t2,t1); */ /* dt=t2-t1, Q15 */
3958 :
3959 0 : IF( dl < 0 )
3960 : {
3961 0 : L_tmp = L_add( 65536, dl );
3962 0 : Ltemp = imult3216( L_tmp, dt );
3963 : }
3964 : ELSE
3965 : {
3966 0 : Ltemp = L_mult0( dt, dl ); /* Ltemp in Q31 */
3967 : }
3968 0 : sinTab[i] = add( t1, (Word16) L_shr( Ltemp, 16 ) );
3969 0 : move16(); /* t1 is interpolated cos(w) */
3970 :
3971 0 : Lw = L_add( Lw, invL ); /* Lw=(i+1)/4L, Q25 */
3972 : }
3973 0 : }
3974 :
3975 :
3976 : /*
3977 : * The decimation-in-time complex FFT/IFFT is implemented below.
3978 : * The input complex numbers are presented as real part followed by
3979 : * imaginary part for each sample. The counters are therefore
3980 : * incremented by two to access the complex valued samples.
3981 : */
3982 0 : static void c_fft_wi_fx( Word16 *farray_ptr_fx, Word16 size, Word16 stage, Word16 isign )
3983 : {
3984 :
3985 : Word16 i, j, k, ii, jj, kk, ji, kj;
3986 : Word32 ftmp_fx, ftmp_real_fx, ftmp_imag_fx;
3987 : Word16 tmp, tmp1, tmp2, temp_sand;
3988 : Word16 n_2, K;
3989 : Word16 ii_table[8];
3990 :
3991 0 : K = 0;
3992 0 : move16();
3993 :
3994 0 : FOR( k = 256; k > 0; k -= size )
3995 : {
3996 0 : K = add( K, 1 ); /* K=512/size */
3997 : }
3998 0 : n_2 = shr( size, 1 );
3999 0 : FOR( i = 1; i <= stage; i++ )
4000 : {
4001 0 : ii_table[i - 1] = shr( size, i );
4002 : }
4003 :
4004 : /* Rearrange the input array in bit reversed order */
4005 0 : j = 0;
4006 0 : move16();
4007 0 : FOR( i = 0; i < size - 2; i = i + 2 )
4008 : {
4009 :
4010 0 : IF( GT_16( j, i ) )
4011 : {
4012 0 : ftmp_fx = *( farray_ptr_fx + i );
4013 0 : *( farray_ptr_fx + i ) = *( farray_ptr_fx + j );
4014 0 : *( farray_ptr_fx + j ) = (Word16) ftmp_fx;
4015 0 : move32();
4016 0 : move16();
4017 0 : move16();
4018 :
4019 0 : ftmp_fx = *( farray_ptr_fx + add( i, 1 ) );
4020 0 : *( farray_ptr_fx + add( i, 1 ) ) = *( farray_ptr_fx + add( j, 1 ) );
4021 0 : *( farray_ptr_fx + add( j, 1 ) ) = (Word16) ftmp_fx;
4022 0 : move32();
4023 0 : move16();
4024 0 : move16();
4025 : }
4026 :
4027 0 : k = n_2;
4028 0 : move16();
4029 0 : WHILE( ( j >= k ) )
4030 : {
4031 0 : j = sub( j, k );
4032 0 : k = shr( k, 1 );
4033 : }
4034 0 : j = add( j, k );
4035 : }
4036 :
4037 : /* The FFT part */
4038 :
4039 :
4040 0 : IF( EQ_16( isign, 1 ) )
4041 : {
4042 0 : FOR( i = 0; i < stage; i++ ) /* i is stage counter */
4043 : {
4044 0 : jj = shl( 2, i ); /* FFT size */
4045 0 : kk = shl( jj, 1 ); /* 2 * FFT size */
4046 :
4047 0 : move16();
4048 :
4049 0 : ii = ii_table[i]; /* 2 * number of FFT's */
4050 :
4051 0 : FOR( j = 0; j < jj; j = j + 2 ) /* j is sample counter */
4052 : {
4053 0 : ji = i_mult( j, ii ); /* ji is phase table index */
4054 :
4055 0 : FOR( k = j; k < size; k = k + kk ) /* k is butterfly top */
4056 : {
4057 0 : kj = add( k, jj ); /* kj is butterfly bottom */
4058 0 : temp_sand = s_and( ( add( i_mult( ji, K ), 384 ) ), 511 );
4059 : /* Butterfly computations */
4060 : /* ftmp_real_fx = L_sub(L_mult(*(farray_ptr_fx + kj), cos_table[ji*K]), */
4061 : /* L_mult(*(farray_ptr_fx + kj + 1), cos_table[(ji*K+384)%512])); */
4062 0 : ftmp_real_fx = L_msu( L_mult( *( farray_ptr_fx + kj ), cos_table[( ji * K )] ),
4063 0 : *( farray_ptr_fx + add( kj, 1 ) ), cos_table[temp_sand] );
4064 :
4065 : /* ftmp_imag_fx = L_add(L_mult(*(farray_ptr_fx + kj + 1), cos_table[ji*K]), */
4066 : /* L_mult(*(farray_ptr_fx + kj), cos_table[(ji*K+384)%512])); */
4067 0 : ftmp_imag_fx = L_mac( L_mult( *( farray_ptr_fx + add( kj, 1 ) ), cos_table[( ji * K )] ),
4068 0 : *( farray_ptr_fx + kj ), cos_table[temp_sand] );
4069 :
4070 0 : tmp1 = round_fx( ftmp_real_fx );
4071 0 : tmp2 = round_fx( ftmp_imag_fx );
4072 :
4073 0 : tmp = sub( *( farray_ptr_fx + k ), tmp1 );
4074 0 : *( farray_ptr_fx + kj ) = shr( tmp, 1 );
4075 0 : move16();
4076 :
4077 0 : tmp = sub( *( farray_ptr_fx + add( k, 1 ) ), tmp2 );
4078 0 : *( farray_ptr_fx + add( kj, 1 ) ) = shr( tmp, 1 );
4079 0 : move16();
4080 :
4081 0 : tmp = add( *( farray_ptr_fx + k ), tmp1 );
4082 0 : *( farray_ptr_fx + k ) = shr( tmp, 1 );
4083 0 : move16();
4084 :
4085 0 : tmp = add( *( farray_ptr_fx + add( k, 1 ) ), tmp2 );
4086 0 : *( farray_ptr_fx + add( k, 1 ) ) = shr( tmp, 1 );
4087 0 : move16();
4088 : }
4089 : }
4090 : }
4091 :
4092 : /* The IFFT part */
4093 : }
4094 : ELSE
4095 : {
4096 0 : FOR( i = 0; i < stage; i++ ) /* i is stage counter */
4097 : {
4098 0 : jj = shl( 2, i ); /* FFT size */
4099 0 : kk = shl( jj, 1 ); /* 2 * FFT size */
4100 0 : ii = ii_table[i]; /* 2 * number of FFT's */
4101 :
4102 0 : FOR( j = 0; j < jj; j = j + 2 ) /* j is sample counter */
4103 : {
4104 0 : ji = i_mult( j, ii ); /* ji is phase table index */
4105 :
4106 0 : FOR( k = j; k < size; k = k + kk ) /* k is butterfly top */
4107 : {
4108 0 : kj = add( k, jj ); /* kj is butterfly bottom */
4109 0 : temp_sand = s_and( ( add( i_mult( ji, K ), 384 ) ), 511 );
4110 : /* Butterfly computations */
4111 : /* ftmp_real_fx = L_add(L_mult(*(farray_ptr_fx + kj), cos_table[ji*K]), */
4112 : /* L_mult(*(farray_ptr_fx + kj + 1), cos_table[(ji*K+384)%512])); */
4113 0 : ftmp_real_fx = L_mac( L_mult( *( farray_ptr_fx + kj ), cos_table[( ji * K )] ),
4114 0 : *( farray_ptr_fx + kj + 1 ), cos_table[temp_sand] );
4115 :
4116 : /* ftmp_imag_fx = L_sub(L_mult(*(farray_ptr_fx + kj + 1), cos_table[ji*K]), */
4117 : /* L_mult(*(farray_ptr_fx + kj), cos_table[(ji*K+384)%512])); */
4118 0 : ftmp_imag_fx = L_msu( L_mult( *( farray_ptr_fx + add( kj, 1 ) ), cos_table[( ji * K )] ),
4119 0 : *( farray_ptr_fx + kj ), cos_table[temp_sand] );
4120 :
4121 0 : tmp1 = round_fx( ftmp_real_fx );
4122 0 : tmp2 = round_fx( ftmp_imag_fx );
4123 :
4124 0 : *( farray_ptr_fx + kj ) = sub_sat( *( farray_ptr_fx + k ), tmp1 );
4125 0 : move16();
4126 0 : *( farray_ptr_fx + kj + 1 ) = sub_sat( *( farray_ptr_fx + k + 1 ), tmp2 );
4127 0 : move16();
4128 0 : *( farray_ptr_fx + k ) = add_sat( *( farray_ptr_fx + k ), tmp1 );
4129 0 : move16();
4130 0 : *( farray_ptr_fx + k + 1 ) = add_sat( *( farray_ptr_fx + k + 1 ), tmp2 );
4131 0 : move16();
4132 : }
4133 : }
4134 : }
4135 : }
4136 :
4137 0 : } /* end of c_fft () */
4138 :
4139 :
4140 0 : void r_fft_4_fx( Word16 *farray_ptr_fx /*Q0*/, Word16 size, Word16 stage, Word16 isign )
4141 : {
4142 :
4143 : Word16 ftmp1_real_fx, ftmp1_imag_fx, ftmp2_real_fx, ftmp2_imag_fx;
4144 : Word32 Lftmp1_real_fx, Lftmp1_imag_fx;
4145 : Word16 i, j, temp_sand;
4146 : Word32 Ltmp1_fx, Ltmp2_fx;
4147 : Word16 n_2, k, K;
4148 :
4149 0 : n_2 = shr( size, 1 );
4150 0 : K = 0;
4151 0 : move16();
4152 :
4153 0 : FOR( k = 256; k > 0; k -= size )
4154 : {
4155 0 : K = add( K, 1 ); /* K=512/size */
4156 : }
4157 :
4158 : /* The FFT part */
4159 0 : IF( EQ_16( isign, 1 ) )
4160 : {
4161 : /* Perform the complex FFT */
4162 0 : c_fft_wi_fx( farray_ptr_fx, size, stage, isign );
4163 :
4164 : /* First, handle the DC and foldover frequencies */
4165 0 : ftmp1_real_fx = *farray_ptr_fx;
4166 0 : ftmp2_real_fx = *( farray_ptr_fx + 1 );
4167 0 : *farray_ptr_fx = add( ftmp1_real_fx, ftmp2_real_fx );
4168 0 : move16();
4169 0 : *( farray_ptr_fx + 1 ) = sub( ftmp1_real_fx, ftmp2_real_fx );
4170 0 : move16();
4171 :
4172 : /* Now, handle the remaining positive frequencies */
4173 0 : j = sub( size, 2 );
4174 0 : FOR( i = 2; i <= n_2; i = i + 2 )
4175 : {
4176 0 : ftmp1_real_fx = add( *( farray_ptr_fx + i ), *( farray_ptr_fx + j ) );
4177 0 : ftmp1_imag_fx = sub( *( farray_ptr_fx + i + 1 ), *( farray_ptr_fx + j + 1 ) );
4178 0 : ftmp2_real_fx = add( *( farray_ptr_fx + i + 1 ), *( farray_ptr_fx + j + 1 ) );
4179 0 : ftmp2_imag_fx = sub( *( farray_ptr_fx + j ), *( farray_ptr_fx + i ) );
4180 :
4181 0 : Lftmp1_real_fx = L_deposit_h( ftmp1_real_fx );
4182 0 : Lftmp1_imag_fx = L_deposit_h( ftmp1_imag_fx );
4183 0 : temp_sand = s_and( add( i_mult( i, K ), 384 ), 511 );
4184 : /* Ltmp1_fx = L_sub(L_mult(ftmp2_real_fx, cos_table[i*K]), L_mult(ftmp2_imag_fx, cos_table[(i*K+384)%512])); */
4185 0 : Ltmp1_fx = L_msu( L_mult( ftmp2_real_fx, cos_table[( i * K )] ), ftmp2_imag_fx, cos_table[temp_sand] );
4186 0 : *( farray_ptr_fx + i ) = round_fx( L_shr( L_add( Lftmp1_real_fx, Ltmp1_fx ), 1 ) );
4187 0 : move16();
4188 :
4189 : /* Ltmp1_fx = L_add(L_mult(ftmp2_imag_fx, cos_table[i*K]), L_mult(ftmp2_real_fx, cos_table[(i*K+384)%512])); */
4190 0 : Ltmp1_fx = L_mac( L_mult( ftmp2_imag_fx, cos_table[( i * K )] ), ftmp2_real_fx, cos_table[temp_sand] );
4191 0 : *( farray_ptr_fx + i + 1 ) = round_fx( L_shr( L_add( Lftmp1_imag_fx, Ltmp1_fx ), 1 ) );
4192 0 : move16();
4193 :
4194 : /* Ltmp1_fx = L_add(L_mult(ftmp2_real_fx, cos_table[j*K]), L_mult(ftmp2_imag_fx, cos_table[(j*K+384)%512])); */
4195 0 : Ltmp1_fx = L_mac( L_mult( ftmp2_real_fx, cos_table[( j * K )] ), ftmp2_imag_fx, cos_table[temp_sand] );
4196 0 : *( farray_ptr_fx + j ) = round_fx( L_shr( L_add( Lftmp1_real_fx, Ltmp1_fx ), 1 ) );
4197 0 : move16();
4198 :
4199 : /* Ltmp1_fx = L_add(L_negate(L_mult(ftmp2_imag_fx, cos_table[j*K])), L_mult(ftmp2_real_fx, cos_table[(j*K+384)%512])); */
4200 0 : Ltmp1_fx = L_msu( L_mult( ftmp2_real_fx, cos_table[temp_sand] ), ftmp2_imag_fx, cos_table[( j * K )] );
4201 0 : Ltmp2_fx = L_sub( Ltmp1_fx, Lftmp1_imag_fx );
4202 0 : *( farray_ptr_fx + j + 1 ) = round_fx( L_shr( Ltmp2_fx, 1 ) );
4203 0 : move16();
4204 0 : j = sub( size, i );
4205 : }
4206 : }
4207 : ELSE
4208 : {
4209 :
4210 : /* First, handle the DC and foldover frequencies */
4211 :
4212 0 : move16();
4213 0 : move16();
4214 :
4215 0 : ftmp1_real_fx = *farray_ptr_fx;
4216 0 : ftmp2_real_fx = *( farray_ptr_fx + 1 );
4217 0 : *farray_ptr_fx = shr( add( ftmp1_real_fx, ftmp2_real_fx ), 1 );
4218 0 : move16();
4219 0 : *( farray_ptr_fx + 1 ) = shr( sub( ftmp1_real_fx, ftmp2_real_fx ), 1 );
4220 0 : move16();
4221 :
4222 : /* Now, handle the remaining positive frequencies */
4223 0 : FOR( i = 2; i <= n_2; i += 2 )
4224 : {
4225 0 : j = sub( size, i );
4226 :
4227 0 : ftmp1_real_fx = add( *( farray_ptr_fx + i ), *( farray_ptr_fx + j ) );
4228 0 : ftmp1_imag_fx = sub( *( farray_ptr_fx + i + 1 ), *( farray_ptr_fx + j + 1 ) );
4229 0 : ftmp2_real_fx = negate( add( *( farray_ptr_fx + j + 1 ), *( farray_ptr_fx + i + 1 ) ) );
4230 0 : ftmp2_imag_fx = negate( sub( *( farray_ptr_fx + j ), *( farray_ptr_fx + i ) ) );
4231 :
4232 0 : Lftmp1_real_fx = L_deposit_h( ftmp1_real_fx );
4233 0 : Lftmp1_imag_fx = L_deposit_h( ftmp1_imag_fx );
4234 0 : temp_sand = s_and( ( add( i_mult( i, K ), 384 ) ), 511 );
4235 : /* Ltmp1_fx = L_add(L_mult(ftmp2_real_fx, cos_table[i*K]), L_mult(ftmp2_imag_fx, cos_table[(i*K+384)%512])); */
4236 0 : Ltmp1_fx = L_mac( L_mult( ftmp2_real_fx, cos_table[( i * K )] ), ftmp2_imag_fx, cos_table[temp_sand] );
4237 0 : *( farray_ptr_fx + i ) = round_fx( L_shr( L_add( Lftmp1_real_fx, Ltmp1_fx ), 1 ) );
4238 0 : move16();
4239 :
4240 : /* Ltmp1_fx = L_sub(L_mult(ftmp2_imag_fx, cos_table[i*K]), L_mult(ftmp2_real_fx, cos_table[(i*K+384)%512])); */
4241 0 : Ltmp1_fx = L_msu( L_mult( ftmp2_imag_fx, cos_table[( i * K )] ), ftmp2_real_fx, cos_table[temp_sand] );
4242 0 : *( farray_ptr_fx + i + 1 ) = round_fx( L_shr( L_add( Lftmp1_imag_fx, Ltmp1_fx ), 1 ) );
4243 0 : move16();
4244 :
4245 : /* Ltmp1_fx = L_sub(L_mult(ftmp2_real_fx, cos_table[j*K]), L_mult(ftmp2_imag_fx, cos_table[(j*K+384)%512])); */
4246 0 : Ltmp1_fx = L_msu( L_mult( ftmp2_real_fx, cos_table[( j * K )] ), ftmp2_imag_fx, cos_table[temp_sand] );
4247 0 : *( farray_ptr_fx + j ) = round_fx( L_shr( L_add( Lftmp1_real_fx, Ltmp1_fx ), 1 ) );
4248 0 : move16();
4249 :
4250 : /* Ltmp1_fx = L_negate(L_add(L_mult(ftmp2_imag_fx, cos_table[j*K]), L_mult(ftmp2_real_fx, cos_table[(j*K+384)%512]))); */
4251 0 : Ltmp1_fx = L_negate( L_mac( L_mult( ftmp2_imag_fx, cos_table[( j * K )] ), ftmp2_real_fx, cos_table[temp_sand] ) );
4252 0 : Ltmp2_fx = L_sub( Ltmp1_fx, Lftmp1_imag_fx );
4253 0 : *( farray_ptr_fx + j + 1 ) = round_fx( L_shr( Ltmp2_fx, 1 ) );
4254 0 : move16();
4255 : }
4256 :
4257 : /* Perform the complex IFFT */
4258 0 : c_fft_wi_fx( farray_ptr_fx, size, stage, isign );
4259 : }
4260 0 : }
4261 :
4262 :
4263 : /*===================================================================*/
4264 : /* FUNCTION : struct DTFS_fx::copy_phase_fx () */
4265 : /*-------------------------------------------------------------------*/
4266 : /* PURPOSE : Retain the amplitudes of a prototype X2, but copy*/
4267 : /* the phases of another prototype X1 of same length*/
4268 : /* over to make a new prototype */
4269 : /*-------------------------------------------------------------------*/
4270 : /* INPUT ARGUMENTS : */
4271 : /* _ (struct DTFS_fx) X1 : prototype in Cartesian domain */
4272 : /* (Word16) X1.lag: length of prototype in time domain*/
4273 : /* (Word16 []) X1.a,b: re/im of harmonics, normalized */
4274 : /* (Word16) X1.Q: norm factor of X2.a/b */
4275 : /* _ (struct DTFS_fx) X2 : prototype in polar domain */
4276 : /* (Word16) X2.lag: should be same as X1.lag */
4277 : /* (Word16 []) X2.a:amplitude of harmonics, normalized*/
4278 : /* (Word16 []) X2.b: phase of harmonics, don't care */
4279 : /* (Word16) X2.Q: norm factor of X2.a */
4280 : /*-------------------------------------------------------------------*/
4281 : /* OUTPUT ARGUMENTS : */
4282 : /* _ None */
4283 : /*-------------------------------------------------------------------*/
4284 : /* INPUT/OUTPUT ARGUMENTS : */
4285 : /* _ None */
4286 : /*-------------------------------------------------------------------*/
4287 : /* RETURN ARGUMENTS : */
4288 : /* _ (struct DTFS_fx) X : prototype in Cartesian domain */
4289 : /* The amplitudes of this prototype are from X2 */
4290 : /* and the phases are from X1 */
4291 : /*-------------------------------------------------------------------*/
4292 : /* CALLED FROM : TX/RX */
4293 : /*===================================================================*/
4294 : /* X.a[k]=2*X2.a[k]/sqrt(X1.a[k]^2+X1.b[k]^2)*X1.a[k] */
4295 : /* X.b[k]=2*X2.a[k]/sqrt(X1.a[k]^2+X1.b[k]^2)*X1.b[k] */
4296 : /*===================================================================*/
4297 0 : void copy_phase_fx( DTFS_STRUCTURE *X1_fx, DTFS_STRUCTURE X2_fx, DTFS_STRUCTURE *retX_fx )
4298 : {
4299 : /* DTFS_fx X; */
4300 : Word16 k, q, sn, cn, HalfLag;
4301 : Word16 d1h, d1l;
4302 : Word32 Ltemp_fx, L_tmp;
4303 : Word32 Lacc_fx;
4304 : Word16 exp, tmp, exp1;
4305 : #ifndef ISSUE_1836_replace_overflow_libcom__remnant
4306 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
4307 : Flag Overflow = 0;
4308 : move32();
4309 : #endif
4310 : #endif
4311 :
4312 0 : retX_fx->lag_fx = X1_fx->lag_fx;
4313 0 : move16();
4314 0 : retX_fx->Q = sub( X2_fx.Q, 1 ); /* equivalent to 2x MIN_FX(shr(sub(X_fx->lag_fx,1),1),X_fx->nH_fx) */
4315 0 : move16();
4316 0 : HalfLag = s_min( shr( X1_fx->lag_fx, 1 ), X1_fx->nH_fx );
4317 :
4318 0 : FOR( k = 1; k <= HalfLag; k++ )
4319 : {
4320 : #ifdef ISSUE_1836_replace_overflow_libcom__remnant
4321 0 : Lacc_fx = L_mult_sat( X1_fx->a_fx[k], X1_fx->a_fx[k] );
4322 0 : Lacc_fx = L_mac_sat( Lacc_fx, X1_fx->b_fx[k], X1_fx->b_fx[k] ); /* 2*Q+1 */
4323 : #else
4324 : Lacc_fx = L_mult_o( X1_fx->a_fx[k], X1_fx->a_fx[k], &Overflow );
4325 : Lacc_fx = L_mac_o( Lacc_fx, X1_fx->b_fx[k], X1_fx->b_fx[k], &Overflow ); /* 2*Q+1 */
4326 : #endif
4327 :
4328 0 : exp = norm_l( Lacc_fx );
4329 0 : tmp = extract_h( L_shl( Lacc_fx, exp ) );
4330 0 : exp1 = sub( sub( 30, exp ), 2 * X1_fx->Q + 1 );
4331 :
4332 0 : IF( tmp )
4333 : {
4334 0 : tmp = div_s( 16384, tmp ); /* 15+exp1 */
4335 : }
4336 : ELSE
4337 : {
4338 0 : tmp = 0;
4339 0 : move16();
4340 : }
4341 0 : tmp = shr( tmp, 1 );
4342 0 : q = sub( add( add( 15, exp1 ), 16 ), 1 );
4343 :
4344 0 : IF( tmp )
4345 : {
4346 0 : exp = norm_s( tmp );
4347 0 : tmp = shl( tmp, exp );
4348 0 : tmp = div_s( 16384, tmp );
4349 0 : L_tmp = L_deposit_h( tmp );
4350 0 : Ltemp_fx = Isqrt_lc( L_tmp, &exp ); /* Q(31-exp) */
4351 : }
4352 : ELSE
4353 : {
4354 0 : Ltemp_fx = 0;
4355 0 : move32();
4356 : }
4357 :
4358 0 : IF( s_and( q, 1 ) )
4359 : {
4360 0 : Ltemp_fx = Mult_32_16( Ltemp_fx, 23170 ); /* 23170 is 1/sqrt(2) in Q15 */
4361 : }
4362 :
4363 0 : q = shr( q, 1 ); /* Ltemp_fx in Q(q+16) */
4364 :
4365 0 : d1h = extract_h( Ltemp_fx );
4366 0 : d1l = extract_l( Ltemp_fx );
4367 0 : Ltemp_fx = L_mult0( X1_fx->b_fx[k], d1l );
4368 : #ifdef ISSUE_1836_replace_overflow_libcom__remnant
4369 0 : Ltemp_fx = L_add_sat( L_shr( Ltemp_fx, 15 ), L_mult_sat( X1_fx->b_fx[k], d1h ) ); /* sin(w) in Q(q+16+Q-15) */
4370 0 : sn = round_fx_sat( L_shl_sat( Ltemp_fx, sub( 30, add( q, X1_fx->Q ) ) ) ); /* Q15 */
4371 0 : retX_fx->b_fx[k] = mult_r_sat( X2_fx.a_fx[k], sn ); /* X2_fx.Q */
4372 0 : move16();
4373 :
4374 0 : Ltemp_fx = L_mult0( X1_fx->a_fx[k], d1l );
4375 0 : Ltemp_fx = L_add_sat( L_shr( Ltemp_fx, 15 ), L_mult_sat( X1_fx->a_fx[k], d1h ) ); /* cos(w) in Q(q+Q+1) */
4376 0 : cn = round_fx_sat( L_shl_sat( Ltemp_fx, sub( 30, add( q, X1_fx->Q ) ) ) ); /* Q15 */
4377 0 : retX_fx->a_fx[k] = mult_r_sat( X2_fx.a_fx[k], cn ); /* X2_fx.Q */
4378 : #else
4379 : Ltemp_fx = L_add_o( L_shr( Ltemp_fx, 15 ), L_mult_o( X1_fx->b_fx[k], d1h, &Overflow ), &Overflow ); /* sin(w) in Q(q+16+Q-15) */
4380 : sn = round_fx_o( L_shl_o( Ltemp_fx, sub( 30, add( q, X1_fx->Q ) ), &Overflow ), &Overflow ); /* Q15 */
4381 : retX_fx->b_fx[k] = mult_ro( X2_fx.a_fx[k], sn, &Overflow ); /* X2_fx.Q */
4382 : move16();
4383 :
4384 : Ltemp_fx = L_mult0( X1_fx->a_fx[k], d1l );
4385 : Ltemp_fx = L_add_o( L_shr( Ltemp_fx, 15 ), L_mult_o( X1_fx->a_fx[k], d1h, &Overflow ), &Overflow ); /* cos(w) in Q(q+Q+1) */
4386 : cn = round_fx_o( L_shl_o( Ltemp_fx, sub( 30, add( q, X1_fx->Q ) ), &Overflow ), &Overflow ); /* Q15 */
4387 : retX_fx->a_fx[k] = mult_ro( X2_fx.a_fx[k], cn, &Overflow ); /* X2_fx.Q */
4388 : #endif
4389 0 : move16();
4390 : }
4391 0 : k = sub( k, 1 );
4392 :
4393 :
4394 0 : IF( s_and( X1_fx->lag_fx, 1 ) == 0 )
4395 : {
4396 0 : retX_fx->a_fx[k] = shr( retX_fx->a_fx[k], 1 );
4397 0 : move16();
4398 0 : retX_fx->b_fx[k] = shr( retX_fx->b_fx[k], 1 );
4399 0 : move16();
4400 : }
4401 0 : }
4402 :
4403 :
4404 : /*===================================================================*/
4405 : /* FUNCTION : getSpEngyFromResAmp_fx () */
4406 : /*-------------------------------------------------------------------*/
4407 : /* PURPOSE : Get band energy */
4408 : /*-------------------------------------------------------------------*/
4409 : /* INPUT ARGUMENTS : */
4410 : /* _ (struct DTFS_STRUCTURE) X_fx : prototype in polar domain */
4411 : /* (Word16) lag: length of prototype in time domain */
4412 : /* (Word16 []) a: amplitude of harmonics, normalized */
4413 : /* (Word16) Q: norm factor of a */
4414 : /* _ (Word16 []) curr_lpc: LPC coefficients, Q12 */
4415 : /* _ (Word16) lband: lower frequency bound, Q15 */
4416 : /* _ (Word16) hband: upper frequency bound, Q15 */
4417 : /* _ (Word16 []) sin_tab: sine table based on lag, Q15 */
4418 : /* _ (Word16 []) cos_tab: cosine table based on lag, Q15 */
4419 : /*-------------------------------------------------------------------*/
4420 : /* OUTPUT ARGUMENTS : */
4421 : /* _ None */
4422 : /*-------------------------------------------------------------------*/
4423 : /* INPUT/OUTPUT ARGUMENTS : */
4424 : /* _ None */
4425 : /*-------------------------------------------------------------------*/
4426 : /* RETURN ARGUMENTS : */
4427 : /* _ (Word32) en: energy of the specified frequency band, */
4428 : /* Q factor is 2Q-13 */
4429 : /*-------------------------------------------------------------------*/
4430 : /* CALLED FROM : TX */
4431 : /*===================================================================*/
4432 0 : Word32 getSpEngyFromResAmp_fx( DTFS_STRUCTURE *X_fx, Word16 lband, Word16 hband, const Word16 *curr_lpc, Word16 *sin_tab, Word16 *cos_tab )
4433 : {
4434 : Word16 i, k, k4, n, M_fx, HalfLag;
4435 : Word16 fdiff, freq;
4436 : Word32 Ltemp;
4437 : Word32 Lacc;
4438 : Word32 Re, Im; /* Q27 */
4439 : Word32 en;
4440 : Word16 exp, tmp, expa, fraca, expb, fracb, scale;
4441 : Word32 L_tmp;
4442 : #ifndef ISSUE_1836_replace_overflow_libcom__remnant
4443 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
4444 : Flag Overflow = 0;
4445 : move32();
4446 : #endif
4447 : #endif
4448 0 : en = L_deposit_l( 0 );
4449 :
4450 0 : if ( EQ_16( hband, X_fx->upper_cut_off_freq_fx ) )
4451 : {
4452 0 : hband = 0x2803;
4453 0 : move16(); /* 4001.0/12800 in Q15 */
4454 : }
4455 0 : M_fx = shl( X_fx->lag_fx, 2 ); /* M_fx=4*lag */
4456 :
4457 : /* Ltemp=invert_dp(X_fx->lag_fx, 4, &n,1); : Ltemp=1/lag, Q(61-n) */
4458 : /* fdiff=round_fx(L_shl(Ltemp,sub(n,26))); : fdiff=1/lag, Q19 */
4459 :
4460 0 : exp = norm_s( X_fx->lag_fx );
4461 0 : tmp = div_s( shl( 1, sub( 14, exp ) ), X_fx->lag_fx );
4462 0 : L_tmp = L_shl( tmp, add( exp, 6 ) );
4463 0 : fdiff = round_fx( L_tmp );
4464 :
4465 0 : HalfLag = s_min( shr( X_fx->lag_fx, 1 ), X_fx->nH_4kHz_fx );
4466 0 : FOR( k = 0; k <= HalfLag; k++ )
4467 : {
4468 0 : Ltemp = L_mult( fdiff, k ); /* Ltemp=k*fdiff, Q20 */
4469 0 : freq = extract_h( L_shl( Ltemp, 11 ) ); /* k*fdiff in Q15 */
4470 :
4471 0 : test();
4472 0 : IF( LT_16( freq, hband ) && GE_16( freq, lband ) )
4473 : {
4474 0 : Lacc = L_add( 0x10000000, 0 ); /* Re=1.0, Q28 */
4475 0 : k4 = shl( k, 2 ); /* k4=4*k */
4476 :
4477 0 : n = k4;
4478 0 : move16();
4479 0 : FOR( i = 0; i < M + 1; i++ )
4480 : {
4481 : /* Compute Re */
4482 : #ifdef ISSUE_1836_replace_overflow_libcom__remnant
4483 0 : Lacc = L_mac_sat( Lacc, curr_lpc[i], cos_tab[n % M_fx] ); /* Q28 */
4484 : #else
4485 : Lacc = L_mac_o( Lacc, curr_lpc[i], cos_tab[n % M_fx], &Overflow ); /* Q28 */
4486 : #endif
4487 0 : n = add( n, k4 ); /* n=4*i*k */
4488 : }
4489 0 : Re = L_shr( Lacc, 1 ); /* Q27 */
4490 :
4491 0 : n = k4;
4492 0 : move16();
4493 0 : Lacc = L_deposit_l( 0 );
4494 0 : FOR( i = 0; i < M + 1; i++ )
4495 : {
4496 : /* Compute Im */
4497 : #ifdef ISSUE_1836_replace_overflow_libcom__remnant
4498 0 : Lacc = L_msu_sat( Lacc, curr_lpc[i], sin_tab[n % M_fx] ); /* Q28 */
4499 : #else
4500 : Lacc = L_msu_o( Lacc, curr_lpc[i], sin_tab[n % M_fx], &Overflow ); /* Q28 */
4501 : #endif
4502 0 : n = add( n, k4 ); /* n=4*i*k */
4503 : }
4504 0 : Im = L_shr( Lacc, 1 ); /* Q27 */
4505 : /* Lacc=L_add(L_mult_ll(Re,Re),(Word32)L_mult_ll(Im,Im)); : Lacc=Re^2+Im^2 in Q23 */
4506 : #ifdef ISSUE_1836_replace_overflow_libcom__remnant
4507 0 : Lacc = L_add_sat( Mult_32_32( Re, Re ), Mult_32_32( Im, Im ) ); /* Lacc=Re^2+Im^2 in Q23 */
4508 : #else
4509 : Lacc = L_add_o( Mult_32_32( Re, Re ), Mult_32_32( Im, Im ), &Overflow ); /* Lacc=Re^2+Im^2 in Q23 */
4510 : #endif
4511 0 : Ltemp = L_mult0( X_fx->a_fx[k], X_fx->a_fx[k] ); /* 2*a[k]^2 in 2Q */
4512 : /* Ltemp=(Word32)L_sat32_40(divide_dp(Ltemp,Lacc,-19,1)); : Ltemp in Q(2Q-13) */
4513 :
4514 0 : if ( Lacc < 0 )
4515 : {
4516 0 : Lacc = L_negate( Lacc );
4517 : }
4518 :
4519 0 : IF( Lacc )
4520 : {
4521 :
4522 0 : expa = norm_l( Lacc );
4523 0 : fraca = extract_h( L_shl( Lacc, expa ) );
4524 0 : expa = sub( 30, add( expa, 23 ) );
4525 :
4526 :
4527 0 : expb = norm_l( Ltemp );
4528 0 : fracb = round_fx( L_shl( Ltemp, expb ) );
4529 0 : expb = sub( 30, add( expb, shl( X_fx->Q, 1 ) ) );
4530 :
4531 0 : scale = shr( sub( fraca, fracb ), 15 );
4532 0 : fracb = shl( fracb, scale );
4533 0 : expb = sub( expb, scale );
4534 :
4535 0 : tmp = div_s( fracb, fraca ); /* 15-exp */
4536 0 : exp = sub( expb, expa );
4537 : #ifdef ISSUE_1836_replace_overflow_libcom__remnant
4538 0 : Ltemp = L_shl_sat( tmp, sub( add( shl( X_fx->Q, 1 ), exp ), 27 ) );
4539 : #else
4540 : Ltemp = L_shl_o( tmp, sub( add( shl( X_fx->Q, 1 ), exp ), 27 ), &Overflow );
4541 : #endif
4542 : }
4543 : ELSE
4544 : {
4545 0 : Ltemp = L_deposit_l( 0 );
4546 : }
4547 :
4548 0 : test();
4549 0 : IF( X_fx->lag_fx % 2 == 0 && EQ_16( k, shr( X_fx->lag_fx, 1 ) ) )
4550 0 : en = L_add( en, L_shr( Ltemp, 1 ) );
4551 : ELSE
4552 0 : en = L_add( en, Ltemp ); /* en in 2Q-13 */
4553 : }
4554 : }
4555 0 : return ( en ); /* en in 2Q-13 */
4556 : }
4557 : /*===================================================================*/
4558 : /* FUNCTION : DTFS_poleFilter_fx() */
4559 : /*-------------------------------------------------------------------*/
4560 : /* PURPOSE : pole filtering */
4561 : /*-------------------------------------------------------------------*/
4562 : /* INPUT ARGUMENTS : */
4563 : /* _ (Word16) lpc[] : lpc coefficients in Q12 */
4564 : /* _ (Word16) N : lpc order */
4565 : /* _ (Word16) X_fx->lag_fx: in Q0 */
4566 : /* _ (Word16 *) S_fx: sin(2pi*n/(4*lag)) table, Q15 */
4567 : /* _ (Word16 *) C_fx: cos(2pi*n/(4*lag)) table, Q15 */
4568 : /*-------------------------------------------------------------------*/
4569 : /* OUTPUT ARGUMENTS : */
4570 : /* _ None */
4571 : /*-------------------------------------------------------------------*/
4572 : /* INPUT/OUTPUT ARGUMENTS : */
4573 : /* _ (Word16) X_fx->a_fx[] : in Q(X_fx->Q) */
4574 : /* _ (Word16) X_fx->b_fx[] : in Q(X_fx->Q) */
4575 : /* _ (Word16) X_fx->Q: in Q0 */
4576 : /*-------------------------------------------------------------------*/
4577 : /* RETURN ARGUMENTS : _ None. */
4578 : /*-------------------------------------------------------------------*/
4579 : /* CALLED FROM : TX/RX */
4580 : /*===================================================================*/
4581 0 : void DTFS_poleFilter_fx( DTFS_STRUCTURE *X_fx, Word16 *LPC, Word16 N, Word16 *S_fx, Word16 *C_fx )
4582 : {
4583 : Word16 temp, temp1, temp2, HalfLag;
4584 : Word32 sum1_fx, sum2_fx;
4585 : Word32 sum, L_temp1, L_temp2;
4586 : Word16 k, n, na, nb;
4587 : Word16 Qmin, Qab[MAXLAG_WI];
4588 : Word16 exp, tmp;
4589 : #ifndef ISSUE_1836_replace_overflow_libcom__remnant
4590 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
4591 : Flag Overflow = 0;
4592 : move32();
4593 : #endif
4594 : #endif
4595 0 : Qmin = 32767;
4596 0 : move16();
4597 0 : HalfLag = s_min( shr( X_fx->lag_fx, 1 ), X_fx->nH_fx );
4598 0 : FOR( k = 0; k <= HalfLag; k++ )
4599 : {
4600 0 : temp2 = k;
4601 0 : move16();
4602 : /* Calculate sum1 and sum2 */
4603 0 : sum1_fx = L_deposit_h( 4096 ); /* 1: Q(12+15+1) */
4604 :
4605 0 : sum2_fx = L_deposit_l( 0 );
4606 0 : FOR( n = 0; n < N; n++ )
4607 : {
4608 : #ifdef ISSUE_1836_replace_overflow_libcom__remnant
4609 0 : sum1_fx = L_mac_sat( sum1_fx, LPC[n], C_fx[shl( temp2, 2 ) % shl( X_fx->lag_fx, 2 )] ); /* Q(12+15+1) */
4610 0 : sum2_fx = L_mac_sat( sum2_fx, LPC[n], S_fx[shl( temp2, 2 ) % shl( X_fx->lag_fx, 2 )] ); /* Q(12+15+1) */
4611 : #else
4612 : sum1_fx = L_mac_o( sum1_fx, LPC[n], C_fx[shl( temp2, 2 ) % shl( X_fx->lag_fx, 2 )], &Overflow ); /* Q(12+15+1) */
4613 : sum2_fx = L_mac_o( sum2_fx, LPC[n], S_fx[shl( temp2, 2 ) % shl( X_fx->lag_fx, 2 )], &Overflow ); /* Q(12+15+1) */
4614 : #endif
4615 0 : temp2 = add( temp2, k );
4616 : }
4617 :
4618 : #ifdef ISSUE_1836_replace_overflow_libcom__remnant
4619 0 : temp1 = round_fx_sat( sum1_fx ); /* Q(12+15+1-16)=Q(12) */
4620 0 : temp2 = round_fx_sat( sum2_fx ); /* Q(12) */
4621 : /* Calculate the circular convolution */
4622 0 : sum = L_mac_sat( L_mult_sat( temp1, temp1 ), temp2, temp2 ); /* Q(12+12+1)=Q(25) */
4623 :
4624 0 : L_temp1 = L_mult( temp1, X_fx->a_fx[k] );
4625 0 : L_temp1 = L_mac_sat( L_temp1, temp2, X_fx->b_fx[k] ); /* Q(12+Q+1)=Q(13+Q) */
4626 0 : L_temp2 = L_mult( temp1, X_fx->b_fx[k] );
4627 0 : L_temp2 = L_msu_sat( L_temp2, temp2, X_fx->a_fx[k] ); /* Q(12+Q+1)=Q(13+Q) */
4628 : #else
4629 : temp1 = round_fx_o( sum1_fx, &Overflow ); /* Q(12+15+1-16)=Q(12) */
4630 : temp2 = round_fx_o( sum2_fx, &Overflow ); /* Q(12) */
4631 : /* Calculate the circular convolution */
4632 : sum = L_mac_o( L_mult_o( temp1, temp1, &Overflow ), temp2, temp2, &Overflow ); /* Q(12+12+1)=Q(25) */
4633 :
4634 : L_temp1 = L_mult( temp1, X_fx->a_fx[k] );
4635 : L_temp1 = L_mac_o( L_temp1, temp2, X_fx->b_fx[k], &Overflow ); /* Q(12+Q+1)=Q(13+Q) */
4636 : L_temp2 = L_mult( temp1, X_fx->b_fx[k] );
4637 : L_temp2 = L_msu_o( L_temp2, temp2, X_fx->a_fx[k], &Overflow ); /* Q(12+Q+1)=Q(13+Q) */
4638 : #endif
4639 0 : IF( sum )
4640 : {
4641 0 : exp = norm_l( sum );
4642 0 : temp1 = exp;
4643 0 : tmp = extract_h( L_shl( sum, exp ) );
4644 0 : exp = sub( sub( 30, exp ), 25 );
4645 0 : tmp = div_s( 16384, tmp ); /* Q(15+exp) */
4646 0 : sum = L_shl( tmp, 16 );
4647 0 : temp = round_fx( sum );
4648 : }
4649 : ELSE
4650 : {
4651 0 : sum = 0;
4652 0 : move16();
4653 0 : temp = 0;
4654 0 : move16();
4655 0 : temp1 = 0;
4656 0 : move16();
4657 : }
4658 0 : sum1_fx = Mult_32_16( L_temp1, temp ); /* Q(13+Q+20-temp1-15)=Q(Q-temp1+18) */
4659 0 : sum2_fx = Mult_32_16( L_temp2, temp ); /* Q(Q-temp1+18) */
4660 :
4661 : /* normalization */
4662 0 : na = norm_l( sum1_fx );
4663 0 : if ( sum1_fx == 0 )
4664 : {
4665 0 : na = 31;
4666 0 : move16();
4667 : }
4668 0 : nb = norm_l( sum2_fx );
4669 0 : if ( sum2_fx == 0 )
4670 : {
4671 0 : nb = 31;
4672 0 : move16();
4673 : }
4674 :
4675 0 : if ( LT_16( na, nb ) )
4676 : {
4677 0 : nb = na;
4678 0 : move16();
4679 : }
4680 0 : nb = sub( nb, 1 ); /* leave one more sign bit */
4681 0 : X_fx->a_fx[k] = round_fx( L_shl( sum1_fx, nb ) ); /* Q(Q-temp1+22+nb-16)=Q(Q-temp1+nb+2) */
4682 0 : move16();
4683 0 : X_fx->b_fx[k] = round_fx( L_shl( sum2_fx, nb ) ); /* Q(Q-temp1+nb+2) */
4684 0 : move16();
4685 :
4686 0 : Qab[k] = add( sub( add( nb, 2 ), temp1 ), X_fx->Q );
4687 :
4688 0 : if ( LT_16( Qab[k], Qmin ) )
4689 : {
4690 0 : Qmin = Qab[k];
4691 0 : move16();
4692 : }
4693 : }
4694 : /* bring to the same Q */
4695 0 : FOR( k = 0; k <= HalfLag; k++ )
4696 : {
4697 0 : X_fx->a_fx[k] = shl( X_fx->a_fx[k], sub( Qmin, Qab[k] ) );
4698 0 : move16(); /* Q(Q+Qab[k]+Qmin-Qab[k])=Q(Q+Qmin) */
4699 0 : X_fx->b_fx[k] = shl( X_fx->b_fx[k], sub( Qmin, Qab[k] ) );
4700 0 : move16(); /* Q(Q+Qab[k]+Qmin-Qab[k])=Q(Q+Qmin) */
4701 : }
4702 :
4703 0 : X_fx->Q = Qmin;
4704 0 : move16();
4705 0 : }
4706 : /*===================================================================*/
4707 : /* FUNCTION : poleFilter_setup_fx() */
4708 : /*-------------------------------------------------------------------*/
4709 : /* PURPOSE : Sets up pole filtering LPC dependent intermediate*/
4710 : /* values to be used by poleFilter */
4711 : /*-------------------------------------------------------------------*/
4712 : /* INPUT ARGUMENTS : */
4713 : /* _ (Word16) lpc[] : lpc coefficients in Q12 */
4714 : /* _ (Word16) N : lpc order */
4715 : /* _ (Word16) lag : in Q0 */
4716 : /* _ (Word16 *) S_fx: sin(2pi*n/(4*lag)) table, Q15 */
4717 : /* _ (Word16 *) C_fx: cos(2pi*n/(4*lag)) table, Q15 */
4718 : /*-------------------------------------------------------------------*/
4719 : /* OUTPUT ARGUMENTS : */
4720 : /* _ None */
4721 : /*-------------------------------------------------------------------*/
4722 : /* INPUT/OUTPUT ARGUMENTS : */
4723 : /* _ None */
4724 : /*-------------------------------------------------------------------*/
4725 : /* RETURN ARGUMENTS : _ None. */
4726 : /*-------------------------------------------------------------------*/
4727 : /* CALLED FROM : TX/RX */
4728 : /*===================================================================*/
4729 0 : void poleFilter_setup_fx( const Word16 *LPC, Word16 N, DTFS_STRUCTURE X_fx, Word16 *S_fx, Word16 *C_fx, Word16 *pf_temp1, Word16 *pf_temp2, Word16 *pf_temp, Word16 *pf_n2_temp1 )
4730 : {
4731 : Word16 temp1, temp2, HalfLag;
4732 : Word32 sum1_fx, sum2_fx;
4733 : Word32 sum;
4734 : Word16 k, n, n1, n2;
4735 : Word16 exp, tmp;
4736 : #ifndef ISSUE_1836_replace_overflow_libcom__remnant
4737 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
4738 : Flag Overflow = 0;
4739 : move32();
4740 : #endif
4741 : #endif
4742 0 : HalfLag = s_min( shr( X_fx.lag_fx, 1 ), X_fx.nH_fx );
4743 :
4744 0 : FOR( k = 0; k <= HalfLag; k++ )
4745 : {
4746 0 : temp2 = k;
4747 0 : move16();
4748 : /* Calculate sum1 and sum2 */
4749 0 : sum1_fx = L_deposit_h( 4096 ); /* 1: Q(12+15+1) */
4750 :
4751 0 : sum2_fx = L_deposit_l( 0 );
4752 0 : FOR( n = 0; n < N; n++ )
4753 : {
4754 : #ifndef ISSUE_1836_replace_overflow_libcom__remnant
4755 : sum1_fx = L_mac_o( sum1_fx, LPC[n], C_fx[( 4 * temp2 ) % ( 4 * X_fx.lag_fx )], &Overflow ); /* Q(12+15+1) */
4756 : sum2_fx = L_mac_o( sum2_fx, LPC[n], S_fx[( 4 * temp2 ) % ( 4 * X_fx.lag_fx )], &Overflow ); /* Q(12+15+1) */
4757 : #else
4758 0 : sum1_fx = L_mac_sat( sum1_fx, LPC[n], C_fx[( 4 * temp2 ) % ( 4 * X_fx.lag_fx )] ); /* Q(12+15+1) */
4759 0 : sum2_fx = L_mac_sat( sum2_fx, LPC[n], S_fx[( 4 * temp2 ) % ( 4 * X_fx.lag_fx )] ); /* Q(12+15+1) */
4760 : #endif
4761 0 : temp2 = add( temp2, k );
4762 : }
4763 :
4764 0 : n1 = norm_l( sum1_fx );
4765 0 : if ( sum1_fx == 0 )
4766 : {
4767 0 : n1 = 31;
4768 0 : move16();
4769 : }
4770 :
4771 0 : n2 = norm_l( sum2_fx );
4772 0 : if ( sum2_fx == 0 )
4773 : {
4774 0 : n2 = 31;
4775 0 : move16();
4776 : }
4777 :
4778 0 : if ( LT_16( n1, n2 ) )
4779 : {
4780 0 : n2 = n1;
4781 0 : move16();
4782 : }
4783 0 : n2 = sub( n2, 1 );
4784 0 : temp1 = pf_temp1[k] = round_fx( (Word32) L_shl( sum1_fx, n2 ) ); /* Q(12+15+1+n2-16)=Q(12+n2) */
4785 0 : move16();
4786 0 : move16();
4787 0 : temp2 = pf_temp2[k] = round_fx( (Word32) L_shl( sum2_fx, n2 ) ); /* Q(12+n2) */
4788 0 : move16();
4789 0 : move16();
4790 :
4791 : /* Calculate the circular convolution */
4792 0 : sum = L_mac( L_mult( temp1, temp1 ), temp2, temp2 ); /* Q(12+n2+12+n2+1)=Q(25+2*n2) */
4793 :
4794 0 : exp = norm_l( sum );
4795 0 : tmp = extract_h( L_shl( sum, exp ) );
4796 0 : exp = sub( sub( 30, exp ), add( 25, shl( n2, 1 ) ) );
4797 0 : tmp = div_s( 16384, tmp ); /* Q(15+exp) */
4798 0 : sum = tmp;
4799 :
4800 0 : pf_n2_temp1[k] = add( n2, exp );
4801 0 : move16();
4802 0 : pf_temp[k] = (Word16) sum;
4803 0 : move16(); /* Q15+exp */
4804 : }
4805 0 : }
4806 :
4807 :
4808 : /*=================================================================================*/
4809 : /* FUNCTION : DTFS_getEngy_band_wb_fx (Word16 lband, Word16 hband) */
4810 : /*---------------------------------------------------------------------------------*/
4811 : /* PURPOSE : compute the energy of X1.a[k] and X2.b[k] */
4812 : /* Get DTFS energy in the specified range from lband to hband. */
4813 : /* This function is different to "DTFS_getEngy_band" as this can calculate */
4814 : /* lband, hband \in [1,6400] where "DTFS_getEngy_band" only upperlimited to*/
4815 : /* 4Khz. Possibility: modify ""DTFS_getEngy_band"" and get rid of this */
4816 : /* function. */
4817 : /*---------------------------------------------------------------------------------*/
4818 : /* INPUT ARGUMENTS : */
4819 : /* _ (struct DTFS_STRUCTURE) X_fx : a_fx/b_fx in X_fx.Q, lag in Q0 */
4820 : /* _ (Word16) lband: Q0 */
4821 : /* _ (Word16) hband: Q0 */
4822 : /*---------------------------------------------------------------------------------*/
4823 : /* OUTPUT ARGUMENTS : */
4824 : /* _ (Word32) en_fx : 2*X1.Q+1 */
4825 : /*---------------------------------------------------------------------------------*/
4826 : /* INPUT/OUTPUT ARGUMENTS : */
4827 : /* _ None */
4828 : /*---------------------------------------------------------------------------------*/
4829 : /* RETURN ARGUMENTS : _ None. */
4830 : /*---------------------------------------------------------------------------------*/
4831 : /* CALLED FROM : TX */
4832 : /*=================================================================================*/
4833 0 : Word32 DTFS_getEngy_band_wb_fx( DTFS_STRUCTURE X_fx, Word16 lband, Word16 hband )
4834 : {
4835 : Word16 k, lk, hk, HalfLag;
4836 : Word32 freq_fx, L_lband, L_hband;
4837 0 : Word32 en_fx = 0;
4838 :
4839 0 : L_lband = L_mult( lband, X_fx.lag_fx );
4840 0 : L_hband = L_mult( hband, X_fx.lag_fx );
4841 0 : HalfLag = shr( sub( X_fx.lag_fx, 1 ), 1 );
4842 :
4843 : /* get lband and hband */
4844 0 : FOR( k = 1; k <= HalfLag; k++ )
4845 : {
4846 0 : freq_fx = L_mult( k, 12800 );
4847 :
4848 0 : IF( GE_32( freq_fx, L_lband ) )
4849 : {
4850 0 : BREAK;
4851 : }
4852 : }
4853 0 : lk = k;
4854 0 : move16();
4855 0 : FOR( k = 1; k <= HalfLag; k++ )
4856 : {
4857 0 : freq_fx = L_mult( k, 12800 );
4858 0 : IF( GE_32( freq_fx, L_hband ) )
4859 : {
4860 0 : BREAK;
4861 : }
4862 : }
4863 0 : hk = k;
4864 0 : move16();
4865 :
4866 0 : FOR( k = lk; k < hk; k++ )
4867 : {
4868 0 : en_fx = L_mac0( en_fx, X_fx.a_fx[k], X_fx.a_fx[k] ); /* 2*X1.Q+1 */
4869 0 : en_fx = L_mac0( en_fx, X_fx.b_fx[k], X_fx.b_fx[k] );
4870 : }
4871 0 : en_fx = L_shr( en_fx, 1 ); /* 2*X1.Q+1 */
4872 :
4873 0 : IF( lband == 0 )
4874 : {
4875 0 : en_fx = L_mac0( en_fx, X_fx.a_fx[0], X_fx.a_fx[0] ); /* 2*X1.Q+1 */
4876 : }
4877 :
4878 : /* IF ((X_fx.lag_fx%2 == 0) && (hband == X_fx.upper_cut_off_freq_fx)) */
4879 0 : test();
4880 0 : IF( ( s_and( X_fx.lag_fx, 1 ) == 0 ) && EQ_16( hband, X_fx.upper_cut_off_freq_fx ) )
4881 : {
4882 0 : en_fx = L_mac0( en_fx, X_fx.a_fx[k], X_fx.a_fx[k] );
4883 0 : en_fx = L_mac0( en_fx, X_fx.b_fx[k], X_fx.b_fx[k] );
4884 : }
4885 :
4886 0 : return en_fx; /* 2*X1.Q+1 */
4887 : }
|