Line data Source code
1 : /*====================================================================================
2 : EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
3 : ====================================================================================*/
4 :
5 : #include <stdint.h>
6 : #include "options.h"
7 : #include "cnst.h"
8 : #include "prot_fx.h"
9 : #include "basop_util.h"
10 :
11 2994 : static Word16 TCX_MDCT_GetScaleFactor(
12 : const Word16 L, /* Q0 */
13 : Word16 *factor_e /* Q0 */
14 : )
15 : {
16 :
17 : Word16 factor;
18 :
19 2994 : IF( EQ_16( L, NORM_MDCT_FACTOR ) )
20 : {
21 0 : factor = 32767;
22 0 : move16();
23 0 : *factor_e = 0;
24 0 : move16();
25 : }
26 2994 : ELSE IF( EQ_16( L, 2 * NORM_MDCT_FACTOR ) )
27 : {
28 526 : factor = 23170;
29 526 : move16();
30 526 : *factor_e = 0;
31 526 : move16();
32 : }
33 2468 : ELSE IF( EQ_16( L, shl( NORM_MDCT_FACTOR, 2 ) ) )
34 : {
35 618 : factor = 16384;
36 618 : move16();
37 618 : *factor_e = 0;
38 618 : move16();
39 : }
40 : ELSE
41 : {
42 :
43 1850 : factor = mult_r( shl( L, 4 ), 26214 /*128.f / NORM_MDCT_FACTOR*/ ); /* 4Q11 */
44 1850 : *factor_e = 4;
45 1850 : move16();
46 :
47 1850 : factor = ISqrt16( factor, factor_e );
48 : }
49 :
50 2994 : return factor;
51 : }
52 :
53 17473 : static Word16 TCX_MDCT_Inverse_GetScaleFactor(
54 : const Word16 L, /* Q0 */
55 : Word16 *factor_e /* Q0 */
56 : )
57 : {
58 :
59 : Word16 factor;
60 :
61 17473 : IF( EQ_16( L, NORM_MDCT_FACTOR ) )
62 : {
63 17017 : factor = 32767;
64 17017 : move16();
65 17017 : *factor_e = 0;
66 17017 : move16();
67 : }
68 456 : ELSE IF( EQ_16( L, 2 * NORM_MDCT_FACTOR ) )
69 : {
70 16 : factor = 23170;
71 16 : move16();
72 16 : *factor_e = 1;
73 16 : move16();
74 : }
75 440 : ELSE IF( EQ_16( L, 4 * NORM_MDCT_FACTOR ) )
76 : {
77 0 : factor = 32767;
78 0 : move16();
79 0 : *factor_e = 1;
80 0 : move16();
81 : }
82 : ELSE
83 : {
84 440 : factor = mult_r( shl( L, 4 ), 26214 /*128.f / NORM_MDCT_FACTOR*/ ); /* 4Q11 */
85 440 : *factor_e = 4;
86 440 : move16();
87 :
88 440 : factor = Sqrt16( factor, factor_e );
89 : }
90 :
91 17473 : return factor;
92 : }
93 :
94 :
95 1497 : void TCX_MDCT(
96 : const Word16 *x, /* Qx */
97 : Word32 *y, /* exp(y_e) */
98 : Word16 *y_e,
99 : const Word16 l, /* Q0 */
100 : const Word16 m, /* Q0 */
101 : const Word16 r, /* Q0 */
102 : const Word16 element_mode /* Q0 */
103 : )
104 : {
105 :
106 : Word16 i;
107 : Word16 factor, neg_factor;
108 : Word16 factor_e;
109 : (void) element_mode;
110 : #ifndef ISSUE_1836_replace_overflow_libcom
111 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
112 : Flag Overflow = 0;
113 : move32();
114 : #endif
115 : #endif
116 1497 : factor = TCX_MDCT_GetScaleFactor( add( add( shr( l, 1 ), m ), shr( r, 1 ) ), &factor_e );
117 1497 : *y_e = add( *y_e, factor_e );
118 1497 : move16();
119 :
120 1497 : neg_factor = negate( factor );
121 :
122 :
123 : /* Init */
124 330537 : FOR( i = 0; i < m / 2; i++ )
125 : {
126 329040 : y[m / 2 + r / 2 + i] = L_mult( x[l + m / 2 - 1 - i], neg_factor ); /* exp(y_e) */
127 329040 : move32();
128 : }
129 257417 : FOR( i = 0; i < l / 2; i++ )
130 : {
131 : #ifdef ISSUE_1836_replace_overflow_libcom
132 255920 : y[m / 2 + r / 2 + m / 2 + i] = L_msu_sat( L_mult( x[i], factor ), x[l - 1 - i], factor ); /* exp(y_e) */
133 : #else
134 : y[m / 2 + r / 2 + m / 2 + i] = L_msu_o( L_mult( x[i], factor ), x[l - 1 - i], factor, &Overflow ); /* exp(y_e) */
135 : #endif
136 255920 : move32();
137 : }
138 330537 : FOR( i = 0; i < m / 2; i++ )
139 : {
140 329040 : y[m / 2 + r / 2 - 1 - i] = L_mult( x[l + m / 2 + i], neg_factor ); /* exp(y_e) */
141 329040 : move32();
142 : }
143 257417 : FOR( i = 0; i < r / 2; i++ )
144 : {
145 : #ifdef ISSUE_1836_replace_overflow_libcom
146 255920 : y[m / 2 + r / 2 - 1 - m / 2 - i] = L_mac_sat( L_mult( x[l + m + i], neg_factor ), x[l + m + r - 1 - i], neg_factor ); /* exp(y_e) */
147 : #else
148 : y[m / 2 + r / 2 - 1 - m / 2 - i] = L_mac_o( L_mult( x[l + m + i], neg_factor ), x[l + m + r - 1 - i], neg_factor, &Overflow ); /* exp(y_e) */
149 : #endif
150 255920 : move32();
151 : }
152 :
153 1497 : *y_e = sub( 15, *y_e );
154 1497 : move16();
155 1497 : edct_fx( y, y, l / 2 + m + r / 2, y_e );
156 1497 : *y_e = sub( 15 - 1, *y_e );
157 1497 : move16();
158 1497 : return;
159 : }
160 :
161 1497 : void TCX_MDST(
162 : const Word16 *x, /* Qx */
163 : Word32 *y, /* exp(y_e) */
164 : Word16 *y_e,
165 : const Word16 l, /* Q0 */
166 : const Word16 m, /* Q0 */
167 : const Word16 r, /* Q0 */
168 : const Word16 element_mode /* Q0 */
169 : )
170 : {
171 :
172 : Word16 i;
173 : Word16 factor, neg_factor;
174 : Word16 factor_e;
175 : (void) element_mode;
176 : #ifndef ISSUE_1836_replace_overflow_libcom
177 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
178 : Flag Overflow = 0;
179 : move32();
180 : #endif
181 : #endif
182 1497 : factor = TCX_MDCT_GetScaleFactor( add( add( shr( l, 1 ), m ), shr( r, 1 ) ), &factor_e ); /* exp(factor_e) */
183 1497 : *y_e = add( *y_e, factor_e );
184 1497 : move16();
185 :
186 1497 : neg_factor = negate( factor );
187 :
188 :
189 : /* Init */
190 330537 : FOR( i = 0; i < m / 2; i++ )
191 : {
192 329040 : y[m / 2 + r / 2 + i] = L_mult( x[l + m / 2 - 1 - i], neg_factor ); /* exp(y_e) */
193 329040 : move32();
194 : }
195 257417 : FOR( i = 0; i < l / 2; i++ )
196 : {
197 : #ifdef ISSUE_1836_replace_overflow_libcom
198 255920 : y[m / 2 + r / 2 + m / 2 + i] = L_msu_sat( L_mult( x[i], neg_factor ), x[l - 1 - i], factor ); /* exp(y_e) */
199 : #else
200 : y[m / 2 + r / 2 + m / 2 + i] = L_msu_o( L_mult( x[i], neg_factor ), x[l - 1 - i], factor, &Overflow ); /* exp(y_e) */
201 : #endif
202 255920 : move32();
203 : }
204 330537 : FOR( i = 0; i < m / 2; i++ )
205 : {
206 329040 : y[m / 2 + r / 2 - 1 - i] = L_mult( x[l + m / 2 + i], neg_factor ); /* exp(y_e) */
207 329040 : move32();
208 : }
209 257417 : FOR( i = 0; i < r / 2; i++ )
210 : {
211 255920 : y[m / 2 + r / 2 - 1 - m / 2 - i] = L_mac_sat( L_mult( x[l + m + i], neg_factor ), x[l + m + r - 1 - i], factor ); /* exp(y_e) */
212 255920 : move32();
213 : }
214 :
215 1497 : *y_e = sub( 15, *y_e );
216 1497 : move16();
217 :
218 1497 : edst_fx( y, y, add( add( shr( l, 1 ), m ), shr( r, 1 ) ), y_e );
219 :
220 1497 : *y_e = sub( 15 - 1, *y_e );
221 1497 : move16();
222 :
223 1497 : return;
224 : }
225 :
226 17473 : void TCX_MDCT_Inverse(
227 : Word32 *x, // Q( 31 - x_e )
228 : Word16 x_e,
229 : Word16 *y, /* Qy */
230 : const Word16 l, /* Q0 */
231 : const Word16 m, /* Q0 */
232 : const Word16 r, /* Q0 */
233 : const Word16 element_mode /* Q0 */
234 : )
235 : {
236 :
237 : Word16 i, fac, negfac, s;
238 17473 : Word16 L2 = l, R2 = r;
239 : Word32 tmp_buf[N_MAX + L_MDCT_OVLP_MAX / 2];
240 : Word16 fac_e;
241 : (void) element_mode;
242 17473 : L2 = shr( l, 1 );
243 17473 : R2 = shr( r, 1 );
244 :
245 17473 : x_e = sub( 15, x_e );
246 17473 : edct_fx( x, tmp_buf + L2, add( add( shr( l, 1 ), m ), shr( r, 1 ) ), &x_e );
247 17473 : x_e = sub( 15, x_e );
248 :
249 17473 : fac = TCX_MDCT_Inverse_GetScaleFactor( add( add( shr( l, 1 ), m ), shr( r, 1 ) ), &fac_e ); /* exp(fac_e) */
250 17473 : x_e = add( x_e, fac_e );
251 :
252 17473 : negfac = negate( fac );
253 :
254 17473 : s = x_e;
255 17473 : move16();
256 :
257 669194 : FOR( i = 0; i < R2; i++ )
258 : {
259 651721 : y[l + m + R2 + i] = round_fx_sat( L_shl_sat( Mpy_32_16_1( tmp_buf[L2 + i], negfac ), s ) ); /* fold out right end of DCT exp(fac_e)*/
260 :
261 651721 : move16();
262 : }
263 :
264 669194 : FOR( i = 0; i < L2; i++ )
265 : {
266 651721 : y[i] = round_fx_sat( L_shl_sat( Mpy_32_16_1( tmp_buf[L2 + m + R2 + i], fac ), s ) ); /* negate, fold out left end of DCT exp(fac_e)*/
267 651721 : move16();
268 : }
269 :
270 1539193 : FOR( i = 0; i < ( ( L2 + m + R2 ) >> 1 ); i++ )
271 : {
272 : Word16 f;
273 :
274 1521720 : f = round_fx_sat( L_shl_sat( Mpy_32_16_1( tmp_buf[L2 + i], negfac ), s ) );
275 1521720 : y[L2 + i] = round_fx_sat( L_shl_sat( Mpy_32_16_1( tmp_buf[l + m + R2 - 1 - i], negfac ), s ) ); /* time-reverse mid of DCT exp(fac_e)*/
276 1521720 : move16();
277 1521720 : y[l + m + R2 - 1 - i] = f;
278 1521720 : move16();
279 : }
280 17473 : }
281 :
282 0 : void TCX_MDST_Inverse_fx(
283 : Word32 *x, /* exp(x_e) */
284 : Word16 x_e,
285 : Word16 *y, /* Qx */
286 : const Word16 l, /* Q0 */
287 : const Word16 m, /* Q0 */
288 : const Word16 r /* Q0 */
289 : )
290 : {
291 :
292 : Word16 i, fac, negfac, s;
293 0 : Word16 L2 = l, R2 = r;
294 0 : move16();
295 0 : move16();
296 : Word32 tmp_buf[N_MAX + L_MDCT_OVLP_MAX / 2];
297 : Word16 fac_e;
298 :
299 0 : L2 = shr( l, 1 );
300 0 : R2 = shr( r, 1 );
301 :
302 0 : x_e = sub( 15, x_e );
303 0 : edst_fx( x, tmp_buf + L2, add( add( shr( l, 1 ), m ), shr( r, 1 ) ), &x_e );
304 0 : x_e = sub( 15, x_e );
305 :
306 0 : fac = TCX_MDCT_Inverse_GetScaleFactor( add( add( shr( l, 1 ), m ), shr( r, 1 ) ), &fac_e );
307 0 : x_e = add( x_e, fac_e );
308 :
309 0 : negfac = negate( fac );
310 :
311 0 : s = x_e;
312 0 : move16();
313 :
314 0 : FOR( i = 0; i < R2; i++ )
315 : {
316 0 : y[l + m + R2 + i] = round_fx( L_shl( Mpy_32_16_1( tmp_buf[L2 + i], fac ), s ) ); /* fold out right end of DCT exp(fac_e)*/
317 0 : move16();
318 : }
319 :
320 0 : FOR( i = 0; i < L2; i++ )
321 : {
322 0 : y[i] = round_fx( L_shl( Mpy_32_16_1( tmp_buf[L2 + m + R2 + i], negfac ), s ) ); /* negate, fold out left end of DCT exp(fac_e)*/
323 0 : move16();
324 : }
325 :
326 0 : FOR( i = 0; i < ( ( L2 + m + R2 ) >> 1 ); i++ )
327 : {
328 : Word16 f;
329 0 : f = round_fx( L_shl( Mpy_32_16_1( tmp_buf[L2 + i], fac ), s ) );
330 :
331 0 : y[L2 + i] = round_fx( L_shl( Mpy_32_16_1( tmp_buf[l + m + R2 - 1 - i], negfac ), s ) ); /* time-reverse mid of DCT exp(fac_e)*/
332 0 : move16();
333 :
334 0 : y[l + m + R2 - 1 - i] = negate( f );
335 0 : move16();
336 : }
337 0 : }
338 :
339 : /*-------------------------------------------------------------------*
340 : * TCX_MDXT_Inverse_fx()
341 : *
342 : *
343 : *-------------------------------------------------------------------*/
344 :
345 0 : void TCX_MDXT_Inverse_fx(
346 : const Word32 *x, /* exp(x_e) */
347 : Word16 x_e,
348 : Word16 *y, /* Qx */
349 : const Word16 l, /* Q0 */
350 : const Word16 m, /* Q0 */
351 : const Word16 r, /* Q0 */
352 : const UWord16 kernel_type /* Q0 */
353 : )
354 : {
355 : Word16 signLeft;
356 : Word16 signRight;
357 : Word16 i, fac, negfac, s, fac_e;
358 0 : const Word16 L2 = shr( l, 1 ), R2 = shr( r, 1 );
359 : Word32 tmp_buf[N_MAX + L_MDCT_OVLP_MAX / 2];
360 : Word16 f;
361 :
362 0 : set32_fx( tmp_buf, 0, N_MAX + L_MDCT_OVLP_MAX / 2 );
363 :
364 0 : edxt_fx( x, tmp_buf + L2, add( add( L2, m ), R2 ), kernel_type, TRUE );
365 :
366 0 : fac = TCX_MDCT_Inverse_GetScaleFactor( add( add( shr( l, 1 ), m ), shr( r, 1 ) ), &fac_e );
367 0 : x_e = add( x_e, fac_e );
368 :
369 0 : negfac = negate( fac );
370 0 : IF( GE_16( kernel_type, MDCT_II ) )
371 : {
372 0 : signLeft = negfac;
373 : }
374 : ELSE
375 : {
376 0 : signLeft = fac;
377 : }
378 : // signRight = ( kernel_type & 1 ? fac : negfac );
379 0 : IF( L_and( kernel_type, 1 ) )
380 : {
381 0 : signRight = fac;
382 : }
383 : ELSE
384 : {
385 0 : signRight = negfac;
386 : }
387 :
388 0 : s = x_e;
389 0 : move16();
390 :
391 0 : FOR( i = 0; i < L2; i++ )
392 : {
393 0 : y[i] = round_fx( L_shl( Mpy_32_16_1( tmp_buf[L2 + m + R2 + i], signLeft ), s ) ); /* fold out the left end exp(fac_e)*/
394 : }
395 :
396 0 : FOR( i = 0; i < R2; i++ )
397 : {
398 0 : y[l + m + R2 + i] = round_fx( L_shl( Mpy_32_16_1( tmp_buf[L2 + i], signRight ), s ) ); /* ...and right end exp(fac_e)*/
399 0 : move16();
400 : }
401 :
402 0 : FOR( i = 0; i < ( ( L2 + m + R2 ) >> 1 ); i++ )
403 : {
404 :
405 0 : f = round_fx( L_shl( Mpy_32_16_1( tmp_buf[L2 + i], negfac ), s ) );
406 :
407 0 : y[L2 + i] = round_fx( L_shl( Mpy_32_16_1( tmp_buf[l + m + R2 - 1 - i], negfac ), s ) ); /* time-reverse mid of DCT exp(fac_e)*/
408 0 : move16();
409 :
410 0 : y[l + m + R2 - 1 - i] = f;
411 0 : move16();
412 : }
413 :
414 0 : return;
415 : }
|