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