Line data Source code
1 : /*====================================================================================
2 : EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
3 : ====================================================================================*/
4 :
5 : #define _USE_MATH_DEFINES
6 :
7 : #include <assert.h>
8 : #include <stdint.h>
9 : #include "options.h"
10 : #include "cnst.h"
11 : #include "rom_basop_util.h"
12 : #include "rom_com.h"
13 : #include "basop_util.h"
14 : #include "prot_fx.h"
15 : #include "ivas_prot_fx.h"
16 :
17 : /*---------------------------------------------------------------------*
18 : * Local function prototypes
19 : *---------------------------------------------------------------------*/
20 : static void calcPseudoSpec( const Word32 *mdctSpec, const Word16 mdctSpec_exp, const Word16 nSamples, Word16 floorPowerSpectrum, Word32 *powerSpec, Word16 *powerSpec_exp );
21 : static void getEnvelope( const Word16 nSamples, const Word32 *powerSpec, Word16 F0, Word32 *envelope, Word32 *smoothedSpectrum );
22 : static void GetF0( Word16 const nSamples, Word16 const nSamplesCore, Word32 const *const powerSpectrum, Word32 const pitchLag, Word16 *const pOrigF0, Word16 *const pF0 );
23 : static void ivas_GetF0_fx( Word16 const nSamples, Word16 const nSamplesCore, Word32 const *const powerSpectrum, Word32 const pitchLag, Word16 *const pOrigF0, Word16 *const pF0 );
24 : static void findStrongestHarmonics( const Word16 nSamples, const Word32 *powerSpectrum, const Word16 F0, const Word16 nTotalHarmonics, Word16 *pHarmonicIndexes, Word16 *pnHarmonics );
25 : static void CorrectF0( const Word16 *pHarmonicIndexes, const Word16 nHarmonics, Word16 *pF0 );
26 : static void ivas_CorrectF0_fx( const Word16 *pHarmonicIndexes, const Word16 nHarmonics, Word16 *pF0 );
27 : static void findCandidates( const Word16 nSamples, const Word32 *MDCTSpectrum, const Word16 MDCTSpectrum_exp, Word16 *thresholdModificationNew, Word16 floorPowerSpectrum );
28 : static void modifyThreshold( Word16 i, Word16 F0, Word16 threshold, Word16 *thresholdModification );
29 : static void modifyThresholds( Word16 F0, Word16 origF0, Word16 *thresholdModification );
30 : static void RefineThresholdsUsingPitch( const Word16 nSamples, const Word16 nSamplesCore, const Word32 powerSpectrum[], const Word32 lastPitchLag, const Word32 currentPitchLag, Word16 *pF0, Word16 *thresholdModification );
31 : static void ivas_RefineThresholdsUsingPitch_fx( const Word16 nSamples, const Word16 nSamplesCore, const Word32 powerSpectrum[], const Word32 lastPitchLag, const Word32 currentPitchLag, Word16 *pF0, Word16 *thresholdModification );
32 : static void findTonalComponents( Word16 *indexOfTonalPeak, Word16 *lowerIndex, Word16 *upperIndex, Word16 *numIndexes, Word16 nSamples, const Word32 *powerSpectrum, Word16 F0, Word16 *thresholdModification, Word16 element_mode );
33 : static void ivas_findTonalComponents_fx( Word16 *indexOfTonalPeak, Word16 *lowerIndex, Word16 *upperIndex, Word16 *numIndexes, Word16 nSamples, const Word32 *powerSpectrum, const Word16 powerSpectrum_e, Word16 F0, Word16 *thresholdModification, Word16 element_mode );
34 :
35 : /*-------------------------------------------------------------------*
36 : * DetectTonalComponents()
37 : *
38 : * Detect tonal components in the lastMDCTSpectrum, use
39 : * secondLastPowerSpectrum for the precise location of the peaks and
40 : * store them in indexOfTonalPeak. Updates lowerIndex, upperIndex,
41 : * pNumIndexes accordingly.
42 : *-------------------------------------------------------------------*/
43 :
44 1425 : void ivas_DetectTonalComponents_fx(
45 : Word16 indexOfTonalPeak[], /*Q0*/
46 : Word16 lowerIndex[], /*Q0*/
47 : Word16 upperIndex[], /*Q0*/
48 : Word16 *pNumIndexes, /*Q0*/
49 : const Word32 lastPitchLag, /*Qx*/
50 : const Word32 currentPitchLag, /*Qx*/
51 : const Word16 lastMDCTSpectrum[],
52 : const Word16 lastMDCTSpectrum_exp,
53 : const Word16 scaleFactors[],
54 : const Word16 scaleFactors_exp[],
55 : const Word16 scaleFactors_max_e,
56 : const Word32 secondLastPowerSpectrum[], /*Q31-secondLastPowerSpectrum_e*/
57 : const Word16 secondLastPowerSpectrum_e,
58 : const Word16 nSamples,
59 : const Word16 nSamplesCore,
60 : Word16 floorPowerSpectrum, /* i: lower limit for power spectrum bins Q0*/
61 : const PsychoacousticParameters *psychParamsCurrent,
62 : Word16 element_mode /* i: element mode */
63 : )
64 : {
65 : Word16 F0;
66 : Word16 thresholdModification[L_FRAME_MAX], lastMDCTSpect_exp;
67 : Word32 pScaledMdctSpectrum[L_FRAME_MAX];
68 : Word16 nBands;
69 : Word32 sns_int_scf_fx[FDNS_NPTS]; /*Q16*/
70 : Word16 q_pScaledMdctSpectrum;
71 :
72 1425 : set32_fx( pScaledMdctSpectrum, 0, L_FRAME_MAX );
73 :
74 751351 : FOR( Word16 i = 0; i < nSamples; i++ )
75 : {
76 749926 : pScaledMdctSpectrum[i] = L_shl( lastMDCTSpectrum[i], 16 ); /*15-lastMDCTSpectrum_exp+16 -> 31 - lastMDCTSpectrum_exp*/
77 749926 : move32();
78 : }
79 92625 : FOR( Word16 i = 0; i < FDNS_NPTS; i++ )
80 : {
81 91200 : sns_int_scf_fx[i] = L_shl_sat( scaleFactors[i], add( 1, scaleFactors_exp[i] ) ); // Q16
82 91200 : move32();
83 : }
84 1425 : IF( psychParamsCurrent == NULL )
85 : {
86 697 : nBands = FDNS_NPTS;
87 697 : move16();
88 : // PMT("add nBands argument to mdct_shaping_16")
89 :
90 697 : mdct_shaping_16( lastMDCTSpectrum, nSamplesCore, nSamples, scaleFactors, scaleFactors_exp, scaleFactors_max_e, pScaledMdctSpectrum );
91 697 : lastMDCTSpect_exp = add( lastMDCTSpectrum_exp, scaleFactors_max_e );
92 : }
93 : ELSE
94 : {
95 728 : q_pScaledMdctSpectrum = sub( 31, lastMDCTSpectrum_exp );
96 728 : sns_shape_spectrum_fx( pScaledMdctSpectrum, &q_pScaledMdctSpectrum, psychParamsCurrent, sns_int_scf_fx, 16, nSamplesCore, NULL );
97 728 : q_pScaledMdctSpectrum = add( q_pScaledMdctSpectrum, 1 );
98 728 : Word16 tmp_e = sub( 31, q_pScaledMdctSpectrum );
99 728 : nBands = psychParamsCurrent->nBands;
100 728 : move16();
101 : // till nSamplesCore different Q and nSamples - nSamplesCore in different Q
102 728 : Scale_sig32( pScaledMdctSpectrum + nSamplesCore, sub( nSamples, nSamplesCore ), sub( lastMDCTSpectrum_exp, tmp_e ) ); /*q_pScaledMdctSpectrum+lastMDCTSpectrum_exp-tmp_e*/
103 728 : lastMDCTSpect_exp = sub( 31, q_pScaledMdctSpectrum );
104 :
105 119351 : FOR( Word16 i = nSamplesCore; i < nSamples; ++i )
106 : {
107 118623 : Word64 tmp = W_mult_32_32( pScaledMdctSpectrum[i], sns_int_scf_fx[nBands - 1] ); /*q_pScaledMdctSpectrum+16+1*/
108 118623 : pScaledMdctSpectrum[i] = W_extract_h( W_shl( tmp, Q15 ) ); /*q_pScaledMdctSpectrum*/
109 118623 : move32();
110 : }
111 : }
112 :
113 : /* Guard bit */
114 1425 : lastMDCTSpect_exp = add( lastMDCTSpect_exp, 1 );
115 1425 : scale_sig32( pScaledMdctSpectrum, nSamples, -1 ); /*q_pScaledMdctSpectrum - 1*/
116 :
117 : /* Find peak candidates in the last frame. */
118 1425 : findCandidates( nSamples, pScaledMdctSpectrum, lastMDCTSpect_exp, thresholdModification, floorPowerSpectrum );
119 :
120 : /* Refine peak candidates using the pitch information */
121 1425 : ivas_RefineThresholdsUsingPitch_fx( nSamples, nSamplesCore, secondLastPowerSpectrum, lastPitchLag, currentPitchLag, &F0, thresholdModification );
122 :
123 : /* Find peaks in the second last frame */
124 1425 : ivas_findTonalComponents_fx( indexOfTonalPeak, lowerIndex, upperIndex, pNumIndexes, nSamples, secondLastPowerSpectrum, secondLastPowerSpectrum_e, F0, thresholdModification, element_mode );
125 1425 : }
126 :
127 0 : void DetectTonalComponents(
128 : Word16 indexOfTonalPeak[], /*Q0*/
129 : Word16 lowerIndex[], /*Q0*/
130 : Word16 upperIndex[], /*Q0*/
131 : Word16 *pNumIndexes, /*Q0*/
132 : const Word32 lastPitchLag, /*Qx*/
133 : const Word32 currentPitchLag, /*Qx*/
134 : const Word16 lastMDCTSpectrum[],
135 : const Word16 lastMDCTSpectrum_exp,
136 : const Word16 scaleFactors[],
137 : const Word16 scaleFactors_exp[],
138 : const Word16 scaleFactors_max_e,
139 : const Word32 secondLastPowerSpectrum[], /*Qx*/
140 : const Word16 nSamples,
141 : const Word16 nSamplesCore,
142 : Word16 floorPowerSpectrum, /* i: lower limit for power spectrum bins Q0*/
143 : Word16 element_mode
144 : #ifdef IVAS_CODE_MDCT_GSHAPE
145 : ,
146 : const PsychoacousticParameters *psychParamsCurrent
147 : #endif
148 : )
149 : {
150 : Word16 F0;
151 : Word16 thresholdModification[L_FRAME_MAX], lastMDCTSpect_exp;
152 : Word32 pScaledMdctSpectrum[L_FRAME_MAX];
153 : #ifdef IVAS_CODE_MDCT_GSHAPE
154 : Word16 nBands;
155 : IF( psychParamsCurrent == NULL )
156 : {
157 : nBands = FDNS_NPTS;
158 : PMT( "add nBands argument to mdct_shaping_16" )
159 : #endif
160 :
161 0 : mdct_shaping_16( lastMDCTSpectrum, nSamplesCore, nSamples, scaleFactors, scaleFactors_exp, scaleFactors_max_e, pScaledMdctSpectrum );
162 : #ifdef IVAS_CODE_MDCT_GSHAPE
163 : }
164 : ELSE
165 : {
166 : sns_shape_spectrum( pScaledMdctSpectrum, psychParamsCurrent, scaleFactors, nSamplesCore );
167 : nBands = psychParamsCurrent->nBands;
168 : }
169 : #endif
170 :
171 0 : lastMDCTSpect_exp = add( lastMDCTSpectrum_exp, scaleFactors_max_e );
172 :
173 : /* Find peak candidates in the last frame. */
174 0 : findCandidates( nSamples, pScaledMdctSpectrum, lastMDCTSpect_exp, thresholdModification, floorPowerSpectrum );
175 :
176 : /* Refine peak candidates using the pitch information */
177 0 : RefineThresholdsUsingPitch( nSamples, nSamplesCore, secondLastPowerSpectrum, lastPitchLag, currentPitchLag, &F0, thresholdModification );
178 :
179 : /* Find peaks in the second last frame */
180 0 : findTonalComponents( indexOfTonalPeak, lowerIndex, upperIndex, pNumIndexes, nSamples, secondLastPowerSpectrum, F0, thresholdModification, element_mode );
181 0 : }
182 :
183 : /*-------------------------------------------------------------------*
184 : * RefineTonalComponents()
185 : *
186 : *-------------------------------------------------------------------*/
187 : /* When called, the tonal components are already stored in
188 : * indexOfTonalPeak. Detect tonal components in the lastMDCTSpectrum,
189 : * use secondLastPowerSpectrum for the precise location of the peaks and
190 : * then keep in indexOfTonalPeak only the tonal components that are
191 : * again detected Updates indexOfTonalPeak, lowerIndex, upperIndex,
192 : * phaseDiff, phases, pNumIndexes accordingly. */
193 0 : void RefineTonalComponents(
194 : Word16 indexOfTonalPeak[], /*Q0*/
195 : Word16 lowerIndex[], /*Q0*/
196 : Word16 upperIndex[], /*Q0*/
197 : Word16 phaseDiff[], /*Q12*/
198 : Word16 phases[], /*Q13*/
199 : Word16 *pNumIndexes, /*Q0*/
200 : const Word32 lastPitchLag, /*Qx*/
201 : const Word32 currentPitchLag, /*Qx*/
202 : const Word16 lastMDCTSpectrum[],
203 : const Word16 lastMDCTSpectrum_exp,
204 : const Word16 scaleFactors[],
205 : const Word16 scaleFactors_exp[],
206 : const Word16 scaleFactors_max_e,
207 : const Word32 secondLastPowerSpectrum[], /*Qx*/
208 : const Word16 nSamples,
209 : const Word16 nSamplesCore,
210 : const Word16 floorPowerSpectrum, /* i: lower limit for power spectrum bins Q0*/
211 : Word16 element_mode
212 : #ifdef IVAS_CODE_MDCT_GSHAPE
213 : ,
214 : const PsychoacousticParameters *psychParamsCurrent
215 : #endif
216 : )
217 : {
218 : Word16 newIndexOfTonalPeak[MAX_NUMBER_OF_IDX]; /*Q0*/
219 : Word16 newLowerIndex[MAX_NUMBER_OF_IDX]; /*Q0*/
220 : Word16 newUpperIndex[MAX_NUMBER_OF_IDX]; /*Q0*/
221 : Word16 newNumIndexes, nPreservedPeaks;
222 : Word16 iNew, iOld, j;
223 : Word16 *pOldPhase, *pNewPhase;
224 :
225 :
226 0 : DetectTonalComponents( newIndexOfTonalPeak, newLowerIndex, newUpperIndex, &newNumIndexes, lastPitchLag, currentPitchLag, lastMDCTSpectrum,
227 : lastMDCTSpectrum_exp, scaleFactors, scaleFactors_exp, scaleFactors_max_e, secondLastPowerSpectrum, nSamples, nSamplesCore, floorPowerSpectrum, element_mode
228 : #ifdef IVAS_CODE_MDCT_GSHAPE
229 : ,
230 : psychParamsCurrent
231 : #endif
232 : );
233 :
234 0 : nPreservedPeaks = 0;
235 0 : move16();
236 0 : iNew = 0;
237 0 : move16();
238 0 : pOldPhase = phases; /*Q13*/
239 0 : pNewPhase = phases; /*Q13*/
240 :
241 0 : FOR( iOld = 0; iOld < *pNumIndexes; iOld++ )
242 : {
243 : /* We don't want that the old peak index is at the border of the new peak region, that is why >= newUpperIndex and > newLowerIndex */
244 0 : test();
245 0 : WHILE( LT_16( iNew, newNumIndexes ) && GE_16( indexOfTonalPeak[iOld], newUpperIndex[iNew] ) )
246 : {
247 0 : iNew = add( iNew, 1 );
248 : }
249 :
250 0 : test();
251 0 : IF( LT_16( iNew, newNumIndexes ) && GT_16( indexOfTonalPeak[iOld], newLowerIndex[iNew] ) )
252 : {
253 0 : newIndexOfTonalPeak[nPreservedPeaks] = indexOfTonalPeak[iOld]; /*Q0*/
254 0 : move16();
255 0 : newLowerIndex[nPreservedPeaks] = lowerIndex[iOld]; /*Q0*/
256 0 : move16();
257 0 : newUpperIndex[nPreservedPeaks] = upperIndex[iOld]; /*Q0*/
258 0 : move16();
259 0 : phaseDiff[nPreservedPeaks] = phaseDiff[iOld]; /*Q12*/
260 0 : move16();
261 :
262 0 : FOR( j = lowerIndex[iOld]; j <= upperIndex[iOld]; j++ )
263 : {
264 0 : *pNewPhase++ = *pOldPhase++; /*Q13*/
265 0 : move16();
266 : }
267 0 : nPreservedPeaks = add( nPreservedPeaks, 1 );
268 : }
269 : ELSE
270 : {
271 0 : pOldPhase += sub( upperIndex[iOld], add( lowerIndex[iOld], 1 ) ); /*Q13*/
272 : }
273 : }
274 :
275 0 : FOR( iNew = 0; iNew < nPreservedPeaks; iNew++ )
276 : {
277 0 : indexOfTonalPeak[iNew] = newIndexOfTonalPeak[iNew]; /*Q0*/
278 0 : move16();
279 0 : lowerIndex[iNew] = newLowerIndex[iNew]; /*Q0*/
280 0 : move16();
281 0 : upperIndex[iNew] = newUpperIndex[iNew]; /*Q0*/
282 0 : move16();
283 : }
284 0 : *pNumIndexes = nPreservedPeaks; /*Q0*/
285 0 : move16();
286 0 : return;
287 : }
288 :
289 0 : void ivas_RefineTonalComponents_fx(
290 : Word16 indexOfTonalPeak[], /*Q0*/
291 : Word16 lowerIndex[], /*Q0*/
292 : Word16 upperIndex[], /*Q0*/
293 : Word16 phaseDiff[], /*Q12*/
294 : Word16 phases[], /*Q13*/
295 : Word16 *pNumIndexes, /*Q0*/
296 : const Word32 lastPitchLag, /*Qx*/
297 : const Word32 currentPitchLag, /*Qx*/
298 : const Word16 lastMDCTSpectrum[],
299 : const Word16 lastMDCTSpectrum_exp,
300 : const Word16 scaleFactors[],
301 : const Word16 scaleFactors_exp[],
302 : const Word16 scaleFactors_max_e,
303 : const Word32 secondLastPowerSpectrum[], /*Q31-secondLastPowerSpectrum_e*/
304 : const Word16 secondLastPowerSpectrum_e,
305 : const Word16 nSamples,
306 : const Word16 nSamplesCore,
307 : const Word16 floorPowerSpectrum, /* i: lower limit for power spectrum bins Q0*/
308 : Word16 element_mode,
309 : const PsychoacousticParameters *psychParamsCurrent )
310 : {
311 : Word16 newIndexOfTonalPeak[MAX_NUMBER_OF_IDX]; /*Q0*/
312 : Word16 newLowerIndex[MAX_NUMBER_OF_IDX]; /*Q0*/
313 : Word16 newUpperIndex[MAX_NUMBER_OF_IDX]; /*Q0*/
314 : Word16 newNumIndexes, nPreservedPeaks;
315 : Word16 iNew, iOld, j;
316 : Word16 *pOldPhase, *pNewPhase;
317 :
318 :
319 0 : ivas_DetectTonalComponents_fx( newIndexOfTonalPeak, newLowerIndex, newUpperIndex, &newNumIndexes, lastPitchLag, currentPitchLag, lastMDCTSpectrum,
320 : lastMDCTSpectrum_exp, scaleFactors, scaleFactors_exp, scaleFactors_max_e, secondLastPowerSpectrum, secondLastPowerSpectrum_e, nSamples, nSamplesCore, floorPowerSpectrum,
321 : psychParamsCurrent, element_mode );
322 :
323 0 : nPreservedPeaks = 0;
324 0 : move16();
325 0 : iNew = 0;
326 0 : move16();
327 0 : pOldPhase = phases; /*Q13*/
328 0 : pNewPhase = phases; /*Q13*/
329 :
330 0 : FOR( iOld = 0; iOld < *pNumIndexes; iOld++ )
331 : {
332 : /* We don't want that the old peak index is at the border of the new peak region, that is why >= newUpperIndex and > newLowerIndex */
333 0 : test();
334 0 : WHILE( LT_16( iNew, newNumIndexes ) && GE_16( indexOfTonalPeak[iOld], newUpperIndex[iNew] ) )
335 : {
336 0 : iNew = add( iNew, 1 );
337 : }
338 :
339 0 : test();
340 0 : IF( LT_16( iNew, newNumIndexes ) && GT_16( indexOfTonalPeak[iOld], newLowerIndex[iNew] ) )
341 : {
342 0 : newIndexOfTonalPeak[nPreservedPeaks] = indexOfTonalPeak[iOld]; /*Q0*/
343 0 : move16();
344 0 : newLowerIndex[nPreservedPeaks] = lowerIndex[iOld]; /*Q0*/
345 0 : move16();
346 0 : newUpperIndex[nPreservedPeaks] = upperIndex[iOld]; /*Q0*/
347 0 : move16();
348 0 : phaseDiff[nPreservedPeaks] = phaseDiff[iOld]; /*Q12*/
349 0 : move16();
350 :
351 0 : FOR( j = lowerIndex[iOld]; j <= upperIndex[iOld]; j++ )
352 : {
353 0 : *pNewPhase++ = *pOldPhase++; /*Q13*/
354 0 : move16();
355 : }
356 0 : nPreservedPeaks = add( nPreservedPeaks, 1 );
357 : }
358 : ELSE
359 : {
360 0 : pOldPhase += sub( upperIndex[iOld], add( lowerIndex[iOld], 1 ) ); /*Q13*/
361 : }
362 : }
363 :
364 0 : FOR( iNew = 0; iNew < nPreservedPeaks; iNew++ )
365 : {
366 0 : indexOfTonalPeak[iNew] = newIndexOfTonalPeak[iNew]; /*Q0*/
367 0 : move16();
368 0 : lowerIndex[iNew] = newLowerIndex[iNew]; /*Q0*/
369 0 : move16();
370 0 : upperIndex[iNew] = newUpperIndex[iNew]; /*Q0*/
371 0 : move16();
372 : }
373 0 : *pNumIndexes = nPreservedPeaks; /*Q0*/
374 0 : move16();
375 0 : return;
376 : }
377 : /*-------------------------------------------------------------------*
378 : * Local functions
379 : *-------------------------------------------------------------------*/
380 1425 : static void calcPseudoSpec(
381 : const Word32 *mdctSpec, /* i: MDCT spectrum */
382 : const Word16 mdctSpec_exp, /* i: exponent of MDCT spectrum */
383 : const Word16 nSamples, /* i: frame size */
384 : Word16 floorPowerSpectrum, /* i: lower limit for power spectrum bins Q0*/
385 : Word32 *powerSpec, /* o: estimated power spectrum */
386 : Word16 *powerSpec_exp /* o: exponent of estimated power spectrum */
387 : )
388 : {
389 : Word16 k;
390 : Word32 x, L_tmp, L_tmp_floor;
391 : Word16 tmp_loop;
392 :
393 :
394 1425 : *powerSpec_exp = add( add( mdctSpec_exp, mdctSpec_exp ), 5 );
395 1425 : move16();
396 :
397 1425 : k = sub( 31, *powerSpec_exp );
398 : /* If the signal is bellow floor, special care is needed for *powerSpec_exp */
399 1425 : IF( LT_16( add( 16 - 3, norm_s( floorPowerSpectrum ) ), k ) ) /*extra 3 bits of headroom for MA filter in getEnvelope*/
400 : {
401 72 : k = add( 16 - 3, norm_s( floorPowerSpectrum ) ); /*extra 3 bits of headroom for MA filter in getEnvelope*/
402 72 : L_tmp_floor = L_shl( L_deposit_l( floorPowerSpectrum ), k ); /*Q : 13+norm_s( floorPowerSpectrum )*/
403 72 : set32_fx( powerSpec, L_tmp_floor, nSamples ); /*Q : 13+norm_s( floorPowerSpectrum )*/
404 72 : *powerSpec_exp = sub( 31, k );
405 : }
406 : ELSE
407 : {
408 1353 : L_tmp_floor = L_shl( L_deposit_l( floorPowerSpectrum ), k ); /*Q : 31 - *powerSpec_exp*/
409 :
410 1353 : tmp_loop = sub( nSamples, 2 );
411 718187 : FOR( k = 1; k <= tmp_loop; k++ )
412 : {
413 716834 : x = L_sub( L_shr( mdctSpec[k + 1], 1 ), L_shr( mdctSpec[k - 1], 1 ) ); /* An MDST estimate */ /*30-mdctSpec_exp*/
414 :
415 716834 : x = L_shr( Mpy_32_32( x, x ), 3 ); /*26-2*mdctSpec_exp*/
416 :
417 716834 : L_tmp = Mpy_32_32( mdctSpec[k], mdctSpec[k] ); /*31-2*mdctSpec_exp*/
418 716834 : L_tmp = L_shr( L_tmp, 5 ); /*26-2*mdctSpec_exp*/
419 :
420 716834 : powerSpec[k] = L_max( L_tmp_floor, L_add( L_tmp, x ) ); /*Q : 31 - *powerSpec_exp*/
421 716834 : move32();
422 : }
423 : }
424 :
425 1425 : powerSpec[0] = L_shr( powerSpec[1], 1 ); /*0.5f * powerSpec[1]*/
426 1425 : move32();
427 1425 : powerSpec[nSamples - 1] = L_shr( powerSpec[nSamples - 2], 1 ); /*0.5f * powerSpec[nSamples - 2]*/
428 1425 : move32();
429 1425 : return;
430 : }
431 :
432 : #define LEVEL_EXP 3 /*+4*/
433 2850 : static void getEnvelope(
434 : const Word16 nSamples, /*i: Q0 */
435 : const Word32 *powerSpec, /*i: powerSpec_exp */
436 : Word16 F0, /*i: 5Q10*/
437 : Word32 *envelope, /*o: powerSpec_exp + LEVEL_EXP Q28*/
438 : Word32 *smoothedSpectrum /*o: powerSpec_exp + LEVEL_EXP Q28*/
439 : )
440 : {
441 : Word16 nFilterLength, nHalfFilterLength, nSecondHalfFilterLength, n1, n2;
442 : Word16 level, inv_len;
443 : Word16 i;
444 : Word32 sum, tmp;
445 :
446 2850 : IF( F0 == 0 )
447 : {
448 2492 : nFilterLength = 15; /*Q0*/
449 2492 : move16();
450 : }
451 358 : ELSE IF( F0 <= 10240 /*10.0f Q10*/ )
452 : {
453 76 : nFilterLength = 11; /*Q0*/
454 76 : move16();
455 : }
456 282 : ELSE IF( F0 >= 22528 /*22.0f Q10*/ )
457 : {
458 : /* For F0 >= 22 peak is isolated well enough with the filter length of 23.
459 : This case is however not triggered due to the limit of pit_min,
460 : but the line is left for security reasons. */
461 16 : nFilterLength = 23; /*Q0*/
462 16 : move16();
463 : }
464 : ELSE
465 : {
466 266 : nFilterLength = s_or( 1, shr( F0, 10 ) ); /*1+2*(int)(F0/2); F0->Q10*/
467 266 : move16();
468 : }
469 :
470 2850 : nHalfFilterLength = shr( nFilterLength, 1 );
471 :
472 2850 : n1 = add( nHalfFilterLength, 1 );
473 :
474 2850 : nSecondHalfFilterLength = sub( nFilterLength, nHalfFilterLength );
475 :
476 2850 : n2 = sub( nSecondHalfFilterLength, 1 );
477 :
478 2850 : assert( ( nFilterLength >= 7 ) && ( nFilterLength <= 23 ) && ( nFilterLength % 2 == 1 ) );
479 :
480 :
481 2850 : sum = L_deposit_l( 0 );
482 2850 : level = 31089 /*LEVEL_ABOVE_ENVELOPE Q12*/; /*Q12*/
483 2850 : move16();
484 :
485 22653 : FOR( i = 0; i < n2; i++ )
486 : {
487 19803 : sum = L_add( sum, powerSpec[i] ); /*powerSpec_exp*/
488 : }
489 : /* No need for PTR_INIT for powerSpec[i+n2] as we continue from the previous loop */
490 25503 : FOR( i = 0; i < n1; i++ )
491 : {
492 22653 : sum = L_add_sat( sum, powerSpec[i + n2] ); /*powerSpec_exp*/
493 22653 : tmp = Mpy_32_16_1( sum /*Q31,powerSpec_exp*/, level /*Q12*/ ); /*Q28,powerSpec_exp*/
494 22653 : envelope[i] /*Q28,powerSpec_exp*/ = Mpy_32_16_1( tmp /*Q28,powerSpec_exp*/, InvIntTable[i + nSecondHalfFilterLength] /*Q15*/ );
495 22653 : move32();
496 : }
497 :
498 2850 : inv_len = mult_r( level, InvIntTable[nFilterLength] ); /*Q12*/
499 1460246 : FOR( i = n1; i < nSamples - n2; i++ )
500 : {
501 1457396 : sum = L_add_sat( sum, L_sub( powerSpec[i + n2], powerSpec[i - n1] ) ); /*powerSpec_exp*/
502 1457396 : envelope[i] = Mpy_32_16_1( sum, inv_len ); /*Q28*/
503 1457396 : move32();
504 : }
505 :
506 22653 : FOR( i = nSamples - n2; i < nSamples; i++ )
507 : {
508 19803 : sum = L_sub( sum, powerSpec[i - n1] );
509 19803 : tmp = Mpy_32_16_1( sum, level ); /*Q28*/
510 19803 : envelope[i] = Mpy_32_16_1( tmp, InvIntTable[( nSamples - ( i - nHalfFilterLength ) )] ); /*Q28*/
511 19803 : move32();
512 : }
513 :
514 1497002 : FOR( i = 1; i < nSamples - 1; i++ )
515 : {
516 1494152 : smoothedSpectrum[i] = L_add( L_add( Mpy_32_16_1( powerSpec[i - 1], 3072 /*0.75f Q12*/ ), L_shr( powerSpec[i], LEVEL_EXP ) ), Mpy_32_16_1( powerSpec[i + 1], 3072 /*0.75f Q12*/ ) ); /*Q28*/
517 1494152 : move32();
518 : }
519 :
520 2850 : move32();
521 2850 : move32();
522 2850 : smoothedSpectrum[0] = L_add( Mpy_32_16_1( powerSpec[1], 3072 /*0.75f Q12*/ ), L_shr( powerSpec[0], LEVEL_EXP ) ); /*Q28*/
523 2850 : smoothedSpectrum[nSamples - 1] = L_add( Mpy_32_16_1( powerSpec[nSamples - 2], 3072 /*0.75f Q12*/ ), L_shr( powerSpec[nSamples - 1], LEVEL_EXP ) ); /**/
524 2850 : return;
525 : }
526 :
527 0 : static void GetF0(
528 : Word16 /*short*/ const nSamples, /*i - Q0 */
529 : Word16 /*short*/ const nSamplesCore, /*i - Q0 */
530 : Word32 /*int*/ const *const powerSpectrum,
531 : /*i - Qx */ /*is justed handed over and given back*/
532 : Word32 /*int*/ const pitchLag, /*i - Q16*/
533 : Word16 /*short*/ *const pOrigF0, /*o - Q10*/
534 : Word16 /*short*/ *const pF0 ) /*o - Q10*/
535 : {
536 : Word16 /*short*/ tmpPitchLag;
537 : Word16 /*short*/ rgiStrongHarmonics[MAX_PEAKS_FROM_PITCH]; /*Q0*/
538 : Word16 /*short*/ nTotalHarmonics, nStrongHarmonics;
539 : Word16 tmp;
540 :
541 :
542 0 : assert( LAST_HARMONIC_POS_TO_CHECK <= nSamplesCore );
543 :
544 : /* Use only F0 >= 100 Hz */
545 0 : test();
546 0 : IF( ( pitchLag > 0 ) && ( LE_16( round_fx( pitchLag ), shr( nSamplesCore, 1 ) ) ) )
547 : {
548 :
549 : tmpPitchLag /*"halfPitchLag" in FLC - read as Q5 for comparison to halfpitchlag Q4*/
550 0 : = round_fx( L_shl( pitchLag, 4 ) ); /*no division by 2, will be done in following division -
551 : furthermore, do a leftshift before rounding, to preserve more accuracy -
552 : will be accommodated also in following division*/
553 :
554 : /**pF0 = nSamplesCore/tmpPitchLag;*/
555 0 : BASOP_Util_Divide_MantExp( nSamplesCore, 0, tmpPitchLag, -( 1 /*division by 2*/ + 4 /*accommodate accuracy-prevention-leftshift*/ ), pF0, &tmp ); /*pF0 is Q15*/
556 0 : move16();
557 0 : *pF0 = shr_sat( *pF0, sub( 5, tmp ) ); /*Q10 without scalingfactor*/
558 0 : move16();
559 0 : *pOrigF0 = *pF0; /*Q10*/
560 0 : move16();
561 0 : tmp = 2 * LAST_HARMONIC_POS_TO_CHECK;
562 0 : if ( LT_16( nSamples, 2 * LAST_HARMONIC_POS_TO_CHECK ) )
563 : {
564 0 : move16();
565 0 : tmp = nSamples;
566 : }
567 0 : BASOP_Util_Divide_MantExp( tmp, 15, *pF0, 5, &nTotalHarmonics, &tmp );
568 0 : nTotalHarmonics = shl( nTotalHarmonics, sub( tmp, 15 ) );
569 :
570 :
571 : /* Get in rgiStrongHarmonics all i for which i*F0 are the strongest harmonics */
572 0 : findStrongestHarmonics( nSamples, powerSpectrum, *pF0, nTotalHarmonics, rgiStrongHarmonics, &nStrongHarmonics );
573 :
574 0 : CorrectF0( rgiStrongHarmonics, nStrongHarmonics, pF0 );
575 : }
576 : ELSE
577 : {
578 0 : move16();
579 0 : move16();
580 0 : *pF0 = 0;
581 0 : *pOrigF0 = 0;
582 : }
583 0 : return;
584 : }
585 :
586 1425 : static void ivas_GetF0_fx(
587 : Word16 /*short*/ const nSamples, /*i - Q0 */
588 : Word16 /*short*/ const nSamplesCore, /*i - Q0 */
589 : Word32 /*int*/ const *const powerSpectrum,
590 : /*i - Qx */ /*is justed handed over and given back*/
591 : Word32 /*int*/ const pitchLag, /*i - Q16*/
592 : Word16 /*short*/ *const pOrigF0, /*o - Q10*/
593 : Word16 /*short*/ *const pF0 ) /*o - Q10*/
594 : {
595 : Word16 /*short*/ tmpPitchLag;
596 : Word16 /*short*/ rgiStrongHarmonics[MAX_PEAKS_FROM_PITCH]; /*Q0*/
597 : Word16 /*short*/ nTotalHarmonics, nStrongHarmonics;
598 : Word16 tmp;
599 :
600 :
601 1425 : assert( LAST_HARMONIC_POS_TO_CHECK <= nSamplesCore );
602 :
603 : /* Use only F0 >= 100 Hz */
604 1425 : test();
605 1425 : IF( ( pitchLag > 0 ) && ( LE_16( round_fx( pitchLag ), shr( nSamplesCore, 1 ) ) ) )
606 : {
607 :
608 : tmpPitchLag /*"halfPitchLag" in FLC - read as Q5 for comparison to halfpitchlag Q4*/
609 368 : = round_fx( L_shl( pitchLag, 4 ) ); /*no division by 2, will be done in following division -
610 : furthermore, do a leftshift before rounding, to preserve more accuracy -
611 : will be accommodated also in following division*/
612 :
613 : /**pF0 = nSamplesCore/tmpPitchLag;*/
614 368 : BASOP_Util_Divide_MantExp( nSamplesCore, 0, tmpPitchLag, -( 1 /*division by 2*/ + 4 /*accommodate accuracy-prevention-leftshift*/ ), pF0, &tmp ); /*pF0 is Q15*/
615 368 : move16();
616 368 : *pF0 = shr_sat( *pF0, sub( 5, tmp ) ); /*Q10 without scalingfactor*/
617 368 : move16();
618 368 : *pOrigF0 = *pF0; /*Q10*/
619 368 : move16();
620 368 : tmp = 2 * LAST_HARMONIC_POS_TO_CHECK;
621 368 : if ( LT_16( nSamples, 2 * LAST_HARMONIC_POS_TO_CHECK ) )
622 : {
623 24 : move16();
624 24 : tmp = nSamples;
625 : }
626 368 : BASOP_Util_Divide_MantExp( tmp, 15, *pF0, 5, &nTotalHarmonics, &tmp );
627 368 : nTotalHarmonics = shl( nTotalHarmonics, sub( tmp, 15 ) );
628 :
629 :
630 : /* Get in rgiStrongHarmonics all i for which i*F0 are the strongest harmonics */
631 368 : findStrongestHarmonics( nSamples, powerSpectrum, *pF0, nTotalHarmonics, rgiStrongHarmonics, &nStrongHarmonics );
632 :
633 368 : ivas_CorrectF0_fx( rgiStrongHarmonics, nStrongHarmonics, pF0 );
634 : }
635 : ELSE
636 : {
637 1057 : move16();
638 1057 : move16();
639 1057 : *pF0 = 0;
640 1057 : *pOrigF0 = 0;
641 : }
642 1425 : return;
643 : }
644 :
645 :
646 368 : static void findStrongestHarmonics(
647 : const Word16 nSamples,
648 : const Word32 *powerSpectrum, /*Qx*/
649 : const Word16 F0 /*5Q10*/,
650 : const Word16 nTotalHarmonics,
651 : Word16 *pHarmonicIndexes, /*Q0*/
652 : Word16 *pnHarmonics /*Q0*/ )
653 : {
654 : Word32 peaks[MAX_PEAKS_FROM_PITCH] /*Qx*/, smallestPeak;
655 : Word16 nPeaksToCheck, nPeaks, iSmallestPeak;
656 : Word16 i, l, k;
657 : (void) nSamples;
658 :
659 :
660 368 : nPeaks = 0;
661 368 : move16();
662 :
663 368 : iSmallestPeak = 0;
664 368 : move16();
665 368 : smallestPeak = 0x7fffffff;
666 368 : move32();
667 :
668 368 : nPeaksToCheck = s_min( nTotalHarmonics, MAX_PEAKS_FROM_PITCH + 1 );
669 :
670 4014 : FOR( i = 1; i < nPeaksToCheck; i++ )
671 : {
672 : Word32 newPeak;
673 :
674 3646 : k = extract_h( L_shl( L_mult( i, F0 ), 5 ) ); /*k = (int)(i*F0); Q0*/
675 3646 : assert( k > 0 && k < 2 * LAST_HARMONIC_POS_TO_CHECK && k < nSamples );
676 :
677 3646 : newPeak = L_add( powerSpectrum[k], 0 ); /*Qx*/
678 :
679 3646 : peaks[nPeaks] = newPeak; /*Qx*/
680 3646 : move32();
681 3646 : pHarmonicIndexes[nPeaks] = i;
682 3646 : move16();
683 :
684 3646 : IF( LE_32( newPeak, smallestPeak ) )
685 : {
686 2084 : iSmallestPeak = nPeaks;
687 2084 : move16();
688 2084 : smallestPeak = L_add( newPeak, 0 );
689 : }
690 :
691 3646 : nPeaks = add( nPeaks, 1 );
692 : }
693 :
694 4534 : FOR( ; i < nTotalHarmonics; i++ )
695 : {
696 : Word32 newPeak;
697 :
698 4166 : k = extract_h( L_shl( L_mult( i, F0 ), 5 ) ); /*Q0*/
699 4166 : assert( k > 0 && k < 2 * LAST_HARMONIC_POS_TO_CHECK && k < nSamples );
700 :
701 4166 : newPeak = L_add( powerSpectrum[k], 0 ); /*Qx*/
702 :
703 4166 : IF( GT_32( newPeak, smallestPeak ) )
704 : {
705 643 : peaks[iSmallestPeak] = newPeak; /*Qx*/
706 643 : move32();
707 643 : pHarmonicIndexes[iSmallestPeak] = i;
708 643 : move16();
709 643 : smallestPeak = L_add( newPeak, 0 );
710 :
711 7073 : FOR( l = 0; l < MAX_PEAKS_FROM_PITCH; l++ )
712 : {
713 6430 : IF( peaks[l] <= smallestPeak )
714 : {
715 1318 : iSmallestPeak = l;
716 1318 : move16();
717 1318 : smallestPeak = L_add( peaks[l], 0 );
718 : }
719 : }
720 : }
721 : }
722 :
723 368 : sort_fx( pHarmonicIndexes, 0, sub( nPeaks, 1 ) );
724 :
725 368 : *pnHarmonics = nPeaks; /*Q0*/
726 368 : move16();
727 368 : return;
728 : }
729 :
730 : /* Use new F0, for which harmonics are most common in pHarmonicIndexes */
731 0 : static void CorrectF0(
732 : const Word16 /*short*/ *pHarmonicIndexes, /*I - Q0 */
733 : const Word16 /*short*/ nHarmonics, /*I - Q0 */
734 : Word16 /*short*/ *pF0 ) /*I/O - Q10 range: {0}, [4..18) */
735 : {
736 : Word16 /*short*/ i;
737 : Word16 /*short*/ F0;
738 : Word16 /*short*/ diff[MAX_PEAKS_FROM_PITCH - 1], sortedDiff[MAX_PEAKS_FROM_PITCH - 1]; /*Q0*/
739 : Word16 /*short*/ iMostCommonDiff, nMostCommonDiff, nSameDiff, iMult; /*Q0*/
740 :
741 : Word16 tmp;
742 :
743 0 : F0 = *pF0; /*Q10*/
744 :
745 0 : test();
746 0 : IF( F0 > 0 && nHarmonics != 0 )
747 : {
748 0 : tmp = sub( nHarmonics, 1 );
749 0 : FOR( i = 0; i < tmp; i++ )
750 : {
751 0 : diff[i] = sub( pHarmonicIndexes[i + 1], pHarmonicIndexes[i] ); /*Q0*/
752 0 : move16();
753 0 : sortedDiff[i] = diff[i]; /*Q0*/
754 0 : move16();
755 : }
756 0 : sort_fx( sortedDiff, 0, sub( nHarmonics, 1 + 1 ) );
757 0 : iMostCommonDiff = sortedDiff[0]; /*Q0*/
758 0 : move16();
759 0 : nSameDiff = 1;
760 0 : move16();
761 0 : i = 1;
762 0 : move16();
763 0 : IF( EQ_16( imult1616( sortedDiff[0], pHarmonicIndexes[0] ), 1 ) )
764 : {
765 : /* Find how many distances between peaks have length 1 */
766 0 : FOR( ; i < tmp; i++ )
767 : {
768 0 : if ( EQ_16( sortedDiff[i], 1 ) )
769 : {
770 0 : nSameDiff = add( nSameDiff, 1 );
771 : }
772 : }
773 : }
774 0 : nMostCommonDiff = nSameDiff; /*Q0*/
775 0 : move16();
776 :
777 : /* If there are at least 3 distances between peaks with length 1 and if the 1st harmonic is in pHarmonicIndexes then keep the original F0 */
778 : /* Otherwise find the most common distance between peaks */
779 0 : IF( LT_16( nSameDiff, 3 ) )
780 : {
781 : /* Find the most common difference */
782 0 : FOR( i = nSameDiff; i < tmp; i++ )
783 : {
784 0 : IF( EQ_16( sortedDiff[i], sortedDiff[i - 1] ) )
785 : {
786 0 : nSameDiff = add( nSameDiff, 1 );
787 : }
788 : ELSE
789 : {
790 0 : IF( GT_16( nSameDiff, nMostCommonDiff ) )
791 : {
792 0 : nMostCommonDiff = nSameDiff; /*Q0*/
793 0 : move16();
794 0 : iMostCommonDiff = sortedDiff[i - 1]; /*Q0*/
795 0 : move16();
796 : }
797 : ELSE
798 : {
799 0 : test();
800 0 : IF( EQ_16( nSameDiff, nMostCommonDiff ) && GT_16( abs_s( sub( iMostCommonDiff, pHarmonicIndexes[0] ) ), abs_s( sub( sortedDiff[i - 1], pHarmonicIndexes[0] ) ) ) )
801 : {
802 0 : nMostCommonDiff = nSameDiff; /*Q0*/
803 0 : move16();
804 0 : iMostCommonDiff = sortedDiff[i - 1]; /*Q0*/
805 0 : move16();
806 : }
807 : }
808 0 : nSameDiff = 1;
809 0 : move16();
810 : }
811 : }
812 0 : IF( GT_16( nSameDiff, nMostCommonDiff ) )
813 : {
814 0 : nMostCommonDiff = nSameDiff; /*Q0*/
815 0 : move16();
816 0 : iMostCommonDiff = sortedDiff[nHarmonics - 2]; /*Q0*/
817 0 : move16();
818 : }
819 : }
820 :
821 : /* If there are enough peaks at the same distance */
822 0 : IF( GE_16( nMostCommonDiff, MAX_PEAKS_FROM_PITCH / 2 ) )
823 : {
824 0 : iMult = 1;
825 0 : move16();
826 0 : FOR( i = 0; i < tmp; i++ )
827 : {
828 0 : IF( EQ_16( diff[i], iMostCommonDiff ) )
829 : {
830 0 : iMult = pHarmonicIndexes[i]; /*Q0*/
831 0 : move16();
832 0 : BREAK;
833 : }
834 : /* for rare cases of octave mismatch or missing harmonics */
835 0 : test();
836 0 : test();
837 0 : IF( GT_16( sub( nHarmonics, 2 ), i ) && ( EQ_16( diff[i], diff[i + 1] ) ) && ( EQ_16( add( diff[i], diff[i + 1] ), iMostCommonDiff ) ) )
838 : {
839 0 : iMult = pHarmonicIndexes[i]; /*Q0*/
840 0 : move16();
841 0 : BREAK;
842 : }
843 : }
844 :
845 : /* If the real F0 is much higher than the original F0 from the pitch */
846 :
847 0 : IF( LE_16( iMult, 3 ) )
848 : {
849 : /* Use iMostCommonDiff, because the lowest pHarmonicIndexes[i] (which is equal to iMult) may not correspond to the new F0, but to it's multiple */
850 0 : F0 = round_fx_sat( L_shl_sat( L_mult( iMostCommonDiff /*Q0*/, F0 /*Q10*/ ), 15 ) ); /*Q10*/
851 : }
852 : ELSE
853 : {
854 0 : F0 = 0;
855 0 : move16();
856 : }
857 : }
858 : /* Otherwise if there are at least 3 distances between peaks with length 1 and if the 1st harmonic is in pHarmonicIndexes then keep the original F0 */
859 : /* Otherwise don't use F0 */
860 : ELSE
861 : {
862 0 : test();
863 0 : if ( ( GT_16( iMostCommonDiff, 1 ) ) || ( LT_16( nMostCommonDiff, 3 ) ) )
864 : {
865 : /* Not enough peaks at the same distance => don't use the pitch. */
866 0 : F0 = 0;
867 0 : move16();
868 : }
869 : }
870 0 : *pF0 = F0;
871 0 : move16();
872 : }
873 0 : return;
874 : }
875 :
876 368 : static void ivas_CorrectF0_fx(
877 : const Word16 /*short*/ *pHarmonicIndexes, /*I - Q0 */
878 : const Word16 /*short*/ nHarmonics, /*I - Q0 */
879 : Word16 /*short*/ *pF0 ) /*I/O - Q10 range: {0}, [4..18) */
880 : {
881 : Word16 /*short*/ i;
882 : Word16 /*short*/ F0;
883 : Word16 /*short*/ diff[MAX_PEAKS_FROM_PITCH - 1], sortedDiff[MAX_PEAKS_FROM_PITCH - 1]; /*Q0*/
884 : Word16 /*short*/ iMostCommonDiff, nMostCommonDiff, nSameDiff, iMult; /*Q0*/
885 :
886 : Word16 tmp;
887 :
888 3680 : FOR( i = 0; i < MAX_PEAKS_FROM_PITCH - 1; i++ )
889 : {
890 3312 : diff[i] = 0;
891 3312 : sortedDiff[i] = 0;
892 3312 : move16();
893 3312 : move16();
894 : }
895 :
896 368 : F0 = *pF0; /*Q10*/
897 :
898 368 : test();
899 368 : IF( F0 > 0 && nHarmonics != 0 )
900 : {
901 368 : tmp = sub( nHarmonics, 1 );
902 3646 : FOR( i = 0; i < tmp; i++ )
903 : {
904 3278 : diff[i] = sub( pHarmonicIndexes[i + 1], pHarmonicIndexes[i] ); /*Q0*/
905 3278 : move16();
906 3278 : sortedDiff[i] = diff[i]; /*Q0*/
907 3278 : move16();
908 : }
909 368 : sort_fx( sortedDiff, 0, sub( nHarmonics, 1 + 1 ) );
910 368 : iMostCommonDiff = sortedDiff[0]; /*Q0*/
911 368 : move16();
912 368 : nSameDiff = 1;
913 368 : move16();
914 368 : i = 1;
915 368 : move16();
916 368 : IF( EQ_16( imult1616( sortedDiff[0], pHarmonicIndexes[0] ), 1 ) )
917 : {
918 : /* Find how many distances between peaks have length 1 */
919 2954 : FOR( ; i < tmp; i++ )
920 : {
921 2622 : if ( EQ_16( sortedDiff[i], 1 ) )
922 : {
923 2223 : nSameDiff = add( nSameDiff, 1 );
924 : }
925 : }
926 : }
927 368 : nMostCommonDiff = nSameDiff; /*Q0*/
928 368 : move16();
929 :
930 : /* If there are at least 3 distances between peaks with length 1 and if the 1st harmonic is in pHarmonicIndexes then keep the original F0 */
931 : /* Otherwise find the most common distance between peaks */
932 368 : IF( LT_16( nSameDiff, 3 ) )
933 : {
934 : /* Find the most common difference */
935 369 : FOR( i = nSameDiff; i < tmp; i++ )
936 : {
937 327 : IF( EQ_16( sortedDiff[i], sortedDiff[i - 1] ) )
938 : {
939 262 : nSameDiff = add( nSameDiff, 1 );
940 : }
941 : ELSE
942 : {
943 65 : IF( GT_16( nSameDiff, nMostCommonDiff ) )
944 : {
945 39 : nMostCommonDiff = nSameDiff; /*Q0*/
946 39 : move16();
947 39 : iMostCommonDiff = sortedDiff[i - 1]; /*Q0*/
948 39 : move16();
949 : }
950 : ELSE
951 : {
952 26 : test();
953 26 : IF( EQ_16( nSameDiff, nMostCommonDiff ) && GT_16( abs_s( sub( iMostCommonDiff, pHarmonicIndexes[0] ) ), abs_s( sub( sortedDiff[i - 1], pHarmonicIndexes[0] ) ) ) )
954 : {
955 1 : nMostCommonDiff = nSameDiff; /*Q0*/
956 1 : move16();
957 1 : iMostCommonDiff = sortedDiff[i - 1]; /*Q0*/
958 1 : move16();
959 : }
960 : }
961 65 : nSameDiff = 1;
962 65 : move16();
963 : }
964 : }
965 42 : IF( GT_16( nSameDiff, nMostCommonDiff ) )
966 : {
967 18 : nMostCommonDiff = nSameDiff; /*Q0*/
968 18 : move16();
969 18 : iMostCommonDiff = sortedDiff[nHarmonics - 2]; /*Q0*/
970 18 : move16();
971 : }
972 : }
973 :
974 : /* If there are enough peaks at the same distance */
975 368 : IF( GE_16( nMostCommonDiff, MAX_PEAKS_FROM_PITCH / 2 ) )
976 : {
977 350 : iMult = 1;
978 350 : move16();
979 360 : FOR( i = 0; i < tmp; i++ )
980 : {
981 360 : IF( EQ_16( diff[i], iMostCommonDiff ) )
982 : {
983 337 : iMult = pHarmonicIndexes[i]; /*Q0*/
984 337 : move16();
985 337 : BREAK;
986 : }
987 : /* for rare cases of octave mismatch or missing harmonics */
988 23 : test();
989 23 : test();
990 23 : IF( GT_16( sub( nHarmonics, 2 ), i ) && ( EQ_16( diff[i], diff[i + 1] ) ) && ( EQ_16( add( diff[i], diff[i + 1] ), iMostCommonDiff ) ) )
991 : {
992 13 : iMult = pHarmonicIndexes[i]; /*Q0*/
993 13 : move16();
994 13 : BREAK;
995 : }
996 : }
997 :
998 : /* If the real F0 is much higher than the original F0 from the pitch */
999 :
1000 350 : IF( LE_16( iMult, 3 ) )
1001 : {
1002 : /* Use iMostCommonDiff, because the lowest pHarmonicIndexes[i] (which is equal to iMult) may not correspond to the new F0, but to it's multiple */
1003 344 : F0 = round_fx_sat( L_shl_sat( L_mult( iMostCommonDiff /*Q0*/, F0 /*Q10*/ ), 15 ) ); /*Q10*/
1004 : }
1005 : ELSE
1006 : {
1007 6 : F0 = 0;
1008 6 : move16();
1009 : }
1010 : }
1011 : /* Otherwise if there are at least 3 distances between peaks with length 1 and if the 1st harmonic is in pHarmonicIndexes then keep the original F0 */
1012 : /* Otherwise don't use F0 */
1013 : ELSE
1014 : {
1015 18 : test();
1016 18 : if ( ( GT_16( iMostCommonDiff, 1 ) ) || ( LT_16( nMostCommonDiff, 3 ) ) )
1017 : {
1018 : /* Not enough peaks at the same distance => don't use the pitch. */
1019 4 : F0 = 0;
1020 4 : move16();
1021 : }
1022 : }
1023 368 : *pF0 = F0;
1024 368 : move16();
1025 : }
1026 368 : return;
1027 : }
1028 :
1029 3532 : static void modifyThreshold(
1030 : Word16 /*short*/ i, /*I - Q0 */
1031 : Word16 /*short*/ F0, /*I - Q10*/
1032 : Word16 /*short*/ threshold, /*I - Q10*/
1033 : Word16 * /*short*/ thresholdModification ) /*I/O - Q10*/
1034 : {
1035 : Word32 harmonic;
1036 : Word16 fractional /*Q15*/;
1037 : Word16 k /*Q0*/;
1038 : Word16 twoTimesFract /*Q10*/;
1039 :
1040 :
1041 3532 : harmonic = L_mult( shl( i, 5 ), F0 ); /*Q0 * Q10 = 15Q16*/
1042 3532 : k = extract_h( harmonic ); /*Q0*/
1043 3532 : fractional = lshr( extract_l( harmonic ), 1 ); /* Fractional part of the i*F0 */ /*Q15*/
1044 3532 : twoTimesFract = mult( 2048 /*2 in Q10*/, fractional /*Q15*/ ); /*Q10*/ /* threshold if the center of the peek is between k-1 and k, threshold+2 if the center of the peek is between k and k+1 */
1045 :
1046 3532 : move16();
1047 3532 : thresholdModification[k] = threshold;
1048 3532 : move16();
1049 3532 : thresholdModification[k - 1] = add( threshold /*Q10*/, twoTimesFract /*Q10*/ ); /*Q10*/
1050 3532 : move16();
1051 3532 : thresholdModification[k + 1] = add( threshold /*Q10*/, sub( 2048 /*2 in Q10*/, twoTimesFract /*Q10*/ ) /*Q10*/ ); /*Q10*/
1052 3532 : return;
1053 : }
1054 :
1055 1425 : static void modifyThresholds(
1056 : Word16 /*short*/ F0, /*I - Q10*/
1057 : Word16 /*short*/ origF0, /*I - Q10*/
1058 : Word16 * /*short*/ thresholdModification ) /*I/O - Q10*/
1059 : {
1060 : Word16 /*int*/ i, /*int*/ nHarmonics;
1061 : Word16 tmp, tmpM, tmpE;
1062 :
1063 :
1064 1425 : IF( origF0 > 0 )
1065 : {
1066 368 : IF( F0 == 0 )
1067 : {
1068 10 : nHarmonics /*Q0*/ = s_min( MAX_PEAKS_FROM_PITCH /*Q0*/, shl( ( div_s( LAST_HARMONIC_POS_TO_CHECK /*Q0*/, origF0 /*Q10*/ ) /*Q15*2^10*/ ), -5 /*Q0*2^-5*/ ) /*Q0*/ );
1069 :
1070 109 : FOR( i = 1; i <= nHarmonics; i++ )
1071 : {
1072 99 : modifyThreshold( i, origF0, 717 /*0.7f Q10*/ /*0.7f in Q10*/, thresholdModification );
1073 : }
1074 : }
1075 368 : IF( F0 > 0 )
1076 : {
1077 358 : nHarmonics /*Q0*/ = s_min( MAX_PEAKS_FROM_PITCH /*Q0*/, shl( ( div_s( LAST_HARMONIC_POS_TO_CHECK /*Q0*/, F0 /*Q10*/ ) /*Q15*2^10*/ ), -5 /*Q0*2^-5*/ ) /*Q0*/ );
1078 :
1079 : /*(int)(F0/origF0+0.5f)*/
1080 358 : BASOP_Util_Divide_MantExp( F0, 0, origF0, 0, &tmpM, &tmpE );
1081 358 : tmp = round_fx( L_shl( L_deposit_l( tmpM ), add( tmpE, 1 ) ) );
1082 :
1083 746 : FOR( i = tmp; i > 0; i-- )
1084 : {
1085 388 : modifyThreshold( i, origF0, 358 /*0.35f Q10*/, thresholdModification );
1086 : }
1087 3403 : FOR( i = 1; i <= nHarmonics; i++ )
1088 : {
1089 3045 : modifyThreshold( i, F0, 358 /*0.35f Q10*/, thresholdModification );
1090 : }
1091 : }
1092 : }
1093 1425 : return;
1094 : }
1095 :
1096 1425 : static void findCandidates(
1097 : const Word16 nSamples, /* i: frame size */
1098 : const Word32 *MDCTSpectrum, /* i: MDCT spectrum */
1099 : const Word16 MDCTSpectrum_exp, /* i: exponent of MDCT spectrum */
1100 : Word16 *thresholdModificationNew, /* o: threshold modification Q10 */
1101 : Word16 floorPowerSpectrum /* i: lower limit for power spectrum bins Q0*/
1102 : )
1103 : {
1104 : Word32 powerSpectrum[L_FRAME_MAX];
1105 : Word16 powerSpectrum_exp;
1106 : Word32 envelope[L_FRAME_MAX]; /*powerSpec_exp + LEVEL_EXP*/
1107 : Word32 smoothedSpectrum[L_FRAME_MAX]; /*powerSpec_exp + LEVEL_EXP*/
1108 : Word16 upperIdx, lowerIdx;
1109 : Word16 k, j;
1110 : Word32 biggerNeighbor;
1111 : Word16 tmp_loop1, tmp_loop2, tmp_loop3;
1112 :
1113 :
1114 1425 : calcPseudoSpec( MDCTSpectrum, MDCTSpectrum_exp, nSamples, floorPowerSpectrum, powerSpectrum, &powerSpectrum_exp );
1115 :
1116 1425 : getEnvelope( nSamples, powerSpectrum, 0, envelope, smoothedSpectrum );
1117 :
1118 1425 : set16_fx( thresholdModificationNew, UNREACHABLE_THRESHOLD, nSamples ); /*Q10*/
1119 :
1120 1425 : k = GROUP_LENGTH / 2;
1121 1425 : move16();
1122 1425 : tmp_loop1 = sub( nSamples, ( GROUP_LENGTH - GROUP_LENGTH / 2 ) );
1123 1425 : tmp_loop2 = sub( nSamples, 1 );
1124 668896 : WHILE( LE_16( k, tmp_loop1 ) )
1125 : {
1126 667471 : IF( GT_32( smoothedSpectrum[k], envelope[k] ) )
1127 : {
1128 : /* The check that bin at k is bigger than bins at k-1 and k+1 is needed to avoid deadlocks when the thresholds are low. */
1129 : /* It removes some true peaks, especially if non weighted sum is used for the smoothed spectrum. */
1130 6265 : biggerNeighbor = L_max( powerSpectrum[k - 1], powerSpectrum[k + 1] ); /*powerSpectrum_exp*/
1131 :
1132 6265 : IF( GE_32( powerSpectrum[k], biggerNeighbor ) )
1133 : {
1134 : /* Find the right foot */
1135 3702 : upperIdx = add( k, 1 );
1136 73801 : WHILE( LT_16( upperIdx, tmp_loop2 ) )
1137 : {
1138 :
1139 73655 : IF( LT_32( powerSpectrum[upperIdx], powerSpectrum[upperIdx + 1] ) )
1140 : {
1141 : /* Side lobes may increase for certain amount */
1142 7014 : IF( LT_32( L_shl( Mpy_32_16_1( powerSpectrum[upperIdx], ALLOWED_SIDE_LOBE_FLUCTUATION ), ALLOWED_SIDE_LOBE_FLUCTUATION_EXP ), powerSpectrum[upperIdx + 1] ) )
1143 : {
1144 3174 : BREAK;
1145 : }
1146 : /* Check for further decrease after a side lobe increase */
1147 4397 : FOR( j = add( upperIdx, 1 ); j < tmp_loop2; j++ )
1148 : {
1149 4397 : IF( LT_32( powerSpectrum[j], L_shl( Mpy_32_16_1( powerSpectrum[j + 1], ALLOWED_SIDE_LOBE_FLUCTUATION ), ALLOWED_SIDE_LOBE_FLUCTUATION_EXP ) ) )
1150 : {
1151 3840 : BREAK;
1152 : }
1153 : }
1154 : /* Side lobe increase must be 2 times smaller than the decrease to the foot */
1155 : /* Eq. to 2.0f*powerSpectrum[lowerIdx-1]/powerSpectrum[lowerIdx] > powerSpectrum[lowerIdx]/powerSpectrum[j] */
1156 3840 : IF( GT_32( Mpy_32_32( L_shl( powerSpectrum[upperIdx + 1], 1 ), powerSpectrum[j] ), Mpy_32_32( powerSpectrum[upperIdx], powerSpectrum[upperIdx] ) ) )
1157 : {
1158 382 : BREAK;
1159 : }
1160 3458 : upperIdx = sub( j, 1 );
1161 : }
1162 70099 : upperIdx = add( upperIdx, 1 );
1163 : }
1164 : /* left foot */
1165 3702 : lowerIdx = sub( k, 1 );
1166 43563 : WHILE( lowerIdx > 0 )
1167 : {
1168 :
1169 43339 : IF( LT_32( powerSpectrum[lowerIdx], powerSpectrum[lowerIdx - 1] ) )
1170 : {
1171 : /* Side lobes may increase for certain amount */
1172 6397 : IF( LT_32( L_shl( Mpy_32_16_1( powerSpectrum[lowerIdx], ALLOWED_SIDE_LOBE_FLUCTUATION ), ALLOWED_SIDE_LOBE_FLUCTUATION_EXP ), powerSpectrum[lowerIdx - 1] ) )
1173 : {
1174 3064 : BREAK;
1175 : }
1176 : /* Check for further decrease after a side lobe increase */
1177 3918 : FOR( j = sub( lowerIdx, 1 ); j > 0; j-- )
1178 : {
1179 3918 : IF( LT_32( powerSpectrum[j], L_shl( Mpy_32_16_1( powerSpectrum[j - 1], ALLOWED_SIDE_LOBE_FLUCTUATION ), ALLOWED_SIDE_LOBE_FLUCTUATION_EXP ) ) )
1180 : {
1181 3333 : BREAK;
1182 : }
1183 : }
1184 : /* Side lobe increase must be 2 times smaller than the decrease to the foot */
1185 : /* Eq. to 2.0f*powerSpectrum[lowerIdx-1]/powerSpectrum[lowerIdx] > powerSpectrum[lowerIdx]/powerSpectrum[j] */
1186 3333 : IF( GT_32( Mpy_32_32( L_shl( powerSpectrum[lowerIdx - 1], 1 ), powerSpectrum[j] ), Mpy_32_32( powerSpectrum[lowerIdx], powerSpectrum[lowerIdx] ) ) )
1187 : {
1188 414 : BREAK;
1189 : }
1190 2919 : lowerIdx = add( j, 1 );
1191 : }
1192 39861 : lowerIdx = sub( lowerIdx, 1 );
1193 : }
1194 :
1195 : /* Check if there is a bigger peak up to the next peak foot */
1196 3702 : tmp_loop3 = s_min( upperIdx, tmp_loop1 );
1197 124737 : FOR( j = s_max( GROUP_LENGTH / 2, lowerIdx ); j <= tmp_loop3; j++ )
1198 : {
1199 121035 : if ( GT_32( powerSpectrum[j], powerSpectrum[k] ) )
1200 : {
1201 18 : k = j;
1202 18 : move16();
1203 : }
1204 : }
1205 :
1206 : /* Modify thresholds for the following frame */
1207 3702 : tmp_loop3 = add( k, 2 );
1208 14808 : FOR( j = sub( k, 1 ); j < tmp_loop3; j++ )
1209 : {
1210 11106 : thresholdModificationNew[j] = BIG_THRESHOLD; /*Q10*/
1211 11106 : move16();
1212 :
1213 11106 : if ( GT_32( smoothedSpectrum[j], envelope[j] ) )
1214 : {
1215 7219 : thresholdModificationNew[j] = SMALL_THRESHOLD; /*Q10*/
1216 7219 : move16();
1217 : }
1218 : }
1219 : /* Jump to the next foot of the peak. */
1220 3702 : k = upperIdx;
1221 3702 : move16();
1222 : }
1223 : }
1224 667471 : k = add( k, 1 );
1225 : }
1226 1425 : return;
1227 : }
1228 :
1229 0 : static void RefineThresholdsUsingPitch(
1230 : const Word16 nSamples,
1231 : const Word16 nSamplesCore,
1232 : const Word32 powerSpectrum[], /*Qx*/
1233 : const Word32 lastPitchLag, /*Qx*/
1234 : const Word32 currentPitchLag, /*Qx*/
1235 : Word16 *pF0, /*Q10*/
1236 : Word16 *thresholdModification /*Q10*/
1237 : )
1238 : {
1239 : Word16 pitchIsStable;
1240 : Word16 origF0;
1241 : Word32 L_tmp;
1242 :
1243 : /*pitchIsStable = (fabs(lastPitchLag-currentPitchLag) < 0.25f);*/
1244 0 : pitchIsStable = 0;
1245 0 : move16();
1246 0 : L_tmp = L_abs( L_sub( lastPitchLag, currentPitchLag ) );
1247 0 : if ( LT_32( L_tmp, 16384l /*0.25f Q16*/ ) )
1248 : {
1249 0 : pitchIsStable = 1;
1250 0 : move16();
1251 : }
1252 :
1253 0 : IF( pitchIsStable )
1254 : {
1255 0 : GetF0( nSamples,
1256 : nSamplesCore,
1257 : powerSpectrum, lastPitchLag, &origF0, pF0 );
1258 :
1259 0 : modifyThresholds( *pF0, origF0, thresholdModification );
1260 : }
1261 : ELSE
1262 : {
1263 0 : *pF0 = 0;
1264 0 : move16();
1265 : }
1266 0 : return;
1267 : }
1268 :
1269 1425 : static void ivas_findTonalComponents_fx(
1270 : Word16 *indexOfTonalPeak, /* OUT Q0*/
1271 : Word16 *lowerIndex, /* OUT Q0*/
1272 : Word16 *upperIndex, /* OUT Q0*/
1273 : Word16 *numIndexes, /* OUT Q0*/
1274 : Word16 nSamples, /* IN */
1275 : const Word32 *powerSpectrum, /* IN Q31-powerSpectrum_e*/
1276 : const Word16 powerSpectrum_e,
1277 : Word16 F0, /* IN */
1278 : Word16 *thresholdModification, /* IN Q10*/
1279 : Word16 element_mode ) /* IN */
1280 : {
1281 : Word32 envelope[L_FRAME_MAX]; /*powerSpec_exp + LEVEL_EXP*/
1282 : Word32 smoothedSpectrum[L_FRAME_MAX]; /*powerSpec_exp + LEVEL_EXP*/
1283 : Word16 nrOfFIS;
1284 : Word16 upperIdx, lowerIdx, lowerBound;
1285 : Word16 k, j, m;
1286 : Word32 biggerNeighbor;
1287 : Word16 tmp_loop1, tmp_loop2, tmp_loop3;
1288 :
1289 1425 : getEnvelope( nSamples, powerSpectrum, F0, envelope, smoothedSpectrum );
1290 :
1291 :
1292 1425 : nrOfFIS = 0;
1293 1425 : move16();
1294 1425 : lowerBound = 0;
1295 1425 : move16();
1296 :
1297 1425 : k = GROUP_LENGTH / 2;
1298 1425 : move16();
1299 1425 : tmp_loop1 = sub( nSamples, ( GROUP_LENGTH - GROUP_LENGTH / 2 ) );
1300 1425 : tmp_loop2 = sub( nSamples, 1 );
1301 692973 : WHILE( LE_16( k, tmp_loop1 ) )
1302 : {
1303 691548 : Word64 mult_64 = W_mult_32_16( envelope[k], thresholdModification[k] ); // (Q31-(powerSpectrum_e+LEVEL_EXP))+1+10
1304 691548 : Word16 lshift = W_norm( mult_64 );
1305 691548 : Word32 mult_32 = W_extract_h( W_shl( mult_64, lshift ) ); //(Q31-(powerSpectrum_e+LEVEL_EXP) + lshift )+11 -32
1306 691548 : Word16 mult_exp = sub( Q31, sub( add( sub( Q31, add( powerSpectrum_e, LEVEL_EXP ) ), add( 10, lshift ) ), 31 ) );
1307 691548 : Word16 flag = BASOP_Util_Cmp_Mant32Exp( smoothedSpectrum[k], ( powerSpectrum_e + LEVEL_EXP ), mult_32, mult_exp );
1308 : /* There is 3 bits headroom in envelope and max of thresholdModification is 16384, so shifting left for 4 would produce overflow only when the result is anyhow close to 1 */
1309 691548 : IF( EQ_16( flag, 1 ) )
1310 : {
1311 : /* The check that bin at k is bigger than bins at k-1 and k+1 is needed to avoid deadlocks when the thresholds are low. */
1312 : /* It removes some true peaks, especially if non weighted sum is used for the smoothed spectrum. */
1313 4113 : biggerNeighbor = L_max( powerSpectrum[k - 1], powerSpectrum[k + 1] ); /*Qx*/
1314 :
1315 4113 : IF( GE_32( powerSpectrum[k], biggerNeighbor ) )
1316 : {
1317 : /* Find the right foot */
1318 2939 : upperIdx = add( k, 1 );
1319 49600 : WHILE( LT_16( upperIdx, tmp_loop2 ) )
1320 : {
1321 49549 : IF( LT_32( powerSpectrum[upperIdx], powerSpectrum[upperIdx + 1] ) )
1322 : {
1323 : /* Side lobes may increase for certain amount */
1324 3185 : IF( LT_32( L_shl( Mpy_32_16_1( powerSpectrum[upperIdx], ALLOWED_SIDE_LOBE_FLUCTUATION ), ALLOWED_SIDE_LOBE_FLUCTUATION_EXP ), powerSpectrum[upperIdx + 1] ) )
1325 : {
1326 1242 : BREAK;
1327 : }
1328 : /* Check for further decrease after a side lobe increase */
1329 2460 : FOR( j = add( upperIdx, 1 ); j < tmp_loop2; j++ )
1330 : {
1331 2460 : IF( LT_32( powerSpectrum[j], L_shl( Mpy_32_16_1( powerSpectrum[j + 1], ALLOWED_SIDE_LOBE_FLUCTUATION ), ALLOWED_SIDE_LOBE_FLUCTUATION_EXP ) ) )
1332 : {
1333 1943 : BREAK;
1334 : }
1335 : }
1336 : /* Side lobe increase must be 2 times smaller than the decrease to the foot */
1337 : /* Eq. to 2.0f*powerSpectrum[lowerIdx-1]/powerSpectrum[lowerIdx] > powerSpectrum[lowerIdx]/powerSpectrum[j] */
1338 1943 : test();
1339 1943 : test();
1340 1943 : test();
1341 1943 : IF( ( EQ_16( element_mode, EVS_MONO ) && GT_32( Mpy_32_32( L_shl( powerSpectrum[upperIdx + 1], 1 ), powerSpectrum[j] ), Mpy_32_32( powerSpectrum[upperIdx], powerSpectrum[upperIdx] ) ) ) ||
1342 : ( NE_16( element_mode, EVS_MONO ) && ( GT_64( W_mult_32_32( L_shl( powerSpectrum[upperIdx + 1], 1 ), powerSpectrum[j] ), W_mult_32_32( powerSpectrum[upperIdx], powerSpectrum[upperIdx] ) ) ) ) )
1343 : {
1344 : BREAK;
1345 : }
1346 297 : upperIdx = sub( j, 1 );
1347 : }
1348 46661 : upperIdx = add( upperIdx, 1 );
1349 : }
1350 : /* left foot */
1351 2939 : lowerIdx = sub( k, 1 );
1352 17711 : WHILE( GT_16( lowerIdx, lowerBound ) )
1353 : {
1354 16730 : IF( LT_32( powerSpectrum[lowerIdx], powerSpectrum[lowerIdx - 1] ) )
1355 : {
1356 : /* Side lobes may increase for certain amount */
1357 3684 : IF( LT_32( L_shl( Mpy_32_16_1( powerSpectrum[lowerIdx], ALLOWED_SIDE_LOBE_FLUCTUATION ), ALLOWED_SIDE_LOBE_FLUCTUATION_EXP ), powerSpectrum[lowerIdx - 1] ) )
1358 : {
1359 1357 : BREAK;
1360 : }
1361 : /* Check for further decrease after a side lobe increase */
1362 2817 : FOR( j = sub( lowerIdx, 1 ); j > 0; j-- )
1363 : {
1364 2817 : IF( LT_32( powerSpectrum[j], L_shl( Mpy_32_16_1( powerSpectrum[j - 1], ALLOWED_SIDE_LOBE_FLUCTUATION ), ALLOWED_SIDE_LOBE_FLUCTUATION_EXP ) ) )
1365 : {
1366 2327 : BREAK;
1367 : }
1368 : }
1369 : /* Side lobe increase must be 2 times smaller than the decrease to the foot */
1370 : /* Eq. to 2.0f*powerSpectrum[lowerIdx-1]/powerSpectrum[lowerIdx] > powerSpectrum[lowerIdx]/powerSpectrum[j] */
1371 2327 : IF( GT_32( Mpy_32_32( L_shl( powerSpectrum[lowerIdx - 1], 1 ), powerSpectrum[j] ), Mpy_32_32( powerSpectrum[lowerIdx], powerSpectrum[lowerIdx] ) ) )
1372 : {
1373 601 : BREAK;
1374 : }
1375 1726 : lowerIdx = add( j, 1 );
1376 : }
1377 14772 : lowerIdx = sub( lowerIdx, 1 );
1378 : }
1379 :
1380 2939 : lowerBound = upperIdx;
1381 2939 : move16();
1382 :
1383 : /* Check if there is a bigger peak up to the next peak foot */
1384 2939 : tmp_loop3 = s_min( upperIdx, tmp_loop1 );
1385 73539 : FOR( j = s_max( GROUP_LENGTH / 2, lowerIdx ); j <= tmp_loop3; j++ )
1386 : {
1387 70600 : if ( GT_32( powerSpectrum[j], powerSpectrum[k] ) )
1388 : {
1389 :
1390 7 : k = j;
1391 7 : move16();
1392 : }
1393 : }
1394 :
1395 2939 : assert( ( nrOfFIS == 0 ) || ( indexOfTonalPeak[nrOfFIS - 1] < k ) );
1396 :
1397 2939 : lowerIndex[nrOfFIS] = sub( k, GROUP_LENGTH / 2 );
1398 2939 : move16();
1399 :
1400 2939 : upperIndex[nrOfFIS] = add( k, ( GROUP_LENGTH - GROUP_LENGTH / 2 - 1 ) );
1401 2939 : move16();
1402 :
1403 2939 : test();
1404 2939 : IF( ( nrOfFIS > 0 ) && ( LE_16( lowerIndex[nrOfFIS], upperIndex[nrOfFIS - 1] ) ) )
1405 : {
1406 20 : m = shr( add( k, indexOfTonalPeak[nrOfFIS - 1] ), 1 );
1407 20 : upperIndex[nrOfFIS - 1] = m;
1408 20 : move16();
1409 20 : lowerIndex[nrOfFIS] = add( m, 1 );
1410 20 : move16();
1411 : }
1412 :
1413 2939 : indexOfTonalPeak[nrOfFIS++] = k;
1414 2939 : move16();
1415 :
1416 2939 : IF( EQ_16( nrOfFIS, MAX_NUMBER_OF_IDX ) )
1417 : {
1418 0 : BREAK;
1419 : }
1420 : /* Jump to the next foot of the peak. */
1421 2939 : k = upperIdx;
1422 2939 : move16();
1423 : }
1424 : }
1425 691548 : k = add( k, 1 );
1426 : }
1427 :
1428 1425 : *numIndexes = nrOfFIS;
1429 1425 : move16();
1430 1425 : return;
1431 : }
1432 :
1433 :
1434 1425 : static void ivas_RefineThresholdsUsingPitch_fx(
1435 : const Word16 nSamples,
1436 : const Word16 nSamplesCore,
1437 : const Word32 powerSpectrum[], /*Qx*/
1438 : const Word32 lastPitchLag, /*Qx*/
1439 : const Word32 currentPitchLag, /*Qx*/
1440 : Word16 *pF0, /*Q10*/
1441 : Word16 *thresholdModification /*Q10*/
1442 : )
1443 : {
1444 : Word16 pitchIsStable;
1445 : Word16 origF0;
1446 : Word32 L_tmp;
1447 :
1448 : /*pitchIsStable = (fabs(lastPitchLag-currentPitchLag) < 0.25f);*/
1449 1425 : pitchIsStable = 0;
1450 1425 : move16();
1451 1425 : L_tmp = L_abs( L_sub( lastPitchLag, currentPitchLag ) );
1452 1425 : if ( LT_32( L_tmp, 16384l /*0.25f Q16*/ ) )
1453 : {
1454 1425 : pitchIsStable = 1;
1455 1425 : move16();
1456 : }
1457 :
1458 1425 : IF( pitchIsStable )
1459 : {
1460 1425 : ivas_GetF0_fx( nSamples,
1461 : nSamplesCore,
1462 : powerSpectrum, lastPitchLag, &origF0, pF0 );
1463 :
1464 1425 : modifyThresholds( *pF0, origF0, thresholdModification );
1465 : }
1466 : ELSE
1467 : {
1468 0 : *pF0 = 0;
1469 0 : move16();
1470 : }
1471 1425 : return;
1472 : }
1473 0 : static void findTonalComponents(
1474 : Word16 *indexOfTonalPeak, /* OUT Q0*/
1475 : Word16 *lowerIndex, /* OUT Q0*/
1476 : Word16 *upperIndex, /* OUT Q0*/
1477 : Word16 *numIndexes, /* OUT Q0*/
1478 : Word16 nSamples, /* IN */
1479 : const Word32 *powerSpectrum, /* IN Qx*/
1480 : Word16 F0, /* IN */
1481 : Word16 *thresholdModification, /* IN Q10*/
1482 : Word16 element_mode ) /* IN */
1483 : {
1484 : Word32 envelope[L_FRAME_MAX]; /*powerSpec_exp + LEVEL_EXP*/
1485 : Word32 smoothedSpectrum[L_FRAME_MAX]; /*powerSpec_exp + LEVEL_EXP*/
1486 : Word16 nrOfFIS;
1487 : Word16 upperIdx, lowerIdx, lowerBound;
1488 : Word16 k, j, m;
1489 : Word32 biggerNeighbor;
1490 : Word16 tmp_loop1, tmp_loop2, tmp_loop3;
1491 :
1492 0 : getEnvelope( nSamples, powerSpectrum, F0, envelope, smoothedSpectrum );
1493 :
1494 :
1495 0 : nrOfFIS = 0;
1496 0 : move16();
1497 0 : lowerBound = 0;
1498 0 : move16();
1499 :
1500 0 : k = GROUP_LENGTH / 2;
1501 0 : move16();
1502 0 : tmp_loop1 = sub( nSamples, ( GROUP_LENGTH - GROUP_LENGTH / 2 ) );
1503 0 : tmp_loop2 = sub( nSamples, 1 );
1504 0 : WHILE( LE_16( k, tmp_loop1 ) )
1505 : {
1506 : /* There is 3 bits headroom in envelope and max of thresholdModification is 16384, so shifting left for 4 would produce overflow only when the result is anyhow close to 1 */
1507 0 : IF( GT_32( L_shr( smoothedSpectrum[k], 1 ), L_shl( Mpy_32_16_1( envelope[k] /*Q28,powerSpec_exp*/, thresholdModification[k] /*Q10*/ ), 4 ) ) )
1508 : {
1509 : /* The check that bin at k is bigger than bins at k-1 and k+1 is needed to avoid deadlocks when the thresholds are low. */
1510 : /* It removes some true peaks, especially if non weighted sum is used for the smoothed spectrum. */
1511 0 : biggerNeighbor = L_max( powerSpectrum[k - 1], powerSpectrum[k + 1] ); /*Qx*/
1512 :
1513 0 : IF( GE_32( powerSpectrum[k], biggerNeighbor ) )
1514 : {
1515 : /* Find the right foot */
1516 0 : upperIdx = add( k, 1 );
1517 0 : WHILE( LT_16( upperIdx, tmp_loop2 ) )
1518 : {
1519 0 : IF( LT_32( powerSpectrum[upperIdx], powerSpectrum[upperIdx + 1] ) )
1520 : {
1521 : /* Side lobes may increase for certain amount */
1522 0 : IF( LT_32( L_shl( Mpy_32_16_1( powerSpectrum[upperIdx], ALLOWED_SIDE_LOBE_FLUCTUATION ), ALLOWED_SIDE_LOBE_FLUCTUATION_EXP ), powerSpectrum[upperIdx + 1] ) )
1523 : {
1524 0 : BREAK;
1525 : }
1526 : /* Check for further decrease after a side lobe increase */
1527 0 : FOR( j = add( upperIdx, 1 ); j < tmp_loop2; j++ )
1528 : {
1529 0 : IF( LT_32( powerSpectrum[j], L_shl( Mpy_32_16_1( powerSpectrum[j + 1], ALLOWED_SIDE_LOBE_FLUCTUATION ), ALLOWED_SIDE_LOBE_FLUCTUATION_EXP ) ) )
1530 : {
1531 0 : BREAK;
1532 : }
1533 : }
1534 : /* Side lobe increase must be 2 times smaller than the decrease to the foot */
1535 : /* Eq. to 2.0f*powerSpectrum[lowerIdx-1]/powerSpectrum[lowerIdx] > powerSpectrum[lowerIdx]/powerSpectrum[j] */
1536 0 : test();
1537 0 : test();
1538 0 : test();
1539 0 : IF( ( EQ_16( element_mode, EVS_MONO ) && GT_32( Mpy_32_32( L_shl( powerSpectrum[upperIdx + 1], 1 ), powerSpectrum[j] ), Mpy_32_32( powerSpectrum[upperIdx], powerSpectrum[upperIdx] ) ) ) ||
1540 : ( NE_16( element_mode, EVS_MONO ) && ( GT_64( W_mult_32_32( L_shl( powerSpectrum[upperIdx + 1], 1 ), powerSpectrum[j] ), W_mult_32_32( powerSpectrum[upperIdx], powerSpectrum[upperIdx] ) ) ) ) )
1541 : {
1542 : BREAK;
1543 : }
1544 0 : upperIdx = sub( j, 1 );
1545 : }
1546 0 : upperIdx = add( upperIdx, 1 );
1547 : }
1548 : /* left foot */
1549 0 : lowerIdx = sub( k, 1 );
1550 0 : WHILE( GT_16( lowerIdx, lowerBound ) )
1551 : {
1552 0 : IF( LT_32( powerSpectrum[lowerIdx], powerSpectrum[lowerIdx - 1] ) )
1553 : {
1554 : /* Side lobes may increase for certain amount */
1555 0 : IF( LT_32( L_shl( Mpy_32_16_1( powerSpectrum[lowerIdx], ALLOWED_SIDE_LOBE_FLUCTUATION ), ALLOWED_SIDE_LOBE_FLUCTUATION_EXP ), powerSpectrum[lowerIdx - 1] ) )
1556 : {
1557 0 : BREAK;
1558 : }
1559 : /* Check for further decrease after a side lobe increase */
1560 0 : FOR( j = sub( lowerIdx, 1 ); j > 0; j-- )
1561 : {
1562 0 : IF( LT_32( powerSpectrum[j], L_shl( Mpy_32_16_1( powerSpectrum[j - 1], ALLOWED_SIDE_LOBE_FLUCTUATION ), ALLOWED_SIDE_LOBE_FLUCTUATION_EXP ) ) )
1563 : {
1564 0 : BREAK;
1565 : }
1566 : }
1567 : /* Side lobe increase must be 2 times smaller than the decrease to the foot */
1568 : /* Eq. to 2.0f*powerSpectrum[lowerIdx-1]/powerSpectrum[lowerIdx] > powerSpectrum[lowerIdx]/powerSpectrum[j] */
1569 0 : IF( GT_32( Mpy_32_32( L_shl( powerSpectrum[lowerIdx - 1], 1 ), powerSpectrum[j] ), Mpy_32_32( powerSpectrum[lowerIdx], powerSpectrum[lowerIdx] ) ) )
1570 : {
1571 0 : BREAK;
1572 : }
1573 0 : lowerIdx = add( j, 1 );
1574 : }
1575 0 : lowerIdx = sub( lowerIdx, 1 );
1576 : }
1577 :
1578 0 : lowerBound = upperIdx;
1579 0 : move16();
1580 :
1581 : /* Check if there is a bigger peak up to the next peak foot */
1582 0 : tmp_loop3 = s_min( upperIdx, tmp_loop1 );
1583 0 : FOR( j = s_max( GROUP_LENGTH / 2, lowerIdx ); j <= tmp_loop3; j++ )
1584 : {
1585 0 : if ( GT_32( powerSpectrum[j], powerSpectrum[k] ) )
1586 : {
1587 :
1588 0 : k = j;
1589 0 : move16();
1590 : }
1591 : }
1592 :
1593 0 : assert( ( nrOfFIS == 0 ) || ( indexOfTonalPeak[nrOfFIS - 1] < k ) );
1594 :
1595 0 : lowerIndex[nrOfFIS] = sub( k, GROUP_LENGTH / 2 );
1596 0 : move16();
1597 :
1598 0 : upperIndex[nrOfFIS] = add( k, ( GROUP_LENGTH - GROUP_LENGTH / 2 - 1 ) );
1599 0 : move16();
1600 :
1601 0 : test();
1602 0 : IF( ( nrOfFIS > 0 ) && ( LE_16( lowerIndex[nrOfFIS], upperIndex[nrOfFIS - 1] ) ) )
1603 : {
1604 0 : m = shr( add( k, indexOfTonalPeak[nrOfFIS - 1] ), 1 );
1605 0 : upperIndex[nrOfFIS - 1] = m;
1606 0 : move16();
1607 0 : lowerIndex[nrOfFIS] = add( m, 1 );
1608 0 : move16();
1609 : }
1610 :
1611 0 : indexOfTonalPeak[nrOfFIS++] = k;
1612 0 : move16();
1613 :
1614 0 : IF( EQ_16( nrOfFIS, MAX_NUMBER_OF_IDX ) )
1615 : {
1616 0 : BREAK;
1617 : }
1618 : /* Jump to the next foot of the peak. */
1619 0 : k = upperIdx;
1620 0 : move16();
1621 : }
1622 : }
1623 0 : k = add( k, 1 );
1624 : }
1625 :
1626 0 : *numIndexes = nrOfFIS;
1627 0 : move16();
1628 0 : return;
1629 : }
|