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