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 <assert.h>
34 : #include <stdint.h>
35 : #include <math.h>
36 : #include "options.h"
37 : #include "cnst.h"
38 : #include "ivas_cnst.h"
39 : #include "prot_fx.h"
40 : #include "wmc_auto.h"
41 : #include "rom_com.h"
42 : #include "ivas_rom_com.h"
43 : #include "ivas_prot_fx.h"
44 :
45 : /*---------------------------------------------------------------
46 : * interpTargetChannel_fx()
47 : *
48 : * Target signal correction FOR shift variations.
49 : * The pointer passsed into this function is assumed to be chanR/chanL + currNCShift.
50 : * ---------------------------------------------------------------*/
51 :
52 : #define SPREAD_FACTOR1 ( 1.0f / INTERP_FACTOR1 )
53 :
54 : static Word32 table_596[N_MAX_SHIFT_CHANGE + 1] = {
55 : 0, 2441216, 1220608, 813738, 610304, 488243, 406869, 348745,
56 : 305152, 271246, 244121, 221928, 203434, 187785, 174372, 162747,
57 : 152576, 143600, 135623, 128485, 122060
58 : }; // Q12
59 :
60 : static Word32 inv_table_596[N_MAX_SHIFT_CHANGE + 1] = {
61 : 0, 7206320, 14412641, 21618962, 28825283, 36031605, 43237924, 50444244,
62 : 57650567, 64856889, 72063211, 79269528, 86475849, 93682173, 100888489, 108094813,
63 : 115301135, 122507459, 129713778, 136920096, 144126422
64 : }; // Q31
65 :
66 : static Word32 tableD1_596[N_MAX_SHIFT_CHANGE + 1] = {
67 : 0, 216, 1731, 5842, 13849, 27049, 46741, 74223,
68 : 110794, 157752, 216396, 288023, 373932, 475422, 593791, 730337,
69 : 886359, 1063155, 1262023, 1484262, 1731170
70 : }; // Q35
71 :
72 :
73 : static Word32 table_298[N_MAX_SHIFT_CHANGE + 1] = {
74 : 0, 1220608, 610304, 406869, 305152, 244121, 203434, 174372,
75 : 152576, 135623, 122060, 110964, 101717, 93892, 87186, 81373,
76 : 76288, 71800, 67811, 64242, 61030
77 : }; // Q12
78 :
79 : static Word32 inv_table_298[N_MAX_SHIFT_CHANGE + 1] = {
80 : 0, 14412641, 28825283, 43237924, 57650567, 72063211, 86475849, 100888489,
81 : 115301135, 129713778, 144126422, 158539056, 172951698, 187364347, 201776979, 216189627,
82 : 230602270, 245014919, 259427557, 273840192, 288252845
83 : }; // Q31
84 :
85 : static Word32 tableD1_298[N_MAX_SHIFT_CHANGE + 1] = {
86 : 0, 1731, 13849, 46741, 110794, 216396, 373932, 593791,
87 : 886359, 1262023, 1731170, 2304187, 2991462, 3803381, 4750330, 5842699,
88 : 7090873, 8505240, 10096185, 11874096, 13849363
89 : }; // Q35
90 :
91 :
92 : static Word32 table_290[N_MAX_SHIFT_CHANGE + 1] = {
93 : 0, 1187840, 593920, 395946, 296960, 237568, 197973, 169691,
94 : 148480, 131982, 118784, 107985, 98986, 91372, 84845, 79189,
95 : 74240, 69872, 65991, 62517, 59392
96 : }; // Q12
97 :
98 : static Word32 inv_table_290[N_MAX_SHIFT_CHANGE + 1] = {
99 : 0, 14810232, 29620464, 44430697, 59240928, 74051160, 88861394, 103671628,
100 : 118481856, 133292091, 148102320, 162912554, 177722789, 192533022, 207343256, 222153473,
101 : 236963712, 251773958, 266584183, 281394409, 296204640
102 : }; // Q31
103 :
104 : static Word32 tableD1_290[N_MAX_SHIFT_CHANGE + 1] = {
105 : 0, 1878, 15027, 50717, 120219, 234803, 405740, 644300,
106 : 961755, 1369374, 1878428, 2500187, 3245924, 4126907, 5154407, 6339694,
107 : 7694041, 9228719, 10954993, 12884138, 15027425
108 : }; // Q35
109 :
110 :
111 : static Word32 table_145[N_MAX_SHIFT_CHANGE + 1] = {
112 : 0, 593920, 296960, 197973, 148480, 118784, 98986, 84845,
113 : 74240, 65991, 59392, 53992, 49493, 45686, 42422, 39594,
114 : 37120, 34936, 32995, 31258, 29696
115 : }; // Q12
116 :
117 : static Word32 inv_table_145[N_MAX_SHIFT_CHANGE + 1] = {
118 : 0, 29620464, 59240928, 88861394, 118481856, 148102320, 177722789, 207343256,
119 : 236963712, 266584183, 296204640, 325825109, 355445578, 385066045, 414686513, 444306946,
120 : 473927425, 503547916, 533168367, 562788819, 592409281
121 : }; // Q31
122 :
123 : static Word32 tableD1_145[N_MAX_SHIFT_CHANGE + 1] = {
124 : 0, 15027, 120219, 405740, 961755, 1878428, 3245924, 5154407,
125 : 7694041, 10954993, 15027425, 20001503, 25967392, 33015256, 41235259, 50717555,
126 : 61552334, 73829752, 87639951, 103073111, 120219402
127 : }; // Q35
128 :
129 :
130 : /*---------------------------------------------------------------
131 : * Function interpTargetChannel_fx()
132 : *
133 : *
134 : *---------------------------------------------------------------*/
135 :
136 3234 : static void interpTargetChannel_fx(
137 : Word32 *target_fx, // qsynth
138 : const Word16 prevShift, // Q0
139 : const Word16 currShift, // Q0
140 : const Word16 L_shift_adapt ) // Q0
141 : {
142 : Word16 i, j, k, /*m,*/ d, N, signShift, lim1, lim2;
143 : const Word32 *win_fx;
144 : Word32 *ptr1_fx, *ptr2_fx;
145 : Word32 tempBuff1_fx[INTERP_FACTOR1 * ( L_SHIFT_ADAPT_MAX + 2 * N_MAX_SHIFT_CHANGE + 2 )], tempBuff2_fx[L_SHIFT_ADAPT_MAX - 1];
146 : Word32 x_fx[4], y_fx[4], tempF1_fx;
147 : Word32 interp_factor2_fx, factor_fx;
148 : Word32 spread_factor2_fx;
149 : Word64 tempD1_fx, tempD2_fx;
150 :
151 3234 : d = sub( prevShift, currShift );
152 :
153 3234 : IF( d == 0 )
154 : {
155 : /* this can happen in DFT->TD switching */
156 1197 : return;
157 : }
158 :
159 2037 : signShift = 1;
160 2037 : move16();
161 :
162 2037 : if ( d < 0 )
163 : {
164 1165 : signShift = -1;
165 1165 : move16();
166 : }
167 :
168 2037 : N = L_shift_adapt;
169 2037 : move16();
170 2037 : Word32 *table_pointer = NULL;
171 2037 : Word32 *inv_table_pointer = NULL;
172 2037 : Word32 *table_D1_pointer = NULL;
173 2037 : SWITCH( N )
174 : {
175 1662 : case 596:
176 1662 : table_pointer = table_596; // Q12
177 1662 : inv_table_pointer = inv_table_596; // Q31
178 1662 : table_D1_pointer = tableD1_596; // Q35
179 1662 : BREAK;
180 0 : case 298:
181 0 : table_pointer = table_298; // Q12
182 0 : inv_table_pointer = inv_table_298; // Q31
183 0 : table_D1_pointer = tableD1_298; // Q35
184 0 : BREAK;
185 375 : case 290:
186 375 : table_pointer = table_290; // Q12
187 375 : inv_table_pointer = inv_table_290; // Q31
188 375 : table_D1_pointer = tableD1_290; // Q35
189 375 : BREAK;
190 0 : case 145:
191 0 : table_pointer = table_145; // Q12
192 0 : inv_table_pointer = inv_table_145; // Q31
193 0 : table_D1_pointer = tableD1_145; // Q35
194 0 : BREAK;
195 0 : default:
196 0 : assert( 0 );
197 : }
198 :
199 2037 : factor_fx = table_pointer[abs( d )]; // Q12
200 2037 : move32();
201 2037 : interp_factor2_fx = L_shr( factor_fx, 1 ); // Q12
202 2037 : spread_factor2_fx = inv_table_pointer[abs( d )]; // Q31
203 2037 : move32();
204 :
205 : /* start from (target - N - d + 1) : (extra lag = step1) :to: (target - 1 - d) : (extra lag = d) */
206 : /* sinc interp by a factor of 2 */
207 :
208 2037 : win_fx = ica_sincInterp2_fx + SINC_ORDER1; // Q31
209 2037 : ptr1_fx = target_fx; // qsynth
210 2037 : ptr2_fx = tempBuff1_fx + ( N_MAX_SHIFT_CHANGE + 1 ) * INTERP_FACTOR1;
211 :
212 2371749 : FOR( i = -( N_MAX_SHIFT_CHANGE + 1 ) * INTERP_FACTOR1; i < ( N + N_MAX_SHIFT_CHANGE + 1 ) * INTERP_FACTOR1; i++ )
213 : {
214 2369712 : IF( s_and( i, 0x1 ) )
215 : {
216 1184856 : ptr2_fx[i] = 0;
217 1184856 : move32();
218 : /* lim1 = ceil((i - SINC_ORDER1)*SPREAD_FACTOR1); */
219 : /* lim2 = floor((i + SINC_ORDER1)*SPREAD_FACTOR1); */
220 1184856 : lim1 = add( shr( sub( i, SINC_ORDER1 ), 1 ), 1 );
221 :
222 1184856 : lim2 = shr( add( i, SINC_ORDER1 ), 1 );
223 :
224 29621400 : FOR( j = lim1; j <= lim2; j++ )
225 : {
226 28436544 : ptr2_fx[i] = Madd_32_32( ptr2_fx[i], win_fx[j * INTERP_FACTOR1 - i], ptr1_fx[j] ); // qsynth
227 28436544 : move32();
228 : }
229 : }
230 : ELSE
231 : {
232 1184856 : ptr2_fx[i] = ptr1_fx[i / 2]; // qsynth
233 1184856 : move32();
234 : }
235 : }
236 :
237 : /* cubic spline interp */
238 2037 : ptr1_fx = ptr2_fx; // qsynth
239 2037 : ptr2_fx = tempBuff2_fx; // qsynth
240 :
241 2037 : tempD1_fx = W_deposit32_l( table_D1_pointer[abs( d )] ); // Q35
242 2037 : tempD2_fx = W_mult0_32_32( 3, table_D1_pointer[abs( d )] ); // Q35
243 :
244 2037 : tempF1_fx = -ONE_IN_Q12; // Q12
245 2037 : move32();
246 :
247 2037 : if ( EQ_16( signShift, 1 ) )
248 : {
249 872 : tempF1_fx = ONE_IN_Q12; // Q12
250 872 : move32();
251 : }
252 :
253 2037 : tempF1_fx = L_sub( imult3216( factor_fx, d ), tempF1_fx ); // Q12
254 1099302 : FOR( k = 0; k < N - 1; k++ )
255 : {
256 1097265 : Word32 local = Madd_32_32( -ONE_IN_Q12, tempF1_fx, spread_factor2_fx ); // Q12
257 1097265 : Word32 local_int = L_shr( local, 12 ); // Q0
258 : Word32 res_a1, res_a2, res_a3;
259 : Word32 res_b1, res_b2, res_b3;
260 : Word32 res_c1, res_c2, res_c3;
261 : Word32 res_d1, res_d2, res_d3;
262 : Word32 local_int_scaled;
263 : Word64 res_a, res_b, res_c, res_d;
264 : Word64 tempa, tempb;
265 : Word64 mult_a_D1, mult_b_D2;
266 1097265 : local_int_scaled = L_shl( local_int, 12 ); // Q12
267 1097265 : lim1 = extract_l( local_int ); // Q0
268 1097265 : if ( L_sub( local_int_scaled, local ) > 0 ) // Q12
269 : {
270 0 : lim1 = sub( lim1, 1 ); // Q0
271 : }
272 :
273 1097265 : y_fx[0] = ptr1_fx[lim1]; // qsynth
274 1097265 : move32();
275 1097265 : y_fx[1] = ptr1_fx[lim1 + 1]; // qsynth
276 1097265 : move32();
277 1097265 : y_fx[2] = ptr1_fx[lim1 + 2]; // qsynth
278 1097265 : move32();
279 1097265 : y_fx[3] = ptr1_fx[lim1 + 3]; // qsynth
280 1097265 : move32();
281 :
282 1097265 : x_fx[0] = imult3216( interp_factor2_fx, lim1 ); // Q12
283 1097265 : move32();
284 1097265 : x_fx[1] = L_add( x_fx[0], interp_factor2_fx ); // Q12
285 1097265 : move32();
286 1097265 : x_fx[2] = L_add( x_fx[1], interp_factor2_fx ); // Q12
287 1097265 : move32();
288 1097265 : x_fx[3] = L_add( x_fx[2], interp_factor2_fx ); // Q12
289 1097265 : move32();
290 :
291 1097265 : res_a1 = L_sub( tempF1_fx, x_fx[0] ); // Q12
292 1097265 : res_a2 = L_sub( tempF1_fx, x_fx[1] ); // Q12
293 1097265 : res_a3 = L_sub( tempF1_fx, x_fx[2] ); // Q12
294 1097265 : res_a = W_shr( W_mult0_32_32( res_a1, res_a2 ), 12 ) * res_a3; // Q24
295 1097265 : res_a = ( y_fx[3] * W_shr( res_a, 16 ) ); // qsynth+8
296 :
297 1097265 : res_b1 = L_sub( tempF1_fx, x_fx[1] ); // Q12
298 1097265 : res_b2 = L_sub( tempF1_fx, x_fx[2] ); // Q12
299 1097265 : res_b3 = L_sub( tempF1_fx, x_fx[3] ); // Q12
300 1097265 : res_b = W_shr( W_mult0_32_32( res_b1, res_b2 ), 12 ) * res_b3; // Q24
301 1097265 : res_b = ( y_fx[0] * W_shr( res_b, 16 ) ); // qsynth+8
302 :
303 1097265 : res_c1 = L_sub( tempF1_fx, x_fx[0] ); // Q12
304 1097265 : res_c2 = L_sub( tempF1_fx, x_fx[2] ); // Q12
305 1097265 : res_c3 = L_sub( tempF1_fx, x_fx[3] ); // Q12
306 1097265 : res_c = W_shr( W_mult0_32_32( res_c1, res_c2 ), 12 ) * res_c3; // Q24
307 1097265 : res_c = ( y_fx[1] * W_shr( res_c, 16 ) ); // qsynth+8
308 :
309 1097265 : res_d1 = L_sub( tempF1_fx, x_fx[0] ); // Q12
310 1097265 : res_d2 = L_sub( tempF1_fx, x_fx[1] ); // Q12
311 1097265 : res_d3 = L_sub( tempF1_fx, x_fx[3] ); // Q12
312 1097265 : res_d = W_shr( W_mult0_32_32( res_d1, res_d2 ), 12 ) * res_d3; // Q24
313 1097265 : res_d = ( y_fx[2] * W_shr( res_d, 16 ) ); // qsynth+8
314 :
315 :
316 1097265 : tempa = W_sub( res_a, res_b ); // qsynth+8
317 1097265 : tempb = W_sub( res_c, res_d ); // qsynth+8
318 :
319 1097265 : mult_a_D1 = W_shr( ( tempD1_fx * W_shr( tempa, 14 ) ), 15 ); // Q38
320 1097265 : mult_b_D2 = W_shr( ( tempD2_fx * W_shr( tempb, 14 ) ), 15 ); // Q38
321 1097265 : ptr2_fx[k] = W_extract_l( ( W_shr( W_add( mult_a_D1, mult_b_D2 ), 14 ) ) ); // 38-14
322 1097265 : move32();
323 :
324 1097265 : IF( EQ_16( signShift, 1 ) )
325 : {
326 476918 : tempF1_fx = W_extract_l( W_add( tempF1_fx, L_sub( factor_fx, ONE_IN_Q12 ) ) ); // Q12
327 476918 : move32();
328 : }
329 : ELSE
330 : {
331 620347 : tempF1_fx = W_extract_l( W_add( tempF1_fx, L_sub( factor_fx, -ONE_IN_Q12 ) ) ); // Q12
332 620347 : move32();
333 : }
334 : }
335 2037 : ptr1_fx = target_fx; // qsynth
336 2037 : Copy32( ptr2_fx, ptr1_fx, sub( N, 1 ) ); // qsynth
337 :
338 2037 : return;
339 : }
340 :
341 :
342 : /*---------------------------------------------------------------
343 : * Function targetCh_AlignStereoDFT()
344 : *
345 : * Align target channel in DFT stereo to correct FOR shift variations
346 : * ---------------------------------------------------------------*/
347 :
348 1045 : static void targetCh_AlignStereoDFT_fx(
349 : Word32 *target_fx, // qsynth
350 : const Word16 prevShift, // Q0
351 : const Word16 currShift, // Q0
352 : const Word16 L_shift_adapt ) // Q0
353 : {
354 : Word16 i;
355 : Word32 winSlope_fx, alpha_fx;
356 : Word16 d;
357 :
358 : Word32 fadeOutBuff_fx[L_SHIFT_ADAPT_MAX];
359 : Word32 fadeInBuff_fx[L_SHIFT_ADAPT_MAX];
360 :
361 1045 : d = negate( sub( currShift, prevShift ) ); // Q0
362 :
363 1045 : Copy32( target_fx + d, fadeOutBuff_fx, L_shift_adapt ); // qsynth
364 1045 : Copy32( target_fx, fadeInBuff_fx, L_shift_adapt ); // qsynth
365 :
366 1045 : IF( L_shift_adapt > 0 )
367 : {
368 1045 : alpha_fx = 0;
369 1045 : SWITCH( L_shift_adapt )
370 : {
371 809 : case 596:
372 809 : winSlope_fx = 3603160; /* ( 1 / 596 ) in Q31 */ // Q31
373 809 : move32();
374 809 : BREAK;
375 8 : case 298:
376 8 : winSlope_fx = 7206320; /* ( 1 / 298 ) in Q31 */ // Q31
377 8 : move32();
378 8 : BREAK;
379 224 : case 290:
380 224 : winSlope_fx = 7405116; /* ( 1 / 290 ) in Q31 */ // Q31
381 224 : move32();
382 224 : BREAK;
383 4 : case 145:
384 4 : winSlope_fx = 14810232; /* ( 1 / 145 ) in Q31 */ // Q31
385 4 : move32();
386 4 : BREAK;
387 0 : default:
388 0 : winSlope_fx = ONE_IN_Q31; // Q31
389 0 : move32();
390 0 : BREAK;
391 : }
392 551133 : FOR( i = 0; i < L_shift_adapt; i++ )
393 : {
394 550088 : target_fx[i] = Madd_32_32( Mpy_32_32( alpha_fx, fadeInBuff_fx[i] ), L_sub( ONE_IN_Q31, alpha_fx ), fadeOutBuff_fx[i] ); // qsynth
395 550088 : move32();
396 :
397 550088 : alpha_fx = L_add_sat( alpha_fx, winSlope_fx ); // Q31
398 : }
399 : }
400 : ELSE
401 : {
402 0 : Copy32( fadeInBuff_fx, target_fx, L_shift_adapt ); // qsynth
403 : }
404 :
405 1045 : return;
406 : }
407 :
408 :
409 : /*---------------------------------------------------------------
410 : * adjustTargetSignal()
411 : *
412 : * Target signal correction FOR shift variations.
413 : * ---------------------------------------------------------------*/
414 :
415 4279 : void adjustTargetSignal_fx(
416 : Word32 *target_fx, // qsynth
417 : const Word16 prevShift, // Q0
418 : const Word16 currShift, // Q0
419 : const Word16 L_shift_adapt, // Q0
420 : const Word16 method ) // Q0
421 : {
422 : /* inter-frame shift variation and target shifting */
423 :
424 4279 : IF( method == 0 )
425 : {
426 3234 : interpTargetChannel_fx( target_fx, prevShift, currShift, L_shift_adapt );
427 : }
428 : ELSE
429 : {
430 1045 : targetCh_AlignStereoDFT_fx( target_fx, prevShift, currShift, L_shift_adapt );
431 : }
432 :
433 4279 : return;
434 : }
|