LCOV - code coverage report
Current view: top level - lib_com - ivas_mdft_imdft_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main @ 5cb54858cb3178c8db39c9c2163d829984772878 Lines: 131 139 94.2 %
Date: 2025-11-05 02:09:30 Functions: 6 6 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             : #include <stdio.h>
      33             : 
      34             : #include <stdint.h>
      35             : #include "options.h"
      36             : #include "prot_fx.h"
      37             : #include "ivas_rom_com.h"
      38             : #include <assert.h>
      39             : #include "wmc_auto.h"
      40             : #include <stdint.h>
      41             : #include <math.h>
      42             : #include "debug.h"
      43             : #include "ivas_prot_fx.h"
      44             : 
      45             : /*-----------------------------------------------------------------------------------------*
      46             :  * Local constants
      47             :  *-----------------------------------------------------------------------------------------*/
      48             : 
      49             : #define IVAS_ONE_BY_960_Q37 143165577
      50             : #define IVAS_ONE_BY_640_Q37 214748365
      51             : #define IVAS_ONE_BY_320_Q37 429496730
      52             : #define IVAS_ONE_BY_240_Q37 572662306
      53             : #define IVAS_ONE_BY_160_Q37 858993459
      54             : #define IVAS_ONE_BY_80_Q37  1717986918
      55             : /*-----------------------------------------------------------------------------------------*
      56             :  * Function ivas_get_mdft_twid_factors()
      57             :  *
      58             :  * get twiddle tables for MDFT
      59             :  *-----------------------------------------------------------------------------------------*/
      60             : 
      61    10278271 : static void ivas_get_mdft_twid_factors_fx(
      62             :     const Word16 length,
      63             :     const Word32 **ppTwid // Q31
      64             : )
      65             : {
      66    10278271 :     SWITCH( length )
      67             :     {
      68      128223 :         case L_FRAME48k:
      69      128223 :             *ppTwid = &ivas_mdft_coeff_cos_twid_960_fx[0]; // Q31
      70      128223 :             BREAK;
      71      138723 :         case L_FRAME32k:
      72      138723 :             *ppTwid = &ivas_mdft_coeff_cos_twid_640_fx[0]; // Q31
      73      138723 :             BREAK;
      74       27240 :         case L_FRAME16k:
      75       27240 :             *ppTwid = &ivas_mdft_coeff_cos_twid_320_fx[0]; // Q31
      76       27240 :             BREAK;
      77     8008782 :         case IVAS_240_PT_LEN:
      78     8008782 :             *ppTwid = &ivas_mdft_coeff_cos_twid_240_fx[0]; // Q31
      79     8008782 :             BREAK;
      80     1233659 :         case IVAS_160_PT_LEN:
      81     1233659 :             *ppTwid = &ivas_mdft_coeff_cos_twid_160_fx[0]; // Q31
      82     1233659 :             BREAK;
      83      478022 :         case IVAS_120_PT_LEN:
      84      478022 :             *ppTwid = &ivas_mdft_coeff_cos_twid_120_fx[0]; // Q31
      85      478022 :             BREAK;
      86      263622 :         case IVAS_80_PT_LEN:
      87      263622 :             *ppTwid = &ivas_mdft_coeff_cos_twid_80_fx[0]; // Q31
      88      263622 :             BREAK;
      89           0 :         case IVAS_40_PT_LEN:
      90           0 :             *ppTwid = &ivas_mdft_coeff_cos_twid_40_fx[0]; // Q31
      91           0 :             BREAK;
      92           0 :         default:
      93           0 :             assert( !"Not supported FFT length!" );
      94             :             BREAK;
      95             :     }
      96             : 
      97    10278271 :     return;
      98             : }
      99             : /*-----------------------------------------------------------------------------------------*
     100             :  * Function ivas_get_imdft_twid_factors()
     101             :  *
     102             :  * get twiddle tables for IMDFT
     103             :  *-----------------------------------------------------------------------------------------*/
     104             : 
     105     1716481 : static void ivas_get_imdft_twid_factors_fx(
     106             :     const Word16 length,
     107             :     const Word32 **ppTwid // Q31
     108             : )
     109             : {
     110     1716481 :     SWITCH( length )
     111             :     {
     112      307578 :         case L_FRAME48k:
     113      307578 :             *ppTwid = ivas_mdft_coeff_cos_twid_960_fx; // Q31
     114      307578 :             BREAK;
     115      206773 :         case L_FRAME32k:
     116      206773 :             *ppTwid = ivas_mdft_coeff_cos_twid_640_fx; // Q31
     117      206773 :             BREAK;
     118       39740 :         case L_FRAME16k:
     119       39740 :             *ppTwid = ivas_mdft_coeff_cos_twid_320_fx; // Q31
     120       39740 :             BREAK;
     121     1141652 :         case 240:
     122     1141652 :             *ppTwid = ivas_mdft_coeff_cos_twid_240_fx; // Q31
     123     1141652 :             BREAK;
     124        7378 :         case 160:
     125        7378 :             *ppTwid = ivas_mdft_coeff_cos_twid_160_fx; // Q31
     126        7378 :             BREAK;
     127       13360 :         case 80:
     128       13360 :             *ppTwid = ivas_mdft_coeff_cos_twid_80_fx; // Q31
     129       13360 :             BREAK;
     130           0 :         default:
     131           0 :             assert( !"Not supported FFT length!" );
     132             :     }
     133             : 
     134     1716481 :     return;
     135             : }
     136             : 
     137     1716481 : static void get_one_by_length_fx(
     138             :     Word32 *one_by_length, // Q37
     139             :     const Word16 length )
     140             : {
     141     1716481 :     IF( EQ_16( length, L_FRAME48k ) )
     142             :     {
     143      307578 :         *one_by_length = IVAS_ONE_BY_960_Q37; // Q37
     144      307578 :         move32();
     145             :     }
     146     1408903 :     ELSE IF( EQ_16( length, L_FRAME32k ) )
     147             :     {
     148      206773 :         *one_by_length = IVAS_ONE_BY_640_Q37; // Q37
     149      206773 :         move32();
     150             :     }
     151     1202130 :     ELSE IF( EQ_16( length, L_FRAME16k ) )
     152             :     {
     153       39740 :         *one_by_length = IVAS_ONE_BY_320_Q37; // Q37
     154       39740 :         move32();
     155             :     }
     156     1162390 :     ELSE IF( EQ_16( length, IVAS_240_PT_LEN ) )
     157             :     {
     158     1141652 :         *one_by_length = IVAS_ONE_BY_240_Q37; // Q37
     159     1141652 :         move32();
     160             :     }
     161       20738 :     ELSE IF( EQ_16( length, IVAS_160_PT_LEN ) )
     162             :     {
     163        7378 :         *one_by_length = IVAS_ONE_BY_160_Q37; // Q37
     164        7378 :         move32();
     165             :     }
     166       13360 :     ELSE IF( EQ_16( length, IVAS_80_PT_LEN ) )
     167             :     {
     168       13360 :         *one_by_length = IVAS_ONE_BY_80_Q37; // Q37
     169       13360 :         move32();
     170             :     }
     171             :     ELSE
     172             :     {
     173           0 :         assert( !"Not supported FFT length!" );
     174             :     }
     175             : 
     176     1716481 :     return;
     177             : }
     178             : 
     179             : /*-----------------------------------------------------------------------------------------*
     180             :  * Function ivas_ifft_cplx1()
     181             :  *
     182             :  * Complex IFFT implementation using fft()
     183             :  *-----------------------------------------------------------------------------------------*/
     184             : 
     185     1716481 : static void ivas_ifft_cplx1_fx(
     186             :     Word32 *re, // inp: Qin -> out: Qin + 6
     187             :     Word32 *im, // inp: Qin -> out: Qin + 6
     188             :     const Word16 length )
     189             : {
     190             :     Word16 i;
     191             :     Word32 one_by_length, tmp;
     192     1716481 :     get_one_by_length_fx( &one_by_length, length ); // Q37
     193             : 
     194             :     /* re-arrange inputs to use fft as ifft */
     195     1716481 :     re[0] = Mpy_32_32( re[0], one_by_length ); // ( Qin + Q37 ) - Q31 -> Qin + 6
     196     1716481 :     move32();
     197     1716481 :     im[0] = Mpy_32_32( im[0], one_by_length ); // ( Qin + Q37 ) - Q31 -> Qin + 6
     198     1716481 :     move32();
     199             : 
     200   360002561 :     FOR( i = 1; i <= length >> 1; i++ )
     201             :     {
     202   358286080 :         tmp = Mpy_32_32( re[length - i], one_by_length );   /*stl_arr_index       Q: ( Qin + Q37 ) - Q31 -> Qin + 6 */
     203   358286080 :         re[length - i] = Mpy_32_32( re[i], one_by_length ); /*stl_arr_index       Q: ( Qin + Q37 ) - Q31 -> Qin + 6 */
     204   358286080 :         move32();
     205   358286080 :         re[i] = tmp;
     206   358286080 :         move32();
     207             : 
     208   358286080 :         tmp = Mpy_32_32( im[length - i], one_by_length );   /*stl_arr_index        Q: ( Qin + Q37 ) - Q31 -> Qin + 6 */
     209   358286080 :         im[length - i] = Mpy_32_32( im[i], one_by_length ); /*stl_arr_index        Q: ( Qin + Q37 ) - Q31 -> Qin + 6 */
     210   358286080 :         move32();
     211   358286080 :         im[i] = tmp; // Q: ( Qin + Q37 ) - Q31 -> Qin + 6
     212   358286080 :         move32();
     213             :     }
     214             : 
     215     1716481 :     fft_fx( re, im, length, 1 );
     216             : 
     217     1716481 :     return;
     218             : }
     219             : 
     220             : /*-----------------------------------------------------------------------------------------*
     221             : * Function ivas_mdft()
     222             : 
     223             : * MDFT implementation
     224             : *-----------------------------------------------------------------------------------------*/
     225             : 
     226    10278271 : void ivas_mdft_fx(
     227             :     const Word32 *pIn,         /* i  : input time-domain signal    Qin    */
     228             :     Word32 *pOut_re,           /* o  : Real part of MDFT signal    Qin    */
     229             :     Word32 *pOut_im,           /* o  : Imag. part of MDFT signal   Qin    */
     230             :     const Word16 input_length, /* i  : signal length                      */
     231             :     const Word16 mdft_length   /* i  : MDFT length                        */
     232             : )
     233             : {
     234             :     Word32 re[L_FRAME48k];
     235             :     Word32 im[L_FRAME48k];
     236             :     Word16 j, len_by_2;
     237             :     const Word32 *pTwid; // Q31
     238    10278271 :     len_by_2 = shr( mdft_length, 1 );
     239             : 
     240    10278271 :     ivas_get_mdft_twid_factors_fx( mdft_length, &pTwid );
     241    10278271 :     IF( EQ_16( mdft_length, input_length ) )
     242             :     {
     243  1372245441 :         FOR( j = 0; j < mdft_length; j++ )
     244             :         {
     245  1366513920 :             re[j] = Mpy_32_32( pIn[j], pTwid[j] ); // ( Qin + Q31 ) - Q31 -> Qin
     246  1366513920 :             move32();
     247  1366513920 :             im[j] = Mpy_32_32( L_negate( pIn[j] ), pTwid[mdft_length - j] ); // ( Qin + Q31 ) - Q31 -> Qin
     248  1366513920 :             move32();
     249             :         }
     250             :     }
     251             :     ELSE
     252             :     {
     253  1056571950 :         FOR( j = 0; j < mdft_length; j++ )
     254             :         {
     255  1052025200 :             re[j] = Msub_32_32( Mpy_32_32( pIn[j], pTwid[j] ), pIn[add( mdft_length, j )], pTwid[mdft_length - j] ); // ( Qin + Q31 ) - Q31 -> Qin
     256  1052025200 :             move32();
     257  1052025200 :             im[j] = Msub_32_32( Mpy_32_32( L_negate( pIn[j] ), pTwid[mdft_length - j] ), pIn[mdft_length + j], pTwid[j] ); // ( Qin + Q31 ) - Q31 -> Qin
     258  1052025200 :             move32();
     259             :         }
     260             :     }
     261             : 
     262    10278271 :     fft_fx( re, im, mdft_length, 1 );
     263  1219547831 :     FOR( j = 0; j < len_by_2; j++ )
     264             :     {
     265  1209269560 :         pOut_re[2 * j] = re[j]; // Qin
     266  1209269560 :         move32();
     267  1209269560 :         pOut_re[2 * j + 1] = re[mdft_length - j - 1]; // Qin
     268  1209269560 :         move32();
     269             : 
     270  1209269560 :         pOut_im[2 * j] = im[j]; // Qin
     271  1209269560 :         move32();
     272  1209269560 :         pOut_im[2 * j + 1] = L_negate( im[mdft_length - j - 1] ); // Qin
     273  1209269560 :         move32();
     274             :     }
     275    10278271 :     return;
     276             : }
     277             : 
     278             : 
     279             : /*-----------------------------------------------------------------------------------------*
     280             :  * Function ivas_imdft()
     281             :  *
     282             :  * iMDFT implementation
     283             :  * out buffer needs to have 2*length worth memory
     284             :  *-----------------------------------------------------------------------------------------*/
     285             : 
     286     1716481 : void ivas_imdft_fx(
     287             :     const Word32 *pRe,  /* i  : Real part of MDFT signal      Qin          */
     288             :     const Word32 *pIm,  /* i  : Imag. part of MDFT signal     Qin          */
     289             :     Word32 *pOut,       /* o  : output time-domain signal     Qin        */
     290             :     const Word16 length /* i  : signal length                              */
     291             : )
     292             : {
     293     1716481 :     Word32 *re_tmp = pOut;
     294     1716481 :     Word32 *im_tmp = pOut + length;
     295             :     Word32 tmp;
     296             :     Word16 j;
     297             :     Word16 len_by_2;
     298             :     const Word32 *pTwid; // Q31
     299     1716481 :     len_by_2 = shr( length, 1 );
     300             : 
     301     1716481 :     ivas_get_imdft_twid_factors_fx( length, &pTwid );
     302             : 
     303   360002561 :     FOR( j = 0; j < len_by_2; j++ )
     304             :     {
     305   358286080 :         re_tmp[j] = pRe[2 * j]; // Qin
     306   358286080 :         move32();
     307   358286080 :         re_tmp[j + len_by_2] = pRe[length - 2 * j - 1]; // Qin
     308   358286080 :         move32();
     309             : 
     310   358286080 :         im_tmp[j] = pIm[2 * j]; // Qin
     311   358286080 :         move32();
     312   358286080 :         im_tmp[j + len_by_2] = L_negate( pIm[length - 2 * j - 1] ); // Qin
     313   358286080 :         move32();
     314             :     }
     315             : 
     316     1716481 :     ivas_ifft_cplx1_fx( re_tmp, im_tmp, length );
     317             :     // re_tmp: Qin + 6
     318             :     // im_tmp: Qin + 6
     319             : 
     320   718288641 :     FOR( j = 0; j < length; j++ )
     321             :     {
     322   716572160 :         tmp = Msub_32_32( Mpy_32_32( L_shr( re_tmp[j], Q6 ), pTwid[j] ), L_shr( im_tmp[j], Q6 ), pTwid[length - j] );                   // ( ( Qin + Q6 - Q6 ) + Q31 ) - Q31 -> Qin
     323   716572160 :         im_tmp[j] = L_negate( Madd_32_32( Mpy_32_32( L_shr( re_tmp[j], Q6 ), pTwid[length - j] ), L_shr( im_tmp[j], Q6 ), pTwid[j] ) ); // ( ( Qin + Q6 - Q6 ) + Q31 ) - Q31 -> Qin
     324   716572160 :         move32();
     325   716572160 :         re_tmp[j] = tmp; // ( ( Qin + Q6 - Q6 ) + Q31 ) - Q31 -> Qin
     326   716572160 :         move32();
     327             :     }
     328     1716481 :     return;
     329             : }

Generated by: LCOV version 1.14