LCOV - code coverage report
Current view: top level - lib_com - ivas_mdct_imdct_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main enc/dec/rend @ 3b2f07138c61dcf997bbf4165d0882f794b2995f Lines: 147 157 93.6 %
Date: 2025-05-03 01:55:50 Functions: 8 8 100.0 %

          Line data    Source code
       1             : /******************************************************************************************************
       2             : 
       3             :    (C) 2022-2025 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
       4             :    Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
       5             :    Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
       6             :    Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
       7             :    contributors to this repository. All Rights Reserved.
       8             : 
       9             :    This software is protected by copyright law and by international treaties.
      10             :    The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
      11             :    Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
      12             :    Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
      13             :    Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
      14             :    contributors to this repository retain full ownership rights in their respective contributions in
      15             :    the software. This notice grants no license of any kind, including but not limited to patent
      16             :    license, nor is any license granted by implication, estoppel or otherwise.
      17             : 
      18             :    Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
      19             :    contributions.
      20             : 
      21             :    This software is provided "AS IS", without any express or implied warranties. The software is in the
      22             :    development stage. It is intended exclusively for experts who have experience with such software and
      23             :    solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
      24             :    and fitness for a particular purpose are hereby disclaimed and excluded.
      25             : 
      26             :    Any dispute, controversy or claim arising under or in relation to providing this software shall be
      27             :    submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
      28             :    accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
      29             :    the United Nations Convention on Contracts on the International Sales of Goods.
      30             : 
      31             : *******************************************************************************************************/
      32             : 
      33             : #include <stdint.h>
      34             : #include "options.h"
      35             : #include "prot_fx.h"
      36             : #include "ivas_prot_fx.h"
      37             : #include "ivas_rom_com_fx.h"
      38             : #ifdef DEBUGGING
      39             : #include "debug.h"
      40             : #endif
      41             : #include "ivas_stat_com.h"
      42             : #include "wmc_auto.h"
      43             : 
      44             : /*------------------------------------------------------------------------------------------*
      45             :  * Local constants
      46             :  *------------------------------------------------------------------------------------------*/
      47             : 
      48             : #define IVAS_MDCT_SCALING_GAIN_48k_Q31 0x00001086 /* 1.9699011974118126e-06f */
      49             : #define IVAS_MDCT_SCALING_GAIN_48k_Q46 0x08432A51
      50             : #define IVAS_MDCT_SCALING_GAIN_32k_Q31 0x000018C9 /* 2.9548517961177197e-06f */
      51             : #define IVAS_MDCT_SCALING_GAIN_32k_Q46 0x0C64BF7A
      52             : #define IVAS_MDCT_SCALING_GAIN_16k_Q31 0X00003193 /* 5.909703592235439e-06f */
      53             : #define IVAS_MDCT_SCALING_GAIN_16k_Q46 0x18C97EF4
      54             : 
      55             : 
      56             : #define IVAS_ONE_BY_IMDCT_SCALING_GAIN_Q16 0x08432A51 /* 1 / 2115.165304808f */
      57             : 
      58             : 
      59             : /*-----------------------------------------------------------------------------------------*
      60             :  * Function ivas_tda_fx()
      61             :  *
      62             :  * Time domain aliasing
      63             :  *-----------------------------------------------------------------------------------------*/
      64             : 
      65         252 : void ivas_tda_fx(
      66             :     const Word32 *pIn,  /* i  : time domain buffer of size 2*length  Q10*/
      67             :     Word32 *pOut,       /* o  : time domain buffer of size length  Q10 */
      68             :     const Word16 length /* i  : length of time alised signal buffer   Q0*/
      69             : )
      70             : {
      71             :     Word16 i;
      72             :     Word16 len_by_2;
      73         252 :     len_by_2 = shr( length, 1 );
      74             : 
      75       60572 :     FOR( i = 0; i < len_by_2; i++ )
      76             :     {
      77       60320 :         pOut[i] = L_sub( pIn[len_by_2 + i], pIn[len_by_2 - i - 1] ); /* Q10*/
      78       60320 :         move32();
      79       60320 :         pOut[len_by_2 + i] = L_add( pIn[length * 2 - i - 1], pIn[length + i] ); /* Q10*/
      80       60320 :         move32();
      81             :     }
      82             : 
      83         252 :     return;
      84             : }
      85             : 
      86             : 
      87             : /*-----------------------------------------------------------------------------------------*
      88             :  * Function ivas_dct_windowing_fx()
      89             :  *
      90             :  * Windowing block, input is passed through Fielder window
      91             :  *-----------------------------------------------------------------------------------------*/
      92             : 
      93       53092 : void ivas_dct_windowing_fx(
      94             :     const Word16 fade_len,        /*Q0*/
      95             :     const Word16 full_len,        /*Q0*/
      96             :     const Word16 dct_len,         /*Q0*/
      97             :     const Word16 zero_pad_len,    /*Q0*/
      98             :     const Word32 *pWindow_coeffs, /*Q31*/
      99             :     const Word16 frame_len,       /*Q0*/
     100             :     Word32 *pOut_buf,             // Q10
     101             :     Word32 *pBuffer_prev,         // Q10
     102             :     Word32 *pTemp_lfe )           // Q10
     103             : {
     104             :     Word16 i;
     105             :     Word16 rem_len;
     106       53092 :     rem_len = 0;
     107       53092 :     move16();
     108             : 
     109       53092 :     Copy32( pBuffer_prev, pOut_buf + zero_pad_len, fade_len ); // Q10
     110             : 
     111       53092 :     Copy32( pTemp_lfe, ( pOut_buf + add( fade_len, zero_pad_len ) ), dct_len ); // Q10
     112             : 
     113       53092 :     set32_fx( pOut_buf, 0, zero_pad_len );
     114             : 
     115       53092 :     Copy32( ( pOut_buf + sub( full_len, fade_len ) ), pBuffer_prev, fade_len ); // Q10
     116             : 
     117    20322404 :     FOR( i = 0; i < fade_len; i++ )
     118             :     {
     119    20269312 :         pOut_buf[zero_pad_len + i] = Mult_32_32( pOut_buf[zero_pad_len + i], pWindow_coeffs[i] ); // Q10
     120    20269312 :         move32();
     121             :     }
     122             : 
     123       53092 :     rem_len = sub( full_len, ( add( i_mult( zero_pad_len, 3 ), fade_len ) ) );
     124             : 
     125    20322404 :     FOR( i = 0; i < rem_len; i++ )
     126             :     {
     127    20269312 :         pOut_buf[zero_pad_len * 3 + fade_len + i] = Mult_32_32( pOut_buf[zero_pad_len * 3 + fade_len + i], pWindow_coeffs[fade_len - i - 1] ); // Q10
     128    20269312 :         move32();
     129             :     }
     130             : 
     131       53092 :     set32_fx( &pOut_buf[full_len], 0, sub( frame_len, full_len ) );
     132             : 
     133       53092 :     return;
     134             : }
     135             : 
     136             : 
     137             : /*-----------------------------------------------------------------------------------------*
     138             :  * Function ivas_mdct_fx()
     139             :  *
     140             :  * MDCT implementation
     141             :  *-----------------------------------------------------------------------------------------*/
     142             : 
     143       52840 : void ivas_mdct_fx(
     144             :     const Word32 *pIn,   // q_out
     145             :     Word32 *pOut,        // q_out
     146             :     const Word16 length, // Q0
     147             :     Word16 *q_out )
     148             : {
     149             :     const Word16 *pTwid_re, *pTwid_im;
     150             :     Word16 i, len_by_2;
     151             :     Word32 re[IVAS_480_PT_LEN], im[IVAS_480_PT_LEN];
     152             :     Word32 ivas_mdct_scaling_gain;
     153             : 
     154       52840 :     len_by_2 = shr( length, 1 );
     155       52840 :     ivas_mdct_scaling_gain = ivas_get_mdct_scaling_gain_fx( len_by_2 ); // Q46
     156             : 
     157       52840 :     ivas_get_twid_factors_fx1( length, &pTwid_re, &pTwid_im );
     158             : 
     159    12660840 :     FOR( i = 0; i < len_by_2; i++ )
     160             :     {
     161    12608000 :         pOut[i] = L_sub( pIn[len_by_2 + i], pIn[len_by_2 - i - 1] ); // q_out
     162    12608000 :         move32();
     163    12608000 :         pOut[len_by_2 + i] = L_add( pIn[length * 2 - i - 1], pIn[length + i] ); // q_out
     164    12608000 :         move32();
     165             :     }
     166             : 
     167    12660840 :     FOR( i = 0; i < len_by_2; i++ )
     168             :     {
     169    12608000 :         re[i] = L_negate( L_add( Mpy_32_16_1( pOut[2 * i], pTwid_re[i] ), Mpy_32_16_1( pOut[length - 1 - 2 * i], pTwid_im[i] ) ) ); // q_out
     170    12608000 :         move32();
     171    12608000 :         im[i] = L_sub( Mpy_32_16_1( pOut[length - 1 - 2 * i], pTwid_re[i] ), Mpy_32_16_1( pOut[2 * i], pTwid_im[i] ) ); // q_out
     172    12608000 :         move32();
     173             :     }
     174             : 
     175       52840 :     DoFFT_fx( &re[0], &im[0], len_by_2 );
     176             : 
     177    12660840 :     FOR( i = 0; i < len_by_2; i++ )
     178             :     {
     179    12608000 :         re[i] = Mult_32_32( re[i], ivas_mdct_scaling_gain ); // q_out+15
     180    12608000 :         move32();
     181    12608000 :         im[i] = Mult_32_32( im[i], ivas_mdct_scaling_gain ); // q_out +15
     182    12608000 :         move32();
     183             :     }
     184       52840 :     *q_out = add( *q_out, Q15 );
     185       52840 :     move16();
     186    12660840 :     FOR( i = 0; i < len_by_2; i++ )
     187             :     {
     188             :         Word32 tmp;
     189    12608000 :         tmp = L_sub( Mpy_32_16_1( re[i], pTwid_re[i] ), Mpy_32_16_1( im[i], pTwid_im[i] ) );   // q_out
     190    12608000 :         im[i] = L_add( Mpy_32_16_1( im[i], pTwid_re[i] ), Mpy_32_16_1( re[i], pTwid_im[i] ) ); // q_out
     191    12608000 :         move32();
     192    12608000 :         re[i] = tmp; // q_out
     193    12608000 :         move32();
     194             :     }
     195             : 
     196    12660840 :     FOR( i = 0; i < len_by_2; i++ )
     197             :     {
     198    12608000 :         pOut[length - 2 * i - 1] = re[i]; // q_out
     199    12608000 :         move32();
     200    12608000 :         pOut[2 * i] = im[i]; // q_out
     201    12608000 :         move32();
     202             :     }
     203             : 
     204       52840 :     return;
     205             : }
     206             : 
     207             : 
     208             : /*-----------------------------------------------------------------------------------------*
     209             :  * Function ivas_ifft_cplx()
     210             :  *
     211             :  * Complex IFFT implementation using DoFFT
     212             :  *-----------------------------------------------------------------------------------------*/
     213             : 
     214       49922 : static void ivas_ifft_cplx(
     215             :     Word32 *re, /*Q24*/
     216             :     Word32 *im, /*Q24*/
     217             :     const Word16 length /*Q0*/ )
     218             : {
     219             :     Word16 i;
     220             :     Word32 ivas_imdct_one_by_powergain;
     221       49922 :     ivas_imdct_one_by_powergain = IVAS_ONE_BY_IMDCT_SCALING_GAIN_Q16; // Q16
     222       49922 :     move32();
     223             :     /*re-arrange inputs to use fft as ifft */
     224       49922 :     re[0] = Mult_32_32( re[0], ivas_imdct_one_by_powergain ); // Q9
     225       49922 :     move32();
     226       49922 :     im[0] = Mult_32_32( im[0], ivas_imdct_one_by_powergain ); // Q9
     227       49922 :     move32();
     228             : 
     229     5734242 :     FOR( i = 1; i <= ( length / 2 ); i++ )
     230             :     {
     231             :         Word32 tmp;
     232     5684320 :         tmp = Mult_32_32( re[length - i], ivas_imdct_one_by_powergain );   // Q9
     233     5684320 :         re[length - i] = Mult_32_32( re[i], ivas_imdct_one_by_powergain ); // Q9
     234     5684320 :         move32();
     235     5684320 :         re[i] = tmp; //-Q6
     236     5684320 :         move32();
     237             : 
     238     5684320 :         tmp = Mult_32_32( im[length - i], ivas_imdct_one_by_powergain );   // Q9
     239     5684320 :         im[length - i] = Mult_32_32( im[i], ivas_imdct_one_by_powergain ); // Q9
     240     5684320 :         move32();
     241     5684320 :         im[i] = tmp; // Q9
     242     5684320 :         move32();
     243             :     }
     244             : 
     245       49922 :     DoFFT_fx( re, im, length );
     246             : 
     247       49922 :     return;
     248             : }
     249             : 
     250             : 
     251             : /*-----------------------------------------------------------------------------------------*
     252             :  * Function ivas_itda()
     253             :  *
     254             :  * Inverse time domain alias implementation
     255             :  *-----------------------------------------------------------------------------------------*/
     256             : 
     257         252 : void ivas_itda_fx(
     258             :     const Word32 *re,   /* i  : time alised signal after IDCT      Q24 */
     259             :     Word32 *pOut,       /* o  : time domain buffer of size 2*length */
     260             :     const Word16 length /* i  : length of time alised signal buffer Q0 */
     261             : )
     262             : {
     263             :     Word16 i;
     264             :     Word16 len_by_2;
     265         252 :     len_by_2 = shr( length, 1 );
     266             : 
     267       60572 :     FOR( i = 0; i < len_by_2; i++ )
     268             :     {
     269       60320 :         pOut[i] = L_negate( re[len_by_2 - i - 1] ); /*Q24 */
     270       60320 :         move32();
     271       60320 :         pOut[add( len_by_2, i )] = re[i]; /*Q24 */
     272       60320 :         move32();
     273       60320 :         pOut[add( length, i )] = re[len_by_2 + i]; /*Q24 */
     274       60320 :         move32();
     275       60320 :         pOut[3 * len_by_2 + i] = re[length - i - 1]; /*Q24 */
     276       60320 :         move32();
     277             :     }
     278             : 
     279         252 :     return;
     280             : }
     281             : 
     282             : 
     283             : /*-----------------------------------------------------------------------------------------*
     284             :  * Function ivas_imdct_fx()
     285             :  *
     286             :  * IMDCT implementation
     287             :  *-----------------------------------------------------------------------------------------*/
     288             : 
     289       49922 : void ivas_imdct_fx(
     290             :     const Word32 *pIn, // Q24
     291             :     Word32 *pOut,      // q_out Q9
     292             :     const Word16 length /*Q0*/,
     293             :     Word16 *q_out )
     294             : {
     295             :     const Word16 *pTwid_re, *pTwid_im;
     296             :     Word16 len_by_2;
     297             :     Word16 i;
     298             :     Word32 re[IVAS_480_PT_LEN];
     299             :     Word32 im[IVAS_480_PT_LEN];
     300       49922 :     len_by_2 = shr( length, 1 );
     301             : 
     302       49922 :     ivas_get_twid_factors_fx1( length, &pTwid_re, &pTwid_im );
     303             : 
     304    11418562 :     FOR( i = 0; i < len_by_2; i++ )
     305             :     {
     306    11368640 :         re[i] = L_add( Mpy_32_16_1( pIn[length - 2 * i - 1], pTwid_re[i] ), Mpy_32_16_1( pIn[2 * i], pTwid_im[i] ) ); /*stl_arr_index  Q24*/
     307    11368640 :         move32();
     308    11368640 :         im[i] = L_sub( Mpy_32_16_1( pIn[2 * i], pTwid_re[i] ), Mpy_32_16_1( pIn[length - 2 * i - 1], pTwid_im[i] ) ); /*stl_arr_index Q24*/
     309    11368640 :         move32();
     310             :     }
     311             : 
     312       49922 :     ivas_ifft_cplx( &re[0], &im[0], len_by_2 );
     313       49922 :     IF( len_by_2 > 0 )
     314             :     {
     315       49922 :         *q_out = sub( *q_out, Q15 );
     316       49922 :         move16();
     317             :     }
     318             : 
     319    11418562 :     FOR( i = 0; i < len_by_2; i++ )
     320             :     {
     321             :         Word32 tmp;
     322    11368640 :         tmp = L_add( Mpy_32_16_1( re[i], pTwid_re[i] ), Mpy_32_16_1( im[i], pTwid_im[i] ) );   // Q9
     323    11368640 :         im[i] = L_sub( Mpy_32_16_1( im[i], pTwid_re[i] ), Mpy_32_16_1( re[i], pTwid_im[i] ) ); // Q9
     324    11368640 :         move32();
     325    11368640 :         re[i] = tmp; // Q9
     326    11368640 :         move32();
     327             :     }
     328             : 
     329    11418562 :     FOR( i = ( len_by_2 - 1 ); i >= 0; i-- )
     330             :     {
     331    11368640 :         re[2 * i + 1] = im[( len_by_2 - 1 ) - i]; // Q9
     332    11368640 :         move32();
     333    11368640 :         re[2 * i] = L_negate( re[i] ); // Q9
     334    11368640 :         move32();
     335             :     }
     336             : 
     337    11418562 :     FOR( i = 0; i < len_by_2; i++ )
     338             :     {
     339    11368640 :         pOut[i] = L_negate( re[len_by_2 - i - 1] ); // Q9
     340    11368640 :         move32();
     341    11368640 :         pOut[len_by_2 + i] = re[i]; // Q9
     342    11368640 :         move32();
     343    11368640 :         pOut[length + i] = re[len_by_2 + i]; // Q9
     344    11368640 :         move32();
     345    11368640 :         pOut[3 * len_by_2 + i] = re[length - i - 1]; // Q9
     346    11368640 :         move32();
     347             :     }
     348             : 
     349       49922 :     return;
     350             : }
     351             : 
     352             : 
     353             : /*-----------------------------------------------------------------------------------------*
     354             :  * Function ivas_get_twid_factors_fx1()
     355             :  *
     356             :  * Sets/Maps the fft twiddle tables based on fft length
     357             :  *-----------------------------------------------------------------------------------------*/
     358      102762 : void ivas_get_twid_factors_fx1(
     359             :     const Word16 length,      // Q0
     360             :     const Word16 **pTwid_re,  // Q15
     361             :     const Word16 **pTwid_im ) // Q15
     362             : {
     363      102762 :     IF( EQ_16( length, 480 ) )
     364             :     {
     365       97824 :         *pTwid_re = (const Word16 *) &ivas_cos_twiddle_480_fx[0]; // Q15
     366       97824 :         *pTwid_im = (const Word16 *) &ivas_sin_twiddle_480_fx[0]; // Q15
     367             :     }
     368        4938 :     ELSE IF( EQ_16( length, 320 ) )
     369             :     {
     370        1298 :         *pTwid_re = (const Word16 *) &ivas_cos_twiddle_320_fx[0]; // Q15
     371        1298 :         *pTwid_im = (const Word16 *) &ivas_sin_twiddle_320_fx[0]; // Q15
     372             :     }
     373        3640 :     ELSE IF( EQ_16( length, 160 ) )
     374             :     {
     375        3640 :         *pTwid_re = (const Word16 *) &ivas_cos_twiddle_160_fx[0]; // Q15
     376        3640 :         *pTwid_im = (const Word16 *) &ivas_sin_twiddle_160_fx[0]; // Q15
     377             :     }
     378           0 :     ELSE IF( EQ_16( length, 80 ) )
     379             :     {
     380           0 :         *pTwid_re = (const Word16 *) &ivas_cos_twiddle_80_fx[0]; // Q15
     381           0 :         *pTwid_im = (const Word16 *) &ivas_sin_twiddle_80_fx[0]; // Q15
     382             :     }
     383             :     ELSE
     384             :     {
     385           0 :         assert( !"Not supported FFT length!" );
     386             :     }
     387             : 
     388      102762 :     return;
     389             : }
     390             : 
     391             : /*-----------------------------------------------------------------------------------------*
     392             :  * Function ivas_get_mdct_scaling_gain_fx()
     393             :  *
     394             :  * Get scaling gain for MDCT functions
     395             :  *-----------------------------------------------------------------------------------------*/
     396             : 
     397       52840 : Word32 ivas_get_mdct_scaling_gain_fx(
     398             :     const Word16 dct_len_by_2 )
     399             : {
     400             :     Word32 gain;
     401       52840 :     gain = 0;
     402       52840 :     move32();
     403             : 
     404       52840 :     SWITCH( dct_len_by_2 )
     405             :     {
     406       51920 :         case L_FRAME48k >> 2:
     407             :         {
     408       51920 :             gain = IVAS_MDCT_SCALING_GAIN_48k_Q46; /*Q46*/
     409       51920 :             move32();
     410       51920 :             BREAK;
     411             :         }
     412         920 :         case L_FRAME32k >> 2:
     413             :         {
     414         920 :             gain = IVAS_MDCT_SCALING_GAIN_32k_Q46; /*Q46*/
     415         920 :             move32();
     416         920 :             BREAK;
     417             :         }
     418           0 :         case L_FRAME16k >> 2:
     419             :         {
     420           0 :             gain = IVAS_MDCT_SCALING_GAIN_16k_Q46; /*Q46*/
     421           0 :             move32();
     422           0 :             BREAK;
     423             :         }
     424           0 :         default:
     425             :         {
     426           0 :             assert( !"Unsupported frame length!" );
     427             :             BREAK;
     428             :         }
     429             :     }
     430             : 
     431       52840 :     return gain;
     432             : }

Generated by: LCOV version 1.14