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 : #include <stdint.h>
34 : #include "options.h"
35 : #include "cnst.h"
36 : #include "prot_fx.h"
37 : #include "rom_com.h"
38 : #include "ivas_rom_com.h"
39 : #include <math.h>
40 : #include <assert.h>
41 : #include "wmc_auto.h"
42 : #include "ivas_prot_fx.h"
43 :
44 : /*-------------------------------------------------------------------
45 : * sns_compute_scf_fx()
46 : *
47 : *
48 : *-------------------------------------------------------------------*/
49 :
50 664619 : void sns_compute_scf_fx(
51 : Word32 spectrum[], /* i : Spectrum Q_in */
52 : const PsychoacousticParameters *pPsychParams,
53 : const Word16 L_frame,
54 : Word32 *scf, /* o : Scalefactors (Q16)*/
55 : Word16 Q_in )
56 : {
57 : Word16 i, n, k;
58 : Word32 x[FDNS_NPTS], xs[FDNS_NPTS], mean, xl4[SNS_NPTS], nf, xl[FDNS_NPTS];
59 : Word64 x_64[FDNS_NPTS];
60 : Word64 sum;
61 : Word32 L_tmp;
62 : const Word32 *pow_tilt;
63 : Word16 q_shift, q_out, f_tmp;
64 : Word16 bw, inv_bw, exp;
65 664619 : const UWord8 nBands = pPsychParams->nBands;
66 664619 : move16();
67 664619 : const UWord8 *bandLengths = pPsychParams->bandLengths;
68 :
69 664619 : const Word16 w_0 = 2730; // (1.0f / 12.0f) in Q15
70 664619 : move16();
71 664619 : const Word16 w_1 = 5461; // (2.0f / 12.0f) in Q15
72 664619 : move16();
73 664619 : const Word16 w_2 = 8192; // 0.25f ( 3.0f / 12.0f ) in Q15
74 664619 : move16();
75 664619 : const Word16 w_3 = w_2; // q15
76 664619 : move16();
77 664619 : const Word16 w_4 = w_1; // q15
78 664619 : move16();
79 664619 : const Word16 w_5 = w_0; // q15
80 664619 : move16();
81 :
82 664619 : assert( nBands == FDNS_NPTS );
83 :
84 664619 : set64_fx( x_64, 0, FDNS_NPTS );
85 664619 : set32_fx( x, 0, FDNS_NPTS );
86 :
87 664619 : IF( bandLengths == NULL )
88 : {
89 1331 : bw = shr( L_frame, 6 );
90 1331 : move16();
91 :
92 1331 : exp = norm_s( bw );
93 1331 : inv_bw = div_s( ONE_IN_Q14, shl( bw, exp ) ); // Q:15+14-exp = 29-exp
94 1331 : inv_bw = shl( inv_bw, sub( exp, 14 ) ); // Q15
95 :
96 : /* Energy per band */
97 1331 : k = 0;
98 1331 : move16();
99 86515 : FOR( i = 0; i < nBands; ++i )
100 : {
101 85184 : sum = 0;
102 85184 : move64();
103 804160 : FOR( n = 0; n < bw; ( ++n, ++k ) )
104 : {
105 : /* x[i] += spectrum[k];
106 : inv_bw is for x[i] /= bw; */
107 718976 : sum = W_mac_32_16( sum, spectrum[k], inv_bw ); // Q_in+15+1
108 : }
109 85184 : x_64[i] = sum; // Q_in+16
110 85184 : move64();
111 : }
112 : }
113 : ELSE
114 : {
115 : /* Energy per band */
116 663288 : k = 0;
117 663288 : move16();
118 43113720 : FOR( i = 0; i < nBands; ++i )
119 : {
120 42450432 : exp = norm_s( bandLengths[i] );
121 42450432 : inv_bw = div_s( ONE_IN_Q14, shl( bandLengths[i], exp ) ); // Q:15+14-exp
122 42450432 : inv_bw = shl( inv_bw, sub( exp, 14 ) ); // Q15
123 :
124 42450432 : sum = 0;
125 42450432 : move64();
126 404312640 : FOR( n = 0; n < bandLengths[i]; ( ++n, ++k ) )
127 : {
128 : /* x[i] += spectrum[k];
129 : inv_bw is for x[i] /= bandLengths[i]; */
130 361862208 : sum = W_mac_32_16( sum, spectrum[k], inv_bw ); // Q_in+15+1
131 : }
132 42450432 : x_64[i] = sum; // Q_in+16
133 42450432 : move64();
134 : }
135 : }
136 :
137 : /* Move accumulated values to 32-bit */
138 664619 : q_shift = W_norm_arr( x_64, nBands ); // W_norm_arr return 63 when all the values of the input buffer are zeroes
139 664619 : IF( EQ_16( q_shift, 63 ) )
140 : {
141 : /* If all the values of x_64 are zeros, the scale factor (scf) values will be calculated as zeroes as per the below operations.
142 : To avoid extra computations in such a case, set scf values as zeroes and return. */
143 :
144 6219 : set_zero_fx( scf, SNS_NPTS );
145 :
146 6219 : return;
147 : }
148 :
149 42796000 : FOR( i = 0; i < nBands; ++i )
150 : {
151 42137600 : x[i] = W_extract_h( W_shl( x_64[i], q_shift ) ); // Q: Q_in+16+q_shift-32 = Q_in+q_shift-16
152 42137600 : move32();
153 : }
154 :
155 : /* Smoothing */
156 658400 : xs[0] = Madd_32_16( Mpy_32_16_1( x[0], 24576 /* 0.75 in Q15 */ ), x[1], 8192 /* 0.25 in Q15 */ ); // Q_in+q_shift-16
157 658400 : move32();
158 :
159 41479200 : FOR( i = 1; i < FDNS_NPTS - 1; i++ )
160 : {
161 40820800 : xs[i] = Madd_32_16( Madd_32_16( Mpy_32_16_1( x[i], 16384 /* 0.5 in Q15 */ ), x[i - 1], 8192 /* 0.25 in Q15 */ ), x[i + 1], 8192 /* 0.25 in Q15 */ ); // Q_in+q_shift-16
162 40820800 : move32();
163 : }
164 :
165 658400 : xs[FDNS_NPTS - 1] = Madd_32_16( Mpy_32_16_1( x[FDNS_NPTS - 1], 24576 /* 0.75 in Q15 */ ), x[FDNS_NPTS - 2], 8192 /* 0.25 in Q15 */ ); // Q_in+q_shift-16
166 658400 : move32();
167 :
168 : /* Pre-emphasis */
169 658400 : SWITCH( L_frame )
170 : {
171 63611 : case L_FRAME16k:
172 63611 : pow_tilt = pow_tilt_16k; // Q23
173 63611 : BREAK;
174 265945 : case L_FRAME25_6k:
175 265945 : pow_tilt = pow_tilt_25_6k; // Q23
176 265945 : BREAK;
177 328844 : case L_FRAME32k:
178 328844 : pow_tilt = pow_tilt_32k; // Q23
179 328844 : BREAK;
180 0 : default:
181 0 : pow_tilt = NULL;
182 0 : assert( !"illegal frame length in sns_compute_scf_fx" );
183 : }
184 :
185 42796000 : FOR( i = 0; i < FDNS_NPTS; i++ )
186 : {
187 42137600 : xs[i] = Mpy_32_32( xs[i], pow_tilt[i] ); // Q_in+q_shift-16+23-31 = Q_in+q_shift-24
188 42137600 : move32();
189 : }
190 :
191 : /* Noise floor at -40dB */
192 658400 : sum = 0;
193 658400 : move64();
194 42796000 : FOR( i = 0; i < FDNS_NPTS; i++ )
195 : {
196 42137600 : sum = W_mac_32_16( sum, xs[i], 1 ); // Q_in+q_shift-24+1
197 : }
198 :
199 658400 : q_out = sub( add( Q_in, q_shift ), 24 );
200 :
201 : /* mean = sum / FDNS_NPTS;
202 : -Q6 is for division with FDNS_NPTS and -Q1 is to reduce Q by one */
203 658400 : mean = W_shl_sat_l( sum, -Q7 ); // q_out
204 658400 : nf = Mpy_32_32( mean, 214748 /* powf( 10.0f, -4.0f ) in Q31 */ ); // q_out
205 :
206 658400 : IF( LE_32( nf, L_shl_sat( 256, sub( q_out, 40 ) ) ) ) /* powf( 2.0f, -32.0f ) in Q40 */
207 : {
208 20 : nf = 256;
209 20 : move32();
210 20 : q_out = 40;
211 20 : move16();
212 : }
213 :
214 42796000 : FOR( i = 0; i < FDNS_NPTS; i++ )
215 : {
216 42137600 : xs[i] = L_max( xs[i], nf ); // q_out
217 42137600 : move32();
218 : }
219 :
220 : /* Log-domain */
221 42796000 : FOR( i = 0; i < FDNS_NPTS; i++ )
222 : {
223 : /* xl[i] = logf( xs[i] ) * scale_log;
224 : scale_log = INV_LOG_2 * 0.5f; */
225 :
226 42137600 : exp = norm_l( xs[i] );
227 42137600 : f_tmp = Log2_norm_lc( L_shl( xs[i], exp ) ); // Q15
228 42137600 : exp = sub( sub( 30, exp ), q_out );
229 42137600 : L_tmp = L_mac( L_deposit_h( exp ), f_tmp, 1 ); // Q16
230 42137600 : xl[i] = L_shr( L_tmp, 1 ); // Q16
231 42137600 : move32();
232 : }
233 :
234 : /* Downsampling */
235 658400 : L_tmp = Madd_32_16( Mpy_32_16_1( xl[0], w_0 ), xl[0], w_1 ); // Q16
236 658400 : L_tmp = Madd_32_16( L_tmp, xl[1], w_2 ); // Q16
237 658400 : L_tmp = Madd_32_16( L_tmp, xl[2], w_3 ); // Q16
238 658400 : L_tmp = Madd_32_16( L_tmp, xl[3], w_4 ); // Q16
239 658400 : xl4[0] = Madd_32_16( L_tmp, xl[4], w_5 ); // Q16
240 :
241 :
242 9876000 : FOR( n = 1; n < SNS_NPTS - 1; n++ )
243 : {
244 9217600 : L_tmp = Mpy_32_16_1( xl[4 * n - 1], w_0 ); // Q16
245 9217600 : L_tmp = Madd_32_16( L_tmp, xl[4 * n], w_1 ); // Q16
246 9217600 : L_tmp = Madd_32_16( L_tmp, xl[4 * n + 1], w_2 ); // Q16
247 9217600 : L_tmp = Madd_32_16( L_tmp, xl[4 * n + 2], w_3 ); // Q16
248 9217600 : L_tmp = Madd_32_16( L_tmp, xl[4 * n + 3], w_4 ); // Q16
249 9217600 : xl4[n] = Madd_32_16( L_tmp, xl[4 * n + 4], w_5 ); // Q16
250 9217600 : move32();
251 : }
252 :
253 658400 : L_tmp = Mpy_32_16_1( xl[FDNS_NPTS - 5], w_0 ); // Q16
254 658400 : L_tmp = Madd_32_16( L_tmp, xl[FDNS_NPTS - 4], w_1 ); // Q16
255 658400 : L_tmp = Madd_32_16( L_tmp, xl[FDNS_NPTS - 3], w_2 ); // Q16
256 658400 : L_tmp = Madd_32_16( L_tmp, xl[FDNS_NPTS - 2], w_3 ); // Q16
257 658400 : L_tmp = Madd_32_16( L_tmp, xl[FDNS_NPTS - 1], w_4 ); // Q16
258 658400 : xl4[SNS_NPTS - 1] = Madd_32_16( L_tmp, xl[FDNS_NPTS - 1], w_5 ); // Q16
259 658400 : move32();
260 :
261 : /* Remove mean and scaling */
262 658400 : sum = 0;
263 658400 : move64();
264 11192800 : FOR( i = 0; i < SNS_NPTS; i++ )
265 : {
266 10534400 : sum = W_mac_32_16( sum, xl4[i], 1 ); // Q16+1
267 : }
268 : /* mean = sum / SNS_NPTS;
269 : -Q4 is for division with SNS_NPTS and -Q1 is to reduce Q by one */
270 658400 : mean = W_shl_sat_l( sum, -Q5 ); // Q16
271 :
272 11192800 : FOR( i = 0; i < SNS_NPTS; i++ )
273 : {
274 10534400 : scf[i] = Mpy_32_16_1( L_sub( xl4[i], mean ), 27853 /* 0.85 in in Q15 */ ); // Q16
275 10534400 : move32();
276 : }
277 :
278 658400 : return;
279 : }
280 :
281 : /*-------------------------------------------------------------------
282 : * sns_interpolate_scalefactors_fx()
283 : *
284 : *
285 : *-------------------------------------------------------------------*/
286 :
287 2025931 : void sns_interpolate_scalefactors_fx(
288 : Word32 *scf_int, /* o : interpolated scalefactors for spectrum shaping q16*/
289 : const Word32 *scf, /* i : sns scalefactors as derived from the signal or read from the bitstream Q16*/
290 : Word16 encoder_side /* i : flag, if scalefactors have to be inverted */
291 : )
292 : {
293 : Word16 n;
294 : Word32 L_tmp;
295 : Word16 exp;
296 :
297 : /* Interpolation */
298 2025931 : scf_int[0] = scf[0]; // q16
299 2025931 : scf_int[1] = scf[0]; // q16
300 2025931 : move32();
301 2025931 : move32();
302 :
303 32414896 : FOR( n = 0; n <= M - 2; n++ )
304 : {
305 30388965 : scf_int[n * 4 + 2] = Madd_32_16( scf[n], L_sub( scf[n + 1], scf[n] ), 4096 /* 4096 -> 1/8 in Q15 */ ); // q16
306 30388965 : scf_int[n * 4 + 3] = Madd_32_16( scf[n], L_sub( scf[n + 1], scf[n] ), 12288 /* 12288 -> 3/8 in Q15 */ ); // q16
307 30388965 : scf_int[n * 4 + 4] = Madd_32_16( scf[n], L_sub( scf[n + 1], scf[n] ), 20480 /* 20480 -> 5/8 in Q15 */ ); // q16
308 30388965 : scf_int[n * 4 + 5] = Madd_32_16( scf[n], L_sub( scf[n + 1], scf[n] ), 28672 /* 28672 -> 7/8 in Q15 */ ); // q16
309 30388965 : move32();
310 30388965 : move32();
311 30388965 : move32();
312 30388965 : move32();
313 : }
314 :
315 2025931 : scf_int[FDNS_NPTS - 2] = Madd_32_16( scf[M - 1], L_sub( scf[M - 1], scf[M - 2] ), 4096 /* 4096 -> 1/8 in Q15 */ ); // q16
316 2025931 : scf_int[FDNS_NPTS - 1] = Madd_32_16( scf[M - 1], L_sub( scf[M - 1], scf[M - 2] ), 12288 /* 12288 -> 3/8 in Q15 */ ); // q16
317 2025931 : move32();
318 2025931 : move32();
319 :
320 : /* Inversion at encoder-side */
321 2025931 : IF( encoder_side == ENC /*0*/ )
322 : {
323 80526030 : FOR( n = 0; n < FDNS_NPTS; n++ )
324 : {
325 79287168 : scf_int[n] = L_negate( scf_int[n] ); // q16
326 79287168 : move32();
327 : }
328 : }
329 :
330 : /* Linear domain */
331 131685515 : FOR( n = 0; n < FDNS_NPTS; n++ )
332 : {
333 129659584 : L_tmp = BASOP_util_Pow2( scf_int[n], 15 /*31-Q16*/, &exp ); // Q=31-exp
334 129659584 : exp = sub( 15, exp );
335 129659584 : scf_int[n] = L_shr( L_tmp, exp ); // q16
336 129659584 : move32();
337 : }
338 :
339 2025931 : return;
340 : }
341 :
342 :
343 : /*-------------------------------------------------------------------
344 : * sns_shape_spectrum_fx()
345 : *
346 : *
347 : *-------------------------------------------------------------------*/
348 :
349 1869100 : void sns_shape_spectrum_fx(
350 : Word32 spectrum[], /* i/o: spectrum to be shaped Input Q is q_spectrum and ouput Q is (q_spectrum-1)*/
351 : Word16 *q_spectrum, /* i/o: Q of spectrum */
352 : const PsychoacousticParameters *pPsychParams, /* i : psychoacoustic parameters used to get the frequency bands */
353 : const Word32 *scf_int, /* i : already interpolated SNS scalefactors */
354 : const Word16 q_scf_int, /* i : Q of interpolated SNS scalefactors q_scf_int*/
355 : const Word16 L_frame, /* i : frame length */
356 : Word16 *length )
357 : {
358 1869100 : Word16 i, n, k, tmp_k, bw, q_tmp = 0, shift, min_shift = 63;
359 1869100 : move16();
360 1869100 : move16();
361 : Word64 L64_tmp[L_FRAME48k];
362 1869100 : const UWord8 nBands = pPsychParams->nBands;
363 1869100 : move16();
364 1869100 : const UWord8 *bandLengths = pPsychParams->bandLengths;
365 :
366 1869100 : IF( bandLengths == NULL )
367 : {
368 3479 : bw = divide3216( shl( L_frame, 1 ), nBands ); // q0
369 :
370 : /* Shape spectrum */
371 3479 : k = 0;
372 3479 : move16();
373 226135 : FOR( i = 0; i < nBands; ++i )
374 : {
375 2540992 : FOR( n = 0; n < bw; ( ++n, ++k ) )
376 : {
377 2318336 : L64_tmp[k] = W_mult_32_32( spectrum[k], scf_int[i] ); // Q = q_spectrum + q_scf_int + 1
378 2318336 : move64();
379 : }
380 : }
381 3479 : tmp_k = k;
382 3479 : move16();
383 3479 : if ( length != NULL )
384 : {
385 3479 : *length = k;
386 3479 : move16();
387 : }
388 3479 : min_shift = W_norm_arr( L64_tmp, k );
389 3479 : q_tmp = sub( add( add( *q_spectrum, q_scf_int ), min_shift ), 32 );
390 3479 : if ( GT_16( q_tmp, 30 ) )
391 : {
392 34 : q_tmp = 30;
393 34 : move16();
394 : }
395 3479 : shift = sub( q_tmp, add( *q_spectrum, q_scf_int ) );
396 2321815 : FOR( k = 0; k < tmp_k; k++ )
397 : {
398 2318336 : spectrum[k] = W_shl_sat_l( L64_tmp[k], shift ); // q_tmp+1
399 2318336 : move32();
400 : }
401 3479 : *q_spectrum = q_tmp;
402 3479 : move16();
403 : }
404 : ELSE
405 : {
406 : /* Shape spectrum */
407 1865621 : k = 0;
408 1865621 : move16();
409 121265365 : FOR( i = 0; i < nBands; ++i )
410 : {
411 1138775392 : FOR( n = 0; n < bandLengths[i]; ( ++n, ++k ) )
412 : {
413 1019375648 : L64_tmp[k] = W_mult_32_32( spectrum[k], scf_int[i] ); // Q = q_spectrum + q_scf_int + 1
414 1019375648 : move64();
415 : }
416 : }
417 1865621 : tmp_k = k;
418 1865621 : move16();
419 1865621 : if ( length != NULL )
420 : {
421 1863514 : *length = k;
422 1863514 : move16();
423 : }
424 1865621 : min_shift = W_norm_arr( L64_tmp, k );
425 1865621 : q_tmp = sub( add( add( *q_spectrum, q_scf_int ), min_shift ), 32 );
426 1865621 : if ( GT_16( q_tmp, 30 ) )
427 : {
428 2043 : q_tmp = 30;
429 2043 : move16();
430 : }
431 1865621 : shift = sub( q_tmp, add( *q_spectrum, q_scf_int ) );
432 1021241269 : FOR( k = 0; k < tmp_k; k++ )
433 : {
434 1019375648 : spectrum[k] = W_shl_sat_l( L64_tmp[k], shift ); // q_tmp+1
435 1019375648 : move32();
436 : }
437 1865621 : *q_spectrum = q_tmp;
438 1865621 : move16();
439 : }
440 :
441 1869100 : return;
442 : }
|