LCOV - code coverage report
Current view: top level - lib_enc - ivas_stereo_cng_enc_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main enc/dec/rend @ 3b2f07138c61dcf997bbf4165d0882f794b2995f Lines: 311 327 95.1 %
Date: 2025-05-03 01:55:50 Functions: 5 5 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 <stdint.h>
      34             : #include "options.h"
      35             : #include <math.h>
      36             : #include "cnst.h"
      37             : #include "rom_enc.h"
      38             : #include "rom_com.h"
      39             : #include "prot_fx.h"
      40             : #include "ivas_cnst.h"
      41             : #include "ivas_rom_com.h"
      42             : #include "wmc_auto.h"
      43             : #include "ivas_prot_fx.h"
      44             : 
      45             : 
      46             : /*-------------------------------------------------------------------
      47             :  * Local constants
      48             :  *-------------------------------------------------------------------*/
      49             : 
      50             : #define COH_FADE_MAX     4
      51             : #define COH_FADE_UPDATES 2
      52             : 
      53             : 
      54             : /*---------------------------------------------------------------
      55             :  * stereo_dft_enc_sid_calc_coh()
      56             :  *
      57             :  * Encodes the coherence in SID frames
      58             :  * ---------------------------------------------------------------*/
      59        1449 : void stereo_dft_enc_sid_calc_coh_fx(
      60             :     STEREO_DFT_ENC_DATA_HANDLE hStereoDft,                /* i/o: DFT stereo handle           */
      61             :     Word32 prev_cohBand[2 * ( STEREO_DFT_BAND_MAX / 2 )], /* i/o: Previous coherence  Q31 */
      62             :     Word16 *td_active,                                    /* i/o: TD stereo mode indicator    */
      63             :     Word16 *first_SID,                                    /* i/o: First SID indicator         */
      64             :     Word32 *cohBand                                       /* i/o: Coherence per band Q31         */
      65             : )
      66             : {
      67             :     Word16 b, k;
      68             :     Word32 coh_weight;
      69             :     Word16 coh_weight_e;
      70             :     Word32 coh_weight_sum;
      71             :     Word16 coh_weight_sum_e;
      72             :     Word32 xspec_scale;
      73             :     Word32 L_tmp1, L_tmp2, L_tmp3;
      74             :     Word16 L_tmp1_e, L_tmp2_e, L_tmp3_e;
      75             :     Word64 W_tmp;
      76             :     Word16 W_tmp_q;
      77             :     // Word16 prev_cohBand_e[2 * (STEREO_DFT_BAND_MAX / 2)];
      78             :     Word16 cohBand_e[STEREO_DFT_BAND_MAX / 2];
      79             :     /* Cluster the coherence into bands using a weighted average. The coherence is weighted with the energy spectrum of the
      80             :        mixdown signal.  */
      81        9827 :     FOR( b = 0; b < hStereoDft->nbands; b++ )
      82             :     {
      83        8378 :         cohBand[b] = 0;
      84        8378 :         move32();
      85        8378 :         cohBand_e[b] = 0;
      86        8378 :         move16();
      87        8378 :         coh_weight_sum = 0;
      88        8378 :         move32();
      89        8378 :         coh_weight_sum_e = 0;
      90        8378 :         move16();
      91             : 
      92        8378 :         test();
      93        8378 :         IF( hStereoDft->coh_fade_counter == 0 && !*first_SID )
      94             :         {
      95      223902 :             FOR( k = hStereoDft->band_limits[b]; k < hStereoDft->band_limits[b + 1]; k++ )
      96             :             {
      97             :                 // xspec_scale = sqrtf( ( prev_cohBand[b] * ( hStereoDft->Spd_L_smooth[k] * hStereoDft->Spd_R_smooth[k] ) ) / ( hStereoDft->xspec_smooth[2 * k] * hStereoDft->xspec_smooth[2 * k] + hStereoDft->xspec_smooth[2 * k + 1] * hStereoDft->xspec_smooth[2 * k + 1] + EPSILON ) );
      98      221704 :                 W_tmp = W_mult_32_32( hStereoDft->Spd_L_smooth_fx[k], hStereoDft->Spd_R_smooth_fx[k] );
      99      221704 :                 W_tmp_q = W_norm( W_tmp );
     100      221704 :                 L_tmp1 = W_extract_h( W_shl( W_tmp, W_tmp_q ) );
     101      221704 :                 L_tmp1_e = sub( add( hStereoDft->Spd_L_smooth_fx_e, hStereoDft->Spd_R_smooth_fx_e ), W_tmp_q );
     102      221704 :                 L_tmp2 = BASOP_Util_Add_Mant32Exp( Mpy_32_32( hStereoDft->xspec_smooth_fx[2 * k], hStereoDft->xspec_smooth_fx[2 * k] ), shl( hStereoDft->xspec_smooth_fx_e[2 * k], 1 ), Mpy_32_32( hStereoDft->xspec_smooth_fx[2 * k + 1], hStereoDft->xspec_smooth_fx[2 * k + 1] ), shl( hStereoDft->xspec_smooth_fx_e[2 * k + 1], 1 ), &L_tmp2_e );
     103      221704 :                 L_tmp2 = BASOP_Util_Add_Mant32Exp( L_tmp2, L_tmp2_e, EPSILON_FX_M, EPSILON_FX_E, &L_tmp2_e );
     104      221704 :                 L_tmp3 = BASOP_Util_Divide3232_Scale_newton( L_tmp1, L_tmp2, &L_tmp3_e );
     105      221704 :                 L_tmp3_e = add( L_tmp3_e, sub( L_tmp1_e, L_tmp2_e ) );
     106      221704 :                 L_tmp3 = Mpy_32_32( prev_cohBand[b], L_tmp3 );
     107      221704 :                 xspec_scale = Sqrt32( L_tmp3, &L_tmp3_e );
     108             :                 // xspec_scale = L_shl(xspec_scale, L_tmp3_e);//Q31
     109             : 
     110      221704 :                 hStereoDft->xspec_smooth_fx[2 * k] = Mpy_32_32( hStereoDft->xspec_smooth_fx[2 * k], xspec_scale ); // Q(31-(xspec_smooth_fx_e+tmp3_e))
     111      221704 :                 move32();
     112      221704 :                 hStereoDft->xspec_smooth_fx_e[2 * k] = add( hStereoDft->xspec_smooth_fx_e[2 * k], L_tmp3_e );
     113      221704 :                 move16();
     114      221704 :                 hStereoDft->xspec_smooth_fx[2 * k + 1] = Mpy_32_32( hStereoDft->xspec_smooth_fx[2 * k + 1], xspec_scale ); // Q(31-(xspec_smooth_fx_e+tmp3_e))
     115      221704 :                 move32();
     116      221704 :                 hStereoDft->xspec_smooth_fx_e[2 * k + 1] = add( hStereoDft->xspec_smooth_fx_e[2 * k + 1], L_tmp3_e );
     117      221704 :                 move16();
     118             :             }
     119             : 
     120        2198 :             cohBand[b] = prev_cohBand[b];
     121        2198 :             move32();
     122             :         }
     123             :         ELSE
     124             :         {
     125      609267 :             FOR( k = hStereoDft->band_limits[b]; k < hStereoDft->band_limits[b + 1]; k++ )
     126             :             {
     127             :                 // coh_weight = hStereoDft->DFT[0][2 * k] * hStereoDft->DFT[0][2 * k] + hStereoDft->DFT[0][2 * k + 1] * hStereoDft->DFT[0][2 * k + 1];
     128      603087 :                 W_tmp = W_add( W_mult_32_32( hStereoDft->DFT_fx[0][2 * k], hStereoDft->DFT_fx[0][2 * k] ), W_mult_32_32( hStereoDft->DFT_fx[0][2 * k + 1], hStereoDft->DFT_fx[0][2 * k + 1] ) );
     129      603087 :                 W_tmp_q = W_norm( W_tmp );
     130      603087 :                 coh_weight = W_extract_h( W_shl( W_tmp, W_tmp_q ) );
     131      603087 :                 coh_weight_e = sub( shl( hStereoDft->DFT_fx_e[0], 1 ), W_tmp_q ); // 31 - dft_e*2 + W_tmp_q
     132             : 
     133             :                 // cohBand[b] += coh_weight * ( hStereoDft->xspec_smooth[2 * k] * hStereoDft->xspec_smooth[2 * k] + hStereoDft->xspec_smooth[2 * k + 1] * hStereoDft->xspec_smooth[2 * k + 1] ) / ( hStereoDft->Spd_L_smooth[k] * hStereoDft->Spd_R_smooth[k] + EPSILON );
     134      603087 :                 L_tmp1 = BASOP_Util_Add_Mant32Exp( Mpy_32_32( hStereoDft->xspec_smooth_fx[2 * k], hStereoDft->xspec_smooth_fx[2 * k] ), shl( hStereoDft->xspec_smooth_fx_e[2 * k], 1 ), Mpy_32_32( hStereoDft->xspec_smooth_fx[2 * k + 1], hStereoDft->xspec_smooth_fx[2 * k + 1] ), shl( hStereoDft->xspec_smooth_fx_e[2 * k + 1], 1 ), &L_tmp1_e );
     135      603087 :                 W_tmp = W_mult_32_32( hStereoDft->Spd_L_smooth_fx[k], hStereoDft->Spd_R_smooth_fx[k] );
     136      603087 :                 W_tmp_q = W_norm( W_tmp );
     137      603087 :                 L_tmp2 = W_extract_h( W_shl( W_tmp, W_tmp_q ) );
     138      603087 :                 L_tmp2_e = sub( add( hStereoDft->Spd_L_smooth_fx_e, hStereoDft->Spd_R_smooth_fx_e ), W_tmp_q );
     139      603087 :                 L_tmp2 = BASOP_Util_Add_Mant32Exp( L_tmp2, L_tmp2_e, EPSILON_FX_M, EPSILON_FX_E, &L_tmp2_e );
     140      603087 :                 L_tmp3 = BASOP_Util_Divide3232_Scale_newton( L_tmp1, L_tmp2, &L_tmp3_e );
     141      603087 :                 L_tmp3_e = add( L_tmp3_e, sub( L_tmp1_e, L_tmp2_e ) );
     142      603087 :                 L_tmp3 = Mpy_32_32( coh_weight, L_tmp3 );
     143      603087 :                 L_tmp3_e = add( coh_weight_e, L_tmp3_e );
     144      603087 :                 cohBand[b] = BASOP_Util_Add_Mant32Exp( cohBand[b], cohBand_e[b], L_tmp3, L_tmp3_e, &cohBand_e[b] );
     145      603087 :                 move32();
     146             : 
     147             :                 // coh_weight_sum += coh_weight;
     148      603087 :                 coh_weight_sum = BASOP_Util_Add_Mant32Exp( coh_weight_sum, coh_weight_sum_e, coh_weight, coh_weight_e, &coh_weight_sum_e );
     149             :             }
     150        6180 :             IF( coh_weight_sum > 0 )
     151             :             {
     152             :                 // cohBand[b] = cohBand[b] / coh_weight_sum;
     153        6153 :                 cohBand[b] = BASOP_Util_Divide3232_Scale_newton( cohBand[b], coh_weight_sum, &L_tmp1_e );
     154        6153 :                 move32();
     155        6153 :                 cohBand_e[b] = add( L_tmp1_e, sub( cohBand_e[b], coh_weight_sum_e ) );
     156        6153 :                 move16();
     157        6153 :                 cohBand[b] = L_shl_sat( cohBand[b], cohBand_e[b] ); // Q31: value does not exceed 1.0
     158        6153 :                 move32();
     159             :             }
     160             :         }
     161             :     }
     162             : 
     163        1449 :     IF( *first_SID )
     164             :     {
     165          27 :         Copy32( cohBand, prev_cohBand, hStereoDft->nbands );
     166          27 :         Copy32( prev_cohBand, &( prev_cohBand[STEREO_DFT_BAND_MAX / 2] ), hStereoDft->nbands );
     167          27 :         *first_SID = 0;
     168          27 :         move32();
     169             :     }
     170             : 
     171        1449 :     test();
     172        1449 :     test();
     173        1449 :     IF( LT_16( hStereoDft->coh_fade_counter, COH_FADE_MAX ) && ( *td_active || LT_16( hStereoDft->currentNumUpdates, COH_FADE_UPDATES ) ) )
     174             :     {
     175         224 :         FOR( b = 0; b < hStereoDft->nbands; b++ )
     176             :         {
     177             :             // cohBand[b] = ( cohBand[b] * hStereoDft->coh_fade_counter + prev_cohBand[b] * ( COH_FADE_MAX - hStereoDft->coh_fade_counter ) ) / COH_FADE_MAX;
     178         191 :             SWITCH( hStereoDft->coh_fade_counter )
     179             :             {
     180         191 :                 case 0:
     181         191 :                     cohBand[b] = prev_cohBand[b];
     182         191 :                     move32();
     183         191 :                     BREAK;
     184           0 :                 case 1:
     185           0 :                     cohBand[b] = L_add( L_shr( cohBand[b], 2 ), Mpy_32_32( prev_cohBand[b], 1610612736 /*3/4*/ ) );
     186           0 :                     move32();
     187           0 :                     BREAK;
     188           0 :                 case 2:
     189           0 :                     cohBand[b] = L_add( L_shr( cohBand[b], 1 ), L_shr( prev_cohBand[b], 1 ) );
     190           0 :                     move32();
     191           0 :                     BREAK;
     192           0 :                 case 3:
     193           0 :                     cohBand[b] = L_add( Mpy_32_32( cohBand[b], 1610612736 /*3/4*/ ), L_shr( prev_cohBand[b], 2 ) );
     194           0 :                     move32();
     195           0 :                     BREAK;
     196           0 :                 default:
     197             :                     assert( "unexpected hStereoDft->coh_fade_counter value" );
     198           0 :                     BREAK;
     199             :             }
     200             :         }
     201          33 :         hStereoDft->coh_fade_counter = add( hStereoDft->coh_fade_counter, 1 );
     202          33 :         IF( hStereoDft->coh_fade_counter > 0 )
     203             :         {
     204          33 :             Copy32( &prev_cohBand[STEREO_DFT_BAND_MAX / 2], prev_cohBand, hStereoDft->nbands );
     205             :         }
     206          33 :         Copy32( cohBand, &prev_cohBand[STEREO_DFT_BAND_MAX / 2], hStereoDft->nbands );
     207             :     }
     208             :     ELSE
     209             :     {
     210        1416 :         IF( hStereoDft->coh_fade_counter > 0 )
     211             :         {
     212        1046 :             Copy32( &prev_cohBand[STEREO_DFT_BAND_MAX / 2], prev_cohBand, hStereoDft->nbands );
     213             :         }
     214        1416 :         Copy32( cohBand, &prev_cohBand[STEREO_DFT_BAND_MAX / 2], hStereoDft->nbands );
     215        1416 :         hStereoDft->coh_fade_counter = COH_FADE_MAX;
     216        1416 :         move16();
     217        1416 :         *td_active = 0;
     218        1416 :         move16();
     219             :     }
     220             : 
     221        1449 :     return;
     222             : }
     223             : 
     224             : /*---------------------------------------------------------------
     225             :  * stereo_dft_enc_sid_coh()
     226             :  *
     227             :  * Encodes the coherence in SID frames
     228             :  * ---------------------------------------------------------------*/
     229             : 
     230        1449 : void stereo_dft_enc_sid_coh_fx(
     231             :     BSTR_ENC_HANDLE hBstr, /* i/o: bitstream handle             */
     232             :     Word32 *mem_cohBand,   /* i/o: Coherence memory        Q31  */
     233             :     const Word16 nbands,   /* i  : number of DFT stereo bands   */
     234             :     Word16 *nb_bits,       /* i/o: number of bits written       */
     235             :     Word32 *cohBand        /* i/o: Coherence per band      Q31  */
     236             : )
     237             : {
     238             :     Word16 b, k;
     239             :     Word16 zeropad;
     240             :     Word16 nr_of_sid_stereo_bits;
     241             :     Word16 coh_pred_index;
     242             :     Word64 min_pred_err;
     243             :     Word16 pred_err; // Q13
     244             :     Word16 res_index;
     245             :     Word16 i;
     246             :     Word32 tmp;
     247             :     const Word16 *pptr;
     248             :     Word16 pred;                              // Q13
     249             :     Word16 cohBandq[STEREO_DFT_BAND_MAX / 2]; /* Reconstructed coherence values for intra-frame prediction Q15 */
     250             :     const Word16 *alphaptr;
     251             :     Word16 nbbits_test;
     252             :     Word16 prev_nbbits_test;
     253             :     Word16 alpha_step;
     254             :     Word16 alpha_level;
     255             :     Word16 n;
     256             : 
     257        1449 :     nr_of_sid_stereo_bits = ( IVAS_SID_5k2 - SID_2k40 ) / FRAMES_PER_SEC - SID_FORMAT_NBITS;
     258        1449 :     move16();
     259        1449 :     zeropad = 0;
     260        1449 :     move16();
     261             : 
     262             :     /* Encode coherence vector. Find best fixed predictor by minimizing prediction error on input vector.
     263             :        The prediction is formed by a linear combination of the previous values
     264             :        in the vector. Hence, prediction is only done for coefficient 1 and up.
     265             :        If not enough bits for at least one bit for encoding prediction
     266             :        residual then skip the coding and write zeroes to the bitstream if needed.
     267             :        In this case the decoder will set alpha to 0, i.e. reuse previous coherence */
     268             : 
     269        1449 :     IF( sub( sub( nr_of_sid_stereo_bits, *nb_bits ), STEREO_DFT_N_COH_ALPHA_BITS + STEREO_DFT_PRED_NBITS ) > 0 )
     270             :     {
     271        1449 :         min_pred_err = 134217728000000; // 1e6 in Q27
     272        1449 :         move64();
     273        1449 :         coh_pred_index = -1;
     274        1449 :         move16();
     275        1449 :         pptr = dft_cng_coh_pred_fx[0]; // Q13
     276        7245 :         FOR( k = 0; k < STEREO_DFT_N_COH_PRED; k++ )
     277             :         {
     278        5796 :             Word64 pred_err64 = 0;
     279        5796 :             move64();
     280       33512 :             FOR( b = 1; b < nbands; b++ ) /* Set b=1 to skip first coefficient (same error would otherwise be added for all predictors: (cohBand[0] - 0).^2) */
     281             :             {
     282       27716 :                 Word64 pred64 = 0;
     283       27716 :                 move64();
     284      108336 :                 FOR( i = 0; i < b; i++ )
     285             :                 {
     286             :                     // pred += ( *pptr++ ) * cohBand[i];
     287       80620 :                     pred64 = W_mac_32_16( pred64, cohBand[i], *pptr++ ); // Q45 (31+13+1)
     288             :                 }
     289       27716 :                 tmp = L_sub( L_shr( cohBand[b], 18 ), W_extract_h( pred64 ) ); // Q13
     290             :                 // pred_err += tmp * tmp;
     291       27716 :                 pred_err64 = W_mac_32_32( pred_err64, tmp, tmp ); // Q27
     292             :             }
     293             :             // if ( pred_err < min_pred_err ) /* Store best candidate */
     294        5796 :             IF( LT_64( pred_err64, min_pred_err ) ) /* Store best candidate */
     295             :             {
     296        3121 :                 min_pred_err = pred_err64; // Q27
     297        3121 :                 move64();
     298        3121 :                 coh_pred_index = k;
     299        3121 :                 move16();
     300             :             }
     301             :         }
     302             : 
     303        1449 :         push_next_indice( hBstr, coh_pred_index, STEREO_DFT_PRED_NBITS ); /* Write selected predictor to bitstream */
     304        1449 :         ( *nb_bits ) = add( *nb_bits, STEREO_DFT_PRED_NBITS );
     305        1449 :         move16();
     306             : 
     307             :         /* Pick two different alphas (one low and one high) as a function
     308             :            of the number of available bits. */
     309        1449 :         alpha_step = 0;
     310        1449 :         move16();
     311        7245 :         FOR( i = 0; i < STEREO_DFT_N_COH_ALPHA_STEPS - 1; i++ )
     312             :         {
     313        5796 :             IF( GT_16( sub( sub( nr_of_sid_stereo_bits, *nb_bits ), STEREO_DFT_N_COH_ALPHA_BITS ), dft_cng_coh_alpha_start[i] ) )
     314             :             {
     315        5796 :                 alpha_step = add( i, 1 );
     316             :             }
     317             :         }
     318             : 
     319             :         /* Calculate the number of encoded bits.   */
     320        1449 :         alphaptr = dft_cng_alpha_bits_fx[alpha_step];
     321        1449 :         alpha_level = 0;
     322        1449 :         move16();
     323        1449 :         prev_nbbits_test = 100;
     324        1449 :         move16();
     325        4347 :         FOR( i = 0; i < STEREO_DFT_N_COH_ALPHA_LEVELS; i++ )
     326             :         {
     327        2898 :             nbbits_test = 0;
     328        2898 :             move16();
     329        2898 :             pptr = dft_cng_coh_pred_fx[coh_pred_index]; // Q13
     330        2898 :             pred = 3277 /*0.4f*/;
     331        2898 :             move16();
     332       19654 :             FOR( b = 0; b < nbands; b++ )
     333             :             {
     334       57066 :                 FOR( n = 0; n < b; n++ )
     335             :                 {
     336             :                     // pred += ( *pptr++ ) * cohBandq[n];
     337       40310 :                     pred = add( pred, mult_r( cohBandq[n], *pptr++ ) ); // Q13
     338             :                 }
     339             : 
     340             :                 // pred = ( *alphaptr ) * pred + ( 1 - ( *alphaptr ) ) * mem_cohBand[b];
     341       16756 :                 pred = add( mult_r( pred, *alphaptr ), shr_r( mult_r( extract_h( mem_cohBand[b] ), sub( MAX_16, *alphaptr ) ), 2 ) ); // Q13
     342       16756 :                 pred_err = sub( shr_r( extract_h( cohBand[b] ), 2 ), pred );                                                          // Q13
     343       16756 :                 res_index = usquant_fx( pred_err, &pred_err, -3277 /*-0.4f in Q13*/, 410 /*0.1f in Q12*/, 9 );
     344       16756 :                 res_index = dft_cng_coh_i2u[res_index];
     345       16756 :                 nbbits_test = add( nbbits_test, add( res_index, 1 ) );
     346       16756 :                 res_index = dft_cng_coh_u2i[res_index];
     347       16756 :                 pred_err = usdequant_fx( res_index, -3277 /*-0.4f in Q13*/, 410 /*0.1f in Q12*/ ); // Q13
     348       16756 :                 cohBandq[b] = add( pred, pred_err );
     349       16756 :                 move16();
     350       16756 :                 cohBandq[b] = shl_sat( cohBandq[b], 2 ); // Q15
     351       16756 :                 move16();
     352       16756 :                 if ( cohBandq[b] < 0 )
     353             :                 {
     354         249 :                     cohBandq[b] = 0;
     355         249 :                     move16();
     356             :                 }
     357       16756 :                 pred = 0;
     358       16756 :                 move16();
     359             :             }
     360             : 
     361        2898 :             if ( LT_16( nbbits_test, sub( sub( nr_of_sid_stereo_bits, *nb_bits ), STEREO_DFT_N_COH_ALPHA_BITS ) ) )
     362             :             {
     363        2875 :                 alpha_level = i;
     364        2875 :                 move16();
     365             :             }
     366             : 
     367        2898 :             if ( LT_16( nbbits_test, prev_nbbits_test ) )
     368             :             {
     369        1526 :                 alpha_level = i;
     370        1526 :                 move16();
     371             :             }
     372             : 
     373        2898 :             prev_nbbits_test = nbbits_test;
     374        2898 :             move16();
     375        2898 :             alphaptr++;
     376             :         }
     377             : 
     378             :         /* Do the actual encoding using the selected predictor and alpha */
     379        1449 :         push_next_indice( hBstr, alpha_level, STEREO_DFT_N_COH_ALPHA_BITS ); /* Write selected alpha index to bitstream */
     380        1449 :         ( *nb_bits ) += STEREO_DFT_N_COH_ALPHA_BITS;
     381        1449 :         move16();
     382        1449 :         alphaptr = &dft_cng_alpha_bits_fx[alpha_step][alpha_level];
     383        1449 :         pptr = dft_cng_coh_pred_fx[coh_pred_index]; /* Set pointer to selected predictor */
     384        1449 :         pred = 3277 /*0.4f in Q13*/;
     385        1449 :         move16();
     386        9827 :         FOR( b = 0; b < nbands; b++ )
     387             :         {
     388             :             /* Intra-frame prediction using quantized values */
     389       28533 :             FOR( i = 0; i < b; i++ )
     390             :             {
     391             :                 // pred += ( *pptr++ ) * cohBandq[i];
     392       20155 :                 pred = add( pred, mult_r( cohBandq[i], *pptr++ ) ); // Q13
     393             :             }
     394             :             /* Weighted intra/inter-frame prediction */
     395             :             // pred = ( *alphaptr ) * pred + ( 1 - ( *alphaptr ) ) * mem_cohBand[b];
     396        8378 :             pred = add( mult_r( pred, *alphaptr ), shr_r( mult_r( extract_h( mem_cohBand[b] ), sub( MAX_16, *alphaptr ) ), 2 ) ); // Q13
     397        8378 :             pred_err = sub( shr_r( extract_h( cohBand[b] ), 2 ), pred );                                                          // Q13
     398             : 
     399        8378 :             res_index = usquant_fx( pred_err, &pred_err, -3277 /*-0.4f in Q13*/, 410 /*0.1f in Q12*/, 9 ); /* Quantize prediction residual */
     400        8378 :             res_index = dft_cng_coh_i2u[res_index];                                                        /* Convert to unary codeword - res_index+1 now equal to codeword
     401             :                                                                                                             length in bits with the following order:
     402             :                                                                                                             [0.0, 0.1, -0.1, 0.2, -0.2, 0.3, -0.3, 0.4, -0.4] */
     403             :             /* Bit rate truncation */
     404        8378 :             WHILE( res_index + 1 + *nb_bits > nr_of_sid_stereo_bits && res_index > 0 )
     405             :             {
     406           0 :                 test();
     407           0 :                 res_index = s_max( 0, sub( res_index, 2 ) ); /* Reduce step by one, keeping sign. */
     408             :             }
     409             :             /* Write residual index to bitstream */
     410        8378 :             IF( LE_16( add( add( res_index, 1 ), *nb_bits ), nr_of_sid_stereo_bits ) ) /* If the bit limit is reached, res_index = 0 is assumed for remaining indices */
     411             :             {
     412        8378 :                 *nb_bits = add( *nb_bits, write_GR0_fx( hBstr, IND_STEREO_DFT_SID_COH, &res_index, 1 ) );
     413        8378 :                 move16();
     414             :             }
     415             : 
     416             :             /* Reconstruct */
     417        8378 :             res_index = dft_cng_coh_u2i[res_index];
     418        8378 :             move16();
     419        8378 :             pred_err = usdequant_fx( res_index, -3277 /*-0.4f in Q13*/, 410 /*0.1f in Q12*/ );
     420        8378 :             cohBandq[b] = add( pred, pred_err ); /* Store for intra-frame prediction */
     421        8378 :             move16();
     422        8378 :             cohBandq[b] = shl_sat( cohBandq[b], 2 ); // Q15
     423        8378 :             move16();
     424        8378 :             if ( cohBandq[b] < 0 )
     425             :             {
     426         165 :                 cohBandq[b] = 0;
     427         165 :                 move16();
     428             :             }
     429             : 
     430        8378 :             mem_cohBand[b] = L_deposit_h( cohBandq[b] ); /* Update memory for next frame  Q31*/
     431        8378 :             move32();
     432        8378 :             pred = 0;
     433        8378 :             move16();
     434             :         }
     435             :     }
     436             : 
     437             :     /* Zero pad up to max number of bits to get constant bitrate */
     438       23701 :     FOR( k = *nb_bits; k < nr_of_sid_stereo_bits; k++ )
     439             :     {
     440       22252 :         push_next_indice( hBstr, zeropad, 1 );
     441       22252 :         ( *nb_bits ) = add( *nb_bits, 1 );
     442       22252 :         move16();
     443             :     }
     444             : 
     445             : 
     446        1449 :     return;
     447             : }
     448             : 
     449             : /*-------------------------------------------------------------------------
     450             :  * stereo_dft_cng_side_gain()
     451             :  *
     452             :  * Calculate CNG side gain
     453             :  *-------------------------------------------------------------------------*/
     454             : 
     455       10307 : void stereo_dft_cng_side_gain_fx(
     456             :     STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i/o: DFT stereo handle            */
     457             :     STEREO_CNG_ENC_HANDLE hStereoCng,      /* i/o: Stereo CNG data structure    */
     458             :     const Word32 core_brate,               /* i  : core bitrate                 */
     459             :     const Word32 last_core_brate,          /* i  : last core bitrate            */
     460             :     const Word16 bwidth                    /* i  : audio band-width             */
     461             : )
     462             : {
     463             :     Word16 b;
     464             :     Word16 sgSum;
     465             :     Word16 band_limits_full[STEREO_DFT_BAND_MAX + 1];
     466             :     Word16 prev_weight; // Q15
     467             :     Word16 NFFT_inner;
     468             :     Word16 nbands_full;
     469             :     Word32 tmp;
     470             :     Word16 tmp_16;
     471             :     Word16 tmp_e;
     472             :     Word64 W_tmp;
     473             :     Word16 W_tmp_q;
     474             : 
     475             :     // NFFT_inner = STEREO_DFT_N_MAX_ENC * inner_frame_tbl[bwidth] / L_FRAME48k;
     476       10307 :     NFFT_inner = shl( inner_frame_tbl[bwidth], 1 );
     477       10307 :     nbands_full = hStereoDft->nbands;
     478       10307 :     move16();
     479             : 
     480             :     /* Calculate side gain average. First average in an inactive period */
     481             :     /* uses a weighted sum of the current average and the one from the  */
     482             :     /* previous inactive segment */
     483             : 
     484             :     /* Inactive frame => Update both sets of averages */
     485      105234 :     FOR( b = 0; b < nbands_full; b++ )
     486             :     {
     487             :         // hStereoCng->sg_average[b] += hStereoDft->sidSideGain[b];
     488       94927 :         hStereoCng->sg_average_fx[b] = L_add( hStereoCng->sg_average_fx[b], L_shr_r( hStereoDft->sidSideGain_fx[b], 5 ) );
     489       94927 :         move32();
     490             :     }
     491       10307 :     hStereoCng->sg_average_counter = add( hStereoCng->sg_average_counter, 1 );
     492       10307 :     move32();
     493             : 
     494       10307 :     hStereoCng->cng_counter = add( hStereoCng->cng_counter, 1 );
     495       10307 :     move16();
     496       10307 :     hStereoCng->cng_counter = s_min( hStereoCng->cng_counter, STEREO_DFT_SG_ACT_CNT_MAX );
     497       10307 :     move16();
     498             : 
     499       10307 :     IF( EQ_32( core_brate, SID_2k40 ) )
     500             :     {
     501             :         /* SID frame */
     502        1523 :         test();
     503        1523 :         IF( EQ_32( last_core_brate, FRAME_NO_DATA ) || hStereoCng->first_SID )
     504             :         {
     505             :             /* If first ever SID frame or not the first SID in an inactive segment  */
     506             :             /* Calculate average only based on current sg_average                   */
     507             :             /* Copy current sum to previous                                         */
     508       11709 :             FOR( b = 0; b < hStereoDft->nbands; b++ )
     509             :             {
     510       10562 :                 hStereoCng->prev_sg_average_fx[b] = hStereoCng->sg_average_fx[b];
     511       10562 :                 move32();
     512             :                 // hStereoCng->sg_average[b] = hStereoCng->sg_average[b] / (float) hStereoCng->sg_average_counter;
     513       10562 :                 hStereoCng->sg_average_fx[b] = BASOP_Util_Divide3232_Scale_newton( hStereoCng->sg_average_fx[b], hStereoCng->sg_average_counter, &tmp_e );
     514       10562 :                 move32();
     515       10562 :                 tmp_e = sub( tmp_e, 31 - 5 );
     516       10562 :                 hStereoCng->sg_average_fx[b] = L_shl_r( hStereoCng->sg_average_fx[b], sub( tmp_e, 5 ) ); // Q31
     517       10562 :                 move32();
     518             :             }
     519             : 
     520        1147 :             hStereoCng->prev_sg_average_counter = hStereoCng->sg_average_counter;
     521        1147 :             move16();
     522             :         }
     523             :         ELSE
     524             :         {
     525             :             /* If first SID in a new inactive segment                                       */
     526             :             /* Calculate weighting factor based on the time since the last inactive segment */
     527             :             // prev_weight = 0.8f * (float) ( STEREO_DFT_SG_ACT_CNT_MAX - hStereoCng->sg_active_cnt ) / (float) STEREO_DFT_SG_ACT_CNT_MAX + 0.2f;
     528         376 :             tmp_16 = BASOP_Util_Divide1616_Scale( sub( STEREO_DFT_SG_ACT_CNT_MAX, hStereoCng->sg_active_cnt ), STEREO_DFT_SG_ACT_CNT_MAX, &tmp_e );
     529         376 :             prev_weight = add( shl( mult_r( 26214 /*0.8f*/, tmp_16 ), tmp_e ), 6554 /*0.2f*/ );
     530             : 
     531             :             /* Calculate weighted average between prev and current sg */
     532             :             /* Set prev_sg sum to current. */
     533        3900 :             FOR( b = 0; b < hStereoDft->nbands; b++ )
     534             :             {
     535        3524 :                 tmp = hStereoCng->sg_average_fx[b];
     536        3524 :                 move32();
     537             :                 // hStereoCng->sg_average[b] = ( hStereoCng->sg_average[b] + prev_weight * hStereoCng->prev_sg_average[b] ) / ( (float) hStereoCng->sg_average_counter + prev_weight * (float) hStereoCng->prev_sg_average_counter );
     538        3524 :                 hStereoCng->sg_average_fx[b] = BASOP_Util_Divide3232_Scale_newton( L_add( hStereoCng->sg_average_fx[b], Mpy_32_16_1( hStereoCng->prev_sg_average_fx[b], prev_weight ) ), L_add( L_shl( hStereoCng->sg_average_counter, Q15 ), L_mult0( prev_weight, hStereoCng->prev_sg_average_counter ) ), &tmp_e );
     539        3524 :                 move32();
     540        3524 :                 tmp_e = sub( tmp_e, 16 - 5 );
     541        3524 :                 hStereoCng->sg_average_fx[b] = L_shl_r( hStereoCng->sg_average_fx[b], sub( tmp_e, 5 ) ); // Q26
     542        3524 :                 move32();
     543             : 
     544        3524 :                 hStereoCng->prev_sg_average_fx[b] = tmp;
     545        3524 :                 move32();
     546             :             }
     547         376 :             hStereoCng->prev_sg_average_counter = hStereoCng->sg_average_counter;
     548         376 :             move16();
     549             :         }
     550             : 
     551             :         /* Use coarse band partitioning in inactive frames                              */
     552             :         /* Rescale bands to the coarser partitioning taking the band size into account  */
     553        1523 :         Copy( hStereoDft->band_limits, band_limits_full, STEREO_DFT_BAND_MAX + 1 );
     554        1523 :         hStereoDft->nbands = stereo_dft_band_config_fx( hStereoDft->band_limits, hStereoDft->hConfig->band_res, s_min( STEREO_DFT_N_32k_ENC, NFFT_inner ), ENC );
     555        1523 :         move16();
     556        1523 :         IF( GT_16( nbands_full, add( hStereoDft->nbands, 1 ) ) )
     557             :         {
     558        5939 :             FOR( b = 0; b < hStereoDft->nbands; b++ )
     559             :             {
     560             :                 // hStereoDft->sidSideGain[b] = hStereoCng->sg_average[2 * b] * ( band_limits_full[2 * b + 1] - band_limits_full[2 * b] );
     561        5068 :                 W_tmp = W_shl( W_mult_32_32( hStereoCng->sg_average_fx[2 * b], sub( band_limits_full[2 * b + 1], band_limits_full[2 * b] ) ), 5 ); // Q31
     562        5068 :                 sgSum = sub( band_limits_full[2 * b + 1], band_limits_full[2 * b] );
     563             :                 // if ( ( 2 * b + 1 ) < nbands_full )
     564        5068 :                 IF( LT_16( add( shl( b, 1 ), 1 ), nbands_full ) )
     565             :                 {
     566             :                     // hStereoDft->sidSideGain[b] += hStereoCng->sg_average[2 * b + 1] * ( band_limits_full[2 * b + 2] - band_limits_full[2 * b + 1] );
     567        5055 :                     W_tmp = W_add( W_tmp, W_shl( W_mult_32_32( hStereoCng->sg_average_fx[2 * b + 1], sub( band_limits_full[2 * b + 2], band_limits_full[2 * b + 1] ) ), 5 ) ); // Q31
     568        5055 :                     sgSum = add( sgSum, sub( band_limits_full[2 * b + 2], band_limits_full[2 * b + 1] ) );
     569             :                 }
     570             :                 // hStereoDft->sidSideGain[b] = hStereoDft->sidSideGain[b] / sgSum;
     571        5068 :                 W_tmp_q = W_norm( W_tmp );
     572        5068 :                 hStereoDft->sidSideGain_fx[b] = W_extract_h( W_shl( W_tmp, W_tmp_q ) );
     573        5068 :                 move32();
     574        5068 :                 hStereoDft->sidSideGain_fx[b] = BASOP_Util_Divide3232_Scale_newton( hStereoDft->sidSideGain_fx[b], sgSum, &tmp_e );
     575        5068 :                 move32();
     576        5068 :                 tmp_e = sub( tmp_e, W_tmp_q );
     577        5068 :                 hStereoDft->sidSideGain_fx[b] = L_shl_sat( hStereoDft->sidSideGain_fx[b], tmp_e ); // Q31: saturation is fine since stereo_dft_quantize_res_gains_fx limits value to 1.0
     578        5068 :                 move32();
     579        5068 :                 stereo_dft_quantize_res_gains_fx( &hStereoDft->sidSideGain_fx[b], NULL, NULL, NULL, hStereoDft->side_gain_index_EC + b, NULL );
     580             :             }
     581             :         }
     582             :         ELSE
     583             :         {
     584             :             Word32 sg_average_fx_q31;
     585        4406 :             FOR( b = 0; b < hStereoDft->nbands; b++ )
     586             :             {
     587        3754 :                 sg_average_fx_q31 = L_shl_sat( hStereoCng->sg_average_fx[b], 5 ); // Q31
     588        3754 :                 stereo_dft_quantize_res_gains_fx( &sg_average_fx_q31, NULL, NULL, NULL, hStereoDft->side_gain_index_EC + b, NULL );
     589             :             }
     590             :         }
     591             :         /* Restart SID avg after sending SID */
     592        1523 :         hStereoCng->sg_average_counter = 0;
     593        1523 :         move16();
     594        1523 :         set_zero_fx( hStereoCng->sg_average_fx, STEREO_DFT_BAND_MAX );
     595             :     }
     596             :     ELSE
     597             :     {
     598       89625 :         FOR( b = 0; b < nbands_full; b++ )
     599             :         {
     600             :             // hStereoCng->prev_sg_average[b] += hStereoDft->sidSideGain[b];
     601       80841 :             hStereoCng->prev_sg_average_fx[b] = L_add( hStereoCng->prev_sg_average_fx[b], L_shr_r( hStereoDft->sidSideGain_fx[b], 5 ) ); // Q26
     602       80841 :             move32();
     603             :         }
     604             : 
     605        8784 :         hStereoCng->prev_sg_average_counter = add( hStereoCng->prev_sg_average_counter, 1 );
     606        8784 :         move16();
     607             :     }
     608             : 
     609       10307 :     hStereoCng->sg_active_cnt = 0;
     610       10307 :     move16();
     611       10307 :     hStereoCng->first_SID_after_TD = 0;
     612       10307 :     move16();
     613             : 
     614       10307 :     return;
     615             : }
     616             : 
     617             : /*---------------------------------------------------------------
     618             :  * stereo_enc_cng_init()
     619             :  *
     620             :  * Initializes counters and averages
     621             :  * ---------------------------------------------------------------*/
     622             : 
     623          57 : void stereo_enc_cng_init_fx(
     624             :     STEREO_CNG_ENC_HANDLE hStereoCng /* i/o: stereo CNG encoder structure   */
     625             : )
     626             : {
     627          57 :     hStereoCng->sg_average_counter = 0;
     628          57 :     move16();
     629          57 :     set32_fx( hStereoCng->sg_average_fx, 0, STEREO_DFT_BAND_MAX );
     630          57 :     hStereoCng->prev_sg_average_counter = 0;
     631          57 :     move16();
     632          57 :     set32_fx( hStereoCng->prev_sg_average_fx, 0, STEREO_DFT_BAND_MAX );
     633          57 :     hStereoCng->sg_active_cnt = 0;
     634          57 :     move16();
     635          57 :     hStereoCng->first_SID = 1;
     636          57 :     move16();
     637          57 :     set32_fx( hStereoCng->mem_cohBand_fx, ONE_IN_Q30, STEREO_DFT_BAND_MAX / 2 );
     638          57 :     set32_fx( hStereoCng->prev_cohBand_fx, 0, 2 * ( STEREO_DFT_BAND_MAX / 2 ) );
     639          57 :     hStereoCng->td_active = 0;
     640          57 :     move16();
     641          57 :     hStereoCng->first_SID_after_TD = 1;
     642          57 :     move16();
     643          57 :     hStereoCng->cng_counter = 0;
     644          57 :     move16();
     645             : 
     646          57 :     return;
     647             : }
     648             : 
     649             : 
     650             : /*-------------------------------------------------------------------------
     651             :  * stereo_cng_upd_counters()
     652             :  *
     653             :  * Update Stereo CNG counters
     654             :  *-------------------------------------------------------------------------*/
     655       21661 : void stereo_cng_upd_counters_fx(
     656             :     STEREO_CNG_ENC_HANDLE hStereoCng, /* i/o: Stereo CNG data structure     */
     657             :     const Word32 element_mode,        /* i  : element mode                  */
     658             :     const Word16 nbands,              /* i  : Number of bands in active     */
     659             :     const Word32 sidSideGain[],       /* i  : SID side gains            Q31 */
     660             :     const Word16 burst_ho_count,      /* i  : Hang-over count               */
     661             :     Word16 *coh_fade_counter          /* i  : Coherence fade counter        */
     662             : )
     663             : {
     664             :     Word16 b;
     665             : 
     666             :     /* Update sg avg in hangover frames, reset in active frames */
     667       21661 :     test();
     668       21661 :     IF( burst_ho_count > 0 && EQ_32( element_mode, IVAS_CPE_DFT ) )
     669             :     {
     670       13854 :         FOR( b = 0; b < nbands; b++ )
     671             :         {
     672             :             // hStereoCng->sg_average[b] += sidSideGain[b];
     673       12487 :             hStereoCng->sg_average_fx[b] = L_add( hStereoCng->sg_average_fx[b], L_shr_r( sidSideGain[b], 5 ) ); // Q26
     674       12487 :             move32();
     675             :         }
     676        1367 :         hStereoCng->sg_average_counter = add( hStereoCng->sg_average_counter, 1 );
     677        1367 :         move16();
     678             :     }
     679             :     else
     680             :     {
     681       20294 :         hStereoCng->sg_average_counter = 0;
     682       20294 :         move16();
     683       20294 :         set_zero_fx( hStereoCng->sg_average_fx, STEREO_DFT_BAND_MAX );
     684             :     }
     685             : 
     686             :     /* Increment active counter, stop at max value */
     687       21661 :     hStereoCng->sg_active_cnt = add( hStereoCng->sg_active_cnt, 1 );
     688       21661 :     move16();
     689       21661 :     hStereoCng->sg_active_cnt = s_min( hStereoCng->sg_active_cnt, STEREO_DFT_SG_ACT_CNT_MAX );
     690       21661 :     move16();
     691             : 
     692       21661 :     IF( GT_16( hStereoCng->sg_active_cnt, STEREO_DFT_CNG_ITD_CNT ) )
     693             :     {
     694       19757 :         hStereoCng->cng_counter = 0;
     695       19757 :         move16();
     696             :     }
     697             : 
     698       21661 :     IF( EQ_32( element_mode, IVAS_CPE_DFT ) )
     699             :     {
     700       19992 :         *coh_fade_counter = 0;
     701       19992 :         move16();
     702             :     }
     703       21661 :     return;
     704             : }

Generated by: LCOV version 1.14