Line data Source code
1 : /******************************************************************************************************
2 :
3 : (C) 2022-2025 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
4 : Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
5 : Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
6 : Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
7 : contributors to this repository. All Rights Reserved.
8 :
9 : This software is protected by copyright law and by international treaties.
10 : The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
11 : Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
12 : Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
13 : Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
14 : contributors to this repository retain full ownership rights in their respective contributions in
15 : the software. This notice grants no license of any kind, including but not limited to patent
16 : license, nor is any license granted by implication, estoppel or otherwise.
17 :
18 : Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
19 : contributions.
20 :
21 : This software is provided "AS IS", without any express or implied warranties. The software is in the
22 : development stage. It is intended exclusively for experts who have experience with such software and
23 : solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
24 : and fitness for a particular purpose are hereby disclaimed and excluded.
25 :
26 : Any dispute, controversy or claim arising under or in relation to providing this software shall be
27 : submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
28 : accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
29 : the United Nations Convention on Contracts on the International Sales of Goods.
30 :
31 : *******************************************************************************************************/
32 :
33 : /*====================================================================================
34 : EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
35 : ====================================================================================*/
36 :
37 : #include <assert.h>
38 : #include <stdint.h>
39 : #include "options.h"
40 : #include "cnst.h"
41 : #include "basop_proto_func.h"
42 : #include "stl.h"
43 : #include "prot_fx.h"
44 : #include "rom_com.h"
45 :
46 : #define WMC_TOOL_SKIP
47 :
48 : /* compare two positive normalized 16 bit mantissa/exponent values */
49 : /* return value: positive if first value greater, negative if second value greater, zero if equal */
50 : // static Word16 compMantExp16Unorm( Word16 m1, Word16 e1, Word16 m2, Word16 e2 )
51 : //{
52 : // Word16 tmp;
53 : //
54 : // assert( ( m1 >= 0x4000 ) && ( m2 >= 0x4000 ) ); /* comparisons below work only for normalized mantissas */
55 : //
56 : // tmp = sub( e1, e2 );
57 : // if ( tmp == 0 )
58 : // tmp = sub( m1, m2 );
59 : //
60 : // return tmp;
61 : // }
62 :
63 368068 : void basop_lpc2mdct_fx(
64 : Word16 *lpcCoeffs, /* Q12 */
65 : Word16 lpcOrder, /* Q0 */
66 : Word16 *mdct_gains, /* Q12 */
67 : Word16 *mdct_gains_exp,
68 : Word16 *mdct_inv_gains, /* Q12 */
69 : Word16 *mdct_inv_gains_exp )
70 : {
71 : Word32 RealData[FDNS_NPTS];
72 : Word32 ImagData[FDNS_NPTS];
73 : Word16 i, j, k, step, scale, s, tmp16;
74 : Word16 g, g_e, ig, ig_e;
75 : Word32 tmp32;
76 : const PWord16 *ptwiddle;
77 :
78 :
79 : /* short-cut, to avoid calling of BASOP_getTables() */
80 368068 : ptwiddle = SineTable512_fx;
81 368068 : step = 8;
82 368068 : move16();
83 : /*ODFT*/
84 368068 : assert( lpcOrder < FDNS_NPTS );
85 :
86 : /* pre-twiddle */
87 6639213 : FOR( i = 0; i <= lpcOrder; i++ )
88 : {
89 6271145 : RealData[i] = L_mult( lpcCoeffs[i], ptwiddle->v.re ); /* Q28 */
90 6271145 : move32();
91 6271145 : ImagData[i] = L_negate( L_mult( lpcCoeffs[i], ptwiddle->v.im ) ); /* Q28 */
92 6271145 : move32();
93 6271145 : ptwiddle += step;
94 : }
95 :
96 : /* zero padding */
97 17653275 : FOR( ; i < FDNS_NPTS; i++ )
98 : {
99 17285207 : RealData[i] = 0;
100 17285207 : move32();
101 17285207 : ImagData[i] = 0;
102 17285207 : move32();
103 : }
104 :
105 : /* half length FFT */
106 368068 : scale = add( norm_s( lpcCoeffs[0] ), 1 );
107 368068 : move16();
108 368068 : BASOP_cfft_ivas( RealData, ImagData, 1, &scale ); /* sizeOfFft == FDNS_NPTS == 8 */
109 :
110 :
111 : /*Get amplitude*/
112 368068 : j = FDNS_NPTS - 1; /* Q0 */
113 368068 : k = 0;
114 368068 : move16();
115 368068 : move16();
116 :
117 12146244 : FOR( i = 0; i < FDNS_NPTS / 2; i++ )
118 : {
119 11778176 : s = sub( norm_l( L_max( L_abs( RealData[i] ), L_abs( ImagData[i] ) ) ), 1 );
120 :
121 11778176 : tmp16 = extract_h( L_shl( RealData[i], s ) );
122 11778176 : tmp32 = L_mult( tmp16, tmp16 );
123 :
124 11778176 : tmp16 = extract_h( L_shl( ImagData[i], s ) );
125 11778176 : tmp16 = mac_r( tmp32, tmp16, tmp16 );
126 :
127 11778176 : s = shl( sub( scale, s ), 1 );
128 :
129 11778176 : if ( tmp16 == 0 )
130 : {
131 0 : s = -16;
132 0 : move16();
133 : }
134 11778176 : if ( tmp16 == 0 )
135 : {
136 0 : tmp16 = 1;
137 0 : move16();
138 : }
139 :
140 11778176 : BASOP_Util_Sqrt_InvSqrt_MantExp( tmp16, s, &g, &g_e, &ig, &ig_e );
141 :
142 11778176 : if ( mdct_gains != NULL )
143 : {
144 11330528 : mdct_gains[k] = g; /* exp(g_e) */
145 11330528 : move16();
146 : }
147 :
148 11778176 : if ( mdct_gains_exp != NULL )
149 : {
150 11330528 : mdct_gains_exp[k] = g_e;
151 11330528 : move16();
152 : }
153 :
154 11778176 : if ( mdct_inv_gains != NULL )
155 : {
156 11330528 : mdct_inv_gains[k] = ig; /* exp(ig_e) */
157 11330528 : move16();
158 : }
159 :
160 11778176 : if ( mdct_inv_gains_exp != NULL )
161 : {
162 11330528 : mdct_inv_gains_exp[k] = ig_e;
163 11330528 : move16();
164 : }
165 :
166 11778176 : k++;
167 :
168 :
169 11778176 : s = sub( norm_l( L_max( L_abs( RealData[j] ), L_abs( ImagData[j] ) ) ), 1 );
170 :
171 11778176 : tmp16 = extract_h( L_shl( RealData[j], s ) );
172 11778176 : tmp32 = L_mult( tmp16, tmp16 );
173 :
174 11778176 : tmp16 = extract_h( L_shl( ImagData[j], s ) );
175 11778176 : tmp16 = mac_r( tmp32, tmp16, tmp16 );
176 :
177 11778176 : s = shl( sub( scale, s ), 1 );
178 :
179 11778176 : if ( tmp16 == 0 )
180 : {
181 0 : s = -16;
182 0 : move16();
183 : }
184 11778176 : if ( tmp16 == 0 )
185 : {
186 0 : tmp16 = 1;
187 0 : move16();
188 : }
189 :
190 11778176 : BASOP_Util_Sqrt_InvSqrt_MantExp( tmp16, s, &g, &g_e, &ig, &ig_e );
191 :
192 11778176 : if ( mdct_gains != NULL )
193 : {
194 11330528 : mdct_gains[k] = g; /* exp(g_e) */
195 11330528 : move16();
196 : }
197 :
198 11778176 : if ( mdct_gains_exp != NULL )
199 : {
200 11330528 : mdct_gains_exp[k] = g_e;
201 11330528 : move16();
202 : }
203 :
204 11778176 : if ( mdct_inv_gains != NULL )
205 : {
206 11330528 : mdct_inv_gains[k] = ig; /* exp(ig_e) */
207 11330528 : move16();
208 : }
209 :
210 11778176 : if ( mdct_inv_gains_exp != NULL )
211 : {
212 11330528 : mdct_inv_gains_exp[k] = ig_e;
213 11330528 : move16();
214 : }
215 :
216 11778176 : j--;
217 11778176 : k++;
218 : }
219 368068 : }
220 :
221 :
222 13989 : void basop_mdct_noiseShaping_interp_fx(
223 : Word32 x[], /* Q16 */
224 : Word16 lg, /* Q0 */
225 : Word16 gains[], /* exp(gain_exp) */
226 : Word16 gains_exp[] )
227 : {
228 : Word16 i, j, jp, jn, k, l;
229 : Word16 g, pg, ng, e, tmp;
230 :
231 :
232 13989 : assert( lg % FDNS_NPTS == 0 );
233 13989 : k = shr( lg, 6 ); /* FDNS_NPTS = 64 */
234 :
235 13989 : IF( gains != NULL )
236 : {
237 : /* Linear interpolation */
238 13989 : IF( sub( k, 4 ) == 0 )
239 : {
240 12695 : jp = 0;
241 12695 : move16();
242 12695 : j = 0;
243 12695 : move16();
244 12695 : jn = 1;
245 12695 : move16();
246 :
247 825175 : FOR( i = 0; i < lg; i += 4 )
248 : {
249 812480 : pg = gains[jp];
250 812480 : move16();
251 812480 : g = gains[j];
252 812480 : move16();
253 812480 : ng = gains[jn];
254 812480 : move16();
255 :
256 : /* common exponent for pg and g */
257 812480 : tmp = sub( gains_exp[j], gains_exp[jp] );
258 812480 : if ( tmp > 0 )
259 89229 : pg = shr( pg, tmp );
260 812480 : if ( tmp < 0 )
261 53391 : g = shl( g, tmp );
262 812480 : e = s_max( gains_exp[j], gains_exp[jp] );
263 :
264 812480 : tmp = mac_r( L_mult( pg, 12288 /* 0.375 in Q15 */ ), g, 20480 /* 0.625 in Q15 */ ); /* exp(gains_exp) */
265 812480 : x[i] = L_shl( Mpy_32_16_1( x[i], tmp ), e ); /* Q16 */
266 812480 : move32();
267 :
268 812480 : tmp = mac_r( L_mult( pg, 4096 /* 0.125 in Q15*/ ), g, 28672 /* 0.875 in Q15 */ ); /* exp(gains_exp) */
269 812480 : x[i + 1] = L_shl( Mpy_32_16_1( x[i + 1], tmp ), e ); /* Q16 */
270 812480 : move32();
271 :
272 : /* common exponent for g and ng */
273 812480 : g = gains[j]; /* exp(gains_exp) */
274 812480 : move16();
275 812480 : tmp = sub( gains_exp[j], gains_exp[jn] );
276 812480 : if ( tmp > 0 )
277 53391 : ng = shr( ng, tmp );
278 812480 : if ( tmp < 0 )
279 89229 : g = shl( g, tmp );
280 812480 : e = s_max( gains_exp[j], gains_exp[jn] );
281 :
282 812480 : tmp = mac_r( L_mult( g, 28672 /* 0.875 in Q15 */ ), ng, 4096 /* 0.125 in Q15*/ ); /* exp(gains_exp) */
283 812480 : x[i + 2] = L_shl( Mpy_32_16_1( x[i + 2], tmp ), e ); /* Q16 */
284 812480 : move32();
285 :
286 812480 : tmp = mac_r( L_mult( g, 20480 /* 0.625 in Q15 */ ), ng, 12288 /* 0.375 in Q15 */ ); /* exp(gains_exp) */
287 812480 : x[i + 3] = L_shl( Mpy_32_16_1( x[i + 3], tmp ), e ); /* Q16 */
288 812480 : move32();
289 :
290 812480 : jp = j;
291 812480 : move16();
292 812480 : j = jn;
293 812480 : move16();
294 812480 : jn = s_min( add( jn, 1 ), FDNS_NPTS - 1 ); /* Q0 */
295 : }
296 : }
297 1294 : ELSE IF( sub( k, 5 ) == 0 )
298 : {
299 1294 : jp = 0;
300 1294 : move16();
301 1294 : j = 0;
302 1294 : move16();
303 1294 : jn = 1;
304 1294 : move16();
305 :
306 84110 : FOR( i = 0; i < lg; i += 5 )
307 : {
308 82816 : pg = gains[jp];
309 82816 : move16();
310 82816 : g = gains[j];
311 82816 : move16();
312 82816 : ng = gains[jn];
313 82816 : move16();
314 :
315 : /* common exponent for pg and g */
316 82816 : tmp = sub( gains_exp[j], gains_exp[jp] );
317 82816 : if ( tmp > 0 )
318 8768 : pg = shr( pg, tmp );
319 82816 : if ( tmp < 0 )
320 5135 : g = shl( g, tmp );
321 82816 : e = s_max( gains_exp[j], gains_exp[jp] );
322 :
323 82816 : tmp = mac_r( L_mult( pg, 13107 /* 0.4 in Q15 */ ), g, 19661 /* 0.6 in Q15 */ ); /* exp(gains_exp) */
324 82816 : x[i] = L_shl( Mpy_32_16_1( x[i], tmp ), e ); /* Q16 */
325 82816 : move32();
326 :
327 82816 : tmp = mac_r( L_mult( pg, 6554 /* 0.2 in Q15 */ ), g, 26214 /* 0.8 in Q15 */ ); /* exp(gains_exp) */
328 82816 : x[i + 1] = L_shl( Mpy_32_16_1( x[i + 1], tmp ), e ); /* Q16 */
329 82816 : move32();
330 :
331 :
332 82816 : x[i + 2] = L_shl( Mpy_32_16_1( x[i + 2], gains[j] ), gains_exp[j] ); /* Q16 */
333 82816 : move32();
334 :
335 : /* common exponent for g and ng */
336 82816 : g = gains[j];
337 82816 : move16();
338 82816 : tmp = sub( gains_exp[j], gains_exp[jn] );
339 82816 : if ( tmp > 0 )
340 5135 : ng = shr( ng, tmp );
341 82816 : if ( tmp < 0 )
342 8768 : g = shl( g, tmp );
343 82816 : e = s_max( gains_exp[j], gains_exp[jn] );
344 :
345 82816 : tmp = mac_r( L_mult( g, 26214 /* 0.8 in Q15 */ ), ng, 6554 /* 0.2 in Q15 */ ); /* exp(gains_exp) */
346 82816 : x[i + 3] = L_shl( Mpy_32_16_1( x[i + 3], tmp ), e ); /* Q16 */
347 82816 : move32();
348 :
349 82816 : tmp = mac_r( L_mult( g, 19661 /* 0.6 in Q15 */ ), ng, 13107 /* 0.4 in Q15 */ ); /* exp(gains_exp) */
350 82816 : x[i + 4] = L_shl( Mpy_32_16_1( x[i + 4], tmp ), e ); /* Q16 */
351 82816 : move32();
352 :
353 82816 : jp = j;
354 82816 : move16();
355 82816 : j = jn;
356 82816 : move16();
357 82816 : jn = s_min( add( jn, 1 ), FDNS_NPTS - 1 ); /* Q0 */
358 : }
359 : }
360 : ELSE /* no interpolation */
361 : {
362 0 : FOR( i = 0; i < FDNS_NPTS; i++ )
363 : {
364 0 : FOR( l = 0; l < k; l++ )
365 : {
366 0 : *x = L_shl( Mpy_32_16_1( *x, *gains ), *gains_exp ); /* Q16 */
367 0 : move32();
368 0 : x++;
369 : }
370 :
371 0 : gains++;
372 0 : gains_exp++;
373 : }
374 : }
375 : }
376 13989 : }
377 :
378 :
379 13989 : void basop_PsychAdaptLowFreqDeemph_fx(
380 : Word32 x[], /* Q16 */
381 : const Word16 lpcGains[], /* exp(lpcGains_e) */
382 : const Word16 lpcGains_e[],
383 : Word16 lf_deemph_factors[] /* Qx */
384 : )
385 : {
386 : Word16 i;
387 : Word16 max_val, max_e, fac, min_val, min_e, tmp, tmp_e;
388 : Word32 L_tmp;
389 :
390 :
391 13989 : assert( lpcGains[0] >= 0x4000 );
392 :
393 13989 : max_val = lpcGains[0];
394 13989 : move16();
395 13989 : max_e = lpcGains_e[0];
396 13989 : move16();
397 13989 : min_val = lpcGains[0];
398 13989 : move16();
399 13989 : min_e = lpcGains_e[0];
400 13989 : move16();
401 :
402 : /* find minimum (min) and maximum (max) of LPC gains in low frequencies */
403 125901 : FOR( i = 1; i < 9; i++ )
404 : {
405 111912 : IF( compMantExp16Unorm( lpcGains[i], lpcGains_e[i], min_val, min_e ) < 0 )
406 : {
407 79733 : min_val = lpcGains[i];
408 79733 : move16();
409 79733 : min_e = lpcGains_e[i];
410 79733 : move16();
411 : }
412 :
413 111912 : IF( compMantExp16Unorm( lpcGains[i], lpcGains_e[i], max_val, max_e ) > 0 )
414 : {
415 22577 : max_val = lpcGains[i];
416 22577 : move16();
417 22577 : max_e = lpcGains_e[i];
418 22577 : move16();
419 : }
420 : }
421 :
422 13989 : min_e = add( min_e, 5 ); /* min *= 32.0f; */
423 :
424 13989 : test();
425 13989 : IF( ( compMantExp16Unorm( max_val, max_e, min_val, min_e ) < 0 ) && ( min_val > 0 ) )
426 : {
427 : /* fac = tmp = (float)pow(max / min, 0.0078125f); */
428 13989 : tmp_e = min_e;
429 13989 : move16();
430 13989 : tmp = Inv16( min_val, &tmp_e );
431 13989 : L_tmp = L_shl( L_mult( tmp, max_val ), add( tmp_e, max_e ) ); /* Q31 */
432 13989 : L_tmp = BASOP_Util_Log2( L_tmp ); /* Q25 */
433 13989 : L_tmp = L_shr( L_tmp, 7 ); /* 0.0078125f = 1.f/(1<<7) */
434 13989 : L_tmp = BASOP_Util_InvLog2( L_tmp ); /* Q31 */
435 13989 : tmp = round_fx( L_tmp ); /* Q15 */
436 13989 : fac = tmp; /* Q15 */
437 13989 : move16();
438 :
439 : /* gradual lowering of lowest 32 bins; DC is lowered by (max/tmp)^1/4 */
440 461637 : FOR( i = 31; i >= 0; i-- )
441 : {
442 447648 : x[i] = Mpy_32_16_1( x[i], fac ); /* Q16 */
443 447648 : move32();
444 447648 : if ( lf_deemph_factors != NULL )
445 : {
446 0 : lf_deemph_factors[i] = mult_r( lf_deemph_factors[i], fac ); /* Qx */
447 0 : move16();
448 : }
449 447648 : fac = mult_r( fac, tmp ); /* Q15 */
450 : }
451 : }
452 13989 : }
453 :
454 : #undef WMC_TOOL_SKIP
|