Line data Source code
1 : /*====================================================================================
2 : EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
3 : ====================================================================================*/
4 :
5 : /*This BASOP port is up to date with trunk rev. 36554*/
6 :
7 : #include <assert.h>
8 : #include <stdint.h>
9 : #include "options.h"
10 : #include "cnst.h"
11 : #include "prot_fx.h"
12 : #include "basop32.h"
13 : #include "basop_util.h"
14 : /*-------------------------------------------------------------------------
15 : *
16 : * Perform resynchronisation of the last glottal pulse in voiced lost frame
17 : *
18 : *------------------------------------------------------------------------*/
19 :
20 :
21 : /** Get the location of the minimum energy in the given signal.
22 : * @returns Index of the position of the minimum energy, that is the position i where filter(x[i-filterLength/2],...,x[i+(filterLength-filterLength/2)-1]) is at maximum.
23 : */
24 2444 : static Word16 GetMinimumPosition_fx(
25 : Word16 const *x, /* Input signal. Qx*/
26 : Word16 length, /* The length of the input signal. Q0*/
27 : Word16 filterLength /* the length of the filter length used for the energy calculation. Q0*/
28 : )
29 : {
30 : Word16 iMinEnergyPos, center, i;
31 : Word16 cnt, tmp_e, tmp16;
32 : Word32 energy, energy_old, tmptest;
33 : #ifndef ISSUE_1866_replace_overflow_libdec
34 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
35 : Flag Overflow = 0;
36 : move16();
37 : #endif
38 : #endif
39 :
40 2444 : filterLength = s_min( filterLength, length ); /*Q0*/
41 2444 : center = shr( filterLength, 1 ); /*Q0*/
42 2444 : iMinEnergyPos = center; /*Q0*/
43 2444 : move16();
44 :
45 2444 : IF( filterLength > 0 )
46 : {
47 1774 : center = add( center, 1 );
48 1774 : energy = L_deposit_l( 0 );
49 1774 : energy_old = L_deposit_l( 0 );
50 :
51 1774 : cnt = sub( length, filterLength ); /*Q0*/
52 :
53 1774 : tmp_e = 0;
54 1774 : move16();
55 322381 : FOR( i = 0; i < cnt; i++ )
56 : {
57 320607 : tmp16 = shr( x[i], tmp_e ); /*Qx*/
58 320607 : energy = L_msu_sat( energy_old, tmp16, tmp16 ); /*2Qx+1*/
59 320607 : tmp16 = shr( x[( i + filterLength )], tmp_e ); /*Qx*/
60 : BASOP_SATURATE_WARNING_OFF_EVS /*Saturation will be handled*/
61 320607 : energy = L_mac_sat( energy, tmp16, tmp16 ); /*2Qx+1*/
62 : BASOP_SATURATE_WARNING_ON_EVS
63 :
64 : /*if (energy == MAXVAL_WORD32)*/
65 : BASOP_SATURATE_WARNING_OFF_EVS /*saturates if energy < 0*/
66 : #ifdef ISSUE_1866_replace_overflow_libdec
67 320607 : tmptest = L_sub_sat( energy, MAXVAL_WORD32 );
68 : /*Q31*/
69 : #else
70 : tmptest = L_sub_o( energy, MAXVAL_WORD32, &Overflow ); /*Q31*/
71 : #endif
72 : BASOP_SATURATE_WARNING_ON_EVS
73 320607 : IF( tmptest == 0 )
74 : {
75 0 : tmp_e = add( tmp_e, 1 );
76 0 : energy = L_shr( energy_old, 2 );
77 0 : tmp16 = shr( x[i], tmp_e ); /*Qx-1*/
78 0 : energy = L_msu( energy, tmp16, tmp16 ); /*2Qx-1*/
79 0 : tmp16 = shr( x[( i - filterLength )], tmp_e );
80 0 : energy = L_mac( energy, tmp16, tmp16 ); /*2Qx-1*/
81 : }
82 :
83 320607 : IF( energy < 0 )
84 : {
85 11552 : iMinEnergyPos = add( i, center ); /*Q0*/
86 11552 : tmp_e = 0;
87 11552 : move16();
88 11552 : energy = 0;
89 11552 : move16();
90 : }
91 320607 : energy_old = L_add( energy, 0 );
92 : }
93 : }
94 :
95 2444 : return iMinEnergyPos; /*Q0*/
96 : }
97 :
98 : /*!
99 : * \brief FindMaxPeak - Get the location of the maximum peak in the given signal.
100 : *
101 : * \returns Index of the position of the maximum peak, that is the position i where abs(x[i]) has it's maximum.
102 : */
103 :
104 1233 : static Word16 FindMaxPeak_fx(
105 : Word16 /*float*/ const *x, /*<!i : Input signal. Q15*/
106 : Word16 /*int*/ length /*<!i : The length of the input signal.*/
107 : )
108 : {
109 : Word16 iMax, i;
110 :
111 1233 : iMax = 0;
112 1233 : move16();
113 287151 : FOR( i = 1; i < length; i++ )
114 : {
115 285918 : if ( GT_16( abs_s( x[i] ), abs_s( x[iMax] ) ) )
116 : {
117 6796 : iMax = i; /*Q0*/
118 6796 : move16();
119 : }
120 : }
121 :
122 1233 : return iMax; /*Q0*/
123 : }
124 :
125 764 : static void AddSamples_fx(
126 : Word16 const *const old_exc, /*Qx*/
127 : Word16 *const new_exc, /*Qx*/
128 : Word16 const L_frame, /*Q0*/
129 : Word16 const n_samples_to_add, /*Q0*/
130 : Word16 const min_pos[], /*Q0*/
131 : Word16 const points_by_pos[], /*Q0*/
132 : Word16 const nb_min /*Q0*/
133 : )
134 : {
135 : Word16 *pt_dest;
136 : Word16 const *pt_src;
137 : Word16 last_min_pos, i, j;
138 : Word16 ftmp;
139 :
140 764 : pt_dest = new_exc; /*Qx*/
141 764 : pt_src = old_exc; /*Qx*/
142 764 : last_min_pos = 0;
143 764 : move16();
144 :
145 4165 : FOR( i = 0; i < nb_min; i++ )
146 : {
147 : /* Copy section */
148 507705 : FOR( j = min_pos[i] - last_min_pos; j > 0; j-- )
149 : {
150 504304 : *pt_dest++ = *pt_src++; /*Qx*/
151 504304 : move16();
152 : }
153 : /* Add some samples */
154 3401 : ftmp = negate( mult( *pt_src, 1638 /*.05f Q15*/ ) ); /*Qx*/
155 :
156 8082 : FOR( j = 0; j < points_by_pos[i]; j++ )
157 : {
158 4681 : *pt_dest++ = ftmp; /*Qx*/
159 4681 : move16();
160 4681 : ftmp = negate( ftmp ); /*Qx*/
161 : }
162 : /* Prepare for the next loop iteration */
163 3401 : last_min_pos = min_pos[i]; /*Q0*/
164 3401 : move16();
165 : }
166 : /* Copy remaining length */
167 46595 : FOR( j = sub( L_frame, add( n_samples_to_add, last_min_pos ) ); j > 0; j-- )
168 : {
169 45831 : *pt_dest++ = *pt_src++; /*Qx*/
170 45831 : move16();
171 : }
172 764 : }
173 :
174 469 : static void RemoveSamples_fx(
175 : Word16 /*float*/ const *const old_exc, /*i : Qx */
176 : Word16 /*float*/ *const new_exc, /*o : Qx */
177 : Word16 /*int*/ const L_frame, /*i : Q0 */
178 : Word16 /*int*/ const n_samples_to_add, /*i : Q0 */
179 : Word16 /*int*/ const min_pos[], /*i : Q0 */
180 : Word16 /*int*/ const points_by_pos[], /*i : Q0 */
181 : Word16 /*int*/ const nb_min /*i : Q0*/
182 : )
183 : {
184 : Word16 /*float*/ *pt_dest;
185 : Word16 /*float*/ const *pt_src;
186 : Word16 /*int*/ last_min_pos, i, j;
187 :
188 :
189 469 : pt_dest = new_exc + L_frame; /*Qx*/
190 469 : last_min_pos = sub( L_frame, n_samples_to_add ); /*Q0*/
191 :
192 2835 : FOR( i = sub( nb_min, 1 ); i >= 0; i-- )
193 : {
194 : /* Compute len to copy */
195 : /* Copy section, removing some samples */
196 2366 : pt_src = old_exc + last_min_pos; /*Qx*/
197 :
198 323794 : FOR( j = sub( last_min_pos, add( min_pos[i], points_by_pos[i] ) ); j > 0; j-- )
199 : {
200 321428 : *--pt_dest = *--pt_src; /*Qx*/
201 321428 : move16();
202 : }
203 : /* Prepare for the next loop iteration */
204 2366 : last_min_pos = min_pos[i]; /*Q0*/
205 2366 : move16();
206 : }
207 : /* Copy remaining length */
208 469 : pt_src = old_exc + last_min_pos; /*Qx*/
209 :
210 18625 : FOR( j = last_min_pos; j > 0; j-- )
211 : {
212 18156 : *--pt_dest = *--pt_src; /*Qx*/
213 18156 : move16();
214 : }
215 469 : }
216 :
217 : /** Resynchronize glotal pulse positions of the signal in src_exc and store it in dst_exc.
218 : * src_exc holds on call the harmonic part of the signal with the constant pitch, constructed by repeating the last pitch cycle of length pitchStart.
219 : * dst_exc holds on return the harmonic part of the signal with the pitch changing from pitchStart to pitchEnd.
220 : * src_exc and dst_exc can overlap, but src_exc < dst_exc must be fullfiled.
221 : */
222 : /*This BASOP port is up to date with trunk rev 8779(svnext2)*/
223 1233 : void PulseResynchronization_fx(
224 : Word16 /*float*/ const *const src_exc, /*<!i : Input excitation buffer Q15*/
225 : Word16 /*float*/ *const dst_exc, /*<!o : Output excitation buffer Q15*/
226 : Word16 /*int*/ const nFrameLength, /*<!i : Length of the frame, that is the length of the valid data in the excitation buffer on return. Q0 */
227 : Word16 /*int*/ const nSubframes, /*<!i : Number of subframes in the excitation buffer. nFrameLength must be divisible by nSubframes Q0 */
228 : Word32 /*float*/ const pitchStart, /*<!i : Pitch at the end of the last frame Q16*/
229 : Word32 /*float*/ const pitchEnd /*<!i : Pitch at the end of the current frame Q16*/
230 : )
231 : {
232 : Word16 /*int*/ T0, i, k;
233 : Word16 /*float*/ perCycleDeltaDelta, cycleDelta, freqStart, fractionalLeft;
234 : Word16 /*int*/ roundedPitchStart, nSamplesDelta, nSamplesDeltaRemain, iMinPos1, iMinPos[NB_PULSES_MAX + 1], iDeltaSamples[NB_PULSES_MAX + 1], maxDeltaSamples, roundedCycleDelta;
235 : Word16 tmp16, tmp16_a, freqStart_e /*exponent of freqStart*/, tmp_e, samplesDelta_e, perCycleDeltaDelta_e, cycleDelta_e, tmp2_e, tmp3_e;
236 : Word32 /* pitchDelta, */ tmp32, tmp32_a, tmp32_b, samplesDelta, absPitchDiff, cycleDelta32;
237 : #ifndef ISSUE_1866_replace_overflow_libdec
238 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
239 : Flag Overflow = 0;
240 : move32();
241 : #endif
242 : #endif
243 :
244 :
245 1233 : test();
246 1233 : test();
247 1233 : test();
248 1233 : test();
249 1233 : test();
250 1233 : test();
251 1233 : IF( ( LT_32( L_deposit_h( nFrameLength ), pitchStart ) ) || ( pitchStart <= 0 ) || ( pitchEnd <= 0 ) || ( LT_16( nSubframes, 1 ) ) || ( GT_16( nSubframes, 5 ) ) || ( LE_32( Mpy_32_16_1( pitchEnd, add( nSubframes, 1 ) ), Mpy_32_16_1( pitchStart, sub( nSubframes, 1 ) ) ) ) || ( src_exc - dst_exc >= 0 ) )
252 : {
253 : /* This is error handling and recovery that should never occur. */
254 0 : test();
255 0 : IF( src_exc != dst_exc && LE_16( nFrameLength, 1200 ) )
256 : {
257 0 : Copy( src_exc, dst_exc, nFrameLength ); /*Q15*/
258 : }
259 0 : return;
260 : }
261 :
262 1233 : roundedPitchStart = round_fx( pitchStart ); /*Q0*/
263 :
264 : /* freqStart = 1.0f/roundedPitchStart; */
265 1233 : freqStart_e = 15;
266 1233 : move16();
267 1233 : freqStart = Inv16( roundedPitchStart, &freqStart_e ); /*Q15,freqStart_e*/
268 :
269 : /* Calculate number of samples to be removed (if negative) or added (if positive) */
270 : /*samplesDelta = 0.5f*pitchDelta*nFrameLength*(nSubframes+1)*freqStart;*/
271 : /* pitchDelta*freqStart = ((pitchEnd - pitchStart)/roundedPitchStart)/nSubframes */
272 1233 : tmp16 = shl( roundedPitchStart, 2 ); /*Q0*/
273 1233 : if ( EQ_16( nSubframes, 5 ) )
274 : {
275 630 : tmp16 = add( tmp16, roundedPitchStart ); /*Q0*/ /*tmp16=roundedPitchStart*nSubframes*/
276 : }
277 1233 : tmp_e = norm_s( tmp16 );
278 1233 : tmp16 = shl( tmp16, tmp_e ); /*Q0,-tmp_e*/ /*tmp16=roundedPitchStart*nSubframes*/
279 1233 : tmp_e = sub( 15, tmp_e );
280 1233 : tmp16 = Inv16( tmp16, &tmp_e ); /*Q15,tmp_e*/ /*tmp16=1.0/(roundedPitchStart*nSubframes)*/
281 1233 : tmp32 = L_sub( pitchEnd, pitchStart ); /*Q16*/
282 1233 : tmp2_e = norm_l( tmp32 );
283 1233 : tmp32 = L_shl( tmp32, tmp2_e ); /*Q16,-tmp2_e*/
284 1233 : tmp32 = Mpy_32_16_1( tmp32, tmp16 ); /*Q16,tmp_e-tmp2_e*/ /*tmp32=pitchDelta*freqStart*/
285 1233 : tmp_e = sub( tmp_e, tmp2_e ); /* sum up all the scalings for tmp32 */
286 :
287 1233 : tmp16 = imult1616( nFrameLength, add( nSubframes, 1 ) ); /*Q0*/ /*tmp16=nFrameLength*(nSubframes+1)*/
288 1233 : tmp2_e = norm_s( tmp16 );
289 1233 : tmp16 = shl( tmp16, tmp2_e ); /*Q0+tmp2_e*/
290 :
291 1233 : tmp32 = Mpy_32_16_1( tmp32, tmp16 ); /*Q1 scaling (tmp_e-tmp2_e-1), -1 because of 0.5f*/ /*tmp32=0.5f*pitchDelta*nFrameLength*(nSubframes+1)*freqStart*/
292 1233 : tmp_e = sub( sub( tmp_e, tmp2_e ), 1 ); /* sum up all the scalings for tmp32 */
293 1233 : tmp_e = add( tmp_e, 31 - 1 ); /* tmp32 is now regarded as Q31 with scaling tmp_e */
294 :
295 : /*samplesDelta -= nFrameLength*(1.0f-pitchStart*freqStart);*/
296 1233 : tmp2_e = norm_l( pitchStart );
297 1233 : tmp32_a = L_shl( pitchStart, tmp2_e ); /*Q16+tmp2_e*/
298 1233 : tmp32_a = Mpy_32_16_1( tmp32_a /*Q16,-tmp2_e*/, freqStart /*Q15,freqStart_e*/ ); /*Q16, scaling (freqStart_e-tmp2_e)*/ /*tmp32_a=pitchStart*freqStart*/
299 1233 : tmp16 = norm_l( tmp32_a );
300 1233 : tmp32_a = L_shl( tmp32_a, tmp16 );
301 1233 : tmp2_e = sub( sub( freqStart_e, tmp16 ), tmp2_e ); /* sum up all scalings for tmp32_a */
302 1233 : tmp2_e = add( tmp2_e, 31 - 16 ); /* tmp32_a is now regarded as Q31 with scaling tmp2_e */
303 :
304 1233 : tmp3_e = tmp2_e;
305 1233 : move16();
306 1233 : tmp32_a = L_negate( tmp32_a );
307 : #ifdef ISSUE_1866_replace_overflow_libdec
308 1233 : tmp32_a = L_add( L_shl_sat( 1, sub( 31, tmp3_e ) ), tmp32_a ); /*Q31,tmp3_e*/ /*tmp32_a= 1.0f-pitchStart*freqStart*/
309 : #else
310 : tmp32_a = L_add( L_shl_o( 1, sub( 31, tmp3_e ), &Overflow ), tmp32_a ); /*Q31,tmp3_e*/ /*tmp32_a= 1.0f-pitchStart*freqStart*/
311 : #endif
312 1233 : tmp2_e = norm_s( nFrameLength );
313 1233 : tmp16_a = shl( nFrameLength, tmp2_e ); /*Q0+tmp2_e*/
314 1233 : tmp32_a = Mpy_32_16_1( tmp32_a /*Q31,tmp3_e*/, tmp16_a /*Q0,-tmp2_e*/ ); /*Q16,tmp3_e-tmp2_e*/ /*tmp32_a= nFrameLength*(1.0f-pitchStart*freqStart)*/
315 1233 : tmp2_e = add( sub( tmp3_e, tmp2_e ), 15 );
316 1233 : samplesDelta = BASOP_Util_Add_Mant32Exp( tmp32, tmp_e, L_negate( tmp32_a ), tmp2_e, &samplesDelta_e ); /*Q31,samplesDelta_e*/
317 :
318 : /* To have enough samples in the buffer of length nFrameLength*(nSubframes+1)/nSubframes, pitchEnd/pitchEnd must be bigger than (nSubframes-1)/(nSubframes+1)=1-2/(nSubframes+1) */
319 : /* Thus nSubframes must be bigger than 1 */
320 1233 : nSamplesDelta = round_fx( L_shl( samplesDelta, sub( samplesDelta_e, 31 - 16 ) ) ); /*Q0*/
321 1233 : nSamplesDeltaRemain = abs_s( nSamplesDelta );
322 : /* Find the location of the glottal pulse */
323 1233 : T0 = FindMaxPeak_fx( src_exc, roundedPitchStart ); /*Q0*/
324 : /* Get the index of the last pulse in the resynchronized frame */
325 : /*k = (int)ceil((nFrameLength-nSamplesDelta-T0)*freqStart - 1);*/
326 1233 : tmp32 = BASOP_Util_Add_Mant32Exp( L_mult( sub( nFrameLength, add( nSamplesDelta, T0 ) ), freqStart ) /*Q16*/, add( freqStart_e, 31 - 16 ), (Word32) 0x80000000 /*-1.f Q31*/, 0, &tmp_e );
327 1233 : tmp32 = L_shl( tmp32, sub( tmp_e, 31 - 16 ) ) /*Q16*/;
328 1233 : tmp32 = L_add( tmp32, 65536l /*1.f Q16*/ );
329 1233 : k = extract_h( tmp32 );
330 1233 : test();
331 1233 : IF( ( k >= 0 ) && LE_16( add( k, 1 ), NB_PULSES_MAX ) )
332 : {
333 1233 : absPitchDiff = L_abs( L_sub( L_deposit_h( roundedPitchStart ), pitchEnd ) ); /*Q16*/
334 :
335 : /* Calculate the delta of the samples to be added/removed between consecutive cycles */
336 : /*perCycleDeltaDelta = (absPitchDiff*(nFrameLength-samplesDelta) - (float)fabs(samplesDelta)*roundedPitchStart)
337 : / ((k+1)*(T0+0.5f*k*roundedPitchStart));*/
338 1233 : tmp32 = L_sub( L_deposit_h( nFrameLength ), L_shl( samplesDelta, sub( samplesDelta_e, 31 - 16 ) ) ); /*Q16*/
339 1233 : tmp_e = 15; /*tmp32 = Q31,tmp_e*/
340 1233 : move16();
341 1233 : tmp2_e = norm_l( tmp32 );
342 1233 : tmp32 = L_shl( tmp32, tmp2_e );
343 1233 : tmp_e = sub( tmp_e, tmp2_e ); /*tmp32 = Q31,tmp_e*/
344 1233 : tmp2_e = norm_l( absPitchDiff );
345 1233 : tmp32_b = L_shl( absPitchDiff, tmp2_e ); /*Q16+tmp2_e*/
346 1233 : tmp_e = sub( tmp_e, tmp2_e );
347 1233 : tmp32 = Mpy_32_16_1( tmp32_b, round_fx( tmp32 ) ); /*Q16,tmp_e*/ /*tmp32 = absPitchDiff*(nFrameLength-samplesDelta)*/
348 1233 : tmp32_a = Mpy_32_16_1( L_abs( samplesDelta ) /*Q31,samplesDelta_e*/, roundedPitchStart /*Q0*/ ); /*Q16,samplesDelta_e*/ /*tmp32_a=fabs(samplesDelta)*roundedPitchStart*/
349 1233 : tmp32 = BASOP_Util_Add_Mant32Exp( tmp32, add( tmp_e, 31 - 16 ), L_negate( tmp32_a ), add( samplesDelta_e, 31 - 16 ), &tmp_e ); /*Q31,tmp_e*/ /*tmp32=absPitchDiff*(nFrameLength-samplesDelta)-fabs(samplesDelta)*roundedPitchStart*/
350 1233 : tmp16 = imult1616( add( k, 1 ), add( shl( T0, 1 ), imult1616( k, roundedPitchStart ) ) ); /*Q0,-1*/ /*tmp16=(k+1)*(T0+0.5f*k*roundedPitchStart)*/
351 1233 : perCycleDeltaDelta = BASOP_Util_Divide3216_Scale( tmp32 /*Q31,tmp_e*/, tmp16 /*Q0,-1*/, &perCycleDeltaDelta_e ); /*Q15,perCycleDeltaDelta_e*/
352 1233 : perCycleDeltaDelta_e = add( perCycleDeltaDelta_e, sub( tmp_e, -1 + 15 ) );
353 1233 : tmp_e = norm_s( perCycleDeltaDelta );
354 1233 : perCycleDeltaDelta_e = sub( perCycleDeltaDelta_e, tmp_e );
355 1233 : perCycleDeltaDelta = shl( perCycleDeltaDelta, tmp_e ); /*Q15,perCycleDeltaDelta_e*/
356 :
357 :
358 : /* Calculate the integer number of samples to be added/removed in each pitch cycle */
359 : /*cycleDelta = max(0, (absPitchDiff-(k+1)*perCycleDeltaDelta)*T0*freqStart); */
360 1233 : tmp_e = norm_s( add( k, 1 ) );
361 1233 : tmp32 = L_mult( perCycleDeltaDelta /*Q15,perCycleDeltaDelta_e*/, shl( add( k, 1 ), tmp_e ) /*Q0, tmp_e*/ ) /*Q0+16, perCycleDeltaDelta_e-tmp_e*/;
362 1233 : tmp32 = BASOP_Util_Add_Mant32Exp( absPitchDiff /*Q16*/, 31 - 16, L_negate( tmp32 ), add( sub( perCycleDeltaDelta_e, tmp_e ), 31 - 16 ), &tmp_e ); /*Q31,tmp_e*/
363 1233 : tmp32 = Mpy_32_16_1( tmp32, T0 /*Q0*/ ); /*Q16,tmp_e*/
364 1233 : tmp32 = Mpy_32_16_1( tmp32 /*Q16,tmp_e*/, freqStart /*Q15,freqStart_e*/ ) /*Q16, tmp_e+(freqStart_e)*/;
365 1233 : tmp32 = L_max( 0, tmp32 );
366 1233 : cycleDelta_e = add( tmp_e, freqStart_e );
367 1233 : tmp32_a = L_shl( tmp32, cycleDelta_e );
368 1233 : roundedCycleDelta = extract_h( L_abs( tmp32_a ) );
369 1233 : if ( tmp32 < 0 )
370 : {
371 0 : roundedCycleDelta = negate( roundedCycleDelta );
372 : }
373 1233 : fractionalLeft = lshr( extract_l( tmp32_a ), 1 ); /*Q15*/
374 1233 : tmp_e = sub( 15, norm_l( tmp32 ) );
375 1233 : cycleDelta_e = add( cycleDelta_e, tmp_e );
376 1233 : tmp32 = L_shr( tmp32, sub( tmp_e, 15 ) ); /*Q31 frac, cycleDelta_e*/
377 : #ifdef ISSUE_1866_replace_overflow_libdec
378 1233 : cycleDelta = round_fx_sat( tmp32 ); /*Q15, cycleDelta_e*/
379 : #else
380 : cycleDelta = round_fx_o( tmp32, &Overflow ); /*Q15, cycleDelta_e*/
381 : #endif
382 1233 : if ( cycleDelta == 0 )
383 : {
384 93 : cycleDelta_e = 0;
385 93 : move16();
386 : }
387 :
388 : /*roundedCycleDelta = (int)(cycleDelta); */ /*done above*/
389 1233 : iDeltaSamples[0] = roundedCycleDelta; /*Q0*/
390 1233 : move16();
391 : /*fractionalLeft = cycleDelta-roundedCycleDelta;*/ /*done above*/
392 1233 : nSamplesDeltaRemain = sub( nSamplesDeltaRemain, roundedCycleDelta ); /*Q0*/
393 :
394 1233 : tmp_e = s_max( 2, k );
395 1233 : tmp_e = norm_s( tmp_e ); /*maximum norming factor for following loop*/
396 :
397 :
398 4534 : FOR( i = 1; i <= k; i++ )
399 : {
400 : /*cycleDelta = (absPitchDiff-(k+1-i)*perCycleDeltaDelta) + fractionalLeft; */
401 3301 : tmp32 = L_mult( perCycleDeltaDelta /*Q15,perCycleDeltaDelta_e*/, shl( sub( add( k, 1 ), i ), tmp_e ) /*Q0, tmp_e*/ ) /*Q0+16, perCycleDeltaDelta_e-tmp_e*/; /*calcultion of base for first iteration*/
402 3301 : tmp32 = L_shl( tmp32, sub( perCycleDeltaDelta_e, tmp_e ) ); /*Q16*/
403 3301 : tmp32_a = L_sub( absPitchDiff, tmp32 );
404 3301 : tmp32_b = L_lshl( L_deposit_l( fractionalLeft /*Q15*/ ), 1 ) /*Q16*/;
405 3301 : cycleDelta32 = L_add( tmp32_a, tmp32_b ); /*Q16*/
406 3301 : cycleDelta32 = L_max( 0, cycleDelta32 );
407 :
408 : /* Make sure that the number of samples increases */
409 3301 : IF( GT_32( L_deposit_h( roundedCycleDelta ), cycleDelta32 ) )
410 : {
411 211 : iDeltaSamples[i] = roundedCycleDelta; /*Q0*/
412 211 : move16();
413 211 : roundedCycleDelta = extract_h( cycleDelta32 ); /* cycleDelta32 should never be < 0 here Q0*/
414 211 : iDeltaSamples[i - 1] = roundedCycleDelta; /*Q0*/
415 211 : move16();
416 : }
417 : ELSE
418 : {
419 3090 : roundedCycleDelta = extract_h( cycleDelta32 ); /* cycleDelta32 should never be < 0 here Q0*/
420 3090 : iDeltaSamples[i] = roundedCycleDelta; /*Q0*/
421 3090 : move16();
422 : }
423 : /*fractionalLeft = cycleDelta-roundedCycleDelta = cycleDelta-(int)cycleDelta;*/
424 3301 : fractionalLeft = lshr( extract_l( cycleDelta32 ), 1 ); /*Q15*/ /* cycleDelta32 should never be < 0 here */
425 3301 : nSamplesDeltaRemain = sub( nSamplesDeltaRemain, roundedCycleDelta );
426 : }
427 1233 : iDeltaSamples[( k + 1 )] = s_max( 0, nSamplesDeltaRemain );
428 1233 : move16();
429 1233 : maxDeltaSamples = s_max( iDeltaSamples[k], iDeltaSamples[( k + 1 )] ); /*Q0*/
430 :
431 : /* Find the location of the minimum energy between the first two pulses */
432 :
433 : /*iMinPos1 = T0+GetMinimumPosition_fx(src_exc+T0, min(roundedPitchStart, (nSubframes+1)*nFrameLength/nSubframes-T0), maxDeltaSamples);*/
434 1233 : BASOP_Util_Divide_MantExp( add( nSubframes, 1 ), 15, nSubframes, 15, &tmp16, &tmp_e );
435 1233 : tmp32 = L_mult( nFrameLength /*Q0*/, tmp16 /*Q15,tmp_e*/ ); /*Q16,tmp_e*/
436 1233 : tmp16 = round_fx( L_shl( tmp32, tmp_e ) ); /*Q0*/
437 1233 : tmp16 = sub( tmp16, T0 ); /*Q0*/
438 1233 : tmp16 = s_min( roundedPitchStart, tmp16 );
439 :
440 1233 : iMinPos1 = GetMinimumPosition_fx(
441 1233 : src_exc + T0, /*Qx*/
442 : tmp16, /*Q0*/
443 : maxDeltaSamples /*Q0*/
444 : );
445 1233 : iMinPos1 = add( iMinPos1, T0 );
446 :
447 :
448 1233 : IF( nSamplesDelta < 0 )
449 : {
450 : /* Find the location of the minimum energy before the first pulse */
451 :
452 469 : IF( GT_16( iMinPos1, add( roundedPitchStart, shr( iDeltaSamples[0], 1 ) ) ) )
453 : {
454 247 : iMinPos[0] = sub( iMinPos1, sub( roundedPitchStart, shr( iDeltaSamples[0], 1 ) ) ); /*Q0*/
455 247 : move16();
456 : }
457 : ELSE
458 : {
459 222 : iMinPos[0] = sub( GetMinimumPosition_fx( src_exc, T0, iDeltaSamples[0] ), shr( iDeltaSamples[0], 1 ) ); /*Q0*/
460 222 : move16();
461 : }
462 :
463 : /* Find the location of the minimum energy between the pulses */
464 1897 : FOR( i = 1; i <= k; i++ )
465 : {
466 1428 : iMinPos[i] = add( iMinPos1, sub( imult1616( sub( i, 1 ), roundedPitchStart ), shr( iDeltaSamples[i], 1 ) ) ); /*Q0*/
467 1428 : move16();
468 : }
469 : /* Find the location of the minimum energy after the last pulse */
470 :
471 469 : IF( LT_16( add( iMinPos1, add( imult1616( k, roundedPitchStart ), sub( iDeltaSamples[( k + 1 )], shr( iDeltaSamples[( k + 1 )], 1 ) ) ) ), sub( nFrameLength, nSamplesDelta ) ) )
472 : {
473 215 : iMinPos[( k + 1 )] = add( iMinPos1, sub( imult1616( k, roundedPitchStart ), shr( iDeltaSamples[( k + 1 )], 1 ) ) ); /*Q0*/
474 215 : move16();
475 : }
476 : ELSE
477 : {
478 : /*iMinPos[k+1] = T0+k*roundedPitchStart
479 : + GetMinimumPosition_fx(src_exc+T0+k*roundedPitchStart, nFrameLength-nSamplesDelta-(T0+k*roundedPitchStart), iDeltaSamples[k+1])
480 : - iDeltaSamples[k+1]/2; */
481 254 : tmp16 = GetMinimumPosition_fx( src_exc + add( T0, imult1616( k, roundedPitchStart ) ), sub( nFrameLength, add( nSamplesDelta, add( T0, imult1616( k, roundedPitchStart ) ) ) ), iDeltaSamples[( k + 1 )] ); /*Q0*/
482 254 : tmp16 = add( add( T0, imult1616( k, roundedPitchStart ) ), tmp16 );
483 254 : tmp16 = sub( tmp16, shr( iDeltaSamples[( k + 1 )], 1 ) );
484 254 : iMinPos[( k + 1 )] = tmp16;
485 254 : move16();
486 : }
487 :
488 469 : IF( GT_16( add( iMinPos[( k + 1 )], iDeltaSamples[( k + 1 )] ), sub( nFrameLength, nSamplesDelta ) ) )
489 : {
490 1 : iDeltaSamples[k] = add( iDeltaSamples[k], add( iMinPos[( k + 1 )], sub( iDeltaSamples[( k + 1 )], sub( nFrameLength, nSamplesDelta ) ) ) ); /*Q0*/
491 1 : move16();
492 1 : iDeltaSamples[( k + 1 )] = sub( nFrameLength, add( nSamplesDelta, iMinPos[( k + 1 )] ) ); /*Q0*/
493 1 : move16();
494 : }
495 :
496 : /* Remove samples at the given positions */
497 469 : RemoveSamples_fx( src_exc, dst_exc, nFrameLength, nSamplesDelta, iMinPos, iDeltaSamples, add( k, 2 ) );
498 : }
499 : ELSE
500 : {
501 : /* Find the location of the minimum energy before the first pulse */
502 764 : IF( GT_16( iMinPos1, roundedPitchStart ) )
503 : {
504 400 : iMinPos[0] = sub( iMinPos1, roundedPitchStart ); /*Q0*/
505 400 : move16();
506 : }
507 : ELSE
508 : {
509 364 : iMinPos[0] = GetMinimumPosition_fx( src_exc, T0, iDeltaSamples[0] ); /*Q0*/
510 364 : move16();
511 : }
512 : /* Find the location of the minimum energy between the pulses */
513 :
514 2637 : FOR( i = 1; i <= k; i++ )
515 : {
516 1873 : iMinPos[i] = iMinPos1; /*Q0*/
517 1873 : move16();
518 1873 : iMinPos1 = add( iMinPos1, roundedPitchStart ); /*Q0*/
519 : }
520 :
521 : /* Find the location of the minimum energy after the last pulse */
522 764 : IF( LT_16( iMinPos1, sub( nFrameLength, nSamplesDelta ) ) )
523 : {
524 393 : iMinPos[( k + 1 )] = iMinPos1;
525 393 : move16();
526 : }
527 : ELSE
528 : {
529 :
530 371 : tmp16 = GetMinimumPosition_fx( src_exc + add( T0, imult1616( k, roundedPitchStart ) ), sub( nFrameLength, add( nSamplesDelta, add( T0, imult1616( k, roundedPitchStart ) ) ) ), iDeltaSamples[( k + 1 )] ); /*Q0*/
531 371 : tmp16 = add( add( tmp16, T0 ), imult1616( k, roundedPitchStart ) );
532 371 : iMinPos[( k + 1 )] = tmp16; /*Q0*/
533 371 : move16();
534 : }
535 :
536 764 : IF( GT_16( add( iMinPos[( k + 1 )], iDeltaSamples[( k + 1 )] ), sub( nFrameLength, nSamplesDelta ) ) )
537 : {
538 8 : iDeltaSamples[k] = add( iDeltaSamples[k], add( iMinPos[( k + 1 )], sub( iDeltaSamples[( k + 1 )], sub( nFrameLength, nSamplesDelta ) ) ) ); /*Q0*/
539 8 : move16();
540 8 : iDeltaSamples[( k + 1 )] = sub( sub( nFrameLength, nSamplesDelta ), iMinPos[( k + 1 )] ); /*Q0*/
541 8 : move16();
542 : }
543 : /* Add samples at the given positions */
544 764 : AddSamples_fx( src_exc, dst_exc, nFrameLength, nSamplesDelta, iMinPos, iDeltaSamples, add( k, 2 ) );
545 : }
546 : }
547 : }
|