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