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