LCOV - code coverage report
Current view: top level - lib_dec - ivas_stereo_ica_dec.c (source / functions) Hit Total Coverage
Test: Coverage on main -- short test vectors @ 6c9ddc4024a9c0e1ecb8f643f114a84a0e26ec6b Lines: 125 125 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 "ivas_cnst.h"
      39             : #include "prot.h"
      40             : #include "ivas_prot.h"
      41             : #ifdef DEBUGGING
      42             : #include "debug.h"
      43             : #endif
      44             : #include "wmc_auto.h"
      45             : #include "rom_com.h"
      46             : #include "ivas_rom_com.h"
      47             : 
      48             : 
      49             : /*---------------------------------------------------------------
      50             :  *  stereo_tca_dec()
      51             :  *
      52             :  *     Stereo temporal channel adjustment/allocation processing module;
      53             :  *     upnmix, convert L/R to M/S.
      54             :  * ---------------------------------------------------------------*/
      55             : 
      56      450150 : void stereo_tca_dec(
      57             :     CPE_DEC_HANDLE hCPE,        /* i/o: CPE decoder structure           */
      58             :     float *synth[CPE_CHANNELS], /* i/o: output synth                    */
      59             :     const int16_t output_frame  /* i  : length of a frame per channel   */
      60             : )
      61             : {
      62             :     /* Buffers, input Left and right channels  @ input_Fs*/
      63             :     float bufChanL[L_DEC_MEM_LEN_ICA + L_FRAME48k];
      64             :     float bufChanR[L_DEC_MEM_LEN_ICA + L_FRAME48k];
      65             :     float *ptrChanL, *ptrChanR;
      66             :     float *target;
      67             :     int16_t target_idx, prevNCShift, currentNCShift, l_shift_adapt;
      68             :     int16_t dsFactor, tempMax;
      69             :     float *ref;
      70             :     int16_t bothChannelShift;
      71             :     int32_t output_Fs;
      72             :     STEREO_TCA_DEC_HANDLE hStereoTCA;
      73             : 
      74      450150 :     hStereoTCA = hCPE->hStereoTCA;
      75             : 
      76      450150 :     output_Fs = hCPE->hCoreCoder[0]->output_Fs;
      77             : 
      78      450150 :     if ( hCPE->nchan_out == 1 )
      79             :     {
      80       92418 :         if ( hCPE->hStereoDftDmx )
      81             :         {
      82       71424 :             if ( hCPE->element_mode == IVAS_CPE_DFT )
      83             :             {
      84       67365 :                 hCPE->hStereoDftDmx->targetGain = 1.0f;
      85             :             }
      86             : 
      87             :             /* save the target gain for next frame */
      88       71424 :             hCPE->hStereoDftDmx->prevTargetGain = hCPE->hStereoDftDmx->targetGain;
      89             :         }
      90             : 
      91       92418 :         return;
      92             :     }
      93      357732 :     else if ( hCPE->element_mode == IVAS_CPE_MDCT && !hCPE->hStereoMdct->use_itd )
      94             :     {
      95      208398 :         return;
      96             :     }
      97             : 
      98             :     /* populate L/R memories into current buffers */
      99      149334 :     mvr2r( hStereoTCA->memChanL, bufChanL, L_DEC_MEM_LEN_ICA );
     100      149334 :     mvr2r( hStereoTCA->memChanR, bufChanR, L_DEC_MEM_LEN_ICA );
     101             : 
     102             :     /* pointers to the current frame */
     103      149334 :     ptrChanL = bufChanL + L_DEC_MEM_LEN_ICA;
     104      149334 :     ptrChanR = bufChanR + L_DEC_MEM_LEN_ICA;
     105             : 
     106             :     /* copy interleaved stereo data to two channels, e.g., L, R */
     107      149334 :     mvr2r( synth[0], ptrChanL, output_frame );
     108      149334 :     mvr2r( synth[1], ptrChanR, output_frame );
     109             : 
     110             :     /* back up the L/R target synth for next frame */
     111      149334 :     mvr2r( bufChanL + output_frame, hStereoTCA->memChanL, L_DEC_MEM_LEN_ICA );
     112      149334 :     mvr2r( bufChanR + output_frame, hStereoTCA->memChanR, L_DEC_MEM_LEN_ICA );
     113             : 
     114             :     /* TCA parameter de-quantize */
     115      149334 :     dsFactor = (int16_t) ( output_Fs / 8000 );
     116      149334 :     tempMax = NS2SA( output_Fs, L_NCSHIFT_NS );
     117      149334 :     hStereoTCA->corrLagStats = min( hStereoTCA->indx_ica_NCShift * dsFactor, tempMax );
     118             : 
     119      149334 :     bothChannelShift = 0;
     120      149334 :     if ( hCPE->element_mode == IVAS_CPE_DFT || hCPE->element_mode == IVAS_CPE_MDCT )
     121             :     {
     122      142053 :         hStereoTCA->corrLagStats = 0;
     123      142053 :         hStereoTCA->refChanIndx = L_CH_INDX;
     124      142053 :         hStereoTCA->targetGain = 1.0f;
     125             : 
     126      142053 :         if ( hCPE->element_mode == IVAS_CPE_DFT )
     127             :         {
     128      111693 :             hStereoTCA->corrLagStats = (int16_t) fabsf( hCPE->hStereoDft->itd[1] );
     129      111693 :             hStereoTCA->refChanIndx = ( hCPE->hStereoDft->itd[1] >= 0 ) ? ( L_CH_INDX ) : ( R_CH_INDX );
     130             :         }
     131       30360 :         else if ( hCPE->element_mode == IVAS_CPE_MDCT )
     132             :         {
     133             :             float itd;
     134             : 
     135       30360 :             itd = hCPE->hStereoMdct->itd;
     136       30360 :             hStereoTCA->corrLagStats = (int16_t) fabsf( itd );
     137       30360 :             hStereoTCA->refChanIndx = ( itd >= 0 ) ? ( L_CH_INDX ) : ( R_CH_INDX );
     138             :         }
     139             : 
     140      142053 :         if ( hStereoTCA->refChanIndx != hStereoTCA->prevRefChanIndx && hStereoTCA->corrLagStats != 0 )
     141             :         {
     142        1170 :             bothChannelShift = 1;
     143             :         }
     144             :     }
     145             : 
     146      149334 :     prevNCShift = (int16_t) abs( hStereoTCA->prevCorrLagStats );
     147      149334 :     currentNCShift = (int16_t) abs( hStereoTCA->corrLagStats );
     148             : 
     149      149334 :     if ( hCPE->element_mode == IVAS_CPE_TD && hCPE->last_element_mode == IVAS_CPE_TD )
     150             :     {
     151        7170 :         if ( hStereoTCA->corrLagStats == hStereoTCA->prevCorrLagStats && hStereoTCA->interp_dec_switch_to_zero_diff == 0 )
     152             :         {
     153        3612 :             hStereoTCA->interp_dec_switch_to_zero_diff = 1;
     154             :         }
     155             :         else
     156             :         {
     157        3558 :             hStereoTCA->interp_dec_switch_to_zero_diff = 0;
     158             :         }
     159             : 
     160        7170 :         if ( currentNCShift != 0 )
     161             :         {
     162          12 :             currentNCShift = TRUNC( 0.6 * prevNCShift + 0.4 * currentNCShift );
     163             :         }
     164             : 
     165        7170 :         prevNCShift = hStereoTCA->interp_dec_prevNCShift;
     166        7170 :         hStereoTCA->interp_dec_prevNCShift = currentNCShift;
     167             :     }
     168             :     else
     169             :     {
     170      142164 :         hStereoTCA->interp_dec_prevNCShift = currentNCShift;
     171      142164 :         hStereoTCA->interp_dec_switch_to_zero_diff = 0;
     172             :     }
     173             : 
     174      149334 :     ref = ptrChanL;
     175      149334 :     target = ptrChanR;
     176      149334 :     target_idx = R_CH_INDX;
     177             :     /* identify target signal to adjust for shift variations */
     178      149334 :     if ( ( prevNCShift == 0 && hStereoTCA->refChanIndx == R_CH_INDX ) || ( hStereoTCA->prevRefChanIndx == R_CH_INDX ) )
     179             :     {
     180       45654 :         ref = ptrChanR;
     181       45654 :         target = ptrChanL;
     182       45654 :         target_idx = L_CH_INDX;
     183             :     }
     184             : 
     185      149334 :     if ( bothChannelShift == 1 )
     186             :     {
     187        1170 :         ref = ptrChanL;
     188        1170 :         target = ptrChanR;
     189        1170 :         target_idx = R_CH_INDX;
     190        1170 :         if ( hStereoTCA->refChanIndx == R_CH_INDX )
     191             :         {
     192         927 :             ref = ptrChanR;
     193         927 :             target = ptrChanL;
     194         927 :             target_idx = L_CH_INDX;
     195             :         }
     196             :     }
     197             : 
     198             :     /* target signal adjustment for temporal shift variations */
     199      149334 :     if ( hStereoTCA->prevCorrLagStats != hStereoTCA->corrLagStats || bothChannelShift || ( hStereoTCA->interp_dec_switch_to_zero_diff == 1 && hCPE->element_mode == IVAS_CPE_TD ) )
     200             :     {
     201       10734 :         l_shift_adapt = L_SHIFT_ADAPT_16k;
     202       10734 :         if ( output_Fs > 16000 )
     203             :         {
     204        8481 :             l_shift_adapt = L_SHIFT_ADAPT_MAX;
     205             :         }
     206             : 
     207       10734 :         if ( hCPE->element_mode == IVAS_CPE_TD && hCPE->last_element_mode == IVAS_CPE_DFT )
     208             :         {
     209          36 :             l_shift_adapt = l_shift_adapt >> 1;
     210             :         }
     211             : 
     212             : #ifdef DEBUGGING
     213             :         /* Max sample looked in INTERP1 should lie within the bounds of output_frame and memory populated */
     214             :         assert( ( ( min( N_MAX_SHIFT_CHANGE, N_MAX_SHIFT_CHANGE * output_Fs / 32000.0f ) + 1 ) + SINC_ORDER1 / INTERP_FACTOR1 ) + l_shift_adapt - currentNCShift < output_frame );
     215             :         assert( ( ( min( N_MAX_SHIFT_CHANGE, N_MAX_SHIFT_CHANGE * output_Fs / 32000.0f ) + 1 ) + SINC_ORDER1 / INTERP_FACTOR1 + currentNCShift ) <= L_DEC_MEM_LEN_ICA );
     216             : #endif
     217       10734 :         if ( abs( currentNCShift - prevNCShift ) <= N_MAX_SHIFT_CHANGE && bothChannelShift == 0 )
     218             :         {
     219        8787 :             adjustTargetSignal( target - currentNCShift, currentNCShift, prevNCShift, l_shift_adapt, 0 );
     220             :         }
     221             :         else
     222             :         {
     223        1947 :             if ( bothChannelShift == 1 )
     224             :             {
     225        1170 :                 adjustTargetSignal( ref, 0, prevNCShift, l_shift_adapt, 1 );
     226        1170 :                 adjustTargetSignal( target - currentNCShift, currentNCShift, 0, l_shift_adapt, 1 );
     227             :             }
     228             :             else
     229             :             {
     230         777 :                 adjustTargetSignal( target - currentNCShift, currentNCShift, prevNCShift, l_shift_adapt, 1 );
     231             :             }
     232             :         }
     233             :     }
     234             : 
     235             :     /* temporal channel adjustment */
     236      149334 :     mvr2r( target - currentNCShift, synth[target_idx], output_frame );
     237             : 
     238      149334 :     mvr2r( ref, synth[!target_idx], output_frame );
     239             : 
     240             :     /* Scale the Right channel with the gain */
     241      149334 :     stereo_tca_scale_R_channel( hCPE, synth[1], output_frame );
     242             : 
     243             :     /*-----------------------------------------------------------------*
     244             :      * updates and memory backups
     245             :      *-----------------------------------------------------------------*/
     246             : 
     247             :     /* save the reference channel index for next frame */
     248      149334 :     hStereoTCA->prevRefChanIndx = hStereoTCA->refChanIndx;
     249             : 
     250             :     /* save the corr lag stats for next frame */
     251      149334 :     hStereoTCA->prevCorrLagStats = hStereoTCA->corrLagStats;
     252             : 
     253             :     /* save the target gain for next frame */
     254      149334 :     hStereoTCA->prevTargetGain = hStereoTCA->targetGain;
     255             : 
     256      149334 :     return;
     257             : }
     258             : 
     259             : /*-------------------------------------------------------------------*
     260             :  * stereo_tca_scale_R_channel()
     261             :  *
     262             :  * Scale the Right channel with the gain
     263             :  *-------------------------------------------------------------------*/
     264             : 
     265      153414 : void stereo_tca_scale_R_channel(
     266             :     CPE_DEC_HANDLE hCPE,       /* i/o: CPE decoder structure       */
     267             :     float *output,             /* i/o: output synthesis, R channel */
     268             :     const int16_t output_frame /* i  : frame length                */
     269             : )
     270             : {
     271             :     STEREO_TCA_DEC_HANDLE hStereoTCA;
     272             :     int16_t i, j, l_ica_ovl, flat_old;
     273             :     float tempF, tempF1, winSlope;
     274             :     int32_t output_Fs;
     275             : 
     276      153414 :     hStereoTCA = hCPE->hStereoTCA;
     277      153414 :     output_Fs = hCPE->hCoreCoder[0]->output_Fs;
     278             : 
     279      153414 :     if ( hCPE->hCoreCoder[0]->core_brate <= SID_2k40 && hCPE->nchan_out == 2 )
     280             :     {
     281       21747 :         return;
     282             :     }
     283             :     /* Scale the Right channel with the gain */
     284      131667 :     l_ica_ovl = NS2SA( output_Fs, STEREO_L_TCA_OVLP_NS );
     285             : 
     286      131667 :     if ( hCPE->nchan_out == 1 )
     287             :     {
     288             :         /* in mono DMX, the scaling is done before synchro_synthesis() */
     289        4080 :         flat_old = NS2SA( output_Fs, ACELP_LOOK_NS + IVAS_DEC_DELAY_NS - DELAY_CLDFB_NS );
     290             : 
     291        4080 :         if ( hCPE->last_element_mode == IVAS_CPE_TD && hCPE->element_mode == IVAS_CPE_DFT )
     292             :         {
     293          21 :             hCPE->hStereoDftDmx->prevTargetGain *= 2.0f;
     294          21 :             hCPE->hStereoDftDmx->prevTargetGain = min( hCPE->hStereoDftDmx->prevTargetGain, powf( 10, ( ( 1 << STEREO_BITS_TCA_GD ) - 1 ) * STEREO_TCA_GDSTEP + STEREO_TCA_GDMIN ) );
     295          21 :             hCPE->hStereoDftDmx->targetGain = 1.0f;
     296             : 
     297          21 :             flat_old = NS2SA( output_Fs, IVAS_DEC_DELAY_NS );
     298             :         }
     299             :     }
     300      127587 :     else if ( hCPE->last_element_mode == IVAS_CPE_TD && hCPE->element_mode == IVAS_CPE_DFT )
     301             :     {
     302          42 :         flat_old = NS2SA( output_Fs, IVAS_DEC_DELAY_NS );
     303             :     }
     304             :     else
     305             :     {
     306      127545 :         flat_old = NS2SA( output_Fs, ACELP_LOOK_NS + IVAS_DEC_DELAY_NS );
     307             :     }
     308             : 
     309      131667 :     if ( hCPE->nchan_out == 1 )
     310             :     {
     311        4080 :         tempF1 = 1.0f / hCPE->hStereoDftDmx->targetGain;
     312        4080 :         tempF = 1.0f / hCPE->hStereoDftDmx->prevTargetGain;
     313             :     }
     314             :     else
     315             :     {
     316      127587 :         tempF1 = 1.0f / hStereoTCA->targetGain;
     317      127587 :         tempF = 1.0f / hStereoTCA->prevTargetGain;
     318             :     }
     319      131667 :     winSlope = 1.0f / (float) l_ica_ovl;
     320             : 
     321    50376663 :     for ( i = 0; i < flat_old; i++ )
     322             :     {
     323    50244996 :         output[i] *= tempF;
     324             :     }
     325    21137907 :     for ( j = 0; i < flat_old + l_ica_ovl; i++, j++ )
     326             :     {
     327    21006240 :         output[i] = ( 1.0f - j * winSlope ) * tempF * output[i] + ( j * winSlope ) * tempF1 * output[i];
     328             :     }
     329    12905391 :     for ( ; i < output_frame; i++ )
     330             :     {
     331    12773724 :         output[i] *= tempF1;
     332             :     }
     333             : 
     334      131667 :     return;
     335             : }
     336             : 
     337             : 
     338             : /*-------------------------------------------------------------------*
     339             :  * stereo_tca_init_dec()
     340             :  *
     341             :  * Stereo temporal channel adjustment (TCA) decoder initialization
     342             :  *-------------------------------------------------------------------*/
     343             : 
     344        1608 : void stereo_tca_init_dec(
     345             :     STEREO_TCA_DEC_HANDLE hStereoTCA /* i/o: Stereo TCA handle */
     346             : )
     347             : {
     348        1608 :     hStereoTCA->refChanIndx = L_CH_INDX;
     349        1608 :     hStereoTCA->prevRefChanIndx = L_CH_INDX;
     350        1608 :     hStereoTCA->indx_ica_NCShift = 0;
     351        1608 :     hStereoTCA->indx_ica_gD = 0;
     352        1608 :     hStereoTCA->targetGain = 1.0f;
     353        1608 :     hStereoTCA->prevTargetGain = 1.0f;
     354             : 
     355        1608 :     hStereoTCA->corrLagStats = 0;
     356        1608 :     hStereoTCA->prevCorrLagStats = 0;
     357             : 
     358        1608 :     hStereoTCA->interp_dec_prevNCShift = 0;
     359        1608 :     hStereoTCA->interp_dec_switch_to_zero_diff = 0;
     360             : 
     361        1608 :     set_f( hStereoTCA->memChanL, 0.0f, L_DEC_MEM_LEN_ICA );
     362        1608 :     set_f( hStereoTCA->memChanR, 0.0f, L_DEC_MEM_LEN_ICA );
     363             : 
     364        1608 :     return;
     365             : }

Generated by: LCOV version 1.14