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