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

Generated by: LCOV version 1.14