LCOV - code coverage report
Current view: top level - lib_com - ivas_stereo_ica_com_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main enc/dec/rend @ 3b2f07138c61dcf997bbf4165d0882f794b2995f Lines: 143 161 88.8 %
Date: 2025-05-03 01:55:50 Functions: 3 3 100.0 %

          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             : }

Generated by: LCOV version 1.14