LCOV - code coverage report
Current view: top level - lib_dec - ivas_stereo_dft_dec_dmx.c (source / functions) Hit Total Coverage
Test: Coverage on main -- short test vectors @ 6c9ddc4024a9c0e1ecb8f643f114a84a0e26ec6b Lines: 107 107 100.0 %
Date: 2025-05-23 08:37:30 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.h"
      39             : #include "ivas_prot.h"
      40             : #include "ivas_cnst.h"
      41             : #include "ivas_rom_com.h"
      42             : #include "ivas_rom_dec.h"
      43             : #include "rom_com.h"
      44             : #ifdef DEBUGGING
      45             : #include "debug.h"
      46             : #endif
      47             : #include "wmc_auto.h"
      48             : 
      49             : 
      50             : /*-------------------------------------------------------------------------
      51             :  * stereo_dft_dmx_out_reset()
      52             :  *
      53             :  * Reset DFT stereo mono output memories
      54             :  *------------------------------------------------------------------------*/
      55             : 
      56        1824 : void stereo_dft_dmx_out_reset(
      57             :     STEREO_DFT_DMX_DATA_HANDLE hStereoDftDmx /* i/o: DFT stereo DMX decoder          */
      58             : )
      59             : {
      60        1824 :     hStereoDftDmx->targetGain = 1.0f;
      61        1824 :     hStereoDftDmx->prevTargetGain = 1.0f;
      62             : 
      63        1824 :     set_zero( hStereoDftDmx->memOutHB, NS2SA( 48000, STEREO_DFT32MS_OVL_NS ) );
      64        1824 :     set_zero( hStereoDftDmx->memTransitionHB, NS2SA( 48000, STEREO_DFT32MS_OVL_NS ) );
      65             : 
      66        1824 :     return;
      67             : }
      68             : 
      69             : 
      70             : /*-------------------------------------------------------------------------
      71             :  * stereo_dft_unify_dmx()
      72             :  *
      73             :  * create a uniform dmx in case of residual coding by converting from passive
      74             :  * to active dmx in residual coding region
      75             :  *-------------------------------------------------------------------------*/
      76             : 
      77       16026 : void stereo_dft_unify_dmx(
      78             :     STEREO_DFT_DEC_DATA_HANDLE hStereoDft,       /* i/o: decoder stereo handle          */
      79             :     Decoder_State *st0,                          /* i/o: decoder state structure        */
      80             :     float DFT[CPE_CHANNELS][STEREO_DFT_BUF_MAX], /* i/o: DFT buffers                    */
      81             :     float *input_mem,                            /* i/o: mem of buffer DFT analysis     */
      82             :     const int16_t prev_sid_nodata                /* i  : Previous SID/No data indicator */
      83             : )
      84             : {
      85             :     int16_t i, k, b, N_div;
      86             :     float DFT_L[STEREO_DFT32MS_N_MAX];
      87             :     float DFT_R[STEREO_DFT32MS_N_MAX];
      88             :     float *pDFT_DMX;
      89             :     float *pDFT_RES;
      90             :     float g, tmp;
      91             :     float *pSideGain;
      92             :     int16_t k_offset;
      93             : 
      94             :     /* Variables for stereo residual PLC */
      95             :     float DFT_PRED_RES[STEREO_DFT32MS_N_32k];
      96             :     float samp_ratio;
      97             :     int16_t prev_bfi;
      98             :     float dmx_nrg;
      99             :     float *pPredGain;
     100             :     int16_t stop;
     101             :     int16_t output_frame;
     102             :     int16_t plocs[STEREO_DFT_RES_N_PEAKS_MAX];
     103             :     int16_t num_plocs;
     104             :     float plocsi[STEREO_DFT_RES_N_PEAKS_MAX];
     105             : 
     106       16026 :     output_frame = (int16_t) ( st0->output_Fs / FRAMES_PER_SEC );
     107       16026 :     samp_ratio = (float) st0->sr_core / (float) st0->output_Fs;
     108       16026 :     prev_bfi = st0->prev_old_bfi;
     109             : 
     110             :     /* Initialization */
     111       16026 :     k_offset = 1;
     112       16026 :     N_div = STEREO_DFT_NBDIV;
     113             : 
     114       16026 :     dmx_nrg = 0.0f;
     115             :     /* make sure number of bands corresponds to output bwidth in case it is lower than parameter bwidth */
     116       16026 :     if ( output_frame < inner_frame_tbl[st0->bwidth] )
     117             :     {
     118        3693 :         hStereoDft->nbands = stereo_dft_band_config( hStereoDft->band_limits, hStereoDft->band_res[k_offset], hStereoDft->NFFT, DEC );
     119             :     }
     120       16026 :     if ( prev_bfi )
     121             :     {
     122         783 :         dmx_nrg = stereo_dft_dmx_swb_nrg( DFT[0], DFT[0] + STEREO_DFT32MS_N_MAX, min( hStereoDft->NFFT, STEREO_DFT32MS_N_32k ) );
     123             :     }
     124             : 
     125             :     /* Analyze nature of current frame */
     126       14940 :     hStereoDft->trans = ( ( ( st0->clas_dec == ONSET ) || ( st0->clas_dec == SIN_ONSET ) || ( st0->clas_dec == UNVOICED_CLAS ) || ( st0->clas_dec == UNVOICED_TRANSITION ) ) || ( st0->stab_fac <= 0.25f ) ) ||
     127       30966 :                         ( st0->core == TCX_20_CORE && ( ( st0->hTcxCfg->tcx_last_overlap_mode == MIN_OVERLAP ) || ( st0->hTcxCfg->tcx_last_overlap_mode == HALF_OVERLAP ) ) ) || ( st0->core == TCX_10_CORE );
     128             : 
     129             :     /* Smoothing for the current frame */
     130       16026 :     stereo_dft_dec_smooth_parameters( hStereoDft, prev_sid_nodata, st0->hFdCngDec->hFdCngCom->active_frame_counter, st0->element_brate );
     131             : 
     132       48078 :     for ( k = 0; k < N_div; k++ )
     133             :     {
     134       32052 :         pDFT_DMX = DFT[0] + k * STEREO_DFT32MS_N_MAX;
     135       32052 :         pDFT_RES = DFT[1] + k * STEREO_DFT32MS_N_MAX;
     136             : 
     137       32052 :         assert( hStereoDft->hConfig->dmx_active );
     138             :         /*Apply Stereo*/
     139       32052 :         g = 1.f;
     140             : 
     141             :         /* since delay is just 3.125ms, the parameters received are used for the second window */
     142       32052 :         pSideGain = hStereoDft->side_gain + ( k + k_offset ) * STEREO_DFT_BAND_MAX;
     143             : 
     144             : 
     145             :         /* Stereo residual PLC */
     146       32052 :         if ( hStereoDft->res_cod_band_max > 0 )
     147             :         {
     148       32052 :             if ( !st0->bfi )
     149             :             {
     150       30462 :                 if ( k == 1 )
     151             :                 {
     152       15231 :                     mvr2r( pDFT_RES, hStereoDft->res_mem, 2 * hStereoDft->band_limits[hStereoDft->res_cod_band_max] );
     153       15231 :                     hStereoDft->time_offs = 0;
     154             :                 }
     155             :             }
     156             :             else
     157             :             {
     158        1590 :                 hStereoDft->nbands = hStereoDft->res_cod_band_max; /* Limit nbands since residual PLC only needs the low frequency range of the stereo filling */
     159        1590 :                 pPredGain = hStereoDft->res_pred_gain + ( k + k_offset ) * STEREO_DFT_BAND_MAX;
     160        1590 :                 hStereoDft->past_DMX_pos = ( hStereoDft->past_DMX_pos + STEREO_DFT_PAST_MAX - 1 ) % STEREO_DFT_PAST_MAX;
     161        1590 :                 stereo_dft_generate_res_pred( hStereoDft, samp_ratio, pDFT_DMX, DFT_PRED_RES, pPredGain, k, DFT[1] + k * STEREO_DFT32MS_N_MAX, &stop, st0->bfi );
     162        1590 :                 stereo_dft_res_ecu( hStereoDft, pDFT_RES, DFT_PRED_RES, k, output_frame, prev_bfi, dmx_nrg, &num_plocs, plocs, plocsi, input_mem );
     163             :             }
     164             :         }
     165             : 
     166             : 
     167             :         /* Apply active DMX */
     168       32052 :         DFT_L[0] = pDFT_DMX[0];
     169       32052 :         DFT_R[0] = pDFT_DMX[0];
     170             : 
     171             :         /* upmix residual part */
     172      192312 :         for ( b = 0; b < hStereoDft->res_cod_band_max; b++ )
     173             :         {
     174      160260 :             g = pSideGain[b];
     175             : 
     176             : #ifdef DEBUG_MODE_DFT
     177             :             dbgwrite( &g, sizeof( float ), 1, 1, "./res/stereo_dft_dec_g.pcm" );
     178             : #endif
     179             : 
     180      801300 :             for ( i = hStereoDft->band_limits[b]; i < hStereoDft->band_limits[b + 1]; i++ )
     181             :             {
     182      641040 :                 tmp = g * pDFT_DMX[2 * i] + pDFT_RES[2 * i];
     183             : 
     184      641040 :                 DFT_L[2 * i] = pDFT_DMX[2 * i] + tmp;
     185      641040 :                 DFT_R[2 * i] = pDFT_DMX[2 * i] - tmp;
     186             : 
     187      641040 :                 tmp = g * pDFT_DMX[2 * i + 1] + pDFT_RES[2 * i + 1];
     188             : 
     189      641040 :                 DFT_L[2 * i + 1] = pDFT_DMX[2 * i + 1] + tmp;
     190      641040 :                 DFT_R[2 * i + 1] = pDFT_DMX[2 * i + 1] - tmp;
     191             :             }
     192             :         }
     193             : 
     194             :         /* downmix residual part with active downmix */
     195      192312 :         for ( b = 0; b < hStereoDft->res_cod_band_max; b++ )
     196             :         {
     197             :             int16_t j;
     198      160260 :             float sum_nrg_L = EPSILON, sum_nrg_R = EPSILON, dot_prod_real = EPSILON, dot_prod_img = EPSILON;
     199             :             float sum_nrg_Mid, sum_abs, dot_prod_abs;
     200             :             float wR, wL;
     201             : 
     202      801300 :             for ( j = hStereoDft->band_limits[b]; j < hStereoDft->band_limits[b + 1]; j++ )
     203             :             {
     204      641040 :                 sum_nrg_L += DFT_L[2 * j] * DFT_L[2 * j] + DFT_L[2 * j + 1] * DFT_L[2 * j + 1];
     205      641040 :                 sum_nrg_R += DFT_R[2 * j] * DFT_R[2 * j] + DFT_R[2 * j + 1] * DFT_R[2 * j + 1];
     206      641040 :                 dot_prod_real += DFT_L[2 * j] * DFT_R[2 * j] + DFT_L[2 * j + 1] * DFT_R[2 * j + 1];
     207      641040 :                 dot_prod_img += DFT_L[2 * j + 1] * DFT_R[2 * j] - DFT_L[2 * j] * DFT_R[2 * j + 1];
     208             :             }
     209      160260 :             sum_nrg_Mid = max( 0.f, sum_nrg_L + sum_nrg_R + 2.f * dot_prod_real );
     210      160260 :             sum_abs = sqrtf( sum_nrg_L ) + sqrtf( sum_nrg_R ) + EPSILON;
     211      160260 :             dot_prod_abs = sqrtf( dot_prod_real * dot_prod_real + dot_prod_img * dot_prod_img );
     212      160260 :             wR = sqrtf( 0.5f * ( sum_nrg_L + sum_nrg_R ) + dot_prod_abs ) / sum_abs;
     213      160260 :             wL = wR + sqrtf( 2.f ) * ( 1.f - sqrtf( sum_nrg_Mid ) / sum_abs );
     214             : 
     215      801300 :             for ( i = hStereoDft->band_limits[b]; i < hStereoDft->band_limits[b + 1]; i++ )
     216             :             {
     217             :                 /*DMX Mapping*/
     218      641040 :                 pDFT_DMX[2 * i] = ( wL * DFT_L[2 * i] + wR * DFT_R[2 * i] ) * INV_SQRT_2;
     219      641040 :                 pDFT_DMX[2 * i + 1] = ( wL * DFT_L[2 * i + 1] + wR * DFT_R[2 * i + 1] ) * INV_SQRT_2;
     220             :             }
     221             :         }
     222             : 
     223       32052 :         mvr2r( pDFT_DMX, DFT[0] + k * STEREO_DFT32MS_N_MAX, hStereoDft->NFFT );
     224             : 
     225             :         /* Update DFT_past_DMX, needed for stereo filling used by stereo residual PLC */
     226       32052 :         hStereoDft->past_DMX_pos = ( hStereoDft->past_DMX_pos + 1 ) % STEREO_DFT_PAST_MAX;
     227       32052 :         mvr2r( pDFT_DMX, hStereoDft->DFT_past_DMX[hStereoDft->past_DMX_pos], min( hStereoDft->NFFT, STEREO_DFT32MS_N_32k ) );
     228             : 
     229       32052 :         if ( st0->bfi && !prev_bfi )
     230             :         {
     231             :             int16_t idx_k0, idx_k1;
     232        1476 :             idx_k0 = ( hStereoDft->past_DMX_pos + STEREO_DFT_PAST_MAX - 1 ) % STEREO_DFT_PAST_MAX;
     233        1476 :             idx_k1 = ( idx_k0 + 1 ) % STEREO_DFT_PAST_MAX;
     234             : 
     235             :             /*dmx energy memory*/
     236        1476 :             hStereoDft->past_dmx_nrg = stereo_dft_dmx_swb_nrg( hStereoDft->DFT_past_DMX[idx_k0], hStereoDft->DFT_past_DMX[idx_k1], min( hStereoDft->NFFT, STEREO_DFT32MS_N_32k ) );
     237             :         }
     238             :     }
     239             : 
     240       16026 :     return;
     241             : }
     242             : 
     243             : 
     244             : /*-------------------------------------------------------------------*
     245             :  * add_HB_to_mono_dmx()
     246             :  *
     247             :  * add ACELP HB for DFT Stereo mono output with residual coding
     248             :  *-------------------------------------------------------------------*/
     249             : 
     250       52866 : void add_HB_to_mono_dmx(
     251             :     CPE_DEC_HANDLE hCPE,        /* i/o: CPE decoder structure       */
     252             :     float output[L_FRAME48k],   /* i/o: output synthesis            */
     253             :     float outputHB[L_FRAME48k], /* i  : HB synthesis                */
     254             :     const int16_t last_core,    /* i  : last core, primary channel  */
     255             :     const int16_t output_frame  /* i  : frame length                */
     256             : )
     257             : {
     258             :     int16_t i, j, decoderDelay, icbweOLASize, dftOvlLen, memOffset;
     259             :     float temp[L_FRAME48k + NS2SA( 48000, IVAS_DEC_DELAY_NS - DELAY_BWE_TOTAL_NS )];
     260             : 
     261             :     float winSlope;
     262             :     float alpha;
     263             :     const float *win_dft;
     264             :     int32_t output_Fs;
     265             :     float *memOutHB, *memTransitionHB;
     266             : 
     267       52866 :     output_Fs = hCPE->hCoreCoder[0]->output_Fs;
     268       52866 :     memOutHB = hCPE->hStereoDftDmx->memOutHB;
     269       52866 :     memTransitionHB = hCPE->hStereoDftDmx->memTransitionHB;
     270             : 
     271       52866 :     memOffset = NS2SA( output_Fs, IVAS_DEC_DELAY_NS - DELAY_BWE_TOTAL_NS );
     272             : 
     273       52866 :     if ( hCPE->hCoreCoder[0]->core == ACELP_CORE && hCPE->hCoreCoder[0]->extl_brate > 0 )
     274             :     {
     275             :         /* Resampled LB and HB offset */
     276       33135 :         mvr2r( outputHB, temp + memOffset, output_frame - memOffset );
     277             : 
     278       33135 :         decoderDelay = NS2SA( output_Fs, IVAS_DEC_DELAY_NS );
     279             : 
     280       33135 :         if ( last_core != ACELP_CORE )
     281             :         {
     282             :             /* 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 */
     283        2214 :             icbweOLASize = NS2SA( output_Fs, STEREO_DFT_DELAY_DEC_BWE_NS );
     284             : 
     285      299394 :             for ( i = 0; i < decoderDelay; i++ )
     286             :             {
     287      297180 :                 temp[i] = 0;
     288             :             }
     289             : 
     290        2214 :             assert( icbweOLASize > 0 );
     291        2214 :             winSlope = 1.0f / icbweOLASize;
     292        2214 :             alpha = winSlope;
     293      116514 :             for ( ; i < decoderDelay + icbweOLASize; i++ )
     294             :             {
     295      114300 :                 temp[i] *= alpha;
     296      114300 :                 alpha += winSlope;
     297             :             }
     298             :         }
     299             :         else
     300             :         {
     301       30921 :             mvr2r( memOutHB, temp, memOffset );
     302             :         }
     303             : 
     304       33135 :         v_add( temp, output, output, output_frame );
     305             : 
     306       33135 :         mvr2r( outputHB + output_frame - memOffset, memOutHB, memOffset );
     307             : 
     308       33135 :         win_dft = hCPE->hStereoDft->win32ms;
     309       33135 :         dftOvlLen = hCPE->hStereoDft->dft32ms_ovl;
     310             : 
     311             :         /* Preparing buffers in anticipation of an ACELP to TCX switch */
     312       33135 :         j = 0;
     313     1243455 :         for ( i = 0; i < memOffset; i++ )
     314             :         {
     315     1210320 :             memTransitionHB[i] = memOutHB[i] * win_dft[STEREO_DFT32MS_STEP * ( dftOvlLen - 1 - j )];
     316     1210320 :             j++;
     317             :         }
     318             : 
     319     2857215 :         for ( i = 0; j < dftOvlLen; i++ )
     320             :         {
     321     2824080 :             memTransitionHB[memOffset + i] = outputHB[output_frame - i - 1] * win_dft[STEREO_DFT32MS_STEP * ( dftOvlLen - 1 - j )];
     322     2824080 :             j++;
     323             :         }
     324             :     }
     325             :     else
     326             :     {
     327       19731 :         if ( last_core == ACELP_CORE )
     328             :         {
     329             :             /* This is generated in the ACELP frame and windowed. This process is akin to GenTransition for IC-BWE */
     330        7311 :             if ( hCPE->element_mode == IVAS_CPE_DFT && hCPE->nchan_out == 1 && hCPE->hStereoDft->hConfig->res_cod_mode == STEREO_DFT_RES_COD_OFF )
     331             :             {
     332        3039 :                 v_add( output, outputHB, output, NS2SA( output_Fs, STEREO_DFT32MS_OVL_NS ) );
     333             :             }
     334             :             else
     335             :             {
     336        4272 :                 v_add( output, memTransitionHB, output, NS2SA( output_Fs, STEREO_DFT32MS_OVL_NS ) );
     337             :             }
     338             : 
     339        7311 :             set_f( memOutHB, 0, memOffset );
     340        7311 :             set_f( memTransitionHB, 0, NS2SA( output_Fs, STEREO_DFT32MS_OVL_NS ) );
     341             :         }
     342             :     }
     343             : 
     344       52866 :     return;
     345             : }

Generated by: LCOV version 1.14