LCOV - code coverage report
Current view: top level - lib_dec - ivas_stereo_dft_dec_dmx_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main enc/dec/rend @ 3b2f07138c61dcf997bbf4165d0882f794b2995f Lines: 240 252 95.2 %
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 "options.h"
      36             : #include <math.h>
      37             : #include "cnst.h"
      38             : #include "prot_fx.h"
      39             : #include "ivas_cnst.h"
      40             : #include "ivas_rom_com.h"
      41             : #include "ivas_rom_dec.h"
      42             : #include "rom_com.h"
      43             : #include "wmc_auto.h"
      44             : #include "ivas_prot_fx.h"
      45             : 
      46             : 
      47             : /*-------------------------------------------------------------------------
      48             :  * stereo_dft_dmx_out_reset()
      49             :  *
      50             :  * Reset DFT stereo mono output memories
      51             :  *------------------------------------------------------------------------*/
      52             : 
      53         565 : void stereo_dft_dmx_out_reset_fx(
      54             :     STEREO_DFT_DMX_DATA_HANDLE hStereoDftDmx /* i/o: DFT stereo DMX decoder          */
      55             : )
      56             : {
      57         565 :     hStereoDftDmx->targetGain_fx = ONE_IN_Q29; /* Q29 */
      58         565 :     move32();
      59         565 :     hStereoDftDmx->prevTargetGain_fx = ONE_IN_Q29; /* Q29 */
      60         565 :     move32();
      61             : 
      62         565 :     set32_fx( hStereoDftDmx->memOutHB_fx, 0, NS2SA( 48000, STEREO_DFT32MS_OVL_NS ) );
      63         565 :     set32_fx( hStereoDftDmx->memTransitionHB_fx, 0, NS2SA( 48000, STEREO_DFT32MS_OVL_NS ) );
      64             : 
      65         565 :     return;
      66             : }
      67             : 
      68             : 
      69             : /*-------------------------------------------------------------------------
      70             :  * stereo_dft_unify_dmx()
      71             :  *
      72             :  * create a uniform dmx in case of residual coding by converting from passive
      73             :  * to active dmx in residual coding region
      74             :  *-------------------------------------------------------------------------*/
      75             : 
      76        5345 : void stereo_dft_unify_dmx_fx(
      77             :     STEREO_DFT_DEC_DATA_HANDLE hStereoDft,        /* i/o: decoder stereo handle                                                   */
      78             :     Decoder_State *st0,                           /* i/o: decoder state structure                                                 */
      79             :     Word32 DFT[CPE_CHANNELS][STEREO_DFT_BUF_MAX], /* i/o: DFT buffers                                     hStereoDft->qDFT*/
      80             :     Word32 *input_mem,                            /* i/o: mem of buffer DFT analysis                               Q11*/
      81             :     const Word16 prev_sid_nodata                  /* i  : Previous SID/No data indicator                                Q0*/
      82             : )
      83             : {
      84             :     Word16 i, k, b, N_div;
      85             :     Word32 DFT_L[STEREO_DFT32MS_N_MAX];
      86             :     Word32 DFT_R[STEREO_DFT32MS_N_MAX];
      87             :     Word32 *pDFT_DMX;
      88             :     Word32 *pDFT_RES;
      89             :     Word32 tmp;
      90             :     Word32 *pSideGain;
      91             :     Word16 k_offset, g;
      92             : 
      93             :     /* Variables for stereo residual PLC */
      94             :     Word32 DFT_PRED_RES[STEREO_DFT32MS_N_32k];
      95             :     Word16 samp_ratio, q_samp_ratio;
      96             :     Word16 prev_bfi;
      97             :     Word32 dmx_nrg;
      98             :     Word32 *pPredGain;
      99             :     Word16 stop;
     100             :     Word16 output_frame;
     101             :     Word16 plocs[STEREO_DFT_RES_N_PEAKS_MAX];
     102             :     Word16 num_plocs;
     103             :     Word32 plocsi[STEREO_DFT_RES_N_PEAKS_MAX];
     104             : 
     105        5345 :     set32_fx( DFT_PRED_RES, 0, STEREO_DFT32MS_N_32k );
     106             : 
     107        5345 :     output_frame = extract_l( Mult_32_16( st0->output_Fs, INV_FRAME_PER_SEC_Q15 ) ); /* Q0 */
     108        5345 :     samp_ratio = BASOP_Util_Divide3232_Scale( st0->sr_core, st0->output_Fs, &q_samp_ratio );
     109        5345 :     samp_ratio = shr( samp_ratio, sub( Q15 - Q12, q_samp_ratio ) );
     110             : 
     111        5345 :     prev_bfi = st0->prev_old_bfi; /* Q0 */
     112        5345 :     move32();
     113             : 
     114             :     /* Initialization */
     115        5345 :     k_offset = 1;
     116        5345 :     move16();
     117        5345 :     N_div = STEREO_DFT_NBDIV;
     118        5345 :     move16();
     119             : 
     120        5345 :     dmx_nrg = 0;
     121        5345 :     move32();
     122             :     /* make sure number of bands corresponds to output bwidth in case it is lower than parameter bwidth */
     123        5345 :     IF( LT_16( output_frame, inner_frame_tbl[st0->bwidth] ) )
     124             :     {
     125        1231 :         hStereoDft->nbands = stereo_dft_band_config_fx( hStereoDft->band_limits, hStereoDft->band_res[k_offset], hStereoDft->NFFT, DEC );
     126        1231 :         move16();
     127             :     }
     128        5345 :     IF( prev_bfi )
     129             :     {
     130         136 :         dmx_nrg = stereo_dft_dmx_swb_nrg_fx( DFT[0], DFT[0] + STEREO_DFT32MS_N_MAX, s_min( hStereoDft->NFFT, STEREO_DFT32MS_N_32k ), 0, 0 );
     131             :     }
     132             : 
     133             :     /* Analyze nature of current frame */
     134        5345 :     test();
     135        5345 :     test();
     136        5345 :     test();
     137        5345 :     test();
     138        5345 :     test();
     139        5345 :     test();
     140        5345 :     test();
     141        5345 :     test();
     142       10263 :     hStereoDft->trans = (Word16) ( ( EQ_16( st0->clas_dec, ONSET ) || EQ_16( st0->clas_dec, SIN_ONSET ) || EQ_16( st0->clas_dec, UNVOICED_CLAS ) || EQ_16( st0->clas_dec, UNVOICED_TRANSITION ) ) || LE_16( st0->stab_fac_fx, (Word16) 0x2000 ) ) ||
     143        4918 :                         ( ( EQ_16( st0->core, TCX_20_CORE ) && ( EQ_16( st0->hTcxCfg->tcx_last_overlap_mode, MIN_OVERLAP ) || EQ_16( st0->hTcxCfg->tcx_last_overlap_mode, HALF_OVERLAP ) ) ) || EQ_16( st0->core, TCX_10_CORE ) ); /* Q0 */
     144        5345 :     move16();
     145             : 
     146             :     /* Smoothing for the current frame */
     147        5345 :     stereo_dft_dec_smooth_parameters_fx( hStereoDft, prev_sid_nodata, st0->hFdCngDec->hFdCngCom->active_frame_counter, st0->element_brate );
     148             : 
     149       16035 :     FOR( k = 0; k < N_div; k++ )
     150             :     {
     151       10690 :         pDFT_DMX = DFT[0] + i_mult( k, STEREO_DFT32MS_N_MAX ); /* qDFT */
     152       10690 :         pDFT_RES = DFT[1] + i_mult( k, STEREO_DFT32MS_N_MAX ); /* qDFT */
     153             : 
     154       10690 :         assert( hStereoDft->hConfig->dmx_active );
     155             :         /*Apply Stereo*/
     156       10690 :         g = MAX_16;
     157       10690 :         move16();
     158             :         /* since delay is just 3.125ms, the parameters received are used for the second window */
     159       10690 :         pSideGain = hStereoDft->side_gain_fx + i_mult( add( k, k_offset ), STEREO_DFT_BAND_MAX ); /* Q31 */
     160             : 
     161             :         /* Stereo residual PLC */
     162       10690 :         IF( hStereoDft->res_cod_band_max > 0 )
     163             :         {
     164       10690 :             IF( !st0->bfi )
     165             :             {
     166       10418 :                 IF( EQ_16( k, 1 ) )
     167             :                 {
     168        5209 :                     Copy32( pDFT_RES, hStereoDft->res_mem_fx, shl( hStereoDft->band_limits[hStereoDft->res_cod_band_max], 1 ) ); /* qDFT */
     169        5209 :                     hStereoDft->q_res_mem = hStereoDft->q_dft;
     170        5209 :                     move16();
     171        5209 :                     hStereoDft->time_offs = 0;
     172        5209 :                     move16();
     173             :                 }
     174             :             }
     175             :             ELSE
     176             :             {
     177         272 :                 hStereoDft->nbands = hStereoDft->res_cod_band_max; /* Limit nbands since residual PLC only needs the low frequency range of the stereo filling */
     178         272 :                 move16();
     179         272 :                 pPredGain = hStereoDft->res_pred_gain_fx + i_mult( add( k, k_offset ), STEREO_DFT_BAND_MAX ); /* Q31 */
     180         272 :                 hStereoDft->past_DMX_pos = ( sub( add( hStereoDft->past_DMX_pos, STEREO_DFT_PAST_MAX ), 1 ) ) % STEREO_DFT_PAST_MAX;
     181         272 :                 move16();
     182         272 :                 stereo_dft_generate_res_pred_fx( hStereoDft, samp_ratio, pDFT_DMX, DFT_PRED_RES, pPredGain, k, DFT[1] + k * STEREO_DFT32MS_N_MAX, &stop, st0->bfi );
     183         272 :                 stereo_dft_res_ecu_fx( hStereoDft, pDFT_RES, DFT_PRED_RES, k, output_frame, prev_bfi, dmx_nrg, &num_plocs, plocs, plocsi, input_mem );
     184         272 :                 hStereoDft->q_res_cod_mem_fx = hStereoDft->q_dft;
     185         272 :                 move16();
     186             :             }
     187             :         }
     188             : 
     189             : 
     190             :         /* Apply active DMX */
     191       10690 :         DFT_L[0] = pDFT_DMX[0]; /* qDFT */
     192       10690 :         move32();
     193       10690 :         DFT_R[0] = pDFT_DMX[0];
     194       10690 :         move32();
     195             : 
     196             :         /* upmix residual part */
     197       64140 :         FOR( b = 0; b < hStereoDft->res_cod_band_max; b++ )
     198             :         {
     199       53450 :             g = extract_h( pSideGain[b] ); /* Q15 */
     200       53450 :             move16();
     201             : 
     202      267250 :             FOR( i = hStereoDft->band_limits[b]; i < hStereoDft->band_limits[b + 1]; i++ )
     203             :             {
     204      213800 :                 tmp = Madd_32_16( pDFT_RES[2 * i], pDFT_DMX[2 * i], g ); /* qDFT */
     205             : 
     206      213800 :                 DFT_L[2 * i] = L_add( pDFT_DMX[2 * i], tmp ); /* qDFT */
     207      213800 :                 move32();
     208      213800 :                 DFT_R[2 * i] = L_sub( pDFT_DMX[2 * i], tmp ); /* qDFT */
     209      213800 :                 move32();
     210             : 
     211      213800 :                 tmp = Madd_32_16( pDFT_RES[2 * i + 1], pDFT_DMX[2 * i + 1], g );
     212             : 
     213      213800 :                 DFT_L[2 * i + 1] = L_add( pDFT_DMX[2 * i + 1], tmp ); /* qDFT */
     214      213800 :                 move32();
     215      213800 :                 DFT_R[2 * i + 1] = L_sub( pDFT_DMX[2 * i + 1], tmp ); /* qDFT */
     216      213800 :                 move32();
     217             :             }
     218             :         }
     219             : 
     220             :         /* downmix residual part with active downmix */
     221       64140 :         FOR( b = 0; b < hStereoDft->res_cod_band_max; b++ )
     222             :         {
     223             :             Word16 j;
     224             :             Word32 sum_nrg_Mid, sum_abs, dot_prod_abs;
     225             :             Word16 wR, wL;
     226       53450 :             Word16 norm_sum_nrg_L = 63, norm_sum_nrg_R = 63, norm_dot_prod_real = 63, norm_dot_prod_imag = 63, guard_bit = 2 /*find_guarded_bits_fx( 4 )*/, min_norm, q_sum_nrg_L, q_sum_nrg_R, q_dot_prod_real;
     227       53450 :             move16();
     228       53450 :             move16();
     229       53450 :             move16();
     230       53450 :             move16();
     231       53450 :             move16();
     232             :             Word16 exp_sum_nrg_l, exp_sum_nrg_R, exp_dot_prod_abs, exp_sum_nrg_Mid;
     233             :             Word32 sum_nrg_L_32, sum_nrg_R_32, dot_prod_real_32, dot_prod_img_32;
     234       53450 :             Word64 sum_nrg_L = 0, sum_nrg_R = 0;
     235       53450 :             move64();
     236       53450 :             move64();
     237       53450 :             Word64 dot_prod_real = 0, dot_prod_img = 0;
     238       53450 :             move64();
     239       53450 :             move64();
     240             : 
     241      267250 :             FOR( j = hStereoDft->band_limits[b]; j < hStereoDft->band_limits[b + 1]; j++ )
     242             :             {
     243      213800 :                 sum_nrg_L = W_add( sum_nrg_L, W_add( W_mult_32_32( DFT_L[2 * j], DFT_L[2 * j] ), W_mult_32_32( DFT_L[2 * j + 1], DFT_L[2 * j + 1] ) ) ); /* 2 * q_dft + 1 */
     244      213800 :                 sum_nrg_R = W_add( sum_nrg_R, W_add( W_mult_32_32( DFT_R[2 * j], DFT_R[2 * j] ), W_mult_32_32( DFT_R[2 * j + 1], DFT_R[2 * j + 1] ) ) ); /* 2 * q_dft + 1 */
     245             : 
     246      213800 :                 dot_prod_real = W_add( dot_prod_real, W_add( W_mult_32_32( DFT_L[2 * j], DFT_R[2 * j] ), W_mult_32_32( DFT_L[2 * j + 1], DFT_R[2 * j + 1] ) ) ); /* 2 * q_dft + 1 */
     247      213800 :                 dot_prod_img = W_add( dot_prod_img, W_sub( W_mult_32_32( DFT_L[2 * j + 1], DFT_R[2 * j] ), W_mult_32_32( DFT_L[2 * j], DFT_R[2 * j + 1] ) ) );   /* 2 * q_dft + 1 */
     248             :             }
     249             : 
     250       53450 :             IF( sum_nrg_L != 0 )
     251             :             {
     252       53450 :                 norm_sum_nrg_L = W_norm( sum_nrg_L );
     253             :             }
     254       53450 :             IF( sum_nrg_R != 0 )
     255             :             {
     256       53450 :                 norm_sum_nrg_R = W_norm( sum_nrg_R );
     257             :             }
     258       53450 :             IF( dot_prod_real != 0 )
     259             :             {
     260       53450 :                 norm_dot_prod_real = W_norm( dot_prod_real );
     261             :             }
     262       53450 :             IF( dot_prod_img != 0 )
     263             :             {
     264       52905 :                 norm_dot_prod_imag = W_norm( dot_prod_img );
     265             :             }
     266             : 
     267       53450 :             guard_bit = find_guarded_bits_fx( 4 );
     268       53450 :             min_norm = s_min( s_min( s_min( norm_sum_nrg_L, norm_sum_nrg_R ), norm_dot_prod_real ), norm_dot_prod_imag ) - guard_bit;
     269       53450 :             sum_nrg_L_32 = W_extract_h( W_shl( sum_nrg_L, min_norm ) );
     270       53450 :             sum_nrg_R_32 = W_extract_h( W_shl( sum_nrg_R, min_norm ) );
     271       53450 :             dot_prod_real_32 = W_extract_h( W_shl( dot_prod_real, min_norm ) );
     272       53450 :             dot_prod_img_32 = W_extract_h( W_shl( dot_prod_img, min_norm ) );
     273             : 
     274       53450 :             q_sum_nrg_L = sub( add( shl( hStereoDft->q_dft, 1 ), min_norm ), 31 );
     275       53450 :             q_sum_nrg_R = sub( add( shl( hStereoDft->q_dft, 1 ), min_norm ), 31 );
     276       53450 :             q_dot_prod_real = sub( add( shl( hStereoDft->q_dft, 1 ), min_norm ), 31 );
     277             : 
     278       53450 :             exp_sum_nrg_l = sub( 31, q_sum_nrg_L );
     279       53450 :             exp_sum_nrg_R = sub( 31, q_sum_nrg_R );
     280       53450 :             exp_dot_prod_abs = sub( 31, sub( shl( q_dot_prod_real, 1 ), 31 ) );
     281       53450 :             exp_sum_nrg_Mid = sub( 31, q_sum_nrg_L );
     282             : 
     283       53450 :             sum_nrg_Mid = L_max( 0, L_add( L_add( sum_nrg_L_32, sum_nrg_R_32 ), L_shl( dot_prod_real_32, 1 ) ) ); /* q_sum_nrg_L */
     284             : 
     285       53450 :             Word32 tmp_nrg_L = Sqrt32( sum_nrg_L_32, &exp_sum_nrg_l );
     286       53450 :             Word32 tmp_nrg_R = Sqrt32( sum_nrg_R_32, &exp_sum_nrg_R );
     287       53450 :             Word16 exp_sum_abs = exp_sum_nrg_l;
     288       53450 :             move16();
     289             : 
     290       53450 :             if ( GT_16( exp_sum_nrg_R, exp_sum_nrg_l ) )
     291             :             {
     292       22697 :                 exp_sum_abs = exp_sum_nrg_R;
     293       22697 :                 move16();
     294             :             }
     295       53450 :             exp_sum_abs = add( exp_sum_abs, 1 );
     296       53450 :             sum_abs = L_add( L_shr( tmp_nrg_L, sub( exp_sum_abs, exp_sum_nrg_l ) ), L_shr( tmp_nrg_R, sub( exp_sum_abs, exp_sum_nrg_R ) ) );
     297       53450 :             dot_prod_abs = Sqrt32( L_add( Mpy_32_32( dot_prod_real_32, dot_prod_real_32 ), Mpy_32_32( dot_prod_img_32, dot_prod_img_32 ) ), &exp_dot_prod_abs );
     298       53450 :             Word32 num = L_add( L_shr( L_add( sum_nrg_L_32, sum_nrg_R_32 ), 1 ), L_shr( dot_prod_abs, sub( sub( 31, exp_dot_prod_abs ), q_sum_nrg_L ) ) ); /* q_sum_nrg_L */
     299       53450 :             Word16 E_num = sub( 31, q_sum_nrg_L );
     300       53450 :             Word32 num_sqrt = Sqrt32( num, &E_num );
     301       53450 :             Word16 exp_wR = exp_sum_abs;
     302       53450 :             move16();
     303             : 
     304       53450 :             if ( LT_16( exp_sum_abs, E_num ) )
     305             :             {
     306           0 :                 exp_wR = E_num;
     307           0 :                 move16();
     308             :             }
     309             :             Word16 wR_temp;
     310       53450 :             test();
     311       53450 :             test();
     312       53450 :             IF( num_sqrt == 0 && sum_abs == 0 )
     313             :             {
     314           0 :                 wR_temp = 6364; // 0.776887059 in Q13
     315           0 :                 move16();
     316             :             }
     317       53450 :             ELSE IF( num_sqrt == 0 && sum_abs != 0 )
     318             :             {
     319           0 :                 wR_temp = 5793; // 0.707106769 in Q13
     320           0 :                 move16();
     321             :             }
     322             :             ELSE
     323             :             {
     324       53450 :                 wR_temp = shr( divide3232( L_shr( num_sqrt, sub( exp_wR, E_num ) ), L_shr( sum_abs, sub( exp_wR, exp_sum_abs ) ) ), 2 ); /* Q13 */
     325             :             }
     326             : 
     327       53450 :             Word32 sum_nrg_Mid_sqrt = Sqrt32( sum_nrg_Mid, &exp_sum_nrg_Mid );
     328             : 
     329       53450 :             Word16 exp_wL = exp_sum_abs;
     330       53450 :             move16();
     331       53450 :             if ( LT_16( exp_sum_abs, exp_sum_nrg_Mid ) )
     332             :             {
     333           0 :                 exp_wL = exp_sum_nrg_Mid;
     334           0 :                 move16();
     335             :             }
     336             :             Word16 wL_temp;
     337       53450 :             test();
     338       53450 :             test();
     339       53450 :             IF( sum_nrg_Mid_sqrt == 0 && sum_abs == 0 )
     340             :             {
     341           0 :                 wL_temp = 6364; /* Q13 */
     342           0 :                 move16();
     343             :             }
     344       53450 :             ELSE IF( sum_nrg_Mid_sqrt == 0 && sum_abs != 0 )
     345             :             {
     346           0 :                 wL_temp = 5793; /* Q13 */
     347           0 :                 move16();
     348             :             }
     349             :             ELSE
     350             :             {
     351       53450 :                 wL_temp = shr( divide3232( L_shr( sum_nrg_Mid_sqrt, sub( exp_wL, exp_sum_nrg_Mid ) ), L_shr( sum_abs, sub( exp_wL, exp_sum_abs ) ) ), 1 );
     352             :             }
     353             : 
     354       53450 :             wR = wR_temp; /* Q13 */
     355       53450 :             move16();
     356       53450 :             wL = add( wR, mult( 23170 /*sqrt(2.0f in Q14)*/, sub( 16384 /* 1.0f in Q14 */, wL_temp ) ) ); /* Q13 */
     357             : 
     358      267250 :             FOR( i = hStereoDft->band_limits[b]; i < hStereoDft->band_limits[b + 1]; i++ )
     359             :             {
     360             :                 /*DMX Mapping*/
     361      213800 :                 pDFT_DMX[2 * i] = L_shl( Mpy_32_32( L_add( Mpy_32_16_1( DFT_L[2 * i], wL ), Mpy_32_16_1( DFT_R[2 * i], wR ) ), INV_SQRT_2_Q31 ), Q2 ); /* Q(hStereoDft->q_dft) */
     362      213800 :                 move32();
     363      213800 :                 pDFT_DMX[2 * i + 1] = L_shl( Mpy_32_32( L_add( Mpy_32_16_1( DFT_L[2 * i + 1], wL ), Mpy_32_16_1( DFT_R[2 * i + 1], wR ) ), INV_SQRT_2_Q31 ), Q2 ); /* Q(hStereoDft->q_dft) */
     364      213800 :                 move32();
     365             :             }
     366             :         }
     367       10690 :         Copy32( pDFT_DMX, DFT[0] + i_mult( k, STEREO_DFT32MS_N_MAX ), hStereoDft->NFFT ); /* hStereoDft->q_dft */
     368             : 
     369             :         /* Update DFT_past_DMX, needed for stereo filling used by stereo residual PLC */
     370       10690 :         hStereoDft->past_DMX_pos = ( hStereoDft->past_DMX_pos + 1 ) % STEREO_DFT_PAST_MAX; /* Q0 */
     371       10690 :         move16();
     372       10690 :         Copy32( pDFT_DMX, hStereoDft->DFT_past_DMX_fx[hStereoDft->past_DMX_pos], s_min( hStereoDft->NFFT, STEREO_DFT32MS_N_32k ) ); /* hStereoDft->q_dft */
     373       10690 :         hStereoDft->q_DFT_past_DMX_fx[hStereoDft->past_DMX_pos] = hStereoDft->q_dft;
     374       10690 :         move16();
     375       10690 :         test();
     376       10690 :         IF( st0->bfi && !prev_bfi )
     377             :         {
     378             :             Word16 idx_k0, idx_k1;
     379             :             Word16 q_shift0;
     380             :             Word16 q_shift1;
     381         272 :             idx_k0 = ( add( hStereoDft->past_DMX_pos, 1 ) ) % STEREO_DFT_PAST_MAX;
     382         272 :             move16();
     383         272 :             idx_k1 = ( add( idx_k0, 1 ) ) % STEREO_DFT_PAST_MAX;
     384         272 :             move16();
     385         272 :             q_shift0 = sub( hStereoDft->q_dft, hStereoDft->q_DFT_past_DMX_fx[idx_k0] );
     386         272 :             q_shift1 = sub( hStereoDft->q_dft, hStereoDft->q_DFT_past_DMX_fx[idx_k1] );
     387             : 
     388             :             /*dmx energy memory*/
     389         272 :             hStereoDft->past_dmx_nrg_fx = stereo_dft_dmx_swb_nrg_fx( hStereoDft->DFT_past_DMX_fx[idx_k0], hStereoDft->DFT_past_DMX_fx[idx_k1], s_min( hStereoDft->NFFT, STEREO_DFT32MS_N_32k ), q_shift0, q_shift1 ); /* 2 * q_dft */
     390         272 :             move32();
     391             :         }
     392             :     }
     393             : 
     394        5345 :     return;
     395             : }
     396             : 
     397             : 
     398             : /*-------------------------------------------------------------------*
     399             :  * add_HB_to_mono_dmx()
     400             :  *
     401             :  * add ACELP HB for DFT Stereo mono output with residual coding
     402             :  *-------------------------------------------------------------------*/
     403             : 
     404       17465 : void add_HB_to_mono_dmx_fx(
     405             :     CPE_DEC_HANDLE hCPE,         /* i/o: CPE decoder structure         */
     406             :     Word32 output[L_FRAME48k],   /* i/o: output synthesis            Qx*/
     407             :     Word32 outputHB[L_FRAME48k], /* i  : HB synthesis               Q11*/
     408             :     const Word16 last_core,      /* i  : last core, primary channel  Q0*/
     409             :     const Word16 output_frame    /* i  : frame length                Q0*/
     410             : )
     411             : {
     412             :     Word16 i, j, decoderDelay, icbweOLASize, dftOvlLen, memOffset;
     413             :     Word32 temp_fx[L_FRAME48k + NS2SA( 48000, IVAS_DEC_DELAY_NS - DELAY_BWE_TOTAL_NS )];
     414             : 
     415       17465 :     Word32 winSlope_fx = 0;
     416       17465 :     move32();
     417             :     Word32 alpha_fx;
     418             :     const Word16 *win_dft_fx;
     419             :     Word32 output_Fs;
     420             :     Word32 *memOutHB_fx, *memTransitionHB_fx;
     421             : 
     422       17465 :     output_Fs = hCPE->hCoreCoder[0]->output_Fs; /* Q0 */
     423       17465 :     move32();
     424       17465 :     memOutHB_fx = hCPE->hStereoDftDmx->memOutHB_fx;               /* Q11 */
     425       17465 :     memTransitionHB_fx = hCPE->hStereoDftDmx->memTransitionHB_fx; /* Q11 */
     426             : 
     427       17465 :     memOffset = NS2SA_FX2( output_Fs, IVAS_DEC_DELAY_NS - DELAY_BWE_TOTAL_NS );
     428       17465 :     move16();
     429             : 
     430       17465 :     test();
     431       17465 :     IF( hCPE->hCoreCoder[0]->core == ACELP_CORE && hCPE->hCoreCoder[0]->extl_brate > 0 )
     432             :     {
     433             :         /* Resampled LB and HB offset */
     434       10963 :         Copy32( outputHB, temp_fx + memOffset, sub( output_frame, memOffset ) );
     435             : 
     436       10963 :         decoderDelay = NS2SA_FX2( output_Fs, IVAS_DEC_DELAY_NS );
     437       10963 :         move16();
     438             : 
     439       10963 :         IF( last_core != ACELP_CORE )
     440             :         {
     441             :             /* hb_synth of mid band is faded out in the 1.25 ms prior to DFT analysis and the icbwe is faded in time domain */
     442         711 :             icbweOLASize = NS2SA_FX2( output_Fs, STEREO_DFT_DELAY_DEC_BWE_NS );
     443         711 :             move16();
     444             : 
     445       95403 :             FOR( i = 0; i < decoderDelay; i++ )
     446             :             {
     447       94692 :                 temp_fx[i] = 0;
     448       94692 :                 move32();
     449             :             }
     450             : 
     451         711 :             assert( icbweOLASize > 0 );
     452         711 :             SWITCH( output_Fs )
     453             :             {
     454         469 :                 case 48000:
     455         469 :                     winSlope_fx = 17895698; // Q30
     456         469 :                     move32();
     457         469 :                     BREAK;
     458         172 :                 case 32000:
     459         172 :                     winSlope_fx = 26843546;
     460         172 :                     move32();
     461         172 :                     BREAK;
     462          70 :                 case 16000:
     463          70 :                     winSlope_fx = 53687092;
     464          70 :                     move32();
     465          70 :                     BREAK;
     466             :             }
     467         711 :             alpha_fx = winSlope_fx; // Q30
     468         711 :             move32();
     469       37131 :             FOR( ; i < decoderDelay + icbweOLASize; i++ )
     470             :             {
     471       36420 :                 temp_fx[i] = L_shl( Mpy_32_32( temp_fx[i], alpha_fx ), 1 ); // Q30
     472       36420 :                 move32();
     473       36420 :                 alpha_fx = L_add_sat( alpha_fx, winSlope_fx ); /* Q30 */
     474             :             }
     475             :         }
     476             :         ELSE
     477             :         {
     478       10252 :             Copy32( memOutHB_fx, temp_fx, memOffset ); /* Q11 */
     479             :         }
     480             : 
     481       10963 :         v_add_32( temp_fx, output, output, output_frame );
     482             : 
     483       10963 :         Copy32( outputHB + sub( output_frame, memOffset ), memOutHB_fx, memOffset ); /* Q11 */
     484             : 
     485       10963 :         win_dft_fx = hCPE->hStereoDft->win32ms_fx; /* Q15 */
     486       10963 :         dftOvlLen = hCPE->hStereoDft->dft32ms_ovl; /* Q0 */
     487       10963 :         move16();
     488             : 
     489             :         /* Preparing buffers in anticipation of an ACELP to TCX switch */
     490       10963 :         j = 0;
     491       10963 :         move16();
     492      410443 :         FOR( i = 0; i < memOffset; i++ )
     493             :         {
     494      399480 :             memTransitionHB_fx[i] = Mpy_32_16_1( memOutHB_fx[i], win_dft_fx[STEREO_DFT32MS_STEP * ( dftOvlLen - 1 - j )] ); /* Q11 */
     495      399480 :             move32();
     496      399480 :             j++;
     497             :         }
     498             : 
     499      943083 :         FOR( i = 0; j < dftOvlLen; i++ )
     500             :         {
     501      932120 :             memTransitionHB_fx[memOffset + i] = Mpy_32_16_1( outputHB[output_frame - i - 1], win_dft_fx[STEREO_DFT32MS_STEP * ( dftOvlLen - 1 - j )] ); /* Q11 */
     502      932120 :             move32();
     503      932120 :             j++;
     504             :         }
     505             :     }
     506             :     ELSE
     507             :     {
     508        6502 :         IF( last_core == ACELP_CORE )
     509             :         {
     510        2458 :             test();
     511        2458 :             test();
     512             :             /* This is generated in the ACELP frame and windowed. This process is akin to GenTransition for IC-BWE */
     513        2458 :             IF( EQ_16( hCPE->element_mode, IVAS_CPE_DFT ) && EQ_16( hCPE->nchan_out, 1 ) && hCPE->hStereoDft->hConfig->res_cod_mode == STEREO_DFT_RES_COD_OFF )
     514             :             {
     515        1014 :                 v_add_32( output, outputHB, output, NS2SA_FX2( output_Fs, STEREO_DFT32MS_OVL_NS ) );
     516             :             }
     517             :             ELSE
     518             :             {
     519        1444 :                 v_add_32( output, memTransitionHB_fx, output, NS2SA_FX2( output_Fs, STEREO_DFT32MS_OVL_NS ) );
     520             :             }
     521             : 
     522        2458 :             set32_fx( memOutHB_fx, 0, memOffset );
     523        2458 :             set32_fx( memTransitionHB_fx, 0, NS2SA_FX2( output_Fs, STEREO_DFT32MS_OVL_NS ) );
     524             :         }
     525             :     }
     526             : 
     527       17465 :     return;
     528             : }

Generated by: LCOV version 1.14