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