LCOV - code coverage report
Current view: top level - lib_com - tcx_utils.c (source / functions) Hit Total Coverage
Test: Coverage on main -- short test vectors @ 6c9ddc4024a9c0e1ecb8f643f114a84a0e26ec6b Lines: 296 313 94.6 %
Date: 2025-05-23 08:37:30 Functions: 13 13 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             : /*====================================================================================
      34             :     EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
      35             :   ====================================================================================*/
      36             : 
      37             : #include <assert.h>
      38             : #include <stdint.h>
      39             : #include "options.h"
      40             : #ifdef DEBUGGING
      41             : #include "debug.h"
      42             : #endif
      43             : #include <math.h>
      44             : #include "cnst.h"
      45             : #include "rom_com.h"
      46             : #include "prot.h"
      47             : #include "wmc_auto.h"
      48             : 
      49             : /*-------------------------------------------------------------------*
      50             :  * tcx_get_windows()
      51             :  *
      52             :  *
      53             :  *-------------------------------------------------------------------*/
      54      486728 : void tcx_get_windows(
      55             :     TCX_CONFIG_HANDLE hTcxCfg, /* i  : TCX configuration                   */
      56             :     const int16_t left_mode,   /* i  : overlap mode of left window half    */
      57             :     const int16_t right_mode,  /* i  : overlap mode of right window half   */
      58             :     int16_t *left_overlap,     /* o  : left overlap length                 */
      59             :     const float **left_win,    /* o  : left overlap window                 */
      60             :     int16_t *right_overlap,    /* o  : right overlap length                */
      61             :     const float **right_win,   /* o  : right overlap window                */
      62             :     const int16_t fullband     /* i  : fullband flag                       */
      63             : )
      64             : {
      65      486728 :     if ( !fullband )
      66             :     {
      67             :         /* Left part */
      68             : 
      69      108975 :         if ( left_mode == TRANSITION_OVERLAP )
      70             :         {
      71             :             /* ACELP->TCX transition */
      72         318 :             *left_overlap = hTcxCfg->tcx_mdct_window_trans_length;
      73         318 :             *left_win = hTcxCfg->tcx_mdct_window_trans;
      74             :         }
      75      108657 :         else if ( left_mode == MIN_OVERLAP )
      76             :         {
      77        2173 :             *left_overlap = hTcxCfg->tcx_mdct_window_min_length;
      78        2173 :             *left_win = hTcxCfg->tcx_mdct_window_minimum;
      79             :         }
      80      106484 :         else if ( left_mode == HALF_OVERLAP )
      81             :         {
      82        1744 :             *left_overlap = hTcxCfg->tcx_mdct_window_half_length;
      83        1744 :             *left_win = hTcxCfg->tcx_mdct_window_half;
      84             :         }
      85      104740 :         else if ( left_mode == FULL_OVERLAP )
      86             :         {
      87      104740 :             *left_overlap = hTcxCfg->tcx_mdct_window_length;
      88      104740 :             *left_win = hTcxCfg->tcx_aldo_window_1_trunc;
      89             :         }
      90             :         else
      91             :         {
      92           0 :             assert( !"Not supported overlap" );
      93             :         }
      94             : 
      95             :         /* Right part */
      96             : 
      97      108975 :         if ( right_mode == MIN_OVERLAP )
      98             :         {
      99        2187 :             *right_overlap = hTcxCfg->tcx_mdct_window_min_length;
     100        2187 :             *right_win = hTcxCfg->tcx_mdct_window_minimum;
     101             :         }
     102      106788 :         else if ( right_mode == HALF_OVERLAP )
     103             :         {
     104        1747 :             *right_overlap = hTcxCfg->tcx_mdct_window_half_length;
     105        1747 :             *right_win = hTcxCfg->tcx_mdct_window_half;
     106             :         }
     107      105041 :         else if ( right_mode == FULL_OVERLAP )
     108             :         {
     109      105041 :             *right_overlap = hTcxCfg->tcx_mdct_window_delay;
     110      105041 :             *right_win = hTcxCfg->tcx_aldo_window_2;
     111             :         }
     112             :         else
     113             :         {
     114           0 :             assert( !"Not supported overlap" );
     115             :         }
     116             :     }
     117             :     else
     118             :     {
     119             :         /* Left part */
     120             : 
     121      377753 :         if ( left_mode == TRANSITION_OVERLAP )
     122             :         {
     123             :             /* ACELP->TCX transition */
     124       10968 :             *left_overlap = hTcxCfg->tcx_mdct_window_trans_lengthFB;
     125       10968 :             *left_win = hTcxCfg->tcx_mdct_window_transFB;
     126             :         }
     127      366785 :         else if ( left_mode == MIN_OVERLAP )
     128             :         {
     129       58742 :             *left_overlap = hTcxCfg->tcx_mdct_window_min_lengthFB;
     130       58742 :             *left_win = hTcxCfg->tcx_mdct_window_minimumFB;
     131             :         }
     132      308043 :         else if ( left_mode == HALF_OVERLAP )
     133             :         {
     134       14719 :             *left_overlap = hTcxCfg->tcx_mdct_window_half_lengthFB;
     135       14719 :             *left_win = hTcxCfg->tcx_mdct_window_halfFB;
     136             :         }
     137      293324 :         else if ( left_mode == RECTANGULAR_OVERLAP )
     138             :         {
     139       32860 :             *left_overlap = 0;
     140       32860 :             *left_win = NULL;
     141             :         }
     142      260464 :         else if ( left_mode == FULL_OVERLAP )
     143             :         {
     144      260464 :             *left_overlap = hTcxCfg->tcx_mdct_window_lengthFB;
     145      260464 :             *left_win = hTcxCfg->tcx_aldo_window_1_FB_trunc;
     146             :         }
     147             :         else
     148             :         {
     149           0 :             assert( !"Not supported overlap" );
     150             :         }
     151             : 
     152             :         /* Right part */
     153             : 
     154      377753 :         if ( right_mode == MIN_OVERLAP )
     155             :         {
     156       61754 :             *right_overlap = hTcxCfg->tcx_mdct_window_min_lengthFB;
     157       61754 :             *right_win = hTcxCfg->tcx_mdct_window_minimumFB;
     158             :         }
     159      315999 :         else if ( right_mode == HALF_OVERLAP )
     160             :         {
     161       15236 :             *right_overlap = hTcxCfg->tcx_mdct_window_half_lengthFB;
     162       15236 :             *right_win = hTcxCfg->tcx_mdct_window_halfFB;
     163             :         }
     164      300763 :         else if ( right_mode == RECTANGULAR_OVERLAP )
     165             :         {
     166       32841 :             *right_overlap = 0;
     167       32841 :             *right_win = NULL;
     168             :         }
     169      267922 :         else if ( right_mode == FULL_OVERLAP )
     170             :         {
     171      267922 :             *right_overlap = hTcxCfg->tcx_mdct_window_delayFB;
     172      267922 :             *right_win = hTcxCfg->tcx_aldo_window_2_FB;
     173             :         }
     174             :         else
     175             :         {
     176           0 :             assert( !"Not supported overlap" );
     177             :         }
     178             :     }
     179             : 
     180      486728 :     return;
     181             : }
     182             : 
     183             : /*-------------------------------------------------------------------*
     184             :  * tcx_windowing_analysis()
     185             :  *
     186             :  *
     187             :  *-------------------------------------------------------------------*/
     188             : 
     189      486697 : void tcx_windowing_analysis(
     190             :     const float *signal,         /* i  : signal vector               */
     191             :     const int16_t L_frame,       /* i  : frame length                */
     192             :     const int16_t left_overlap,  /* i  : left overlap length         */
     193             :     const float *left_win,       /* i  : left overlap window         */
     194             :     const int16_t right_overlap, /* i  : right overlap length        */
     195             :     const float *right_win,      /* i  : right overlap window        */
     196             :     float *output                /* o  : windowed signal vector      */
     197             : )
     198             : {
     199             :     int16_t w;
     200             : 
     201             :     /* Left overlap */
     202   139071869 :     for ( w = 0; w < left_overlap; w++ )
     203             :     {
     204   138585172 :         *output++ = *signal++ * left_win[w];
     205             :     }
     206             : 
     207             :     /* Non overlapping region */
     208   197677497 :     for ( w = 0; w < L_frame - ( left_overlap + right_overlap ) / 2; w++ )
     209             :     {
     210   197190800 :         *output++ = *signal++;
     211             :     }
     212             : 
     213             :     /* Right overlap */
     214   141706965 :     for ( w = 0; w < right_overlap; w++ )
     215             :     {
     216   141220268 :         *output++ = *signal++ * right_win[right_overlap - 1 - w];
     217             :     }
     218             : 
     219      486697 :     return;
     220             : }
     221             : 
     222             : 
     223             : /*-------------------------------------------------------------------*
     224             :  * WindowSignal()
     225             :  *
     226             :  *
     227             :  *-------------------------------------------------------------------*/
     228             : 
     229      486697 : void WindowSignal(
     230             :     TCX_CONFIG_HANDLE hTcxCfg,        /* i  : configuration of TCX                */
     231             :     int16_t offset,                   /* i  : left folding point offset relative to the input signal pointer */
     232             :     const int16_t left_overlap_mode,  /* i  : overlap mode of left window half    */
     233             :     const int16_t right_overlap_mode, /* i  : overlap mode of right window half   */
     234             :     int16_t *left_overlap_length,     /* o  : TCX window left overlap length      */
     235             :     int16_t *right_overlap_length,    /* o  : TCX window right overlap length     */
     236             :     const float in[],                 /* i  : input signal                        */
     237             :     int16_t *L_frame,                 /* i/o: frame length                        */
     238             :     float out[],                      /* o  : output windowed signal              */
     239             :     const int16_t truncate_aldo,      /* i  : nonzero to truncate long ALDO slope */
     240             :     const int16_t fullband            /* i  : fullband flag                       */
     241             : )
     242             : {
     243             :     int16_t l, r;
     244             :     const float *left_win;
     245             :     const float *right_win;
     246             : 
     247             :     /*-----------------------------------------------------------*
     248             :      * Init                                                      *
     249             :      *-----------------------------------------------------------*/
     250             : 
     251      486697 :     tcx_get_windows( hTcxCfg, left_overlap_mode, right_overlap_mode, &l, &left_win, &r, &right_win, fullband );
     252             : 
     253             :     /* Init lengths */
     254             : 
     255             :     /* if past frame is ACELP */
     256      486697 :     if ( left_overlap_mode == TRANSITION_OVERLAP )
     257             :     {
     258             :         /* Increase frame size for 5ms */
     259       11286 :         if ( !fullband )
     260             :         {
     261         318 :             *L_frame += hTcxCfg->tcx5Size;
     262         318 :             offset = -hTcxCfg->tcx_mdct_window_trans_length / 2;
     263             :         }
     264             :         else
     265             :         {
     266       10968 :             *L_frame += hTcxCfg->tcx5SizeFB;
     267       10968 :             offset = -hTcxCfg->tcx_mdct_window_trans_lengthFB / 2;
     268             :         }
     269             :     }
     270             : 
     271             :     /*-----------------------------------------------------------*
     272             :      * Windowing                                                 *
     273             :      *-----------------------------------------------------------*/
     274             : 
     275      486697 :     tcx_windowing_analysis( in - l / 2 + offset, *L_frame, l, left_win, r, right_win, out );
     276             : 
     277      486697 :     if ( left_overlap_mode == FULL_OVERLAP && truncate_aldo )
     278             :     {
     279             :         /* fade truncated ALDO window to avoid discontinuities */
     280      341967 :         if ( !fullband )
     281             :         {
     282      104740 :             v_mult( out, hTcxCfg->tcx_mdct_window_minimum, out, hTcxCfg->tcx_mdct_window_min_length );
     283             :         }
     284             :         else
     285             :         {
     286      237227 :             v_mult( out, hTcxCfg->tcx_mdct_window_minimumFB, out, hTcxCfg->tcx_mdct_window_min_lengthFB );
     287             :         }
     288             :     }
     289             : 
     290      486697 :     *left_overlap_length = l;
     291      486697 :     *right_overlap_length = r;
     292             : 
     293      486697 :     return;
     294             : }
     295             : 
     296             : 
     297             : /*-------------------------------------------------------------------*
     298             :  * tcx_windowing_synthesis_current_frame()
     299             :  *
     300             :  *
     301             :  *-------------------------------------------------------------------*/
     302             : 
     303      374967 : void tcx_windowing_synthesis_current_frame(
     304             :     float *signal,                    /* i/o: signal vector                             */
     305             :     const float *window,              /* i  : TCX window vector                         */
     306             :     const float *window_half,         /* i  : TCX window vector for half-overlap window */
     307             :     const float *window_min,          /* i  : TCX minimum overlap window                */
     308             :     const int16_t window_length,      /* i  : TCX window length                         */
     309             :     const int16_t window_half_length, /* i  : TCX half window length                    */
     310             :     const int16_t window_min_length,  /* i  : TCX minimum overlap length                */
     311             :     const int16_t left_rect,          /* i  : left part is rectangular                  */
     312             :     const int16_t left_mode,          /* i  : overlap mode of left window half          */
     313             :     float *acelp_zir,                 /* i/o: acelp ZIR                                 */
     314             :     const float *old_syn,             /* i  : old synthesis                             */
     315             :     const float *syn_overl,           /* i  : overlap synthesis                         */
     316             :     const float *A_zir,
     317             :     const float *window_trans,
     318             :     int16_t acelp_zir_len,
     319             :     const int16_t acelp_mem_len,
     320             :     const int16_t last_core_bfi, /* i  : last mode                                 */
     321             :     const int16_t last_is_cng,
     322             :     const int16_t fullbandScale )
     323             : {
     324             :     int16_t i, w, overlap;
     325             :     float tmp[L_FRAME_MAX / 2];
     326             : 
     327             :     /* Init */
     328      374967 :     overlap = window_length >> 1;
     329             : 
     330             :     /* Past-frame is TCX concealed as CNG and current-frame is TCX */
     331      374967 :     if ( last_is_cng == 1 && left_rect == 0 )
     332             :     {
     333           0 :         if ( !fullbandScale )
     334             :         {
     335           0 :             set_zero( acelp_zir, acelp_zir_len );
     336           0 :             syn_filt( A_zir, M, acelp_zir, acelp_zir, acelp_zir_len, signal + overlap + acelp_mem_len - M, 0 );
     337             :         }
     338             :         else
     339             :         {
     340           0 :             lerp( acelp_zir, tmp, acelp_zir_len, acelp_zir_len * FSCALE_DENOM / fullbandScale );
     341           0 :             acelp_zir = tmp;
     342             :         }
     343             : 
     344           0 :         for ( i = 0; i < acelp_zir_len; i++ )
     345             :         {
     346           0 :             signal[i] *= (float) ( i ) / (float) ( acelp_zir_len );
     347           0 :             signal[i] += acelp_zir[i] * (float) ( acelp_zir_len - i ) / (float) ( acelp_zir_len );
     348             :         }
     349             :     }
     350      374967 :     else if ( left_rect == 1 && last_core_bfi == ACELP_CORE ) /* Rectangular window (past-frame is ACELP) */
     351             :     {
     352     6765020 :         for ( i = 0; i < overlap - acelp_mem_len; i++ )
     353             :         {
     354     6701076 :             signal[i] = 0;
     355             :         }
     356             : 
     357       63944 :         if ( fullbandScale == 0 )
     358             :         {
     359             :             /*OLA with ACELP*/
     360      777617 :             for ( i = 0; i < 2 * acelp_mem_len; i++ )
     361             :             {
     362             :                 /*window decoded TCX with aliasing*/
     363      741552 :                 signal[i + overlap - acelp_mem_len] *= window_trans[i];
     364             :                 /*Time TDAC: 1)forward part of ACELP*/
     365      741552 :                 signal[i + overlap - acelp_mem_len] += old_syn[acelp_zir_len - 2 * acelp_mem_len + i] * window_trans[2 * acelp_mem_len - i - 1] * window_trans[2 * acelp_mem_len - i - 1];
     366             : 
     367             :                 /*Time TDAC: 1)reward part of ACELP*/
     368      741552 :                 signal[i + overlap - acelp_mem_len] += old_syn[acelp_zir_len - i - 1] * window_trans[i] * window_trans[2 * acelp_mem_len - i - 1];
     369             :             }
     370             : 
     371      613105 :             for ( i = 0; i < M; i++ )
     372             :             {
     373      577040 :                 signal[overlap + acelp_mem_len - M + i] -= old_syn[acelp_zir_len - M + i];
     374             :             }
     375             :         }
     376             : 
     377             :         /* ZIR at the end of the ACELP frame */
     378       63944 :         acelp_zir_len = 64;
     379             : 
     380       63944 :         if ( !fullbandScale )
     381             :         {
     382       36065 :             set_zero( acelp_zir, acelp_zir_len );
     383       36065 :             syn_filt( A_zir, M, acelp_zir, acelp_zir, acelp_zir_len, signal + overlap + acelp_mem_len - M, 0 );
     384             :         }
     385             :         else
     386             :         {
     387       27879 :             lerp( acelp_zir, tmp, acelp_zir_len * fullbandScale / FSCALE_DENOM, acelp_zir_len );
     388       27879 :             acelp_zir_len = acelp_zir_len * fullbandScale / FSCALE_DENOM;
     389       27879 :             acelp_zir = tmp;
     390             : 
     391       27879 :             if ( acelp_zir_len >= 2.0f * 64 )
     392             :             {
     393             :                 /* apply a simple low-pass to the ZIR, to avoid potentially unmasked HF content */
     394     4272789 :                 for ( i = 2; i < acelp_zir_len; i++ )
     395             :                 {
     396     4251402 :                     acelp_zir[i] = 0.25f * acelp_zir[i - 2] + 0.35f * acelp_zir[i - 1] + 0.40f * acelp_zir[i];
     397             :                 }
     398       21387 :                 acelp_zir[acelp_zir_len - 1] = 0.40f * acelp_zir[acelp_zir_len - 1] + 0.35f * acelp_zir[acelp_zir_len - 1] + 0.25f * acelp_zir[acelp_zir_len - 2];
     399       21387 :                 acelp_zir[acelp_zir_len - 2] = 0.40f * acelp_zir[acelp_zir_len - 2] + 0.35f * acelp_zir[acelp_zir_len - 1] + 0.25f * acelp_zir[acelp_zir_len - 1];
     400     4272789 :                 for ( i = acelp_zir_len - 3; i >= 0; i-- )
     401             :                 {
     402     4251402 :                     acelp_zir[i] = 0.40f * acelp_zir[i] + 0.35f * acelp_zir[i + 1] + 0.25f * acelp_zir[i + 2];
     403             :                 }
     404             :             }
     405             :         }
     406             : 
     407     7268488 :         for ( i = 0; i < acelp_zir_len; i++ )
     408             :         {
     409             :             /*remove reconstructed ZIR and add ACELP ZIR*/
     410     7204544 :             signal[i + overlap + acelp_mem_len] -= acelp_zir[i] * (float) ( acelp_zir_len - i ) / (float) acelp_zir_len;
     411             :         }
     412             :     }
     413      311023 :     else if ( left_rect == 1 && last_core_bfi != 0 ) /* Rectangular window (past-frame is TCX) */
     414             :     {
     415      271968 :         for ( i = 0; i < overlap + acelp_mem_len; i++ )
     416             :         {
     417      270048 :             signal[i] = 0;
     418             :         }
     419      474504 :         for ( i = 0; i < window_length; i++ )
     420             :         {
     421      472584 :             signal[i + overlap + acelp_mem_len] *= window[i];
     422             :         }
     423             :     }
     424      309103 :     else if ( left_rect != 1 && last_core_bfi == 0 ) /* Normal window (past-frame is ACELP) */
     425             :     {
     426       36348 :         for ( i = 0; i < window_length; i++ )
     427             :         {
     428       36204 :             signal[i] *= window[i];
     429             :         }
     430             : 
     431       36348 :         for ( i = 0; i < window_length; i++ )
     432             :         {
     433       36204 :             signal[i] += syn_overl[i];
     434             :         }
     435             :     }
     436             :     else /* Normal window (past-frame is TCX) */
     437             :     {
     438      308959 :         if ( left_mode == 2 )
     439             :         {
     440             :             /* min. overlap */
     441     8593525 :             for ( i = 0; i < ( window_length - window_min_length ) / 2; i++ )
     442             :             {
     443     8408196 :                 signal[i] = 0.0f;
     444             :             }
     445     8159873 :             for ( w = 0; w < window_min_length; i++, w++ )
     446             :             {
     447     7974544 :                 signal[i] *= window_min[w];
     448             :             }
     449             :         }
     450      123630 :         else if ( left_mode == 3 )
     451             :         {
     452             :             /* half OL */
     453     1069179 :             for ( i = 0; i < ( window_length - window_half_length ) / 2; i++ )
     454             :             {
     455     1024688 :                 signal[i] = 0.0f;
     456             :             }
     457     5762515 :             for ( w = 0; w < window_half_length; i++, w++ )
     458             :             {
     459     5718024 :                 signal[i] *= window_half[w];
     460             :             }
     461             :         }
     462             :         else
     463             :         {
     464             :             /* normal full/maximum overlap */
     465    24092051 :             for ( i = 0; i < window_length; i++ )
     466             :             {
     467    24012912 :                 signal[i] *= window[i];
     468             :             }
     469             :         }
     470             :     }
     471             : 
     472      374967 :     return;
     473             : }
     474             : 
     475             : 
     476             : /*-------------------------------------------------------------------*
     477             :  * tcx_windowing_synthesis_past_frame()
     478             :  *
     479             :  *
     480             :  *-------------------------------------------------------------------*/
     481             : 
     482      379656 : void tcx_windowing_synthesis_past_frame(
     483             :     float *signal,                    /* i/o: signal vector                              */
     484             :     const float *window,              /* i  : TCX window vector                          */
     485             :     const float *window_half,         /* i  : TCX window vector for half-overlap window  */
     486             :     const float *window_min,          /* i  : TCX minimum overlap window                 */
     487             :     const int16_t window_length,      /* i  : TCX window length                          */
     488             :     const int16_t window_half_length, /* i  : TCX half window length                     */
     489             :     const int16_t window_min_length,  /* i  : TCX minimum overlap length                 */
     490             :     const int16_t right_mode          /* i  : overlap mode (left_mode of current frame)  */
     491             : )
     492             : {
     493             :     int16_t i, w;
     494             : 
     495      379656 :     if ( right_mode == MIN_OVERLAP )
     496             :     {
     497             :         /* min. overlap */
     498     8690694 :         for ( i = ( window_length - window_min_length ) / 2, w = 0; w < window_min_length; i++, w++ )
     499             :         {
     500     8493824 :             signal[i] *= window_min[window_min_length - 1 - w];
     501             :         }
     502    13438910 :         for ( ; i < window_length; i++ )
     503             :         {
     504    13242040 :             signal[i] = 0.0f;
     505             :         }
     506             :     }
     507      182786 :     else if ( right_mode == HALF_OVERLAP )
     508             :     {
     509             :         /* half OL */
     510     6518639 :         for ( i = ( window_length - window_half_length ) / 2, w = 0; w < window_half_length; i++, w++ )
     511             :         {
     512     6467736 :             signal[i] *= window_half[window_half_length - 1 - w];
     513             :         }
     514     4362727 :         for ( ; i < window_length; i++ )
     515             :         {
     516     4311824 :             signal[i] = 0.0f;
     517             :         }
     518             :     }
     519      131883 :     else if ( right_mode == FULL_OVERLAP )
     520             :     {
     521             :         /* normal full/maximum overlap */
     522    36256783 :         for ( i = 0; i < window_length; i++ )
     523             :         {
     524    36124900 :             signal[i] *= window[window_length - 1 - i];
     525             :         }
     526             :     }
     527             : 
     528      379656 :     return;
     529             : }
     530             : 
     531             : 
     532             : /*-------------------------------------------------------------------*
     533             :  * lpc2mdct()
     534             :  *
     535             :  *
     536             :  *-------------------------------------------------------------------*/
     537             : 
     538     1287206 : void lpc2mdct(
     539             :     float *lpcCoeffs,
     540             :     const int16_t lpcOrder,
     541             :     float mdct_gains[],
     542             :     const int16_t length,
     543             :     const int16_t noInverse )
     544             : {
     545             :     float RealData[2 * FDNS_NPTS], ImagData[2 * FDNS_NPTS];
     546             :     float tmp;
     547             :     int16_t i, sizeN;
     548             : 
     549     1287206 :     assert( length <= FDNS_NPTS );
     550             : 
     551     1287206 :     sizeN = 2 * length;
     552             : 
     553             :     /* ODFT */
     554    23169708 :     for ( i = 0; i < lpcOrder + 1; i++ )
     555             :     {
     556    21882502 :         tmp = (float) ( ( (float) i ) * EVS_PI / (float) ( sizeN ) );
     557    21882502 :         RealData[i] = (float) ( lpcCoeffs[i] * cos( tmp ) );
     558    21882502 :         ImagData[i] = (float) ( -lpcCoeffs[i] * sin( tmp ) );
     559             :     }
     560             : 
     561   144167072 :     for ( ; i < sizeN; i++ )
     562             :     {
     563   142879866 :         RealData[i] = 0.f;
     564   142879866 :         ImagData[i] = 0.f;
     565             :     }
     566             : 
     567     1287206 :     DoFFT( RealData, ImagData, sizeN );
     568             : 
     569     1287206 :     if ( noInverse )
     570             :     {
     571           0 :         for ( i = 0; i < length; i++ )
     572             :         {
     573           0 :             mdct_gains[i] = (float) ( sqrt( RealData[i] * RealData[i] + ImagData[i] * ImagData[i] ) );
     574             :         }
     575             :     }
     576             :     else
     577             :     /* Get amplitude */
     578             :     {
     579    83668390 :         for ( i = 0; i < length; i++ )
     580             :         {
     581    82381184 :             mdct_gains[i] = (float) ( 1.0f / max( EPSILON, sqrt( RealData[i] * RealData[i] + ImagData[i] * ImagData[i] ) ) );
     582             :         }
     583             :     }
     584             : 
     585     1287206 :     return;
     586             : }
     587             : 
     588             : 
     589             : /*-------------------------------------------------------------------*
     590             :  * mdct_noiseShaping()
     591             :  *
     592             :  *
     593             :  *-------------------------------------------------------------------*/
     594             : 
     595     1264517 : void mdct_noiseShaping(
     596             :     float x[],
     597             :     const int16_t lg,
     598             :     const float gains[],
     599             :     const int16_t nBands )
     600             : {
     601             :     int16_t i, j, k, l;
     602             :     float g;
     603             :     int16_t m, n, k1, k2;
     604             : 
     605     1264517 :     j = 0;
     606     1264517 :     assert( nBands != 0 );
     607     1264517 :     k = lg / nBands;
     608     1264517 :     m = lg % nBands;
     609             : 
     610     1264517 :     if ( m )
     611             :     {
     612       17014 :         if ( m <= ( FDNS_NPTS / 2 ) )
     613             :         {
     614       17014 :             n = FDNS_NPTS / m;
     615       17014 :             k1 = k;
     616       17014 :             k2 = k + 1;
     617             :         }
     618             :         else
     619             :         {
     620           0 :             n = FDNS_NPTS / ( FDNS_NPTS - m );
     621           0 :             k1 = k + 1;
     622           0 :             k2 = k;
     623             :         }
     624             : 
     625     1105910 :         for ( i = 0; i < lg; )
     626             :         {
     627     1088896 :             if ( j % n )
     628             :             {
     629      800608 :                 k = k1;
     630             :             }
     631             :             else
     632             :             {
     633      288288 :                 k = k2;
     634             :             }
     635     1088896 :             g = gains[j++];
     636             : 
     637             :             /* Limit number of loops, if end is reached */
     638     1088896 :             k = min( k, lg - i );
     639             : 
     640     8224416 :             for ( l = 0; l < k; l++ )
     641             :             {
     642     7135520 :                 x[i++] *= g;
     643             :             }
     644             :         }
     645             :     }
     646             :     else
     647             :     {
     648    81087695 :         for ( i = 0; i < lg; )
     649             :         {
     650    79840192 :             g = gains[j++];
     651             : 
     652   581903040 :             for ( l = 0; l < k; l++ )
     653             :             {
     654   502062848 :                 x[i++] *= g;
     655             :             }
     656             :         }
     657             :     }
     658             : 
     659     1264517 :     return;
     660             : }
     661             : 
     662             : 
     663             : /*-------------------------------------------------------------------*
     664             :  * PsychAdaptLowFreqDeemph()
     665             :  *
     666             :  *
     667             :  *-------------------------------------------------------------------*/
     668             : 
     669       83034 : void PsychAdaptLowFreqDeemph(
     670             :     float x[],
     671             :     const float lpcGains[],
     672             :     float lf_deemph_factors[] )
     673             : {
     674             :     int16_t i;
     675             :     float max_val, fac, tmp;
     676             : 
     677       83034 :     max_val = tmp = lpcGains[0];
     678             : 
     679             :     /* find minimum (tmp) and maximum (max) of LPC gains in low frequencies */
     680      747306 :     for ( i = 1; i < 9; i++ )
     681             :     {
     682      664272 :         if ( tmp > lpcGains[i] )
     683             :         {
     684      497470 :             tmp = lpcGains[i];
     685             :         }
     686      664272 :         if ( max_val < lpcGains[i] )
     687             :         {
     688      117559 :             max_val = lpcGains[i];
     689             :         }
     690             :     }
     691             : 
     692       83034 :     tmp *= 32.0f;
     693             : 
     694       83034 :     if ( ( max_val < tmp ) && ( tmp > FLT_MIN ) )
     695             :     {
     696       83034 :         fac = tmp = (float) pow( max_val / tmp, 0.0078125f );
     697             : 
     698       83034 :         if ( lf_deemph_factors )
     699             :         {
     700             :             /* gradual lowering of lowest 32 bins; DC is lowered by (max/tmp)^1/4 */
     701     2257695 :             for ( i = 31; i >= 0; i-- )
     702             :             {
     703     2189280 :                 x[i] *= fac;
     704     2189280 :                 lf_deemph_factors[i] *= fac;
     705     2189280 :                 fac *= tmp;
     706             :             }
     707             :         }
     708             :         else
     709             :         {
     710             :             /* gradual lowering of lowest 32 bins; DC is lowered by (max/tmp)^1/4 */
     711      482427 :             for ( i = 31; i >= 0; i-- )
     712             :             {
     713      467808 :                 x[i] *= fac;
     714      467808 :                 fac *= tmp;
     715             :             }
     716             :         }
     717             :     }
     718             : 
     719       83034 :     return;
     720             : }
     721             : 
     722             : 
     723             : /*-------------------------------------------------------------------*
     724             :  * AdaptLowFreqDeemph()
     725             :  *
     726             :  *
     727             :  *-------------------------------------------------------------------*/
     728             : 
     729      505316 : void AdaptLowFreqDeemph(
     730             :     float x[],
     731             :     int16_t tcx_lpc_shaped_ari,
     732             :     const float lpcGains[],
     733             :     const int16_t lg,
     734             :     float lf_deemph_factors[] )
     735             : {
     736             :     int16_t i, i_max_old, i_max;
     737             : 
     738      505316 :     if ( !tcx_lpc_shaped_ari )
     739             :     {
     740             :         /* 1. find first magnitude maximum in lower quarter of spectrum */
     741      436901 :         i_max = -1;
     742             : 
     743     2674371 :         for ( i = 0; i < lg / 4; i++ )
     744             :         {
     745     2658455 :             if ( ( x[i] <= -4.0f ) || ( x[i] >= 4.0f ) )
     746             :             {
     747      420985 :                 x[i] += ( x[i] < 0.0f ) ? 2.0f : -2.0f;
     748      420985 :                 i_max = i;
     749      420985 :                 break;
     750             :             }
     751             :         }
     752             :         /* 2. expand value range of all xi up to i_max: two extra steps */
     753             : 
     754     1475987 :         for ( i = 0; i < i_max; i++ )
     755             :         {
     756     1039086 :             x[i] *= 0.5f;
     757     1039086 :             lf_deemph_factors[i] *= 0.5f;
     758             :         }
     759             :         /* 3. find first magnitude maximum in lower quarter of spectrum */
     760      436901 :         i_max_old = i_max;
     761             : 
     762      436901 :         if ( i_max_old > -1 )
     763             :         {
     764      420985 :             i_max = -1;
     765             : 
     766     2156611 :             for ( i = 0; i < lg / 4; i++ )
     767             :             {
     768     2156547 :                 if ( ( x[i] <= -4.0f ) || ( x[i] >= 4.0f ) )
     769             :                 {
     770      420921 :                     x[i] += ( x[i] < 0.0f ) ? 2.0f : -2.0f;
     771      420921 :                     i_max = i;
     772      420921 :                     break;
     773             :                 }
     774             :             }
     775             :         }
     776             :         /* 4. expand value range of all xi up to i_max: two extra steps */
     777     2167663 :         for ( i = 0; i < i_max; i++ )
     778             :         {
     779     1730762 :             x[i] *= 0.5f;
     780     1730762 :             lf_deemph_factors[i] *= 0.5f;
     781             :         }
     782             :         /* 5. always expand two lines; lines could be at index 0 and 1! */
     783      436901 :         if ( i_max < i_max_old )
     784             :         {
     785          64 :             i_max = i_max_old;
     786             :         }
     787      436901 :         i = i_max + 1;
     788      436901 :         if ( x[i] < 0.0f )
     789             :         {
     790      192945 :             if ( x[i] > -4.0f )
     791             :             {
     792       68881 :                 lf_deemph_factors[i] *= 0.5f;
     793             :             }
     794      192945 :             x[i] = ( x[i] <= -4.0f ) ? x[i] + 2.0f : x[i] * 0.5f;
     795             :         }
     796             :         else
     797             :         {
     798      243956 :             if ( x[i] < 4.0f )
     799             :             {
     800      115928 :                 lf_deemph_factors[i] *= 0.5f;
     801             :             }
     802      243956 :             x[i] = ( x[i] >= 4.0f ) ? x[i] - 2.0f : x[i] * 0.5f;
     803             :         }
     804      436901 :         i++;
     805      436901 :         if ( x[i] < 0.0f )
     806             :         {
     807      186233 :             if ( x[i] > -4.0f )
     808             :             {
     809       73570 :                 lf_deemph_factors[i] *= 0.5f;
     810             :             }
     811      186233 :             x[i] = ( x[i] <= -4.0f ) ? x[i] + 2.0f : x[i] * 0.5f;
     812             :         }
     813             :         else
     814             :         {
     815      250668 :             if ( x[i] < 4.0f )
     816             :             {
     817      139102 :                 lf_deemph_factors[i] *= 0.5f;
     818             :             }
     819      250668 :             x[i] = ( x[i] >= 4.0f ) ? x[i] - 2.0f : x[i] * 0.5f;
     820             :         }
     821             :     }
     822             :     else
     823             :     {
     824       68415 :         PsychAdaptLowFreqDeemph( x, lpcGains, lf_deemph_factors );
     825             :     }
     826             : 
     827      505316 :     return;
     828             : }
     829             : 
     830             : 
     831             : /*-------------------------------------------------------------------*
     832             :  * tcx_noise_filling()
     833             :  *
     834             :  *
     835             :  *-------------------------------------------------------------------*/
     836             : 
     837     2709633 : void tcx_noise_filling(
     838             :     float *Q,
     839             :     const int16_t noiseFillSeed,
     840             :     const int16_t iFirstLine,
     841             :     const int16_t lowpassLine,
     842             :     const int16_t nTransWidth,
     843             :     const int16_t L_frame,
     844             :     const float tiltCompFactor,
     845             :     float fac_ns,
     846             :     uint8_t *infoTCXNoise,
     847             :     const int16_t element_mode /* i  : IVAS element mode                         */
     848             : )
     849             : {
     850             :     int16_t i, m, segmentOffset;
     851             :     int16_t win; /* window coefficient */
     852             :     Word16 seed;
     853             :     float tilt_factor, nrg, tmp1, tmp2;
     854             : 
     855             :     /* 16-bit random number generator seed for generating filled lines */
     856     2709633 :     seed = (Word16) noiseFillSeed;
     857             : 
     858     2709633 :     tilt_factor = (float) pow( max( 0.375f, tiltCompFactor ), 1.0f / (float) L_frame );
     859     2709633 :     fac_ns /= (float) ( nTransWidth * nTransWidth );
     860             : 
     861             :     /* find last nonzero line below iFirstLine, use it as start offset */
     862     2709633 :     i = iFirstLine;
     863             : 
     864     2709633 :     if ( element_mode == IVAS_CPE_MDCT ) /* ... but only in mono or parametric stereo since it may cause binaural unmasking in discrete stereo */
     865             :     {
     866     1846692 :         segmentOffset = i;
     867             :     }
     868             :     else
     869             :     {
     870     2557853 :         for ( ; i > ( iFirstLine >> 1 ); i-- )
     871             :         {
     872     2552950 :             if ( Q[i] != 0.0f )
     873             :             {
     874      858038 :                 break;
     875             :             }
     876             :         }
     877             : 
     878      862941 :         fac_ns *= (float) pow( tilt_factor, (float) i );
     879      862941 :         segmentOffset = ++i;
     880             :     }
     881             : 
     882     2709633 :     nrg = 1e-9f;
     883     2709633 :     win = 0;
     884             : 
     885  1173140130 :     for ( ; i < lowpassLine; i++ )
     886             :     {
     887  1170430497 :         fac_ns *= tilt_factor;
     888             : 
     889  1170430497 :         if ( Q[i] != 0.0f )
     890             :         {
     891   276622291 :             if ( win > 0 )
     892             :             {
     893             :                 /* RMS-normalize current noise-filled segment */
     894   129466023 :                 tmp1 = (float) sqrt( ( i - segmentOffset ) / nrg );
     895   129466023 :                 tmp2 = tmp1 * (float) nTransWidth;
     896             : 
     897   330629923 :                 for ( m = segmentOffset; m < i - win; m++ )
     898             :                 {
     899   201163900 :                     Q[m] *= tmp2;
     900             :                 }
     901             : 
     902   511679503 :                 for ( ; win > 0; win-- )
     903             :                 {
     904   382213480 :                     Q[m++] *= tmp1 * (float) win;
     905             :                 }
     906   129466023 :                 nrg = 1e-9f; /* start new segment: reset noise segment energy */
     907             :             }
     908   276622291 :             segmentOffset = i + 1;
     909             :         }
     910             :         else
     911             :         {
     912             :             /* line is zero, so fill line and update window and energy */
     913   893808206 :             if ( win < nTransWidth )
     914             :             {
     915   399779644 :                 win++;
     916             :             }
     917   893808206 :             tmp1 = (float) own_random( &seed );
     918   893808206 :             nrg += tmp1 * tmp1; /* sum up energy of current noise segment */
     919   893808206 :             Q[i] = tmp1 * (float) win * fac_ns;
     920             : 
     921   893808206 :             if ( infoTCXNoise )
     922             :             {
     923             :                 /* set noiseflags for IGF */
     924   498873828 :                 infoTCXNoise[i] = 1;
     925             :             }
     926             :         }
     927             :     }
     928             : 
     929     2709633 :     if ( win > 0 )
     930             :     {
     931             :         /* RMS-normalize uppermost noise-filled segment */
     932     2516728 :         tmp1 = (float) sqrt( ( lowpassLine - segmentOffset ) / nrg );
     933     2516728 :         tmp2 = tmp1 * (float) nTransWidth;
     934             : 
     935   312947554 :         for ( m = segmentOffset; m < lowpassLine; m++ )
     936             :         {
     937   310430826 :             Q[m] *= tmp2;
     938             :         }
     939             :     }
     940             : 
     941     2709633 :     return;
     942             : }
     943             : 
     944             : 
     945             : /*-------------------------------------------------------------------*
     946             :  * InitTnsConfigs()
     947             :  *
     948             :  *
     949             :  *-------------------------------------------------------------------*/
     950             : 
     951       89048 : void InitTnsConfigs(
     952             :     const int16_t bwidth,
     953             :     const int16_t L_frame,
     954             :     STnsConfig tnsConfig[2][2],
     955             :     const int16_t igfStopFreq,
     956             :     const int32_t total_brate,
     957             :     const int16_t element_mode,
     958             :     const int16_t MCT_flag )
     959             : {
     960       89048 :     if ( total_brate > ACELP_32k )
     961             :     {
     962       68408 :         InitTnsConfiguration( bwidth, L_frame / 2, &tnsConfig[0][0], igfStopFreq, total_brate, element_mode, MCT_flag );
     963             :     }
     964             : 
     965       89048 :     InitTnsConfiguration( bwidth, L_frame, &tnsConfig[1][0], igfStopFreq, total_brate, element_mode, MCT_flag );
     966             : 
     967       89048 :     InitTnsConfiguration( bwidth, L_frame + L_frame / 4, &tnsConfig[1][1], igfStopFreq, total_brate, element_mode, MCT_flag );
     968             : 
     969       89048 :     return;
     970             : }
     971             : 
     972             : 
     973             : /*-------------------------------------------------------------------*
     974             :  *  SetAllowTnsOnWhite
     975             :  *
     976             :  *  set TNS config flag for possible application of TNS in the whitened domain
     977             :  *-------------------------------------------------------------------*/
     978             : 
     979       89048 : void SetAllowTnsOnWhite(
     980             :     STnsConfig tnsConfig[2][2],  /* o  : updated TNS configurations */
     981             :     const int8_t allowTnsOnWhite /* i  : flag for TNS in whiteded domain mode */
     982             : )
     983             : {
     984       89048 :     tnsConfig[0][0].allowTnsOnWhite = allowTnsOnWhite;
     985       89048 :     tnsConfig[0][1].allowTnsOnWhite = allowTnsOnWhite;
     986       89048 :     tnsConfig[1][0].allowTnsOnWhite = allowTnsOnWhite;
     987       89048 :     tnsConfig[1][1].allowTnsOnWhite = allowTnsOnWhite;
     988             : 
     989       89048 :     return;
     990             : }
     991             : 
     992             : 
     993             : /*-------------------------------------------------------------------*
     994             :  * SetTnsConfig()
     995             :  *
     996             :  *
     997             :  *-------------------------------------------------------------------*/
     998             : 
     999     3642774 : void SetTnsConfig(
    1000             :     TCX_CONFIG_HANDLE hTcxCfg,
    1001             :     const int16_t isTCX20,
    1002             :     const int16_t isAfterACELP )
    1003             : {
    1004     3642774 :     hTcxCfg->pCurrentTnsConfig = &hTcxCfg->tnsConfig[isTCX20][isAfterACELP];
    1005     3642774 :     assert( hTcxCfg->pCurrentTnsConfig != NULL );
    1006             : 
    1007     3642774 :     return;
    1008             : }

Generated by: LCOV version 1.14