Line data Source code
1 : /*====================================================================================
2 : EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
3 : ====================================================================================*/
4 :
5 : #include <stdint.h>
6 : #include "options.h" /* Compilation switches */
7 : #include "rom_dec.h" /* Static table prototypes */
8 : #include "rom_com.h" /* Static table prototypes */
9 : #include "prot_fx.h"
10 : #include "basop_util.h"
11 : #include "ivas_prot_fx.h"
12 :
13 : /*---------------------------------------------------------------------*
14 : * Local constants
15 : *---------------------------------------------------------------------*/
16 :
17 : #define FEC_MAX 512
18 : #define FEC_NB_PULSE_MAX 20
19 : #define FEC_FFT_MAX_SIZE 512
20 : #define FEC_DCIM_FILT_SIZE_MAX 60
21 :
22 : #define ENV_STAB_DEC_THR 16384 /* Q15 st->env_stab based threshold for hq-ecu technology decision */
23 :
24 : #define PHASE_DITH_fx 25736 /* 2*pi in Q12 */
25 : #define DELTA_CORR 6 /* Tuning parameter - defining range for phase correction around peak */
26 : #define THRESH_TR_DB_FX 10
27 : #define THRESH_TR_LIN_BY2_FX ( 10 / 2 ) /* 10.0^(THRESH_TR_DB_FX/10.0)/2. Divided by 2 to facilitate fixed-point implementation. */
28 : #define MAX_INCREASE_GRPPOW_FX 0 /* max. amplification in case of transients (in dB scale) */
29 : #define MAX_INCREASE_GRPPOW_LIN_FX 32767 /* in Q15-- 10.0^(MAX_INCREASE_GRPPOW_FX/10.0) (in linear scale) */
30 :
31 : #define PHASE_DITH_SCALE_SHIFT 16 /* The number of bit shift equivalent to multiply by PHASE_DITH_SCALE */
32 :
33 : #define BURST_PHDITH_THRESH ( 4 - 1 ) /* speech start phase dither with <burst_phdith_thresh> losses in a row */
34 : #define BURST_PHDITH_RAMPUP_LEN 2 /* speech ramp up degree of phase dither over a length of <burst_phdith_rampup_len> frames */
35 : #define BURST_ATT_THRESH ( 3 - 1 ) /* speech start attenuate with <burst_att_thresh> losses in a row */
36 : #define ATT_PER_FRAME 4 /* speech attenuation in dB */
37 : #define BETA_MUTE_THR 10 /* time threshold to start beta-noise attenuation */
38 :
39 : #define LGW32K 7
40 : #define LGW16K 6
41 : #define LGW48K LGW32K + 1 /* Use the same frequency groups as for SWB + 1 */
42 :
43 : #define LTRANALOG32K 8
44 : #define LTRANALOG16K 7
45 : #define PFIND_SENS_FX 31785 /* 0.97 in Q15 */
46 : #define CMPLMNT_PFIND_SENS_FX 983 /* (1.0 - pfind_sen) in Q15 */
47 :
48 : #define DELTA_CORR_F0_INT 2 /* Constant controls the bin range where Jacobsen is used */
49 : #define L_PROT_NS 32000000L /* Prototype frame length in nanoseconds (32 ms) */
50 : #define PH_ECU_CORR_LIMIT_Q15 27853 /* 0.85 in Q15 */
51 : #define PH_ECU_N_LIMIT 56 /* fec_alg analysis frame limit for IVAS Phase ECU activation */
52 : #define CMPLMNT_ST_PFIND_SENS_FX 2293 /* (1.0 - st_pfind_sen) in Q15 */
53 :
54 : #define FEC_HQ_ECU_POINT5 ( 0x4000 ) /* 0.5 in Q15. Prefix with FEC_HQ namespace to avoid naming conflict. */
55 : #define FEC_HQ_ECU_ROOT2 ( 0x5a83 ) /* sqrt(2) in Q14 */
56 : #define FEC_HQ_HAMM_A0 17695 /* 0.54 in Q15 */
57 : #define FEC_HQ_HAMM_A1 15073 /* 0.46 in Q15 */
58 : #define FEC_HQ_WIN_A0 FEC_HQ_HAMM_A0
59 : #define FEC_HQ_WIN_A1 FEC_HQ_HAMM_A1
60 :
61 : static Word16 sqrt2ndOrder( const Word16 );
62 :
63 : static void windowing( const Word16 *, Word16 *, const Word16 *, const Word16, const Word16 );
64 : static void windowing_ROM_optimized( const Word16 *, Word16 *, const Word16, const Word16, const Word16 );
65 : static void fft_spec2_fx( const Word16[], Word32[], const Word16 );
66 : #ifdef NONBE_FIX_1180_HQMDCT_PHECU_LT_MUTING
67 : static void trans_ana_fx( const Word16 *, Word16 *, Word16 *, Word16 *, const Word16, const Word16, const Word16, const Word16, const Word16, Word16 *, Word16 *, Word16 *, Word16 * );
68 : #else
69 : static void trans_ana_fx( const Word16 *, Word16 *, Word16 *, Word16 *, const Word16, const Word16, const Word16, const Word16, Word16 *, Word16 *, Word16 *, Word16 * );
70 : #endif
71 : static void peakfinder_fx( const Word16 *, const Word16, Word16 *, Word16 *, const Word16 );
72 : static Word16 imax_fx( const Word16 *, const Word16 );
73 : static void spec_ana_fx( const Word16 *prevsynth, Word16 *plocs, Word32 *plocsi, Word16 *num_plocs, Word16 *X_sav, const Word16 output_frame, const Word16 bwidth_fx, Word16 *Q );
74 : static void subst_spec_fx( const Word16 *, const Word32 *, Word16 *, const Word16, Word16 *, const Word16 *, const Word16, const Word16 *, const Word16, Word16 *, const Word16 *, const Word16 *, Word16, const Word16 * );
75 : static Word16 rand_phase_fx( const Word16 seed, Word16 *sin_F, Word16 *cos_F );
76 :
77 : /*------------------------------------------------------------------*
78 : * rand_phase()
79 : *
80 : * randomized phase in form of sin and cos components
81 : *------------------------------------------------------------------*/
82 115272 : static Word16 rand_phase_fx( const Word16 seed, Word16 *sin_F /*Q15*/, Word16 *cos_F /*Q15*/ )
83 : {
84 115272 : const Word16 *sincos = sincos_t_ext_fx + 128; // Q15
85 115272 : Word16 seed2 = own_random2_fx( seed );
86 115272 : Word16 seed2_shift = shr( seed2, 8 );
87 :
88 115272 : *sin_F = negate( *( sincos + seed2_shift ) ); // Q15
89 115272 : move16();
90 115272 : if ( s_and( seed2, 0x40 ) != 0 )
91 : {
92 57586 : *sin_F = *( sincos + seed2_shift );
93 57586 : move16();
94 : }
95 :
96 115272 : *cos_F = negate( *( sincos - seed2_shift ) ); // Q15
97 115272 : move16();
98 115272 : if ( s_and( seed2, 0x80 ) != 0 )
99 : {
100 57665 : *cos_F = *( sincos - seed2_shift );
101 57665 : move16();
102 : }
103 :
104 115272 : return seed2;
105 : }
106 :
107 : /*! r: The location, relative to the middle of the 3 given data point, of the maximum. (Q15)*/
108 886 : static Word16 ivas_imax2_jacobsen_mag_fx(
109 : const Word16 *y_re, /* i : The 3 given data points. real part order -1 0 1 Qx */
110 : const Word16 *y_im /* i : The 3 given data points. imag part order 1 0 -1 (from FFT) Qx */
111 : )
112 : {
113 : Word16 posi; // Q15
114 : const Word16 *pY;
115 : Word16 y_m1_re, y_0_re, y_p1_re;
116 : Word16 y_m1_im, y_0_im, y_p1_im;
117 : Word32 N_re, N_im;
118 : Word32 D_re, D_im;
119 : Word16 tmp, tmp_e;
120 : Word32 numer, denom;
121 : Word64 tmp_64_n, tmp_64_d;
122 :
123 : /* Jacobsen estimates peak offset relative y_0 using
124 : * X_m1 - X_p1
125 : * d = REAL ( ------------------- ) * c_jacob
126 : * 2*X_0 - X_m1 -Xp1
127 : *
128 : * Where c_jacob is a window dependent constant
129 : */
130 : #define C_JACOB_FX 18765 /* % assume 0.1875 hammrect window 'symmetric' */ /*Q14*/
131 :
132 : /* Get the bin parameters into variables */
133 886 : pY = y_re;
134 886 : y_m1_re = *pY++;
135 886 : move16();
136 886 : y_0_re = *pY++;
137 886 : move16();
138 886 : y_p1_re = *pY++;
139 886 : move16();
140 :
141 : /* Same for imaginary parts - note reverse order from FFT */
142 886 : pY = y_im;
143 886 : y_p1_im = *pY++;
144 886 : move16();
145 886 : y_0_im = *pY++;
146 886 : move16();
147 886 : y_m1_im = *pY++;
148 886 : move16();
149 :
150 : /* prepare numerator real and imaginary parts*/
151 886 : N_re = L_sub( y_m1_re, y_p1_re );
152 886 : N_im = L_sub( y_m1_im, y_p1_im );
153 :
154 : /* prepare denominator real and imaginary parts */
155 :
156 886 : D_re = L_sub( L_sub( L_shl( y_0_re, 1 ), y_m1_re ), y_p1_re );
157 886 : D_im = L_sub( L_sub( L_shl( y_0_im, 1 ), y_m1_im ), y_p1_im );
158 :
159 : /* REAL part of complex division */
160 886 : tmp_64_n = W_mac_32_32( W_mult_32_32( N_re, D_re ), N_im, D_im );
161 886 : tmp_64_d = W_mac_32_32( W_mult_32_32( D_re, D_re ), D_im, D_im );
162 886 : tmp_e = s_min( W_norm( tmp_64_n ), W_norm( tmp_64_d ) );
163 886 : numer = W_extract_h( W_shl( tmp_64_n, tmp_e ) );
164 886 : denom = W_extract_h( W_shl( tmp_64_d, tmp_e ) );
165 :
166 886 : test();
167 886 : IF( numer != 0 && denom != 0 )
168 : {
169 886 : tmp = BASOP_Util_Divide3232_Scale( numer, denom, &tmp_e );
170 886 : tmp = shl_sat( tmp, tmp_e ); // Q15
171 886 : posi = shl_sat( mult_r( tmp, C_JACOB_FX ), Q1 ); // Q15
172 : }
173 : ELSE
174 : {
175 0 : posi = 0; /* flat top, division is not possible choose center freq */
176 0 : move16();
177 : }
178 :
179 886 : return posi;
180 : }
181 :
182 : /*-----------------------------------------------------------------------------
183 : * fft_spec2_fx()
184 : *
185 : * Square magnitude of fft spectrum
186 : *----------------------------------------------------------------------------*/
187 162 : static void fft_spec2_fx(
188 : const Word16 x[], /* i : Input vector: complex spectrum Q0*/
189 : Word32 xMagSq[], /* o : Magnitude square spectrum Q0*/
190 : const Word16 N /* i : Input vector length */
191 : )
192 : {
193 : Word16 i, l;
194 : const Word16 *pRe, *pIm;
195 : Word32 *pMagSq, acc;
196 :
197 : /* Magnitude at 0. */
198 162 : pMagSq = &xMagSq[0];
199 162 : pRe = &x[0];
200 162 : *pMagSq++ = L_mult0( *pRe, *pRe );
201 162 : move32();
202 162 : pRe++; /* Non-fractional multiply gives subsequent group power accumulation a bit headroom. */
203 :
204 : /* From 1 to (N/2 - 1). */
205 162 : l = sub( shr( N, 1 ), 1 ); /* N/2 - 1. */
206 162 : pIm = &x[N];
207 162 : pIm--;
208 51072 : FOR( i = 0; i < l; i++ )
209 : {
210 50910 : acc = L_mult0( *pRe, *pRe );
211 50910 : pRe++; /* Non-fractional mode multiply. */
212 50910 : *pMagSq++ = L_mac0( acc, *pIm, *pIm );
213 50910 : pIm--;
214 50910 : move32();
215 : }
216 :
217 : /* The magnitude square at N/2 */
218 162 : *pMagSq = L_mult0( *pRe, *pRe );
219 162 : move32();
220 162 : return;
221 : }
222 :
223 : /*-----------------------------------------------------------------------------
224 : * trans_ana_fx()
225 : *
226 : * Transient analysis
227 : *----------------------------------------------------------------------------*/
228 132 : static void trans_ana_fx(
229 : const Word16 *xfp, /* i : Input signal Q0 */
230 : Word16 *mag_chg, /* o : Magnitude modification Q15 */
231 : Word16 *ph_dith, /* o : Phase dither, 2*PI is not included (Q15, i.e., between 0.0 and 1.0) */
232 : Word16 *mag_chg_1st, /* i/o: per band magnitude modifier for transients Q15 */
233 : const Word16 output_frame, /* i : Frame length */
234 : const Word16 time_offs, /* i : Time offset (integral multiple of output_frame) */
235 : const Word16 est_mus_content, /* i : 0.0=speech_like ... 1.0=Music (==st->env_stab ) */
236 : const Word16 last_fec, /* i : signal that previous frame was concealed with fec_alg */
237 : #ifdef NONBE_FIX_1180_HQMDCT_PHECU_LT_MUTING
238 : const Word16 element_mode, /* i : element_mode req to handle EVS_MONO specific BE path */
239 : #endif
240 : Word16 *alpha, /* o : Magnitude modification factors for fade to average */
241 : Word16 *beta, /* o : Magnitude modification factors for fade to average */
242 : Word16 *beta_mute, /* o : Factor for long-term mute Q15 */
243 : Word16 *Xavg /* o : Frequency group average gain to fade to */
244 : )
245 : {
246 : const Word16 *w_hamm, *pFftTbl;
247 : Word16 att_val, attDegreeFrames;
248 : Word16 xfp_left[L_TRANA48k], xfp_right[L_TRANA48k];
249 : Word32 magSqLeft[L_TRANA48k / 2 + 1], magSqRight[L_TRANA48k / 2 + 1];
250 : Word32 *pLeft, *pRight, *pGrPowLeft, *pGrPowRight;
251 : Word32 gr_pow_left[LGW_MAX], gr_pow_right[LGW_MAX];
252 : const Word16 *pXfp, *pGw;
253 : Word16 Ltrana, Ltrana_2, Lprot, three4thLength, LtranaLogMinus1, Lgw, i, k, l, burst_len;
254 : Word16 man, expo;
255 132 : Word16 att_always = 0; /* fixed attenuation per frequency group if set to 1 */
256 : Word16 oneOverFrame, roundEstMusContent, tmp16, headroom, lowerEdge;
257 132 : Word16 burst_phdith_thresh = BURST_PHDITH_THRESH; /*speech settings */
258 132 : Word16 burst_att_thresh = BURST_ATT_THRESH;
259 132 : Word16 att_per_frame = ATT_PER_FRAME;
260 132 : Word16 burst_phdith_rampup_len = BURST_PHDITH_RAMPUP_LEN;
261 : Word16 tr_dec[LGW_MAX];
262 : UWord16 lsb;
263 : Word32 acc;
264 :
265 132 : Lgw = 0;
266 132 : move16();
267 132 : LtranaLogMinus1 = 0;
268 132 : move16();
269 :
270 132 : move16(); // att_always
271 132 : move16(); // burst_phdith_thresh
272 132 : move16(); // burst_att_thresh
273 132 : move16(); // att_per_frame
274 132 : move16(); // burst_phdith_rampup_len
275 :
276 132 : pFftTbl = NULL;
277 :
278 : /* Initialisation to prevent warnings */
279 132 : oneOverFrame = 102; /* 1/320 in Q15 */
280 132 : move16();
281 132 : w_hamm = w_hamm16k_2_fx;
282 132 : move16();
283 132 : Lprot = 512;
284 132 : move16();
285 :
286 : /* check burst error */
287 132 : IF( EQ_16( output_frame, L_FRAME48k ) ) /* output_frame = (sampling frequency)/50 */
288 : {
289 103 : oneOverFrame = 34; /* 1/960 in Q15 */
290 103 : move16();
291 103 : w_hamm = w_hamm48k_2_fx;
292 103 : move16();
293 103 : Lgw = LGW48K;
294 103 : move16();
295 103 : Lprot = 1536; /* (2*output_frame)*1024/1280; */
296 103 : move16();
297 : }
298 29 : ELSE IF( EQ_16( output_frame, L_FRAME32k ) )
299 : {
300 29 : oneOverFrame = 51; /* 1/640 in Q15 */
301 29 : move16();
302 29 : w_hamm = w_hamm32k_2_fx;
303 29 : Lgw = LGW32K;
304 29 : move16();
305 29 : Lprot = 1024;
306 29 : move16();
307 29 : pFftTbl = FFT_W128; /* Table for 256 real input radix-2 FFT */
308 29 : LtranaLogMinus1 = LTRANALOG32K - 1;
309 29 : move16();
310 : }
311 : ELSE
312 : {
313 0 : oneOverFrame = 102; /* 1/320 in Q15 */
314 0 : move16();
315 0 : w_hamm = w_hamm16k_2_fx;
316 0 : Lgw = LGW16K;
317 0 : move16();
318 0 : Lprot = 512;
319 0 : move16();
320 0 : pFftTbl = FFT_W64; /* Table for 128 real input radix-2 FFT */
321 0 : LtranaLogMinus1 = LTRANALOG16K - 1;
322 0 : move16();
323 : }
324 132 : burst_len = add( mult_r( time_offs, oneOverFrame ), 1 );
325 :
326 132 : *ph_dith = 0;
327 132 : move16(); /* typical pattern is 2*pi*[0 0 .25 .50 .75 1.0 1.0 1.0 ..] */
328 :
329 132 : IF( GE_16( output_frame, L_FRAME32k ) ) /*currently est_mus_content only calculated for SWB and FB */
330 : {
331 132 : roundEstMusContent = 0;
332 132 : move16();
333 132 : if ( GE_16( est_mus_content, FEC_HQ_ECU_POINT5 ) ) /* est_mus_content is in [0.0, 1.0]. */
334 : {
335 131 : roundEstMusContent = 1;
336 131 : move16();
337 : }
338 :
339 : /* softly shift attenuation just a bit later for estimated "stable" music_content */
340 132 : burst_phdith_thresh = add( BURST_PHDITH_THRESH, roundEstMusContent );
341 132 : burst_att_thresh = add( BURST_ATT_THRESH, roundEstMusContent );
342 132 : att_per_frame = sub( ATT_PER_FRAME, roundEstMusContent ); /* only slighty less att for music */
343 : }
344 : ELSE
345 : {
346 : /* lock to music-like stable envelope setting for now */
347 0 : burst_phdith_thresh = add( BURST_PHDITH_THRESH, 1 ); /* in Q0 */
348 0 : burst_att_thresh = add( BURST_ATT_THRESH, 1 ); /* in Q0 */
349 0 : att_per_frame = sub( ATT_PER_FRAME, 1 ); /* in Q0 */
350 : }
351 :
352 132 : IF( GT_16( burst_len, burst_phdith_thresh ) )
353 : {
354 : /* increase degree of dither */
355 : #if BURST_PHDITH_RAMPUP_LEN != 2
356 : #error The implementation of phase_dith=min(1.0, (burst_len - burst_phdith_thresh)/burst_phdith_rampup_len)) is incorrect
357 : #endif
358 72 : *ph_dith = 32767; /* 1.0 in Q15. N.B. 2*PI is not included. */
359 72 : move16();
360 72 : tmp16 = sub( burst_len, burst_phdith_thresh );
361 72 : if ( LT_16( tmp16, burst_phdith_rampup_len ) )
362 : {
363 2 : *ph_dith = 16384; /* 0.5 in Q15. N.B. 2*PI is not included. */
364 2 : move16();
365 : }
366 : }
367 :
368 132 : attDegreeFrames = 0;
369 132 : move16();
370 132 : IF( GT_16( burst_len, burst_att_thresh ) )
371 : {
372 74 : att_always = 1;
373 74 : move16();
374 : /* increase degree of attenuation */
375 :
376 : /* N.B. To facilitate the subsequent 10^(-att_degree/20) implementation
377 : * so as to use direct table-lookup,
378 : * (burstLen - burst_att_thresh) is NOT multiplied by "att_per_frame". */
379 74 : attDegreeFrames = sub( burst_len, burst_att_thresh ); /* Not multiplied by att_per_frqme! */
380 : /* Furthermore, in order to minimize the size of the lookup-table required to
381 : * implement 10^(-att_degree/10), hard limit attDegreeFrames to (30% of 50)=15.
382 : * If attDegreeFrames is greater than 15, it means there are more than 15 successive
383 : * bad frames. In this case, no matter what to do, the sound quality will be bad.
384 : */
385 74 : if ( GT_16( attDegreeFrames, OFF_FRAMES_LIMIT ) )
386 : {
387 14 : attDegreeFrames = OFF_FRAMES_LIMIT; /* Hard limit the no. of frames */
388 14 : move16();
389 : }
390 : }
391 :
392 132 : Ltrana = shr( Lprot, 2 );
393 132 : Ltrana_2 = shr( Ltrana, 1 );
394 :
395 132 : test();
396 132 : test();
397 132 : IF( LE_16( burst_len, 1 ) || ( EQ_16( burst_len, 2 ) && last_fec != 0 ) )
398 : {
399 :
400 54 : set16_fx( alpha, 32767, LGW_MAX );
401 54 : set16_fx( beta, 0, LGW_MAX );
402 54 : *beta_mute = BETA_MUTE_FAC_INI;
403 54 : move16();
404 :
405 : /* Apply Hamming window */
406 54 : windowing( xfp, xfp_left, w_hamm, 0, Ltrana_2 ); /* 1st quarter */
407 54 : three4thLength = sub( Lprot, Ltrana );
408 54 : pXfp = xfp + three4thLength;
409 54 : windowing( pXfp, xfp_right, w_hamm, 0, Ltrana_2 ); /* 4th quarter */
410 :
411 : /* spectrum */
412 54 : IF( EQ_16( output_frame, L_FRAME48k ) )
413 : {
414 25 : fft3_fx( xfp_left, xfp_left, Ltrana );
415 25 : fft3_fx( xfp_right, xfp_right, Ltrana );
416 : }
417 : ELSE
418 : {
419 29 : r_fft_fx_lc( pFftTbl, Ltrana, Ltrana_2, LtranaLogMinus1, xfp_left, xfp_left, 1 );
420 29 : r_fft_fx_lc( pFftTbl, Ltrana, Ltrana_2, LtranaLogMinus1, xfp_right, xfp_right, 1 );
421 : }
422 :
423 : /* square representation */
424 54 : fft_spec2_fx( xfp_left, magSqLeft, Ltrana );
425 54 : fft_spec2_fx( xfp_right, magSqRight, Ltrana );
426 :
427 : /* band powers in frequency groups
428 : * exclude bin at PI from calculation */
429 54 : magSqLeft[Ltrana_2] = L_deposit_l( 0 );
430 54 : move32();
431 54 : magSqRight[Ltrana_2] = L_deposit_l( 0 );
432 54 : move32();
433 : }
434 :
435 132 : pGrPowLeft = &gr_pow_left[0];
436 132 : pGrPowRight = &gr_pow_right[0];
437 132 : pGw = gw;
438 1159 : FOR( k = 0; k < Lgw; k++ )
439 : {
440 1027 : test();
441 1027 : test();
442 1027 : IF( LE_16( burst_len, 1 ) || ( EQ_16( burst_len, 2 ) && last_fec != 0 ) )
443 : {
444 403 : lowerEdge = *pGw++;
445 403 : move16();
446 403 : l = sub( *pGw, lowerEdge );
447 403 : headroom = GR_POW_HEADROOM[k]; /* Number of bits to scale down preventing from saturation in accumulation.*/
448 403 : move16();
449 403 : pLeft = magSqLeft + lowerEdge;
450 403 : pRight = magSqRight + lowerEdge;
451 403 : *pGrPowLeft = L_deposit_l( 0 );
452 403 : move32();
453 403 : *pGrPowRight = L_deposit_l( 0 );
454 403 : move32();
455 8861 : FOR( i = 0; i < l; i++ )
456 : {
457 8458 : acc = L_shr( *pLeft++, headroom ); /* Scale down to prevent from saturation. */
458 8458 : *pGrPowLeft = L_add( *pGrPowLeft, acc );
459 8458 : move32();
460 8458 : acc = L_shr( *pRight++, headroom );
461 8458 : *pGrPowRight = L_add( *pGrPowRight, acc );
462 8458 : move32();
463 : }
464 :
465 : /*Xavg[k] = sqrt(0.5f*(gr_pow_left[k]+gr_pow_right[k])/(float)(gw[k+1]-gw[k]));*/
466 403 : acc = L_shr( L_add( *pGrPowLeft, *pGrPowRight ), 1 );
467 403 : acc = Mult_32_16( acc, gw_len_inv_fx[k] ); /* -headroom */
468 :
469 403 : acc = Sqrt_l( acc, &expo ); /* -headroom+31+expo */
470 :
471 403 : expo = sub( add( expo, 31 ), headroom );
472 403 : if ( EQ_16( s_and( expo, 1 ), 1 ) )
473 : {
474 295 : acc = Mult_32_16( acc, 23170 ); /* 1/sqrt(2) in Q15 */
475 : }
476 403 : expo = shr( expo, 1 );
477 403 : Xavg[k] = round_fx( L_shl( acc, sub( sub( 16, expo ), 2 ) ) ); /* Q0, additional right shift by 2 to account for that Xavg is
478 : calculated using lenght N/4 fft but is applied on a fft of length N */
479 403 : move16();
480 :
481 : /*dither phase in case of transient */
482 : /* separate transition detection and application of forced burst dithering */
483 403 : tr_dec[k] = 0;
484 403 : move16();
485 403 : Mpy_32_16_ss( *pGrPowLeft, THRESH_TR_LIN_BY2_FX, &acc, &lsb ); /* To facilitate fixed-point implementation, divide threshold by 2. */
486 403 : acc = L_or( L_shl_sat( acc, 16 ), L_and( 0xffffL, lsb ) ); /* Equivalent to concatenate acc and lsb, and then down shift by 16 bits. */
487 403 : if ( GT_32( *pGrPowRight, acc ) ) /* gr_pow_right > thres_tr_lin*gr_pow_left */
488 : {
489 12 : tr_dec[k] = 1;
490 12 : move16();
491 : }
492 403 : Mpy_32_16_ss( *pGrPowRight, THRESH_TR_LIN_BY2_FX, &acc, &lsb );
493 403 : acc = L_or( L_shl_sat( acc, 16 ), L_and( 0xffffL, lsb ) ); /* Equivalent to concatenate acc and lsb, and then down shift by 16 bits. */
494 403 : if ( GT_32( *pGrPowLeft, acc ) ) /* gr_pow_left > thres_tr_lin*gr_pow_right */
495 : {
496 10 : tr_dec[k] = 1;
497 10 : move16();
498 : }
499 :
500 : /* magnitude modification */
501 403 : IF( add( tr_dec[k], att_always ) != 0 )
502 : {
503 :
504 : #if MAX_INCREASE_GRPPOW_FX != 0
505 : #error trans_ana_fx-- The following implementation is incorrect
506 : #endif
507 22 : att_val = 32767;
508 22 : move16();
509 22 : IF( *pGrPowRight > 0 )
510 : {
511 17 : IF( LT_32( *pGrPowRight, *pGrPowLeft ) ) /* i.e., (gr_pow_right/gr_pow_left) < 1.0 */
512 : {
513 : /* Compute sqrt(grp_pow_chg), where grp_pow_chg = gr_pow_right/gr_pow_left. */
514 5 : tmp16 = ratio( *pGrPowRight, *pGrPowLeft, &expo ); /* tmp16 in Q14 */
515 5 : expo = sub( expo, ( 15 - 14 ) ); /* Now, tmp16 is considered in Q15 */
516 5 : i = norm_s( tmp16 );
517 5 : man = shl( tmp16, i ); /* Mandatory normalization before sqrtNthOrder(). */
518 5 : expo = add( expo, i );
519 5 : man = sqrt2ndOrder( man );
520 5 : if ( s_and( expo, 1 ) != 0 ) /* Check even or odd. */
521 : {
522 4 : man = mult_r( man, FEC_HQ_ECU_ROOT2 );
523 : }
524 5 : expo = shr( expo, 1 ); /* Divided by 2-- square root operation. */
525 5 : att_val = shr( man, expo ); /* Denormalize the mantissa back to Q15. */
526 : }
527 : /* ELSE do nothing because (gr_pow_right/gr_pow_left) >= 1.0 (i.e.,
528 : * max_increase_grppow_lin) */
529 : }
530 :
531 22 : mag_chg_1st[k] = att_val;
532 22 : move16();
533 22 : mag_chg[k] = att_val;
534 22 : move16();
535 : }
536 : ELSE
537 : {
538 381 : mag_chg_1st[k] = 32767;
539 381 : move16();
540 381 : mag_chg[k] = 32767;
541 381 : move16(); /* Set to 1.0 in Q15 */
542 : }
543 : }
544 : ELSE
545 : {
546 : /* Since attDegreeFrames is discrete (integer) and hard limited to OFF_FRAMES_LIMIT,
547 : * it is much easier to implement 10^(-att_degree/20.0) by a simply direct
548 : * table-lookup. Also, att_per_frame is discrete as well and can be
549 : * either ATT_PER_FRAME-1 or ATT_PER_FRAME and nothing else. This
550 : * means only 2 tables of size=(OFF_FRAMES_LIMIT+1) each are required.
551 : * To take square root into account, it is divided by 20 instead of 10. */
552 624 : IF( EQ_16( att_per_frame, ATT_PER_FRAME ) ) /* Select the corresponding lookup-table. */
553 : {
554 0 : att_val = POW_ATT_TABLE0[attDegreeFrames]; /* 10^(-attDegreeFrames*(ATT_PER_FRAME)/20) */
555 0 : move16();
556 : }
557 : ELSE
558 : {
559 624 : att_val = POW_ATT_TABLE1[attDegreeFrames]; /* 10^(-attDegreeFrames*(ATT_PER_FRAME - 1)/20) */
560 624 : move16();
561 : }
562 624 : mag_chg[k] = mult_r( mag_chg_1st[k], att_val ); /* Q15 */
563 624 : move16();
564 :
565 : #ifdef NONBE_FIX_1180_HQMDCT_PHECU_LT_MUTING
566 624 : IF( NE_16( element_mode, EVS_MONO ) )
567 : {
568 624 : IF( EQ_16( k, 0 ) && GT_16( burst_len, BETA_MUTE_THR ) ) /* beta_mute final long term attenuation adjusted only once per frame in the first sub-band, Ref Eq(184) in 26.447 */
569 : {
570 60 : *beta_mute = shr( *beta_mute, 1 );
571 60 : move16();
572 : }
573 : }
574 : ELSE
575 : {
576 0 : IF( GT_16( burst_len, BETA_MUTE_THR ) ) /* legacy incorrect(too fast) EVS_MONO operation, still kept for BE. To be updated after EVS CR, ref Eq (184) in 26.447 */
577 : {
578 0 : *beta_mute = shr( *beta_mute, 1 );
579 0 : move16();
580 : }
581 : }
582 : #else
583 : IF( GT_16( burst_len, BETA_MUTE_THR ) )
584 : {
585 : *beta_mute = shr( *beta_mute, 1 );
586 : move16();
587 : }
588 : #endif
589 624 : alpha[k] = mag_chg[k];
590 624 : move16();
591 : /*beta[k] = sqrt(1.0f - SQR(alpha[k])) * *beta_mute;*/
592 624 : acc = L_sub( 1073741824, L_mult0( alpha[k], alpha[k] ) );
593 624 : acc = Sqrt_l( acc, &expo );
594 624 : expo = add( 30, add( 31, expo ) );
595 624 : if ( EQ_16( s_and( expo, 1 ), 1 ) )
596 : {
597 624 : acc = Mult_32_16( acc, 23170 ); /* 1/sqrt(2) in Q15 */
598 : }
599 624 : expo = shr( expo, 1 );
600 624 : beta[k] = mult_r( *beta_mute, round_fx( L_shl( acc, sub( 31, expo ) ) ) );
601 624 : move16();
602 :
603 624 : IF( GE_16( k, LGW32K - 1 ) )
604 : {
605 156 : beta[k] = mult_r( beta[k], 3277 ); /* 0.1 in Q15 */
606 156 : move16();
607 : }
608 468 : ELSE IF( GE_16( k, LGW16K - 1 ) )
609 : {
610 78 : beta[k] = mult_r( beta[k], 16384 ); /* 0.5 in Q15 */
611 78 : move16();
612 : }
613 : }
614 1027 : pGrPowLeft++;
615 1027 : pGrPowRight++;
616 : }
617 :
618 132 : return;
619 : }
620 :
621 : /*-----------------------------------------------------------------------------
622 : * peakfinder_fx()
623 : *
624 : * Peak-picking algorithm
625 : *----------------------------------------------------------------------------*/
626 54 : static void ivas_peakfinder_fx(
627 : const Word16 *x0, /* i : vector from which the maxima will be found */
628 : const Word16 len0, /* i : length of input vector */
629 : Word16 *plocs, /* o : the indices of the identified peaks in x0 Q0 */
630 : Word16 *cInd, /* o : number of identified peaks Q0 */
631 : const Word16 sel, /* i : The amount above surrounding data for a peak to be identified */
632 : const Word16 endpoints /* i : Flag to include endpoints in peak search */
633 : )
634 : {
635 : const Word16 *pX0;
636 : Word16 minMag, tempMag, leftMin;
637 : Word16 dx0[L_PROT48k_2], x[L_PROT48k_2 + 1], peakMag[MAX_PLOCS];
638 : Word16 *pDx0, *pDx01, *pX;
639 : Word16 i, len, tempLoc, foundPeak, ii, xInd, tmp16, threshold, xAt0, xAt1, xAt2;
640 : Word16 len0Minus1, len0Minus2, lenMinus1;
641 : Word16 indarr[L_PROT48k_2 + 1], peakLoc[MAX_PLOCS];
642 : Word16 *pInd;
643 :
644 54 : tempLoc = 0;
645 54 : move16();
646 :
647 : /* Find derivative */
648 54 : len0Minus1 = sub( len0, 1 );
649 54 : pX0 = x0 + 1;
650 54 : Vr_subt( pX0, x0, dx0, len0Minus1 );
651 :
652 34102 : FOR( i = 0; i < len0Minus1; i++ )
653 : {
654 34048 : if ( dx0[i] == 0 )
655 : {
656 7663 : dx0[i] = -1;
657 7663 : move16();
658 : }
659 : }
660 :
661 : /* Find where the derivative changes sign
662 : Include endpoints in potential peaks and valleys */
663 54 : pX = x;
664 54 : pX0 = x0;
665 54 : pInd = indarr;
666 54 : pDx01 = dx0;
667 54 : pDx0 = pDx01 + 1;
668 54 : len = 0;
669 54 : move16();
670 54 : IF( endpoints )
671 : {
672 54 : *pX++ = *pX0++;
673 54 : move16();
674 54 : *pInd++ = 0;
675 54 : move16();
676 54 : len = 2;
677 54 : move16();
678 : }
679 54 : len0Minus2 = sub( len0, 2 );
680 :
681 34048 : FOR( i = 0; i < len0Minus2; i++ )
682 : {
683 33994 : IF( s_xor( *pDx01++, *pDx0++ ) < 0 ) /* Detect sign change. */
684 : {
685 15438 : *pInd++ = add( i, 1 );
686 15438 : move16();
687 15438 : *pX++ = *pX0;
688 15438 : move16();
689 15438 : len = add( len, 1 );
690 : }
691 33994 : pX0++;
692 : }
693 54 : IF( endpoints )
694 : {
695 54 : *pInd = len0Minus1;
696 54 : move16();
697 54 : *pX = *pX0;
698 54 : move16();
699 : }
700 : /* x[] only has the peaks, valleys, and endpoints */
701 54 : minimum_fx( x, len, &minMag );
702 :
703 54 : pInd = indarr;
704 54 : test();
705 54 : test();
706 54 : IF( GT_16( len, 2 ) || ( !endpoints && ( len > 0 ) ) )
707 : {
708 : /* Set initial parameters for loop */
709 54 : tempMag = minMag;
710 54 : move16();
711 54 : foundPeak = 0;
712 54 : move16();
713 54 : leftMin = minMag;
714 54 : move16();
715 54 : threshold = add( leftMin, sel );
716 :
717 54 : IF( len > 0 )
718 : {
719 : /* Deal with first point a little differently since tacked it on
720 : Calculate the sign of the derivative since we took the first point
721 : on it does not necessarily alternate like the rest. */
722 :
723 : /* The first point is larger or equal to the second */
724 54 : pX = x;
725 54 : xAt0 = *pX++;
726 54 : move16();
727 54 : xAt1 = *pX++;
728 54 : move16();
729 54 : xAt2 = *pX--; /* After decrement, pX points to x[1]. */
730 54 : move16();
731 54 : IF( GE_16( xAt0, xAt1 ) )
732 : {
733 10 : ii = -1;
734 10 : move16();
735 10 : IF( GE_16( xAt1, xAt2 ) ) /* x[1] is not extremum -> overwrite with x[0] */
736 : {
737 0 : *pX = xAt0; /* x[1] = x[0] */
738 0 : move16();
739 0 : tmp16 = *pInd++;
740 0 : move16();
741 0 : *pInd++ = tmp16; /* ind[1] = ind[0] */
742 0 : move16();
743 0 : len = sub( len, 1 );
744 : }
745 10 : pX--; /* After decrement, pX points to x[0]. */
746 : }
747 : ELSE /* First point is smaller than the second */
748 : {
749 44 : ii = 0;
750 44 : move16();
751 44 : IF( LT_16( xAt1, xAt2 ) ) /* x[1] is not extremum -> overwrite with x[0] */
752 : {
753 0 : *pX = xAt0; /* x[1] = x[0] */
754 0 : move16();
755 0 : tmp16 = *pInd++;
756 0 : move16();
757 0 : *pInd++ = tmp16; /* ind[1] = ind[0] */
758 0 : move16();
759 0 : len = sub( len, 1 );
760 : }
761 : }
762 54 : pX--; /* After decrement, pX points to either x[-1] or x[0]. */
763 : }
764 : ELSE
765 : {
766 : // PMTE ()
767 0 : ii = -1; /* First point is a peak */
768 0 : move16();
769 0 : IF( GE_16( len, 2 ) )
770 : {
771 0 : if ( GE_16( x[1], x[0] ) )
772 : {
773 0 : ii = 0; /* First point is a valley, skip it */
774 0 : move16();
775 : }
776 : }
777 : }
778 54 : *cInd = 0;
779 54 : move16();
780 : /*Loop through extrema which should be peaks and then valleys*/
781 54 : lenMinus1 = sub( len, 1 );
782 : FOR( ;; )
783 : {
784 7793 : ii = add( ii, 1 ); /* This is a peak */
785 :
786 : /* Make sure we don't iterate past the length of our vector */
787 7793 : IF( GE_16( ii, lenMinus1 ) )
788 : {
789 54 : BREAK;
790 : }
791 :
792 : /*Reset peak finding if we had a peak and the next peak is bigger
793 : than the last or the left min was small enough to reset.*/
794 7739 : IF( foundPeak > 0 )
795 : {
796 890 : tempMag = minMag;
797 890 : move16();
798 890 : foundPeak = 0;
799 890 : move16();
800 : }
801 :
802 : /* Found new peak that was larger than temp mag and selectivity larger
803 : than the minimum to its left. */
804 7739 : IF( GT_16( *( ++pX ), tempMag ) )
805 : {
806 7660 : IF( GT_16( *pX, threshold ) ) /* threshold = leftMin + sel */
807 : {
808 987 : tempLoc = ii;
809 987 : move16();
810 987 : tempMag = *pX;
811 987 : move16();
812 : }
813 : }
814 :
815 7739 : ii = add( ii, 1 ); /* Move onto the valley */
816 7739 : pX++;
817 :
818 : /* Come down at least sel from peak */
819 7739 : IF( foundPeak == 0 )
820 : {
821 7739 : IF( GT_16( tempMag, add( sel, *pX ) ) )
822 : {
823 890 : foundPeak = 1; /* We have found a peak */
824 890 : move16();
825 890 : leftMin = *pX;
826 890 : move16();
827 890 : threshold = add( leftMin, sel );
828 890 : peakLoc[*cInd] = tempLoc; /* Add peak to index */
829 890 : move16();
830 890 : peakMag[*cInd] = tempMag;
831 890 : move16();
832 890 : *cInd = add( *cInd, 1 );
833 890 : move16();
834 : }
835 : }
836 7739 : IF( foundPeak == 0 ) /* The above IF-block has not found the peak yet. */
837 : {
838 6849 : IF( LT_16( *pX, leftMin ) ) /* New left minimum */
839 : {
840 746 : leftMin = *pX;
841 746 : move16();
842 746 : threshold = add( leftMin, sel );
843 : }
844 : }
845 : }
846 :
847 : /* Check end point */
848 54 : IF( GT_16( x[lenMinus1], tempMag ) )
849 : {
850 38 : IF( GT_16( x[lenMinus1], threshold ) ) /* threshold = leftMin + sel */
851 : {
852 0 : peakLoc[*cInd] = lenMinus1;
853 0 : move16();
854 0 : peakMag[*cInd] = x[lenMinus1];
855 0 : move16();
856 0 : *cInd = add( *cInd, 1 );
857 0 : move16();
858 0 : foundPeak = 1;
859 0 : move16();
860 : }
861 : }
862 54 : IF( foundPeak == 0 ) /* Check if we still need to add the last point */
863 : {
864 54 : IF( GT_16( tempMag, minMag ) )
865 : {
866 0 : peakLoc[*cInd] = tempLoc;
867 0 : move16();
868 0 : peakMag[*cInd] = tempMag;
869 0 : move16();
870 0 : *cInd = add( *cInd, 1 );
871 0 : move16();
872 : }
873 : }
874 :
875 : /* Create output */
876 944 : FOR( i = 0; i < *cInd; i++ )
877 : {
878 890 : plocs[i] = *( indarr + peakLoc[i] );
879 890 : move16();
880 : }
881 : }
882 : ELSE /* This is a monotone function where an endpoint is the only peak */
883 : {
884 0 : IF( endpoints )
885 : {
886 0 : xInd = 1;
887 0 : move16();
888 0 : if ( GT_16( x[0], x[1] ) )
889 : {
890 0 : xInd = 0;
891 0 : move16();
892 : }
893 :
894 0 : peakMag[0] = x[xInd];
895 0 : move16();
896 0 : IF( GT_16( peakMag[0], add( minMag, sel ) ) )
897 : {
898 0 : plocs[0] = *( indarr + xInd );
899 0 : move16();
900 0 : *cInd = 1;
901 0 : move16();
902 : }
903 : ELSE
904 : {
905 0 : *cInd = 0;
906 0 : move16();
907 : }
908 : }
909 : ELSE
910 : { /* Input constant or all zeros -- no peaks found */
911 0 : *cInd = 0;
912 0 : move16();
913 : }
914 : }
915 54 : }
916 :
917 0 : static void peakfinder_fx(
918 : const Word16 *x0, /* i : vector from which the maxima will be found */
919 : const Word16 len0, /* i : length of input vector */
920 : Word16 *plocs, /* o : the indices of the identified peaks in x0 Q0 */
921 : Word16 *cInd, /* o : number of identified peaks Q0 */
922 : const Word16 sel /* i : The amount above surrounding data for a peak to be identified */
923 : )
924 : {
925 : const Word16 *pX0;
926 : Word16 minMag, tempMag, leftMin;
927 : Word16 dx0[L_PROT48k_2], x[L_PROT48k_2 + 1], peakMag[MAX_PLOCS];
928 : Word16 *pDx0, *pDx01, *pX;
929 : Word16 i, len, tempLoc, foundPeak, ii, xInd, tmp16, threshold, xAt0, xAt1, xAt2;
930 : Word16 len0Minus1, len0Minus2, lenMinus1;
931 : Word16 indarr[L_PROT48k_2 + 1], peakLoc[MAX_PLOCS];
932 : Word16 *pInd;
933 :
934 0 : tempLoc = 0;
935 0 : move16();
936 :
937 : /* Find derivative */
938 0 : len0Minus1 = sub( len0, 1 );
939 0 : pX0 = x0 + 1;
940 0 : Vr_subt( pX0, x0, dx0, len0Minus1 );
941 :
942 0 : FOR( i = 0; i < len0Minus1; i++ )
943 : {
944 0 : if ( dx0[i] == 0 )
945 : {
946 0 : dx0[i] = -1;
947 0 : move16();
948 : }
949 : }
950 :
951 : /* Find where the derivative changes sign
952 : Include endpoints in potential peaks and valleys */
953 0 : pX = x;
954 0 : pX0 = x0;
955 0 : pInd = indarr;
956 0 : pDx01 = dx0;
957 0 : pDx0 = pDx01 + 1;
958 : {
959 0 : *pX++ = *pX0++;
960 0 : move16();
961 0 : *pInd++ = 0;
962 0 : move16();
963 0 : len = 2;
964 0 : move16();
965 : }
966 0 : len0Minus2 = sub( len0, 2 );
967 :
968 0 : FOR( i = 0; i < len0Minus2; i++ )
969 : {
970 0 : IF( s_xor( *pDx01++, *pDx0++ ) < 0 ) /* Detect sign change. */
971 : {
972 0 : *pInd++ = add( i, 1 );
973 0 : move16();
974 0 : *pX++ = *pX0;
975 0 : move16();
976 0 : len = add( len, 1 );
977 : }
978 0 : pX0++;
979 : }
980 : {
981 0 : *pInd = len0Minus1;
982 0 : move16();
983 0 : *pX = *pX0;
984 0 : move16();
985 : }
986 : /* x[] only has the peaks, valleys, and endpoints */
987 0 : minimum_fx( x, len, &minMag );
988 :
989 0 : pInd = indarr;
990 0 : IF( GT_16( len, 2 ) )
991 : {
992 : /* Set initial parameters for loop */
993 0 : tempMag = minMag;
994 0 : move16();
995 0 : foundPeak = 0;
996 0 : move16();
997 0 : leftMin = minMag;
998 0 : move16();
999 0 : threshold = add( leftMin, sel );
1000 :
1001 : {
1002 : /* Deal with first point a little differently since tacked it on
1003 : Calculate the sign of the derivative since we took the first point
1004 : on it does not necessarily alternate like the rest. */
1005 :
1006 : /* The first point is larger or equal to the second */
1007 0 : pX = x;
1008 0 : xAt0 = *pX++;
1009 0 : move16();
1010 0 : xAt1 = *pX++;
1011 0 : move16();
1012 0 : xAt2 = *pX--; /* After decrement, pX points to x[1]. */
1013 0 : move16();
1014 0 : IF( GE_16( xAt0, xAt1 ) )
1015 : {
1016 0 : ii = -1;
1017 0 : move16();
1018 0 : IF( GE_16( xAt1, xAt2 ) ) /* x[1] is not extremum -> overwrite with x[0] */
1019 : {
1020 0 : *pX = xAt0; /* x[1] = x[0] */
1021 0 : move16();
1022 0 : tmp16 = *pInd++;
1023 0 : move16();
1024 0 : *pInd++ = tmp16; /* ind[1] = ind[0] */
1025 0 : move16();
1026 0 : len = sub( len, 1 );
1027 : }
1028 0 : pX--; /* After decrement, pX points to x[0]. */
1029 : }
1030 : ELSE /* First point is smaller than the second */
1031 : {
1032 0 : ii = 0;
1033 0 : move16();
1034 0 : IF( LT_16( xAt1, xAt2 ) ) /* x[1] is not extremum -> overwrite with x[0] */
1035 : {
1036 0 : *pX = xAt0; /* x[1] = x[0] */
1037 0 : move16();
1038 0 : tmp16 = *pInd++;
1039 0 : move16();
1040 0 : *pInd++ = tmp16; /* ind[1] = ind[0] */
1041 0 : move16();
1042 0 : len = sub( len, 1 );
1043 : }
1044 : }
1045 0 : pX--; /* After decrement, pX points to either x[-1] or x[0]. */
1046 : }
1047 0 : *cInd = 0;
1048 0 : move16();
1049 : /*Loop through extrema which should be peaks and then valleys*/
1050 0 : lenMinus1 = sub( len, 1 );
1051 : FOR( ;; )
1052 : {
1053 0 : ii = add( ii, 1 ); /* This is a peak */
1054 :
1055 : /* Make sure we don't iterate past the length of our vector */
1056 0 : IF( GE_16( ii, lenMinus1 ) )
1057 : {
1058 0 : BREAK;
1059 : }
1060 :
1061 : /*Reset peak finding if we had a peak and the next peak is bigger
1062 : than the last or the left min was small enough to reset.*/
1063 0 : IF( foundPeak > 0 )
1064 : {
1065 0 : tempMag = minMag;
1066 0 : move16();
1067 0 : foundPeak = 0;
1068 0 : move16();
1069 : }
1070 :
1071 : /* Found new peak that was larger than temp mag and selectivity larger
1072 : than the minimum to its left. */
1073 0 : IF( GT_16( *( ++pX ), tempMag ) )
1074 : {
1075 0 : IF( GT_16( *pX, threshold ) ) /* threshold = leftMin + sel */
1076 : {
1077 0 : tempLoc = ii;
1078 0 : move16();
1079 0 : tempMag = *pX;
1080 0 : move16();
1081 : }
1082 : }
1083 :
1084 0 : ii = add( ii, 1 ); /* Move onto the valley */
1085 0 : pX++;
1086 :
1087 : /* Come down at least sel from peak */
1088 0 : IF( foundPeak == 0 )
1089 : {
1090 0 : IF( GT_16( tempMag, add( sel, *pX ) ) )
1091 : {
1092 0 : foundPeak = 1; /* We have found a peak */
1093 0 : move16();
1094 0 : leftMin = *pX;
1095 0 : move16();
1096 0 : threshold = add( leftMin, sel );
1097 0 : peakLoc[*cInd] = tempLoc; /* Add peak to index */
1098 0 : move16();
1099 0 : peakMag[*cInd] = tempMag;
1100 0 : move16();
1101 0 : *cInd = add( *cInd, 1 );
1102 0 : move16();
1103 : }
1104 : }
1105 0 : IF( foundPeak == 0 ) /* The above IF-block has not found the peak yet. */
1106 : {
1107 0 : IF( LT_16( *pX, leftMin ) ) /* New left minimum */
1108 : {
1109 0 : leftMin = *pX;
1110 0 : move16();
1111 0 : threshold = add( leftMin, sel );
1112 : }
1113 : }
1114 : }
1115 :
1116 : /* Check end point */
1117 0 : IF( GT_16( x[lenMinus1], tempMag ) )
1118 : {
1119 0 : IF( GT_16( x[lenMinus1], threshold ) ) /* threshold = leftMin + sel */
1120 : {
1121 0 : peakLoc[*cInd] = lenMinus1;
1122 0 : move16();
1123 0 : peakMag[*cInd] = x[lenMinus1];
1124 0 : move16();
1125 0 : *cInd = add( *cInd, 1 );
1126 0 : foundPeak = 1;
1127 0 : move16();
1128 : }
1129 : }
1130 0 : IF( foundPeak == 0 ) /* Check if we still need to add the last point */
1131 : {
1132 0 : IF( GT_16( tempMag, minMag ) )
1133 : {
1134 0 : peakLoc[*cInd] = tempLoc;
1135 0 : move16();
1136 0 : peakMag[*cInd] = tempMag;
1137 0 : move16();
1138 0 : *cInd = add( *cInd, 1 );
1139 0 : move16();
1140 : }
1141 : }
1142 :
1143 : /* Create output */
1144 0 : FOR( i = 0; i < *cInd; i++ )
1145 : {
1146 0 : plocs[i] = *( indarr + peakLoc[i] );
1147 0 : move16();
1148 : }
1149 : }
1150 : ELSE /* This is a monotone function where an endpoint is the only peak */
1151 : {
1152 : {
1153 0 : xInd = 1;
1154 0 : move16();
1155 0 : if ( GT_16( x[0], x[1] ) )
1156 : {
1157 0 : xInd = 0;
1158 0 : move16();
1159 : }
1160 :
1161 0 : peakMag[0] = x[xInd];
1162 0 : move16();
1163 0 : IF( GT_16( peakMag[0], add( minMag, sel ) ) )
1164 : {
1165 0 : plocs[0] = *( indarr + xInd );
1166 0 : move16();
1167 0 : *cInd = 1;
1168 0 : move16();
1169 : }
1170 : ELSE
1171 : {
1172 0 : *cInd = 0;
1173 0 : move16();
1174 : }
1175 : }
1176 : }
1177 0 : }
1178 :
1179 : /*-----------------------------------------------------------------------------
1180 : * imax_fx()
1181 : *
1182 : * Get interpolated maximum position
1183 : *-----------------------------------------------------------------------------*/
1184 0 : static Word16 imax_fx( /* o: The location, relative to the middle of the 3 given data point, of the maximum. (Q15) */
1185 : const Word16 *y, /* i: The 3 given data points. */
1186 : const Word16 special /* i: -1 = left edge special case, 0 = normal, +1 = right edge special case */
1187 : )
1188 : {
1189 : Word16 posi;
1190 : Word16 y1, y2, y3, man, expo, edge;
1191 : const Word16 *pY;
1192 : Word32 numer, denom, sign, acc, y3_y1;
1193 : /* Seek the extremum of the parabola P(x) defined by 3 consecutive points
1194 : so that P([-1 0 1]) = [y1 y2 y3] */
1195 0 : pY = y;
1196 0 : y1 = *pY++, y2 = *pY++, y3 = *pY;
1197 0 : move16();
1198 0 : move16();
1199 0 : move16();
1200 :
1201 : /* The extremum value:
1202 : * y2i = -0.125f * SQR(y3_y1) / (y1+y3-2*y2)+y2
1203 : * is not computed. Alternatively, the derivative of the parabola evaluated at y=0,
1204 : * dP/dy|y=0, is used to determine whether the extremum is maximum or not.
1205 : */
1206 :
1207 : /* Compute the extremum location: posi = (y3 - y1)/(4*y2 - 2*y1 - 2*y3). */
1208 0 : y3_y1 = L_sub( y3, y1 );
1209 0 : acc = L_shl( y2, 1 ); /* N.B. y2 is multiplied by 2 not 4. */
1210 0 : acc = L_sub( acc, y1 ); /* N.B. Y1 is not multiplied by 2. */
1211 0 : denom = L_sub( acc, y3 ); /* N.B. Y3 is not multiplied by 2. */
1212 0 : sign = L_xor( y3_y1, denom ); /* Preserve the sign since div_s() only takes positive arguments. */
1213 0 : numer = L_abs( y3_y1 );
1214 0 : denom = L_abs( denom );
1215 0 : IF( numer == 0 )
1216 : {
1217 0 : return 0;
1218 : }
1219 0 : IF( denom == 0 )
1220 : {
1221 0 : return 0;
1222 : }
1223 : /* Although the output of ratio() is in Q14, adding the missing factor of 2 (See above)
1224 : * in the denominator, the output is now considered to be in Q15. */
1225 0 : man = ratio( numer, denom, &expo ); /* The mantissa is considered in Q15 */
1226 0 : posi = shr_sat( man, expo ); /* in Q15 (Due to saturation, it is automatically bound inside [-1.0,1.0].) */
1227 0 : if ( sign < 0 ) /* Restore the sign. */
1228 : {
1229 0 : posi = negate( posi );
1230 : }
1231 :
1232 : /* For both edges (left and right), the extremum found above may be minimum.
1233 : * It needs to reject the minimum. */
1234 0 : IF( special != 0 ) /* Either edge specical case. */
1235 : {
1236 0 : edge = 0x7fff; /* 1 in Q15 for the right edge special case */
1237 0 : move16();
1238 0 : if ( special < 0 )
1239 : {
1240 0 : edge = 0; /* Left edge special case */
1241 0 : move16();
1242 : }
1243 :
1244 : /* The derivative (slope) of the interpolating parabola = 2*A*y + B,
1245 : * where A = (y3 + y1)/2 - y2
1246 : * and B = (y3 - y1)/2.
1247 : * Therefore, the slope at y=0 is simply B. Use this slope to determine
1248 : * if the parabola is concave upward or downward.
1249 : */
1250 0 : IF( posi > 0 ) /* The extremum is in between the middle and the right given data points. */
1251 : {
1252 0 : IF( LE_16( y3, y1 ) ) /* Check the slope at y=0, i.e., at the middle given data point. */
1253 : {
1254 0 : posi = edge; /* minimum case */
1255 0 : move16();
1256 : }
1257 : ELSE
1258 : {
1259 0 : posi = sub( 0x7fff, posi ); /* maximum case */
1260 : }
1261 : }
1262 : ELSE /* The extremum is in between the left and the middle given data points. */
1263 : {
1264 0 : IF( GE_16( y3, y1 ) )
1265 : {
1266 0 : posi = edge; /* minimum case */
1267 0 : move16();
1268 : }
1269 : ELSE
1270 : {
1271 0 : posi = add( 0x7fff, posi ); /* maximum case */
1272 : }
1273 : }
1274 : }
1275 0 : return posi; /* Q15. The position either left or right relative to the index of the middle of the 3 given data points. */
1276 : }
1277 :
1278 : /*-----------------------------------------------------------------------------
1279 : * spec_ana_fx()
1280 : *
1281 : * Spectral analysis
1282 : *-----------------------------------------------------------------------------*/
1283 :
1284 54 : static void ivas_spec_ana_fx(
1285 : const Word16 *prevsynth, /* i : Input signal */
1286 : Word16 *plocs, /* o : The indicies of the identified peaks Q0 */
1287 : Word32 *plocsi, /* o : Interpolated positions of the identified peaks Q16 */
1288 : Word16 *num_plocs, /* o : Number of identified peaks Q0 */
1289 : Word16 *X_sav, /* o : Stored fft spectrum */
1290 : const Word16 output_frame, /* i : Frame length Q0 */
1291 : const Word16 bwidth_fx, /* i : Encoded bandwidth index Q0 */
1292 : Word16 *Q, /* o : Q value of the fft spectrum */
1293 : const Word16 element_mode, /* i : IVAS element mode */
1294 : Word16 *noise_fac, /* o : for few peaks zeroing valleys decision making Q15*/
1295 : const Word16 pcorr )
1296 : {
1297 54 : Word16 Lprot, LprotLog2Minus1 = 0, hamm_len2 = 0, Lprot2, Lprot2_1, m, n;
1298 54 : const Word16 *pFftTbl = NULL;
1299 : Word16 xfp[L_PROT48k];
1300 : Word32 magSq[L_PROT48k / 2 + 1], *pMagSq;
1301 : Word16 *pXfp, *pXfp1, *pXsav, *pPlocs;
1302 : Word16 Xmax, Xmin, sel, man, expo, expoBy2;
1303 : Word16 sinTblOffset, rectLength, fraction, special;
1304 : Word32 *pPlocsi;
1305 : Word32 acc;
1306 : Word16 stop_band_start;
1307 : Word16 stop_band_length;
1308 54 : const Word16 *w_hamm = NULL;
1309 : Word16 window_corr, window_corr_step;
1310 : Word16 currPlocs, endPlocs, nJacob, k, i;
1311 : Word32 sig, noise, st_point, end_point;
1312 : Word32 xfp_32[3]; // Q + 16
1313 :
1314 54 : move16(); // LprotLog2Minus1
1315 54 : move16(); // hamm_len2
1316 54 : Lprot = 512; /* 1536=(2*output_frame)*1024/1280; */
1317 54 : move16();
1318 :
1319 54 : sinTblOffset = 0;
1320 54 : move16();
1321 :
1322 54 : IF( EQ_16( output_frame, L_FRAME48k ) )
1323 : {
1324 25 : Lprot = L_PROT48k; /* 1536=(2*output_frame)*1024/1280; */
1325 25 : move16();
1326 25 : hamm_len2 = L_PROT_HAMM_LEN2_48k; /* half Hamming window = 288 */
1327 25 : move16();
1328 25 : w_hamm = w_hamm_sana48k_2_fx;
1329 : }
1330 29 : ELSE IF( EQ_16( output_frame, L_FRAME32k ) )
1331 : {
1332 29 : Lprot = L_PROT32k; /* 1024 */
1333 29 : move16();
1334 29 : sinTblOffset = 4;
1335 29 : move16();
1336 29 : hamm_len2 = L_PROT_HAMM_LEN2_32k; /* half Hamming window = 192 */
1337 29 : move16();
1338 29 : pFftTbl = FFT_W512; /* Table for 1024-point real input FFT */
1339 29 : LprotLog2Minus1 = 9; /* FFT stages for complex input FFT */
1340 29 : move16();
1341 29 : w_hamm = w_hamm_sana32k_2_fx;
1342 : }
1343 : ELSE
1344 : {
1345 0 : Lprot = 512;
1346 0 : move16();
1347 0 : sinTblOffset = 8;
1348 0 : move16();
1349 0 : hamm_len2 = L_PROT_HAMM_LEN2_16k; /* half Hamming window = 96 */
1350 0 : move16();
1351 0 : pFftTbl = FFT_W256; /* Table for 512-point real input FFT */
1352 0 : LprotLog2Minus1 = 8; /* FFT stages for complex input FFT */
1353 0 : move16();
1354 0 : w_hamm = w_hamm_sana16k_2_fx;
1355 : }
1356 :
1357 54 : Lprot2 = shr( Lprot, 1 );
1358 54 : Lprot2_1 = add( Lprot2, 1 );
1359 54 : rectLength = sub( Lprot, shl( hamm_len2, 1 ) ); /* The length of the rectangular portion of the Hamming-Rectangular window. */
1360 :
1361 54 : *Q = s_max( 0, sub( Exp16Array( Lprot, prevsynth ), 1 ) );
1362 54 : move16();
1363 54 : Copy_Scale_sig( prevsynth, xfp, Lprot, *Q );
1364 :
1365 :
1366 54 : IF( EQ_16( output_frame, L_FRAME48k ) )
1367 : {
1368 : /* Apply hamming-rect window */
1369 25 : IF( element_mode == EVS_MONO )
1370 : {
1371 0 : windowing( xfp, xfp, w_hamm_sana48k_2_fx, rectLength, hamm_len2 );
1372 : }
1373 : ELSE
1374 : {
1375 : // PMTE()
1376 25 : window_corr = w_hamm[0];
1377 25 : move16();
1378 25 : window_corr_step = idiv1616( w_hamm[0], hamm_len2 );
1379 7225 : FOR( i = 0; i < hamm_len2; i++ )
1380 : {
1381 7200 : xfp[i] = mult_r( shl( prevsynth[i], *Q ), sub( w_hamm[i], window_corr ) );
1382 7200 : move16();
1383 7200 : xfp[Lprot - i - 1] = mult_r( shl( prevsynth[Lprot - i - 1], *Q ), sub( w_hamm[i], window_corr ) );
1384 7200 : move16();
1385 7200 : window_corr = sub( window_corr, window_corr_step );
1386 : }
1387 : }
1388 : /* Spectrum */
1389 25 : fft3_fx( xfp, xfp, Lprot );
1390 : }
1391 : ELSE
1392 : {
1393 29 : IF( element_mode == EVS_MONO )
1394 : {
1395 : /* Apply hamming-rect window */
1396 0 : windowing_ROM_optimized( xfp, xfp, sinTblOffset, rectLength, hamm_len2 );
1397 : }
1398 : ELSE
1399 : {
1400 : // PMTE()
1401 29 : window_corr = w_hamm[0];
1402 29 : move16();
1403 29 : window_corr_step = idiv1616( w_hamm[0], hamm_len2 );
1404 5597 : FOR( i = 0; i < hamm_len2; i++ )
1405 : {
1406 5568 : xfp[i] = mult_r( shl( prevsynth[i], *Q ), sub( w_hamm[i], window_corr ) );
1407 5568 : move16();
1408 5568 : xfp[Lprot - i - 1] = mult_r( shl( prevsynth[Lprot - i - 1], *Q ), sub( w_hamm[i], window_corr ) );
1409 5568 : move16();
1410 5568 : window_corr = sub( window_corr, window_corr_step );
1411 : }
1412 : }
1413 : /* Spectrum */
1414 29 : r_fft_fx_lc( pFftTbl, Lprot, Lprot2, LprotLog2Minus1, xfp, xfp, 1 );
1415 : }
1416 :
1417 : /* Apply zeroing of non-coded FFT spectrum */
1418 54 : IF( GT_16( output_frame, inner_frame_tbl[bwidth_fx] ) )
1419 : {
1420 11 : stop_band_start = shl( 128, bwidth_fx );
1421 11 : stop_band_length = sub( Lprot, shl( stop_band_start, 1 ) );
1422 11 : stop_band_start = add( stop_band_start, 1 );
1423 11 : set16_fx( xfp + stop_band_start, 0, stop_band_length );
1424 : }
1425 :
1426 54 : pXfp = xfp;
1427 54 : pXsav = X_sav;
1428 :
1429 68150 : FOR( m = 0; m < Lprot; m++ )
1430 : {
1431 68096 : *pXsav++ = *pXfp++;
1432 68096 : move16();
1433 : }
1434 :
1435 : /* Magnitude representation */
1436 54 : fft_spec2_fx( xfp, magSq, Lprot );
1437 :
1438 : /* Compute xfp[m] = sqrt(magSq[m]) */
1439 54 : pXfp = xfp;
1440 54 : pMagSq = magSq;
1441 34156 : FOR( m = 0; m < Lprot2_1; m++ )
1442 : {
1443 34102 : IF( *pMagSq == 0 )
1444 : {
1445 5526 : *pXfp++ = extract_l( *pMagSq++ ); /* magSq[] is zero */
1446 5526 : move16();
1447 : }
1448 : ELSE
1449 : {
1450 28576 : expo = norm_l( *pMagSq ); /* exponent */
1451 28576 : man = extract_h( L_shl( *pMagSq++, expo ) ); /* mantissa */
1452 28576 : man = sqrt2ndOrder( man );
1453 28576 : expoBy2 = shr( expo, 1 ); /* Divided by 2-- square root operation. */
1454 28576 : IF( s_and( expo, 1 ) == 0 ) /* Check even or odd. */
1455 : {
1456 15599 : man = mult_r( man, FEC_HQ_ECU_ROOT2 ); /* FEC_HQ_ECU_ROOT2 is sqrt(2) in Q14 */
1457 15599 : expoBy2 = sub( expoBy2, 1 );
1458 : }
1459 28576 : *pXfp++ = shr_sat( man, expoBy2 );
1460 28576 : move16(); /* Denormalize the mantissa back to Q0. */
1461 : }
1462 : }
1463 :
1464 : /* Find maximum and minimum. */
1465 54 : maximum_fx( xfp, Lprot2_1, &Xmax );
1466 54 : minimum_fx( xfp, Lprot2_1, &Xmin );
1467 54 : IF( element_mode == EVS_MONO )
1468 : {
1469 0 : sel = mult_r( sub( Xmax, Xmin ), CMPLMNT_PFIND_SENS_FX );
1470 : }
1471 : ELSE
1472 : {
1473 54 : sel = mult_r( sub( Xmax, Xmin ), CMPLMNT_ST_PFIND_SENS_FX );
1474 : }
1475 54 : ivas_peakfinder_fx( xfp, Lprot2_1, plocs, num_plocs, sel, TRUE );
1476 :
1477 :
1478 : /* Currently not the pitch correlation but some LF correlation */
1479 54 : if ( element_mode != EVS_MONO && *num_plocs > 50 && pcorr < 19661 /* 0.6f in Q15 */ )
1480 : {
1481 0 : *num_plocs = 0;
1482 0 : move16();
1483 : }
1484 :
1485 54 : IF( element_mode == EVS_MONO )
1486 : {
1487 :
1488 : /* Refine peaks */
1489 0 : pPlocsi = plocsi;
1490 0 : pPlocs = plocs;
1491 0 : n = sub( *num_plocs, 1 ); /* -1 so as to exclude the very last peak. */
1492 : /* Special case-- The very 1st peak if it is at 0 index position */
1493 0 : IF( *pPlocs == 0 ) /* Only the very 1st peak is possible the peak at 0 index position. */
1494 : {
1495 0 : fraction = imax_fx( xfp, -1 ); /* -1 signifies special left edge case. */
1496 0 : acc = L_deposit_h( *pPlocs++ ); /* N.B., (*pPlocs) must be zero here. */
1497 0 : *pPlocsi++ = L_mac( acc, fraction, 1 );
1498 0 : move32(); /* in Q16 */
1499 0 : n = sub( n, 1 ); /* This special case is taken care of-- one less to go */
1500 : }
1501 : /* All peaks except the very last peak but including the very 1st one if it has not been taken care of. */
1502 0 : pXfp1 = xfp - 1;
1503 0 : FOR( m = 0; m < n; m++ ) /* Loop through up to the last but one peak. (The last one is excluded.) */
1504 : {
1505 0 : pXfp = pXfp1 + *pPlocs;
1506 0 : fraction = imax_fx( pXfp, 0 ); /* in Q15 */
1507 0 : acc = L_deposit_h( *pPlocs++ );
1508 0 : *pPlocsi++ = L_mac( acc, fraction, 1 );
1509 0 : move32(); /* in Q16. Append the fractional part to the integral part. */
1510 : }
1511 0 : IF( n >= 0 )
1512 : {
1513 : /* Special case-- The very last peak */
1514 0 : pXfp = pXfp1 + *pPlocs;
1515 0 : IF( EQ_16( *pPlocs, Lprot2 ) ) /* Only the very last peak is possible the peak at Lprot2 index position. */
1516 : {
1517 0 : pXfp--; /* Special case needs extra decrement */
1518 0 : special = 1; /* Signify special right edge case. */
1519 0 : move16();
1520 : }
1521 : ELSE
1522 : {
1523 0 : special = 0;
1524 0 : move16();
1525 : }
1526 0 : fraction = imax_fx( pXfp, special ); /* in Q15 */
1527 0 : acc = L_deposit_h( *pPlocs );
1528 0 : *pPlocsi = L_mac( acc, fraction, 1 );
1529 0 : move32(); /* in Q16. Append the fractional part to the integral part. */
1530 : }
1531 : }
1532 : ELSE
1533 : {
1534 54 : Lprot2 = shr( Lprot, 1 );
1535 54 : Lprot2_1 = add( Lprot2, 1 );
1536 :
1537 : /* Refine peaks */
1538 54 : pPlocsi = plocsi;
1539 54 : pPlocs = plocs;
1540 54 : n = *num_plocs; /* number of peaks to process */
1541 54 : move16();
1542 :
1543 : /* Special case-- The very 1st peak if it is at 0 index position (DC) */
1544 : /* With DELTA_CORR_F0_INT == 2 one needs to handle both *pPlocs==0 and *pPlocs==1 */
1545 : // IF( n > 0 && *pPlocs == 0 ) /* Very 1st peak position possible to have a peak at 0/DC index position. */
1546 54 : test();
1547 54 : IF( n > 0 && *pPlocs == 0 ) /* Very 1st peak position possible to have a peak at 0/DC index position. */
1548 : {
1549 0 : Copy_Scale_sig_16_32_no_sat( &xfp[*pPlocs], xfp_32, 3, Q15 ); // Q + 15
1550 0 : acc = L_deposit_h( *pPlocs ); // Q16
1551 0 : *pPlocsi++ = L_add( acc, L_shl( imax_pos_fx( xfp_32 ) /* Q15 */, 1 ) ); // Q16
1552 0 : move32();
1553 0 : pPlocs++;
1554 0 : n = sub( n, 1 );
1555 : }
1556 :
1557 54 : test();
1558 54 : IF( n > 0 && EQ_16( *pPlocs, 1 ) ) /* Also 2nd peak position uses DC which makes jacobsen unsuitable. */
1559 : {
1560 4 : Copy_Scale_sig_16_32_no_sat( &xfp[*pPlocs - 1], xfp_32, 3, Q15 ); // Q + 15
1561 4 : acc = L_deposit_h( sub( *pPlocs, 1 ) ); // Q16
1562 4 : *pPlocsi++ = L_add( acc, L_shl( imax_pos_fx( xfp_32 ) /* Q15 */, 1 ) ); // Q16
1563 4 : move32();
1564 4 : currPlocs = *pPlocs++; // Q16
1565 4 : move16();
1566 4 : n = sub( n, 1 );
1567 : }
1568 :
1569 : /* All remaining peaks except the very last two possible integer positions */
1570 54 : currPlocs = *pPlocs++;
1571 54 : move16();
1572 54 : endPlocs = sub( Lprot2_1, DELTA_CORR_F0_INT ); /* last *pPlocs position for Jacobsen */
1573 :
1574 : /* precompute number of turns based on endpoint integer location and make into a proper for loop */
1575 54 : IF( n > 0 )
1576 : {
1577 54 : nJacob = n;
1578 54 : move16();
1579 54 : if ( sub( endPlocs, plocs[*num_plocs - 1] ) <= 0 )
1580 : {
1581 0 : nJacob = sub( nJacob, 1 );
1582 : }
1583 :
1584 940 : FOR( k = 0; k < nJacob; k++ )
1585 : {
1586 886 : fraction = ivas_imax2_jacobsen_mag_fx( &( X_sav[currPlocs - 1] ), &( X_sav[Lprot - 1 - currPlocs] ) ); /* in Q15 */
1587 886 : acc = L_deposit_h( currPlocs ); // Q16
1588 886 : *pPlocsi++ = L_mac( acc, fraction, 1 ); // Q16
1589 886 : move32();
1590 886 : currPlocs = *pPlocs++; // Q16
1591 886 : move16();
1592 : }
1593 54 : n = sub( n, nJacob );
1594 : }
1595 :
1596 : /* At this point there should at most two plocs left to process */
1597 : /* the position before fs/2 and fs/2 both use the same magnitude points */
1598 54 : IF( n > 0 )
1599 : {
1600 : /* [ . . . . . . . ] Lprot/2+1 positions */
1601 : /* | | | */
1602 : /* 0 (Lprot/2-2) (Lprot/2) */
1603 :
1604 0 : IF( EQ_16( currPlocs, ( sub( Lprot2_1, DELTA_CORR_F0_INT ) ) ) ) /* Also 2nd last peak position uses fs/2 which makes jacobsen less suitable. */
1605 : {
1606 0 : Copy_Scale_sig_16_32_no_sat( &xfp[currPlocs - 1], xfp_32, 3, Q15 ); // Q + 15
1607 0 : acc = L_deposit_h( sub( currPlocs, 1 ) ); // Q16
1608 0 : *pPlocsi++ = L_add( acc, L_shl( imax_pos_fx( xfp_32 ) /* Q15 */, 1 ) ); // Q16
1609 0 : move32();
1610 0 : currPlocs = *pPlocs++; // Q16
1611 0 : move16();
1612 0 : n = sub( n, 1 );
1613 : }
1614 :
1615 : /* Here the only remaining point would be a fs/2 plocs */
1616 : /* pXfp = xfp + sub(Lprot2,1); already set just a reminder where it
1617 : * whould point */
1618 0 : IF( n > 0 ) /* fs/2 which makes special case . */
1619 : {
1620 0 : Copy_Scale_sig_16_32_no_sat( &xfp[currPlocs - 2], xfp_32, 3, Q15 ); // Q + 15
1621 0 : acc = L_deposit_h( sub( currPlocs, 2 ) ); // Q16
1622 0 : *pPlocsi++ = L_add( acc, L_shl( imax_pos_fx( xfp_32 ) /* Q15 */, 1 ) ); // Q16
1623 0 : move32();
1624 0 : currPlocs = *pPlocs++; // Q16
1625 0 : move16();
1626 0 : n = sub( n, 1 );
1627 : }
1628 : }
1629 :
1630 : /* For few peaks decide noise floor attenuation */
1631 54 : test();
1632 54 : IF( LT_16( *num_plocs, 3 ) && *num_plocs > 0 )
1633 : {
1634 3 : sig = L_add( sum16_32_fx( xfp, Lprot2_1 ), 1 );
1635 :
1636 : /*excluding peaks and neighboring bins*/
1637 9 : FOR( i = 0; i < *num_plocs; i++ )
1638 : {
1639 6 : st_point = s_max( 0, sub( plocs[i], DELTA_CORR ) );
1640 6 : end_point = s_min( sub( Lprot2_1, 1 ), add( plocs[i], DELTA_CORR ) );
1641 6 : set16_fx( &xfp[st_point], 0, extract_l( L_add( L_sub( end_point, st_point ), 1 ) ) );
1642 : }
1643 3 : noise = L_add( sum16_32_fx( xfp, Lprot2_1 ), 1 );
1644 :
1645 3 : IF( LT_32( noise, Mpy_32_32( 64424509 /* 0.03 in Q31 */, sig ) ) )
1646 : {
1647 0 : *noise_fac = 16384; /* 0.5f in Q15 */
1648 0 : move16();
1649 : }
1650 : ELSE
1651 : {
1652 3 : *noise_fac = 32767; /* 1.0f in Q15 */
1653 3 : move16();
1654 : }
1655 : }
1656 : }
1657 54 : }
1658 :
1659 0 : static void spec_ana_fx(
1660 : const Word16 *prevsynth, /* i : Input signal */
1661 : Word16 *plocs, /* o : The indicies of the identified peaks Q0 */
1662 : Word32 *plocsi, /* o : Interpolated positions of the identified peaks Q16 */
1663 : Word16 *num_plocs, /* o : Number of identified peaks Q0 */
1664 : Word16 *X_sav, /* o : Stored fft spectrum */
1665 : const Word16 output_frame, /* i : Frame length Q0 */
1666 : const Word16 bwidth_fx, /* i : Encoded bandwidth index Q0 */
1667 : Word16 *Q /* o : Q value of the fft spectrum */
1668 : )
1669 : {
1670 : Word16 Lprot, LprotLog2Minus1, hamm_len2, Lprot2, Lprot2_1, m, n;
1671 0 : const Word16 *pFftTbl = NULL;
1672 : Word16 xfp[L_PROT48k];
1673 : Word32 magSq[L_PROT48k / 2 + 1], *pMagSq;
1674 : Word16 *pXfp, *pXfp1, *pXsav, *pPlocs;
1675 : Word16 Xmax, Xmin, sel, man, expo, expoBy2;
1676 : Word16 sinTblOffset, rectLength, fraction, special;
1677 : Word32 *pPlocsi;
1678 : Word32 acc;
1679 : Word16 stop_band_start;
1680 : Word16 stop_band_length;
1681 :
1682 0 : LprotLog2Minus1 = 0;
1683 0 : hamm_len2 = 0;
1684 0 : move16(); // LprotLog2Minus1
1685 0 : move16(); // hamm_len2
1686 0 : Lprot = 512; /* 1536=(2*output_frame)*1024/1280; */
1687 0 : move16();
1688 :
1689 0 : sinTblOffset = 0;
1690 0 : move16();
1691 :
1692 0 : IF( EQ_16( output_frame, L_FRAME48k ) )
1693 : {
1694 0 : Lprot = L_PROT48k; /* 1536=(2*output_frame)*1024/1280; */
1695 0 : move16();
1696 0 : hamm_len2 = L_PROT_HAMM_LEN2_48k; /* half Hamming window = 288 */
1697 0 : move16();
1698 : }
1699 0 : ELSE IF( EQ_16( output_frame, L_FRAME32k ) )
1700 : {
1701 0 : Lprot = L_PROT32k; /* 1024 */
1702 0 : move16();
1703 0 : sinTblOffset = 4;
1704 0 : move16();
1705 0 : hamm_len2 = L_PROT_HAMM_LEN2_32k; /* half Hamming window = 192 */
1706 0 : move16();
1707 0 : pFftTbl = FFT_W512; /* Table for 1024-point real input FFT */
1708 0 : LprotLog2Minus1 = 9; /* FFT stages for complex input FFT */
1709 0 : move16();
1710 : }
1711 : ELSE
1712 : {
1713 0 : Lprot = 512;
1714 0 : move16();
1715 0 : sinTblOffset = 8;
1716 0 : move16();
1717 0 : hamm_len2 = L_PROT_HAMM_LEN2_16k; /* half Hamming window = 96 */
1718 0 : move16();
1719 0 : pFftTbl = FFT_W256; /* Table for 512-point real input FFT */
1720 0 : LprotLog2Minus1 = 8; /* FFT stages for complex input FFT */
1721 0 : move16();
1722 : }
1723 :
1724 0 : Lprot2 = shr( Lprot, 1 );
1725 0 : Lprot2_1 = add( Lprot2, 1 );
1726 0 : rectLength = sub( Lprot, shl( hamm_len2, 1 ) ); /* The length of the rectangular portion of the Hamming-Rectangular window. */
1727 :
1728 0 : *Q = s_max( 0, sub( Exp16Array( Lprot, prevsynth ), 1 ) );
1729 0 : move16();
1730 0 : Copy_Scale_sig( prevsynth, xfp, Lprot, *Q );
1731 :
1732 0 : IF( EQ_16( output_frame, L_FRAME48k ) )
1733 : {
1734 : /* Apply hamming-rect window */
1735 : {
1736 0 : windowing( xfp, xfp, w_hamm_sana48k_2_fx, rectLength, hamm_len2 );
1737 : }
1738 : /* Spectrum */
1739 0 : fft3_fx( xfp, xfp, Lprot );
1740 : }
1741 : ELSE
1742 : {
1743 : {
1744 : /* Apply hamming-rect window */
1745 0 : windowing_ROM_optimized( xfp, xfp, sinTblOffset, rectLength, hamm_len2 );
1746 : }
1747 : /* Spectrum */
1748 0 : r_fft_fx_lc( pFftTbl, Lprot, Lprot2, LprotLog2Minus1, xfp, xfp, 1 );
1749 : }
1750 :
1751 : /* Apply zeroing of non-coded FFT spectrum */
1752 0 : IF( GT_16( output_frame, inner_frame_tbl[bwidth_fx] ) )
1753 : {
1754 0 : stop_band_start = shl( 128, bwidth_fx );
1755 0 : stop_band_length = sub( Lprot, shl( stop_band_start, 1 ) );
1756 0 : stop_band_start = add( stop_band_start, 1 );
1757 0 : set16_fx( xfp + stop_band_start, 0, stop_band_length );
1758 : }
1759 :
1760 0 : pXfp = xfp;
1761 0 : pXsav = X_sav;
1762 0 : FOR( m = 0; m < Lprot; m++ )
1763 : {
1764 0 : *pXsav++ = *pXfp++;
1765 0 : move16();
1766 : }
1767 :
1768 : /* Magnitude representation */
1769 0 : fft_spec2_fx( xfp, magSq, Lprot );
1770 :
1771 : /* Compute xfp[m] = sqrt(magSq[m]) */
1772 0 : pXfp = xfp;
1773 0 : pMagSq = magSq;
1774 0 : FOR( m = 0; m < Lprot2_1; m++ )
1775 : {
1776 0 : IF( *pMagSq == 0 )
1777 : {
1778 0 : *pXfp++ = extract_l( *pMagSq++ ); /* magSq[] is zero */
1779 : }
1780 : ELSE
1781 : {
1782 0 : expo = norm_l( *pMagSq ); /* exponent */
1783 0 : man = extract_h( L_shl( *pMagSq++, expo ) ); /* mantissa */
1784 0 : man = sqrt2ndOrder( man );
1785 0 : expoBy2 = shr( expo, 1 ); /* Divided by 2-- square root operation. */
1786 0 : IF( s_and( expo, 1 ) == 0 ) /* Check even or odd. */
1787 : {
1788 0 : man = mult_r( man, FEC_HQ_ECU_ROOT2 ); /* FEC_HQ_ECU_ROOT2 is sqrt(2) in Q14 */
1789 0 : expoBy2 = sub( expoBy2, 1 );
1790 : }
1791 0 : *pXfp++ = shr_sat( man, expoBy2 );
1792 0 : move16(); /* Denormalize the mantissa back to Q0. */
1793 : }
1794 : }
1795 :
1796 : /* Find maximum and minimum. */
1797 0 : maximum_fx( xfp, Lprot2_1, &Xmax );
1798 0 : minimum_fx( xfp, Lprot2_1, &Xmin );
1799 : {
1800 0 : sel = mult_r( sub( Xmax, Xmin ), CMPLMNT_PFIND_SENS_FX );
1801 : }
1802 0 : peakfinder_fx( xfp, Lprot2_1, plocs, num_plocs, sel );
1803 :
1804 :
1805 : {
1806 :
1807 : /* Refine peaks */
1808 0 : pPlocsi = plocsi;
1809 0 : pPlocs = plocs;
1810 0 : n = sub( *num_plocs, 1 ); /* -1 so as to exclude the very last peak. */
1811 : /* Special case-- The very 1st peak if it is at 0 index position */
1812 0 : IF( *pPlocs == 0 ) /* Only the very 1st peak is possible the peak at 0 index position. */
1813 : {
1814 0 : fraction = imax_fx( xfp, -1 ); /* -1 signifies special left edge case. */
1815 0 : acc = L_deposit_h( *pPlocs++ ); /* N.B., (*pPlocs) must be zero here. */
1816 0 : *pPlocsi++ = L_mac( acc, fraction, 1 );
1817 0 : move32(); /* in Q16 */
1818 0 : n = sub( n, 1 ); /* This special case is taken care of-- one less to go */
1819 : }
1820 : /* All peaks except the very last peak but including the very 1st one if it has not been taken care of. */
1821 0 : pXfp1 = xfp - 1;
1822 0 : FOR( m = 0; m < n; m++ ) /* Loop through up to the last but one peak. (The last one is excluded.) */
1823 : {
1824 0 : pXfp = pXfp1 + *pPlocs;
1825 0 : fraction = imax_fx( pXfp, 0 ); /* in Q15 */
1826 0 : acc = L_deposit_h( *pPlocs++ );
1827 0 : *pPlocsi++ = L_mac( acc, fraction, 1 );
1828 0 : move32(); /* in Q16. Append the fractional part to the integral part. */
1829 : }
1830 0 : IF( n >= 0 )
1831 : {
1832 : /* Special case-- The very last peak */
1833 0 : pXfp = pXfp1 + *pPlocs;
1834 0 : IF( EQ_16( *pPlocs, Lprot2 ) ) /* Only the very last peak is possible the peak at Lprot2 index position. */
1835 : {
1836 0 : pXfp--; /* Special case needs extra decrement */
1837 0 : special = 1; /* Signify special right edge case. */
1838 0 : move16();
1839 : }
1840 : ELSE
1841 : {
1842 0 : special = 0;
1843 0 : move16();
1844 : }
1845 0 : fraction = imax_fx( pXfp, special ); /* in Q15 */
1846 0 : acc = L_deposit_h( *pPlocs );
1847 0 : *pPlocsi = L_mac( acc, fraction, 1 );
1848 0 : move32(); /* in Q16. Append the fractional part to the integral part. */
1849 : }
1850 : }
1851 0 : }
1852 :
1853 : /*-------------------------------------------------------------------*
1854 : * subst_spec_fx()
1855 : *
1856 : * Substitution spectrum calculation
1857 : *-------------------------------------------------------------------*/
1858 :
1859 132 : static void ivas_subst_spec_fx(
1860 : const Word16 *plocs, /* i : The indices of the identified peaks Q0 */
1861 : const Word32 *plocsi, /* i : Interpolated positions of the identified peaks Q16 */
1862 : Word16 *num_plocs, /* i/o : Number of identified peaks Q0 */
1863 : const Word16 time_offs, /* i : Time offset Q0 */
1864 : Word16 *X, /* i/o : FFT spectrum */
1865 : const Word16 *mag_chg, /* i : Magnitude modification Q15 */
1866 : const Word16 ph_dith, /* i : Phase dither, 2*PI is not included. (Q15, i.e., between 0.0 and 1.0) */
1867 : const Word16 *is_trans, /* i : Transient flags (either 0 or 1) */
1868 : const Word16 output_frame, /* i : Frame length Q0 */
1869 : Word16 *seed, /* i/o : Random seed */
1870 : const Word16 *alpha, /* i : Magnitude modification factors for fade to average Q15 */
1871 : const Word16 *beta, /* i : Magnitude modification factors for fade to average Q15 */
1872 : Word16 beta_mute, /* i : Factor for long-term mute Q15 */
1873 : const Word16 *Xavg, /* i : Frequency group averages to fade to Q0 */
1874 : const Word16 element_mode, /* i : IVAS element mode */
1875 : const Word16 ph_ecu_lookahead, /* i : Phase ECU lookahead */
1876 : const Word16 noise_fac /* i : noise factor Q15 */
1877 : )
1878 : {
1879 : Word16 Xph_short;
1880 : Word32 corr_phase[MAX_PLOCS], Xph;
1881 : Word32 *pCorrPhase;
1882 : Word16 cos_F, sin_F, tmp;
1883 : Word16 Lprot, m, i, e, im_ind, delta_corr_up, delta_corr_dn, delta_tmp;
1884 : Word32 tmp1;
1885 : Word16 j, re, im, *pReX, *pImX, lastPeak, lprotBy2Minus1, segmentLen;
1886 : Word16 pkLocation_1, pkLocation, pkLocation1;
1887 : const Word16 *pPlocs;
1888 : const Word32 *pPlocsi;
1889 : Word32 acc;
1890 : Word16 Lecu;
1891 : Word16 Lprot_inv;
1892 : Word16 k;
1893 : Word16 tmp2;
1894 : Word16 alpha_local;
1895 : Word16 beta_local;
1896 : Word16 expo;
1897 : Word16 one_peak_flag_mask;
1898 : Word16 mag_chg_local; /*for peak attenuation in burst */
1899 :
1900 132 : Lprot = 512;
1901 132 : move16();
1902 132 : Lprot_inv = 8192;
1903 132 : move16();
1904 132 : Lecu = shl( output_frame, 1 );
1905 :
1906 132 : IF( EQ_16( output_frame, L_FRAME48k ) )
1907 : {
1908 103 : Lprot = L_PROT48k; /* 1536=(2*output_frame)*1024/1280; */
1909 103 : move16();
1910 103 : Lprot_inv = 2731; /* Q22 */
1911 103 : move16();
1912 : }
1913 29 : ELSE IF( EQ_16( output_frame, L_FRAME32k ) )
1914 : {
1915 29 : Lprot = L_PROT32k; /* 1024 */
1916 29 : move16();
1917 29 : Lprot_inv = 4096; /* Q22 */
1918 29 : move16();
1919 : }
1920 : ELSE
1921 : {
1922 0 : Lprot = 512;
1923 0 : move16();
1924 0 : Lprot_inv = 8192; /* Q22 */
1925 0 : move16();
1926 : }
1927 :
1928 : /* Correction phase of the identified peaks */
1929 132 : IF( s_or( is_trans[0], is_trans[1] ) != 0 )
1930 : {
1931 4 : *num_plocs = 0;
1932 4 : move16();
1933 : }
1934 : ELSE
1935 : {
1936 : // tmp = NS2SA(output_frame*50,PH_ECU_ALDO_OLP2_NS-PH_ECU_LOOKAHEAD_NS);
1937 128 : tmp = NS2SA_FX2( L_mult0( output_frame, 50 ), PH_ECU_ALDO_OLP2_NS );
1938 128 : move16();
1939 128 : tmp = sub( tmp, ph_ecu_lookahead );
1940 128 : tmp = add( tmp, sub( Lecu, shr( sub( Lecu, Lprot ), 1 ) ) );
1941 128 : tmp = sub( tmp, shr( output_frame, 1 ) );
1942 128 : tmp1 = L_mac0( L_mult0( tmp, Lprot_inv ), time_offs, Lprot_inv ); /* Q22 */
1943 :
1944 128 : pPlocsi = plocsi;
1945 128 : pCorrPhase = corr_phase;
1946 5637 : FOR( m = 0; m < *num_plocs; m++ )
1947 : {
1948 5509 : acc = L_shl( Mpy_32_32( *pPlocsi++, tmp1 ), 9 ); /* 16+22+9-31 = 16*/
1949 5509 : *pCorrPhase++ = acc; /* in Q16. 2*PI is not included. */
1950 5509 : move32();
1951 : }
1952 : }
1953 132 : one_peak_flag_mask = 32767 /* 1.0f in Q15 */; /* all ones mask -> keep */
1954 132 : move16();
1955 132 : IF( element_mode != EVS_MONO )
1956 : {
1957 132 : test();
1958 132 : if ( ( *num_plocs > 0 ) && ( sub( *num_plocs, 3 ) < 0 ) )
1959 : {
1960 3 : one_peak_flag_mask = noise_fac; /* all zeroes mask -> zero */
1961 3 : move16();
1962 : }
1963 132 : IF( *num_plocs == 0 )
1964 : {
1965 4 : X[0] = 0; /* reset DC if there are no peaks */
1966 4 : move16();
1967 4 : X[Lprot / 2] = 0; /* also reset fs/2 if there are no peaks */
1968 4 : move16();
1969 : }
1970 : }
1971 132 : lprotBy2Minus1 = sub( shr( Lprot, 1 ), 1 );
1972 132 : i = 1;
1973 132 : move16();
1974 132 : k = 0;
1975 132 : move16();
1976 132 : im_ind = sub( Lprot, 1 );
1977 132 : move16();
1978 132 : pReX = X + i;
1979 132 : pImX = X + im_ind;
1980 132 : pPlocs = plocs;
1981 132 : pCorrPhase = corr_phase;
1982 132 : pkLocation = *pPlocs; /* N.B. No post-increment */
1983 132 : move16();
1984 132 : pkLocation1 = *pPlocs++;
1985 132 : move16();
1986 132 : lastPeak = sub( *num_plocs, 1 );
1987 5641 : FOR( m = 0; m < *num_plocs; m++ )
1988 : {
1989 5509 : delta_corr_dn = DELTA_CORR;
1990 5509 : move16();
1991 5509 : delta_corr_up = DELTA_CORR;
1992 5509 : move16();
1993 :
1994 5509 : pkLocation_1 = pkLocation; /* plocs[m - 1] */
1995 5509 : move16();
1996 5509 : pkLocation = pkLocation1; /* plocs[m] */
1997 5509 : move16();
1998 5509 : pkLocation1 = *pPlocs++; /* plocs[m + 1] */
1999 5509 : move16();
2000 5509 : IF( m > 0 )
2001 : {
2002 5381 : delta_tmp = shr( sub( sub( pkLocation, pkLocation_1 ), 1 ), 1 );
2003 5381 : if ( LT_16( delta_tmp, DELTA_CORR ) )
2004 : {
2005 4626 : delta_corr_dn = delta_tmp;
2006 4626 : move16();
2007 : }
2008 : }
2009 :
2010 5509 : IF( LT_16( m, lastPeak ) )
2011 : {
2012 5381 : delta_tmp = shr( sub( sub( pkLocation1, pkLocation ), 1 ), 1 );
2013 5381 : if ( LT_16( delta_tmp, DELTA_CORR ) )
2014 : {
2015 4626 : delta_corr_up = delta_tmp;
2016 4626 : move16();
2017 : }
2018 : }
2019 :
2020 : /* Input Xph */
2021 5509 : segmentLen = sub( sub( pkLocation, delta_corr_dn ), i );
2022 : /* i = add(i, segmentLen); */
2023 14047 : FOR( j = 0; j < segmentLen; j++ )
2024 : {
2025 8538 : *seed = rand_phase_fx( *seed, &sin_F, &cos_F );
2026 :
2027 8538 : re = *pReX;
2028 8538 : move16();
2029 8538 : im = *pImX;
2030 8538 : move16();
2031 8538 : IF( element_mode == EVS_MONO )
2032 : {
2033 0 : tmp = sub( mult_r( re, cos_F ), mult_r( im, sin_F ) );
2034 0 : im = add( mult_r( re, sin_F ), mult_r( im, cos_F ) );
2035 : }
2036 : ELSE
2037 : {
2038 8538 : tmp = mult_r( one_peak_flag_mask, sub( mult_r( re, cos_F ), mult_r( im, sin_F ) ) );
2039 8538 : im = mult_r( one_peak_flag_mask, add( mult_r( re, sin_F ), mult_r( im, cos_F ) ) );
2040 : }
2041 8538 : IF( LT_16( alpha[k], 32766 ) )
2042 : {
2043 5180 : *seed = rand_phase_fx( *seed, &sin_F, &cos_F );
2044 5180 : move16();
2045 5180 : tmp2 = mult_r( beta[k], Xavg[k] );
2046 5180 : *pReX++ = add( mult_r( alpha[k], tmp ), mult_r( tmp2, cos_F ) );
2047 5180 : move16();
2048 5180 : *pImX-- = add( mult_r( alpha[k], im ), mult_r( tmp2, sin_F ) );
2049 5180 : move16();
2050 : }
2051 : ELSE
2052 : {
2053 3358 : *pReX++ = mult_r( mag_chg[k], tmp );
2054 3358 : move16();
2055 3358 : *pImX-- = mult_r( mag_chg[k], im );
2056 3358 : move16();
2057 : }
2058 8538 : i = add( i, 1 );
2059 8538 : if ( GE_16( i, ivas_gwlpr[k + 1] ) )
2060 : {
2061 70 : k = add( k, 1 );
2062 : }
2063 : }
2064 :
2065 5509 : e = add( pkLocation, delta_corr_up );
2066 5509 : if ( GT_16( e, lprotBy2Minus1 ) )
2067 : {
2068 0 : e = lprotBy2Minus1;
2069 0 : move16();
2070 : }
2071 :
2072 5509 : Xph = *pCorrPhase;
2073 5509 : move32();
2074 5509 : Xph_short = s_and( extract_l( L_shr( Xph, 16 - 10 ) ), 0x3ff ); /* 10 bits precision after radix point */
2075 5509 : IF( GE_16( Xph_short, 512 ) )
2076 : {
2077 2761 : sin_F = negate( sincos_t_ext_fx[Xph_short - 512] );
2078 2761 : IF( LT_16( Xph_short, 768 ) )
2079 : {
2080 1405 : cos_F = negate( sincos_t_ext_fx[Xph_short - ( 512 - 256 )] );
2081 : }
2082 : ELSE
2083 : {
2084 1356 : cos_F = sincos_t_ext_fx[-Xph_short + ( 1024 + 256 )];
2085 1356 : move16();
2086 : }
2087 : }
2088 : ELSE
2089 : {
2090 2748 : sin_F = sincos_t_ext_fx[Xph_short];
2091 2748 : move16();
2092 2748 : IF( LT_16( Xph_short, 256 ) )
2093 : {
2094 1420 : cos_F = sincos_t_ext_fx[Xph_short + 256];
2095 1420 : move16();
2096 : }
2097 : ELSE
2098 : {
2099 1328 : cos_F = negate( sincos_t_ext_fx[-Xph_short + ( 256 + 512 )] );
2100 : }
2101 : }
2102 :
2103 5509 : segmentLen = add( sub( e, i ), 1 );
2104 : /* i = add(i, segmentLen); */
2105 40815 : FOR( j = 0; j < segmentLen; j++ )
2106 : {
2107 35306 : mag_chg_local = mag_chg[k];
2108 35306 : move16();
2109 35306 : IF( ph_dith != 0 )
2110 : {
2111 25812 : Xph = *pCorrPhase; /* in Q16. 2*PI is not included. */
2112 25812 : move32();
2113 25812 : Random( seed ); /* in Q0 */
2114 25812 : acc = L_mult( *seed, ph_dith ); /* N.B. ph_dith[i] is in Q15, i.e., in between 0 and 1.0 (2*PI not included) */
2115 25812 : acc = L_shr( acc, PHASE_DITH_SCALE_SHIFT );
2116 25812 : Xph = L_add( Xph, acc ); /* in Q16. */
2117 :
2118 25812 : IF( ph_dith > 0 ) /* up to 6 dB additional att of peaks in non_transient longer bursts, (when peak phase is randomized ) */
2119 : {
2120 : /* mag_chg_local *= 0.5 + (1.0 - ph_dith[i])/2 where 0.5~= sqrt((float)pow(10.0,-6/10.0)) and ph_dith=0..1.0--> scale=1.0 ...5 */
2121 25812 : mag_chg_local = mult_r( mag_chg_local, sub( 32767, shr( ph_dith, 1 ) ) );
2122 : }
2123 25812 : Xph_short = s_and( extract_l( L_shr( Xph, 16 - 10 ) ), 0x3ff );
2124 25812 : IF( GE_16( Xph_short, 512 ) )
2125 : {
2126 12722 : sin_F = negate( sincos_t_ext_fx[Xph_short - 512] );
2127 12722 : IF( LT_16( Xph_short, 768 ) )
2128 : {
2129 6328 : cos_F = negate( sincos_t_ext_fx[Xph_short - ( 512 - 256 )] );
2130 : }
2131 : ELSE
2132 : {
2133 6394 : cos_F = sincos_t_ext_fx[-Xph_short + ( 1024 + 256 )];
2134 6394 : move16();
2135 : }
2136 : }
2137 : ELSE
2138 : {
2139 13090 : sin_F = sincos_t_ext_fx[Xph_short];
2140 13090 : move16();
2141 13090 : IF( LT_16( Xph_short, 256 ) )
2142 : {
2143 6521 : cos_F = sincos_t_ext_fx[Xph_short + 256];
2144 6521 : move16();
2145 : }
2146 : ELSE
2147 : {
2148 6569 : cos_F = negate( sincos_t_ext_fx[-Xph_short + ( 256 + 512 )] );
2149 : }
2150 : }
2151 : }
2152 :
2153 35306 : re = *pReX;
2154 35306 : move16();
2155 35306 : im = *pImX;
2156 35306 : move16();
2157 35306 : tmp = sub_sat( mult_r( re, cos_F ), mult_r( im, sin_F ) );
2158 35306 : im = add( mult_r( re, sin_F ), mult_r( im, cos_F ) );
2159 35306 : IF( LT_16( alpha[k], 32766 ) )
2160 : {
2161 26529 : alpha_local = mag_chg_local;
2162 26529 : move16();
2163 :
2164 26529 : acc = L_sub( 1073741824L, L_mult0( alpha_local, alpha_local ) );
2165 26529 : acc = Sqrt_l( acc, &expo );
2166 26529 : expo = add( 30, add( 31, expo ) );
2167 26529 : if ( EQ_16( s_and( expo, 1 ), 1 ) )
2168 : {
2169 26529 : acc = Mult_32_16( acc, 23170 ); /* 1/sqrt(2) in Q15 */
2170 : }
2171 26529 : expo = shr( expo, 1 );
2172 26529 : beta_local = mult_r( beta_mute, round_fx( L_shl( acc, sub( 31, expo ) ) ) );
2173 :
2174 26529 : IF( GE_16( k, LGW32K - 1 ) )
2175 : {
2176 10138 : beta_local = mult_r( beta_local, 3277 ); /* 0.1 in Q15 */
2177 : }
2178 16391 : ELSE IF( GE_16( k, LGW16K - 1 ) )
2179 : {
2180 8325 : beta_local = mult_r( beta_local, 16384 ); /* 0.5 in Q15 */
2181 : }
2182 :
2183 26529 : *seed = rand_phase_fx( *seed, &sin_F, &cos_F );
2184 26529 : move16();
2185 26529 : tmp2 = mult_r( beta_local, Xavg[k] );
2186 26529 : *pReX++ = add( mult_r( alpha_local, tmp ), mult_r( tmp2, cos_F ) );
2187 26529 : move16();
2188 26529 : *pImX-- = add( mult_r( alpha_local, im ), mult_r( tmp2, sin_F ) );
2189 26529 : move16();
2190 : }
2191 : ELSE
2192 : {
2193 8777 : *pReX++ = mult_r( mag_chg_local, tmp );
2194 8777 : move16();
2195 8777 : *pImX-- = mult_r( mag_chg_local, im );
2196 8777 : move16();
2197 : }
2198 :
2199 35306 : i = add( i, 1 );
2200 35306 : if ( GE_16( i, ivas_gwlpr[k + 1] ) )
2201 : {
2202 637 : k = add( k, 1 );
2203 : }
2204 : }
2205 5509 : pCorrPhase++;
2206 : }
2207 :
2208 132 : segmentLen = sub( shr( Lprot, 1 ), i );
2209 50108 : FOR( j = 0; j < segmentLen; j++ )
2210 : {
2211 49976 : *seed = rand_phase_fx( *seed, &sin_F, &cos_F );
2212 49976 : move16();
2213 :
2214 49976 : re = *pReX;
2215 49976 : move16();
2216 49976 : im = *pImX;
2217 49976 : move16();
2218 :
2219 :
2220 49976 : IF( element_mode == EVS_MONO )
2221 : {
2222 0 : tmp = sub( mult_r( re, cos_F ), mult_r( im, sin_F ) );
2223 0 : im = add( mult_r( re, sin_F ), mult_r( im, cos_F ) );
2224 : }
2225 : ELSE
2226 : {
2227 49976 : tmp = mult_r( one_peak_flag_mask, sub( mult_r( re, cos_F ), mult_r( im, sin_F ) ) );
2228 49976 : im = mult_r( one_peak_flag_mask, add( mult_r( re, sin_F ), mult_r( im, cos_F ) ) );
2229 : }
2230 49976 : IF( LT_16( alpha[k], 32766 ) )
2231 : {
2232 25049 : *seed = rand_phase_fx( *seed, &sin_F, &cos_F );
2233 25049 : move16();
2234 25049 : tmp2 = mult_r( beta[k], Xavg[k] );
2235 25049 : *pReX++ = add( mult_r( alpha[k], tmp ), mult_r( tmp2, cos_F ) );
2236 25049 : move16();
2237 25049 : *pImX-- = add( mult_r( alpha[k], im ), mult_r( tmp2, sin_F ) );
2238 25049 : move16();
2239 : }
2240 : ELSE
2241 : {
2242 24927 : *pReX++ = mult_r( mag_chg[k], tmp );
2243 24927 : move16();
2244 24927 : *pImX-- = mult_r( mag_chg[k], im );
2245 24927 : move16();
2246 : }
2247 :
2248 49976 : i = add( i, 1 );
2249 49976 : if ( GE_16( i, ivas_gwlpr[k + 1] ) )
2250 : {
2251 320 : k = add( k, 1 );
2252 : }
2253 : }
2254 132 : }
2255 :
2256 0 : static void subst_spec_fx(
2257 : const Word16 *plocs, /* i : The indices of the identified peaks Q0 */
2258 : const Word32 *plocsi, /* i : Interpolated positions of the identified peaks Q16 */
2259 : Word16 *num_plocs, /* i/o : Number of identified peaks Q0 */
2260 : const Word16 time_offs, /* i : Time offset Q0 */
2261 : Word16 *X, /* i/o : FFT spectrum */
2262 : const Word16 *mag_chg, /* i : Magnitude modification Q15 */
2263 : const Word16 ph_dith, /* i : Phase dither, 2*PI is not included. (Q15, i.e., between 0.0 and 1.0) */
2264 : const Word16 *is_trans, /* i : Transient flags (either 0 or 1) */
2265 : const Word16 output_frame, /* i : Frame length Q0 */
2266 : Word16 *seed, /* i/o : Random seed */
2267 : const Word16 *alpha, /* i : Magnitude modification factors for fade to average Q15 */
2268 : const Word16 *beta, /* i : Magnitude modification factors for fade to average Q15 */
2269 : Word16 beta_mute, /* i : Factor for long-term mute Q15 */
2270 : const Word16 *Xavg /* i : Frequency group averages to fade to Q0 */
2271 : )
2272 : {
2273 : Word16 Xph_short;
2274 : Word32 corr_phase[MAX_PLOCS], Xph;
2275 : Word32 *pCorrPhase;
2276 : Word16 cos_F, sin_F, tmp;
2277 : Word16 Lprot, m, i, e, im_ind, delta_corr_up, delta_corr_dn, delta_tmp;
2278 : UWord16 lsb;
2279 : Word16 j, re, im, *pReX, *pImX, lastPeak, lprotBy2Minus1, segmentLen;
2280 : Word16 pkLocation_1, pkLocation, pkLocation1;
2281 : const Word16 *pPlocs;
2282 : const Word32 *pPlocsi;
2283 : Word32 acc;
2284 : Word16 Lecu;
2285 : Word16 Lprot_inv;
2286 : Word16 k;
2287 : Word16 tmp2;
2288 : Word16 alpha_local;
2289 : Word16 beta_local;
2290 : Word16 expo;
2291 : Word16 mag_chg_local; /*for peak attenuation in burst */
2292 :
2293 0 : Lprot = 512;
2294 0 : move16();
2295 0 : Lprot_inv = 8192;
2296 0 : move16();
2297 0 : Lecu = shl( output_frame, 1 );
2298 :
2299 0 : IF( EQ_16( output_frame, L_FRAME48k ) )
2300 : {
2301 0 : Lprot = L_PROT48k; /* 1536=(2*output_frame)*1024/1280; */
2302 0 : move16();
2303 0 : Lprot_inv = 2731; /* Q22 */
2304 0 : move16();
2305 : }
2306 0 : ELSE IF( EQ_16( output_frame, L_FRAME32k ) )
2307 : {
2308 0 : Lprot = L_PROT32k; /* 1024 */
2309 0 : move16();
2310 0 : Lprot_inv = 4096; /* Q22 */
2311 0 : move16();
2312 : }
2313 : ELSE
2314 : {
2315 0 : Lprot = 512;
2316 0 : move16();
2317 0 : Lprot_inv = 8192; /* Q22 */
2318 0 : move16();
2319 : }
2320 :
2321 : /* Correction phase of the identified peaks */
2322 0 : IF( s_or( is_trans[0], is_trans[1] ) != 0 )
2323 : {
2324 0 : *num_plocs = 0;
2325 0 : move16();
2326 : }
2327 : ELSE
2328 : {
2329 0 : tmp = NS2SA_FX2( L_mult0( output_frame, 50 ), PH_ECU_ALDO_OLP2_NS - PH_ECU_LOOKAHEAD_NS );
2330 0 : move16();
2331 0 : tmp = add( tmp, sub( Lecu, shr( sub( Lecu, Lprot ), 1 ) ) );
2332 0 : tmp = sub( tmp, shr( output_frame, 1 ) );
2333 : #ifdef FIX_1179_USAN_PHASEECU
2334 0 : tmp = add_sat( tmp, time_offs );
2335 : #else
2336 : tmp = add( tmp, time_offs );
2337 : #endif
2338 0 : tmp = round_fx( L_shl( L_mult0( tmp, Lprot_inv ), 4 ) ); /* 0+22+4-16=10 */
2339 :
2340 0 : pPlocsi = plocsi;
2341 0 : pCorrPhase = corr_phase;
2342 0 : FOR( m = 0; m < *num_plocs; m++ )
2343 : {
2344 0 : Mpy_32_16_ss( *pPlocsi++, tmp, &acc, &lsb ); /* plocsi[] in Q16, tmp in Q10 and tmp does not include 2*PI. */
2345 0 : acc = L_add( L_shl( acc, 5 ), lshr( lsb, 11 ) );
2346 0 : *pCorrPhase++ = acc; /* in Q16. 2*PI is not included. */
2347 0 : move32();
2348 : }
2349 : }
2350 0 : lprotBy2Minus1 = sub( shr( Lprot, 1 ), 1 );
2351 0 : i = 1;
2352 0 : move16();
2353 0 : k = 0;
2354 0 : move16();
2355 0 : im_ind = sub( Lprot, 1 );
2356 0 : move16();
2357 0 : pReX = X + i;
2358 0 : pImX = X + im_ind;
2359 0 : pPlocs = plocs;
2360 0 : pCorrPhase = corr_phase;
2361 0 : pkLocation = *pPlocs; /* N.B. No post-increment */
2362 0 : move16();
2363 0 : pkLocation1 = *pPlocs++;
2364 0 : move16();
2365 0 : lastPeak = sub( *num_plocs, 1 );
2366 0 : FOR( m = 0; m < *num_plocs; m++ )
2367 : {
2368 0 : delta_corr_dn = DELTA_CORR;
2369 0 : move16();
2370 0 : delta_corr_up = DELTA_CORR;
2371 0 : move16();
2372 :
2373 0 : pkLocation_1 = pkLocation; /* plocs[m - 1] */
2374 0 : move16();
2375 0 : pkLocation = pkLocation1; /* plocs[m] */
2376 0 : move16();
2377 0 : pkLocation1 = *pPlocs++; /* plocs[m + 1] */
2378 0 : move16();
2379 0 : IF( m > 0 )
2380 : {
2381 0 : delta_tmp = shr( sub( sub( pkLocation, pkLocation_1 ), 1 ), 1 );
2382 0 : if ( LT_16( delta_tmp, DELTA_CORR ) )
2383 : {
2384 0 : delta_corr_dn = delta_tmp;
2385 0 : move16();
2386 : }
2387 : }
2388 :
2389 0 : IF( LT_16( m, lastPeak ) )
2390 : {
2391 0 : delta_tmp = shr( sub( sub( pkLocation1, pkLocation ), 1 ), 1 );
2392 0 : if ( LT_16( delta_tmp, DELTA_CORR ) )
2393 : {
2394 0 : delta_corr_up = delta_tmp;
2395 0 : move16();
2396 : }
2397 : }
2398 :
2399 : /* Input Xph */
2400 0 : segmentLen = sub( sub( pkLocation, delta_corr_dn ), i );
2401 : /* i = add(i, segmentLen); */
2402 0 : FOR( j = 0; j < segmentLen; j++ )
2403 : {
2404 0 : *seed = rand_phase_fx( *seed, &sin_F, &cos_F );
2405 :
2406 0 : re = *pReX;
2407 0 : move16();
2408 0 : im = *pImX;
2409 0 : move16();
2410 : {
2411 0 : tmp = sub( mult_r( re, cos_F ), mult_r( im, sin_F ) );
2412 0 : im = add( mult_r( re, sin_F ), mult_r( im, cos_F ) );
2413 : }
2414 0 : IF( LT_16( alpha[k], 32766 ) )
2415 : {
2416 0 : *seed = rand_phase_fx( *seed, &sin_F, &cos_F );
2417 0 : move16();
2418 0 : tmp2 = mult_r( beta[k], Xavg[k] );
2419 0 : *pReX++ = add( mult_r( alpha[k], tmp ), mult_r( tmp2, cos_F ) );
2420 0 : move16();
2421 0 : *pImX-- = add( mult_r( alpha[k], im ), mult_r( tmp2, sin_F ) );
2422 0 : move16();
2423 : }
2424 : ELSE
2425 : {
2426 0 : *pReX++ = mult_r( mag_chg[k], tmp );
2427 0 : move16();
2428 0 : *pImX-- = mult_r( mag_chg[k], im );
2429 0 : move16();
2430 : }
2431 0 : i = add( i, 1 );
2432 0 : if ( GE_16( i, ivas_gwlpr[k + 1] ) )
2433 : {
2434 0 : k = add( k, 1 );
2435 : }
2436 : }
2437 :
2438 0 : e = add( pkLocation, delta_corr_up );
2439 0 : if ( GT_16( e, lprotBy2Minus1 ) )
2440 : {
2441 0 : e = lprotBy2Minus1;
2442 0 : move16();
2443 : }
2444 :
2445 0 : Xph = *pCorrPhase;
2446 0 : move32();
2447 0 : Xph_short = s_and( extract_l( L_shr( Xph, 16 - 10 ) ), 0x3ff ); /* 10 bits precision after radix point */
2448 0 : IF( GE_16( Xph_short, 512 ) )
2449 : {
2450 0 : sin_F = negate( sincos_t_ext_fx[Xph_short - 512] );
2451 0 : IF( LT_16( Xph_short, 768 ) )
2452 : {
2453 0 : cos_F = negate( sincos_t_ext_fx[Xph_short - ( 512 - 256 )] );
2454 : }
2455 : ELSE
2456 : {
2457 0 : cos_F = sincos_t_ext_fx[-Xph_short + ( 1024 + 256 )];
2458 0 : move16();
2459 : }
2460 : }
2461 : ELSE
2462 : {
2463 0 : sin_F = sincos_t_ext_fx[Xph_short];
2464 0 : move16();
2465 0 : IF( LT_16( Xph_short, 256 ) )
2466 : {
2467 0 : cos_F = sincos_t_ext_fx[Xph_short + 256];
2468 0 : move16();
2469 : }
2470 : ELSE
2471 : {
2472 0 : cos_F = negate( sincos_t_ext_fx[-Xph_short + ( 256 + 512 )] );
2473 : }
2474 : }
2475 :
2476 0 : segmentLen = add( sub( e, i ), 1 );
2477 : /* i = add(i, segmentLen); */
2478 0 : FOR( j = 0; j < segmentLen; j++ )
2479 : {
2480 0 : mag_chg_local = mag_chg[k];
2481 0 : move16();
2482 0 : IF( ph_dith != 0 )
2483 : {
2484 0 : Xph = *pCorrPhase; /* in Q16. 2*PI is not included. */
2485 0 : move32();
2486 0 : Random( seed ); /* in Q0 */
2487 0 : acc = L_mult( *seed, ph_dith ); /* N.B. ph_dith[i] is in Q15, i.e., in between 0 and 1.0 (2*PI not included) */
2488 0 : acc = L_shr( acc, PHASE_DITH_SCALE_SHIFT );
2489 0 : Xph = L_add( Xph, acc ); /* in Q16. */
2490 :
2491 0 : IF( ph_dith > 0 ) /* up to 6 dB additional att of peaks in non_transient longer bursts, (when peak phase is randomized ) */
2492 : {
2493 : /* mag_chg_local *= 0.5 + (1.0 - ph_dith[i])/2 where 0.5~= sqrt((float)pow(10.0,-6/10.0)) and ph_dith=0..1.0--> scale=1.0 ...5 */
2494 0 : mag_chg_local = mult_r( mag_chg_local, sub( 32767, shr( ph_dith, 1 ) ) );
2495 : }
2496 0 : Xph_short = s_and( extract_l( L_shr( Xph, 16 - 10 ) ), 0x3ff );
2497 0 : IF( GE_16( Xph_short, 512 ) )
2498 : {
2499 0 : sin_F = negate( sincos_t_ext_fx[Xph_short - 512] );
2500 0 : IF( LT_16( Xph_short, 768 ) )
2501 : {
2502 0 : cos_F = negate( sincos_t_ext_fx[Xph_short - ( 512 - 256 )] );
2503 : }
2504 : ELSE
2505 : {
2506 0 : cos_F = sincos_t_ext_fx[-Xph_short + ( 1024 + 256 )];
2507 0 : move16();
2508 : }
2509 : }
2510 : ELSE
2511 : {
2512 0 : sin_F = sincos_t_ext_fx[Xph_short];
2513 0 : move16();
2514 0 : IF( LT_16( Xph_short, 256 ) )
2515 : {
2516 0 : cos_F = sincos_t_ext_fx[Xph_short + 256];
2517 0 : move16();
2518 : }
2519 : ELSE
2520 : {
2521 0 : cos_F = negate( sincos_t_ext_fx[-Xph_short + ( 256 + 512 )] );
2522 : }
2523 : }
2524 : }
2525 :
2526 0 : re = *pReX;
2527 0 : move16();
2528 0 : im = *pImX;
2529 0 : move16();
2530 : {
2531 0 : tmp = sub_sat( mult_r( re, cos_F ), mult_r( im, sin_F ) );
2532 0 : im = add_sat( mult_r( re, sin_F ), mult_r( im, cos_F ) );
2533 : }
2534 0 : IF( LT_16( alpha[k], 32766 ) )
2535 : {
2536 0 : alpha_local = mag_chg_local;
2537 0 : move16();
2538 :
2539 0 : acc = L_sub( 1073741824L, L_mult0( alpha_local, alpha_local ) );
2540 0 : acc = Sqrt_l( acc, &expo );
2541 0 : expo = add( 30, add( 31, expo ) );
2542 0 : if ( EQ_16( s_and( expo, 1 ), 1 ) )
2543 : {
2544 0 : acc = Mult_32_16( acc, 23170 ); /* 1/sqrt(2) in Q15 */
2545 : }
2546 0 : expo = shr( expo, 1 );
2547 0 : beta_local = mult_r( beta_mute, round_fx( L_shl( acc, sub( 31, expo ) ) ) );
2548 :
2549 0 : IF( GE_16( k, LGW32K - 1 ) )
2550 : {
2551 0 : beta_local = mult_r( beta_local, 3277 ); /* 0.1 in Q15 */
2552 : }
2553 0 : ELSE IF( GE_16( k, LGW16K - 1 ) )
2554 : {
2555 0 : beta_local = mult_r( beta_local, 16384 ); /* 0.5 in Q15 */
2556 : }
2557 :
2558 0 : *seed = rand_phase_fx( *seed, &sin_F, &cos_F );
2559 0 : move16();
2560 0 : tmp2 = mult_r( beta_local, Xavg[k] );
2561 0 : *pReX++ = add( mult_r( alpha_local, tmp ), mult_r( tmp2, cos_F ) );
2562 0 : move16();
2563 0 : *pImX-- = add( mult_r( alpha_local, im ), mult_r( tmp2, sin_F ) );
2564 0 : move16();
2565 : }
2566 : ELSE
2567 : {
2568 0 : *pReX++ = mult_r( mag_chg_local, tmp );
2569 0 : move16();
2570 0 : *pImX-- = mult_r( mag_chg_local, im );
2571 0 : move16();
2572 : }
2573 :
2574 0 : i = add( i, 1 );
2575 0 : if ( GE_16( i, ivas_gwlpr[k + 1] ) )
2576 : {
2577 0 : k = add( k, 1 );
2578 : }
2579 : }
2580 0 : pCorrPhase++;
2581 : }
2582 :
2583 0 : segmentLen = sub( shr( Lprot, 1 ), i );
2584 0 : FOR( j = 0; j < segmentLen; j++ )
2585 : {
2586 0 : *seed = rand_phase_fx( *seed, &sin_F, &cos_F );
2587 0 : move16();
2588 :
2589 0 : re = *pReX;
2590 0 : move16();
2591 0 : im = *pImX;
2592 0 : move16();
2593 0 : tmp = sub( mult_r( re, cos_F ), mult_r( im, sin_F ) );
2594 0 : im = add( mult_r( re, sin_F ), mult_r( im, cos_F ) );
2595 0 : IF( LT_16( alpha[k], 32766 ) )
2596 : {
2597 0 : *seed = rand_phase_fx( *seed, &sin_F, &cos_F );
2598 0 : move16();
2599 0 : tmp2 = mult_r( beta[k], Xavg[k] );
2600 0 : *pReX++ = add( mult_r( alpha[k], tmp ), mult_r( tmp2, cos_F ) );
2601 0 : move16();
2602 0 : *pImX-- = add( mult_r( alpha[k], im ), mult_r( tmp2, sin_F ) );
2603 0 : move16();
2604 : }
2605 : ELSE
2606 : {
2607 0 : *pReX++ = mult_r( mag_chg[k], tmp );
2608 0 : move16();
2609 0 : *pImX-- = mult_r( mag_chg[k], im );
2610 0 : move16();
2611 : }
2612 :
2613 0 : i = add( i, 1 );
2614 0 : if ( GE_16( i, ivas_gwlpr[k + 1] ) )
2615 : {
2616 0 : k = add( k, 1 );
2617 : }
2618 : }
2619 0 : }
2620 :
2621 : /*--------------------------------------------------------------------------
2622 : * rec_wtda()
2623 : *
2624 : * Windowing and TDA of reconstructed frame
2625 : *--------------------------------------------------------------------------*/
2626 :
2627 132 : static void ivas_rec_wtda_fx(
2628 : Word16 *X, /* i : FFT spectrum */
2629 : Word32 *ecu_rec, /* o : Reconstructed frame in tda domain */
2630 : const Word16 output_frame, /* i : Frame length */
2631 : const Word16 Lprot, /* i : Prototype frame length */
2632 : const Word16 old_dec[270], /* i : end of last decoded for OLA before tda and itda */
2633 : const Word16 element_mode, /* i : IVAS element mode */
2634 : const Word16 *num_p, /* i : Number of peaks Q0 */
2635 : const Word16 *plocs /* i : Peak locations Q0 */
2636 : )
2637 : {
2638 : Word16 timesh;
2639 : Word16 Qin;
2640 : Word16 xf_len;
2641 : Word16 i, idx;
2642 : Word16 *p_ecu;
2643 : Word16 g;
2644 : Word16 tbl_delta;
2645 : Word16 xsubst_[2 * L_FRAME48k];
2646 : const Word16 *w_hamm;
2647 : Word16 *pX_start, *pX_end;
2648 : Word16 tmp, tmp_e;
2649 : Word16 hamm_len2;
2650 : Word16 *pNew;
2651 : const Word16 *pOldW, *pNewW;
2652 : Word16 xfwin[NS2SA( L_FRAME48k * FRAMES_PER_SEC, N_ZERO_MDCT_NS - ( 2 * FRAME_SIZE_NS - L_PROT_NS ) / 2 )];
2653 : const Word16 *pOld;
2654 : Word16 copy_len;
2655 : Word16 ola_len;
2656 :
2657 132 : copy_len = NS2SA_FX2( L_mult0( output_frame, FRAMES_PER_SEC ), ( 2 * FRAME_SIZE_NS - L_PROT_NS ) / 2 ); /* prototype fill on each side of xsubst to fill MDCT Frame */
2658 132 : move16();
2659 132 : ola_len = NS2SA_FX2( L_mult0( output_frame, FRAMES_PER_SEC ), N_ZERO_MDCT_NS - ( 2 * FRAME_SIZE_NS - L_PROT_NS ) / 2 ); /* remaining lengt of LA_ZEROS to overlap add decoded with xsubst */
2660 132 : move16();
2661 :
2662 132 : xf_len = 26;
2663 132 : move16();
2664 132 : tbl_delta = 10082; /* Q12 */
2665 132 : move16();
2666 132 : IF( EQ_16( output_frame, L_FRAME48k ) )
2667 : {
2668 103 : w_hamm = w_hamm_sana48k_2_fx;
2669 103 : hamm_len2 = L_PROT_HAMM_LEN2_48k;
2670 103 : move16();
2671 103 : xf_len = 78;
2672 103 : move16();
2673 103 : tbl_delta = 3361; /* Q12 */
2674 103 : move16();
2675 : }
2676 29 : ELSE IF( EQ_16( output_frame, L_FRAME32k ) )
2677 : {
2678 29 : w_hamm = w_hamm_sana32k_2_fx;
2679 29 : hamm_len2 = L_PROT_HAMM_LEN2_32k;
2680 29 : move16();
2681 29 : xf_len = 52;
2682 29 : move16();
2683 29 : tbl_delta = 5041; /* Q12 */
2684 29 : move16();
2685 : }
2686 : ELSE
2687 : {
2688 0 : w_hamm = w_hamm_sana16k_2_fx;
2689 0 : hamm_len2 = L_PROT_HAMM_LEN2_16k;
2690 0 : move16();
2691 : }
2692 :
2693 132 : test();
2694 132 : test();
2695 132 : IF( element_mode != EVS_MONO && *num_p > 0 && GT_16( plocs[0], 3 ) )
2696 : {
2697 : /* Perform inverse windowing of hammrect */
2698 26 : pX_start = X;
2699 26 : pX_end = X + sub( Lprot, 1 );
2700 6074 : FOR( i = 0; i < hamm_len2; i++ )
2701 : {
2702 6048 : tmp_e = 0;
2703 6048 : tmp = BASOP_Util_Divide1616_Scale( ONE_IN_Q14, *w_hamm, &tmp_e );
2704 6048 : tmp = shl( tmp, 1 );
2705 6048 : tmp = shr( tmp, sub( 4, tmp_e ) ); // Q11
2706 6048 : *pX_start = shl_sat( mult_r( *pX_start, tmp ), 4 ); // Qin
2707 6048 : move16();
2708 6048 : *pX_end = shl_sat( mult_r( *pX_end, tmp ), 4 ); // Qin
2709 6048 : move16();
2710 6048 : pX_start++;
2711 6048 : pX_end--;
2712 6048 : w_hamm++;
2713 : }
2714 : }
2715 :
2716 : /* extract reconstructed frame with aldo window */
2717 132 : timesh = sub( NS2SA_FX2( L_mult0( output_frame, FRAMES_PER_SEC ), N_ZERO_MDCT_NS ), shr( sub( shl( output_frame, 1 ), Lprot ), 1 ) );
2718 :
2719 132 : set16_fx( xsubst_, 0, add( sub( shl( output_frame, 1 ), Lprot ), timesh ) );
2720 132 : Copy( X, xsubst_ + add( sub( shl( output_frame, 1 ), Lprot ), timesh ), sub( Lprot, timesh ) );
2721 :
2722 : /* Copy and OLA look ahead zero part of MDCT window from decoded signal */
2723 132 : IF( element_mode != EVS_MONO )
2724 : {
2725 132 : Copy( old_dec, xsubst_ + NS2SA_FX2( L_mult0( output_frame, FRAMES_PER_SEC ), N_ZERO_MDCT_NS ), copy_len ); /* also need to scale to Q0 ?? */
2726 132 : pOld = old_dec + copy_len;
2727 132 : pNew = xsubst_ + add( copy_len, NS2SA_FX2( L_mult0( output_frame, FRAMES_PER_SEC ), N_ZERO_MDCT_NS ) );
2728 132 : tmp = div_s( 1, shl( ola_len, 1 ) ); // Q15
2729 132 : tmp = round_fx( L_shl( L_mult( tmp, EVS_PI_FX ), 2 ) ); // Q15
2730 132 : sinq_fx( tmp, 0, ola_len, xfwin );
2731 132 : v_mult16_fixed( xfwin, xfwin, xfwin, ola_len ); /* xfwin = sin^2 of 0..pi/4 */
2732 132 : pOldW = xfwin + sub( ola_len, 1 );
2733 132 : pNewW = xfwin;
2734 9674 : FOR( i = 0; i < ola_len; i++ )
2735 : {
2736 9542 : *pNew = add( mult_r( *pOld, *pOldW ), mult_r( *pNew, *pNewW ) );
2737 9542 : move16();
2738 9542 : pOld += 1;
2739 9542 : pNew += 1;
2740 9542 : pOldW -= 1;
2741 9542 : pNewW += 1;
2742 : }
2743 : }
2744 : ELSE
2745 : {
2746 : /* Smoothen onset of ECU frame */
2747 0 : p_ecu = xsubst_ + add( sub( shl( output_frame, 1 ), Lprot ), timesh );
2748 0 : FOR( i = 0; i < xf_len; ( i++, p_ecu++ ) )
2749 : {
2750 0 : idx = extract_l( L_shr( L_mult0( i, tbl_delta ), 12 ) ); // Q0
2751 0 : g = sincos_t_fx[idx]; // Q15
2752 0 : move16();
2753 0 : g = mult( g, g ); // Q15
2754 0 : *p_ecu = mult( g, ( *p_ecu ) );
2755 0 : move16();
2756 0 : p_ecu++;
2757 : }
2758 : }
2759 :
2760 : /* Apply TDA and windowing to ECU frame */
2761 132 : Qin = 0;
2762 132 : move16();
2763 132 : wtda_fx( xsubst_ + output_frame, &Qin, ecu_rec, NULL, 0, ALDO_WINDOW, ALDO_WINDOW, /* window overlap of current frame (0: full, 2: none, or 3: half) */
2764 : output_frame );
2765 :
2766 132 : return;
2767 : }
2768 :
2769 0 : static void rec_wtda_fx(
2770 : Word16 *X, /* i : FFT spectrum */
2771 : Word32 *ecu_rec, /* o : Reconstructed frame in tda domain */
2772 : const Word16 output_frame, /* i : Frame length */
2773 : const Word16 Lprot, /* i : Prototype frame length */
2774 : const Word32 fs )
2775 : {
2776 : Word16 l, Lprot2, timesh;
2777 : Word16 rec_buf[3 * L_FRAME48k];
2778 : Word16 *xsubst_, *out_ptr;
2779 : Word16 Qin;
2780 : Word16 xf_len;
2781 : Word16 i, idx;
2782 : Word16 *p_ecu;
2783 : Word16 g;
2784 : Word16 tbl_delta;
2785 :
2786 : // PMTE()
2787 0 : xsubst_ = rec_buf + output_frame;
2788 0 : Lprot2 = shr( Lprot, 1 );
2789 :
2790 : /* Initialize to WB constants */
2791 0 : xf_len = 26;
2792 0 : move16();
2793 0 : tbl_delta = 10082; /* Q12 */
2794 0 : move16();
2795 0 : IF( EQ_16( output_frame, L_FRAME48k ) )
2796 : {
2797 0 : xf_len = 78;
2798 0 : move16();
2799 0 : tbl_delta = 3361; /* Q12 */
2800 0 : move16();
2801 : }
2802 0 : ELSE IF( EQ_16( output_frame, L_FRAME32k ) )
2803 : {
2804 0 : xf_len = 52;
2805 0 : move16();
2806 0 : tbl_delta = 5041; /* Q12 */
2807 0 : move16();
2808 : }
2809 :
2810 : /* extract reconstructed frame with aldo window */
2811 0 : l = sub( output_frame, Lprot2 );
2812 0 : set16_fx( xsubst_, 0, l );
2813 0 : Copy( X, xsubst_ + l, Lprot );
2814 0 : set16_fx( xsubst_ + add( output_frame, Lprot2 ), 0, l );
2815 :
2816 : /* Smoothen onset of ECU frame */
2817 0 : p_ecu = xsubst_ + sub( output_frame, Lprot2 );
2818 0 : FOR( i = 0; i < xf_len; i++ )
2819 : {
2820 0 : idx = extract_l( L_shr( L_mult0( i, tbl_delta ), 12 ) );
2821 0 : g = sincos_t_fx[idx];
2822 0 : move16();
2823 0 : g = mult( g, g );
2824 0 : *p_ecu = mult( g, ( *p_ecu ) );
2825 0 : move16();
2826 0 : p_ecu++;
2827 : }
2828 :
2829 0 : timesh = NS2SA_FX2( fs, 10000000L - PH_ECU_ALDO_OLP2_NS );
2830 0 : move16();
2831 :
2832 0 : set16_fx( rec_buf, 0, output_frame );
2833 0 : Qin = 0;
2834 0 : move16();
2835 0 : out_ptr = rec_buf + sub( shl( output_frame, 1 ), timesh );
2836 0 : wtda_fx( out_ptr, &Qin, ecu_rec, NULL, 0, ALDO_WINDOW, ALDO_WINDOW, /* window overlap of current frame (0: full, 2: none, or 3: half) */
2837 : output_frame );
2838 0 : return;
2839 : }
2840 :
2841 : /*--------------------------------------------------------------------------
2842 : * rec_frame_fx()
2843 : *
2844 : * Frame reconstruction
2845 : *--------------------------------------------------------------------------*/
2846 :
2847 132 : static void ivas_rec_frame_fx(
2848 : Word16 *X, /* i : FFT spectrum */
2849 : Word32 *ecu_rec, /* o : Reconstructed frame in tda domain */
2850 : const Word16 output_frame, /* i : Frame length */
2851 : const Word16 Q,
2852 : const Word16 *old_dec, /* i : end of last decoded for OLA before tda and itda */
2853 : const Word16 element_mode, /* i : IVAS element mode */
2854 : const Word16 *num_p, /* i : Number of peaks */
2855 : const Word16 *plocs /* i : Peak locations */
2856 : )
2857 : {
2858 : const Word16 *pFftTbl;
2859 : Word16 Lprot, lprotLog2Minus1;
2860 :
2861 : /* Initialize to WB constants */
2862 132 : Lprot = 512;
2863 132 : move16();
2864 132 : lprotLog2Minus1 = 9 - 1;
2865 132 : move16();
2866 132 : pFftTbl = FFT_W256; /* Table for 512-point real input FFT */
2867 132 : IF( EQ_16( output_frame, L_FRAME48k ) )
2868 : {
2869 103 : Lprot = L_PROT48k; /* 1536 = (2*output_frame)*1024/1280 */
2870 103 : move16();
2871 : }
2872 29 : ELSE IF( EQ_16( output_frame, L_FRAME32k ) )
2873 : {
2874 29 : Lprot = L_PROT32k; /* 1024 */
2875 29 : move16();
2876 29 : lprotLog2Minus1 = 10 - 1;
2877 29 : move16();
2878 29 : pFftTbl = FFT_W512; /* Table for 1024-point real input FFT */
2879 : }
2880 :
2881 : /* extend spectrum and IDFT */
2882 132 : IF( EQ_16( output_frame, L_FRAME48k ) )
2883 : {
2884 103 : ifft3_fx( X, X, Lprot );
2885 : }
2886 : ELSE
2887 : {
2888 29 : r_fft_fx_lc( pFftTbl, Lprot, shr( Lprot, 1 ), lprotLog2Minus1, X, X, 0 ); /* Inverse FFT */
2889 : }
2890 132 : Scale_sig( X, Lprot, -Q );
2891 :
2892 132 : ivas_rec_wtda_fx( X, ecu_rec, output_frame, Lprot, old_dec, element_mode, num_p, plocs );
2893 :
2894 132 : return;
2895 : }
2896 :
2897 0 : static void rec_frame_fx(
2898 : Word16 *X, /* i : FFT spectrum */
2899 : Word32 *ecu_rec, /* o : Reconstructed frame in tda domain */
2900 : const Word16 output_frame, /* i : Frame length */
2901 : const Word16 Q )
2902 : {
2903 : const Word16 *pFftTbl;
2904 : Word16 Lprot, lprotLog2Minus1;
2905 : Word32 fs;
2906 :
2907 0 : fs = L_mult0( output_frame, 50 );
2908 :
2909 : /* Initialize to WB constants */
2910 0 : Lprot = 512;
2911 0 : move16();
2912 0 : lprotLog2Minus1 = 9 - 1;
2913 0 : move16();
2914 0 : pFftTbl = FFT_W256; /* Table for 512-point real input FFT */
2915 0 : IF( EQ_16( output_frame, L_FRAME48k ) )
2916 : {
2917 0 : Lprot = L_PROT48k; /* 1536 = (2*output_frame)*1024/1280 */
2918 0 : move16();
2919 : }
2920 0 : ELSE IF( EQ_16( output_frame, L_FRAME32k ) )
2921 : {
2922 0 : Lprot = L_PROT32k; /* 1024 */
2923 0 : move16();
2924 0 : lprotLog2Minus1 = 10 - 1;
2925 0 : move16();
2926 0 : pFftTbl = FFT_W512; /* Table for 1024-point real input FFT */
2927 : }
2928 :
2929 : /* extend spectrum and IDFT */
2930 0 : IF( EQ_16( output_frame, L_FRAME48k ) )
2931 : {
2932 0 : ifft3_fx( X, X, Lprot );
2933 : }
2934 : ELSE
2935 : {
2936 0 : r_fft_fx_lc( pFftTbl, Lprot, shr( Lprot, 1 ), lprotLog2Minus1, X, X, 0 ); /* Inverse FFT */
2937 : }
2938 0 : Scale_sig( X, Lprot, -Q );
2939 :
2940 0 : rec_wtda_fx( X, ecu_rec, output_frame, Lprot, fs );
2941 :
2942 0 : return;
2943 : }
2944 :
2945 0 : static Word32 mult_32_32_q( const Word32 a, const Word32 b, const Word16 q )
2946 : {
2947 : Word32 hi;
2948 : UWord32 lo;
2949 0 : Mpy_32_32_ss( a, b, &hi, &lo );
2950 :
2951 0 : return L_or( L_shl_sat( hi, sub( 32 - 1, q ) ), L_lshr( (Word32) lo, add( q, 1 ) ) );
2952 : }
2953 :
2954 133 : static void fir_dwn_fx(
2955 : const Word16 x[], /* i : input vector Q(x_Q) */
2956 : const Word16 h[], /* i : impulse response of the FIR filter Q(h_Q) */
2957 : const Word16 h_Q, /* H's Q */
2958 : Word16 y[], /* o : output vector (result of filtering) Q~ */
2959 : const Word16 L, /* i : input vector size */
2960 : const Word16 K, /* i : order of the FIR filter (K+1 coefs.) */
2961 : const Word16 decimation /* i : decimation */
2962 : )
2963 : {
2964 : Word32 s;
2965 : Word16 i, j;
2966 : const Word16 *ptr_h, *ptr_x;
2967 : Word16 *ptr_y;
2968 : Word16 Kdiv2;
2969 : Word16 centering;
2970 : Word16 tmp;
2971 :
2972 133 : centering = sub( 16, h_Q );
2973 133 : Kdiv2 = shr( K, 1 );
2974 :
2975 133 : ptr_y = y;
2976 : /* do the filtering */
2977 798 : FOR( i = Kdiv2; i < K; i += decimation )
2978 : {
2979 665 : s = L_deposit_l( 0 );
2980 665 : ptr_h = h + 1;
2981 665 : ptr_x = x + sub( i, 1 );
2982 :
2983 26495 : FOR( j = 1; j <= i; j++ )
2984 : {
2985 25830 : s = L_mac0_sat( s, *ptr_h++, *ptr_x-- ); // Q(h_Q) + Q(x_q)
2986 : }
2987 :
2988 665 : *ptr_y++ = extract_h( L_shl_sat( s, centering ) );
2989 665 : move16();
2990 : }
2991 41363 : FOR( i = K; i < L; i += decimation )
2992 : {
2993 41230 : s = L_deposit_l( 0 );
2994 41230 : ptr_h = h + 1;
2995 41230 : ptr_x = x + sub( i, 1 );
2996 41230 : move16();
2997 :
2998 2329030 : FOR( j = 1; j <= K; j++ )
2999 : {
3000 2287800 : s = L_mac0_sat( s, *ptr_h++, *ptr_x-- ); // Q(h_Q) + Q(x_q)
3001 : }
3002 :
3003 41230 : *ptr_y++ = extract_h( L_shl_sat( s, centering ) );
3004 41230 : move16();
3005 : }
3006 133 : tmp = add( L, Kdiv2 );
3007 798 : FOR( i = i; i < tmp; i += decimation )
3008 : {
3009 665 : s = L_deposit_l( 0 );
3010 665 : ptr_h = h + add( sub( i, L ), 1 );
3011 665 : move16();
3012 665 : ptr_x = x + sub( L, 1 );
3013 665 : move16();
3014 :
3015 30185 : FOR( j = i - L + 1; j <= K; j++ )
3016 : {
3017 29520 : s = L_mac0_sat( s, *ptr_h++, *ptr_x-- );
3018 : }
3019 :
3020 665 : *ptr_y++ = extract_h( L_shl_sat( s, centering ) );
3021 665 : move16();
3022 : }
3023 :
3024 133 : return;
3025 : }
3026 :
3027 : /*--------------------------------------------------------------------------
3028 : * fec_ecu_pitch()
3029 : *
3030 : * Pitch/correlation analysis and adaptive analysis frame length calculation
3031 : *--------------------------------------------------------------------------*/
3032 :
3033 133 : static void fec_ecu_pitch_ivas_fx(
3034 : const Word16 *prevsynth_fx, /*Q15 16 */
3035 : Word16 *prevsynth_LP_fx, /* Q15 16 */
3036 : const Word16 L,
3037 : Word16 *N,
3038 : Word16 *min_corr_fx, /* Q15 16 */
3039 : Word16 *decimatefator,
3040 : const Word16 HqVoicing )
3041 : {
3042 :
3043 : Word16 i, filt_size;
3044 : Word16 QAsr, Ryy, cb_start, tmpQLP;
3045 : Word32 Ryytmp;
3046 : Word32 accA, accB, accBisqrt, accC, accCisqrt;
3047 : Word16 delay_ind, k;
3048 : const Word16 *Asr_LP_fx;
3049 : Word16 *ptr_LP, *ptr_LP2, *ptr_LP3, *ptr_LP4;
3050 : Word16 cb_end;
3051 : Word16 Lmul2, Lon20mul6, Lon20mul28, Lon20mul33, Lon20mul34;
3052 :
3053 :
3054 133 : SWITCH( L )
3055 : {
3056 103 : case L_FRAME48k:
3057 103 : *decimatefator = 6;
3058 103 : move16();
3059 103 : filt_size = 60;
3060 103 : move16();
3061 103 : Asr_LP_fx = Asr_LP48_fx;
3062 103 : QAsr = 17;
3063 103 : move16();
3064 103 : Lon20mul6 = 48;
3065 103 : move16();
3066 103 : Lon20mul28 = 224;
3067 103 : move16();
3068 103 : Lon20mul33 = 264;
3069 103 : move16();
3070 103 : Lon20mul34 = 272;
3071 103 : move16();
3072 103 : Lmul2 = 1920;
3073 103 : move16();
3074 103 : BREAK;
3075 :
3076 30 : case L_FRAME32k:
3077 30 : *decimatefator = 4;
3078 30 : move16();
3079 30 : filt_size = 40;
3080 30 : move16();
3081 30 : Asr_LP_fx = Asr_LP32_fx;
3082 30 : QAsr = 15;
3083 30 : move16();
3084 30 : Lon20mul6 = 48;
3085 30 : move16();
3086 30 : Lon20mul28 = 224;
3087 30 : move16();
3088 30 : Lon20mul33 = 264;
3089 30 : move16();
3090 30 : Lon20mul34 = 272;
3091 30 : move16();
3092 30 : Lmul2 = 1280;
3093 30 : move16();
3094 30 : BREAK;
3095 :
3096 0 : case L_FRAME16k:
3097 0 : *decimatefator = 2;
3098 0 : move16();
3099 0 : filt_size = 20;
3100 0 : move16();
3101 0 : Asr_LP_fx = Asr_LP16_fx;
3102 0 : QAsr = 15;
3103 0 : move16();
3104 0 : Lon20mul6 = 48;
3105 0 : move16();
3106 0 : Lon20mul28 = 224;
3107 0 : move16();
3108 0 : Lon20mul33 = 264;
3109 0 : move16();
3110 0 : Lon20mul34 = 272;
3111 0 : move16();
3112 0 : Lmul2 = 640;
3113 0 : move16();
3114 0 : BREAK;
3115 :
3116 0 : default:
3117 0 : *decimatefator = 2;
3118 0 : move16();
3119 0 : filt_size = 40;
3120 0 : move16();
3121 0 : Asr_LP_fx = Asr_LP16_fx;
3122 0 : QAsr = 15;
3123 0 : move16();
3124 0 : Lon20mul6 = 48;
3125 0 : move16();
3126 0 : Lon20mul28 = 224;
3127 0 : move16();
3128 0 : Lon20mul33 = 264;
3129 0 : move16();
3130 0 : Lon20mul34 = 272;
3131 0 : move16();
3132 0 : Lmul2 = 320;
3133 0 : move16();
3134 0 : BREAK;
3135 : }
3136 :
3137 :
3138 : /* Resampling to work at 8Khz */
3139 133 : fir_dwn_fx( prevsynth_fx, Asr_LP_fx, QAsr, prevsynth_LP_fx, Lmul2, filt_size, *decimatefator ); /* resampling without delay */
3140 :
3141 :
3142 133 : tmpQLP = Find_Max_Norm16( prevsynth_LP_fx, 320 );
3143 133 : Scale_sig( prevsynth_LP_fx, 320, sub( tmpQLP, 3 ) ); /* to avoid over scaling */
3144 :
3145 :
3146 : /* Correlation analysis */
3147 133 : *min_corr_fx = 0;
3148 133 : move16();
3149 133 : accC = L_deposit_l( 0 );
3150 :
3151 133 : ptr_LP = prevsynth_LP_fx + Lon20mul34;
3152 6517 : FOR( k = 0; k < Lon20mul6; k++ )
3153 : {
3154 6384 : accC = L_mac0( accC, *ptr_LP, *ptr_LP );
3155 6384 : ptr_LP++;
3156 : }
3157 :
3158 :
3159 133 : IF( EQ_16( HqVoicing, 1 ) )
3160 : {
3161 0 : cb_start = 0;
3162 0 : move16();
3163 0 : cb_end = Lon20mul33;
3164 0 : move16();
3165 : }
3166 : ELSE
3167 : {
3168 133 : cb_start = 0;
3169 133 : move16();
3170 133 : cb_end = Lon20mul28;
3171 133 : move16();
3172 : }
3173 :
3174 133 : accB = 0;
3175 133 : move16();
3176 133 : delay_ind = cb_start;
3177 133 : move16();
3178 :
3179 22002 : FOR( i = cb_start; i < cb_end; i++ ) /* cb_end = 35 let 6 ms min of loop size */
3180 : {
3181 21911 : accA = 0;
3182 21911 : move16();
3183 21911 : IF( EQ_16( i, cb_start ) )
3184 : {
3185 133 : accB = 0;
3186 133 : move16();
3187 133 : ptr_LP = prevsynth_LP_fx;
3188 133 : ptr_LP2 = prevsynth_LP_fx + Lon20mul34;
3189 6517 : FOR( k = 0; k < Lon20mul6; k++ )
3190 : {
3191 6384 : accA = L_mac0( accA, *ptr_LP, *ptr_LP2 );
3192 6384 : accB = L_mac0( accB, *ptr_LP, *ptr_LP );
3193 6384 : ptr_LP++;
3194 6384 : ptr_LP2++;
3195 : }
3196 : }
3197 : ELSE
3198 : {
3199 :
3200 :
3201 21778 : accB = L_mac0( L_msu0( accB, prevsynth_LP_fx[i - 1], prevsynth_LP_fx[i - 1] ), prevsynth_LP_fx[i + Lon20mul6 - 1], prevsynth_LP_fx[i + Lon20mul6 - 1] ); /* tmpQLP-5 */
3202 :
3203 :
3204 21778 : ptr_LP3 = prevsynth_LP_fx + i;
3205 21778 : ptr_LP4 = prevsynth_LP_fx + Lon20mul34;
3206 :
3207 1067122 : FOR( k = 0; k < Lon20mul6; k++ )
3208 : {
3209 1045344 : accA = L_mac0( accA, *ptr_LP3, *ptr_LP4 ); /*2* tmpQLP-5 */
3210 1045344 : ptr_LP3++;
3211 1045344 : ptr_LP4++;
3212 : }
3213 : }
3214 :
3215 : /*accB*/
3216 : /*accC*/
3217 : /*accA Q 6-2*tmpQLP*/
3218 :
3219 21911 : accBisqrt = Isqrt( accB ); /* Q31 - 3 + tmpQLP */
3220 21911 : accCisqrt = Isqrt( accC ); /* Q31 - 3 + tmpQLP*/
3221 :
3222 :
3223 21911 : Ryytmp = L_shl_sat( Mult_32_32( accA, accCisqrt ), Q15 ); /*Q 6 -2*tmpQLP + Q31 - 3 + tmpQLP -16 -3 +tmpQLP = Q15*/
3224 21911 : Ryy = extract_h( L_shl_sat( Mult_32_32( Ryytmp, accBisqrt ), 16 ) ); /*Q15 + Q31 - 3 + tmpQLP -15 + 3- tmpQLP = Q31*/
3225 :
3226 21911 : IF( GT_16( Ryy, *min_corr_fx ) )
3227 : {
3228 856 : *min_corr_fx = Ryy;
3229 856 : move16();
3230 856 : delay_ind = i;
3231 856 : move16();
3232 : }
3233 :
3234 21911 : test();
3235 21911 : IF( HqVoicing == 0 && GT_16( *min_corr_fx, 31130 ) )
3236 : {
3237 42 : BREAK;
3238 : }
3239 : }
3240 :
3241 133 : *N = sub( Lon20mul34, delay_ind );
3242 133 : move16();
3243 :
3244 133 : Scale_sig( prevsynth_LP_fx, 320, negate( sub( tmpQLP, 3 ) ) );
3245 133 : return;
3246 : }
3247 :
3248 0 : static void fec_ecu_pitch_fx(
3249 : const Word16 *prevsynth_fx, /*Q15 16 */
3250 : Word16 *prevsynth_LP_fx, /* Q15 16 */
3251 : const Word16 L,
3252 : Word16 *N,
3253 : Word16 *min_corr_fx, /* Q15 16 */
3254 : Word16 *decimatefator,
3255 : const Word16 HqVoicing )
3256 : {
3257 :
3258 : Word16 i, filt_size;
3259 : Word16 QAsr, Ryy, cb_start, tmpQLP;
3260 : Word32 Ryytmp;
3261 : Word32 accA, accB, accBisqrt, accC, accCisqrt;
3262 : Word16 delay_ind, k;
3263 : const Word16 *Asr_LP_fx;
3264 : Word16 *ptr_LP, *ptr_LP2, *ptr_LP3, *ptr_LP4;
3265 : Word16 cb_end;
3266 : Word16 Lmul2, Lon20mul6, Lon20mul28, Lon20mul33, Lon20mul34;
3267 :
3268 :
3269 0 : SWITCH( L )
3270 : {
3271 0 : case L_FRAME48k:
3272 0 : *decimatefator = 6;
3273 0 : move16();
3274 0 : filt_size = 60;
3275 0 : move16();
3276 0 : Asr_LP_fx = Asr_LP48_fx;
3277 0 : QAsr = 17;
3278 0 : move16();
3279 0 : Lon20mul6 = 48;
3280 0 : move16();
3281 0 : Lon20mul28 = 224;
3282 0 : move16();
3283 0 : Lon20mul33 = 264;
3284 0 : move16();
3285 0 : Lon20mul34 = 272;
3286 0 : move16();
3287 0 : Lmul2 = 1920;
3288 0 : move16();
3289 0 : BREAK;
3290 :
3291 0 : case L_FRAME32k:
3292 0 : *decimatefator = 4;
3293 0 : move16();
3294 0 : filt_size = 40;
3295 0 : move16();
3296 0 : Asr_LP_fx = Asr_LP32_fx;
3297 0 : QAsr = 15;
3298 0 : move16();
3299 0 : Lon20mul6 = 48;
3300 0 : move16();
3301 0 : Lon20mul28 = 224;
3302 0 : move16();
3303 0 : Lon20mul33 = 264;
3304 0 : move16();
3305 0 : Lon20mul34 = 272;
3306 0 : move16();
3307 0 : Lmul2 = 1280;
3308 0 : move16();
3309 0 : BREAK;
3310 :
3311 0 : case L_FRAME16k:
3312 0 : *decimatefator = 2;
3313 0 : move16();
3314 0 : filt_size = 20;
3315 0 : move16();
3316 0 : Asr_LP_fx = Asr_LP16_fx;
3317 0 : QAsr = 15;
3318 0 : move16();
3319 0 : Lon20mul6 = 48;
3320 0 : move16();
3321 0 : Lon20mul28 = 224;
3322 0 : move16();
3323 0 : Lon20mul33 = 264;
3324 0 : move16();
3325 0 : Lon20mul34 = 272;
3326 0 : move16();
3327 0 : Lmul2 = 640;
3328 0 : move16();
3329 0 : BREAK;
3330 :
3331 0 : default:
3332 0 : *decimatefator = 2;
3333 0 : move16();
3334 0 : filt_size = 40;
3335 0 : move16();
3336 0 : Asr_LP_fx = Asr_LP16_fx;
3337 0 : QAsr = 15;
3338 0 : move16();
3339 0 : Lon20mul6 = 48;
3340 0 : move16();
3341 0 : Lon20mul28 = 224;
3342 0 : move16();
3343 0 : Lon20mul33 = 264;
3344 0 : move16();
3345 0 : Lon20mul34 = 272;
3346 0 : move16();
3347 0 : Lmul2 = 320;
3348 0 : move16();
3349 0 : BREAK;
3350 : }
3351 :
3352 :
3353 : /* Resampling to work at 8Khz */
3354 0 : fir_dwn_fx( prevsynth_fx, Asr_LP_fx, QAsr, prevsynth_LP_fx, Lmul2, filt_size, *decimatefator ); /* resampling without delay */
3355 :
3356 :
3357 0 : tmpQLP = Find_Max_Norm16( prevsynth_LP_fx, 320 );
3358 0 : Scale_sig( prevsynth_LP_fx, 320, sub( tmpQLP, 3 ) ); /* to avoid over scaling */
3359 :
3360 :
3361 : /* Correlation analysis */
3362 0 : *min_corr_fx = 0;
3363 0 : move16();
3364 0 : accC = L_deposit_l( 0 );
3365 :
3366 0 : ptr_LP = prevsynth_LP_fx + Lon20mul34;
3367 0 : FOR( k = 0; k < Lon20mul6; k++ )
3368 : {
3369 0 : accC = L_mac0( accC, *ptr_LP, *ptr_LP );
3370 0 : ptr_LP++;
3371 : }
3372 :
3373 :
3374 0 : IF( EQ_16( HqVoicing, 1 ) )
3375 : {
3376 0 : cb_start = 0;
3377 0 : move16();
3378 0 : cb_end = Lon20mul33;
3379 0 : move16();
3380 : }
3381 : ELSE
3382 : {
3383 0 : cb_start = 0;
3384 0 : move16();
3385 0 : cb_end = Lon20mul28;
3386 0 : move16();
3387 : }
3388 :
3389 0 : accB = 0;
3390 0 : move16();
3391 0 : delay_ind = cb_start;
3392 0 : move16();
3393 :
3394 0 : FOR( i = cb_start; i < cb_end; i++ ) /* cb_end = 35 let 6 ms min of loop size */
3395 : {
3396 0 : accA = 0;
3397 0 : move16();
3398 0 : IF( EQ_16( i, cb_start ) )
3399 : {
3400 0 : accB = 0;
3401 0 : move16();
3402 0 : ptr_LP = prevsynth_LP_fx;
3403 0 : ptr_LP2 = prevsynth_LP_fx + Lon20mul34;
3404 0 : FOR( k = 0; k < Lon20mul6; k++ )
3405 : {
3406 0 : accA = L_mac0( accA, *ptr_LP, *ptr_LP2 );
3407 0 : accB = L_mac0( accB, *ptr_LP, *ptr_LP );
3408 0 : ptr_LP++;
3409 0 : ptr_LP2++;
3410 : }
3411 : }
3412 : ELSE
3413 : {
3414 :
3415 :
3416 0 : accB = L_mac0( L_msu0( accB, prevsynth_LP_fx[i - 1], prevsynth_LP_fx[i - 1] ), prevsynth_LP_fx[i + Lon20mul6 - 1], prevsynth_LP_fx[i + Lon20mul6 - 1] ); /* tmpQLP-5 */
3417 :
3418 :
3419 0 : ptr_LP3 = prevsynth_LP_fx + i;
3420 0 : ptr_LP4 = prevsynth_LP_fx + Lon20mul34;
3421 :
3422 0 : FOR( k = 0; k < Lon20mul6; k++ )
3423 : {
3424 0 : accA = L_mac0( accA, *ptr_LP3, *ptr_LP4 ); /*2* tmpQLP-5 */
3425 0 : ptr_LP3++;
3426 0 : ptr_LP4++;
3427 : }
3428 : }
3429 :
3430 : /*accB*/
3431 : /*accC*/
3432 : /*accA Q 6-2*tmpQLP*/
3433 :
3434 0 : accBisqrt = Isqrt( accB ); /* Q31 - 3 + tmpQLP */
3435 0 : accCisqrt = Isqrt( accC ); /* Q31 - 3 + tmpQLP*/
3436 :
3437 :
3438 0 : Ryytmp = mult_32_32_q( accA, accCisqrt, sub( 16 + 3, tmpQLP ) ); /*Q 6 -2*tmpQLP + Q31 - 3 + tmpQLP -16 -3 +tmpQLP = Q15*/
3439 0 : Ryytmp = mult_32_32_q( Ryytmp, accBisqrt, add( 15 - 3, tmpQLP ) ); /*Q15 + Q31 - 3 + tmpQLP -15 + 3- tmpQLP = Q31*/
3440 0 : Ryy = extract_h( Ryytmp ); /* Q15 */
3441 :
3442 :
3443 0 : IF( GT_16( Ryy, *min_corr_fx ) )
3444 : {
3445 0 : *min_corr_fx = Ryy;
3446 0 : move16();
3447 0 : delay_ind = i;
3448 0 : move16();
3449 : }
3450 :
3451 0 : test();
3452 0 : IF( HqVoicing == 0 && GT_16( *min_corr_fx, 31130 ) )
3453 : {
3454 0 : BREAK;
3455 : }
3456 : }
3457 :
3458 0 : *N = sub( Lon20mul34, delay_ind );
3459 0 : move16();
3460 :
3461 0 : Scale_sig( prevsynth_LP_fx, 320, negate( sub( tmpQLP, 3 ) ) );
3462 0 : return;
3463 : }
3464 :
3465 8 : static void sin_cos_est_fx( Word32 phi, Word16 *cosfreq, Word16 *sinfreq )
3466 : {
3467 :
3468 :
3469 : /* i phi : normalized frequency beteween 0 and Pi (nyquist) in Q30 */
3470 : /* o cosfreq & sinfreq : cos(phi) and sin (phi) in Q15 */
3471 :
3472 : Word16 i;
3473 : Word32 delta;
3474 : Word32 imin;
3475 : Word16 sinb, cosb;
3476 : Word32 sinv, cosv, tmp;
3477 :
3478 8 : i = 0;
3479 8 : move16();
3480 540 : FOR( imin = 0; imin < phi; imin += 4392264 )
3481 : {
3482 532 : i = add( i, 1 );
3483 : }
3484 :
3485 8 : delta = L_sub( phi, imin ); /*Q30 */
3486 8 : sinb = sincos_t_rad3_fx[i];
3487 8 : move16(); /*Q15 */
3488 8 : cosb = sincos_t_rad3_fx[384 - i];
3489 8 : move16(); /*Q15 */
3490 :
3491 : /*sinv = sin(phi) = sinb*cos(delta)+cosb*sin(delta) */
3492 : /*cosv = cos(phi) = cosb*cos(delta)-sinb*sin(delta) */
3493 : /*sin(delta) is approximated by delta for very small delta; cos(delta) is approximated by 1 */
3494 8 : tmp = L_shl( Mult_32_16( delta, cosb ), 1 ); /*Q31 */
3495 8 : sinv = L_add( L_deposit_h( sinb ), tmp );
3496 8 : tmp = L_shl( Mult_32_16( delta, sinb ), 1 ); /*Q31 */
3497 8 : cosv = L_sub_sat( L_deposit_h( cosb ), tmp );
3498 8 : *sinfreq = round_fx_sat( sinv );
3499 8 : move16();
3500 8 : *cosfreq = round_fx_sat( cosv );
3501 8 : move16();
3502 :
3503 8 : return;
3504 : }
3505 :
3506 32 : static Word16 abs_iter_fx( Word16 re /*Qx*/, Word16 im /*Qx*/, Word16 N )
3507 : {
3508 : Word16 A, tmp, L_tmp1, L_tmp2;
3509 : Word16 i, exp;
3510 :
3511 : /*const Word16 cor[10] = { 23170, 20724, 20106, 19950, 19911, 19902, 19899, 19899, 19899, 19898}; */
3512 :
3513 32 : exp = norm_s( re );
3514 32 : exp = s_min( exp, norm_s( im ) );
3515 32 : exp = sub( exp, 2 );
3516 :
3517 32 : re = shl( re, exp );
3518 32 : im = shl( im, exp );
3519 :
3520 :
3521 32 : IF( im < 0 )
3522 : {
3523 13 : im = negate( im );
3524 : }
3525 : ELSE
3526 : {
3527 19 : re = negate( re );
3528 : }
3529 32 : tmp = re;
3530 32 : move16();
3531 32 : re = im;
3532 32 : move16();
3533 32 : im = tmp;
3534 32 : move16();
3535 :
3536 :
3537 192 : FOR( i = 0; i < N; i++ )
3538 : {
3539 160 : L_tmp1 = shr( im, i );
3540 160 : L_tmp2 = shr( re, i );
3541 160 : IF( im < 0 )
3542 : {
3543 83 : L_tmp1 = negate( L_tmp1 );
3544 : }
3545 : ELSE
3546 : {
3547 77 : L_tmp2 = negate( L_tmp2 );
3548 : }
3549 160 : re = add( re, L_tmp1 );
3550 160 : im = add( im, L_tmp2 );
3551 : }
3552 32 : i = s_min( sub( i, 1 ), 9 );
3553 32 : tmp = abs_s( re );
3554 : /*A = round_fx(L_shr(L_mult(tmp, cor[i]), exp)); //this can be ommited, if we don't need the exact abs value */
3555 32 : A = shr_sat( tmp, exp );
3556 32 : return A;
3557 : }
3558 : /*--------------------------------------------------------------------------
3559 : * fec_ecu_dft()
3560 : *
3561 : * DFT analysis on adaptive frame length. Analysis frame stretched to
3562 : * next power of 2 using linear interpolation.
3563 : *--------------------------------------------------------------------------*/
3564 :
3565 1 : static void ivas_fec_ecu_dft_fx(
3566 : const Word16 *prevsynth_LP, /*Qin */
3567 : const Word16 N,
3568 : Word16 *Tfr, /*Qout */
3569 : Word16 *Tfi, /*Qout */
3570 : Word32 *sum_Tf_abs, /*Qout; */
3571 : Word16 *Tf_abs, /*Qout */
3572 : Word16 *Nfft,
3573 : Word16 *exp, /*Qout = Qin+exp */
3574 : const Word16 element_mode /* i : IVAS element mode */
3575 : )
3576 : {
3577 : Word32 L_tmp, Tmp, Tfr32[512], Tfi32[512], fac, *Pt1, *Pt2;
3578 : Word16 i, tmp, tmp_short, N_LP, target[2 * L_FRAME48k], Tfr16[FEC_FFT_MAX_SIZE], *pt1, *pt2, *pt3, Lon20;
3579 : Word16 tmp_loop;
3580 : Word16 alignment_point;
3581 :
3582 1 : Lon20 = 8;
3583 1 : move16();
3584 1 : IF( element_mode == EVS_MONO )
3585 : {
3586 0 : alignment_point = sub( shl( 160, 1 ), i_mult( 3, Lon20 ) );
3587 : }
3588 : ELSE
3589 : {
3590 1 : alignment_point = shl( 160, 1 );
3591 : }
3592 1 : tmp = sub( alignment_point, N );
3593 1 : Copy( &prevsynth_LP[tmp], target, N );
3594 :
3595 : /* DFT */
3596 :
3597 1 : L_tmp = L_deposit_l( N );
3598 10 : FOR( tmp = 0; L_tmp <= 16384; tmp++ )
3599 : {
3600 9 : L_tmp = L_shl( L_tmp, 1 );
3601 : }
3602 1 : *Nfft = shl( 1, sub( 15, tmp ) );
3603 1 : move16();
3604 :
3605 1 : set32_fx( Tfr32, 0, *Nfft );
3606 1 : set32_fx( Tfi32, 0, *Nfft );
3607 1 : Tfr16[0] = target[0];
3608 1 : move16();
3609 1 : Tfr16[*Nfft - 1] = target[N - 1];
3610 1 : move16();
3611 :
3612 1 : IF( EQ_16( *Nfft, N ) )
3613 : {
3614 0 : Copy( &target[1], &Tfr16[1], sub( *Nfft, 2 ) );
3615 : }
3616 : ELSE
3617 : {
3618 :
3619 1 : tmp = div_s( sub( N, 1 ), sub( *Nfft, 1 ) );
3620 1 : Tmp = L_deposit_l( tmp );
3621 1 : fac = L_add( Tmp, 0 );
3622 1 : tmp_loop = sub( *Nfft, 1 );
3623 63 : FOR( i = 1; i < tmp_loop; i++ ) /* interpolation for FFT */
3624 : {
3625 62 : tmp_short = extract_l( L_shr( Tmp, 15 ) );
3626 62 : tmp = extract_l( L_msu( Tmp, tmp_short, 16384 ) );
3627 62 : L_tmp = L_mult( sub_sat( target[tmp_short + 1], target[tmp_short] ), tmp ); /*Qin+16 */
3628 62 : Tfr16[i] = add_sat( target[tmp_short], round_fx_sat( L_tmp ) );
3629 62 : move16(); /*Qin */
3630 62 : Tmp = L_add( Tmp, fac );
3631 : }
3632 : }
3633 :
3634 :
3635 : /*to avoid overflow in DoRTFTn_fx() */
3636 1 : tmp = Exp16Array( *Nfft, Tfr16 );
3637 1 : *exp = add( tmp, add( 2, norm_s( *Nfft ) ) );
3638 1 : move16();
3639 1 : Copy_Scale_sig_16_32_no_sat( Tfr16, Tfr32, *Nfft, *exp ); /*Qin+exp; */
3640 1 : *exp = s_min( *exp, 15 );
3641 :
3642 1 : DoRTFTn_fx( Tfr32, Tfi32, *Nfft );
3643 1 : N_LP = shr( *Nfft, 1 );
3644 :
3645 :
3646 1 : L_tmp = L_deposit_l( 0 );
3647 :
3648 1 : pt1 = Tfr;
3649 1 : pt2 = Tfi;
3650 1 : pt3 = Tf_abs;
3651 1 : Pt1 = Tfr32;
3652 1 : Pt2 = Tfi32;
3653 33 : FOR( i = 0; i < N_LP; i++ )
3654 : {
3655 32 : *pt1 = extract_h( *Pt1 ); /*Qin+exp-16 */
3656 32 : move16();
3657 32 : *pt2 = extract_h( *Pt2 ); /*Qin+exp-16 */
3658 32 : move16();
3659 32 : *pt3 = abs_iter_fx( Tfr[i], Tfi[i], 5 );
3660 32 : move16(); /*Qin+exp-16 */
3661 32 : L_tmp = L_mac0( L_tmp, *pt3, 1 ); /*Qin+exp-16 */
3662 32 : pt1++;
3663 32 : pt2++;
3664 32 : pt3++;
3665 32 : Pt1++;
3666 32 : Pt2++;
3667 : }
3668 1 : *sum_Tf_abs = L_tmp;
3669 1 : move32();
3670 1 : *exp = sub( *exp, 16 );
3671 1 : move16();
3672 1 : return;
3673 : }
3674 :
3675 0 : static void fec_ecu_dft_fx(
3676 : const Word16 *prevsynth_LP, /*Qin */
3677 : const Word16 N,
3678 : Word16 *Tfr, /*Qout */
3679 : Word16 *Tfi, /*Qout */
3680 : Word32 *sum_Tf_abs, /*Qout; */
3681 : Word16 *Tf_abs, /*Qout */
3682 : Word16 *Nfft,
3683 : Word16 *exp /*Qout = Qin+exp */
3684 : )
3685 : {
3686 : Word32 L_tmp, Tmp, Tfr32[512], Tfi32[512], fac, *Pt1, *Pt2;
3687 : Word16 i, tmp, tmp_short, N_LP, target[2 * L_FRAME48k], Tfr16[FEC_FFT_MAX_SIZE], *pt1, *pt2, *pt3;
3688 : Word16 tmp_loop;
3689 0 : tmp = sub( 296, N );
3690 0 : Copy( &prevsynth_LP[tmp], target, N );
3691 :
3692 :
3693 : /* DFT */
3694 :
3695 0 : L_tmp = L_deposit_l( N );
3696 0 : FOR( tmp = 0; L_tmp <= 16384; tmp++ )
3697 : {
3698 0 : L_tmp = L_shl( L_tmp, 1 );
3699 : }
3700 0 : *Nfft = shl( 1, sub( 15, tmp ) );
3701 0 : move16();
3702 :
3703 :
3704 0 : set32_fx( Tfr32, 0, *Nfft );
3705 0 : set32_fx( Tfi32, 0, *Nfft );
3706 0 : Tfr16[0] = target[0];
3707 0 : move16();
3708 0 : Tfr16[*Nfft - 1] = target[N - 1];
3709 0 : move16();
3710 :
3711 0 : IF( EQ_16( *Nfft, N ) )
3712 : {
3713 0 : Copy( &target[1], &Tfr16[1], sub( *Nfft, 2 ) );
3714 : }
3715 : ELSE
3716 : {
3717 :
3718 0 : tmp = div_s( sub( N, 1 ), sub( *Nfft, 1 ) );
3719 0 : Tmp = L_deposit_l( tmp );
3720 0 : fac = L_add( Tmp, 0 );
3721 0 : tmp_loop = sub( *Nfft, 1 );
3722 0 : FOR( i = 1; i < tmp_loop; i++ ) /* interpolation for FFT */
3723 : {
3724 0 : tmp_short = extract_l( L_shr( Tmp, 15 ) );
3725 0 : tmp = extract_l( L_msu( Tmp, tmp_short, 16384 ) );
3726 0 : L_tmp = L_mult( sub_sat( target[tmp_short + 1], target[tmp_short] ), tmp ); /*Qin+16 */
3727 0 : Tfr16[i] = add_sat( target[tmp_short], round_fx_sat( L_tmp ) );
3728 0 : move16(); /*Qin */
3729 0 : Tmp = L_add( Tmp, fac );
3730 : }
3731 : }
3732 :
3733 :
3734 : /*to avoid overflow in DoRTFTn_fx() */
3735 0 : tmp = Exp16Array( *Nfft, Tfr16 );
3736 0 : *exp = add( tmp, add( 2, norm_s( *Nfft ) ) );
3737 0 : move16();
3738 : {
3739 0 : Word16 loctmp = *exp;
3740 0 : move16();
3741 0 : loctmp = s_min( 15, loctmp );
3742 0 : Copy_Scale_sig_16_32_DEPREC( Tfr16, Tfr32, *Nfft, loctmp ); /*Qin+exp; */ /*Even with limiting loctmp, if Copy_Scale_sig_16_32_no_sat() is used, can lead to 1 difference */
3743 : }
3744 :
3745 0 : DoRTFTn_fx( Tfr32, Tfi32, *Nfft );
3746 0 : N_LP = shr( *Nfft, 1 );
3747 :
3748 :
3749 0 : L_tmp = L_deposit_l( 0 );
3750 :
3751 0 : pt1 = Tfr;
3752 0 : pt2 = Tfi;
3753 0 : pt3 = Tf_abs;
3754 0 : Pt1 = Tfr32;
3755 0 : Pt2 = Tfi32;
3756 0 : FOR( i = 0; i < N_LP; i++ )
3757 : {
3758 0 : *pt1 = extract_h( *Pt1 ); /*Qin+exp-16 */
3759 0 : move16();
3760 0 : *pt2 = extract_h( *Pt2 ); /*Qin+exp-16 */
3761 0 : move16();
3762 0 : *pt3 = abs_iter_fx( Tfr[i], Tfi[i], 5 );
3763 0 : move16(); /*Qin+exp-16 */
3764 0 : L_tmp = L_mac0( L_tmp, *pt3, 1 ); /*Qin+exp-16 */
3765 0 : pt1++;
3766 0 : pt2++;
3767 0 : pt3++;
3768 0 : Pt1++;
3769 0 : Pt2++;
3770 : }
3771 0 : *sum_Tf_abs = L_tmp;
3772 0 : move32();
3773 0 : *exp = sub( *exp, 16 );
3774 0 : move16();
3775 0 : return;
3776 : }
3777 :
3778 8 : static void singenerator_fx(
3779 : const Word16 L, /* i : size of output */
3780 : const Word16 cosfreq, /* i : cosine of 1-sample dephasing at the given frequency Q15*/
3781 : const Word16 sinfreq, /* i : sine of 1-sample dephasing at the given frequency Q15*/
3782 : const Word16 a_re,
3783 : /* i : real part of complex spectral coefficient at the given frequency */ /*Qin */
3784 : const Word16 a_im,
3785 : /* i : imag part of complex spectral coefficient at the given frequency */ /*Qin */
3786 : Word32 xx[] /* o : output vector */ /*Qin+16 */
3787 : )
3788 : {
3789 :
3790 : Word32 *ptr, L_C0, L_S0, L_C1, L_S1;
3791 : Word16 C0, S0, C1, S1;
3792 : Word16 i;
3793 :
3794 8 : L_S0 = L_deposit_l( 0 ); /*prevent warning*/
3795 8 : L_C0 = L_deposit_h( a_re ); /*Qin+16 */
3796 8 : S0 = a_im;
3797 8 : move16();
3798 :
3799 8 : ptr = xx;
3800 :
3801 8 : *ptr = L_add_sat( *ptr, L_C0 );
3802 8 : move32();
3803 8 : ptr++;
3804 :
3805 5120 : FOR( i = 0; i < L / 2 - 1; i++ )
3806 : {
3807 5112 : C0 = extract_h( L_C0 ); /*Qin */
3808 5112 : L_C1 = L_mult( C0, cosfreq ); /*Qin+16 */
3809 5112 : L_C1 = L_msu( L_C1, S0, sinfreq ); /*Qin+16 */
3810 5112 : L_S1 = L_mult( C0, sinfreq );
3811 5112 : S1 = mac_r( L_S1, S0, cosfreq );
3812 5112 : *ptr = L_add_sat( *ptr, L_C1 );
3813 5112 : move32(); /*Qin+16 */
3814 5112 : ptr++;
3815 :
3816 5112 : C1 = extract_h( L_C1 );
3817 5112 : L_C0 = L_mult( C1, cosfreq );
3818 5112 : L_C0 = L_msu( L_C0, S1, sinfreq );
3819 5112 : L_S0 = L_mult( C1, sinfreq );
3820 5112 : S0 = mac_r( L_S0, S1, cosfreq );
3821 5112 : *ptr = L_add_sat( *ptr, L_C0 );
3822 5112 : move32();
3823 5112 : ptr++;
3824 : }
3825 :
3826 8 : C0 = extract_h( L_C0 );
3827 8 : S0 = extract_h( L_S0 );
3828 8 : L_C1 = L_mult( C0, cosfreq );
3829 8 : L_C1 = L_msu( L_C1, S0, sinfreq );
3830 8 : *ptr = L_add_sat( *ptr, L_C1 );
3831 8 : move32();
3832 8 : ptr++;
3833 :
3834 8 : return;
3835 : }
3836 :
3837 1 : static void sinusoidal_synthesis_fx(
3838 : const Word16 *Tfr, /*Qin */
3839 : const Word16 *Tfi, /*Qin */
3840 : Word16 *Tf_abs, /*Qin */
3841 : const Word16 N,
3842 : const Word16 L,
3843 : const Word16 decimate_factor,
3844 : const Word16 Nfft,
3845 : const Word32 sum_Tf_abs, /*Qin */
3846 : Word16 *synthesis, /*Qin */
3847 : const Word16 HqVoicing,
3848 : Word16 exp )
3849 : {
3850 1 : Word16 i, k, nb_pulses, indmax = 0, nb_pulses_final;
3851 : Word16 pulses[FEC_MAX / 2];
3852 : Word16 mmax, maxi;
3853 : Word32 cumsum, freq, L_tmp;
3854 : Word16 freqi[FEC_NB_PULSE_MAX], tmp, q, inv_den, new_s, old, cpt;
3855 : Word16 a_re[FEC_NB_PULSE_MAX], a_im[FEC_NB_PULSE_MAX];
3856 1 : Word16 Lon20_10 = 80;
3857 : Word16 flag, Len;
3858 : Word16 cosfreq, sinfreq, sN, PL, glued;
3859 : Word32 synthesis_fx[2 * L_FRAME48k];
3860 : Word16 *pt1, *pt2, *pt3, *pt4;
3861 :
3862 1 : move16(); // indmax
3863 1 : move16(); // Lon20_10
3864 1 : flag = HqVoicing;
3865 1 : move16();
3866 1 : if ( GT_16( N, Lon20_10 ) )
3867 : {
3868 0 : flag = 1;
3869 0 : move16(); /*flag corresponds to condition sub(N, Lon20_10)>0 || HqVoicing */
3870 : }
3871 :
3872 :
3873 1 : pt4 = pulses;
3874 1 : nb_pulses = 0;
3875 1 : move16();
3876 1 : PL = 0;
3877 1 : move16();
3878 1 : cpt = 0;
3879 1 : move16();
3880 1 : old = 0;
3881 1 : move16();
3882 1 : glued = 1;
3883 1 : move16();
3884 1 : new_s = Tf_abs[1]; // Qin
3885 1 : move16();
3886 1 : if ( flag )
3887 : {
3888 0 : PL = 1;
3889 0 : move16();
3890 : }
3891 1 : tmp = sub( shr( N, 1 ), 3 );
3892 26 : WHILE( LE_16( cpt, tmp ) )
3893 : {
3894 25 : test();
3895 25 : IF( GT_16( Tf_abs[cpt], old ) && GT_16( Tf_abs[cpt], new_s ) )
3896 11 : {
3897 : Word16 tmp2;
3898 :
3899 11 : glued = cpt;
3900 11 : move16();
3901 :
3902 11 : tmp2 = add( add( cpt, PL ), 1 );
3903 22 : FOR( i = glued; i < tmp2; i++ )
3904 : {
3905 11 : *pt4++ = i;
3906 11 : move16();
3907 11 : nb_pulses++;
3908 11 : move16();
3909 : }
3910 11 : old = Tf_abs[cpt + PL];
3911 11 : move16();
3912 11 : new_s = Tf_abs[cpt + 2 + PL];
3913 11 : move16();
3914 11 : cpt = add( add( cpt, PL ), 1 );
3915 11 : move16();
3916 11 : glued = 1;
3917 11 : move16();
3918 : }
3919 : ELSE
3920 : {
3921 14 : old = Tf_abs[cpt];
3922 14 : move16();
3923 14 : new_s = Tf_abs[cpt + 2];
3924 14 : move16();
3925 14 : cpt++;
3926 14 : glued = 0;
3927 14 : move16();
3928 : }
3929 : }
3930 :
3931 :
3932 1 : nb_pulses_final = 0;
3933 1 : move16();
3934 :
3935 1 : sN = sub( 13, norm_s( Nfft ) ); /*for amplitude normalization by 2/nfft */
3936 :
3937 1 : cumsum = L_deposit_l( 0 );
3938 :
3939 :
3940 1 : L_tmp = Mult_32_16( sum_Tf_abs, 22938 ); // Qin
3941 :
3942 1 : pt1 = a_re;
3943 1 : pt2 = a_im;
3944 1 : pt3 = freqi;
3945 :
3946 1 : maxi = s_min( FEC_NB_PULSE_MAX, nb_pulses );
3947 1 : nb_pulses_final = maxi;
3948 1 : move16();
3949 :
3950 1 : Len = shl( L, 1 );
3951 1 : IF( HqVoicing )
3952 : {
3953 0 : FOR( i = 0; i < maxi; i++ )
3954 : {
3955 0 : mmax = 0;
3956 0 : move16();
3957 0 : pt4 = pulses;
3958 0 : FOR( k = 0; k < nb_pulses; k++ )
3959 : {
3960 0 : tmp = *pt4++;
3961 0 : move16();
3962 0 : if ( GT_16( Tf_abs[tmp], mmax ) )
3963 : {
3964 0 : indmax = tmp;
3965 0 : move16();
3966 : }
3967 0 : mmax = s_max( Tf_abs[tmp], mmax );
3968 : }
3969 :
3970 0 : *pt1++ = Tfr[indmax];
3971 0 : move16(); /*L_shr(Tfr[indmax], sN); //instead shr -> scaling of a_re is Qin+sN */
3972 0 : *pt2++ = Tfi[indmax];
3973 0 : move16(); /*L_shr(Tfi[indmax], sN); //instead shr -> scaling of a_im is Qin+sN */
3974 0 : *pt3++ = indmax;
3975 0 : move16();
3976 0 : Tf_abs[indmax] = -1;
3977 0 : move16();
3978 : }
3979 : }
3980 : ELSE
3981 : {
3982 : DO
3983 : {
3984 8 : mmax = 0;
3985 8 : move16();
3986 8 : pt4 = pulses;
3987 96 : FOR( k = 0; k < nb_pulses; k++ )
3988 : {
3989 88 : tmp = *pt4++;
3990 88 : move16();
3991 88 : if ( GT_16( Tf_abs[tmp], mmax ) )
3992 : {
3993 19 : indmax = tmp;
3994 19 : move16();
3995 : }
3996 88 : mmax = s_max( Tf_abs[tmp], mmax );
3997 : }
3998 :
3999 8 : cumsum = L_mac0( cumsum, mmax, 1 ); // Qin
4000 :
4001 8 : *pt1++ = Tfr[indmax];
4002 8 : move16(); /*L_shr(Tfr[indmax], sN); //instead shr -> scaling of a_re is Qin+sN */
4003 8 : *pt2++ = Tfi[indmax];
4004 8 : move16(); /*L_shr(Tfi[indmax], sN); //instead shr -> scaling of a_im is Qin+sN */
4005 8 : *pt3++ = indmax;
4006 8 : move16();
4007 8 : Tf_abs[indmax] = -1;
4008 8 : move16();
4009 :
4010 8 : maxi = sub( maxi, 1 );
4011 : }
4012 8 : WHILE( maxi > 0 && LT_32( cumsum, L_tmp ) );
4013 :
4014 1 : nb_pulses_final = sub( nb_pulses_final, maxi );
4015 1 : move16();
4016 : }
4017 :
4018 :
4019 : /* sinusoidal synthesis */
4020 :
4021 :
4022 1 : set32_fx( synthesis_fx, 0, Len );
4023 :
4024 1 : exp = add( exp, sN );
4025 :
4026 :
4027 1 : pt1 = a_re;
4028 1 : pt2 = a_im;
4029 1 : pt3 = freqi;
4030 1 : q = shr_r( N, 2 );
4031 1 : if ( GT_16( N, shl( q, 2 ) ) )
4032 : {
4033 0 : q = add( q, 1 );
4034 : }
4035 :
4036 1 : inv_den = i_mult2( N, decimate_factor ); /*Q0 */
4037 :
4038 : /*tmp = div_s(12868,inv_den);*/ /*Q15 */
4039 :
4040 :
4041 9 : FOR( i = 0; i < nb_pulses_final; i++ )
4042 : {
4043 :
4044 8 : tmp = div_s( shl( *pt3, 1 ), inv_den ); /*Q15 */ /* ind*2/(N*decim) */
4045 8 : freq = L_shl( L_mult( tmp, 25736 ), 1 ); /*Q30 */ /* ind*2/(N*decim)*pi/4*4 never greater than PI/2 */
4046 8 : sin_cos_est_fx( freq, &cosfreq, &sinfreq ); /*cosfreq & sinfreq in Q15 */
4047 8 : singenerator_fx( Len, cosfreq, sinfreq, *pt1, *pt2, synthesis_fx ); /*Qin */
4048 :
4049 8 : pt1++;
4050 8 : pt2++;
4051 8 : pt3++;
4052 : }
4053 1 : Copy_Scale_sig_32_16( synthesis_fx, synthesis, Len, negate( add( exp, 16 ) ) ); /*Qin */
4054 :
4055 :
4056 1 : return;
4057 : }
4058 :
4059 1 : static void ivas_fec_noise_filling_fx(
4060 : const Word16 *prevsynth_fx, /*Qsynth */
4061 : Word16 *synthesis_fx, /*Qsynth */
4062 : Word16 *ni_seed_forfec,
4063 : const Word16 L,
4064 : const Word16 N,
4065 : const Word16 HqVoicing,
4066 : Word16 *gapsynth_fx, /*Qsynth */
4067 : const Word16 element_mode, /* i : IVAS element mode */
4068 : const Word16 *old_out,
4069 : const Word16 Q_old_out )
4070 : {
4071 :
4072 : Word16 Rnd_N_noise;
4073 : Word16 k, kk, i;
4074 : Word16 N_noise;
4075 :
4076 : Word16 tmp_fx, ind, q1, q2, L20, flag;
4077 : Word16 noisevect_fx[34 * L_FRAME48k / 20], SS_fx[L_FRAME48k / 2];
4078 : Word16 *pt1, *pt2, *pt3, *pt4, *pt5;
4079 : const Word16 *pt6;
4080 : Word32 L_tmp;
4081 : const Word16 *sinq_tab;
4082 :
4083 : const Word16 *p_mdct_ola;
4084 : Word16 alignment_point;
4085 : // PMTE()
4086 1 : L20 = extract_h( L_mult( 1639, L ) ); /*L/20 */
4087 1 : IF( element_mode == EVS_MONO )
4088 : {
4089 0 : alignment_point = sub( shl( L, 1 ), i_mult2( 3, L20 ) );
4090 : }
4091 : ELSE
4092 : {
4093 1 : alignment_point = shl( L, 1 );
4094 : }
4095 :
4096 1 : IF( EQ_16( L, L_FRAME32k ) )
4097 : {
4098 1 : sinq_tab = sinq_32k;
4099 : }
4100 0 : ELSE IF( EQ_16( L, L_FRAME48k ) )
4101 : {
4102 0 : sinq_tab = sinq_48k;
4103 : }
4104 : ELSE
4105 : {
4106 0 : sinq_tab = sinq_16k;
4107 : }
4108 :
4109 1 : Copy( prevsynth_fx + sub( alignment_point, N ), noisevect_fx, N );
4110 :
4111 : /* Noise addition on full band */
4112 : /* residual */
4113 :
4114 1 : tmp_fx = s_min( N, L );
4115 1 : N_noise = shr( tmp_fx, 1 );
4116 1 : ind = sub( N, tmp_fx );
4117 1 : pt1 = noisevect_fx;
4118 1 : pt2 = pt1 + ind;
4119 1 : move16();
4120 1 : pt3 = &synthesis_fx[ind];
4121 1 : move16();
4122 221 : FOR( k = 0; k < tmp_fx; k++ )
4123 : {
4124 220 : ( *pt1++ ) = sub_sat( ( *pt2++ ), ( *pt3++ ) );
4125 220 : move16();
4126 : }
4127 :
4128 1 : IF( HqVoicing )
4129 : {
4130 0 : Scale_sig( noisevect_fx, N, -2 );
4131 : }
4132 :
4133 1 : kk = 0;
4134 1 : move16();
4135 1 : k = 0;
4136 1 : move16();
4137 1 : Rnd_N_noise = N_noise;
4138 1 : move16();
4139 :
4140 1 : ind = shl( L, 1 );
4141 1 : flag = ind;
4142 1 : move16();
4143 1 : pt5 = synthesis_fx;
4144 21 : WHILE( flag > 0 )
4145 : {
4146 20 : tmp_fx = Random( ni_seed_forfec );
4147 :
4148 20 : L_tmp = L_mac( 1503264768, tmp_fx, 9830 );
4149 20 : IF( EQ_16( kk, 0 ) )
4150 : {
4151 10 : L_tmp = L_mac( 1073741824, tmp_fx, 6554 );
4152 : }
4153 :
4154 20 : kk = sub( 1, kk );
4155 20 : tmp_fx = round_fx( L_tmp );
4156 20 : Rnd_N_noise = extract_h( L_mult( N_noise, tmp_fx ) ); /*Q0 */
4157 :
4158 :
4159 20 : tmp_fx = div_s( 1, Rnd_N_noise ); /*Q15 */
4160 20 : tmp_fx = round_fx( L_shl( L_mult( tmp_fx, 25736 ), 2 ) ); /*Q15 */
4161 :
4162 20 : sinq_fx( shr( tmp_fx, 1 ), shr( tmp_fx, 2 ), Rnd_N_noise, SS_fx );
4163 :
4164 20 : pt2 = &noisevect_fx[N_noise];
4165 20 : pt1 = pt2 - Rnd_N_noise;
4166 20 : pt3 = SS_fx;
4167 20 : pt4 = pt3 + sub( Rnd_N_noise, 1 );
4168 20 : tmp_fx = s_min( Rnd_N_noise, flag );
4169 1300 : FOR( i = 0; i < tmp_fx; i++ )
4170 : {
4171 1280 : L_tmp = L_mult( ( *pt1++ ), ( *pt3++ ) ); /*Qsynth+16 */
4172 1280 : L_tmp = L_mac_sat( L_tmp, ( *pt2++ ), ( *pt4-- ) ); /*Qsynth+16 */
4173 1280 : *pt5 = add_sat( *pt5, round_fx_sat( L_tmp ) );
4174 1280 : move16(); /*Qsynth */
4175 1280 : pt5++;
4176 : }
4177 20 : flag = sub( flag, tmp_fx );
4178 : }
4179 :
4180 1 : IF( element_mode == EVS_MONO )
4181 : {
4182 0 : kk = i_mult2( 7, L20 );
4183 0 : tmp_fx = i_mult2( 37, L20 );
4184 0 : p_mdct_ola = prevsynth_fx + tmp_fx;
4185 : }
4186 : ELSE
4187 : {
4188 1 : kk = NS2SA_FX2( L_mult0( L, FRAMES_PER_SEC ), N_ZERO_MDCT_NS );
4189 1 : p_mdct_ola = old_out + kk;
4190 : }
4191 :
4192 : /* overlappadd with the ms of valid mdct of the last frame */
4193 1 : tmp_fx = i_mult2( 3, L20 );
4194 1 : pt1 = &synthesis_fx[0];
4195 1 : pt6 = &p_mdct_ola[0];
4196 97 : FOR( k = 0; k < tmp_fx; k++ )
4197 : {
4198 96 : L_tmp = L_mult( *sinq_tab, *sinq_tab ); /*Q31 */
4199 96 : sinq_tab++;
4200 96 : q2 = round_fx( L_sub( 2147483647, L_tmp ) ); /*Q15 */
4201 96 : q1 = round_fx( L_tmp ); /*Q15 */
4202 96 : L_tmp = L_mult( ( *pt1 ), q1 ); /*Qsynth+16 */
4203 96 : L_tmp = L_add_sat( L_tmp, L_shr_sat( Mpy_32_16_1( L_deposit_h( *pt6++ ), q2 ), Q_old_out ) ); /*Qsynth+16 */
4204 96 : ( *pt1++ ) = round_fx_sat( L_tmp ); /*Qsynth */
4205 96 : move16();
4206 : }
4207 :
4208 1 : Copy( synthesis_fx, synthesis_fx + kk, sub( 2 * L, kk ) );
4209 1 : Copy( synthesis_fx + L, gapsynth_fx, L );
4210 1 : Copy( prevsynth_fx + sub( alignment_point, kk ), synthesis_fx, kk );
4211 1 : }
4212 :
4213 0 : static void fec_noise_filling_fx(
4214 : const Word16 *prevsynth_fx, /*Qsynth */
4215 : Word16 *synthesis_fx, /*Qsynth */
4216 : Word16 *ni_seed_forfec,
4217 : const Word16 L,
4218 : const Word16 N,
4219 : const Word16 HqVoicing,
4220 : Word16 *gapsynth_fx /*Qsynth */
4221 : )
4222 : {
4223 :
4224 : Word16 Rnd_N_noise;
4225 : Word16 k, kk, i;
4226 : Word16 N_noise;
4227 :
4228 : Word16 tmp_fx, ind, q1, q2, L20, flag;
4229 : Word16 noisevect_fx[34 * L_FRAME48k / 20], SS_fx[L_FRAME48k / 2];
4230 : Word16 *pt1, *pt2, *pt3, *pt4, *pt5;
4231 : const Word16 *pt6;
4232 : Word32 L_tmp;
4233 : const Word16 *sinq_tab;
4234 :
4235 0 : IF( EQ_16( L, L_FRAME32k ) )
4236 : {
4237 0 : sinq_tab = sinq_32k;
4238 : }
4239 0 : ELSE IF( EQ_16( L, L_FRAME48k ) )
4240 : {
4241 0 : sinq_tab = sinq_48k;
4242 : }
4243 : ELSE
4244 : {
4245 0 : sinq_tab = sinq_16k;
4246 : }
4247 :
4248 0 : L20 = extract_h( L_mult( 1639, L ) ); /*L/20 */
4249 :
4250 : /*N=47*L/20-delay_ind*decimatefator-6*L/20; */
4251 :
4252 0 : tmp_fx = sub( sub( shl( L, 1 ), i_mult2( 3, L20 ) ), N );
4253 0 : Copy( prevsynth_fx + tmp_fx, noisevect_fx, N );
4254 :
4255 : /* Noise addition on full band */
4256 : /* residual */
4257 :
4258 0 : tmp_fx = s_min( N, L );
4259 0 : N_noise = shr( tmp_fx, 1 );
4260 0 : ind = sub( N, tmp_fx );
4261 0 : pt1 = noisevect_fx;
4262 0 : pt2 = pt1 + ind;
4263 0 : move16();
4264 0 : pt3 = &synthesis_fx[ind];
4265 0 : move16();
4266 0 : FOR( k = 0; k < tmp_fx; k++ )
4267 : {
4268 0 : ( *pt1++ ) = sub_sat( ( *pt2++ ), ( *pt3++ ) );
4269 0 : move16();
4270 : }
4271 :
4272 0 : IF( HqVoicing )
4273 : {
4274 0 : Scale_sig( noisevect_fx, N, -2 );
4275 : }
4276 :
4277 0 : kk = 0;
4278 0 : move16();
4279 0 : k = 0;
4280 0 : move16();
4281 0 : Rnd_N_noise = N_noise;
4282 0 : move16();
4283 :
4284 0 : ind = shl( L, 1 );
4285 0 : flag = ind;
4286 0 : move16();
4287 0 : pt5 = synthesis_fx;
4288 0 : WHILE( flag > 0 )
4289 : {
4290 0 : tmp_fx = Random( ni_seed_forfec );
4291 :
4292 0 : L_tmp = L_mac( 1503264768, tmp_fx, 9830 );
4293 0 : if ( kk == 0 )
4294 : {
4295 0 : L_tmp = L_mac( 1073741824, tmp_fx, 6554 );
4296 : }
4297 :
4298 0 : kk = sub( 1, kk );
4299 0 : tmp_fx = round_fx( L_tmp );
4300 0 : Rnd_N_noise = extract_h( L_mult( N_noise, tmp_fx ) ); /*Q0 */
4301 :
4302 :
4303 0 : tmp_fx = div_s( 1, Rnd_N_noise ); /*Q15 */
4304 0 : tmp_fx = round_fx_sat( L_shl_sat( L_mult( tmp_fx, 25736 ), 2 ) ); /*Q15 */
4305 :
4306 0 : sinq_fx( shr( tmp_fx, 1 ), shr( tmp_fx, 2 ), Rnd_N_noise, SS_fx );
4307 :
4308 0 : pt2 = &noisevect_fx[N_noise];
4309 0 : pt1 = pt2 - Rnd_N_noise;
4310 0 : pt3 = SS_fx;
4311 0 : pt4 = pt3 + sub( Rnd_N_noise, 1 );
4312 0 : tmp_fx = s_min( Rnd_N_noise, flag );
4313 0 : FOR( i = 0; i < tmp_fx; i++ )
4314 : {
4315 0 : L_tmp = L_mult( ( *pt1++ ), ( *pt3++ ) ); /*Qsynth+16 */
4316 0 : L_tmp = L_mac_sat( L_tmp, ( *pt2++ ), ( *pt4-- ) ); /*Qsynth+16 */
4317 0 : *pt5 = add_sat( *pt5, round_fx_sat( L_tmp ) );
4318 0 : move16(); /*Qsynth */
4319 0 : pt5++;
4320 : }
4321 0 : flag = sub( flag, tmp_fx );
4322 : }
4323 :
4324 0 : q1 = i_mult2( 7, L20 );
4325 0 : q2 = i_mult2( 33, L20 );
4326 :
4327 0 : Copy( synthesis_fx, synthesis_fx + q1, q2 );
4328 0 : Copy( synthesis_fx + L, gapsynth_fx, L );
4329 0 : Copy( prevsynth_fx + sub( i_mult2( 37, L20 ), q1 ), synthesis_fx, q1 );
4330 0 : pt1 = &synthesis_fx[q1];
4331 0 : q2 = i_mult2( 37, L20 );
4332 0 : pt6 = &prevsynth_fx[q2];
4333 0 : tmp_fx = i_mult2( 3, L20 );
4334 :
4335 : /* overlappadd with the ms of valid mdct of the last frame */
4336 0 : FOR( k = 0; k < tmp_fx; k++ )
4337 : {
4338 0 : L_tmp = L_mult( *sinq_tab, *sinq_tab ); /*Q30 */
4339 0 : sinq_tab++;
4340 0 : q2 = round_fx( L_sub( 2147483647, L_tmp ) ); /*Q15 */
4341 0 : q1 = round_fx( L_tmp ); /*Q15 */
4342 0 : L_tmp = L_mult( ( *pt1 ), q1 ); /*Qsynth+16 */
4343 0 : L_tmp = L_mac( L_tmp, ( *pt6++ ), q2 ); /*Qsynth+16 */
4344 0 : ( *pt1++ ) = round_fx( L_tmp ); /*Qsynth */
4345 0 : move16();
4346 : }
4347 0 : }
4348 :
4349 1 : static void ivas_fec_alg_fx(
4350 : const Word16 *prevsynth, /*Qin */
4351 : const Word16 *prevsynth_LP, /*Qin */
4352 : Word16 *ni_seed_forfec,
4353 : Word32 *ecu_rec, /*Qin+16 (Qin+15 to be coherent witch other scaling) */
4354 : const Word16 output_frame,
4355 : const Word16 N,
4356 : const Word16 decimatefactor,
4357 : const Word16 HqVoicing,
4358 : Word16 *gapsynth, /*Qin */
4359 : const Word16 element_mode, /* i : IVAS element mode */
4360 : const Word16 *old_out,
4361 : const Word16 Q_old_out )
4362 : {
4363 : Word16 Nfft;
4364 : Word32 sum_Tf_abs;
4365 : Word16 Tfr[FEC_FFT_MAX_SIZE];
4366 : Word16 Tfi[FEC_FFT_MAX_SIZE];
4367 : Word16 Tf_abs[FEC_FFT_MAX_SIZE / 2];
4368 : Word16 synthesis[2 * L_FRAME48k];
4369 : Word16 exp;
4370 : Word16 n, Q;
4371 :
4372 1 : ivas_fec_ecu_dft_fx( prevsynth_LP, N, Tfr, Tfi, &sum_Tf_abs, Tf_abs, &Nfft, &exp, element_mode );
4373 :
4374 1 : sinusoidal_synthesis_fx( Tfr, Tfi, Tf_abs, N, output_frame, decimatefactor, Nfft, sum_Tf_abs, synthesis, HqVoicing, exp );
4375 :
4376 1 : ivas_fec_noise_filling_fx( prevsynth, synthesis, ni_seed_forfec, output_frame, i_mult2( N, decimatefactor ), HqVoicing, gapsynth, element_mode, old_out, Q_old_out );
4377 :
4378 1 : n = R1_48 - R2_48;
4379 1 : move16();
4380 :
4381 1 : test();
4382 1 : IF( EQ_16( output_frame, L_FRAME32k ) || EQ_16( output_frame, L_FRAME16k ) )
4383 : {
4384 1 : n = R1_16 - R2_16;
4385 1 : move16();
4386 :
4387 1 : if ( EQ_16( output_frame, L_FRAME32k ) )
4388 : {
4389 1 : n = 2 * N16_CORE_SW;
4390 1 : move16();
4391 : }
4392 : }
4393 1 : Q = 0;
4394 1 : move16();
4395 1 : wtda_fx( synthesis + sub( output_frame, n ), &Q, ecu_rec,
4396 : NULL,
4397 : NULL, ALDO_WINDOW, ALDO_WINDOW, output_frame ); /* return Q15 */
4398 :
4399 1 : return;
4400 : }
4401 :
4402 0 : static void fec_alg_fx(
4403 : const Word16 *prevsynth, /*Qin */
4404 : const Word16 *prevsynth_LP, /*Qin */
4405 : Word16 *ni_seed_forfec,
4406 : Word32 *ecu_rec, /*Qin+16 (Qin+15 to be coherent witch other scaling) */
4407 : const Word16 output_frame,
4408 : const Word16 N,
4409 : const Word16 decimatefactor,
4410 : const Word16 HqVoicing,
4411 : Word16 *gapsynth /*Qin */
4412 : )
4413 : {
4414 : Word16 Nfft;
4415 : Word32 sum_Tf_abs;
4416 : Word16 Tfr[FEC_FFT_MAX_SIZE];
4417 : Word16 Tfi[FEC_FFT_MAX_SIZE];
4418 : Word16 Tf_abs[FEC_FFT_MAX_SIZE / 2];
4419 : Word16 synthesis[2 * L_FRAME48k];
4420 : Word16 exp;
4421 : Word16 n, Q;
4422 :
4423 0 : fec_ecu_dft_fx( prevsynth_LP, N, Tfr, Tfi, &sum_Tf_abs, Tf_abs, &Nfft, &exp );
4424 :
4425 0 : sinusoidal_synthesis_fx( Tfr, Tfi, Tf_abs, N, output_frame, decimatefactor, Nfft, sum_Tf_abs, synthesis, HqVoicing, exp );
4426 :
4427 0 : fec_noise_filling_fx( prevsynth, synthesis, ni_seed_forfec, output_frame, i_mult2( N, decimatefactor ), HqVoicing, gapsynth );
4428 :
4429 0 : n = R1_48 - R2_48;
4430 0 : move16();
4431 :
4432 0 : test();
4433 0 : IF( EQ_16( output_frame, L_FRAME32k ) || EQ_16( output_frame, L_FRAME16k ) )
4434 : {
4435 0 : n = R1_16 - R2_16;
4436 0 : move16();
4437 :
4438 0 : if ( EQ_16( output_frame, L_FRAME32k ) )
4439 : {
4440 0 : n = 2 * N16_CORE_SW;
4441 0 : move16();
4442 : }
4443 : }
4444 0 : Q = 0;
4445 0 : move16();
4446 0 : wtda_fx( synthesis + sub( output_frame, n ), &Q, ecu_rec,
4447 : NULL,
4448 : NULL, ALDO_WINDOW, ALDO_WINDOW, output_frame ); /* return Q15 */
4449 :
4450 0 : return;
4451 : }
4452 :
4453 : /*--------------------------------------------------------------------------
4454 : * hq_phase_ecu_fx()
4455 : *
4456 : * Main routine for HQ phase ECU
4457 : *--------------------------------------------------------------------------*/
4458 :
4459 132 : static void ivas_hq_phase_ecu_fx(
4460 : const Word16 *prevsynth, /* i : buffer of previously synthesized signal Q0 */
4461 : Word32 *ecu_rec, /* o : reconstructed frame in tda domain */
4462 : Word16 *time_offs, /* i/o: Sample offset for consecutive frame losses Q0*/
4463 : Word16 *X_sav, /* i/o: Stored spectrum of prototype frame */
4464 : Word16 *Q_spec, /* i/o: Q value of stored spectrum */
4465 : Word16 *num_p, /* i/o: Number of identified peaks Q0 */
4466 : Word16 *plocs, /* i/o: Peak locations Q0 */
4467 : Word32 *plocsi, /* i/o: Interpolated peak locations Q16 */
4468 : const Word16 env_stab, /* i : Envelope stability parameter */
4469 : Word16 *last_fec, /* i/o: Flag for usage of pitch dependent ECU */
4470 : Word16 *ph_ecu_active, /* i : Phase ECU active flag */
4471 : const Word16 prev_bfi, /* i : indicating burst frame error */
4472 : const Word16 old_is_transient[2], /* i : flags indicating previous transient frames */
4473 : Word16 *mag_chg_1st, /* i/o: per band magnitude modifier for transients*/
4474 : Word16 *Xavg, /* i/o: Frequency group average gain to fade to Q0 */
4475 : Word16 *beta_mute, /* o : Factor for long-term mute Q15 */
4476 : const Word16 bwidth_fx, /* i : Encoded bandwidth */
4477 : const Word16 output_frame, /* i : frame length */
4478 : const Word16 pcorr,
4479 : const Word16 element_mode /* i : IVAS element mode */
4480 : )
4481 : {
4482 : Word16 lprot, offset;
4483 : Word16 mag_chg[LGW_MAX], ph_dith, X[L_PROT48k];
4484 : Word16 seed;
4485 : Word16 alpha[LGW_MAX], beta[LGW_MAX];
4486 :
4487 : const Word16 *old_dec;
4488 : Word16 noise_fac;
4489 : Word16 ph_ecu_lookahead;
4490 :
4491 132 : noise_fac = 32767; /* 1.0f in Q15 */
4492 132 : move16();
4493 :
4494 132 : IF( element_mode == EVS_MONO )
4495 : {
4496 0 : ph_ecu_lookahead = NS2SA_FX2( L_mult0( output_frame, FRAMES_PER_SEC ), PH_ECU_LOOKAHEAD_NS );
4497 0 : move16();
4498 : }
4499 : ELSE
4500 : {
4501 132 : ph_ecu_lookahead = 0;
4502 132 : move16();
4503 : }
4504 132 : IF( EQ_16( output_frame, L_FRAME48k ) )
4505 : {
4506 103 : lprot = L_PROT48k; /* 1536 = (2*output_frame)*1024/1280 */
4507 103 : move16();
4508 : }
4509 29 : ELSE IF( EQ_16( output_frame, L_FRAME32k ) )
4510 : {
4511 29 : lprot = L_PROT32k; /* 1024 */
4512 29 : move16();
4513 : }
4514 0 : ELSE IF( EQ_16( output_frame, L_FRAME16k ) )
4515 : {
4516 0 : lprot = 512;
4517 0 : move16();
4518 : }
4519 : ELSE
4520 : {
4521 0 : lprot = 256;
4522 0 : move16();
4523 : }
4524 :
4525 132 : test();
4526 132 : test();
4527 132 : test();
4528 132 : IF( prev_bfi == 0 || ( prev_bfi != 0 && *last_fec != 0 && ( EQ_16( *time_offs, output_frame ) ) ) )
4529 : {
4530 54 : test();
4531 54 : test();
4532 : #ifdef FIX_1179_USAN_PHASEECU
4533 54 : if ( !( prev_bfi != 0 && *last_fec != 0 && element_mode == EVS_MONO ) )
4534 : {
4535 54 : *time_offs = 0; /* IVAS reset of offset time counter, timeoffset variable later also used to calculate burst length */
4536 54 : move16();
4537 : }
4538 : #else
4539 : // PMT("verify condition compared to float")
4540 : if ( !( prev_bfi != 0 && *last_fec != 0 && element_mode == EVS_MONO ) )
4541 : {
4542 : *time_offs = 0;
4543 : move16();
4544 : }
4545 : #endif
4546 :
4547 54 : offset = add( sub( sub( shl( output_frame, 1 ), lprot ), *time_offs ), ph_ecu_lookahead );
4548 : #ifdef NONBE_FIX_1180_HQMDCT_PHECU_LT_MUTING
4549 54 : trans_ana_fx( prevsynth + offset, mag_chg, &ph_dith, mag_chg_1st, output_frame, *time_offs, env_stab,
4550 54 : *last_fec, element_mode, alpha, beta, beta_mute, Xavg );
4551 : #else
4552 : trans_ana_fx( prevsynth + offset, mag_chg, &ph_dith, mag_chg_1st, output_frame, *time_offs, env_stab,
4553 : *last_fec, alpha, beta, beta_mute, Xavg );
4554 : #endif
4555 :
4556 54 : ivas_spec_ana_fx( prevsynth + offset, plocs, plocsi, num_p, X_sav, output_frame, bwidth_fx, Q_spec, element_mode, &noise_fac, pcorr );
4557 :
4558 54 : test();
4559 54 : IF( prev_bfi != 0 && *last_fec != 0 )
4560 : {
4561 : #ifdef FIX_1179_USAN_PHASEECU
4562 0 : *time_offs = add_sat( *time_offs, output_frame ); /* when saturation is reached, this keeps the long term muting on */
4563 : #else
4564 : *time_offs = add( *time_offs, output_frame );
4565 : #endif
4566 0 : move16();
4567 : }
4568 : }
4569 : ELSE
4570 : {
4571 78 : *time_offs = add_sat( *time_offs, output_frame );
4572 78 : move16();
4573 78 : offset = sub( shl( output_frame, 1 ), lprot );
4574 : #ifdef NONBE_FIX_1180_HQMDCT_PHECU_LT_MUTING
4575 78 : trans_ana_fx( prevsynth + offset, mag_chg, &ph_dith, mag_chg_1st, output_frame, *time_offs, env_stab,
4576 : 0, element_mode, alpha, beta, beta_mute, Xavg );
4577 : #else
4578 : trans_ana_fx( prevsynth + offset, mag_chg, &ph_dith, mag_chg_1st, output_frame, *time_offs, env_stab,
4579 : 0, alpha, beta, beta_mute, Xavg );
4580 : #endif
4581 : }
4582 :
4583 132 : Copy( X_sav, X, lprot );
4584 :
4585 : /* seed for own_rand2 */
4586 132 : seed = *time_offs;
4587 132 : move16();
4588 132 : IF( *num_p > 0 )
4589 : {
4590 132 : seed = extract_l( L_add( L_deposit_l( seed ), L_deposit_l( plocs[*num_p - 1] ) ) );
4591 : }
4592 :
4593 132 : ivas_subst_spec_fx( plocs, plocsi, num_p, *time_offs, X, mag_chg, ph_dith, old_is_transient, output_frame, &seed,
4594 132 : alpha, beta, *beta_mute, Xavg, element_mode, ph_ecu_lookahead, noise_fac );
4595 :
4596 : /* reconstructed frame in tda domain */
4597 132 : old_dec = prevsynth + sub( shl( output_frame, 1 ), NS2SA_FX2( L_mult0( output_frame, FRAMES_PER_SEC ), N_ZERO_MDCT_NS ) );
4598 132 : ivas_rec_frame_fx( X, ecu_rec, output_frame, *Q_spec, old_dec, element_mode, num_p, plocs );
4599 :
4600 132 : *last_fec = 0;
4601 132 : move16();
4602 132 : *ph_ecu_active = 1;
4603 132 : move16();
4604 132 : }
4605 :
4606 0 : static void hq_phase_ecu_fx(
4607 : const Word16 *prevsynth, /* i : buffer of previously synthesized signal Q0 */
4608 : Word32 *ecu_rec, /* o : reconstructed frame in tda domain */
4609 : Word16 *time_offs, /* i/o: Sample offset for consecutive frame losses Q0*/
4610 : Word16 *X_sav, /* i/o: Stored spectrum of prototype frame */
4611 : Word16 *Q_spec, /* i/o: Q value of stored spectrum */
4612 : Word16 *num_p, /* i/o: Number of identified peaks Q0 */
4613 : Word16 *plocs, /* i/o: Peak locations Q0 */
4614 : Word32 *plocsi, /* i/o: Interpolated peak locations Q16 */
4615 : const Word16 env_stab, /* i : Envelope stability parameter */
4616 : Word16 *last_fec, /* i/o: Flag for usage of pitch dependent ECU */
4617 : Word16 *ph_ecu_active, /* i : Phase ECU active flag */
4618 : const Word16 prev_bfi, /* i : indicating burst frame error */
4619 : const Word16 old_is_transient[2], /* i : flags indicating previous transient frames */
4620 : Word16 *mag_chg_1st, /* i/o: per band magnitude modifier for transients*/
4621 : Word16 *Xavg, /* i/o: Frequency group average gain to fade to Q0 */
4622 : Word16 *beta_mute, /* o : Factor for long-term mute Q15 */
4623 : const Word16 bwidth_fx, /* i : Encoded bandwidth */
4624 : const Word16 output_frame /* i : frame length */
4625 : )
4626 : {
4627 : Word16 lprot, offset;
4628 : Word16 mag_chg[LGW_MAX], ph_dith, X[L_PROT48k];
4629 : Word16 seed;
4630 : Word16 alpha[LGW_MAX], beta[LGW_MAX];
4631 :
4632 0 : IF( EQ_16( output_frame, L_FRAME48k ) )
4633 : {
4634 0 : lprot = L_PROT48k; /* 1536 = (2*output_frame)*1024/1280 */
4635 0 : move16();
4636 : }
4637 0 : ELSE IF( EQ_16( output_frame, L_FRAME32k ) )
4638 : {
4639 0 : lprot = L_PROT32k; /* 1024 */
4640 0 : move16();
4641 : }
4642 0 : ELSE IF( output_frame == L_FRAME16k )
4643 : {
4644 0 : lprot = 512;
4645 0 : move16();
4646 : }
4647 : ELSE
4648 : {
4649 0 : lprot = 256;
4650 0 : move16();
4651 : }
4652 :
4653 0 : test();
4654 0 : test();
4655 0 : test();
4656 0 : IF( prev_bfi == 0 || ( prev_bfi != 0 && *last_fec != 0 && ( EQ_16( *time_offs, output_frame ) ) ) )
4657 : {
4658 0 : test();
4659 : #ifndef FIX_1179_USAN_PHASEECU
4660 : // PMT("verify condition compared to float")
4661 : #endif
4662 0 : if ( !( prev_bfi != 0 && *last_fec != 0 ) )
4663 : {
4664 0 : *time_offs = 0;
4665 0 : move16();
4666 : }
4667 :
4668 0 : offset = sub( sub( shl( output_frame, 1 ), lprot ), *time_offs );
4669 : #ifdef NONBE_FIX_1180_HQMDCT_PHECU_LT_MUTING
4670 0 : trans_ana_fx( prevsynth + offset, mag_chg, &ph_dith, mag_chg_1st, output_frame, *time_offs, env_stab,
4671 0 : *last_fec, EVS_MONO, alpha, beta, beta_mute, Xavg );
4672 : #else
4673 : trans_ana_fx( prevsynth + offset, mag_chg, &ph_dith, mag_chg_1st, output_frame, *time_offs, env_stab,
4674 : *last_fec, alpha, beta, beta_mute, Xavg );
4675 : #endif
4676 :
4677 0 : spec_ana_fx( prevsynth + offset, plocs, plocsi, num_p, X_sav, output_frame, bwidth_fx, Q_spec );
4678 :
4679 0 : test();
4680 0 : IF( prev_bfi != 0 && *last_fec != 0 )
4681 : {
4682 : #ifdef FIX_1179_USAN_PHASEECU
4683 0 : *time_offs = add_sat( *time_offs, output_frame );
4684 : #else
4685 : *time_offs = add( *time_offs, output_frame );
4686 : #endif
4687 0 : move16();
4688 : }
4689 : }
4690 : ELSE
4691 : {
4692 : #ifdef FIX_1179_USAN_PHASEECU
4693 0 : *time_offs = add_sat( *time_offs, output_frame );
4694 : #else
4695 : *time_offs = add( *time_offs, output_frame );
4696 : #endif
4697 0 : move16();
4698 :
4699 0 : offset = sub( shl( output_frame, 1 ), lprot );
4700 : #ifdef NONBE_FIX_1180_HQMDCT_PHECU_LT_MUTING
4701 0 : trans_ana_fx( prevsynth + offset, mag_chg, &ph_dith, mag_chg_1st, output_frame, *time_offs, env_stab,
4702 : 0, EVS_MONO, alpha, beta, beta_mute, Xavg );
4703 : #else
4704 : trans_ana_fx( prevsynth + offset, mag_chg, &ph_dith, mag_chg_1st, output_frame, *time_offs, env_stab,
4705 : 0, alpha, beta, beta_mute, Xavg );
4706 : #endif
4707 : }
4708 :
4709 0 : Copy( X_sav, X, lprot );
4710 :
4711 : /* seed for own_rand2 */
4712 0 : seed = *time_offs;
4713 0 : move16();
4714 0 : IF( *num_p > 0 )
4715 : {
4716 : #ifdef FIX_1179_USAN_PHASEECU
4717 0 : seed = add_sat( seed, plocs[*num_p - 1] );
4718 : #else
4719 : seed = add( seed, plocs[*num_p - 1] );
4720 : #endif
4721 : }
4722 :
4723 0 : subst_spec_fx( plocs, plocsi, num_p, *time_offs, X, mag_chg, ph_dith, old_is_transient, output_frame, &seed,
4724 0 : alpha, beta, *beta_mute, Xavg );
4725 :
4726 : /* reconstructed frame in tda domain */
4727 0 : rec_frame_fx( X, ecu_rec, output_frame, *Q_spec );
4728 :
4729 0 : *last_fec = 0;
4730 0 : move16();
4731 0 : *ph_ecu_active = 1;
4732 0 : move16();
4733 0 : }
4734 :
4735 :
4736 : /*--------------------------------------------------------------------------
4737 : * hq_ecu()
4738 : *
4739 : * Main routine for HQ ECU
4740 : *--------------------------------------------------------------------------*/
4741 :
4742 133 : void ivas_hq_ecu_fx(
4743 : const Word16 *prevsynth, /* i : buffer of previously synthesized signal Q0 */
4744 : Word32 *ecu_rec, /* o : reconstructed frame in tda domain */
4745 : Word16 *time_offs, /* i/o: Sample offset for consecutive frame losses Q0 */
4746 : Word16 *X_sav, /* i/o: Stored spectrum of prototype frame */
4747 : Word16 *Q_spec, /* i/o: Q value of stored spectrum */
4748 : Word16 *num_p, /* i/o: Number of identified peaks Q0 */
4749 : Word16 *plocs, /* i/o: Peak locations Q0 */
4750 : Word32 *plocsi, /* i/o: Interpolated peak locations Q16 */
4751 : const Word16 env_stab, /* i : Envelope stability parameter */
4752 : Word16 *last_fec, /* i/o: Flag for usage of pitch dependent ECU */
4753 : const Word16 ph_ecu_HqVoicing, /* i : HQ Voicing flag */
4754 : Word16 *ph_ecu_active, /* i : Phase ECU active flag */
4755 : Word16 *gapsynth, /* o : Gap synthesis */
4756 : const Word16 prev_bfi, /* i : indicating burst frame error */
4757 : const Word16 old_is_transient[2], /* i : flags indicating previous transient frames */
4758 : Word16 *mag_chg_1st, /* i/o: per band magnitude modifier for transients */
4759 : Word16 *Xavg, /* i/o: Frequency group average gain to fade to Q0 */
4760 : Word16 *beta_mute, /* o : Factor for long-term mute Q15 */
4761 : const Word16 output_frame, /* i : frame length */
4762 : Decoder_State *st_fx /* i/o: decoder state structure */
4763 : )
4764 : {
4765 : Word16 N;
4766 : Word16 decimatefactor;
4767 : Word16 corr; /*Q15 */
4768 : Word16 prevsynth_LP[2 * L_FRAME8k];
4769 : HQ_DEC_HANDLE hHQ_core;
4770 : const Word16 *fec_alg_input;
4771 : Word16 evs_mode_selection;
4772 : Word16 ivas_mode_selection;
4773 :
4774 133 : hHQ_core = st_fx->hHQ_core;
4775 133 : corr = 0;
4776 133 : move16();
4777 133 : IF( EQ_16( st_fx->element_mode, EVS_MONO ) )
4778 : {
4779 0 : fec_alg_input = prevsynth + NS2SA_FX2( L_mult0( output_frame, FRAMES_PER_SEC ), ACELP_LOOK_NS / 2 - PH_ECU_LOOKAHEAD_NS );
4780 : }
4781 : ELSE
4782 : {
4783 133 : fec_alg_input = prevsynth - NS2SA_FX2( L_mult0( output_frame, FRAMES_PER_SEC ), PH_ECU_LOOKAHEAD_NS );
4784 : }
4785 : /* init (values ar changed after) */
4786 :
4787 :
4788 : /* find pitch and R value */
4789 :
4790 133 : IF( !( LT_16( output_frame, L_FRAME16k ) ) )
4791 : {
4792 133 : fec_ecu_pitch_ivas_fx( fec_alg_input, prevsynth_LP, output_frame, &N, &corr, &decimatefactor, ph_ecu_HqVoicing );
4793 : }
4794 : ELSE
4795 : {
4796 0 : corr = 0;
4797 0 : decimatefactor = 4;
4798 0 : move16();
4799 0 : N = shr( output_frame, 2 );
4800 0 : move16(); /* just to avoid using uninitialized value in if statement below */
4801 : }
4802 :
4803 133 : test();
4804 133 : test();
4805 133 : test();
4806 133 : test();
4807 133 : test();
4808 133 : test();
4809 133 : test();
4810 133 : test();
4811 133 : test();
4812 133 : test();
4813 133 : test();
4814 133 : test();
4815 133 : test();
4816 133 : test();
4817 133 : test();
4818 :
4819 133 : evs_mode_selection = ( GE_32( st_fx->total_brate, 48000 ) && ( GE_16( output_frame, L_FRAME16k ) && !prev_bfi && ( !old_is_transient[0] || old_is_transient[1] ) &&
4820 399 : ( ph_ecu_HqVoicing || ( ( ( GT_16( hHQ_core->env_stab_plc_fx, 16384 ) /* 0.5 in Q15 */ ) && ( LT_16( corr, 19661 ) /* 0.6 in Q15 */ ) ) || ( LT_16( hHQ_core->env_stab_plc_fx, 16384 ) /* 0.5 in Q15 */ && ( GT_16( corr, 27853 ) /* 0.85 in Q15 */ ) ) ) ) ) ) ||
4821 266 : ( LT_32( st_fx->total_brate, 48000 ) && ( ( ph_ecu_HqVoicing || GT_16( corr, 27853 ) /* 0.85 in Q15 */ ) && !prev_bfi && ( !old_is_transient[0] || old_is_transient[1] ) ) );
4822 :
4823 133 : test();
4824 133 : ivas_mode_selection = ( LT_16( N, PH_ECU_N_LIMIT ) ) || ( LT_16( corr, PH_ECU_CORR_LIMIT_Q15 ) );
4825 133 : test();
4826 133 : test();
4827 133 : test();
4828 133 : test();
4829 133 : IF( ( ( st_fx->element_mode == EVS_MONO ) && evs_mode_selection ) ||
4830 : ( ( st_fx->element_mode != EVS_MONO ) && evs_mode_selection && ivas_mode_selection ) )
4831 : {
4832 1 : ivas_fec_alg_fx( fec_alg_input, prevsynth_LP, &st_fx->hHQ_core->ni_seed_forfec, ecu_rec, output_frame, N, decimatefactor, ph_ecu_HqVoicing, gapsynth, st_fx->element_mode, st_fx->hHQ_core->old_out_fx, st_fx->hHQ_core->Q_old_wtda );
4833 1 : *last_fec = 1;
4834 1 : move16();
4835 1 : *ph_ecu_active = 0;
4836 1 : move16();
4837 1 : *time_offs = output_frame;
4838 1 : move16();
4839 : }
4840 : ELSE
4841 : {
4842 132 : ivas_hq_phase_ecu_fx( prevsynth - NS2SA_FX2( L_mult0( output_frame, FRAMES_PER_SEC ), PH_ECU_LOOKAHEAD_NS ), ecu_rec, time_offs, X_sav, Q_spec, num_p, plocs, plocsi,
4843 : env_stab, last_fec, ph_ecu_active, prev_bfi, old_is_transient,
4844 132 : mag_chg_1st, Xavg, beta_mute, st_fx->bwidth, output_frame, corr, st_fx->element_mode );
4845 :
4846 132 : *last_fec = 0;
4847 132 : move16();
4848 132 : *ph_ecu_active = 1;
4849 132 : move16();
4850 : }
4851 133 : return;
4852 : }
4853 :
4854 0 : void hq_ecu_fx(
4855 : const Word16 *prevsynth, /* i : buffer of previously synthesized signal Q0 */
4856 : Word32 *ecu_rec, /* o : reconstructed frame in tda domain */
4857 : Word16 *time_offs, /* i/o: Sample offset for consecutive frame losses Q0 */
4858 : Word16 *X_sav, /* i/o: Stored spectrum of prototype frame */
4859 : Word16 *Q_spec, /* i/o: Q value of stored spectrum */
4860 : Word16 *num_p, /* i/o: Number of identified peaks Q0 */
4861 : Word16 *plocs, /* i/o: Peak locations Q0 */
4862 : Word32 *plocsi, /* i/o: Interpolated peak locations Q16 */
4863 : const Word16 env_stab, /* i : Envelope stability parameter */
4864 : Word16 *last_fec, /* i/o: Flag for usage of pitch dependent ECU */
4865 : const Word16 ph_ecu_HqVoicing, /* i : HQ Voicing flag */
4866 : Word16 *ph_ecu_active, /* i : Phase ECU active flag */
4867 : Word16 *gapsynth, /* o : Gap synthesis */
4868 : const Word16 prev_bfi, /* i : indicating burst frame error */
4869 : const Word16 old_is_transient[2], /* i : flags indicating previous transient frames */
4870 : Word16 *mag_chg_1st, /* i/o: per band magnitude modifier for transients */
4871 : Word16 *Xavg, /* i/o: Frequency group average gain to fade to Q0 */
4872 : Word16 *beta_mute, /* o : Factor for long-term mute Q15 */
4873 : const Word16 output_frame, /* i : frame length */
4874 : Decoder_State *st_fx /* i/o: decoder state structure */
4875 : )
4876 : {
4877 : Word16 N;
4878 : Word16 decimatefactor;
4879 : Word16 corr; /*Q15 */
4880 : Word16 prevsynth_LP[2 * L_FRAME8k];
4881 : /* init (values ar changed after) */
4882 0 : decimatefactor = 4;
4883 0 : move16();
4884 0 : N = shr( output_frame, 2 );
4885 :
4886 :
4887 : /* find pitch and R value */
4888 :
4889 0 : IF( !( LT_16( output_frame, L_FRAME16k ) ) )
4890 : {
4891 0 : fec_ecu_pitch_fx( prevsynth + NS2SA_FX2( L_mult0( output_frame, 50 ), ACELP_LOOK_NS / 2 - PH_ECU_LOOKAHEAD_NS ), prevsynth_LP, output_frame, &N, &corr, &decimatefactor, ph_ecu_HqVoicing );
4892 : }
4893 : ELSE
4894 : {
4895 0 : corr = 0;
4896 0 : move16(); /* just to avoid using uninitialized value in if statement below */
4897 : }
4898 :
4899 0 : test();
4900 0 : test();
4901 0 : test();
4902 0 : test();
4903 0 : test();
4904 0 : test();
4905 0 : test();
4906 0 : test();
4907 0 : test();
4908 0 : test();
4909 0 : test();
4910 0 : test();
4911 0 : test();
4912 0 : test();
4913 0 : test();
4914 0 : IF( ( GE_32( st_fx->total_brate, 48000 ) &&
4915 : ( GE_16( output_frame, L_FRAME16k ) && !prev_bfi && ( !old_is_transient[0] || old_is_transient[1] ) && ( NE_16( ph_ecu_HqVoicing, 0 ) || ( ( ( NE_16( st_fx->hHQ_core->env_stab_plc_fx, 0 ) ) && ( LT_16( corr, 19661 ) ) ) || ( !( NE_16( st_fx->hHQ_core->env_stab_plc_fx, 0 ) ) && ( GT_16( corr, 27853 ) ) ) ) ) ) ) ||
4916 : ( LT_32( st_fx->total_brate, 48000 ) && ( ( ph_ecu_HqVoicing || GT_16( corr, 27853 ) ) && !prev_bfi && ( !old_is_transient[0] || old_is_transient[1] ) ) ) )
4917 : {
4918 :
4919 0 : fec_alg_fx( prevsynth + NS2SA_FX2( L_mult0( output_frame, 50 ), ACELP_LOOK_NS / 2 - PH_ECU_LOOKAHEAD_NS ), prevsynth_LP, &st_fx->hHQ_core->ni_seed_forfec, ecu_rec, output_frame, N, decimatefactor, ph_ecu_HqVoicing, gapsynth );
4920 0 : *last_fec = 1;
4921 0 : move16();
4922 0 : *ph_ecu_active = 0;
4923 0 : move16();
4924 0 : *time_offs = output_frame;
4925 0 : move16();
4926 : }
4927 : ELSE
4928 : {
4929 0 : hq_phase_ecu_fx( prevsynth, ecu_rec, time_offs, X_sav, Q_spec, num_p, plocs, plocsi,
4930 : env_stab, last_fec, ph_ecu_active, prev_bfi, old_is_transient,
4931 0 : mag_chg_1st, Xavg, beta_mute, st_fx->bwidth, output_frame );
4932 : }
4933 0 : return;
4934 : }
4935 :
4936 : /*******************************************************************************
4937 : * The square root of x which MUST be 0.5 <= x < 1, i.e., x must be normalized.
4938 : * sqrt(x) is approximated by a polynomial of degree n.
4939 : *
4940 : * sqrt(x) = a0 x^n + a1 x^(n-1) + a2 x^(n-2) + ... + an
4941 : * = (...((a0 x + a1) x + a2) x + ...) x + an
4942 : *
4943 : * The coefficients can be readily obtained by the following open source Octave
4944 : * (or commercial Matlab) script:
4945 : * order = 2;
4946 : * N = 400;
4947 : * x = linspace(0.5, 1.0, N);
4948 : * y = sqrt(x);
4949 : * p = polyfit(x, y, order)
4950 : * z = polyval(p, x);
4951 : * err = y - z;
4952 : * plot(err);
4953 : ******************************************************************************/
4954 :
4955 28581 : static Word16 sqrt2ndOrder( /* o: in Q15 (2nd order least square approx.) */
4956 : const Word16 x /* i: x must be in between 0.5 and 1.0 (Q15). */
4957 : )
4958 : {
4959 : Word32 acc;
4960 : Word16 z;
4961 :
4962 28581 : acc = 1890205600L; /* 0.880195572812922 in Q31 */
4963 28581 : move32();
4964 28581 : z = mac_r( acc, x, -6506 ); /* -0.198537395405340 in Q15 */
4965 28581 : acc = 682030261L; /* 0.317595089462249 in Q31 */
4966 28581 : move32();
4967 28581 : z = mac_r( acc, z, x ); /* in Q15 */
4968 28581 : return z;
4969 : }
4970 :
4971 : /*-----------------------------------------------------------------------------
4972 : * windowing()
4973 : *
4974 : * Apply a symmetric Hamming or Hamming-Rectangular window to the signal.
4975 : * If the "rectLength" parameter is zero, it is Hamming window; otherwise, the
4976 : * rectLength signifies the length of the rectangular part of the Hamming-Rectangular
4977 : * window.
4978 : *--------------------------------------------------------------------------- */
4979 108 : static void windowing(
4980 : const Word16 *x, /* i: Input signal Qx*/
4981 : Word16 *y, /* o: Windowed output Qx*/
4982 : const Word16 *win, /* i: Window coefficients Q15*/
4983 : const Word16 rectLength, /* i: Offset in between the 1st and 2nd symmetric halves of the Hamming window */
4984 : const Word16 halfLength /* i: Half of the total length of a complete Hamming window. */
4985 : )
4986 : {
4987 : Word16 i;
4988 : Word16 *pY;
4989 : const Word16 *pX, *pW;
4990 108 : pX = x;
4991 108 : pW = win;
4992 108 : pY = y;
4993 17132 : FOR( i = 0; i < halfLength; i++ ) /* 1st symmetric half of the Hamming window */
4994 : {
4995 17024 : *pY++ = mult_r( *pX++, *pW++ );
4996 17024 : move16();
4997 : }
4998 108 : FOR( i = 0; i < rectLength; i++ ) /* If rectLength is zero, it's a pure Hamming window; otherwise Hamming-Rectangular. */
4999 : {
5000 0 : *pY++ = *pX++;
5001 0 : move16();
5002 : }
5003 17132 : FOR( i = 0; i < halfLength; i++ ) /* 2nd symmetric half of the Hamming window. */
5004 : {
5005 17024 : *pY++ = mult_r( *pX++, *( --pW ) );
5006 17024 : move16();
5007 : }
5008 108 : }
5009 :
5010 : /*-----------------------------------------------------------------------------
5011 : * windowing_ROM_optimized()
5012 : *
5013 : * The coefficients of the Hamming window are derived from the sine table
5014 : * shared with fft3_fx().
5015 : * The entire Hamming-Rectangular window is decomposed into 5 segments:
5016 : * 1. 1st half of the left half of the Hamming window
5017 : * 2. 2nd half of the left half of the Hamming window
5018 : * 3. The flat part of the rectangular region
5019 : * 4. 1st half of the right half of the Hamming window
5020 : * 5. 2nd half of the right half of the Hamming window
5021 : *----------------------------------------------------------------------------*/
5022 0 : static void windowing_ROM_optimized(
5023 : const Word16 *x, /* i: Input signal Qin*/
5024 : Word16 *y, /* o: Windowed output Qin*/
5025 : const Word16 downSamples, /* i: Offset in accessing the sine table. */
5026 : const Word16 rectLength, /* i: Length of the rectangular portion (excluding the Hamming window part) */
5027 : const Word16 halfLength /* i: Half of the total length of the Hamming (excluding rectangular part) window */
5028 : )
5029 : {
5030 : Word16 i, hamm, quarterLen, initOffset;
5031 : Word16 *pY;
5032 : const Word16 *pX, *pSine;
5033 : Word32 acc;
5034 :
5035 0 : quarterLen = shr( halfLength, 1 ); /* 1/4 length of the entire Hamming (excluding the rectangular part) window. */
5036 0 : initOffset = add( T_SIN_PI_2, shr( downSamples, 1 ) );
5037 0 : pSine = sincos_t_rad3_fx + initOffset; // Q15
5038 0 : pX = x;
5039 0 : pY = y;
5040 :
5041 : /* 1st half of the left half of the Hamming window. */
5042 0 : FOR( i = 0; i < quarterLen; i++ )
5043 : {
5044 0 : pSine -= downSamples; /* Decrement address counter */
5045 0 : acc = L_deposit_h( FEC_HQ_WIN_A0 ); /* Derive the Hamming window coefficient from the sine table. Q31*/
5046 0 : hamm = msu_r( acc, *pSine, FEC_HQ_WIN_A1 ); // Q15
5047 0 : *pY++ = mult_r( hamm, *pX++ ); // Qin
5048 0 : move16();
5049 : }
5050 :
5051 : /* 2nd half of the left half of the Hamming window. */
5052 0 : FOR( i = 0; i < quarterLen; i++ )
5053 : {
5054 0 : acc = L_deposit_h( FEC_HQ_WIN_A0 );
5055 0 : hamm = mac_r_sat( acc, *pSine, FEC_HQ_WIN_A1 );
5056 0 : *pY++ = mult_r( hamm, *pX++ );
5057 0 : move16();
5058 0 : pSine += downSamples; /* Increment address counter */
5059 : }
5060 :
5061 : /* The rectangular flat region */
5062 0 : FOR( i = 0; i < rectLength; i++ )
5063 : {
5064 0 : *pY++ = *pX++;
5065 0 : move16();
5066 : }
5067 :
5068 : /* 1st half of the right half of the Hamming window. */
5069 0 : FOR( i = 0; i < quarterLen; i++ )
5070 : {
5071 0 : pSine -= downSamples; /* Decrement address counter */
5072 0 : acc = L_deposit_h( FEC_HQ_WIN_A0 ); // Q31
5073 0 : hamm = mac_r_sat( acc, *pSine, FEC_HQ_WIN_A1 ); // Q15
5074 0 : *pY++ = mult_r( hamm, *pX++ );
5075 0 : move16();
5076 : }
5077 :
5078 : /* 2nd half of the right half of the Hamming window. */
5079 0 : FOR( i = 0; i < quarterLen; i++ )
5080 : {
5081 0 : acc = L_deposit_h( FEC_HQ_WIN_A0 );
5082 0 : hamm = msu_r( acc, *pSine, FEC_HQ_WIN_A1 );
5083 0 : *pY++ = mult_r( hamm, *pX++ );
5084 0 : move16();
5085 0 : pSine += downSamples; /* Increment address counter */
5086 : }
5087 0 : }
|