diff --git a/Workspace_msvc/Workspace_msvc.sln b/Workspace_msvc/Workspace_msvc.sln
new file mode 100644
index 0000000000000000000000000000000000000000..ab6915398db805dbda1dd66710e4b7221191863e
--- /dev/null
+++ b/Workspace_msvc/Workspace_msvc.sln
@@ -0,0 +1,60 @@
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.33027.164
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "common", "common.vcxproj", "{39EC200D-7795-4FF8-B214-B24EDA5526AE}"
+ ProjectSection(ProjectDependencies) = postProject
+ {54509728-928B-44D9-A118-A6F92F08B34F} = {54509728-928B-44D9-A118-A6F92F08B34F}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "evs_dec", "evs_dec.vcxproj", "{E822DDAF-0F5F-4CD0-A694-38AE69DE74D3}"
+ ProjectSection(ProjectDependencies) = postProject
+ {54509728-928B-44D9-A118-A6F92F08B34F} = {54509728-928B-44D9-A118-A6F92F08B34F}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "evs_enc", "evs_enc.vcxproj", "{824DA4CF-06F0-45C9-929A-8792F0E19C3E}"
+ ProjectSection(ProjectDependencies) = postProject
+ {54509728-928B-44D9-A118-A6F92F08B34F} = {54509728-928B-44D9-A118-A6F92F08B34F}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "debug", "debug.vcxproj", "{54509728-928B-44D9-A118-A6F92F08B34F}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ Unittests|Win32 = Unittests|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {39EC200D-7795-4FF8-B214-B24EDA5526AE}.Debug|Win32.ActiveCfg = Debug|Win32
+ {39EC200D-7795-4FF8-B214-B24EDA5526AE}.Debug|Win32.Build.0 = Debug|Win32
+ {39EC200D-7795-4FF8-B214-B24EDA5526AE}.Release|Win32.ActiveCfg = Release|Win32
+ {39EC200D-7795-4FF8-B214-B24EDA5526AE}.Release|Win32.Build.0 = Release|Win32
+ {39EC200D-7795-4FF8-B214-B24EDA5526AE}.Unittests|Win32.ActiveCfg = Release|Win32
+ {39EC200D-7795-4FF8-B214-B24EDA5526AE}.Unittests|Win32.Build.0 = Release|Win32
+ {E822DDAF-0F5F-4CD0-A694-38AE69DE74D3}.Debug|Win32.ActiveCfg = Debug|Win32
+ {E822DDAF-0F5F-4CD0-A694-38AE69DE74D3}.Debug|Win32.Build.0 = Debug|Win32
+ {E822DDAF-0F5F-4CD0-A694-38AE69DE74D3}.Release|Win32.ActiveCfg = Release|Win32
+ {E822DDAF-0F5F-4CD0-A694-38AE69DE74D3}.Release|Win32.Build.0 = Release|Win32
+ {E822DDAF-0F5F-4CD0-A694-38AE69DE74D3}.Unittests|Win32.ActiveCfg = Release|Win32
+ {E822DDAF-0F5F-4CD0-A694-38AE69DE74D3}.Unittests|Win32.Build.0 = Release|Win32
+ {824DA4CF-06F0-45C9-929A-8792F0E19C3E}.Debug|Win32.ActiveCfg = Debug|Win32
+ {824DA4CF-06F0-45C9-929A-8792F0E19C3E}.Debug|Win32.Build.0 = Debug|Win32
+ {824DA4CF-06F0-45C9-929A-8792F0E19C3E}.Release|Win32.ActiveCfg = Release|Win32
+ {824DA4CF-06F0-45C9-929A-8792F0E19C3E}.Release|Win32.Build.0 = Release|Win32
+ {824DA4CF-06F0-45C9-929A-8792F0E19C3E}.Unittests|Win32.ActiveCfg = Release|Win32
+ {824DA4CF-06F0-45C9-929A-8792F0E19C3E}.Unittests|Win32.Build.0 = Release|Win32
+ {54509728-928B-44D9-A118-A6F92F08B34F}.Debug|Win32.ActiveCfg = Debug|Win32
+ {54509728-928B-44D9-A118-A6F92F08B34F}.Debug|Win32.Build.0 = Debug|Win32
+ {54509728-928B-44D9-A118-A6F92F08B34F}.Release|Win32.ActiveCfg = Release|Win32
+ {54509728-928B-44D9-A118-A6F92F08B34F}.Release|Win32.Build.0 = Release|Win32
+ {54509728-928B-44D9-A118-A6F92F08B34F}.Unittests|Win32.ActiveCfg = Unittests|Win32
+ {54509728-928B-44D9-A118-A6F92F08B34F}.Unittests|Win32.Build.0 = Unittests|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {FE9056FB-CCA7-4E31-A173-2A2DEB724C18}
+ EndGlobalSection
+EndGlobal
diff --git a/Workspace_msvc/common.vcxproj b/Workspace_msvc/common.vcxproj
new file mode 100644
index 0000000000000000000000000000000000000000..f29349cae02d2b1d21f717112df9e5d348010498
--- /dev/null
+++ b/Workspace_msvc/common.vcxproj
@@ -0,0 +1,276 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+
+ {39EC200D-7795-4FF8-B214-B24EDA5526AE}
+ common
+ 10.0
+
+
+
+ StaticLibrary
+ false
+ MultiByte
+ v142
+
+
+ StaticLibrary
+ false
+ MultiByte
+ v142
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ProjectFileVersion>15.0.26228.10
+
+
+ .\Debug_Common\
+ .\Debug_Common\
+
+
+ .\Release_Common\
+ .\Release_Common\
+
+
+
+
+
+
+ Disabled
+ ..\lib_enc;..\lib_dec;..\lib_com;..\lib_debug;%(AdditionalIncludeDirectories)
+ _CRT_SECURE_NO_WARNINGS;WIN32;%(PreprocessorDefinitions)
+
+ EnableFastChecks
+ MultiThreadedDebug
+
+
+ $(IntDir)commonlib.pdb
+ Level4
+ true
+ OldStyle
+ Default
+ 4310;4244;%(DisableSpecificWarnings)
+ Column
+
+
+ _DEBUG;%(PreprocessorDefinitions)
+ 0x0c0c
+
+
+ WS2_32.lib;%(AdditionalDependencies)
+ $(OutDir)$(ProjectName).lib
+ true
+
+
+
+
+
+
+
+ MaxSpeed
+ AnySuitable
+ false
+ Neither
+ false
+ false
+ ..\lib_enc;..\lib_dec;..\lib_com;%(AdditionalIncludeDirectories)
+ _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
+ true
+
+ Default
+ MultiThreaded
+ true
+
+
+ $(IntDir)commonlib.pdb
+ Level4
+ true
+
+ Default
+ 4100;4244;4310;%(DisableSpecificWarnings)
+
+
+ NDEBUG;%(PreprocessorDefinitions)
+ 0x0c0c
+
+
+ WS2_32.lib;%(AdditionalDependencies)
+ $(OutDir)$(ProjectName).lib
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {54509728-928b-44d9-a118-a6f92f08b34f}
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Workspace_msvc/debug.vcxproj b/Workspace_msvc/debug.vcxproj
new file mode 100644
index 0000000000000000000000000000000000000000..8e23671bf3f56cf5ba3171313a62ed0c26249e84
--- /dev/null
+++ b/Workspace_msvc/debug.vcxproj
@@ -0,0 +1,158 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Unittests
+ Win32
+
+
+
+ {54509728-928B-44D9-A118-A6F92F08B34F}
+ debug
+ 10.0.17763.0
+
+
+
+ StaticLibrary
+ v141
+ MultiByte
+
+
+ StaticLibrary
+ v142
+ MultiByte
+
+
+ StaticLibrary
+ v142
+ MultiByte
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ProjectFileVersion>15.0.27428.2015
+
+
+ .\Debug_Debug\
+ .\Debug_Debug\
+ lib_debug
+
+
+ .\Debug_$(ProjectName)\
+ .\Debug_$(ProjectName)\
+ libivasdebug
+
+
+ .\Release_$(ProjectName)\
+ .\Release_$(ProjectName)\
+ libivasdebug
+
+
+
+
+
+
+ Disabled
+ ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_rend;%(AdditionalIncludeDirectories)
+ _CRT_SECURE_NO_WARNINGS;$(Macros);%(PreprocessorDefinitions)
+ false
+
+ EnableFastChecks
+ MultiThreadedDebug
+ false
+ $(IntDir)$(ProjectName).pdb
+ Level4
+ OldStyle
+ Default
+ %(DisableSpecificWarnings)
+
+
+ $(OutDir)$(TargetName).lib
+
+
+
+
+
+
+
+
+ Disabled
+ ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_rend;%(AdditionalIncludeDirectories)
+ _CRT_SECURE_NO_WARNINGS;$(Macros);%(PreprocessorDefinitions)
+ false
+
+
+ EnableFastChecks
+ MultiThreadedDebug
+ false
+ $(IntDir)$(ProjectName).pdb
+ Level4
+ OldStyle
+ Default
+ %(DisableSpecificWarnings)
+
+
+ $(OutDir)$(TargetName).lib
+
+
+
+
+
+
+
+ MaxSpeed
+ AnySuitable
+ false
+ false
+ ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_rend;%(AdditionalIncludeDirectories)
+ _CRT_SECURE_NO_WARNINGS;$(Macros);%(PreprocessorDefinitions)
+ true
+
+ Default
+ MultiThreaded
+ true
+ $(IntDir)$(ProjectName).pdb
+ Level4
+
+ Default
+ %(DisableSpecificWarnings)
+
+
+ $(OutDir)$(TargetName).lib
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Workspace_msvc/evs_dec.vcxproj b/Workspace_msvc/evs_dec.vcxproj
new file mode 100644
index 0000000000000000000000000000000000000000..03b5ef5624b817ecfab612b68273f3b748753d4e
--- /dev/null
+++ b/Workspace_msvc/evs_dec.vcxproj
@@ -0,0 +1,297 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+
+ {E822DDAF-0F5F-4CD0-A694-38AE69DE74D3}
+ evs_dec
+ 10.0
+
+
+
+ Application
+ false
+ MultiByte
+ v142
+
+
+ Application
+ false
+ MultiByte
+ v142
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ProjectFileVersion>15.0.26228.10
+
+
+ ..\
+ .\Debug_Dec\
+ false
+ false
+ EVS_dec
+
+
+ ..\
+ .\Release_Dec\
+ false
+ false
+ EVS_dec
+
+
+
+
+
+
+ .\Debug/vbr_dec.tlb
+
+
+
+ Disabled
+ ..\lib_enc;..\lib_dec;..\lib_com;..\lib_debug;%(AdditionalIncludeDirectories)
+ _CRT_SECURE_NO_WARNINGS;WIN32;%(PreprocessorDefinitions)
+
+ EnableFastChecks
+ MultiThreadedDebug
+ false
+
+
+ $(IntDir)evs_dec.pdb
+ Level4
+ true
+ OldStyle
+ Default
+ 4244;%(DisableSpecificWarnings)
+
+
+ _DEBUG;%(PreprocessorDefinitions)
+ 0x0c0c
+
+
+
+
+ ..\EVS_dec.exe
+ true
+
+ true
+ .\Debug/evs_dec.pdb
+ Console
+ false
+
+ MachineX86
+
+
+
+
+ .\Release/vbr_dec.tlb
+
+
+
+ MaxSpeed
+ AnySuitable
+ false
+ Neither
+ false
+ false
+ ..\lib_enc;..\lib_dec;..\lib_com;%(AdditionalIncludeDirectories)
+ _CRT_SECURE_NO_WARNINGS;WIN32;%(PreprocessorDefinitions)
+ true
+
+ Default
+ MultiThreaded
+ true
+ false
+
+
+ $(IntDir)evs_dec.pdb
+ Level4
+ true
+
+ Default
+ 4100;4244;4310;%(DisableSpecificWarnings)
+
+
+ NDEBUG;%(PreprocessorDefinitions)
+ 0x0c0c
+
+
+ ..\EVS_dec.exe
+ true
+
+ false
+ .\Release/vbr_dec.pdb
+ Console
+ false
+
+ MachineX86
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {39ec200d-7795-4ff8-b214-b24eda5526ae}
+ false
+
+
+ {54509728-928b-44d9-a118-a6f92f08b34f}
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Workspace_msvc/evs_enc.vcxproj b/Workspace_msvc/evs_enc.vcxproj
new file mode 100644
index 0000000000000000000000000000000000000000..c562f24300b71e6e4399cf85c63fd6a59afa4cf2
--- /dev/null
+++ b/Workspace_msvc/evs_enc.vcxproj
@@ -0,0 +1,323 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+
+ {824DA4CF-06F0-45C9-929A-8792F0E19C3E}
+ evs_enc
+ 10.0
+
+
+
+ Application
+ false
+ MultiByte
+ v142
+
+
+ Application
+ false
+ MultiByte
+ v142
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ProjectFileVersion>15.0.26228.10
+
+
+ ..\
+ .\Release_Enc\
+ false
+ false
+ EVS_cod
+
+
+ ..\
+ .\Debug_Enc\
+ false
+ false
+ EVS_cod
+
+
+
+
+
+
+ .\Release/vbr_enc.tlb
+
+
+
+ MaxSpeed
+ AnySuitable
+ false
+ Neither
+ false
+ false
+ ..\lib_enc;..\lib_dec;..\lib_com;%(AdditionalIncludeDirectories)
+ _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
+ true
+
+ Default
+ MultiThreaded
+ true
+ Precise
+ false
+
+
+ $(IntDir)ens_enc.pdb
+ Level4
+ true
+
+ Default
+ 4100;4244;4310;%(DisableSpecificWarnings)
+
+
+ NDEBUG;%(PreprocessorDefinitions)
+ 0x0c0c
+
+
+ ..\EVS_cod.exe
+ true
+
+ false
+ .\Release/vbr_enc.pdb
+ Console
+ false
+
+ MachineX86
+
+
+
+
+
+
+
+ .\Debug/vbr_enc.tlb
+
+
+
+ Disabled
+ ..\lib_enc;..\lib_dec;..\lib_com;..\lib_debug;%(AdditionalIncludeDirectories)
+ _CRT_SECURE_NO_WARNINGS;WIN32;%(PreprocessorDefinitions)
+
+ EnableFastChecks
+ MultiThreadedDebug
+ false
+
+
+ $(IntDir)ens_enc.pdb
+ Level4
+ true
+ OldStyle
+ Default
+ 4244;%(DisableSpecificWarnings)
+ false
+
+
+
+
+ _DEBUG;%(PreprocessorDefinitions)
+ 0x0c0c
+
+
+
+
+ ..\EVS_cod.exe
+ true
+
+ false
+ true
+ .\Debug/evs_enc.pdb
+ Console
+
+ false
+
+ MachineX86
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {39ec200d-7795-4ff8-b214-b24eda5526ae}
+ false
+
+
+ {54509728-928b-44d9-a118-a6f92f08b34f}
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/lib_com/ACcontextMapping.c b/lib_com/ACcontextMapping.c
new file mode 100644
index 0000000000000000000000000000000000000000..f1989a09b04221fdee9bad875bdf4642cc1350cd
--- /dev/null
+++ b/lib_com/ACcontextMapping.c
@@ -0,0 +1,74 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include "options.h"
+#include "wmc_auto.h"
+#include "cnst.h"
+#include "prot.h"
+
+
+/*-------------------------------------------------------------------*
+* get_next_coeff_mapped()
+*
+*
+*-------------------------------------------------------------------*/
+
+int get_next_coeff_mapped( /* o : index of next coefficient */
+ int ii[2], /* i/o: coefficient indexes */
+ int *pp, /* o : peak(1)/hole(0) indicator */
+ int *idx, /* o : index in unmapped domain */
+ CONTEXT_HM_CONFIG *hm_cfg /* i : HM configuration */
+)
+{
+ unsigned int p;
+
+ p = (ii[1] - hm_cfg->numPeakIndices) & (hm_cfg->indexBuffer[ii[1]] - hm_cfg->indexBuffer[ii[0]]);
+ p >>= sizeof(p)*8-1;
+ *pp = p;
+ *idx = ii[p];
+ ii[p]++;
+
+ return hm_cfg->indexBuffer[*idx];
+}
+
+
+/*-------------------------------------------------------------------*
+* get_next_coeff_unmapped()
+*
+*
+*-------------------------------------------------------------------*/
+
+int get_next_coeff_unmapped(/* o : index of next coefficient */
+ int *ii, /* i/o: coefficient indexes */
+ int *idx /* o : index in unmapped domain */
+)
+{
+ *idx = *ii;
+ (*ii)++;
+
+ return *idx;
+}
+
+/*-------------------------------------------------------------------*
+* update_mixed_context()
+*
+*
+*-------------------------------------------------------------------*/
+
+int update_mixed_context(
+ int ctx,
+ int a
+)
+{
+ int t;
+
+ t = 1-13 + (a & ~1)*((a>>2)+1);
+
+ if (t > 0)
+ {
+ t = min((a>>3), 2);
+ }
+
+ return (ctx & 0xf) * 16 + t + 13;
+}
diff --git a/lib_com/__zaloha/basop32.c b/lib_com/__zaloha/basop32.c
new file mode 100644
index 0000000000000000000000000000000000000000..124cf72399e45cad14058cbcf210b6a95f9aa3cf
--- /dev/null
+++ b/lib_com/__zaloha/basop32.c
@@ -0,0 +1,2542 @@
+
+/* v.2.3 - 30.Nov.2009
+ =============================================================================
+
+ U U GGG SSSS TTTTT
+
+ U U G S T
+ U U G GG SSSS T
+ U U G G S T
+ UUU GG SSS T
+
+ ========================================
+ ITU-T - USER'S GROUP ON SOFTWARE TOOLS
+ ========================================
+
+ =============================================================
+ COPYRIGHT NOTE: This source code, and all of its derivations,
+ is subject to the "ITU-T General Public License". Please have
+ it read in the distribution disk, or in the ITU-T
+ Recommendation G.191 on "SOFTWARE TOOLS FOR SPEECH AND AUDIO
+ CODING STANDARDS".
+ =============================================================
+
+MODULE: BASOP32, BASIC OPERATORS
+
+ORIGINAL BY:
+ Incorporated from anonymous contributions for
+ ETSI Standards as well as G.723.1, G.729, and G.722.1
+
+DESCRIPTION:
+ This file contains the definition of 16- and 32-bit basic
+ operators to be used in the implementation of signal
+ processing algorithms. The basic operators try to resemble
+ assembly language instructions that are commonly found in
+ digital signal processor (DSP) CPUs, thus allowing algorithm
+ C-code implementations more directly mapeable to DSP assembly
+ code.
+
+ *********************************************************
+ NOTE: so far, this module does not have a demo program!
+ *********************************************************
+
+FUNCTIONS:
+ Defined in basop32.h. Self-documentation within each function.
+
+HISTORY:
+ 26.Jan.00 v1.0 Incorporated to the STL from updated G.723.1/G.729
+ basic operator library (based on basicop2.c) and
+ G.723.1's basop.c [L_mls(), div_l(), i_mult()]
+
+ 05.Jul.00 v1.1 Added 32-bit shiftless accumulation basic
+ operators (L_msu0, L_mac0, L_mult0). Improved
+ documentation for i_mult().
+
+ 03 Nov 04 v2.0 Incorporation of new 32-bit / 40-bit / control
+ operators for the ITU-T Standard Tool Library as
+ described in Geneva, 20-30 January 2004 WP 3/16 Q10/16
+ TD 11 document and subsequent discussions on the
+ wp3audio@yahoogroups.com email reflector.
+ norm_s() weight reduced from 15 to 1.
+ norm_l() weight reduced from 30 to 1.
+ L_abs() weight reduced from 2 to 1.
+ L_add() weight reduced from 2 to 1.
+ L_negate() weight reduced from 2 to 1.
+ L_shl() weight reduced from 2 to 1.
+ L_shr() weight reduced from 2 to 1.
+ L_sub() weight reduced from 2 to 1.
+ mac_r() weight reduced from 2 to 1.
+ msu_r() weight reduced from 2 to 1.
+ mult_r() weight reduced from 2 to 1.
+ L_deposit_h() weight reduced from 2 to 1.
+ L_deposit_l() weight reduced from 2 to 1.
+ L_mls() weight of 5.
+ div_l() weight of 32.
+ i_mult() weight of 3.
+
+ 30 Nov 09 v2.3 round() function is now round_fx().
+ saturate() is not referencable from outside application
+ =============================================================================
+*/
+
+
+/*___________________________________________________________________________
+ | |
+ | Basic arithmetic operators. |
+ | |
+ | |
+ | |
+ | saturate() |
+ | add() |
+ | sub() |
+ | abs_s() |
+ | divide_s() |
+ | extract_h() |
+ | extract_l() |
+ | L_abs() |
+ | L_add() |
+ | L_deposit_h() |
+ | L_deposit_l() |
+ | L_mac() |
+ | L_msu() |
+ | L_mult() |
+ | L_negate() |
+ | L_shl() |
+ | L_shr() |
+ | L_sub() |
+ | mac_r() |
+ | msu_r() |
+ | mult() |
+ | mult_r() |
+ | negate() |
+ | norm_l() |
+ | norm_s() |
+ | round_fx() |
+ | shl() |
+ | shr() |
+ |___________________________________________________________________________|
+*/
+
+
+/*___________________________________________________________________________
+ | |
+ | Include-Files |
+ |___________________________________________________________________________|
+*/
+#ifndef _CRT_SECURE_NO_WARNINGS
+#define _CRT_SECURE_NO_WARNINGS
+#endif
+
+#include
+#include
+#include "stl.h"
+#include "wmc_auto.h"
+
+#define WMC_TOOL_SKIP
+
+/*___________________________________________________________________________
+ | |
+ | Local Functions |
+ |___________________________________________________________________________|
+*/
+static Word16 saturate (Word32 L_var1);
+
+
+/*___________________________________________________________________________
+ | |
+ | Constants and Globals |
+ |___________________________________________________________________________|
+*/
+Flag Overflow = 0;
+Flag Carry = 0;
+
+
+/*___________________________________________________________________________
+ | |
+ | Functions |
+ |___________________________________________________________________________|
+*/
+
+#define PRINT_STACK_ID_ALL "*"
+
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : saturate |
+ | |
+ | Purpose : |
+ | |
+ | Limit the 32 bit input to the range of a 16 bit word. Must NOT be |
+ | referenced from outside applications. |
+ | |
+ | Inputs : |
+ | |
+ | L_var1 |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var1 <= 0x7fff ffff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+static Word16 saturate (Word32 L_var1)
+{
+ Word16 var_out;
+
+ if (L_var1 > 0X00007fffL)
+ {
+ Overflow = 1;
+ var_out = MAX_16;
+ }
+ else if (L_var1 < (Word32) 0xffff8000L)
+ {
+ Overflow = 1;
+ var_out = MIN_16;
+ }
+ else
+ {
+ var_out = extract_l (L_var1);
+ }
+
+ BASOP_CHECK();
+
+ return (var_out);
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : add |
+ | |
+ | Purpose : |
+ | |
+ | Performs the addition (var1+var2) with overflow control and saturation;|
+ | the 16 bit result is set at +32767 when overflow occurs or at -32768 |
+ | when underflow occurs. |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+Word16 add (Word16 var1, Word16 var2)
+{
+ Word16 var_out;
+ Word32 L_sum;
+
+ L_sum = (Word32) var1 + var2;
+ var_out = saturate (L_sum);
+
+
+ return (var_out);
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : sub |
+ | |
+ | Purpose : |
+ | |
+ | Performs the subtraction (var1+var2) with overflow control and satu- |
+ | ration; the 16 bit result is set at +32767 when overflow occurs or at |
+ | -32768 when underflow occurs. |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+Word16 sub (Word16 var1, Word16 var2)
+{
+ Word16 var_out;
+ Word32 L_diff;
+
+ L_diff = (Word32) var1 - var2;
+ var_out = saturate (L_diff);
+
+
+ return (var_out);
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : abs_s |
+ | |
+ | Purpose : |
+ | |
+ | Absolute value of var1; abs_s(-32768) = 32767. |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0x0000 0000 <= var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+Word16 abs_s (Word16 var1)
+{
+ Word16 var_out;
+
+ if (var1 == (Word16) MIN_16)
+ {
+ var_out = MAX_16;
+ }
+ else
+ {
+ if (var1 < 0)
+ {
+ var_out = -var1;
+ }
+ else
+ {
+ var_out = var1;
+ }
+ }
+
+ BASOP_CHECK();
+
+
+ return (var_out);
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : shl |
+ | |
+ | Purpose : |
+ | |
+ | Arithmetically shift the 16 bit input var1 left var2 positions.Zero fill|
+ | the var2 LSB of the result. If var2 is negative, arithmetically shift |
+ | var1 right by -var2 with sign extension. Saturate the result in case of |
+ | underflows or overflows. |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+Word16 shl (Word16 var1, Word16 var2)
+{
+ Word16 var_out;
+ Word32 result;
+
+ if (var2 < 0)
+ {
+ if (var2 < -16)
+ var2 = -16;
+ var2 = -var2;
+ var_out = shr (var1, var2);
+ }
+ else
+ {
+ result = (Word32) var1 *((Word32) 1 << var2);
+
+ if ((var2 > 15 && var1 != 0) || (result != (Word32) ((Word16) result)))
+ {
+ Overflow = 1;
+ var_out = (var1 > 0) ? MAX_16 : MIN_16;
+ }
+ else
+ {
+ var_out = extract_l (result);
+ }
+ }
+
+ BASOP_CHECK();
+
+
+ return (var_out);
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : shr |
+ | |
+ | Purpose : |
+ | |
+ | Arithmetically shift the 16 bit input var1 right var2 positions with |
+ | sign extension. If var2 is negative, arithmetically shift var1 left by |
+ | -var2 with sign extension. Saturate the result in case of underflows or |
+ | overflows. |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+Word16 shr (Word16 var1, Word16 var2)
+{
+ Word16 var_out;
+
+ if (var2 < 0)
+ {
+ if (var2 < -16)
+ var2 = -16;
+ var2 = -var2;
+ var_out = shl (var1, var2);
+ }
+ else
+ {
+ if (var2 >= 15)
+ {
+ var_out = (var1 < 0) ? -1 : 0;
+ }
+ else
+ {
+ if (var1 < 0)
+ {
+ var_out = ~((~var1) >> var2);
+ }
+ else
+ {
+ var_out = var1 >> var2;
+ }
+ }
+ }
+
+ BASOP_CHECK();
+
+
+ return (var_out);
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : mult |
+ | |
+ | Purpose : |
+ | |
+ | Performs the multiplication of var1 by var2 and gives a 16 bit result |
+ | which is scaled i.e.: |
+ | mult(var1,var2) = extract_l(L_shr((var1 times var2),15)) and |
+ | mult(-32768,-32768) = 32767. |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+Word16 mult (Word16 var1, Word16 var2)
+{
+ Word16 var_out;
+ Word32 L_product;
+
+ L_product = (Word32) var1 *(Word32) var2;
+
+ L_product = (L_product & (Word32) 0xffff8000L) >> 15;
+
+ if (L_product & (Word32) 0x00010000L)
+ L_product = L_product | (Word32) 0xffff0000L;
+
+ var_out = saturate (L_product);
+
+
+ return (var_out);
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_mult |
+ | |
+ | Purpose : |
+ | |
+ | L_mult is the 32 bit result of the multiplication of var1 times var2 |
+ | with one shift left i.e.: |
+ | L_mult(var1,var2) = L_shl((var1 times var2),1) and |
+ | L_mult(-32768,-32768) = 2147483647. |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. |
+ |___________________________________________________________________________|
+*/
+Word32 L_mult (Word16 var1, Word16 var2)
+{
+ Word32 L_var_out;
+
+ L_var_out = (Word32) var1 *(Word32) var2;
+
+ if (L_var_out != (Word32) 0x40000000L)
+ {
+ L_var_out *= 2;
+ }
+ else
+ {
+ Overflow = 1;
+ L_var_out = MAX_32;
+ }
+
+ BASOP_CHECK();
+
+
+ return (L_var_out);
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : negate |
+ | |
+ | Purpose : |
+ | |
+ | Negate var1 with saturation, saturate in the case where input is -32768:|
+ | negate(var1) = sub(0,var1). |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+Word16 negate (Word16 var1)
+{
+ Word16 var_out;
+
+ var_out = (var1 == MIN_16) ? MAX_16 : -var1;
+
+
+ BASOP_CHECK();
+
+
+ return (var_out);
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : extract_h |
+ | |
+ | Purpose : |
+ | |
+ | Return the 16 MSB of L_var1. |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | L_var1 |
+ | 32 bit long signed integer (Word32 ) whose value falls in the |
+ | range : 0x8000 0000 <= L_var1 <= 0x7fff ffff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+Word16 extract_h (Word32 L_var1)
+{
+ Word16 var_out;
+
+ var_out = (Word16) (L_var1 >> 16);
+
+ BASOP_CHECK();
+
+
+ return (var_out);
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : extract_l |
+ | |
+ | Purpose : |
+ | |
+ | Return the 16 LSB of L_var1. |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | L_var1 |
+ | 32 bit long signed integer (Word32 ) whose value falls in the |
+ | range : 0x8000 0000 <= L_var1 <= 0x7fff ffff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+Word16 extract_l (Word32 L_var1)
+{
+ Word16 var_out;
+
+ var_out = (Word16) L_var1;
+
+ BASOP_CHECK();
+
+
+ return (var_out);
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : round_fx |
+ | |
+ | Purpose : |
+ | |
+ | Round the lower 16 bits of the 32 bit input number into the MS 16 bits |
+ | with saturation. Shift the resulting bits right by 16 and return the 16 |
+ | bit number: |
+ | round_fx(L_var1) = extract_h(L_add(L_var1,32768)) |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | L_var1 |
+ | 32 bit long signed integer (Word32 ) whose value falls in the |
+ | range : 0x8000 0000 <= L_var1 <= 0x7fff ffff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+Word16 round_fx (Word32 L_var1)
+{
+ Word16 var_out;
+ Word32 L_rounded;
+
+ BASOP_SATURATE_WARNING_OFF
+ L_rounded = L_add (L_var1, (Word32) 0x00008000L);
+ BASOP_SATURATE_WARNING_ON
+ var_out = extract_h (L_rounded);
+
+ BASOP_CHECK();
+
+
+ return (var_out);
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_mac |
+ | |
+ | Purpose : |
+ | |
+ | Multiply var1 by var2 and shift the result left by 1. Add the 32 bit |
+ | result to L_var3 with saturation, return a 32 bit result: |
+ | L_mac(L_var3,var1,var2) = L_add(L_var3,L_mult(var1,var2)). |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | L_var3 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. |
+ |___________________________________________________________________________|
+*/
+Word32 L_mac (Word32 L_var3, Word16 var1, Word16 var2)
+{
+ Word32 L_var_out;
+ Word32 L_product;
+
+ L_product = L_mult (var1, var2);
+ L_var_out = L_add (L_var3, L_product);
+
+ BASOP_CHECK();
+
+
+ return (L_var_out);
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_msu |
+ | |
+ | Purpose : |
+ | |
+ | Multiply var1 by var2 and shift the result left by 1. Subtract the 32 |
+ | bit result from L_var3 with saturation, return a 32 bit result: |
+ | L_msu(L_var3,var1,var2) = L_sub(L_var3,L_mult(var1,var2)). |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | L_var3 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. |
+ |___________________________________________________________________________|
+*/
+Word32 L_msu (Word32 L_var3, Word16 var1, Word16 var2)
+{
+ Word32 L_var_out;
+ Word32 L_product;
+
+ L_product = L_mult (var1, var2);
+ L_var_out = L_sub (L_var3, L_product);
+
+ BASOP_CHECK();
+
+
+ return (L_var_out);
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_macNs |
+ | |
+ | Purpose : |
+ | |
+ | Multiply var1 by var2 and shift the result left by 1. Add the 32 bit |
+ | result to L_var3 without saturation, return a 32 bit result. Generate |
+ | carry and overflow values : |
+ | L_macNs(L_var3,var1,var2) = L_add_c(L_var3,L_mult(var1,var2)). |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | L_var3 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. |
+ | |
+ | Caution : |
+ | |
+ | In some cases the Carry flag has to be cleared or set before using |
+ | operators which take into account its value. |
+ |___________________________________________________________________________|
+*/
+Word32 L_macNs (Word32 L_var3, Word16 var1, Word16 var2)
+{
+ Word32 L_var_out;
+
+ L_var_out = L_mult (var1, var2);
+ L_var_out = L_add_c (L_var3, L_var_out);
+
+ /* BASOP_CHECK(); Do not check for overflow here, function produces the carry bit instead */
+
+
+ return (L_var_out);
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_msuNs |
+ | |
+ | Purpose : |
+ | |
+ | Multiply var1 by var2 and shift the result left by 1. Subtract the 32 |
+ | bit result from L_var3 without saturation, return a 32 bit result. Ge- |
+ | nerate carry and overflow values : |
+ | L_msuNs(L_var3,var1,var2) = L_sub_c(L_var3,L_mult(var1,var2)). |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | L_var3 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. |
+ | |
+ | Caution : |
+ | |
+ | In some cases the Carry flag has to be cleared or set before using |
+ | operators which take into account its value. |
+ |___________________________________________________________________________|
+*/
+Word32 L_msuNs (Word32 L_var3, Word16 var1, Word16 var2)
+{
+ Word32 L_var_out;
+
+ L_var_out = L_mult (var1, var2);
+ L_var_out = L_sub_c (L_var3, L_var_out);
+
+ /* BASOP_CHECK(); Do not check for overflow here, function produces the carry bit instead */
+
+
+ return (L_var_out);
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_add |
+ | |
+ | Purpose : |
+ | |
+ | 32 bits addition of the two 32 bits variables (L_var1+L_var2) with |
+ | overflow control and saturation; the result is set at +2147483647 when |
+ | overflow occurs or at -2147483648 when underflow occurs. |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | L_var1 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | L_var2 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. |
+ |___________________________________________________________________________|
+*/
+Word32 L_add (Word32 L_var1, Word32 L_var2)
+{
+ Word32 L_var_out;
+
+ L_var_out = L_var1 + L_var2;
+
+ if (((L_var1 ^ L_var2) & MIN_32) == 0)
+ {
+ if ((L_var_out ^ L_var1) & MIN_32)
+ {
+ L_var_out = (L_var1 < 0) ? MIN_32 : MAX_32;
+ Overflow = 1;
+ }
+ }
+
+ BASOP_CHECK();
+
+
+ return (L_var_out);
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_sub |
+ | |
+ | Purpose : |
+ | |
+ | 32 bits subtraction of the two 32 bits variables (L_var1-L_var2) with |
+ | overflow control and saturation; the result is set at +2147483647 when |
+ | overflow occurs or at -2147483648 when underflow occurs. |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | L_var1 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | L_var2 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. |
+ |___________________________________________________________________________|
+*/
+Word32 L_sub (Word32 L_var1, Word32 L_var2)
+{
+ Word32 L_var_out;
+
+ L_var_out = L_var1 - L_var2;
+
+ if (((L_var1 ^ L_var2) & MIN_32) != 0)
+ {
+ if ((L_var_out ^ L_var1) & MIN_32)
+ {
+ L_var_out = (L_var1 < 0L) ? MIN_32 : MAX_32;
+ Overflow = 1;
+ }
+ }
+
+ BASOP_CHECK();
+
+
+ return (L_var_out);
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_add_c |
+ | |
+ | Purpose : |
+ | |
+ | Performs 32 bits addition of the two 32 bits variables (L_var1+L_var2+C)|
+ | with carry. No saturation. Generate carry and Overflow values. The car- |
+ | ry and overflow values are binary variables which can be tested and as- |
+ | signed values. |
+ | |
+ | Complexity weight : 2 |
+ | |
+ | Inputs : |
+ | |
+ | L_var1 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | L_var2 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. |
+ | |
+ | Caution : |
+ | |
+ | In some cases the Carry flag has to be cleared or set before using |
+ | operators which take into account its value. |
+ |___________________________________________________________________________|
+*/
+Word32 L_add_c (Word32 L_var1, Word32 L_var2)
+{
+ Word32 L_var_out;
+ Word32 L_test;
+ Flag carry_int = 0;
+
+ L_var_out = L_var1 + L_var2 + Carry;
+
+ L_test = L_var1 + L_var2;
+
+ if ((L_var1 > 0) && (L_var2 > 0) && (L_test < 0))
+ {
+ Overflow = 1;
+ carry_int = 0;
+ }
+ else
+ {
+ if ((L_var1 < 0) && (L_var2 < 0))
+ {
+ if (L_test >= 0)
+ {
+ Overflow = 1;
+ carry_int = 1;
+ }
+ else
+ {
+ Overflow = 0;
+ carry_int = 1;
+ }
+ }
+ else
+ {
+ if (((L_var1 ^ L_var2) < 0) && (L_test >= 0))
+ {
+ Overflow = 0;
+ carry_int = 1;
+ }
+ else
+ {
+ Overflow = 0;
+ carry_int = 0;
+ }
+ }
+ }
+
+ if (Carry)
+ {
+ if (L_test == MAX_32)
+ {
+ Overflow = 1;
+ Carry = carry_int;
+ }
+ else
+ {
+ if (L_test == (Word32) 0xFFFFFFFFL)
+ {
+ Carry = 1;
+ }
+ else
+ {
+ Carry = carry_int;
+ }
+ }
+ }
+ else
+ {
+ Carry = carry_int;
+ }
+
+ /* BASOP_CHECK(); Do not check for overflow here, function produces the carry bit instead */
+
+
+ return (L_var_out);
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_sub_c |
+ | |
+ | Purpose : |
+ | |
+ | Performs 32 bits subtraction of the two 32 bits variables with carry |
+ | (borrow) : L_var1-L_var2-C. No saturation. Generate carry and Overflow |
+ | values. The carry and overflow values are binary variables which can |
+ | be tested and assigned values. |
+ | |
+ | Complexity weight : 2 |
+ | |
+ | Inputs : |
+ | |
+ | L_var1 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | L_var2 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. |
+ | |
+ | Caution : |
+ | |
+ | In some cases the Carry flag has to be cleared or set before using |
+ | operators which take into account its value. |
+ |___________________________________________________________________________|
+*/
+Word32 L_sub_c (Word32 L_var1, Word32 L_var2)
+{
+ Word32 L_var_out;
+ Word32 L_test;
+ Flag carry_int = 0;
+
+ if (Carry)
+ {
+ Carry = 0;
+ if (L_var2 != MIN_32)
+ {
+ L_var_out = L_add_c (L_var1, -L_var2);
+ }
+ else
+ {
+ L_var_out = L_var1 - L_var2;
+ if (L_var1 > 0L)
+ {
+ Overflow = 1;
+ Carry = 0;
+ }
+ }
+ }
+ else
+ {
+ L_var_out = L_var1 - L_var2 - (Word32) 0X00000001L;
+ L_test = L_var1 - L_var2;
+
+ if ((L_test < 0) && (L_var1 > 0) && (L_var2 < 0))
+ {
+ Overflow = 1;
+ carry_int = 0;
+ }
+ else if ((L_test > 0) && (L_var1 < 0) && (L_var2 > 0))
+ {
+ Overflow = 1;
+ carry_int = 1;
+ }
+ else if ((L_test > 0) && ((L_var1 ^ L_var2) > 0))
+ {
+ Overflow = 0;
+ carry_int = 1;
+ }
+ if (L_test == MIN_32)
+ {
+ Overflow = 1;
+ Carry = carry_int;
+ }
+ else
+ {
+ Carry = carry_int;
+ }
+ }
+
+ /* BASOP_CHECK(); Do not check for overflow here, function produces the carry bit instead */
+
+
+ return (L_var_out);
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_negate |
+ | |
+ | Purpose : |
+ | |
+ | Negate the 32 bit variable L_var1 with saturation; saturate in the case |
+ | where input is -2147483648 (0x8000 0000). |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | L_var1 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. |
+ |___________________________________________________________________________|
+*/
+Word32 L_negate (Word32 L_var1)
+{
+ Word32 L_var_out;
+
+ L_var_out = (L_var1 == MIN_32) ? MAX_32 : -L_var1;
+
+
+ BASOP_CHECK();
+
+
+ return (L_var_out);
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : mult_r |
+ | |
+ | Purpose : |
+ | |
+ | Same as mult with rounding, i.e.: |
+ | mult_r(var1,var2) = extract_l(L_shr(((var1 * var2) + 16384),15)) and |
+ | mult_r(-32768,-32768) = 32767. |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0x8000 <= var_out <= 0x7fff. |
+ |___________________________________________________________________________|
+*/
+Word16 mult_r (Word16 var1, Word16 var2)
+{
+ Word16 var_out;
+ Word32 L_product_arr;
+
+ L_product_arr = (Word32) var1 *(Word32) var2; /* product */
+ L_product_arr += (Word32) 0x00004000L; /* round */
+ L_product_arr &= (Word32) 0xffff8000L;
+ L_product_arr >>= 15; /* shift */
+
+ if (L_product_arr & (Word32) 0x00010000L) /* sign extend when necessary */
+ {
+ L_product_arr |= (Word32) 0xffff0000L;
+ }
+ var_out = saturate (L_product_arr);
+
+
+ return (var_out);
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_shl |
+ | |
+ | Purpose : |
+ | |
+ | Arithmetically shift the 32 bit input L_var1 left var2 positions. Zero |
+ | fill the var2 LSB of the result. If var2 is negative, arithmetically |
+ | shift L_var1 right by -var2 with sign extension. Saturate the result in |
+ | case of underflows or overflows. |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | L_var1 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. |
+ |___________________________________________________________________________|
+*/
+Word32 L_shl (Word32 L_var1, Word16 var2)
+{
+
+ Word32 L_var_out = 0L;
+
+ if (var2 <= 0)
+ {
+ if (var2 < -32)
+ var2 = -32;
+ var2 = -var2;
+ L_var_out = L_shr (L_var1, var2);
+ }
+ else
+ {
+ for (; var2 > 0; var2--)
+ {
+ if (L_var1 > (Word32) 0X3fffffffL)
+ {
+ Overflow = 1;
+ L_var_out = MAX_32;
+ break;
+ }
+ else
+ {
+ if (L_var1 < (Word32) 0xc0000000L)
+ {
+ Overflow = 1;
+ L_var_out = MIN_32;
+ break;
+ }
+ }
+ L_var1 *= 2;
+ L_var_out = L_var1;
+ }
+ }
+
+ BASOP_CHECK();
+
+
+ return (L_var_out);
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_shr |
+ | |
+ | Purpose : |
+ | |
+ | Arithmetically shift the 32 bit input L_var1 right var2 positions with |
+ | sign extension. If var2 is negative, arithmetically shift L_var1 left |
+ | by -var2 and zero fill the -var2 LSB of the result. Saturate the result |
+ | in case of underflows or overflows. |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | L_var1 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. |
+ |___________________________________________________________________________|
+*/
+Word32 L_shr (Word32 L_var1, Word16 var2)
+{
+ Word32 L_var_out;
+
+ if (var2 < 0)
+ {
+ if (var2 < -32)
+ var2 = -32;
+ var2 = -var2;
+ L_var_out = L_shl (L_var1, var2);
+ }
+ else
+ {
+ if (var2 >= 31)
+ {
+ L_var_out = (L_var1 < 0L) ? -1 : 0;
+ }
+ else
+ {
+ if (L_var1 < 0)
+ {
+ L_var_out = ~((~L_var1) >> var2);
+ }
+ else
+ {
+ L_var_out = L_var1 >> var2;
+ }
+ }
+ }
+
+ BASOP_CHECK();
+
+
+ return (L_var_out);
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : shr_r |
+ | |
+ | Purpose : |
+ | |
+ | Same as shr(var1,var2) but with rounding. Saturate the result in case of|
+ | underflows or overflows : |
+ | - If var2 is greater than zero : |
+ | if (sub(shl(shr(var1,var2),1),shr(var1,sub(var2,1)))) |
+ | is equal to zero |
+ | then |
+ | shr_r(var1,var2) = shr(var1,var2) |
+ | else |
+ | shr_r(var1,var2) = add(shr(var1,var2),1) |
+ | - If var2 is less than or equal to zero : |
+ | shr_r(var1,var2) = shr(var1,var2). |
+ | |
+ | Complexity weight : 3 |
+ | |
+ | Inputs : |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+Word16 shr_r (Word16 var1, Word16 var2)
+{
+ Word16 var_out;
+
+ if (var2 > 15)
+ {
+ var_out = 0;
+ }
+ else
+ {
+ var_out = shr (var1, var2);
+
+ if (var2 > 0)
+ {
+ if ((var1 & ((Word16) 1 << (var2 - 1))) != 0)
+ {
+ var_out++;
+ }
+ }
+ }
+
+ BASOP_CHECK();
+
+
+ return (var_out);
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : mac_r |
+ | |
+ | Purpose : |
+ | |
+ | Multiply var1 by var2 and shift the result left by 1. Add the 32 bit |
+ | result to L_var3 with saturation. Round the LS 16 bits of the result |
+ | into the MS 16 bits with saturation and shift the result right by 16. |
+ | Return a 16 bit result. |
+ | mac_r(L_var3,var1,var2) = round_fx(L_mac(L_var3,var1,var2)) |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | L_var3 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0x0000 8000 <= L_var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+Word16 mac_r (Word32 L_var3, Word16 var1, Word16 var2)
+{
+ Word16 var_out;
+
+ L_var3 = L_mac (L_var3, var1, var2);
+ L_var3 = L_add (L_var3, (Word32) 0x00008000L);
+ var_out = extract_h (L_var3);
+
+ BASOP_CHECK();
+
+
+ return (var_out);
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : msu_r |
+ | |
+ | Purpose : |
+ | |
+ | Multiply var1 by var2 and shift the result left by 1. Subtract the 32 |
+ | bit result from L_var3 with saturation. Round the LS 16 bits of the res-|
+ | ult into the MS 16 bits with saturation and shift the result right by |
+ | 16. Return a 16 bit result. |
+ | msu_r(L_var3,var1,var2) = round_fx(L_msu(L_var3,var1,var2)) |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | L_var3 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0x0000 8000 <= L_var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+Word16 msu_r (Word32 L_var3, Word16 var1, Word16 var2)
+{
+ Word16 var_out;
+
+ L_var3 = L_msu (L_var3, var1, var2);
+ L_var3 = L_add (L_var3, (Word32) 0x00008000L);
+ var_out = extract_h (L_var3);
+
+ BASOP_CHECK();
+
+
+ return (var_out);
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_deposit_h |
+ | |
+ | Purpose : |
+ | |
+ | Deposit the 16 bit var1 into the 16 MS bits of the 32 bit output. The |
+ | 16 LS bits of the output are zeroed. |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= var_out <= 0x7fff 0000. |
+ |___________________________________________________________________________|
+*/
+Word32 L_deposit_h (Word16 var1)
+{
+ Word32 L_var_out;
+
+ L_var_out = (Word32) var1 << 16;
+
+ BASOP_CHECK();
+
+
+ return (L_var_out);
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_deposit_l |
+ | |
+ | Purpose : |
+ | |
+ | Deposit the 16 bit var1 into the 16 LS bits of the 32 bit output. The |
+ | 16 MS bits of the output are sign extended. |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0xFFFF 8000 <= var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+Word32 L_deposit_l (Word16 var1)
+{
+ Word32 L_var_out;
+
+ L_var_out = (Word32) var1;
+
+ BASOP_CHECK();
+
+
+ return (L_var_out);
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_shr_r |
+ | |
+ | Purpose : |
+ | |
+ | Same as L_shr(L_var1,var2) but with rounding. Saturate the result in |
+ | case of underflows or overflows : |
+ | - If var2 is greater than zero : |
+ | if (L_sub(L_shl(L_shr(L_var1,var2),1),L_shr(L_var1,sub(var2,1))))|
+ | is equal to zero |
+ | then |
+ | L_shr_r(L_var1,var2) = L_shr(L_var1,var2) |
+ | else |
+ | L_shr_r(L_var1,var2) = L_add(L_shr(L_var1,var2),1) |
+ | - If var2 is less than or equal to zero : |
+ | L_shr_r(L_var1,var2) = L_shr(L_var1,var2). |
+ | |
+ | Complexity weight : 3 |
+ | |
+ | Inputs : |
+ | |
+ | L_var1 |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= var1 <= 0x7fff ffff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= var_out <= 0x7fff ffff. |
+ |___________________________________________________________________________|
+*/
+Word32 L_shr_r (Word32 L_var1, Word16 var2)
+{
+ Word32 L_var_out;
+
+ if (var2 > 31)
+ {
+ L_var_out = 0;
+ }
+ else
+ {
+ L_var_out = L_shr (L_var1, var2);
+
+ if (var2 > 0)
+ {
+ if ((L_var1 & ((Word32) 1 << (var2 - 1))) != 0)
+ {
+ L_var_out++;
+ }
+ }
+ }
+
+ BASOP_CHECK();
+
+
+ return (L_var_out);
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_abs |
+ | |
+ | Purpose : |
+ | |
+ | Absolute value of L_var1; Saturate in case where the input is |
+ | -214783648 |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | L_var1 |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= var1 <= 0x7fff ffff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x0000 0000 <= var_out <= 0x7fff ffff. |
+ |___________________________________________________________________________|
+*/
+Word32 L_abs (Word32 L_var1)
+{
+ Word32 L_var_out;
+
+ if (L_var1 == MIN_32)
+ {
+ L_var_out = MAX_32;
+ }
+ else
+ {
+ if (L_var1 < 0)
+ {
+ L_var_out = -L_var1;
+ }
+ else
+ {
+ L_var_out = L_var1;
+ }
+ }
+
+ BASOP_CHECK();
+
+
+ return (L_var_out);
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_sat |
+ | |
+ | Purpose : |
+ | |
+ | 32 bit L_var1 is set to 2147483647 if an overflow occured or to |
+ | -2147483648 if an underflow occured on the most recent L_add_c, |
+ | L_sub_c, L_macNs or L_msuNs operations. The carry and overflow values |
+ | are binary values which can be tested and assigned values. |
+ | |
+ | Complexity weight : 4 |
+ | |
+ | Inputs : |
+ | |
+ | L_var1 |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= var1 <= 0x7fff ffff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= var_out <= 0x7fff ffff. |
+ |___________________________________________________________________________|
+*/
+Word32 L_sat (Word32 L_var1)
+{
+ Word32 L_var_out;
+
+ L_var_out = L_var1;
+
+ if (Overflow)
+ {
+
+ if (Carry)
+ {
+ L_var_out = MIN_32;
+ }
+ else
+ {
+ L_var_out = MAX_32;
+ }
+
+ Carry = 0;
+ Overflow = 0;
+ }
+
+ BASOP_CHECK();
+
+
+ return (L_var_out);
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : norm_s |
+ | |
+ | Purpose : |
+ | |
+ | Produces the number of left shift needed to normalize the 16 bit varia- |
+ | ble var1 for positive values on the interval with minimum of 16384 and |
+ | maximum of 32767, and for negative values on the interval with minimum |
+ | of -32768 and maximum of -16384; in order to normalize the result, the |
+ | following operation must be done : |
+ | norm_var1 = shl(var1,norm_s(var1)). |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0x0000 0000 <= var_out <= 0x0000 000f. |
+ |___________________________________________________________________________|
+*/
+Word16 norm_s (Word16 var1)
+{
+ Word16 var_out;
+
+ if (var1 == 0)
+ {
+ var_out = 0;
+ }
+ else
+ {
+ if (var1 == (Word16) 0xffff)
+ {
+ var_out = 15;
+ }
+ else
+ {
+ if (var1 < 0)
+ {
+ var1 = ~var1;
+ }
+ for (var_out = 0; var1 < 0x4000; var_out++)
+ {
+ var1 <<= 1;
+ }
+ }
+ }
+
+ BASOP_CHECK();
+
+
+ return (var_out);
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : div_s |
+ | |
+ | Purpose : |
+ | |
+ | Produces a result which is the fractional integer division of var1 by |
+ | var2; var1 and var2 must be positive and var2 must be greater or equal |
+ | to var1; the result is positive (leading bit equal to 0) and truncated |
+ | to 16 bits. |
+ | If var1 = var2 then div(var1,var2) = 32767. |
+ | |
+ | Complexity weight : 18 |
+ | |
+ | Inputs : |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0x0000 0000 <= var1 <= var2 and var2 != 0. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : var1 <= var2 <= 0x0000 7fff and var2 != 0. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0x0000 0000 <= var_out <= 0x0000 7fff. |
+ | It's a Q15 value (point between b15 and b14). |
+ |___________________________________________________________________________|
+*/
+Word16 div_s (Word16 var1, Word16 var2)
+{
+ Word16 var_out = 0;
+ Word16 iteration;
+ Word32 L_num;
+ Word32 L_denom;
+
+ if ((var1 > var2) || (var1 < 0) || (var2 < 0))
+ {
+ /* printf ("Division Error var1=%d var2=%d in ", var1, var2); printStack(); */
+ char text[60];
+ sprintf (text, "Division Error var1=%d var2=%d in ", var1, var2);
+ abort(); /* exit (0); */
+ }
+ if (var2 == 0)
+ {
+ /* printf ("Division by 0, Fatal error in "); printStack(); */
+ abort(); /* exit (0); */
+ }
+ if (var1 == 0)
+ {
+ var_out = 0;
+ }
+ else
+ {
+ if (var1 == var2)
+ {
+ var_out = MAX_16;
+ }
+ else
+ {
+ L_num = L_deposit_l (var1);
+ L_denom = L_deposit_l (var2);
+
+ for (iteration = 0; iteration < 15; iteration++)
+ {
+ var_out <<= 1;
+ L_num <<= 1;
+
+ if (L_num >= L_denom)
+ {
+ L_num = L_sub (L_num, L_denom);
+ var_out = add (var_out, 1);
+ }
+ }
+ }
+ }
+
+ BASOP_CHECK();
+
+
+ return (var_out);
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : norm_l |
+ | |
+ | Purpose : |
+ | |
+ | Produces the number of left shifts needed to normalize the 32 bit varia-|
+ | ble L_var1 for positive values on the interval with minimum of |
+ | 1073741824 and maximum of 2147483647, and for negative values on the in-|
+ | terval with minimum of -2147483648 and maximum of -1073741824; in order |
+ | to normalize the result, the following operation must be done : |
+ | norm_L_var1 = L_shl(L_var1,norm_l(L_var1)). |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | L_var1 |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= var1 <= 0x7fff ffff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0x0000 0000 <= var_out <= 0x0000 001f. |
+ |___________________________________________________________________________|
+*/
+Word16 norm_l (Word32 L_var1)
+{
+ Word16 var_out;
+
+ if (L_var1 == 0)
+ {
+ var_out = 0;
+ }
+ else
+ {
+ if (L_var1 == (Word32) 0xffffffffL)
+ {
+ var_out = 31;
+ }
+ else
+ {
+ if (L_var1 < 0)
+ {
+ L_var1 = ~L_var1;
+ }
+ for (var_out = 0; L_var1 < (Word32) 0x40000000L; var_out++)
+ {
+ L_var1 <<= 1;
+ }
+ }
+ }
+
+ BASOP_CHECK();
+
+
+ return (var_out);
+}
+
+/*
+ ******************************************************************************
+ * Additional operators extracted from the G.723.1 Library
+ * Adapted for WMOPS calculations
+ ******************************************************************************
+*/
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_mls |
+ | |
+ | Purpose : |
+ | |
+ | Multiplies a 16 bit word v by a 32 bit word Lv and returns a 32 bit |
+ | word (multiplying 16 by 32 bit words gives 48 bit word; the function |
+ | extracts the 32 MSB and shift the result to the left by 1). |
+ | |
+ | A 32 bit word can be written as |
+ | Lv = a + b * 2^16 |
+ | where a= unsigned 16 LSBs and b= signed 16 MSBs. |
+ | The function returns v * Lv / 2^15 which is equivalent to |
+ | a*v / 2^15 + b*v*2 |
+ | |
+ | Complexity weight : 5 |
+ | |
+ | Inputs : |
+ | |
+ | Lv |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= var1 <= 0x7fff ffff. |
+ | v |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0x8000 <= var1 <= 0x7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= var_out <= 0x7fff ffff. |
+ | |
+ |___________________________________________________________________________|
+*/
+Word32 L_mls (Word32 Lv, Word16 v)
+{
+ Word32 Temp ;
+
+ Temp = Lv & (Word32) 0x0000ffff ;
+ Temp = Temp * (Word32) v ;
+ Temp = L_shr( Temp, (Word16) 15 ) ;
+ Temp = L_mac( Temp, v, extract_h(Lv) ) ;
+
+ BASOP_CHECK();
+
+
+ return Temp ;
+}
+
+
+/*__________________________________________________________________________
+| |
+| Function Name : div_l |
+| |
+| Purpose : |
+| |
+| Produces a result which is the fractional integer division of L_var1 by |
+| var2; L_var1 and var2 must be positive and var2 << 16 must be greater or|
+| equal to L_var1; the result is positive (leading bit equal to 0) and |
+| truncated to 16 bits. |
+| If L_var1 == var2 << 16 then div_l(L_var1,var2) = 32767. |
+| |
+| Complexity weight : 32 |
+| |
+| Inputs : |
+| |
+| L_var1 |
+| 32 bit long signed integer (Word32) whose value falls in the |
+| range : 0x0000 0000 <= var1 <= (var2 << 16) and var2 != 0. |
+| L_var1 must be considered as a Q.31 value |
+| |
+| var2 |
+| 16 bit short signed integer (Word16) whose value falls in the |
+| range : var1 <= (var2<< 16) <= 0x7fff0000 and var2 != 0. |
+| var2 must be considered as a Q.15 value |
+| |
+| Outputs : |
+| |
+| none |
+| |
+| Return Value : |
+| |
+| var_out |
+| 16 bit short signed integer (Word16) whose value falls in the |
+| range : 0x0000 0000 <= var_out <= 0x0000 7fff. |
+| It's a Q15 value (point between b15 and b14). |
+|___________________________________________________________________________|
+*/
+Word16 div_l (Word32 L_num, Word16 den)
+{
+ Word16 var_out = (Word16)0;
+ Word32 L_den;
+ Word16 iteration;
+
+
+ if ( den == (Word16) 0 )
+ {
+ /* printf("Division by 0 in div_l, Fatal error in "); printStack(); */
+ exit(-1);
+ }
+
+ if ( (L_num < (Word32) 0) || (den < (Word16) 0) )
+ {
+ /* printf("Division Error in div_l, Fatal error in "); printStack(); */
+ exit(-1);
+ }
+
+ L_den = L_deposit_h( den ) ;
+
+ if ( L_num >= L_den )
+ {
+
+
+ BASOP_CHECK();
+ return MAX_16 ;
+ }
+ else
+ {
+ L_num = L_shr(L_num, (Word16)1) ;
+ L_den = L_shr(L_den, (Word16)1);
+ for(iteration=(Word16)0; iteration< (Word16)15; iteration++)
+ {
+ var_out = shl( var_out, (Word16)1);
+ L_num = L_shl( L_num, (Word16)1);
+ if (L_num >= L_den)
+ {
+ L_num = L_sub(L_num,L_den);
+ var_out = add(var_out, (Word16)1);
+ }
+ }
+
+
+ BASOP_CHECK();
+
+ return var_out;
+ }
+}
+
+
+/*__________________________________________________________________________
+| |
+| Function Name : i_mult |
+| |
+| Purpose : |
+| |
+| Integer 16-bit multiplication with overflow control. |
+| No overflow protection is performed if ORIGINAL_G7231 is defined. |
+| |
+| Complexity weight : 3 (it is performing something equivalent to |
+| extract_h( L_shl( L_mult0( v1, v2), 16)) |
+| |
+| Inputs : |
+| |
+| a |
+| 16 bit short signed integer (Word16). |
+| |
+| b |
+| 16 bit short signed integer (Word16). |
+| |
+| Outputs : |
+| |
+| none |
+| |
+| Return Value : |
+| |
+| 16 bit short signed integer (Word16). No overflow checks |
+| are performed if ORIGINAL_G7231 is defined. |
+|___________________________________________________________________________|
+*/
+Word16 i_mult (Word16 a, Word16 b)
+{
+#ifdef ORIGINAL_G7231
+ return a*b ;
+#else
+ Word32 /*register*/ c=a*b;
+ return saturate(c) ;
+#endif
+}
+
+
+/*
+ ******************************************************************************
+ * The following three operators are not part of the original
+ * G.729/G.723.1 set of basic operators and implement shiftless
+ * accumulation operation.
+ ******************************************************************************
+*/
+
+/*___________________________________________________________________________
+ |
+ | Function Name : L_mult0
+ |
+ | Purpose :
+ |
+ | L_mult0 is the 32 bit result of the multiplication of var1 times var2
+ | without one left shift.
+ |
+ | Complexity weight : 1
+ |
+ | Inputs :
+ |
+ | var1 16 bit short signed integer (Word16) whose value falls in the
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff.
+ |
+ | var2 16 bit short signed integer (Word16) whose value falls in the
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff.
+ |
+ | Return Value :
+ |
+ | L_var_out
+ | 32 bit long signed integer (Word32) whose value falls in the
+ | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.
+ |___________________________________________________________________________
+*/
+Word32 L_mult0 (Word16 var1,Word16 var2)
+{
+ Word32 L_var_out;
+
+ L_var_out = (Word32)var1 * (Word32)var2;
+
+ BASOP_CHECK();
+
+
+ return(L_var_out);
+}
+
+
+/*___________________________________________________________________________
+ |
+ | Function Name : L_mac0
+ |
+ | Purpose :
+ |
+ | Multiply var1 by var2 (without left shift) and add the 32 bit result to
+ | L_var3 with saturation, return a 32 bit result:
+ | L_mac0(L_var3,var1,var2) = L_add(L_var3,(L_mult0(var1,var2)).
+ |
+ | Complexity weight : 1
+ |
+ | Inputs :
+ |
+ | L_var3 32 bit long signed integer (Word32) whose value falls in the
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.
+ |
+ | var1 16 bit short signed integer (Word16) whose value falls in the
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff.
+ |
+ | var2 16 bit short signed integer (Word16) whose value falls in the
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff.
+ |
+ | Return Value :
+ |
+ | L_var_out
+ | 32 bit long signed integer (Word32) whose value falls in the
+ | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.
+ |___________________________________________________________________________
+*/
+Word32 L_mac0 (Word32 L_var3, Word16 var1, Word16 var2)
+{
+ Word32 L_var_out;
+ Word32 L_product;
+
+ L_product = L_mult0(var1,var2);
+ L_var_out = L_add(L_var3,L_product);
+
+ BASOP_CHECK();
+
+
+ return(L_var_out);
+}
+
+
+/*___________________________________________________________________________
+ |
+ | Function Name : L_msu0
+ |
+ | Purpose :
+ |
+ | Multiply var1 by var2 (without left shift) and subtract the 32 bit
+ | result to L_var3 with saturation, return a 32 bit result:
+ | L_msu0(L_var3,var1,var2) = L_sub(L_var3,(L_mult0(var1,var2)).
+ |
+ | Complexity weight : 1
+ |
+ | Inputs :
+ |
+ | L_var3 32 bit long signed integer (Word32) whose value falls in the
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.
+ |
+ | var1 16 bit short signed integer (Word16) whose value falls in the
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff.
+ |
+ | var2 16 bit short signed integer (Word16) whose value falls in the
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff.
+ |
+ | Return Value :
+ |
+ | L_var_out
+ | 32 bit long signed integer (Word32) whose value falls in the
+ | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.
+ |___________________________________________________________________________
+*/
+Word32 L_msu0 (Word32 L_var3, Word16 var1, Word16 var2)
+{
+ Word32 L_var_out;
+ Word32 L_product;
+
+ L_product = L_mult0(var1,var2);
+ L_var_out = L_sub(L_var3,L_product);
+
+ BASOP_CHECK();
+
+
+ return(L_var_out);
+}
+
+
+/* end of file */
diff --git a/lib_com/__zaloha/basop32.h b/lib_com/__zaloha/basop32.h
new file mode 100644
index 0000000000000000000000000000000000000000..f8126e961d3ea1edb9119cf4e34020cf780c1f84
--- /dev/null
+++ b/lib_com/__zaloha/basop32.h
@@ -0,0 +1,139 @@
+/*
+ ===========================================================================
+ File: BASOP32.H v.2.3 - 30.Nov.2009
+ ===========================================================================
+
+ ITU-T STL BASIC OPERATORS
+
+ GLOBAL FUNCTION PROTOTYPES
+
+ History:
+ 26.Jan.00 v1.0 Incorporated to the STL from updated G.723.1/G.729
+ basic operator library (based on basic_op.h) and
+ G.723.1's basop.h.
+ 05.Jul.00 v1.1 Added 32-bit shiftless mult/mac/msub operators
+
+ 03 Nov 04 v2.0 Incorporation of new 32-bit / 40-bit / control
+ operators for the ITU-T Standard Tool Library as
+ described in Geneva, 20-30 January 2004 WP 3/16 Q10/16
+ TD 11 document and subsequent discussions on the
+ wp3audio@yahoogroups.com email reflector.
+ norm_s() weight reduced from 15 to 1.
+ norm_l() weight reduced from 30 to 1.
+ L_abs() weight reduced from 2 to 1.
+ L_add() weight reduced from 2 to 1.
+ L_negate() weight reduced from 2 to 1.
+ L_shl() weight reduced from 2 to 1.
+ L_shr() weight reduced from 2 to 1.
+ L_sub() weight reduced from 2 to 1.
+ mac_r() weight reduced from 2 to 1.
+ msu_r() weight reduced from 2 to 1.
+ mult_r() weight reduced from 2 to 1.
+ L_deposit_h() weight reduced from 2 to 1.
+ L_deposit_l() weight reduced from 2 to 1.
+ L_mls() weight of 5.
+ div_l() weight of 32.
+ i_mult() weight of 3.
+
+ 30 Nov 09 v2.3 round() function is now round_fx().
+ saturate() is not referencable from outside application
+
+ 13 Mar 12 Add Overflow2 flag for additional overflow checking.
+ ============================================================================
+*/
+
+
+#ifndef _BASIC_OP_H
+#define _BASIC_OP_H
+
+/* #define BASOP_OVERFLOW2 */
+
+/*___________________________________________________________________________
+ | |
+ | Constants and Globals |
+ |___________________________________________________________________________|
+*/
+extern Flag Overflow, Overflow2;
+extern Flag Carry;
+
+#define BASOP_SATURATE_WARNING_ON
+#define BASOP_SATURATE_WARNING_OFF
+#define BASOP_SATURATE_ERROR_ON
+#define BASOP_SATURATE_ERROR_OFF
+#define BASOP_CHECK()
+
+
+#define MAX_32 (Word32)0x7fffffffL
+#define MIN_32 (Word32)0x80000000L
+
+#define MAX_16 (Word16)0x7fff
+#define MIN_16 (Word16)0x8000
+
+/*___________________________________________________________________________
+ | |
+ | Prototypes for basic arithmetic operators |
+ |___________________________________________________________________________|
+*/
+
+Word16 add (Word16 var1, Word16 var2); /* Short add, 1 */
+Word16 sub (Word16 var1, Word16 var2); /* Short sub, 1 */
+Word16 abs_s (Word16 var1); /* Short abs, 1 */
+Word16 shl (Word16 var1, Word16 var2); /* Short shift left, 1 */
+Word16 shr (Word16 var1, Word16 var2); /* Short shift right, 1 */
+Word16 mult (Word16 var1, Word16 var2); /* Short mult, 1 */
+Word32 L_mult (Word16 var1, Word16 var2); /* Long mult, 1 */
+Word16 negate (Word16 var1); /* Short negate, 1 */
+Word16 extract_h (Word32 L_var1); /* Extract high, 1 */
+Word16 extract_l (Word32 L_var1); /* Extract low, 1 */
+Word16 round_fx (Word32 L_var1); /* Round, 1 */
+Word32 L_mac (Word32 L_var3, Word16 var1, Word16 var2); /* Mac, 1 */
+Word32 L_msu (Word32 L_var3, Word16 var1, Word16 var2); /* Msu, 1 */
+Word32 L_macNs (Word32 L_var3, Word16 var1, Word16 var2); /* Mac without
+ sat, 1 */
+Word32 L_msuNs (Word32 L_var3, Word16 var1, Word16 var2); /* Msu without
+ sat, 1 */
+Word32 L_add (Word32 L_var1, Word32 L_var2); /* Long add, 1 */
+Word32 L_sub (Word32 L_var1, Word32 L_var2); /* Long sub, 1 */
+Word32 L_add_c (Word32 L_var1, Word32 L_var2); /* Long add with c, 2 */
+Word32 L_sub_c (Word32 L_var1, Word32 L_var2); /* Long sub with c, 2 */
+Word32 L_negate (Word32 L_var1); /* Long negate, 1 */
+Word16 mult_r (Word16 var1, Word16 var2); /* Mult with round, 1 */
+Word32 L_shl (Word32 L_var1, Word16 var2); /* Long shift left, 1 */
+Word32 L_shr (Word32 L_var1, Word16 var2); /* Long shift right, 1 */
+Word16 shr_r (Word16 var1, Word16 var2); /* Shift right with
+ round, 2 */
+Word16 mac_r (Word32 L_var3, Word16 var1, Word16 var2); /* Mac with
+ rounding, 1 */
+Word16 msu_r (Word32 L_var3, Word16 var1, Word16 var2); /* Msu with
+ rounding, 1 */
+Word32 L_deposit_h (Word16 var1); /* 16 bit var1 -> MSB, 1 */
+Word32 L_deposit_l (Word16 var1); /* 16 bit var1 -> LSB, 1 */
+
+Word32 L_shr_r (Word32 L_var1, Word16 var2); /* Long shift right with
+ round, 3 */
+Word32 L_abs (Word32 L_var1); /* Long abs, 1 */
+Word32 L_sat (Word32 L_var1); /* Long saturation, 4 */
+Word16 norm_s (Word16 var1); /* Short norm, 1 */
+Word16 div_s (Word16 var1, Word16 var2); /* Short division, 18 */
+Word16 norm_l (Word32 L_var1); /* Long norm, 1 */
+
+
+/*
+ * Additional G.723.1 operators
+*/
+Word32 L_mls( Word32, Word16 ) ; /* Weight FFS; currently assigned 5 */
+Word16 div_l( Word32, Word16 ) ; /* Weight FFS; currently assigned 32 */
+Word16 i_mult(Word16 a, Word16 b); /* Weight FFS; currently assigned 3 */
+
+/*
+ * New shiftless operators, not used in G.729/G.723.1
+*/
+Word32 L_mult0(Word16 v1, Word16 v2); /* 32-bit Multiply w/o shift 1 */
+Word32 L_mac0(Word32 L_v3, Word16 v1, Word16 v2); /* 32-bit Mac w/o shift 1 */
+Word32 L_msu0(Word32 L_v3, Word16 v1, Word16 v2); /* 32-bit Msu w/o shift 1 */
+
+
+#endif /* ifndef _BASIC_OP_H */
+
+
+/* end of file */
diff --git a/lib_com/__zaloha/basop_com_lpc.c b/lib_com/__zaloha/basop_com_lpc.c
new file mode 100644
index 0000000000000000000000000000000000000000..30075a1a733a682c661c4e70844ac3b7de5bb138
--- /dev/null
+++ b/lib_com/__zaloha/basop_com_lpc.c
@@ -0,0 +1,239 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include "wmc_auto.h"
+#include
+#include
+#include
+#include
+#include "typedef.h"
+#include "basop_proto_func.h"
+#include "cnst.h"
+
+#include "basop_util.h"
+#include "stl.h"
+
+#define WMC_TOOL_SKIP
+
+#define UNROLL_CHEBYSHEV_INNER_LOOP
+#define NC_MAX 8
+#define GUESS_TBL_SZ 256
+
+#define Madd_32_16(accu, x, y) L_add(accu, Mpy_32_16(x, y))
+#define Msub_32_16(accu, x, y) L_sub(accu, Mpy_32_16(x, y))
+
+
+/*
+ * weight_a
+ *
+ * Parameters:
+ * a I: LP filter coefficients Q12
+ * ap O: weighted LP filter coefficients Q12
+ * gamma I: weighting factor Q15
+ *
+ * Function:
+ * Weighting of LP filter coefficients, ap[i] = a[i] * (gamma^i).
+ *
+ * Returns:
+ * void
+ */
+void basop_weight_a(const Word16 *a, Word16 *ap, const Word16 gamma)
+{
+ Word16 i, fac;
+ Word32 Amax;
+ Word16 shift;
+
+
+
+ fac = gamma;
+ Amax = L_mult( 16384, a[0] );
+ FOR (i = 1; i < M; i++)
+ {
+ Amax = L_max( Amax, L_abs( L_mult0( fac, a[i] ) ) );
+ fac = mult_r( fac, gamma );
+ }
+ Amax = L_max( Amax, L_abs( L_mult0( fac, a[M] ) ) );
+ shift = norm_l( Amax );
+ fac = gamma;
+ ap[0] = shl( a[0], sub(shift,1) );
+ move16();
+ FOR (i = 1; i < M; i++)
+ {
+ ap[i] = round_fx(L_shl(L_mult0(a[i], fac),shift));
+ move16();
+ fac = mult_r( fac, gamma );
+ }
+ ap[M] = round_fx(L_shl(L_mult0(a[M], fac),shift));
+ move16();
+
+
+ return;
+}
+
+/*
+ * weight_a_inv
+ *
+ * Parameters:
+ * a I: LP filter coefficients Q12
+ * ap O: weighted LP filter coefficients Q12
+ * inv_gamma I: inverse weighting factor Q14
+ *
+ * Function:
+ * Weighting of LP filter coefficients, ap[i] = a[i] * (inv_gamma^i).
+ *
+ * Returns:
+ * void
+ */
+void basop_weight_a_inv(const Word16 *a, Word16 *ap, const Word16 inv_gamma)
+{
+ Word16 i;
+ static const Word16 inv_gamma_tab_12k8[16] = { 17809, 19357, 21041, 22870, 24859, 27020, 29370, 31924, /* Q14 */
+ 17350, 18859, 20499, 22281, 24219, 26325, 28614, 31102
+ }; /* Q13 */
+ static const Word16 inv_gamma_tab_16k[16] = { 17430, 18542, 19726, 20985, 22324, 23749, 25265, 26878, /* Q14 */
+ 14297, 15209, 16180, 17213, 18312, 19480, 20724, 22047
+ }; /* Q13 */
+ const Word16 *inv_gamma_tab;
+ Word32 L_tmp;
+ Word32 Amax;
+ Word16 shift;
+
+
+ IF (inv_gamma == 16384)
+ {
+ FOR (i = 0; i <= M; i++)
+ {
+ ap[i] = a[i];
+ move16();
+ }
+ return;
+ }
+
+ assert( inv_gamma==GAMMA1_INV || inv_gamma==GAMMA16k_INV );
+
+ inv_gamma_tab = inv_gamma_tab_12k8;
+ move16();
+ if (sub(inv_gamma,GAMMA16k_INV) == 0)
+ {
+ inv_gamma_tab = inv_gamma_tab_16k;
+ move16();
+ }
+
+ Amax = L_mult( 16384, a[0] );
+ FOR (i = 1; i < 9; i++)
+ {
+ Amax = L_max( Amax, L_abs( L_mult( a[i], inv_gamma_tab[i-1] ) ) );
+ }
+ FOR (i = 9; i < 17; i++)
+ {
+ Amax = L_max( Amax, L_abs( L_shl( L_mult( a[i], inv_gamma_tab[i-1] ), 1 ) ) );
+ }
+ shift = norm_l( Amax );
+ ap[0] = shl( a[0], sub(shift,1) );
+ move16();
+ FOR (i = 1; i < 9; i++)
+ {
+ L_tmp = L_mult( a[i], inv_gamma_tab[i-1] );
+ ap[i] = round_fx( L_shl( L_tmp, shift ) );
+ move16();
+ }
+ shift = add(shift,1);
+ FOR (i = 9; i < 17; i++)
+ {
+ L_tmp = L_mult( a[i], inv_gamma_tab[i-1] );
+ ap[i] = round_fx( L_shl( L_tmp, shift ) );
+ move16();
+ }
+
+
+ return;
+}
+
+/*
+ * basop_E_LPC_a_add_tilt
+ *
+ * Parameters:
+ * a I: LP filter coefficients (m+1 coeffs)
+ * ap O: modified LP filter coefficients (m+2 coeffs)
+ * gamma I: tilt factor
+ *
+ * Function:
+ * Modified LP filter by adding 1st order pre-premphasis, Ap(z)=A(z).(1-gamma.z^(-1))
+ *
+ * Returns:
+ * void
+ */
+void basop_E_LPC_a_add_tilt(const Word16 *a, Word16 *ap, Word16 gamma)
+{
+ Word16 i;
+ Word32 Amax, Atmp[M+2];
+ Word16 shift;
+
+
+
+
+ Amax = L_mult( 16384, a[0] );
+ FOR (i = 1; i <= M; i++)
+ {
+ Atmp[i] = L_sub( L_mult(16384, a[i]), L_mult0(gamma, a[i-1]) );
+ move32();
+ Amax = L_max( Amax, L_abs( Atmp[i] ) );
+ }
+ Atmp[M+1] = L_negate( L_mult0(gamma, a[M]) );
+ move32();
+ Amax = L_max( Amax, L_abs( Atmp[M+1] ) );
+ shift = norm_l( Amax );
+ ap[0] = shl( a[0], sub(shift,1) );
+ move16();
+ FOR (i = 1; i <= M; i++)
+ {
+ ap[i] = round_fx( L_shl( Atmp[i], shift ) );
+ move16();
+ }
+ ap[M+1] = round_fx( L_shl( Atmp[M+1], shift ) );
+ move16();
+
+ return;
+}
+
+
+
+static Word16 xsf_to_xsp(Word16 xsf)
+{
+ /* xsp = cos(xsf * 3.1415/6400); */
+ return getCosWord16R2(xsf);
+}
+
+/*
+ * lsf2lsp
+ *
+ * Parameters:
+ * lsf I: lsf[m] normalized (range: 0 <= val <= 0.5) x2.56
+ * lsp O: lsp[m] (range: -1 <= val < 1) Q15
+ *
+ * Function:
+ * Transformation lsf to lsp
+ *
+ * LSF are line spectral pair in frequency domain (0 to 6400).
+ * LSP are line spectral pair in cosine domain (-1 to 1).
+ *
+ * Returns:
+ * void
+ */
+void basop_lsf2lsp(const Word16 lsf[], Word16 lsp[])
+{
+ Word16 i;
+
+
+
+ /* convert ISFs to the cosine domain */
+ FOR (i = 0; i < M; i++)
+ {
+ *lsp++ = xsf_to_xsp(*lsf++);
+ move16();
+ }
+
+
+ return;
+}
diff --git a/lib_com/__zaloha/basop_lsf_tools.c b/lib_com/__zaloha/basop_lsf_tools.c
new file mode 100644
index 0000000000000000000000000000000000000000..bbb190850f64e0a73b78cfabafba8d70cd113589
--- /dev/null
+++ b/lib_com/__zaloha/basop_lsf_tools.c
@@ -0,0 +1,265 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+
+#include "wmc_auto.h"
+#include
+#include
+#include
+#include "basop_proto_func.h"
+#include "control.h"
+#include "basop_util.h"
+
+#define WMC_TOOL_SKIP
+
+#define NC_MAX 8
+
+static Word16 E_LPC_f_lsp_pol_get(const Word16 lsp[], Word32 f[], const Word16 n, const Word16 past_Ovf, const Word16 isMODE1);
+
+
+/*
+ * E_LPC_f_lsp_a_conversion
+ *
+ * Parameters:
+ * lsp I: Line spectral pairs Q15
+ * a O: Predictor coefficients (order = m) Qx (The Q factor of the output to be deduced from a(0))
+ * m I: order of LP filter
+ *
+ * Function:
+ * Convert ISPs to predictor coefficients a[]
+ *
+ * Returns:
+ * void
+ */
+void basop_E_LPC_f_lsp_a_conversion(const Word16 *lsp, Word16 *a, const Word16 m)
+{
+ Word16 i, j, k;
+ Word32 f1[NC_MAX+1], f2[NC_MAX+1];
+ Word16 nc;
+ Word32 t0;
+ Word16 Ovf, Ovf2;
+
+
+ /*-----------------------------------------------------*
+ * Find the polynomials F1(z) and F2(z) *
+ *-----------------------------------------------------*/
+
+ nc = shr(m, 1);
+
+ assert(m == 16 || m == 10);
+
+ Ovf = 0;
+ move16();
+ Ovf = E_LPC_f_lsp_pol_get(&lsp[0], f1, nc, Ovf, 1);
+ Ovf2 = E_LPC_f_lsp_pol_get(&lsp[1], f2, nc, Ovf, 1);
+ IF(sub(Ovf2,Ovf) !=0)
+ {
+ /* to ensure similar scaling for f1 and f2 in case
+ an overflow would be detected only in f2,
+ but this case never happen on my dtb */
+ E_LPC_f_lsp_pol_get(&lsp[0], f1, nc, s_max(Ovf2,Ovf), 1);
+ }
+ /*-----------------------------------------------------*
+ * Multiply F1(z) by (1+z^-1) and F2(z) by (1-z^-1) *
+ *-----------------------------------------------------*/
+ /*modification*/
+ k = sub(nc,1);
+ FOR (i = 0; i <= k; i++)
+ {
+ f1[nc-i] = L_add(f1[nc-i],f1[nc-i-1]);
+ move32();
+ f2[nc-i] = L_sub(f2[nc-i],f2[nc-i-1]);
+ move32();
+ }
+
+ /*-----------------------------------------------------*
+ * A(z) = (F1(z)+F2(z))/2 *
+ * F1(z) is symmetric and F2(z) is antisymmetric *
+ *-----------------------------------------------------*/
+
+ t0 = L_deposit_l(0);
+ FOR (i = 1; i <= nc; i++)
+ {
+ t0 = L_max( t0, L_abs(L_add(f1[i], f2[i])) );
+ t0 = L_max( t0, L_abs(L_sub(f1[i], f2[i])) );
+ }
+ k = s_min( norm_l(t0), 6 );
+ a[0] = shl( 256, k );
+ move16();
+ test();
+ IF( Ovf || Ovf2)
+ {
+ a[0] = shl( 256, sub(k,Ovf) );
+ move16();
+ }
+ j = m;
+ FOR (i = 1; i <= nc; i++)
+ {
+ /* a[i] = 0.5*(f1[i] + f2[i]) */
+ t0 = L_add(f1[i],f2[i]);
+ t0 = L_shl(t0, k);
+ a[i] = round_fx(t0); /* from Q23 to Qx and * 0.5 */
+
+ /* a[j] = 0.5*(f1[i] - f2[i]) */
+ t0 = L_sub(f1[i],f2[i]);
+ t0 = L_shl(t0, k);
+ a[j] = round_fx(t0); /* from Q23 to Qx and * 0.5 */
+ j--;
+ }
+
+ return;
+}
+
+
+/*---------------------------------------------------------------------------
+* procedure reorder_lsf()
+*
+* To make sure that the lsfs are properly ordered and to keep a certain
+* minimum distance between consecutive lsfs.
+*--------------------------------------------------------------------------*/
+void basop_reorder_lsf(
+ Word16 *lsf, /* i/o: LSFs in the frequency domain (0..0.5) Q(x2.56)*/
+ const Word16 min_dist, /* i : minimum required distance x2.56*/
+ const Word16 n, /* i : LPC order */
+ const Word32 fs /* i : sampling frequency */
+)
+{
+ Word16 i, lsf_min, n_m_1;
+ Word16 lsf_max;
+
+ lsf_min = min_dist;
+ move16();
+
+ /*-----------------------------------------------------------------------*
+ * Verify the LSF ordering and minimum GAP
+ *-----------------------------------------------------------------------*/
+
+ FOR (i = 0; i < n; i++)
+ {
+ if (sub(lsf[i], lsf_min) < 0)
+ {
+ lsf[i] = lsf_min;
+ move16();
+ }
+ lsf_min = add(lsf[i], min_dist);
+ }
+
+ /*-----------------------------------------------------------------------*
+ * Reverify the LSF ordering and minimum GAP in the reverse order (security)
+ *-----------------------------------------------------------------------*/
+ lsf_max = round_fx(L_sub(L_shr(L_mult0(extract_l(L_shr(fs,1)), 1311),9-16), L_deposit_h(min_dist))); /* Q0 + Q9 , 1311 is 2.56 in Q9 */
+ n_m_1 = sub(n,1);
+ IF (sub(lsf[n_m_1], lsf_max) > 0) /* If danger of unstable filter in case of resonance in HF */
+ {
+ FOR (i = n_m_1; i >= 0; i--) /* Reverify the minimum LSF gap in the reverse direction */
+ {
+ if (sub(lsf[i], lsf_max) > 0)
+ {
+ lsf[i] = lsf_max;
+ move16();
+ }
+ lsf_max = sub(lsf[i], min_dist);
+ }
+ }
+}
+
+
+/*
+ * E_LPC_f_lsp_pol_get
+ *
+ * Parameters:
+ * lsp/isp I: Line spectral pairs (cosine domaine) Q15
+ * f O: the coefficients of F1 or F2 Q23
+ * n I: no of coefficients (m/2)
+ * == NC for F1(z); == NC-1 for F2(z)
+ * fact I: scaling factor
+ *
+ *-----------------------------------------------------------*
+ * procedure E_LPC_f_lsp_pol_get: *
+ * ~~~~~~~~~~~ *
+ * Find the polynomial F1(z) or F2(z) from the LSPs. *
+ * This is performed by expanding the product polynomials: *
+ * *
+ * F1(z) = product ( 1 - 2 LSF_i z^-1 + z^-2 ) *
+ * i=0,2,4,6,8 *
+ * F2(z) = product ( 1 - 2 LSF_i z^-1 + z^-2 ) *
+ * i=1,3,5,7,9 *
+ * *
+ * where LSP_i are the LSPs in the cosine domain. *
+ * *
+ *-----------------------------------------------------------*
+ * R.A.Salami October 1990 *
+ *-----------------------------------------------------------*
+ */
+static
+Word16 E_LPC_f_lsp_pol_get(const Word16 lsp[], Word32 f[], const Word16 n, const Word16 past_Ovf, const Word16 isMODE1)
+{
+ /* All computation in Q23 */
+ const Word16 *plsp;
+ Word16 i, j;
+ Word16 b;
+ Word32 b32;
+ Word16 Ovf = 0;
+ Word16 Q_out;
+ Word16 m2;
+
+
+ Q_out = 31-23;
+ move16();
+ Ovf = past_Ovf;
+ move16();
+
+ test();
+ if(past_Ovf && isMODE1) /* Currently this feature is implemented only in MODE1 */
+ {
+ /* In some NB cases, overflow where detectected
+ in f1 or f2 polynomial computation when it
+ happen we reduce the precision of the computing
+ to limit the risk of saturation*/
+ Q_out = add(Q_out, past_Ovf);
+ }
+ Overflow = 0;
+ move16();
+ plsp = lsp;
+ f[0] = L_shl(1, sub(31, Q_out));
+ move32();
+ /*b = -2.0f * *plsp;*/
+ b = *plsp;
+ move16();
+ m2 = shl(-2, sub(15, Q_out));
+ f[1] = L_mult(b, m2);
+ move32();
+
+ FOR (i = 2; i <= n; i++)
+ {
+ plsp += 2;
+ /*b = 2.0f * *plsp;*/
+ move16();
+ b = *plsp;
+ b32 = L_mult(b, m2);
+
+ /*f[i] = -b*f[i-1] + 2.0f*f[i-2];*/
+ move32();
+ f[i] = L_shl(L_sub(f[i-2], Mpy_32_16(f[i-1], b)),1);
+
+ FOR (j = i-1; j > 1; j--)
+ {
+ /*f[j] += b*f[j-1] + f[j-2];*/
+ move32();
+ f[j] = L_add(f[j], L_sub(f[j-2], L_shl(Mpy_32_16(f[j-1], b),1)));
+ }
+ move32();
+ f[1] = L_add(f[1], b32);
+ }
+
+
+ test();
+ IF (Overflow>0 && isMODE1)
+ {
+ /* If an overflow is detected, redo the computation with 1 bit less */
+ Ovf = add(Ovf,1);
+ Ovf = E_LPC_f_lsp_pol_get(lsp, f, n ,Ovf, isMODE1);
+ }
+ return Ovf;
+}
diff --git a/lib_com/__zaloha/basop_mpy.c b/lib_com/__zaloha/basop_mpy.c
new file mode 100644
index 0000000000000000000000000000000000000000..bf5ae96d2a58e8b137d2931bee16831972b02aed
--- /dev/null
+++ b/lib_com/__zaloha/basop_mpy.c
@@ -0,0 +1,56 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+
+#include "wmc_auto.h"
+#include "basop_mpy.h"
+#include "options.h"
+
+#define WMC_TOOL_SKIP
+
+Word32 Mpy_32_16_1(Word32 x, Word16 y)
+{
+ Word32 mh;
+ UWord16 ml;
+
+ Mpy_32_16_ss(x, y, &mh, &ml);
+
+ return (mh);
+}
+
+Word32 Mpy_32_16(Word32 x, Word16 y)
+{
+ Word32 mh;
+ UWord16 ml;
+
+ Mpy_32_16_ss(x, y, &mh, &ml);
+
+ return (mh);
+}
+
+Word32 Mpy_32_16_r(Word32 x, Word16 y)
+{
+ Word32 mh;
+ UWord16 ml;
+
+ Mpy_32_16_ss(x, y, &mh, &ml);
+
+ if(s_and(ml, -32768 /* 0x8000 */))
+ {
+ mh = L_add(mh, 1);
+ }
+
+ return (mh);
+}
+
+
+Word32 Mpy_32_32(Word32 x, Word32 y)
+{
+ Word32 mh;
+ UWord32 ml;
+
+ Mpy_32_32_ss(x, y, &mh, &ml);
+
+ return (mh);
+}
diff --git a/lib_com/__zaloha/basop_mpy.h b/lib_com/__zaloha/basop_mpy.h
new file mode 100644
index 0000000000000000000000000000000000000000..be62d6aa4b345e15c88cea84e19dc70f624c1a87
--- /dev/null
+++ b/lib_com/__zaloha/basop_mpy.h
@@ -0,0 +1,67 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#ifndef __BASOP_MPY_H
+#define __BASOP_MPY_H
+
+#include "stl.h"
+#include "options.h"
+
+/**
+ * \brief 32*16 Bit fractional Multiplication using 40 bit OPS
+ * Performs a multiplication of a 32-bit variable x by
+ * a 16-bit variable y, returning a 32-bit value.
+ *
+ * \param[i] x
+ * \param[i] y
+ *
+ * \return x*y
+ */
+Word32 Mpy_32_16_1(Word32 x,
+ Word16 y);
+
+
+/**
+ * \brief 32*16 Bit fractional Multiplication using 40 bit OPS
+ * Performs a multiplication of a 32-bit variable x by
+ * a 16-bit variable y, returning a 32-bit value.
+ *
+ * \param[i] x
+ * \param[i] y
+ *
+ * \return x*y
+ */
+Word32 Mpy_32_16(Word32 x,
+ Word16 y);
+
+
+/**
+ * \brief 32*16 Bit fractional Multiplication using 40 bit OPS
+ * Performs a multiplication of a 32-bit variable x by
+ * a 16-bit variable y including rounding, returning a 32-bit value.
+ *
+ * \param[i] x
+ * \param[i] y
+ *
+ * \return x*y
+ */
+Word32 Mpy_32_16_r(Word32 x, Word16 y);
+
+
+/**
+ * \brief 32*32 Bit fractional Multiplication using 40 bit OPS
+ *
+ * Performs a multiplication of a 32-bit variable x by
+ * a 32-bit variable y, returning a 32-bit value.
+ *
+ * \param[i] x
+ * \param[i] y
+ *
+ * \return x*y
+ */
+
+Word32 Mpy_32_32(Word32 x,
+ Word32 y);
+
+#endif /* __BASOP_SETTINGS_H */
diff --git a/lib_com/__zaloha/basop_proto_func.h b/lib_com/__zaloha/basop_proto_func.h
new file mode 100644
index 0000000000000000000000000000000000000000..804b8d750a72283f8cd8f0faf769e74ffa203125
--- /dev/null
+++ b/lib_com/__zaloha/basop_proto_func.h
@@ -0,0 +1,39 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#ifndef BASOP_PROTO_FUNC_H
+#define BASOP_PROTO_FUNC_H
+
+#include "stl.h"
+#include "basop_util.h"
+
+
+/* tcx_lpc_cdk.h */
+#define LSF_GAP_VAL(x) (Word16)((x)*2.0f*1.28f)
+#define LSFM(x) FL2WORD16_SCALE(x*1.28, 15-1) /* 14Q1*1.28 */
+
+/* cnst.h */
+#define GAMMA1_INV 17809 /* weighting factor (numerator) default:0.92 (1Q14format) */
+#define GAMMA16k_INV 17430 /* weighting factor (numerator) default:0.94 (1Q14format) */
+#define FS_2 16384 /* isf max value (Use in reorder_fx.c) */
+#define INT_FS_FX 12800 /* internal sampling frequency */
+
+void basop_lsp2a_stab(const Word16 *lsp, Word16 *a);
+void basop_lsf2lsp(const Word16 lsf[], Word16 lsp[]);
+void basop_weight_a(const Word16 *a, Word16 *ap, const Word16 gamma);
+void basop_weight_a_inv(const Word16 *a, Word16 *ap, const Word16 inv_gamma);
+void basop_E_LPC_a_add_tilt(const Word16 *a, Word16 *ap, Word16 gamma);
+void basop_reorder_lsf(Word16 *lsf, const Word16 min_dist, const Word16 n, const Word32 fs);
+void basop_E_LPC_f_lsp_a_conversion(const Word16 *lsp, Word16 *a, const Word16 m);
+
+/* tcx_utils.c */
+void basop_lpc2mdct(Word16 *lpcCoeffs, Word16 lpcOrder,
+ Word16 *mdct_gains, Word16 *mdct_gains_exp,
+ Word16 *mdct_inv_gains, Word16 *mdct_inv_gains_exp);
+
+void basop_PsychAdaptLowFreqDeemph(Word32 x[], const Word16 lpcGains[], const Word16 lpcGains_e[], Word16 lf_deemph_factors[]);
+void basop_mdct_noiseShaping_interp(Word32 x[], Word16 lg, Word16 gains[], Word16 gains_exp[]);
+
+
+#endif
diff --git a/lib_com/__zaloha/basop_settings.h b/lib_com/__zaloha/basop_settings.h
new file mode 100644
index 0000000000000000000000000000000000000000..62f706e10771e28f7c8e5957f56c376a4ea6b8d7
--- /dev/null
+++ b/lib_com/__zaloha/basop_settings.h
@@ -0,0 +1,85 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#ifndef __BASOP_SETTINGS_H
+#define __BASOP_SETTINGS_H
+
+#include "stl.h"
+#include "basop_mpy.h"
+
+#define _LONG long
+#define _SHORT short
+#ifdef _WIN32
+#define _INT64 __int64
+#else
+#define _INT64 long long
+#endif
+
+#define WORD32_BITS 32
+#define MAXVAL_WORD32 ((signed)0x7FFFFFFF)
+#define MINVAL_WORD32 ((signed)0x80000000)
+#define WORD32_FIX_SCALE ((_INT64)(1)<<(WORD32_BITS-1))
+
+#define WORD16_BITS 16
+#define MAXVAL_WORD16 (((signed)0x7FFFFFFF)>>16)
+#define MINVAL_WORD16 (((signed)0x80000000)>>16)
+#define WORD16_FIX_SCALE ((_INT64)(1)<<(WORD16_BITS-1))
+
+/*!
+ \def Macro converts a float < 1 to Word32 fixed point with saturation and rounding
+*/
+#define FL2WORD32(val) \
+(Word32)( ( (val) >= 0) ? \
+((( (double)(val) * (WORD32_FIX_SCALE) + 0.5 ) >= (double)(MAXVAL_WORD32) ) ? (_LONG)(MAXVAL_WORD32) : (_LONG)( (double)(val) * (double)(WORD32_FIX_SCALE) + 0.5)) : \
+((( (double)(val) * (WORD32_FIX_SCALE) - 0.5) <= (double)(MINVAL_WORD32) ) ? (_LONG)(MINVAL_WORD32) : (_LONG)( (double)(val) * (double)(WORD32_FIX_SCALE) - 0.5)) )
+
+/*!
+ \def Macro converts a float < 1 to Word16 fixed point with saturation and rounding
+*/
+#define FL2WORD16(val) \
+(Word16)( ( (val) >= 0) ? \
+((( (double)(val) * (WORD16_FIX_SCALE) + 0.5 ) >= (double)(MAXVAL_WORD16) ) ? (_LONG)(MAXVAL_WORD16) : (_LONG)( (double)(val) * (double)(WORD16_FIX_SCALE) + 0.5)) : \
+((( (double)(val) * (WORD16_FIX_SCALE) - 0.5) <= (double)(MINVAL_WORD16) ) ? (_LONG)(MINVAL_WORD16) : (_LONG)( (double)(val) * (double)(WORD16_FIX_SCALE) - 0.5)) )
+
+/*!
+ \def Macro converts a Word32 fixed point to Word16 fixed point <1 with saturation
+*/
+#define WORD322WORD16(val) \
+ ( ( ((((val) >> (WORD32_BITS-WORD16_BITS-1)) + 1) > (((_LONG)1< 0) ) ? \
+ (Word16)(_SHORT)(((_LONG)1<<(WORD16_BITS-1))-1):(Word16)(_SHORT)((((val) >> (WORD32_BITS-WORD16_BITS-1)) + 1) >> 1) )
+
+/*!
+ \def Macro converts a Word32 fixed point < 1 to float shifts result left by scale
+*/
+#define WORD322FL_SCALE(x,scale) ( ((float)((_LONG)(x))) / (((_INT64)1<<(WORD32_BITS-1 - (scale)))) )
+
+/*!
+ \def Macro converts a float < 1 to Word32 fixed point with saturation and rounding, shifts result right by scale
+*/
+/* Note: Both x and scale must be constants at compile time, scale must be in range -31..31 */
+#define FL2WORD32_SCALE(x,scale) FL2WORD32((double)(x) *(((_INT64)1<<(WORD32_BITS-1 - (scale)))) / ((_INT64)1<<(WORD32_BITS-1)))
+
+/*!
+ \def Macro converts a Word16 fixed point < 1 to float shifts result left by scale
+*/
+#define WORD162FL_SCALE(x,scale) ( ((float)((_LONG)(x))) / (((_INT64)1<<(WORD16_BITS-1 - (scale)))) )
+
+/*!
+ \def Macro converts a float < 1 to Word16 fixed point with saturation and rounding, shifts result right by scale
+*/
+/* Note: At compile time, x must be a float constant and scale must be an integer constant in range -15..15 */
+#define FL2WORD16_SCALE(x,scale) FL2WORD16((float)(x) *(((_INT64)1<<(WORD16_BITS-1 - (scale)))) / ((_INT64)1<<(WORD16_BITS-1)))
+
+
+/* Word16 Packed Type */
+typedef struct
+{
+ struct
+ {
+ Word16 re;
+ Word16 im;
+ } v;
+} PWord16;
+
+#endif /* __BASOP_SETTINGS_H */
diff --git a/lib_com/__zaloha/basop_tcx_utils.c b/lib_com/__zaloha/basop_tcx_utils.c
new file mode 100644
index 0000000000000000000000000000000000000000..92bb558cb61205463a96323a9b3f45889f5ab147
--- /dev/null
+++ b/lib_com/__zaloha/basop_tcx_utils.c
@@ -0,0 +1,406 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include
+#include
+#include
+#include "options.h"
+#include "cnst.h"
+#include "basop_proto_func.h"
+#include "stl.h"
+#include "prot.h"
+#include "rom_com.h"
+#include "wmc_auto.h"
+
+#define WMC_TOOL_SKIP
+
+/* compare two positive normalized 16 bit mantissa/exponent values */
+/* return value: positive if first value greater, negative if second value greater, zero if equal */
+static Word16 compMantExp16Unorm(Word16 m1, Word16 e1, Word16 m2, Word16 e2)
+{
+ Word16 tmp;
+
+ assert((m1 >= 0x4000) && (m2 >= 0x4000)); /* comparisons below work only for normalized mantissas */
+
+ tmp = sub(e1, e2);
+ if (tmp == 0) tmp = sub(m1, m2);
+
+ return tmp;
+}
+
+void basop_lpc2mdct(Word16 *lpcCoeffs, Word16 lpcOrder,
+ Word16 *mdct_gains, Word16 *mdct_gains_exp,
+ Word16 *mdct_inv_gains, Word16 *mdct_inv_gains_exp)
+{
+ Word32 RealData[FDNS_NPTS];
+ Word32 ImagData[FDNS_NPTS];
+ Word16 i, j, k, step, scale, s, tmp16;
+ Word16 g, g_e, ig, ig_e;
+ Word32 tmp32;
+ const PWord16 *ptwiddle;
+
+
+
+ /* short-cut, to avoid calling of BASOP_getTables() */
+ ptwiddle = SineTable512_fx;
+ step = 8;
+
+ /*ODFT*/
+ assert(lpcOrder < FDNS_NPTS);
+
+ /* pre-twiddle */
+ FOR (i=0; i<=lpcOrder; i++)
+ {
+ RealData[i] = L_mult(lpcCoeffs[i], ptwiddle->v.re);
+ move32();
+ ImagData[i] = L_negate(L_mult(lpcCoeffs[i], ptwiddle->v.im));
+ move32();
+ ptwiddle += step;
+ }
+
+ /* zero padding */
+ FOR ( ; i 0) pg = shr(pg, tmp);
+ if (tmp < 0) g = shl(g, tmp);
+ e = s_max(gains_exp[j], gains_exp[jp]);
+
+ tmp = mac_r(L_mult(pg, FL2WORD16(0.375f)), g, FL2WORD16(0.625f));
+ x[i] = L_shl(Mpy_32_16(x[i], tmp), e);
+ move32();
+
+ tmp = mac_r(L_mult(pg, FL2WORD16(0.125f)), g, FL2WORD16(0.875f));
+ x[i+1] = L_shl(Mpy_32_16(x[i+1], tmp), e);
+ move32();
+
+ /* common exponent for g and ng */
+ g = gains[j];
+ move16();
+ tmp = sub(gains_exp[j], gains_exp[jn]);
+ if (tmp > 0) ng = shr(ng, tmp);
+ if (tmp < 0) g = shl(g, tmp);
+ e = s_max(gains_exp[j], gains_exp[jn]);
+
+ tmp = mac_r(L_mult(g, FL2WORD16(0.875f)), ng, FL2WORD16(0.125f));
+ x[i+2] = L_shl(Mpy_32_16(x[i+2], tmp), e);
+ move32();
+
+ tmp = mac_r(L_mult(g, FL2WORD16(0.625f)), ng, FL2WORD16(0.375f));
+ x[i+3] = L_shl(Mpy_32_16(x[i+3], tmp), e);
+ move32();
+
+ jp = j;
+ move16();
+ j = jn;
+ move16();
+ jn = s_min(add(jn, 1), FDNS_NPTS-1);
+ }
+ }
+ ELSE IF (sub(k, 5) == 0)
+ {
+ jp = 0;
+ move16();
+ j = 0;
+ move16();
+ jn = 1;
+ move16();
+
+ FOR (i = 0; i < lg; i += 5)
+ {
+ pg = gains[jp];
+ move16();
+ g = gains[j];
+ move16();
+ ng = gains[jn];
+ move16();
+
+ /* common exponent for pg and g */
+ tmp = sub(gains_exp[j], gains_exp[jp]);
+ if (tmp > 0) pg = shr(pg, tmp);
+ if (tmp < 0) g = shl(g, tmp);
+ e = s_max(gains_exp[j], gains_exp[jp]);
+
+ tmp = mac_r(L_mult(pg, FL2WORD16(0.40f)), g, FL2WORD16(0.60f));
+ x[i] = L_shl(Mpy_32_16(x[i], tmp), e);
+ move32();
+
+ tmp = mac_r(L_mult(pg, FL2WORD16(0.20f)), g, FL2WORD16(0.80f));
+ x[i+1] = L_shl(Mpy_32_16(x[i+1], tmp), e);
+ move32();
+
+
+ x[i+2] = L_shl(Mpy_32_16(x[i+2], gains[j]), gains_exp[j]);
+ move32();
+
+ /* common exponent for g and ng */
+ g = gains[j];
+ move16();
+ tmp = sub(gains_exp[j], gains_exp[jn]);
+ if (tmp > 0) ng = shr(ng, tmp);
+ if (tmp < 0) g = shl(g, tmp);
+ e = s_max(gains_exp[j], gains_exp[jn]);
+
+ tmp = mac_r(L_mult(g, FL2WORD16(0.80f)), ng, FL2WORD16(0.20f));
+ x[i+3] = L_shl(Mpy_32_16(x[i+3], tmp), e);
+ move32();
+
+ tmp = mac_r(L_mult(g, FL2WORD16(0.60f)), ng, FL2WORD16(0.40f));
+ x[i+4] = L_shl(Mpy_32_16(x[i+4], tmp), e);
+ move32();
+
+ jp = j;
+ move16();
+ j = jn;
+ move16();
+ jn = s_min(add(jn, 1), FDNS_NPTS-1);
+ }
+ }
+ ELSE /* no interpolation */
+ {
+ FOR (i = 0; i < FDNS_NPTS; i++)
+ {
+ FOR (l = 0; l < k; l++)
+ {
+ *x = L_shl(Mpy_32_16(*x, *gains), *gains_exp);
+ move32();
+ x++;
+ }
+
+ gains++;
+ gains_exp++;
+ }
+ }
+ }
+
+}
+
+
+void basop_PsychAdaptLowFreqDeemph(Word32 x[],
+ const Word16 lpcGains[], const Word16 lpcGains_e[],
+ Word16 lf_deemph_factors[]
+ )
+{
+ Word16 i;
+ Word16 max, max_e, fac, min, min_e, tmp, tmp_e;
+ Word32 L_tmp;
+
+
+
+ assert(lpcGains[0] >= 0x4000);
+
+ max = lpcGains[0];
+ move16();
+ max_e = lpcGains_e[0];
+ move16();
+ min = lpcGains[0];
+ move16();
+ min_e = lpcGains_e[0];
+ move16();
+
+ /* find minimum (min) and maximum (max) of LPC gains in low frequencies */
+ FOR (i = 1; i < 9; i++)
+ {
+ IF (compMantExp16Unorm(lpcGains[i], lpcGains_e[i], min, min_e) < 0)
+ {
+ min = lpcGains[i];
+ move16();
+ min_e = lpcGains_e[i];
+ move16();
+ }
+
+ IF (compMantExp16Unorm(lpcGains[i], lpcGains_e[i], max, max_e) > 0)
+ {
+ max = lpcGains[i];
+ move16();
+ max_e = lpcGains_e[i];
+ move16();
+ }
+ }
+
+ min_e = add(min_e, 5); /* min *= 32.0f; */
+
+ test();
+ IF ((compMantExp16Unorm(max, max_e, min, min_e) < 0) && (min > 0))
+ {
+ /* fac = tmp = (float)pow(max / min, 0.0078125f); */
+ tmp_e = min_e;
+ move16();
+ tmp = Inv16(min, &tmp_e);
+ L_tmp = L_shl(L_mult(tmp, max), add(tmp_e, max_e)); /* Q31 */
+ L_tmp = BASOP_Util_Log2(L_tmp); /* Q25 */
+ L_tmp = L_shr(L_tmp, 7); /* 0.0078125f = 1.f/(1<<7) */
+ L_tmp = BASOP_Util_InvLog2(L_tmp); /* Q31 */
+ tmp = round_fx(L_tmp); /* Q15 */
+ fac = tmp; /* Q15 */ move16();
+
+ /* gradual lowering of lowest 32 bins; DC is lowered by (max/tmp)^1/4 */
+ FOR (i = 31; i >= 0; i--)
+ {
+ x[i] = Mpy_32_16(x[i], fac);
+ move32();
+ if (lf_deemph_factors != NULL)
+ {
+ lf_deemph_factors[i] = mult_r(lf_deemph_factors[i], fac);
+ move16();
+ }
+ fac = mult_r(fac, tmp);
+ }
+ }
+
+}
diff --git a/lib_com/__zaloha/basop_util.c b/lib_com/__zaloha/basop_util.c
new file mode 100644
index 0000000000000000000000000000000000000000..71edca7bd2a0ad5a4363804ab5504270dbb8f9b4
--- /dev/null
+++ b/lib_com/__zaloha/basop_util.c
@@ -0,0 +1,1044 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include "wmc_auto.h"
+#include
+#include
+#include "options.h"
+#include "basop_util.h"
+#include "rom_com.h"
+#include "basop_settings.h"
+#include "basop_mpy.h"
+#include "control.h"
+#include "cnst.h"
+
+#define WMC_TOOL_SKIP
+
+
+extern const Word32 SqrtTable[32];
+extern const Word16 SqrtDiffTable[32];
+
+extern const Word32 ISqrtTable[32];
+extern const Word16 ISqrtDiffTable[32];
+
+extern const Word32 InvTable[32];
+extern const Word16 InvDiffTable[32];
+
+
+Word32 BASOP_Util_Log2(Word32 x)
+{
+ Word32 exp;
+ Word16 exp_e;
+ Word16 nIn;
+ Word16 accuSqr;
+ Word32 accuRes;
+
+ assert(x >= 0);
+
+ if (x == 0)
+ {
+ return ((Word32)MIN_32);
+ }
+
+ /* normalize input, calculate integer part */
+ exp_e = norm_l(x);
+ x = L_shl(x,exp_e);
+ exp = L_deposit_l(exp_e);
+
+ /* calculate (1-normalized_input) */
+ nIn = extract_h(L_sub(MAX_32,x));
+
+ /* approximate ln() for fractional part (nIn *c0 + nIn^2*c1 + nIn^3*c2 + ... + nIn^8 *c7) */
+
+ /* iteration 1, no need for accumulation */
+ accuRes = L_mult(nIn,ldCoeff[0]); /* nIn^i * coeff[0] */
+ accuSqr = mult(nIn,nIn); /* nIn^2, nIn^3 .... */
+
+ /* iteration 2 */
+ accuRes = L_mac(accuRes,accuSqr,ldCoeff[1]); /* nIn^i * coeff[1] */
+ accuSqr = mult(accuSqr,nIn); /* nIn^2, nIn^3 .... */
+
+ /* iteration 3 */
+ accuRes = L_mac(accuRes,accuSqr,ldCoeff[2]); /* nIn^i * coeff[2] */
+ accuSqr = mult(accuSqr,nIn); /* nIn^2, nIn^3 .... */
+
+ /* iteration 4 */
+ accuRes = L_mac(accuRes,accuSqr,ldCoeff[3]); /* nIn^i * coeff[3] */
+ accuSqr = mult(accuSqr,nIn); /* nIn^2, nIn^3 .... */
+
+ /* iteration 5 */
+ accuRes = L_mac(accuRes,accuSqr,ldCoeff[4]); /* nIn^i * coeff[4] */
+ accuSqr = mult(accuSqr,nIn); /* nIn^2, nIn^3 .... */
+
+ /* iteration 6 */
+ accuRes = L_mac(accuRes,accuSqr,ldCoeff[5]); /* nIn^i * coeff[5] */
+ accuSqr = mult(accuSqr,nIn); /* nIn^2, nIn^3 .... */
+
+ /* iteration 7, no need to calculate accuSqr any more */
+ accuRes = L_mac(accuRes,accuSqr,ldCoeff[6]); /* nIn^i * coeff[6] */
+
+ /* ld(fractional part) = ln(fractional part)/ln(2), 1/ln(2) = (1 + 0.44269504) */
+ accuRes = L_mac0(L_shr(accuRes,1),extract_h(accuRes),14506);
+
+ accuRes = L_shr(accuRes,LD_DATA_SCALE-1); /* fractional part/LD_DATA_SCALE */
+ exp = L_shl(exp,(31-LD_DATA_SCALE)); /* integer part/LD_DATA_SCALE */
+ accuRes = L_sub(accuRes,exp); /* result = integer part + fractional part */
+
+ return (accuRes);
+}
+
+
+Word32 BASOP_Util_InvLog2(Word32 x)
+{
+ Word16 frac;
+ Word16 exp;
+ Word32 retVal;
+ UWord32 index3;
+ UWord32 index2;
+ UWord32 index1;
+ UWord32 lookup3f;
+ UWord32 lookup12;
+ UWord32 lookup;
+
+ if ( x < FL2WORD32(-31.0/64.0) )
+ {
+ return 0;
+ }
+ test();
+ if ( (L_sub(x,FL2WORD32(31.0/64.0)) >= 0) || (x == 0) )
+ {
+ return 0x7FFFFFFF;
+ }
+
+ frac = extract_l(L_and(x,0x3FF));
+
+ index3 = L_and(L_shr(x,10),0x1F);
+ index2 = L_and(L_shr(x,15),0x1F);
+ index1 = L_and(L_shr(x,20),0x1F);
+
+ exp = extract_l(L_shr(x,25));
+ if ( x > 0 )
+ {
+ exp = sub(31,exp);
+ }
+ if ( x < 0 )
+ {
+ exp = negate(exp);
+ }
+
+ lookup3f = L_add(exp2x_tab_long[index3],L_shr(Mpy_32_16(0x0016302F,frac),1));
+ lookup12 = Mpy_32_32(exp2_tab_long[index1],exp2w_tab_long[index2]);
+ lookup = Mpy_32_32(lookup12, lookup3f);
+
+ retVal = L_shr(lookup,sub(exp,3));
+
+ return retVal;
+}
+
+
+Word16 BASOP_Util_Add_MantExp /*!< Exponent of result */
+(Word16 a_m, /*!< Mantissa of 1st operand a */
+ Word16 a_e, /*!< Exponent of 1st operand a */
+ Word16 b_m, /*!< Mantissa of 2nd operand b */
+ Word16 b_e, /*!< Exponent of 2nd operand b */
+ Word16 *ptrSum_m) /*!< Mantissa of result */
+{
+ Word32 L_lm, L_hm;
+ Word16 shift;
+
+ /* Compare exponents: the difference is limited to +/- 15
+ The Word16 mantissa of the operand with higher exponent is moved into the low
+ part of a Word32 and shifted left by the exponent difference. Then, the
+ unshifted mantissa of the operand with the lower exponent is added to the lower
+ 16 bits. The addition result is normalized and the upper Word16 of the result represents
+ the mantissa to return. The returned exponent takes into account all shift operations
+ including the final 16-bit extraction.
+ Note: The resulting mantissa may be inaccurate in the case, where the mantissa of the operand
+ with higher exponent is not really left-aligned, while the mantissa of the operand with
+ lower exponent is so. If in such a case, the difference in exponents is more than 15,
+ an inaccuracy is introduced.
+ Example:
+ A: a_e = 20, a_m = 0x0001
+ B: b_e = 0, b_m = 0x4000
+ correct: A+B=1*2^20+1*2^14=0x0010.0000+0x0000.4000=0x0010.4000=0x4100*2^6
+ previously: A+B=1*2^20+1*2^14=0x0001+0x0000=0x0001*2^20
+ this version: A+B=1*2^20+1*2^14=0x0000.8000+0x0000.4000=0x6000*2^6
+ */
+
+ shift = sub(a_e, b_e);
+ if (shift >= 0)
+ shift = s_min( 15,shift);
+
+ if (shift < 0)
+ shift = s_max(-15,shift);
+ a_e = s_max(a_e,b_e);
+ L_hm = L_deposit_l(a_m); /* mantissa belonging to higher exponent */
+ L_lm = L_deposit_l(a_m); /* mantissa belonging to lower exponent */
+ if (shift >= 0)
+ L_lm = L_deposit_l(b_m);
+ if (shift < 0)
+ L_hm = L_deposit_l(b_m);
+
+ if (shift > 0)
+ shift = negate(shift);
+
+ L_hm = L_shr(L_hm,shift); /* shift left due to negative shift parameter */
+ a_e = add(a_e, shift);
+ L_hm = L_add(L_hm, L_lm);
+ shift = norm_l(L_hm);
+ L_hm = L_shl(L_hm,shift);
+ *ptrSum_m = extract_h(L_hm);
+ move16();
+
+ a_e = sub(a_e,shift);
+ if (L_hm)
+ a_e = add(a_e,16);
+
+ return (a_e);
+}
+
+
+/* local function for Sqrt16 */
+static Word16 Sqrt16_common(Word16 m,
+ Word16 e)
+{
+ Word16 index, frac;
+
+ assert((m >= 0x4000) || (m == 0));
+
+ /* get table index (upper 6 bits minus 32) */
+ /* index = (m >> 9) - 32; */
+ index = mac_r(-32768 - (32 << 16), m, 1 << 6);
+
+ /* get fractional part for interpolation (lower 9 bits) */
+ frac = s_and(m, 0x1FF); /* Q9 */
+
+ /* interpolate */
+ if (m != 0)
+ {
+ BASOP_SATURATE_WARNING_OFF;
+ m = mac_r(SqrtTable[index], SqrtDiffTable[index], frac);
+ BASOP_SATURATE_WARNING_ON;
+ }
+
+ /* handle odd exponents */
+ if (s_and(e, 1) != 0) m = mult_r(m, 0x5a82);
+
+ return m;
+}
+
+
+Word16 Sqrt16( /*!< output mantissa */
+ Word16 mantissa, /*!< input mantissa */
+ Word16 *exponent /*!< pointer to exponent */
+)
+{
+ Word16 preShift, e;
+
+ assert(mantissa >= 0);
+
+ /* normalize */
+ preShift = norm_s(mantissa);
+
+ e = sub(*exponent, preShift);
+ mantissa = shl(mantissa, preShift);
+
+ /* calc mantissa */
+ mantissa = Sqrt16_common(mantissa, e);
+
+ /* e = (e + 1) >> 1 */
+ *exponent = mult_r(e, 1 << 14);
+ move16();
+
+ return mantissa;
+}
+
+Word16 Inv16( /*!< output mantissa */
+ Word16 mantissa, /*!< input mantissa */
+ Word16 *exponent /*!< pointer to exponent */
+)
+{
+ Word16 index, frac;
+ Word16 preShift;
+ Word16 m, e;
+
+ assert(mantissa != 0);
+
+ /* absolute */
+ BASOP_SATURATE_WARNING_OFF;
+ m = abs_s(mantissa);
+ BASOP_SATURATE_WARNING_ON;
+
+ /* normalize */
+ preShift = norm_s(m);
+
+ e = sub(*exponent, preShift);
+ m = shl(m, preShift);
+
+ /* get table index (upper 6 bits minus 32) */
+ /* index = (m >> 9) - 32; */
+ index = mac_r(-32768 - (32 << 16), m, 1 << 6);
+
+ /* get fractional part for interpolation (lower 9 bits) */
+ frac = shl(s_and(m, 0x1FF), 1); /* Q10 */
+
+ /* interpolate */
+ m = msu_r(InvTable[index], InvDiffTable[index], frac);
+
+ /* restore sign */
+ if (mantissa < 0) m = negate(m);
+
+ /* e = 1 - e */
+ *exponent = sub(1, e);
+ move16();
+
+ return m;
+}
+
+
+void BASOP_Util_Sqrt_InvSqrt_MantExp (Word16 mantissa, /*!< mantissa */
+ Word16 exponent, /*!< expoinent */
+ Word16 *sqrt_mant, /*!< Pointer to sqrt mantissa */
+ Word16 *sqrt_exp, /*!< Pointer to sqrt exponent */
+ Word16 *isqrt_mant, /*!< Pointer to 1/sqrt mantissa */
+ Word16 *isqrt_exp /*!< Pointer to 1/sqrt exponent */
+ )
+{
+ Word16 index, frac;
+ Word16 preShift;
+ Word16 m, mi, e_odd;
+
+ assert(mantissa > 0);
+
+ /* normalize */
+ preShift = norm_s(mantissa);
+
+ exponent = sub(exponent, preShift);
+ mantissa = shl(mantissa, preShift);
+
+ /* get table index (upper 6 bits minus 32) */
+ /* index = (m >> 9) - 32; */
+ index = mac_r(-32768 - (32 << 16), mantissa, 1 << 6);
+
+ /* get fractional part for interpolation (lower 9 bits) */
+ frac = s_and(mantissa, 0x1FF); /* Q9 */
+
+ /* interpolate */
+ BASOP_SATURATE_WARNING_OFF;
+ m = mac_r(SqrtTable[index], SqrtDiffTable[index], frac);
+ mi = msu_r(ISqrtTable[index], ISqrtDiffTable[index], frac);
+ BASOP_SATURATE_WARNING_ON;
+
+ /* handle even/odd exponents */
+ e_odd = s_and(exponent, 1);
+ if (e_odd != 0) m = mult_r(m, 0x5a82);
+ if (e_odd == 0) mi = mult_r(mi, 0x5a82);
+
+ /* e = (e + 1) >> 1 */
+ *sqrt_exp = mult_r(exponent, 1 << 14);
+ move16();
+
+ /* e = (2 - e) >> 1 */
+ *isqrt_exp = msu_r(1L << 15, exponent, 1 << 14);
+ move16();
+
+ /* Write result */
+ *sqrt_mant = m;
+ move16();
+ *isqrt_mant = mi;
+ move16();
+
+}
+
+/********************************************************************/
+/*!
+ \brief Calculates the scalefactor needed to normalize input array
+
+ The scalefactor needed to normalize the Word32 input array is returned
+ If the input array contains only '0', a scalefactor 0 is returned
+ Scaling factor is determined wrt a normalized target x: 1073741824 <= x <= 2147483647 for positive x
+ and -2147483648 <= x <= -1073741824 for negative x
+*/
+
+Word16 getScaleFactor32( /* o: measured headroom in range [0..31], 0 if all x[i] == 0 */
+ const Word32 *x, /* i: array containing 32-bit data */
+ const Word16 len_x) /* i: length of the array to scan */
+{
+ Word16 i, i_min, i_max;
+ Word32 x_min, x_max;
+
+ x_max = L_add(0, 0);
+ x_min = L_add(0, 0);
+ FOR (i = 0; i < len_x; i++)
+ {
+ if (x[i] >= 0)
+ x_max = L_max(x_max,x[i]);
+ if (x[i] < 0)
+ x_min = L_min(x_min,x[i]);
+ }
+
+ i_max = 0x20;
+ move16();
+ i_min = 0x20;
+ move16();
+
+ if (x_max != 0)
+ i_max = norm_l(x_max);
+
+ if (x_min != 0)
+ i_min = norm_l(x_min);
+
+ i = s_and(s_min(i_max, i_min),0x1F);
+
+ return i;
+}
+
+
+Word16 BASOP_Util_Divide1616_Scale(Word16 x, Word16 y, Word16 *s)
+{
+ Word16 z;
+ Word16 sx;
+ Word16 sy;
+ Word16 sign;
+
+ /* assert (x >= (Word16)0); */
+ assert (y != (Word16)0);
+
+ sign = 0;
+ move16();
+
+ IF ( x < 0 )
+ {
+ x = negate(x);
+ sign = s_xor(sign,1);
+ }
+
+ IF ( y < 0 )
+ {
+ y = negate(y);
+ sign= s_xor(sign,1);
+ }
+
+ IF ( x == (Word16)0 )
+ {
+ move16();
+ *s = 0;
+
+ return ((Word16)0);
+ }
+
+ sx = norm_s(x);
+ x = shl(x,sx);
+ x = shr(x,1);
+ move16();
+ *s = sub(1,sx);
+
+ sy = norm_s(y);
+ y = shl(y,sy);
+ move16();
+ *s = add(*s,sy);
+
+ z = div_s(x,y);
+
+ if ( sign != 0 )
+ {
+ z = negate(z);
+ }
+
+ return z;
+}
+
+
+void set_val_Word16(Word16 X[], const Word16 val, Word16 n)
+{
+ Word16 i;
+
+
+ FOR (i = 0; i < n; i++)
+ {
+ X[i] = val;
+ move16();
+ }
+
+
+ return;
+}
+
+void set_val_Word32(Word32 X[], const Word32 val, Word16 n)
+{
+ Word16 i;
+
+
+ FOR (i = 0; i < n; i++)
+ {
+ X[i] = val;
+ move32();
+ }
+
+
+ return;
+}
+
+Word16 mult0 ( Word16 x, Word16 y)
+{
+ return extract_l(L_mult0(x,y));
+}
+
+
+#define SINETAB SineTable512_fx
+#define LD 9
+
+/*
+ * Calculates coarse lookup values for sine/cosine and residual angle.
+ * \param x angle in radians with exponent = 2 or as radix 2 with exponent = 0.
+ * \param scale shall always be 2
+ * \param sine pointer to where the sine lookup value is stored into
+ * \param cosine pointer to where the cosine lookup value is stored into
+ * \param flag_radix2 flag indicating radix 2 angle if non-zero.
+ */
+static Word16 fixp_sin_cos_residual_16(Word16 x, const Word16 scale, Word16 *sine, Word16 *cosine, Word8 flag_radix2)
+{
+ Word16 residual;
+ Word16 s;
+ Word16 ssign;
+ Word16 csign;
+ Word16 tmp, cl = 0, sl = 0;
+ const Word16 shift = 15-LD-1-scale;
+
+ if (flag_radix2 == 0)
+ {
+ x = mult_r(x, FL2WORD16(1.0/EVS_PI));
+ }
+ s = shr(x, shift);
+
+ residual = s_and(x, (1< x */
+ s = add(sub(norm_s(y), norm_s(x)), 1);
+ s = s_max(s, 0);
+
+ BASOP_SATURATE_WARNING_OFF
+ y = shl(y, s);
+ BASOP_SATURATE_WARNING_ON
+
+ /* divide and shift */
+ y = shr(div_s(x, y), sub(15, s));
+
+
+ return y;
+}
+
+Word32 BASOP_util_Pow2(
+ const Word32 exp_m, const Word16 exp_e,
+ Word16 *result_e
+)
+{
+ static const Word16 pow2Coeff[8] =
+ {
+ FL2WORD16(0.693147180559945309417232121458177), /* ln(2)^1 /1! */
+ FL2WORD16(0.240226506959100712333551263163332), /* ln(2)^2 /2! */
+ FL2WORD16(0.0555041086648215799531422637686218), /* ln(2)^3 /3! */
+ FL2WORD16(0.00961812910762847716197907157365887), /* ln(2)^4 /4! */
+ FL2WORD16(0.00133335581464284434234122219879962), /* ln(2)^5 /5! */
+ FL2WORD16(1.54035303933816099544370973327423e-4), /* ln(2)^6 /6! */
+ FL2WORD16(1.52527338040598402800254390120096e-5), /* ln(2)^7 /7! */
+ FL2WORD16(1.32154867901443094884037582282884e-6) /* ln(2)^8 /8! */
+ };
+
+ Word32 frac_part = 0, tmp_frac, result_m;
+ Word16 int_part = 0;
+
+ IF (exp_e > 0)
+ {
+ /* "+ 1" compensates L_shr(,1) of the polynomial evaluation at the loop end. */
+
+ int_part = add(1,extract_l(L_shr(exp_m, sub(31, exp_e))));
+ frac_part = L_lshl(exp_m, exp_e);
+ frac_part = L_and(0x7FFFFFFF, frac_part);
+ }
+ if (exp_e <= 0)
+ frac_part = L_shl(exp_m, exp_e);
+ if (exp_e <= 0)
+ {
+ int_part = 1;
+ move16();
+ }
+
+ /* Best accuracy is around 0, so try to get there with the fractional part. */
+ IF( (tmp_frac = L_sub(frac_part,FL2WORD32(0.5))) >= 0)
+ {
+ int_part = add(int_part, 1);
+ frac_part = L_sub(tmp_frac,FL2WORD32(0.5));
+ }
+ ELSE IF( (tmp_frac = L_add(frac_part,FL2WORD32(0.5))) < 0)
+ {
+ int_part = sub(int_part, 1);
+ frac_part = L_add(tmp_frac,FL2WORD32(0.5));
+ }
+
+ /* Evaluate taylor polynomial which approximates 2^x */
+ {
+ Word32 p;
+ Word16 i;
+
+
+ /* First taylor series coefficient a_0 = 1.0, scaled by 0.5 due to L_shr(,1). */
+ result_m = L_add(FL2WORD32(1.0/2.0),L_shr(Mpy_32_16(frac_part, pow2Coeff[0]), 1));
+ p = Mpy_32_32(frac_part, frac_part);
+ FOR (i = 1; i < 7; i++)
+ {
+ /* next taylor series term: a_i * x^i, x=0 */
+ result_m = L_add(result_m, L_shr(Mpy_32_16(p, pow2Coeff[i]), 1));
+ p = Mpy_32_32(p, frac_part);
+ }
+ result_m = L_add(result_m, L_shr(Mpy_32_16(p, pow2Coeff[i]), 1));
+ }
+ *result_e = int_part;
+ move16();
+
+ return result_m;
+}
+
+Word16 BASOP_Util_Divide3216_Scale( /* o: result of division x/y, not normalized */
+ Word32 x, /* i: numerator, signed */
+ Word16 y, /* i: denominator, signed */
+ Word16 *s) /* o: scaling, 0, if x==0 */
+{
+ Word16 z;
+ Word16 sx;
+ Word16 sy;
+ Word16 sign;
+
+ /*assert (x > (Word32)0);
+ assert (y >= (Word16)0);*/
+
+ /* check, if numerator equals zero, return zero then */
+ IF ( x == (Word32)0 )
+ {
+ *s = 0;
+ move16();
+
+ return ((Word16)0);
+ }
+
+ sign = s_xor(extract_h(x),y); /* just to exor the sign bits */
+ BASOP_SATURATE_WARNING_OFF
+ x = L_abs(x);
+ y = abs_s(y);
+ BASOP_SATURATE_WARNING_ON
+ sx = sub(norm_l(x),1);
+ x = L_shl(x,sx);
+ sy = norm_s(y);
+ y = shl(y,sy);
+ *s = sub(sy,sx);
+ move16();
+
+ z = div_s(round_fx(x),y);
+
+ if ( sign < 0 ) /* if sign bits differ, negate the result */
+ {
+ z = negate(z);
+ }
+
+ return z;
+}
+
+
+static const Word16 table_pow2[32] =
+{
+ 16384, 16743, 17109, 17484, 17867, 18258, 18658, 19066, 19484, 19911,
+ 20347, 20792, 21247, 21713, 22188, 22674, 23170, 23678, 24196, 24726,
+ 25268, 25821, 26386, 26964, 27554, 28158, 28774, 29405, 30048, 30706,
+ 31379, 32066
+};
+/* table of table_pow2[i+1] - table_pow2[i] */
+static const Word16 table_pow2_diff_x32[32] =
+{
+ 11488, 11712, 12000, 12256, 12512, 12800, 13056, 13376, 13664, 13952,
+ 14240, 14560, 14912, 15200, 15552, 15872, 16256, 16576, 16960, 17344,
+ 17696, 18080, 18496, 18880, 19328, 19712, 20192, 20576, 21056, 21536,
+ 21984, 22432
+};
+
+Word32 Pow2( /* (o) Q0 : result (range: 0<=val<=0x7fffffff) */
+ Word16 exponant, /* (i) Q0 : Integer part. (range: 0<=val<=30) */
+ Word16 fraction /* (i) Q15 : Fractional part. (range: 0.0<=val<1.0) */
+)
+{
+ Word16 exp, i, a;
+ Word32 L_x;
+
+ i = mac_r(-32768, fraction, 32); /* Extract b10-b16 of fraction */
+ a = s_and(fraction, 0x3ff); /* Extract b0-b9 of fraction */
+
+ L_x = L_deposit_h(table_pow2[i]); /* table[i] << 16 */
+ L_x = L_mac(L_x, table_pow2_diff_x32[i], a);/* L_x -= diff*a*2 */
+
+ exp = sub(30, exponant);
+
+ L_x = L_shr_r(L_x, exp);
+
+ return L_x;
+}
+
+/*************************************************************************
+ *
+ * FUNCTION: Log2_norm()
+ *
+ * PURPOSE: Computes log2(L_x, exp), where L_x is positive and
+ * normalized, and exp is the normalisation exponent
+ * If L_x is negative or zero, the result is 0.
+ *
+ * DESCRIPTION:
+ * The function Log2(L_x) is approximated by a table and linear
+ * interpolation. The following steps are used to compute Log2(L_x)
+ *
+ * 1- exponent = 30-norm_exponent
+ * 2- i = bit25-b31 of L_x; 32<=i<=63 (because of normalization).
+ * 3- a = bit10-b24
+ * 4- i -=32
+ * 5- fraction = table[i]<<16 - (table[i] - table[i+1]) * a * 2
+ *
+ *************************************************************************/
+
+static const Word32 L_table[32] =
+{
+ -32768L, 95322112L, 187793408L, 277577728L,
+ 364871680L, 449740800L, 532381696L, 612859904L,
+ 691306496L, 767787008L, 842432512L, 915308544L,
+ 986546176L, 1056210944L, 1124302848L, 1190887424L,
+ 1256095744L, 1319993344L, 1382580224L, 1443921920L,
+ 1504083968L, 1563131904L, 1621000192L, 1677885440L,
+ 1733722112L, 1788510208L, 1842380800L, 1895399424L,
+ 1947435008L, 1998618624L, 2049015808L, 2098626560L
+};
+
+static const Word16 table_diff[32] =
+{
+ 1455, 1411, 1370, 1332, 1295, 1261, 1228, 1197,
+ 1167, 1139, 1112, 1087, 1063, 1039, 1016, 995,
+ 975, 955, 936, 918, 901, 883, 868, 852,
+ 836, 822, 809, 794, 781, 769, 757, 744
+};
+
+Word16 Log2_norm_lc ( /* (o) : Fractional part of Log2. (range: 0<=val<1) */
+ Word32 L_x /* (i) : input value (normalized) */
+)
+{
+ Word16 i, a;
+ Word16 y;
+
+
+ L_x = L_shr (L_x, 9);
+ a = extract_l (L_x); /* Extract b10-b24 of fraction */
+ a = lshr(a, 1);
+
+ i = mac_r(L_x, -32*2-1, 16384); /* Extract b25-b31 minus 32 */
+
+ y = mac_r(L_table[i], table_diff[i], a);/* table[i] << 16 - diff*a*2 */
+
+
+ return y;
+}
+
+
+Word32 BASOP_Util_fPow(
+ Word32 base_m, Word16 base_e,
+ Word32 exp_m, Word16 exp_e,
+ Word16 *result_e
+)
+{
+
+ Word16 ans_lg2_e, base_lg2_e;
+ Word32 base_lg2_m, ans_lg2_m, result_m;
+ Word16 shift;
+
+ test();
+ IF ((base_m == 0) && (exp_m != 0))
+ {
+ *result_e = 0;
+ move16();
+ return 0;
+ }
+ /* Calc log2 of base */
+ shift = norm_l(base_m);
+ base_m = L_shl(base_m, shift);
+ base_e = sub(base_e, shift);
+ base_lg2_m = BASOP_Util_Log2(base_m);
+
+ /* shift: max left shift such that neither base_e or base_lg2_m saturate. */
+ shift = sub(s_min(norm_s(base_e), WORD16_BITS-1-LD_DATA_SCALE), 1);
+ /* Compensate shift into exponent of result. */
+ base_lg2_e = sub(WORD16_BITS-1, shift);
+ base_lg2_m = L_add(L_shr(base_lg2_m, sub(WORD16_BITS-1-LD_DATA_SCALE, shift)), L_deposit_h(shl(base_e, shift)));
+
+ /* Prepare exp */
+ shift = norm_l(exp_m);
+ exp_m = L_shl(exp_m, shift);
+ exp_e = sub(exp_e, shift);
+
+ /* Calc base pow exp */
+ ans_lg2_m = Mpy_32_32(base_lg2_m, exp_m);
+ ans_lg2_e = add(exp_e, base_lg2_e);
+
+ /* Calc antilog */
+ result_m = BASOP_util_Pow2(ans_lg2_m, ans_lg2_e, result_e);
+
+ return result_m;
+}
+
+Word32 BASOP_Util_Add_Mant32Exp /*!< o: normalized result mantissa */
+(Word32 a_m, /*!< i: Mantissa of 1st operand a */
+ Word16 a_e, /*!< i: Exponent of 1st operand a */
+ Word32 b_m, /*!< i: Mantissa of 2nd operand b */
+ Word16 b_e, /*!< i: Exponent of 2nd operand b */
+ Word16 *ptr_e) /*!< o: exponent of result */
+{
+ Word32 L_tmp;
+ Word16 shift;
+
+ /* Compare exponents: the difference is limited to +/- 30
+ The Word32 mantissa of the operand with lower exponent is shifted right by the exponent difference.
+ Then, the unshifted mantissa of the operand with the higher exponent is added. The addition result
+ is normalized and the result represents the mantissa to return. The returned exponent takes into
+ account all shift operations.
+ */
+
+ if (!a_m)
+ a_e = add(b_e,0);
+
+ if (!b_m)
+ b_e = add(a_e,0);
+
+ shift = sub(a_e, b_e);
+ shift = s_max(-31,shift);
+ shift = s_min(31, shift);
+ if (shift < 0)
+ {
+ /* exponent of b is greater than exponent of a, shr a_m */
+ a_m = L_shl(a_m,shift);
+ }
+ if (shift > 0)
+ {
+ /* exponent of a is greater than exponent of b */
+ b_m = L_shr(b_m,shift);
+ }
+ a_e = add(s_max(a_e,b_e),1);
+ L_tmp = L_add(L_shr(a_m,1),L_shr(b_m,1));
+ shift = norm_l(L_tmp);
+ if (shift)
+ L_tmp = L_shl(L_tmp,shift);
+ if (L_tmp == 0)
+ a_e = add(0,0);
+ if (L_tmp != 0)
+ a_e = sub(a_e,shift);
+ *ptr_e = a_e;
+
+ return (L_tmp);
+}
+
+static const Word32 L_table_isqrt[48] =
+{
+ 2147418112L, 2083389440L, 2024669184L, 1970667520L,
+ 1920794624L, 1874460672L, 1831403520L, 1791098880L,
+ 1753415680L, 1717960704L, 1684602880L, 1653145600L,
+ 1623326720L, 1595080704L, 1568276480L, 1542782976L,
+ 1518469120L, 1495334912L, 1473183744L, 1451950080L,
+ 1431633920L, 1412169728L, 1393491968L, 1375469568L,
+ 1358168064L, 1341521920L, 1325465600L, 1309933568L,
+ 1294991360L, 1280507904L, 1266548736L, 1252982784L,
+ 1239875584L, 1227161600L, 1214775296L, 1202847744L,
+ 1191182336L, 1179910144L, 1168965632L, 1158283264L,
+ 1147863040L, 1137770496L, 1127940096L, 1118306304L,
+ 1108934656L, 1099825152L, 1090912256L, 1082261504L
+};
+/* table of table_isqrt[i] - table_isqrt[i+1] */
+static const Word16 table_isqrt_diff[48] =
+{
+ 977, 896, 824, 761, 707, 657, 615, 575,
+ 541, 509, 480, 455, 431, 409, 389, 371,
+ 353, 338, 324, 310, 297, 285, 275, 264,
+ 254, 245, 237, 228, 221, 213, 207, 200,
+ 194, 189, 182, 178, 172, 167, 163, 159,
+ 154, 150, 147, 143, 139, 136, 132, 130
+};
+static const Word16 shift[] = {9,10};
+Word32 Isqrt_lc1(
+ Word32 frac, /* (i) Q31: normalized value (1.0 < frac <= 0.5) */
+ Word16 * exp /* (i/o) : exponent (value = frac x 2^exponent) */
+)
+{
+ Word16 i, a;
+ Word32 L_tmp;
+
+ IF (frac <= (Word32) 0)
+ {
+ *exp = 0;
+ move16();
+ return 0x7fffffff; /*0x7fffffff*/
+ }
+
+ /* If exponant odd -> shift right by 10 (otherwise 9) */
+ L_tmp = L_shr(frac, shift[s_and(*exp, 1)]);
+
+ /* 1) -16384 to shift left and change sign */
+ /* 2) 32768 to Add 1 to Exponent like it was divided by 2 */
+ /* 3) We let the mac_r add another 0.5 because it imitates */
+ /* the behavior of shr on negative number that should */
+ /* not be rounded towards negative infinity. */
+ /* It replaces: */
+ /* *exp = negate(shr(sub(*exp, 1), 1)); move16(); */
+ *exp = mac_r(32768, *exp, -16384);
+ move16();
+
+ a = extract_l(L_tmp); /* Extract b10-b24 */
+ a = lshr(a, 1);
+
+ i = mac_r(L_tmp, -16*2-1, 16384); /* Extract b25-b31 minus 16 */
+
+ L_tmp = L_msu(L_table_isqrt[i], table_isqrt_diff[i], a);/* table[i] << 16 - diff*a*2 */
+
+ return L_tmp;
+}
+
+
+static const Word16 sqrt_table[49] =
+{
+ 16384, 16888, 17378, 17854, 18318, 18770, 19212,
+ 19644, 20066, 20480, 20886, 21283, 21674, 22058,
+ 22435, 22806, 23170, 23530, 23884, 24232, 24576,
+ 24915, 25249, 25580, 25905, 26227, 26545, 26859,
+ 27170, 27477, 27780, 28081, 28378, 28672, 28963,
+ 29251, 29537, 29819, 30099, 30377, 30652, 30924,
+ 31194, 31462, 31727, 31991, 32252, 32511, 32767
+};
+
+Word32 Sqrt_l( /* o : output value, Q31 */
+ Word32 L_x, /* i : input value, Q31 */
+ Word16 *exp /* o : right shift to be applied to result, Q1 */
+)
+{
+ /*
+ y = sqrt(x)
+
+ x = f * 2^-e, 0.5 <= f < 1 (normalization)
+
+ y = sqrt(f) * 2^(-e/2)
+
+ a) e = 2k --> y = sqrt(f) * 2^-k (k = e div 2,
+ 0.707 <= sqrt(f) < 1)
+ b) e = 2k+1 --> y = sqrt(f/2) * 2^-k (k = e div 2,
+ 0.5 <= sqrt(f/2) < 0.707)
+ */
+
+ Word16 e, i, a, tmp;
+ Word32 L_y;
+
+ if (L_x <= 0)
+ {
+ *exp = 0;
+ move16 ();
+ return L_deposit_l(0);
+ }
+
+ e = s_and(norm_l(L_x), 0x7FFE); /* get next lower EVEN norm. exp */
+ L_x = L_shl(L_x, e); /* L_x is normalized to [0.25..1) */
+ *exp = e;
+ move16 (); /* return 2*exponent (or Q1) */
+
+ L_x = L_shr(L_x, 9);
+ a = extract_l(L_x); /* Extract b10-b24 */
+ a = lshr(a, 1);
+
+ i = mac_r(L_x, -16*2-1, 16384); /* Extract b25-b31 minus 16 */
+
+ L_y = L_deposit_h(sqrt_table[i]); /* table[i] << 16 */
+ tmp = sub(sqrt_table[i], sqrt_table[i + 1]); /* table[i] - table[i+1]) */
+ L_y = L_msu(L_y, tmp, a); /* L_y -= tmp*a*2 */
+
+ /* L_y = L_shr (L_y, *exp); */ /* denormalization done by caller */
+
+ return (L_y);
+
+}
diff --git a/lib_com/__zaloha/basop_util.h b/lib_com/__zaloha/basop_util.h
new file mode 100644
index 0000000000000000000000000000000000000000..7d0797bbec65b6596c783ed2b86f74eb033dc03d
--- /dev/null
+++ b/lib_com/__zaloha/basop_util.h
@@ -0,0 +1,386 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#ifndef __BASOP_UTIL_H__
+#define __BASOP_UTIL_H__
+
+#include "basop_settings.h"
+#include "typedef.h"
+#include "basop32.h"
+#include "basop_mpy.h"
+
+
+#define LD_DATA_SCALE (6)
+
+#define LD_DATA_SHIFT_I5 (7)
+
+#define modDiv2(x) sub(x,shl(shr(x,1),1))
+#define modDiv8(x) L_sub(x,L_shl(L_shr(x,3),3))
+
+#ifndef CHEAP_NORM_SIZE
+#define CHEAP_NORM_SIZE 161
+#endif
+
+static __inline Word16 limitScale16( Word16 s)
+{
+ /* It is assumed, that s is calculated just before, therefore we can switch upon sign */
+ if (s >= 0)
+ s = s_min(s,WORD16_BITS-1);
+ if (s < 0)
+ s = s_max(s,1-WORD16_BITS);
+ return (s);
+}
+
+static __inline Word16 limitScale32( Word16 s)
+{
+ /* It is assumed, that s is calculated just before, therefore we can switch upon sign */
+ if (s >= 0)
+ s = s_min(s, WORD32_BITS-1);
+ if (s < 0)
+ s = s_max(s, 1-WORD32_BITS);
+ return (s);
+}
+
+
+/*!**********************************************************************
+ \brief Add two values given by mantissa and exponent.
+
+ Mantissas are in 16-bit-fractional format with values between 0 and 1.
+ The base for exponents is 2. Example: \f$ a = a\_m * 2^{a\_e} \f$
+
+************************************************************************/
+Word16 BASOP_Util_Add_MantExp /*!< Exponent of result */
+(Word16 a_m, /*!< Mantissa of 1st operand a */
+ Word16 a_e, /*!< Exponent of 1st operand a */
+ Word16 b_m, /*!< Mantissa of 2nd operand b */
+ Word16 b_e, /*!< Exponent of 2nd operand b */
+ Word16 *ptrSum_m); /*!< Mantissa of result */
+
+
+
+/************************************************************************/
+/*!
+ \brief Calculate the squareroot of a number given by mantissa and exponent
+
+ Mantissa is in 16/32-bit-fractional format with values between 0 and 1.
+ For *norm versions mantissa has to be between 0.5 and 1.
+ The base for the exponent is 2. Example: \f$ a = a\_m * 2^{a\_e} \f$
+ The exponent is addressed via pointers and will be overwritten with the result.
+*/
+Word16 Sqrt16( /*!< output mantissa */
+ Word16 mantissa, /*!< input mantissa */
+ Word16 *exponent /*!< pointer to exponent */
+);
+
+/*****************************************************************************/
+/*!
+ \brief Calculate the inverse of a number given by mantissa and exponent
+
+ Mantissa is in 16-bit-fractional format with values between 0 and 1.
+ The base for the exponent is 2. Example: \f$ a = a\_m * 2^{a\_e} \f$
+ The operand is addressed via pointers and will be overwritten with the result.
+
+ The function uses a table lookup and a newton iteration.
+*/
+Word16 Inv16( /*!< output mantissa */
+ Word16 mantissa, /*!< input mantissa */
+ Word16 *exponent /*!< pointer to exponent */
+);
+
+/******************************************************************************/
+/*!
+ \brief Calculate the squareroot and inverse of squareroot of a number given by mantissa and exponent
+
+ Mantissa is in 16-bit-fractional format with values between 0 and 1.
+ The base for the exponent is 2. Example: \f$ a = a\_m * 2^{a\_e} \f$
+*/
+void BASOP_Util_Sqrt_InvSqrt_MantExp (Word16 mantissa, /*!< mantissa */
+ Word16 exponent, /*!< expoinent */
+ Word16 *sqrt_mant, /*!< Pointer to sqrt mantissa */
+ Word16 *sqrt_exp, /*!< Pointer to sqrt exponent */
+ Word16 *isqrt_mant, /*!< Pointer to 1/sqrt mantissa */
+ Word16 *isqrt_exp /*!< Pointer to 1/sqrt exponent */
+ );
+
+
+
+/********************************************************************/
+/*!
+ \brief Calculates the scalefactor needed to normalize input array
+
+ The scalefactor needed to normalize the Word32 input array is returned
+ If the input array contains only '0', a scalefactor 0 is returned
+ Scaling factor is determined wrt a normalized target x: 1073741824 <= x <= 2147483647 for positive x
+ and -2147483648 <= x <= -1073741824 for negative x
+*/
+
+Word16 getScaleFactor32( /* o: measured headroom in range [0..31], 0 if all x[i] == 0 */
+ const Word32 *x, /* i: array containing 32-bit data */
+ const Word16 len_x); /* i: length of the array to scan */
+
+/************************************************************************/
+/*!
+ \brief Binary logarithm with 7 iterations
+
+ \param x
+
+ \return log2(x)/64
+ */
+/************************************************************************/
+Word32 BASOP_Util_Log2(Word32 x);
+
+
+
+/****************************************************************************/
+/*!
+ \brief Does fractional division of Word16 arg1 by Word16 arg2
+
+
+ \return fractional Q15 Word16 z = arg1(Q15)/arg2(Q15) with scaling s
+*/
+Word16 BASOP_Util_Divide1616_Scale( Word16 x, /*!< i : Numerator*/
+ Word16 y, /*!< i : Denominator*/
+ Word16 *s); /*!< o : Additional scalefactor difference*/
+
+/****************************************************************************/
+/*!
+ \brief Does fractional integer division of Word32 arg1 by Word16 arg2
+
+
+ \return fractional Word16 integer z = arg1(32bits)/arg2(16bits) , z not normalized
+*/
+Word16 BASOP_Util_Divide3216_Scale( Word32 x, /*!< i : Numerator */
+ Word16 y, /*!< i : Denominator*/
+ Word16 *s); /*!< o : Additional scalefactor difference*/
+
+
+/************************************************************************/
+/*!
+ * \brief Binary logarithm with 5 iterations
+ *
+ * \param[i] val
+ *
+ * \return basop_log2(val)/128
+ */
+/************************************************************************/
+Word32 BASOP_Util_log2_i5(Word32 val);
+
+/************************************************************************/
+/*!
+ \brief Binary power
+
+ Date: 06-JULY-2012 Arthur Tritthart, IIS Fraunhofer Erlangen
+
+ Version with 3 table lookup and 1 linear interpolations
+
+ Algorithm: compute power of 2, argument x is in Q7.25 format
+ result = 2^(x/64)
+ We split exponent (x/64) into 5 components:
+ integer part: represented by b31..b25 (exp)
+ fractional part 1: represented by b24..b20 (lookup1)
+ fractional part 2: represented by b19..b15 (lookup2)
+ fractional part 3: represented by b14..b10 (lookup3)
+ fractional part 4: represented by b09..b00 (frac)
+ => result = (lookup1*lookup2*(lookup3+C1*frac)<<3)>>exp
+
+ Due to the fact, that all lookup values contain a factor 0.5
+ the result has to be shifted by 3 to the right also.
+ Table exp2_tab_long contains the log2 for 0 to 1.0 in steps
+ of 1/32, table exp2w_tab_long the log2 for 0 to 1/32 in steps
+ of 1/1024, table exp2x_tab_long the log2 for 0 to 1/1024 in
+ steps of 1/32768. Since the 2-logarithm of very very small
+ negative value is rather linear, we can use interpolation.
+
+ Limitations:
+
+ For x <= 0, the result is fractional positive
+ For x > 0, the result is integer in range 1...7FFF.FFFF
+ For x < -31/64, we have to clear the result
+ For x = 0, the result is ~1.0 (0x7FFF.FFFF)
+ For x >= 31/64, the result is 0x7FFF.FFFF
+
+ \param x
+
+ \return pow(2,(x/64))
+ */
+/************************************************************************/
+Word32 BASOP_Util_InvLog2(Word32 x);
+
+
+/****************************************************************************/
+/*!
+ \brief Sets Array Word16 arg1 to value Word16 arg2 for Word16 arg3 elements
+*/
+void set_val_Word16( Word16 X[], /*!< Address of array */
+ const Word16 val, /*!< Value to copy into array */
+ Word16 n); /*!< Number of elements to process */
+
+
+/****************************************************************************/
+/*!
+ \brief Sets Array Word32 arg1 to value Word32 arg2 for Word16 arg3 elements
+*/
+void set_val_Word32( Word32 X[], /*!< Address of array */
+ const Word32 val, /*!< Value to copy into array */
+ Word16 n); /*!< Number of elements to process */
+
+/****************************************************************************/
+/*!
+ \brief Does a multiplication of Word16 input values
+
+ \return z16 = x16 * y16
+*/
+Word16 mult0 ( Word16 x, /*!< i : Multiplier */
+ Word16 y); /*!< i : Multiplicand */
+
+/**
+ * \brief calculate cosine of angle. Tuned for ISF domain.
+ * \param theta Angle normalized to radix 2, theta = (angle in radians)*2.0/pi
+ * \return result with exponent 0.
+ */
+Word16 getCosWord16R2(Word16 theta);
+
+/****************************************************************************/
+/*!
+ \brief 16/16->16 unsigned integer division
+
+ x and y have to be positive, x has to be < 16384
+
+ \return 16/16->16 integer
+ */
+
+Word16 idiv1616U(Word16 x, Word16 y);
+
+
+/**
+ * \brief return 2 ^ (exp * 2^exp_e)
+ * \param exp_m mantissa of the exponent to 2.0f
+ * \param exp_e exponent of the exponent to 2.0f
+ * \param result_e pointer to a INT where the exponent of the result will be stored into
+ * \return mantissa of the result
+ */
+Word32 BASOP_util_Pow2(
+ const Word32 exp_m, const Word16 exp_e,
+ Word16 *result_e
+);
+
+
+Word32 Isqrt_lc1(
+ Word32 frac, /* (i) Q31: normalized value (1.0 < frac <= 0.5) */
+ Word16 * exp /* (i/o) : exponent (value = frac x 2^exponent) */
+);
+
+/*****************************************************************************/
+/*!
+
+ \brief Calculates pow(2,x)
+ ___________________________________________________________________________
+ | |
+ | Function Name : Pow2() |
+ | |
+ | L_x = pow(2.0, exponant.fraction) (exponent = interger part) |
+ | = pow(2.0, 0.fraction) << exponent |
+ |---------------------------------------------------------------------------|
+ | Algorithm: |
+ | |
+ | The function Pow2(L_x) is approximated by a table and linear |
+ | interpolation. |
+ | |
+ | 1- i = bit10-b15 of fraction, 0 <= i <= 31 |
+ | 2- a = bit0-b9 of fraction |
+ | 3- L_x = table[i]<<16 - (table[i] - table[i+1]) * a * 2 |
+ | 4- L_x = L_x >> (30-exponant) (with rounding) |
+ |___________________________________________________________________________|
+*/
+Word32 Pow2( /*!< (o) Q0 : result (range: 0<=val<=0x7fffffff) */
+ Word16 exponant, /*!< (i) Q0 : Integer part. (range: 0<=val<=30) */
+ Word16 fraction /*!< (i) Q15 : Fractionnal part. (range: 0.0<=val<1.0) */
+);
+
+/*************************************************************************
+ *
+ * FUNCTION: Log2_norm()
+ *
+ * PURPOSE: Computes log2(L_x, exp), where L_x is positive and
+ * normalized, and exp is the normalisation exponent
+ * If L_x is negative or zero, the result is 0.
+ *
+ * DESCRIPTION:
+ * The function Log2(L_x) is approximated by a table and linear
+ * interpolation. The following steps are used to compute Log2(L_x)
+ *
+ * 1- exponent = 30-norm_exponent
+ * 2- i = bit25-b31 of L_x; 32<=i<=63 (because of normalization).
+ * 3- a = bit10-b24
+ * 4- i -=32
+ * 5- fraction = table[i]<<16 - (table[i] - table[i+1]) * a * 2
+ *
+ *************************************************************************/
+
+Word16 Log2_norm_lc ( /* (o) : Fractional part of Log2. (range: 0<=val<1) */
+ Word32 L_x /* (i) : input value (normalized) */
+);
+
+/*************************************************************************
+ *
+ * FUNCTION: BASOP_Util_fPow()
+ */
+/**
+ * \brief BASOP_Util_fPow
+ *
+ * PURPOSE: Computes pow(base_m, base_e, exp_m, exp_e), where base_m and base_e
+ * specify the base, and exp_m and exp_e specify the exponent.
+ * The result is returned in a mantissa and exponent representation.
+ *
+ * DESCRIPTION:
+ * The function BASOP_Util_fPow(L_x) calculates the power function by
+ * calculating 2 ^ (log2(base)*exp)
+ *
+ * \param base_m mantissa of base
+ * \param base_e exponent of base
+ * \param exp_m mantissa of exponent
+ * \param exp_e exponent of exponent
+ * \param result_e pointer to exponent of result
+ * \return Word32 mantissa of result
+ *
+ *************************************************************************/
+
+Word32 BASOP_Util_fPow( /* (o) : mantissa of result */
+ Word32 base_m, Word16 base_e, /* (i) : input value for base (mantissa and exponent) */
+ Word32 exp_m, Word16 exp_e, /* (i) : input value for exponent (mantissa and exponent) */
+ Word16 *result_e /* (o) : output pointer to exponent of result */
+);
+
+/*!**********************************************************************
+ \brief Add two values given by mantissa and exponent.
+
+ Mantissas are in 32-bit-fractional format with values between 0 and 1.
+ The base for exponents is 2. Example: \f$ a = a\_m * 2^{a\_e} \f$
+
+************************************************************************/
+Word32 BASOP_Util_Add_Mant32Exp /*!< o: normalized result mantissa */
+(Word32 a_m, /*!< i: Mantissa of 1st operand a */
+ Word16 a_e, /*!< i: Exponent of 1st operand a */
+ Word32 b_m, /*!< i: Mantissa of 2nd operand b */
+ Word16 b_e, /*!< i: Exponent of 2nd operand b */
+ Word16 *ptr_e); /*!< o: exponent of result */
+
+/****************************************************************************/
+/*!
+ \brief Accumulates multiplications
+
+ Accumulates the elementwise multiplications of Word32 Array X with Word16 Array Y
+ pointed to by arg1 and arg2 with specified headroom. Length of to be multiplied arrays is arg3,
+ headroom with has to be taken into account is specified in arg4
+
+ \return Word32 result of accumulated multiplications over Word32 array arg1 and Word16 array arg2 and Word16 pointer
+ to exponent correction factor which needs to be added to the exponent of the result vector
+*/
+Word32 dotWord32_16_guards(const Word32 * X, const Word16 * Y, Word16 n, Word16 hr, Word16 * shift);
+
+
+
+Word32 Sqrt_l(Word32 L_x, Word16 *exp);
+
+#endif /* __BASOP_UTIL_H__ */
diff --git a/lib_com/__zaloha/bastypes.h b/lib_com/__zaloha/bastypes.h
new file mode 100644
index 0000000000000000000000000000000000000000..e88b8484b3792c041807f024ac930b7b35d65fa2
--- /dev/null
+++ b/lib_com/__zaloha/bastypes.h
@@ -0,0 +1,46 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#ifndef __BASTYPES_H
+#define __BASTYPES_H
+
+typedef unsigned char BYTE;
+typedef unsigned short WORD;
+#if defined(__alpha__) || defined(__alpha) || defined(__sgi)
+typedef unsigned int DWORD; /* long is 64 bits on these machines */
+#else
+typedef unsigned long DWORD;
+#endif
+
+typedef int BOOL;
+typedef signed int INT;
+typedef signed long LONG;
+typedef unsigned long ULONG;
+typedef unsigned int UINT;
+typedef float FLOAT;
+typedef double DOUBLE;
+typedef unsigned char UCHAR;
+typedef char CHAR;
+
+/* from uld_types.h: */
+typedef short SHORT;
+typedef unsigned short USHORT;
+typedef long int LINT;
+typedef unsigned long int ULINT;
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#define INVALID_HANDLE NULL
+
+#endif
diff --git a/lib_com/__zaloha/enh1632.c b/lib_com/__zaloha/enh1632.c
new file mode 100644
index 0000000000000000000000000000000000000000..8e031d5f283a538873fd726e2eb55dff93bc5d9c
--- /dev/null
+++ b/lib_com/__zaloha/enh1632.c
@@ -0,0 +1,637 @@
+
+/*
+ ===========================================================================
+ File: ENH1632.C v.2.3 - 30.Nov.2009
+ ===========================================================================
+
+
+ ITU-T STL BASIC OPERATORS
+
+ ENHANCED 16-BIT & 32-BIT ARITHMETIC OPERATORS
+
+ History:
+ 07 Nov 04 v2.0 Incorporation of new 32-bit / 40-bit / control
+ operators for the ITU-T Standard Tool Library as
+ described in Geneva, 20-30 January 2004 WP 3/16 Q10/16
+ TD 11 document and subsequent discussions on the
+ wp3audio@yahoogroups.com email reflector.
+
+ ============================================================================
+*/
+
+
+/*****************************************************************************
+*
+* Enhanced 16/32 bit operators :
+* s_max()
+* s_min()
+* L_max()
+* L_min()
+* shl_r()
+* L_shl_r()
+* L_mac0()
+* L_mult0()
+* L_msu0()
+* s_and()
+* s_or()
+* s_xor()
+* L_and()
+* L_or()
+* lshl()
+* lshr()
+* L_lshl()
+* L_lshr()
+* rotr()
+* rotl()
+* L_rotr()
+* L_rotl()
+*
+*****************************************************************************/
+
+
+/*****************************************************************************
+ *
+ * Include-Files
+ *
+ *****************************************************************************/
+
+#include
+#include
+#include "stl.h"
+#include "wmc_auto.h"
+
+/*****************************************************************************
+ *
+ * Constants and Globals
+ *
+ *****************************************************************************/
+
+
+/*****************************************************************************
+ *
+ * Functions
+ *
+ *****************************************************************************/
+
+
+/*****************************************************************************
+ *
+ * Function Name : lshl
+ *
+ * Purpose :
+ *
+ * Logically shifts left var1 by var2 positions.
+ * - If var2 is negative, var1 is shifted to the LSBits by (-var2)
+ * positions with insertion of 0 at the MSBit.
+ * - If var2 is positive, var1 is shifted to the MSBits by (var2)
+ * positions.
+ *
+ * Complexity weight : 1
+ *
+ * Inputs :
+ *
+ * var1 16 bit short signed integer (Word16) whose value falls in
+ * the range 0xffff 8000 <= var1 <= 0x0000 7fff.
+ *
+ * var2 16 bit short signed integer (Word16) whose value falls in
+ * the range 0xffff 8000 <= var2 <= 0x0000 7fff.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value:
+ *
+ * var_out 16 bit short signed integer (Word16) whose value falls in
+ * the range 0xffff 8000 <= var_out <= 0x0000 7fff.
+ *
+ *****************************************************************************/
+Word16 lshl( Word16 var1, Word16 var2)
+{
+ Word16 var_out=0;
+
+ if( var2 < 0)
+ {
+ var2 = -var2;
+ var_out = lshr( var1, var2);
+ }
+ else
+ {
+ if( var2 == 0 || var1 == 0)
+ {
+ var_out = var1;
+ }
+ else if( var2 >= 16)
+ {
+ var_out = 0;
+ }
+ else
+ {
+ var_out = var1 << var2;
+ }
+ }
+
+ BASOP_CHECK();
+
+
+ return( var_out);
+}
+
+/*****************************************************************************
+ *
+ * Function Name : lshr
+ *
+ * Purpose :
+ *
+ * Logically shifts right var1 by var2 positions.
+ * - If var2 is positive, var1 is shifted to the LSBits by (var2)
+ * positions with insertion of 0 at the MSBit.
+ * - If var2 is negative, var1 is shifted to the MSBits by (-var2)
+ * positions.
+ *
+ * Complexity weight : 1
+ *
+ * Inputs :
+ *
+ * var1 16 bit short signed integer (Word16) whose value falls in
+ * the range 0xffff 8000 <= var1 <= 0x0000 7fff.
+ *
+ * var2 16 bit short signed integer (Word16) whose value falls in
+ * the range 0xffff 8000 <= var2 <= 0x0000 7fff.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value:
+ *
+ * var_out 16 bit short signed integer (Word16) whose value falls in
+ * the range 0xffff 8000 <= var_out <= 0x0000 7fff.
+ *
+ *****************************************************************************/
+Word16 lshr( Word16 var1, Word16 var2)
+{
+ Word16 var_out;
+
+ if( var2 < 0)
+ {
+ var2 = -var2;
+ var_out = lshl( var1, var2);
+ }
+ else
+ {
+ if( var2 == 0 || var1 == 0)
+ {
+ var_out = var1;
+ }
+ else if( var2 >= 16)
+ {
+ var_out = 0;
+ }
+ else
+ {
+ var_out = var1 >> 1;
+ var_out = var_out & 0x7fff;
+ var_out = var_out >> ( var2-1);
+ }
+ }
+
+ BASOP_CHECK();
+
+
+ return( var_out);
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : L_lshl
+ *
+ * Purpose :
+ *
+ * Logically shifts left L_var1 by var2 positions.
+ * - If var2 is negative, L_var1 is shifted to the LSBits by (-var2)
+ * positions with insertion of 0 at the MSBit.
+ * - If var2 is positive, L_var1 is shifted to the MSBits by (var2)
+ * positions.
+ *
+ * Complexity weight : 1
+ *
+ * Inputs :
+ *
+ * L_var1 32 bit long signed integer (Word32) whose value falls in
+ * the range 0x8000 0000 <= L_var1 <= 0x7fff ffff.
+ *
+ * var2 16 bit short signed integer (Word16) whose value falls in
+ * the range 0xffff 8000 <= var2 <= 0x0000 7fff.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value:
+ *
+ * L_var_out 32 bit long signed integer (Word32) whose value falls in
+ * the range 0x8000 0000 <= L_var_out <= 0x7fff ffff.
+ *
+ *****************************************************************************/
+Word32 L_lshl( Word32 L_var1, Word16 var2)
+{
+ Word32 L_var_out=0;
+
+ if( var2 < 0)
+ {
+ var2 = -var2;
+ L_var_out = L_lshr( L_var1, var2);
+ }
+ else
+ {
+ if( var2 == 0 || L_var1 == 0)
+ {
+ L_var_out = L_var1;
+ }
+ else if( var2 >= 32)
+ {
+ L_var_out = 0;
+ }
+ else
+ {
+ L_var_out = L_var1 << var2;
+ }
+ }
+
+ BASOP_CHECK();
+
+
+ return( L_var_out);
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : L_lshr
+ *
+ * Purpose :
+ *
+ * Logically shifts right L_var1 by var2 positions.
+ * - If var2 is positive, L_var1 is shifted to the LSBits by (var2)
+ * positions with insertion of 0 at the MSBit.
+ * - If var2 is negative, L_var1 is shifted to the MSBits by (-var2)
+ * positions.
+ *
+ * Complexity weight : 1
+ *
+ * Inputs :
+ *
+ * L_var1 32 bit long signed integer (Word32) whose value falls in
+ * the range 0x8000 0000 <= L_var1 <= 0x7fff ffff.
+ *
+ * var2 16 bit short signed integer (Word16) whose value falls in
+ * the range 0xffff 8000 <= var2 <= 0x0000 7fff.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value:
+ *
+ * L_var_out 32 bit long signed integer (Word32) whose value falls in
+ * the range 0x8000 0000 <= L_var_out <= 0x7fff ffff.
+ *
+ *****************************************************************************/
+Word32 L_lshr( Word32 L_var1, Word16 var2)
+{
+ Word32 L_var_out;
+
+ if( var2 < 0)
+ {
+ var2 = -var2;
+ L_var_out = L_lshl( L_var1, var2);
+ }
+ else
+ {
+ if( var2 == 0 || L_var1 == 0)
+ {
+ L_var_out = L_var1;
+ }
+ else if( var2 >= 32)
+ {
+ L_var_out = 0;
+ }
+ else
+ {
+ L_var_out = L_var1 >> 1;
+ L_var_out = L_var_out & 0x7fffffff;
+ L_var_out = L_var_out >> (var2 - 1);
+ }
+ }
+
+ BASOP_CHECK();
+
+
+ return( L_var_out);
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : shl_r
+ *
+ * Purpose :
+ *
+ * Identical to shl( var1, var2) but with rounding. Saturates the result
+ * in case of underflows or overflows.
+ *
+ * Complexity weight : 3
+ *
+ * Inputs :
+ *
+ * var1 16 bit short signed integer (Word16) whose value falls in
+ * the range : 0xffff 8000 <= var1 <= 0x0000 7fff.
+ *
+ * var2 16 bit short signed integer (Word16) whose value falls in
+ * the range : 0xffff 8000 <= var2 <= 0x0000 7fff.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value :
+ *
+ * var_out 16 bit short signed integer (Word16) whose value falls in
+ * the range : 0xffff 8000 <= var_out <= 0x0000 7fff.
+ *
+ *****************************************************************************/
+Word16 shl_r( Word16 var1, Word16 var2)
+{
+ Word16 var_out;
+
+ if( var2 >= 0)
+ {
+ var_out = shl( var1, var2);
+ }
+ else
+ {
+ var2 = -var2;
+ var_out = shr_r( var1, var2);
+ }
+
+
+ return( var_out);
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : L_shl_r
+ *
+ * Purpose :
+ *
+ * Same as L_shl( var1, var2) but with rounding. Saturates the result in
+ * case of underflows or overflows.
+ *
+ * Complexity weight : 3
+ *
+ * Inputs :
+ *
+ * L_var1 32 bit long signed integer (Word32) whose value falls in
+ * the range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.
+ *
+ * var2 16 bit short signed integer (Word16) whose value falls in
+ * the range : 0xffff 8000 <= var2 <= 0x0000 7fff.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value :
+ *
+ * L_var_out 32 bit long signed integer (Word32) whose value falls in
+ * the range : 0x8000 0000 <= var_out <= 0x7fff ffff.
+ *
+ *****************************************************************************/
+Word32 L_shl_r( Word32 L_var1, Word16 var2)
+{
+ Word32 var_out;
+
+ if( var2 >= 0)
+ {
+ var_out = L_shl( L_var1, var2);
+ }
+ else
+ {
+ var2 = -var2;
+ var_out = L_shr_r( L_var1, var2);
+ }
+
+
+ return( var_out);
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : rotr
+ *
+ * Purpose :
+ *
+ * Performs a 16-bit logical rotation of var1 by 1 bit to the LSBits. The
+ * MSBit is set to var2 bit 0. The LSBit of var1 is kept in *var3 bit 0.
+ *
+ * Complexity weight : 3
+ *
+ * Inputs :
+ *
+ * var1 16 bit short signed integer (Word16) whose value falls in
+ * the range : 0xffff 8000 <= var1 <= 0x0000 7fff.
+ *
+ * var2 16 bit short signed integer (Word16) whose value must be 0
+ * or 1.
+ *
+ * Outputs :
+ *
+ * *var3 Points on a 16 bit short signed integer (Word16) whose
+ * value will be 0 or 1.
+ *
+ * Return Value :
+ *
+ * var_out 16 bit short signed integer (Word16) whose value falls in
+ * the range : 0xffff 8000 <= var_out <= 0x0000 7fff.
+ *
+ *****************************************************************************/
+Word16 rotr( Word16 var1, Word16 var2, Word16 *var3)
+{
+ Word16 var_out;
+
+ *var3 = s_and( var1, 0x1);
+ var_out = s_or( lshr( var1, 1),
+ lshl( var2, 15));
+
+
+ return( var_out);
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : rotl
+ *
+ * Purpose :
+ *
+ * Performs a 16-bit logical rotation of var1 by 1 bit to the MSBits. The
+ * LSBit is set to var2 bit 0. The MSBit of var1 is kept in *var3 bit 0.
+ *
+ * Complexity weight : 3
+ *
+ * Inputs :
+ *
+ * var1 16 bit short signed integer (Word16) whose value falls in
+ * the range : 0xffff 8000 <= var1 <= 0x0000 7fff.
+ *
+ * var2 16 bit short signed integer (Word16) whose value must be 0
+ * or 1.
+ *
+ * Outputs :
+ *
+ * *var3 Points on a 16 bit short signed integer (Word16) whose
+ * value will be 0 or 1.
+ *
+ * Return Value :
+ *
+ * var_out 16 bit short signed integer (Word16) whose value falls in
+ * the range : 0xffff 8000 <= var_out <= 0x0000 7fff.
+ *
+ *****************************************************************************/
+Word16 rotl( Word16 var1, Word16 var2, Word16 *var3)
+{
+ Word16 var_out;
+
+ *var3 = lshr( var1, 15);
+
+ var_out = s_or( lshl( var1, 1),
+ s_and( var2, 0x1));
+
+
+ return( var_out);
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : L_rotr
+ *
+ * Purpose :
+ *
+ * Performs a 32-bit logical rotation of L_var1 by 1 bit to the LSBits. The
+ * MSBit is set to var2 bit 0. The LSBit of L_var1 is kept in *var3 bit 0.
+ *
+ * Complexity weight : 3
+ *
+ * Inputs :
+ *
+ * L_var1 32 bit long signed integer (Word32) whose value falls in
+ * the range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.
+ *
+ * var2 16 bit short signed integer (Word16) whose value must be 0
+ * or 1.
+ *
+ * Outputs :
+ *
+ * *var3 Points on a 16 bit short signed integer (Word16) whose
+ * value will be 0 or 1.
+ *
+ * Return Value :
+ *
+ * L_var_out 32 bit long signed integer (Word32) whose value falls in
+ * the range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.
+ *
+ *****************************************************************************/
+Word32 L_rotr( Word32 L_var1, Word16 var2, Word16 *var3)
+{
+ Word32 L_var_out;
+
+ *var3 = s_and( extract_l( L_var1), 0x1);
+
+ L_var_out = L_or( L_lshr( L_var1, 1),
+ L_lshl( L_deposit_l( var2), 31));
+
+
+ return( L_var_out);
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : L_rotl
+ *
+ * Purpose :
+ *
+ * Performs a 32-bit logical rotation of L_var1 by 1 bit to the MSBits. The
+ * LSBit is set to var2 bit 0. The MSBit of L_var1 is kept in *var3 bit 0.
+ *
+ * Complexity weight : 3
+ *
+ * Inputs :
+ *
+ * L_var1 32 bit long signed integer (Word32) whose value falls in
+ * the range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.
+ *
+ * var2 16 bit short signed integer (Word16) whose value must be 0
+ * or 1.
+ *
+ * Outputs :
+ *
+ * *var3 Points on a 16 bit short signed integer (Word16) whose
+ * value will be 0 or 1.
+ *
+ * Return Value :
+ *
+ * L_var_out 32 bit long signed integer (Word32) whose value falls in
+ * the range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.
+ *
+ *****************************************************************************/
+Word32 L_rotl( Word32 L_var1, Word16 var2, Word16 *var3)
+{
+ Word32 L_var_out;
+
+ *var3 = extract_l( L_lshr( L_var1, 31));
+
+ L_var_out = L_or( L_lshl( L_var1, 1),
+ L_deposit_l( s_and( var2, 0x1)));
+
+
+ return( L_var_out);
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/* end of file */
diff --git a/lib_com/__zaloha/enh1632.h b/lib_com/__zaloha/enh1632.h
new file mode 100644
index 0000000000000000000000000000000000000000..33a772702abf0a7cbcd3094926ed9b9b7145920a
--- /dev/null
+++ b/lib_com/__zaloha/enh1632.h
@@ -0,0 +1,518 @@
+/*
+ ===========================================================================
+ File: ENH1632.H v.2.3 - 30.Nov.2009
+ ===========================================================================
+
+ ITU-T STL BASIC OPERATORS
+
+ ENHANCED 16-BIT & 32-BIT ARITHMETIC OPERATORS
+
+ History:
+ 07 Nov 04 v2.0 Incorporation of new 32-bit / 40-bit / control
+ operators for the ITU-T Standard Tool Library as
+ described in Geneva, 20-30 January 2004 WP 3/16 Q10/16
+ TD 11 document and subsequent discussions on the
+ wp3audio@yahoogroups.com email reflector.
+ March 06 v2.1 Changed to improve portability.
+ Some counters incrementations were missing (s_and,
+ s_or, s_xor).
+ 30 Nov 09 v2.3 saturate() removed
+
+ ============================================================================
+*/
+
+
+#ifndef _ENH1632_H
+#define _ENH1632_H
+
+
+/*****************************************************************************
+ *
+ * Constants and Globals
+ *
+ *****************************************************************************/
+
+
+#include "stl.h"
+
+
+/*****************************************************************************
+ *
+ * Prototypes for enhanced 16/32 bit arithmetic operators
+ *
+ *****************************************************************************/
+Word16 shl_r( Word16 var1, Word16 var2);
+Word32 L_shl_r( Word32 L_var1, Word16 var2);
+
+
+Word16 lshl( Word16 var1, Word16 var2);
+Word16 lshr( Word16 var1, Word16 var2);
+Word32 L_lshl( Word32 L_var1, Word16 var2);
+Word32 L_lshr( Word32 L_var1, Word16 var2);
+
+Word16 rotr( Word16 var1, Word16 var2, Word16 *var3);
+Word16 rotl( Word16 var1, Word16 var2, Word16 *var3);
+Word32 L_rotr( Word32 var1, Word16 var2, Word16 *var3);
+Word32 L_rotl( Word32 var1, Word16 var2, Word16 *var3);
+
+
+
+/*****************************************************************************
+ *
+ * Functions
+ *
+ *****************************************************************************/
+
+/*****************************************************************************
+ *
+ * Function Name : s_max
+ *
+ * Purpose :
+ *
+ * Compares var1 and var2 and returns the maximum value.
+ *
+ * Complexity weight : 1
+ *
+ * Inputs :
+ *
+ * var1 16 bit short signed integer (Word16) whose value falls in
+ * the range : 0x8000 <= var1 <= 0x7fff.
+ *
+ * var2 16 bit short signed integer (Word16) whose value falls in
+ * the range : 0x8000 <= var2 <= 0x7fff.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value :
+ *
+ * var_out 16 bit short signed integer (Word16) whose value falls in
+ * the range : 0x8000 <= L_var_out <= 0x7fff.
+ *
+ *****************************************************************************/
+static __inline Word16 s_max( Word16 var1, Word16 var2)
+{
+ Word16 var_out;
+
+ if( var1 >= var2)
+ var_out = var1;
+ else
+ var_out = var2;
+
+
+ return( var_out);
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : s_min
+ *
+ * Purpose :
+ *
+ * Compares var1 and var2 and returns the minimum value.
+ *
+ * Complexity weight : 1
+ *
+ * Inputs :
+ *
+ * var1 16 bit short signed integer (Word16) whose value falls in
+ * the range : 0x8000 <= var1 <= 0x7fff.
+ *
+ * var2 16 bit short signed integer (Word16) whose value falls in
+ * the range : 0x8000 <= var2 <= 0x7fff.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value :
+ *
+ * var_out 16 bit short signed integer (Word16) whose value falls in
+ * the range : 0x8000 <= var_out <= 0x7fff.
+ *
+ *****************************************************************************/
+static __inline Word16 s_min( Word16 var1, Word16 var2)
+{
+ Word16 var_out;
+
+ if( var1 <= var2)
+ var_out = var1;
+ else
+ var_out = var2;
+
+
+ return( var_out);
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : L_max
+ *
+ * Purpose :
+ *
+ * Compares L_var1 and L_var2 and returns the maximum value.
+ *
+ * Complexity weight : 1
+ *
+ * Inputs :
+ *
+ * L_var1 32 bit long signed integer (Word32) whose value falls in the
+ * range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.
+ *
+ * L_var2 32 bit long signed integer (Word32) whose value falls in the
+ * range : 0x8000 0000 <= L_var2 <= 0x7fff ffff.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value :
+ *
+ * L_var_out 32 bit long signed integer (Word32) whose value falls in the
+ * range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.
+ *
+ *****************************************************************************/
+static __inline Word32 L_max( Word32 L_var1, Word32 L_var2)
+{
+ Word32 L_var_out;
+
+ if( L_var1 >= L_var2)
+ L_var_out = L_var1;
+ else
+ L_var_out = L_var2;
+
+
+ return( L_var_out);
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : L_min
+ *
+ * Purpose :
+ *
+ * Compares L_var1 and L_var2 and returns the minimum value.
+ *
+ * Complexity weight : 1
+ *
+ * Inputs :
+ *
+ * L_var1 32 bit long signed integer (Word32) whose value falls in the
+ * range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.
+ *
+ * L_var2 32 bit long signed integer (Word32) whose value falls in the
+ * range : 0x8000 0000 <= L_var2 <= 0x7fff ffff.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value :
+ *
+ * L_var_out 32 bit long signed integer (Word32) whose value falls in the
+ * range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.
+ *
+ *****************************************************************************/
+static __inline Word32 L_min( Word32 L_var1, Word32 L_var2)
+{
+ Word32 L_var_out;
+
+ if( L_var1 <= L_var2)
+ L_var_out = L_var1;
+ else
+ L_var_out = L_var2;
+
+
+ return( L_var_out);
+}
+
+
+
+
+
+
+
+
+
+
+/*****************************************************************************
+ *
+ * Function Name : s_and
+ *
+ * Purpose :
+ *
+ * Performs logical AND of the two 16 bit input variables.
+ * var_out = var1 & var2
+ *
+ * Complexity weight : 1
+ *
+ * Inputs :
+ *
+ * var1 16 bit short signed integer (Word16) whose value
+ * falls in the range 0xffff 8000 <= var1 <= 0x0000 7fff.
+ *
+ * var2 16 bit short signed integer (Word16) whose value
+ * falls in the range 0xffff 8000 <= var2 <= 0x0000 7fff.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value :
+ *
+ * var_out 16 bit short signed integer (Word16) whose value
+ * falls in the range 0xffff 8000 <= var_out <= 0x0000 7fff.
+ *
+ *****************************************************************************/
+static __inline Word16 s_and( Word16 var1, Word16 var2)
+{
+ Word16 var_out;
+
+ var_out = var1 & var2;
+
+
+ return( var_out);
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : L_and
+ *
+ * Purpose :
+ *
+ * Performs logical AND of the two 32 bit input variables.
+ * L_var_out = L_var1 & L_var2
+ *
+ * Complexity weight : 1
+ *
+ * Inputs :
+ *
+ * L_var1 32 bit long signed integer (Word32) whose value
+ * falls in the range 0x8000 0000 <= L_var1 <= 0x7fff ffff.
+ *
+ * L_var2 32 bit long signed integer (Word32) whose value
+ * falls in the range 0x8000 0000 <= L_var2 <= 0x7fff ffff.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value :
+ *
+ * L_var_out 32 bit long signed integer (Word32) whose value
+ * falls in the range 0x8000 0000 <= L_var_out <= 0x7fff ffff.
+ *
+ *****************************************************************************/
+static __inline Word32 L_and( Word32 L_var1, Word32 L_var2)
+{
+ Word32 L_var_out;
+
+ L_var_out = L_var1 & L_var2;
+
+
+ return( L_var_out);
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : s_or
+ *
+ * Purpose :
+ *
+ * Performs logical OR of the two 16 bit input variables.
+ * var_out = var1 | var2
+ *
+ * Complexity weight : 1
+ *
+ * Inputs :
+ *
+ * var1 16 bit short signed integer (Word16) whose value
+ * falls in the range 0xffff 8000 <= var1 <= 0x0000 7fff.
+ *
+ * var2 16 bit short signed integer (Word16) whose value
+ * falls in the range 0xffff 8000 <= var2 <= 0x0000 7fff.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value :
+ *
+ * var_out 16 bit short signed integer (Word16) whose value
+ * falls in the range 0xffff 8000 <= var_out <= 0x0000 7fff.
+ *
+ *****************************************************************************/
+static __inline Word16 s_or( Word16 var1, Word16 var2)
+{
+ Word16 var_out;
+
+ var_out = var1 | var2;
+
+
+ return( var_out);
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : L_or
+ *
+ * Purpose :
+ *
+ * Performs logical OR of the two 32 bit input variables.
+ * L_var_out = L_var1 | L_var2
+ *
+ * Complexity weight : 1
+ *
+ * Inputs :
+ *
+ * L_var1 32 bit long signed integer (Word32) whose value
+ * falls in the range 0x8000 0000 <= L_var1 <= 0x7fff ffff.
+ *
+ * L_var2 32 bit long signed integer (Word32) whose value
+ * falls in the range 0x8000 0000 <= L_var2 <= 0x7fff ffff.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value :
+ *
+ * L_var_out 32 bit long signed integer (Word32) whose value
+ * falls in the range 0x8000 0000 <= L_var_out <= 0x7fff ffff.
+ *
+ *****************************************************************************/
+static __inline Word32 L_or( Word32 L_var1, Word32 L_var2)
+{
+
+ Word32 L_var_out;
+
+ L_var_out = L_var1 | L_var2;
+
+
+ return( L_var_out);
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : s_xor
+ *
+ * Purpose :
+ *
+ * Performs logical XOR of the two 16 bit input variables.
+ * var_out = var1 ^ var2
+ *
+ * Complexity weight : 1
+ *
+ * Inputs :
+ *
+ * var1 16 bit short signed integer (Word16) whose value
+ * falls in the range 0xffff 8000 <= var1 <= 0x0000 7fff.
+ *
+ * var2 16 bit short signed integer (Word16) whose value
+ * falls in the range 0xffff 8000 <= var2 <= 0x0000 7fff.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value :
+ *
+ * var_out 16 bit short signed integer (Word16) whose value
+ * falls in the range 0xffff 8000 <= var_out <= 0x0000 7fff.
+ *
+ *****************************************************************************/
+static __inline Word16 s_xor( Word16 var1, Word16 var2)
+{
+ Word16 var_out;
+
+ var_out = var1 ^ var2;
+
+
+ return( var_out);
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : L_xor
+ *
+ * Purpose :
+ *
+ * Performs logical OR of the two 32 bit input variables.
+ * L_var_out = L_var1 ^ L_var2
+ *
+ * Complexity weight : 1
+ *
+ * Inputs :
+ *
+ * L_var1 32 bit long signed integer (Word32) whose value
+ * falls in the range 0x8000 0000 <= L_var1 <= 0x7fff ffff.
+ *
+ * L_var2 32 bit long signed integer (Word32) whose value
+ * falls in the range 0x8000 0000 <= L_var2 <= 0x7fff ffff.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value :
+ *
+ * L_var_out 32 bit long signed integer (Word32) whose value
+ * falls in the range 0x8000 0000 <= L_var_out <= 0x7fff ffff.
+ *
+ *****************************************************************************/
+static __inline Word32 L_xor( Word32 L_var1, Word32 L_var2)
+{
+ Word32 L_var_out;
+
+ L_var_out = L_var1 ^ L_var2;
+
+
+ return( L_var_out);
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#endif /*_ENH1632_H*/
+
+/* end of file */
diff --git a/lib_com/__zaloha/enh40.c b/lib_com/__zaloha/enh40.c
new file mode 100644
index 0000000000000000000000000000000000000000..bc5c9970ae5558de3dcc2bc088bd5d14611c4538
--- /dev/null
+++ b/lib_com/__zaloha/enh40.c
@@ -0,0 +1,1071 @@
+
+/*
+ ===========================================================================
+ File: ENH40.C v.2.3 - 30.Nov.2009
+ ===========================================================================
+
+ ITU-T STL BASIC OPERATORS
+
+ 40-BIT ARITHMETIC OPERATORS
+
+ History:
+ 07 Nov 04 v2.0 Incorporation of new 32-bit / 40-bit / control
+ operators for the ITU-T Standard Tool Library as
+ described in Geneva, 20-30 January 2004 WP 3/16 Q10/16
+ TD 11 document and subsequent discussions on the
+ wp3audio@yahoogroups.com email reflector.
+
+ ============================================================================
+*/
+
+
+/*****************************************************************************
+ *
+ * Enhanced 40 bit operators :
+ *
+ * L40_add()
+ * L40_sub()
+ * L40_abs()
+ * L40_negate()
+ * L40_max()
+ * L40_min()
+ * L40_shr()
+ * L40_shr_r()
+ * L40_shl()
+ * L40_shl_r()
+ * norm_L40()
+ * L40_mult()
+ * L40_mac()
+ * L40_msu()
+ * mac_r40()
+ * msu_r40()
+ * Mpy_32_16_ss()
+ * Mpy_32_32_ss()
+ * L40_lshl()
+ * L40_lshr()
+ * L40_round()
+ * L_saturate40()
+ * L40_set()
+ * Extract40_H()
+ * Extract40_L()
+ * L_Extract40()
+ * L40_deposit_h()
+ * L40_deposit_l()
+ * L40_deposit32()
+ *
+ *****************************************************************************/
+
+
+/*****************************************************************************
+ *
+ * Include-Files
+ *
+ *****************************************************************************/
+#include
+#include
+#include "stl.h"
+#include "wmc_auto.h"
+
+#ifdef _MSC_VER
+#pragma warning( disable : 4310 )
+#endif
+
+/*****************************************************************************
+ *
+ * Local Functions
+ *
+ *****************************************************************************/
+
+
+/*****************************************************************************
+ *
+ * Constants and Globals
+ *
+ *****************************************************************************/
+
+
+/*****************************************************************************
+ *
+ * Functions
+ *
+ *****************************************************************************/
+
+/*****************************************************************************
+ *
+ * Function Name : L40_shl
+ *
+ * Purpose :
+ *
+ * Arithmetically shifts left L40_var1 by var2 positions.
+ * - If var2 is negative, L40_var1 is shifted to the LSBits by (-var2)
+ * positions with extension of the sign bit.
+ * - If var2 is positive, L40_var1 is shifted to the MSBits by (var2)
+ * positions.
+ * Calls the macro L40_UNDERFLOW_OCCURED() in case of underflow on 40-bit.
+ * Calls the macro L40_OVERFLOW_OCCURED() in case of overflow on 40-bit.
+ *
+ * Complexity weight : 1
+ *
+ * Inputs :
+ *
+ * L40_var1 40 bit long signed integer (Word40) whose value falls in the
+ * range : MIN_40 <= L40_var1 <= MAX_40.
+ *
+ * var2 16 bit short signed integer (Word16) whose value falls in
+ * the range : MIN_16 <= var2 <= MAX_16.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value :
+ *
+ * L40_var_out 40 bit long signed integer (Word40) whose value falls in
+ * the range : MIN_40 <= L40_var_out <= MAX_40.
+ *
+ *****************************************************************************/
+Word40 L40_shl( Word40 L40_var1, Word16 var2)
+{
+
+ Word40 L40_var_out;
+ Word40 L40_constant;
+
+#if defined(_MSC_VER) && (_MSC_VER <= 1200)
+ L40_constant = L40_set( 0xc000000000);
+#else
+ L40_constant = L40_set( 0xc000000000LL);
+#endif
+
+ if( var2 < 0)
+ {
+ var2 = -var2;
+ L40_var_out = L40_shr( L40_var1, var2);
+ }
+
+ else
+ {
+ L40_var_out = L40_var1;
+
+ for ( ; var2 > 0; var2--)
+ {
+#if defined(_MSC_VER) && (_MSC_VER <= 1200)
+ if( L40_var_out > 0x003fffffffff)
+#else
+ if( L40_var_out > 0x003fffffffffLL)
+#endif
+ {
+ Overflow = 1;
+ exit(1);
+ /* L40_var_out = L40_OVERFLOW_OCCURED( L40_var_out); */
+ }
+
+ else if ( L40_var_out < L40_constant)
+ {
+ Overflow = 1;
+ exit(2);
+ /* L40_var_out = L40_UNDERFLOW_OCCURED( L40_var_out); */
+ }
+
+ else
+ {
+ L40_var_out = L40_var_out << 1;
+ }
+ }
+ }
+
+ BASOP_CHECK();
+
+
+ return( L40_var_out);
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : L40_shr
+ *
+ * Purpose :
+ *
+ * Arithmetically shifts right L40_var1 by var2 positions.
+ * - If var2 is positive, L40_var1 is shifted to the LSBits by (var2)
+ * positions with extension of the sign bit.
+ * - If var2 is negative, L40_var1 is shifted to the MSBits by (-var2)
+ * positions.
+ * Calls the macro L40_UNDERFLOW_OCCURED() in case of underflow on 40-bit.
+ * Calls the macro L40_OVERFLOW_OCCURED() in case of overflow on 40-bit.
+ *
+ * Complexity weight : 1
+ *
+ * Inputs :
+ *
+ * L40_var1 40 bit long signed integer (Word40) whose value falls in the
+ * range : MIN_40 <= L40_var1 <= MAX_40.
+ *
+ * var2 16 bit short signed integer (Word16) whose value falls in
+ * the range : MIN_16 <= var2 <= MAX_16.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value :
+ *
+ * L40_var_out 40 bit long signed integer (Word40) whose value falls in
+ * the range : MIN_40 <= L40_var_out <= MAX_40.
+ *
+ *****************************************************************************/
+Word40 L40_shr( Word40 L40_var1, Word16 var2)
+{
+ Word40 L40_var_out;
+
+ if( var2 < 0)
+ {
+ var2 = -var2;
+ L40_var_out = L40_shl ( L40_var1, var2);
+ }
+ else
+ {
+ L40_var_out = L40_var1 >> var2;
+
+ }
+
+
+ return( L40_var_out);
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : L40_negate
+ *
+ * Purpose :
+ *
+ * Negates L40_var1.
+ * Calls the macro L40_UNDERFLOW_OCCURED() in case of underflow on 40-bit.
+ * Calls the macro L40_OVERFLOW_OCCURED() in case of overflow on 40-bit.
+ *
+ * Complexity weight : 1
+ *
+ * Inputs :
+ *
+ * L40_var1 40 bit long signed integer (Word40) whose value falls in the
+ * range : MIN_40 <= L40_var1 <= MAX_40.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value :
+ *
+ * L40_var_out 40 bit long signed integer (Word40) whose value falls in
+ * the range : MIN_40 <= L40_var_out <= MAX_40.
+ *
+ *****************************************************************************/
+Word40 L40_negate( Word40 L40_var1)
+{
+ Word40 L40_var_out;
+
+ L40_var_out = L40_add( ~L40_var1, 0x01);
+
+ return( L40_var_out);
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : L40_add
+ *
+ * Purpose :
+ *
+ * Adds L40_var1 and L40_var2 and returns the 40-bit result.
+ * Calls the macro L40_UNDERFLOW_OCCURED() in case of underflow on 40-bit.
+ * Calls the macro L40_OVERFLOW_OCCURED() in case of overflow on 40-bit.
+ *
+ * Complexity weight : 1
+ *
+ * Inputs :
+ *
+ * L40_var1 40 bit long signed integer (Word40) whose value falls in the
+ * range : MIN_40 <= L40_var1 <= MAX_40.
+ *
+ * L40_var2 40 bit long signed integer (Word40) whose value falls in the
+ * range : MIN_40 <= L40_var2 <= MAX_40.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value :
+ *
+ * L40_var_out 40 bit long signed integer (Word40) whose value falls in
+ * the range : MIN_40 <= L40_var_out <= MAX_40.
+ *
+ *****************************************************************************/
+Word40 L40_add( Word40 L40_var1, Word40 L40_var2)
+{
+ Word40 L40_var_out;
+
+ L40_var_out = L40_var1 + L40_var2;
+
+#if defined(_MSC_VER) && (_MSC_VER <= 1200)
+ if( ((( L40_var1 & 0x8000000000) >> 39) != 0)
+ && ((( L40_var2 & 0x8000000000) >> 39) != 0)
+ && ((( L40_var_out & 0x8000000000) >> 39) == 0))
+ {
+ Overflow = 1;
+ exit(2);
+ /* L40_var_out = L40_UNDERFLOW_OCCURED( L40_var_out); */
+
+ }
+ else if( (((L40_var1 & 0x8000000000) >> 39) == 0)
+ && (((L40_var2 & 0x8000000000) >> 39) == 0)
+ && (((L40_var_out & 0x8000000000) >> 39) != 0))
+ {
+ Overflow = 1;
+ exit(1);
+ /* L40_var_out = L40_OVERFLOW_OCCURED( L40_var_out); */
+ }
+#else
+ if( ((( L40_var1 & 0x8000000000LL) >> 39) != 0)
+ && ((( L40_var2 & 0x8000000000LL) >> 39) != 0)
+ && ((( L40_var_out & 0x8000000000LL) >> 39) == 0))
+ {
+ Overflow = 1;
+ exit(2);
+ /* L40_var_out = L40_UNDERFLOW_OCCURED( L40_var_out); */
+
+ }
+ else if( (((L40_var1 & 0x8000000000LL) >> 39) == 0)
+ && (((L40_var2 & 0x8000000000LL) >> 39) == 0)
+ && (((L40_var_out & 0x8000000000LL) >> 39) != 0))
+ {
+ Overflow = 1;
+ exit(1);
+ /* L40_var_out = L40_OVERFLOW_OCCURED( L40_var_out); */
+ }
+#endif
+
+ BASOP_CHECK();
+
+
+ return( L40_var_out);
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : L40_sub
+ *
+ * Purpose :
+ *
+ * Subtracts L40_var2 from L40_var1.
+ * Calls the macro L40_UNDERFLOW_OCCURED() in case of underflow on 40-bit.
+ * Calls the macro L40_OVERFLOW_OCCURED() in case of overflow on 40-bit.
+ *
+ * Complexity weight : 1
+ *
+ * Inputs :
+ *
+ * L40_var1 40 bit long signed integer (Word40) whose value falls in the
+ * range : MIN_40 <= L40_var1 <= MAX_40.
+ *
+ * L40_var2 40 bit long signed integer (Word40) whose value falls in the
+ * range : MIN_40 <= L40_var2 <= MAX_40.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value :
+ *
+ * L40_var_out 40 bit long signed integer (Word40) whose value falls in
+ * the range : MIN_40 <= L40_var_out <= MAX_40.
+ *
+ *****************************************************************************/
+Word40 L40_sub( Word40 L40_var1, Word40 L40_var2)
+{
+ Word40 L40_var_out;
+
+ L40_var_out = L40_var1 - L40_var2;
+
+#if defined(_MSC_VER) && (_MSC_VER <= 1200)
+ if( (((L40_var1 & 0x8000000000) >> 39) != 0)
+ && (((L40_var2 & 0x8000000000) >> 39) == 0)
+ && (((L40_var_out & 0x8000000000) >> 39) == 0))
+ {
+ Overflow = 1;
+ exit(2);
+ /* L40_var_out = L40_UNDERFLOW_OCCURED( L40_var_out); */
+
+ }
+ else if( (((L40_var1 & 0x8000000000) >> 39) == 0)
+ && (((L40_var2 & 0x8000000000) >> 39) != 0)
+ && (((L40_var_out & 0x8000000000) >> 39) != 0))
+ {
+ Overflow = 1;
+ exit(1);
+ /* L40_var_out = L40_OVERFLOW_OCCURED( L40_var_out); */
+ }
+#else
+ if( (((L40_var1 & 0x8000000000LL) >> 39) != 0)
+ && (((L40_var2 & 0x8000000000LL) >> 39) == 0)
+ && (((L40_var_out & 0x8000000000LL) >> 39) == 0))
+ {
+ Overflow = 1;
+ exit(2);
+ /* L40_var_out = L40_UNDERFLOW_OCCURED( L40_var_out); */
+
+ }
+ else if( (((L40_var1 & 0x8000000000LL) >> 39) == 0)
+ && (((L40_var2 & 0x8000000000LL) >> 39) != 0)
+ && (((L40_var_out & 0x8000000000LL) >> 39) != 0))
+ {
+ Overflow = 1;
+ exit(1);
+ /* L40_var_out = L40_OVERFLOW_OCCURED( L40_var_out); */
+ }
+#endif
+
+ BASOP_CHECK();
+
+
+ return( L40_var_out);
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : L40_abs
+ *
+ * Purpose :
+ *
+ * Returns the absolute value of L40_var1.
+ * Calls the macro L40_UNDERFLOW_OCCURED() in case of underflow on 40-bit.
+ * Calls the macro L40_OVERFLOW_OCCURED() in case of overflow on 40-bit.
+ *
+ * Complexity weight : 1
+ *
+ * Inputs :
+ *
+ * L40_var1 40 bit long signed integer (Word40) whose value falls in the
+ * range : MIN_40 <= L40_var1 <= MAX_40.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value :
+ *
+ * L40_var_out 40 bit long signed integer (Word40) whose value falls in
+ * the range : 0x00 0000 0000 <= L40_var_out <= MAX_40.
+ *
+ *****************************************************************************/
+Word40 L40_abs( Word40 L40_var1)
+{
+ Word40 L40_var_out;
+
+ if( L40_var1 < 0)
+ {
+ L40_var_out = L40_negate ( L40_var1);
+ }
+ else
+ {
+ L40_var_out = L40_var1;
+ }
+
+
+ return( L40_var_out);
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : L40_max
+ *
+ * Purpose :
+ *
+ * Compares L40_var1 and L40_var2 and returns the maximum value.
+ *
+ *
+ * Complexity weight : 1
+ *
+ * Inputs :
+ *
+ * L40_var1 40 bit long signed integer (Word40) whose value falls in the
+ * range : MIN_40 <= L40_var1 <= MAX_40.
+ *
+ * L40_var2 40 bit long signed integer (Word40) whose value falls in the
+ * range : MIN_40 <= L40_var2 <= MAX_40.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value :
+ *
+ * L40_var_out 40 bit long signed integer (Word40) whose value falls in
+ * the range : MIN_40 <= L40_var_out <= MAX_40.
+ *
+ *****************************************************************************/
+Word40 L40_max( Word40 L40_var1, Word40 L40_var2)
+{
+ Word40 L40_var_out;
+
+ if( L40_var1 < L40_var2)
+ L40_var_out = L40_var2;
+ else
+ L40_var_out = L40_var1;
+
+
+ return( L40_var_out);
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : L40_min
+ *
+ * Purpose :
+ *
+ * Compares L40_var1 and L40_var2 and returns the minimum value.
+ *
+ *
+ * Complexity weight : 1
+ *
+ * Inputs :
+ *
+ * L40_var1 40 bit long signed integer (Word40) whose value falls in the
+ * range : MIN_40 <= L40_var1 <= MAX_40.
+ *
+ * L40_var2 40 bit long signed integer (Word40) whose value falls in the
+ * range : MIN_40 <= L40_var2 <= MAX_40.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value :
+ *
+ * L40_var_out 40 bit long signed integer (Word40) whose value falls in
+ * the range : MIN_40 <= L40_var_out <= MAX_40.
+ *
+ *****************************************************************************/
+Word40 L40_min( Word40 L40_var1, Word40 L40_var2)
+{
+ Word40 L40_var_out;
+
+ if( L40_var1 < L40_var2)
+ L40_var_out = L40_var1;
+ else
+ L40_var_out = L40_var2;
+
+
+ return( L40_var_out);
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : L_saturate40
+ *
+ * Purpose :
+ *
+ * If L40_var1 is greater than MAX_32, returns MAX_32.
+ * If L40_var1 is lower than MIN_32, returns MIN_32.
+ * If not, returns L_Extract40( L40_var1).
+ *
+ * Complexity weight : 1
+ *
+ * Inputs :
+ *
+ * L40_var1 40 bit long signed integer (Word40) whose value falls in the
+ * range : MIN_40 <= L40_var1 <= MAX_40.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value :
+ *
+ * L_var_out 32 bit long signed integer (Word32) whose value falls in
+ * the range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.
+ *
+ *****************************************************************************/
+Word32 L_saturate40( Word40 L40_var1)
+{
+ Word32 L_var_out;
+
+ Word40 UNDER_L40_var2 = ( Word40) ~(((( Word40) 1) << 31) - ( Word40) 1 );
+ Word40 OVER_L40_var2 = ( Word40) (((( Word40) 1) << 31) - ( Word40) 1 );
+
+ if( L40_var1 < UNDER_L40_var2)
+ {
+ L40_var1 = UNDER_L40_var2;
+ Overflow = 1;
+ }
+
+ if( L40_var1 > OVER_L40_var2)
+ {
+ L40_var1 = OVER_L40_var2;
+ Overflow = 1;
+ }
+
+ L_var_out = L_Extract40( L40_var1);
+
+ BASOP_CHECK();
+
+
+ return( L_var_out);
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : Mpy_32_16_ss
+ *
+ * Purpose :
+ *
+ * Multiplies the 2 signed values L_var1 and var2 with saturation control
+ * on 48-bit. The operation is performed in fractional mode :
+ * - L_var1 is supposed to be in 1Q31 format.
+ * - var2 is supposed to be in 1Q15 format.
+ * - The result is produced in 1Q47 format : L_varout_h points to the
+ * 32 MSBits while varout_l points to the 16 LSBits.
+ *
+ * Complexity weight : 2
+ *
+ * Inputs :
+ *
+ * L_var1 32 bit long signed integer (Word32) whose value falls in
+ * the range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.
+ *
+ * var2 16 bit short signed integer (Word16) whose value falls in
+ * the range : 0xffff 8000 <= var2 <= 0x0000 7fff.
+ *
+ * Outputs :
+ *
+ * *L_varout_h 32 bit long signed integer (Word32) whose value falls in
+ * the range : 0x8000 0000 <= L_varout_h <= 0x7fff ffff.
+ *
+ * *varout_l 16 bit short unsigned integer (UWord16) whose value falls in
+ * the range : 0x0000 0000 <= varout_l <= 0x0000 ffff.
+ *
+ * Return Value :
+ *
+ * none
+ *
+ *****************************************************************************/
+void Mpy_32_16_ss( Word32 L_var1, Word16 var2, Word32 *L_varout_h, UWord16 *varout_l)
+{
+ Word16 var1_h;
+ UWord16 uvar1_l;
+ Word40 L40_var1;
+
+ if( (L_var1 == ( Word32) 0x80000000)
+ && (var2 == ( Word16) 0x8000))
+ {
+ *L_varout_h = 0x7fffffff;
+ *varout_l = ( UWord16) 0xffff;
+
+ }
+ else
+ {
+ uvar1_l = extract_l( L_var1);
+ var1_h = extract_h( L_var1);
+
+ /* Below line can not overflow, so we can use << instead of L40_shl. */
+ L40_var1 = (( Word40) (( Word32) var2 * ( Word32) uvar1_l)) << 1;
+
+ *varout_l = Extract40_L( L40_var1);
+
+ L40_var1 = L40_shr( L40_var1, 16);
+ L40_var1 = L40_mac( L40_var1, var2, var1_h);
+
+ *L_varout_h = L_Extract40( L40_var1);
+ }
+
+
+ return;
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : Mpy_32_32_ss
+ *
+ * Purpose :
+ *
+ * Multiplies the 2 signed values L_var1 and L_var2 with saturation control
+ * on 64-bit. The operation is performed in fractional mode :
+ * - L_var1 and L_var2 are supposed to be in 1Q31 format.
+ * - The result is produced in 1Q63 format : L_varout_h points to the
+ * 32 MSBits while L_varout_l points to the 32 LSBits.
+ *
+ * Complexity weight : 4
+ *
+ * Inputs :
+ *
+ * L_var1 32 bit long signed integer (Word32) whose value falls in the
+ * range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.
+ *
+ * L_var2 32 bit long signed integer (Word32) whose value falls in the
+ * range : 0x8000 0000 <= L_var2 <= 0x7fff ffff.
+ *
+ * Outputs :
+ *
+ * *L_varout_h 32 bit long signed integer (Word32) whose value falls in
+ * the range : 0x8000 0000 <= L_varout_h <= 0x7fff ffff.
+ *
+ * *L_varout_l 32 bit short unsigned integer (UWord32) whose value falls in
+ * the range : 0x0000 0000 <= L_varout_l <= 0xffff ffff.
+ *
+ *
+ * Return Value :
+ *
+ * none
+ *
+ *****************************************************************************/
+void Mpy_32_32_ss( Word32 L_var1, Word32 L_var2, Word32 *L_varout_h, UWord32 *L_varout_l)
+{
+ UWord16 uvar1_l, uvar2_l;
+ Word16 var1_h, var2_h;
+ Word40 L40_var1;
+
+ if( (L_var1 == ( Word32)0x80000000)
+ && (L_var2 == ( Word32)0x80000000))
+ {
+ *L_varout_h = 0x7fffffff;
+ *L_varout_l = ( UWord32)0xffffffff;
+
+ }
+ else
+ {
+
+ uvar1_l = extract_l( L_var1);
+ var1_h = extract_h( L_var1);
+ uvar2_l = extract_l( L_var2);
+ var2_h = extract_h( L_var2);
+
+ /* Below line can not overflow, so we can use << instead of L40_shl. */
+ L40_var1 = (( Word40) (( UWord32) uvar2_l * ( UWord32) uvar1_l)) << 1;
+
+ *L_varout_l = 0x0000ffff & L_Extract40( L40_var1);
+
+ L40_var1 = L40_shr( L40_var1, 16);
+ L40_var1 = L40_add( L40_var1, (( Word40) (( Word32) var2_h * ( Word32) uvar1_l)) << 1);
+ L40_var1 = L40_add( L40_var1, (( Word40) (( Word32) var1_h * ( Word32) uvar2_l)) << 1);
+ *L_varout_l |= (L_Extract40( L40_var1)) << 16;
+
+ L40_var1 = L40_shr( L40_var1, 16);
+ L40_var1 = L40_mac( L40_var1, var1_h, var2_h);
+
+ *L_varout_h = L_Extract40( L40_var1);
+ }
+
+
+ return;
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : L40_lshl
+ *
+ * Purpose :
+ *
+ * Logically shifts left L40_var1 by var2 positions.
+ * - If var2 is negative, L40_var1 is shifted to the LSBits by (-var2)
+ * positions with insertion of 0 at the MSBit.
+ * - If var2 is positive, L40_var1 is shifted to the MSBits by (var2)
+ * positions.
+ *
+ * Complexity weight : 1
+ *
+ * Inputs :
+ *
+ * L40_var1 40 bit long signed integer (Word40) whose value falls in the
+ * range : MIN_40 <= L40_var1 <= MAX_40.
+ *
+ * var2 16 bit short signed integer (Word16) whose value falls in
+ * the range : MIN_16 <= var2 <= MAX_16.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value :
+ *
+ * L40_var_out 40 bit long signed integer (Word40) whose value falls in
+ * the range : MIN_40 <= L40_var_out <= MAX_40.
+ *
+ *****************************************************************************/
+Word40 L40_lshl( Word40 L40_var1, Word16 var2)
+{
+ Word40 L40_var_out;
+
+ if( var2 <= 0)
+ {
+ var2 = -var2;
+ L40_var_out = L40_lshr ( L40_var1, var2);
+ }
+ else
+ {
+ if( var2 >= 40)
+ L40_var_out = 0x0000000000;
+ else
+ {
+ L40_var_out = L40_var1 << var2;
+ }
+ L40_var_out = L40_set( L40_var_out);
+ }
+
+ BASOP_CHECK();
+
+
+ return( L40_var_out);
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : L40_lshr
+ *
+ * Purpose :
+ *
+ * Logically shifts right L40_var1 by var2 positions.
+ * - If var2 is positive, L40_var1 is shifted to the LSBits by (var2)
+ * positions with insertion of 0 at the MSBit.
+ * - If var2 is negative, L40_var1 is shifted to the MSBits by (-var2)
+ * positions.
+ *
+ * Complexity weight : 1
+ *
+ * Inputs :
+ *
+ * L40_var1 40 bit long signed integer (Word40) whose value falls in the
+ * range : MIN_40 <= L40_var1 <= MAX_40.
+ *
+ * var2 16 bit short signed integer (Word16) whose value falls in
+ * the range : MIN_16 <= var2 <= MAX_16.
+*
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value :
+ *
+ * L40_var_out 40 bit long signed integer (Word40) whose value falls in
+ * the range : MIN_40 <= L40_var_out <= MAX_40.
+ *
+ *****************************************************************************/
+Word40 L40_lshr( Word40 L40_var1, Word16 var2)
+{
+ Word40 L40_var_out;
+
+ if( var2 < 0)
+ {
+ var2 = -var2;
+ L40_var_out = L40_lshl ( L40_var1, var2);
+ }
+ else
+ {
+ if( var2 >= 40)
+ L40_var_out = 0x0000000000;
+ else
+ {
+#if defined(_MSC_VER) && (_MSC_VER <= 1200)
+ L40_var_out = (L40_var1 & 0xffffffffff) >> var2;
+#else
+ L40_var_out = (L40_var1 & 0xffffffffffLL) >> var2;
+#endif
+ }
+ }
+
+ BASOP_CHECK();
+
+
+ return( L40_var_out);
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : norm_L40
+ *
+ * Purpose :
+ *
+ * Produces the number of left shifts needed to normalize in 32 bit format
+ * the 40 bit variable L40_var1. This returned value can be used to scale
+ * L_40_var1 into the following intervals :
+ * - [(MAX_32+1)/2 .. MAX_32 ] for positive values.
+ * - [ MIN_32 .. (MIN_32/2)+1 ] for negative values.
+ * - [ 0 .. 0 ] for null values.
+ * In order to normalize the result, the following operation must be done :
+ * normelized_L40_var1 = L40_shl( L40_var1, norm_L40( L40_var1))
+ *
+ * Complexity weight : 1
+ *
+ * Inputs :
+ *
+ * L40_var1 40 bit long signed integer (Word40) whose value falls in the
+ * range : MIN_40 <= L40_var1 <= MAX_40.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value :
+ *
+ * var_out 16 bit short signed integer (Word16) whose value falls in
+ * the range : -8 <= var_out <= 31.
+ *
+ *****************************************************************************/
+Word16 norm_L40( Word40 L40_var1)
+{
+ Word16 var_out;
+
+ var_out = 0;
+
+ if( L40_var1 != 0)
+ {
+ while( (L40_var1 > ( Word32)0x80000000L)
+ && (L40_var1 < ( Word32)0x7fffffffL))
+ {
+
+ L40_var1 = L40_shl( L40_var1, 1);
+ var_out++;
+ }
+
+ while( (L40_var1 < ( Word32)0x80000000L)
+ || (L40_var1 > ( Word32)0x7fffffffL))
+ {
+
+ L40_var1 = L40_shl( L40_var1, -1);
+ var_out--;
+ }
+ }
+
+
+ return( var_out);
+}
+
+
+
+
+
+
+/*****************************************************************************
+ *
+ * Function Name : L40_shr_r
+ *
+ * Purpose :
+ *
+ * Arithmetically shifts right L40_var1 by var2 positions and rounds the
+ * result. It is equivalent to L40_shr( L40_var1, var2) except that if the
+ * last bit shifted out to the LSBit is 1, then the shifted result is
+ * incremented by 1.
+ * Calls the macro L40_UNDERFLOW_OCCURED() in case of underflow on 40-bit.
+ * Calls the macro L40_OVERFLOW_OCCURED() in case of overflow on 40-bit.
+ *
+ * Complexity weight : 3
+ *
+ * Inputs :
+ *
+ * L40_var1 40 bit long signed integer (Word40) whose value falls in the
+ * range : MIN_40 <= L40_var1 <= MAX_40.
+ *
+ * var2 16 bit short signed integer (Word16) whose value falls in
+ * the range : 0xffff 8000 <= var2 <= 0x0000 7fff.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value :
+ *
+ * L40_var_out 40 bit long signed integer (Word40) whose value falls in
+ * the range : MIN_40 <= L40_var_out <= MAX_40.
+ *
+ *****************************************************************************/
+Word40 L40_shr_r( Word40 L40_var1, Word16 var2)
+{
+ Word40 L40_var_out;
+
+ if( var2 > 39)
+ {
+ L40_var_out = 0;
+ }
+ else
+ {
+ L40_var_out = L40_shr( L40_var1, var2);
+
+ if( var2 > 0)
+ {
+ if( ( L40_var1 & (( Word40) 1 << (var2 - 1))) != 0)
+ {
+ /* below line can not generate overflows on 40-bit */
+ L40_var_out++;
+ }
+ }
+ }
+
+ BASOP_CHECK();
+
+
+ return( L40_var_out);
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : L40_shl_r
+ *
+ * Purpose :
+ *
+ * Arithmetically shifts left L40_var1 by var2 positions and rounds the
+ * result. It is equivalent to L40_shl( L40_var1, var2) except if var2 is
+ * negative. In that case, it does the same as
+ * L40_shr_r( L40_var1, (-var2)).
+ * Calls the macro L40_UNDERFLOW_OCCURED() in case of underflow on 40-bit.
+ * Calls the macro L40_OVERFLOW_OCCURED() in case of overflow on 40-bit.
+ *
+ * Complexity weight : 3
+ *
+ * Inputs :
+ *
+ * L40_var1 40 bit long signed integer (Word40) whose value falls in the
+ * range : MIN_40 <= L40_var1 <= MAX_40.
+ *
+ * var2 16 bit short signed integer (Word16) whose value falls in
+ * the range : 0xffff 8000 <= var2 <= 0x0000 7fff.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value :
+ *
+ * L40_var_out 40 bit long signed integer (Word40) whose value falls in
+ * the range : MIN_40 <= L40_var_out <= MAX_40.
+ *
+ *****************************************************************************/
+Word40 L40_shl_r( Word40 L40_var1, Word16 var2)
+{
+ Word40 L40_var_out;
+
+ if( var2 >= 0)
+ {
+ L40_var_out = L40_shl( L40_var1, var2);
+ }
+ else
+ {
+ var2 = -var2;
+ L40_var_out = L40_shr_r ( L40_var1, var2);
+ }
+
+
+ return( L40_var_out);
+}
+
+
+/* end of file */
diff --git a/lib_com/__zaloha/enh40.h b/lib_com/__zaloha/enh40.h
new file mode 100644
index 0000000000000000000000000000000000000000..bc13eda04839c78996257ce33a2ae08189355910
--- /dev/null
+++ b/lib_com/__zaloha/enh40.h
@@ -0,0 +1,383 @@
+/*
+ ===========================================================================
+ File: ENH40.H v.2.3 - 30.Nov.2009
+ ===========================================================================
+
+ ITU-T STL BASIC OPERATORS
+
+ 40-BIT ARITHMETIC OPERATORS
+
+ History:
+ 07 Nov 04 v2.0 Incorporation of new 32-bit / 40-bit / control
+ operators for the ITU-T Standard Tool Library as
+ described in Geneva, 20-30 January 2004 WP 3/16 Q10/16
+ TD 11 document and subsequent discussions on the
+ wp3audio@yahoogroups.com email reflector.
+ March 06 v2.1 Changed to improve portability.
+
+ ============================================================================
+*/
+
+
+#ifndef _ENH40_H
+#define _ENH40_H
+
+
+#include "stl.h"
+
+
+#ifdef _MSC_VER
+#define MAX_40 (0x0000007fffffffff)
+#define MIN_40 (0xffffff8000000000)
+#endif /* ifdef _MSC_VER */
+
+
+
+#define L40_OVERFLOW_OCCURED( L40_var1) (Overflow = 1, exit(1), L40_var1)
+#define L40_UNDERFLOW_OCCURED( L40_var1) (Overflow = 1, exit(2), L40_var1)
+
+
+
+/*****************************************************************************
+*
+* Prototypes for enhanced 40 bit arithmetic operators
+*
+*****************************************************************************/
+Word40 L40_shr( Word40 L40_var1, Word16 var2);
+Word40 L40_shr_r( Word40 L40_var1, Word16 var2);
+Word40 L40_shl( Word40 L40_var1, Word16 var2);
+Word40 L40_shl_r( Word40 L40_var1, Word16 var2);
+
+static __inline Word40 L40_mult( Word16 var1, Word16 var2);
+
+static __inline Word40 L40_mac( Word40 L40_var1, Word16 var1, Word16 var2);
+static __inline Word16 mac_r40( Word40 L40_var1, Word16 var1, Word16 var2);
+
+static __inline Word40 L40_msu( Word40 L40_var1, Word16 var1, Word16 var2);
+static __inline Word16 msu_r40( Word40 L40_var1, Word16 var1, Word16 var2);
+
+
+void Mpy_32_16_ss( Word32 L_var1, Word16 var2, Word32 *L_varout_h, UWord16 *varout_l);
+void Mpy_32_32_ss( Word32 L_var1, Word32 L_var2, Word32 *L_varout_h, UWord32 *L_varout_l);
+
+
+Word40 L40_lshl( Word40 L40_var1, Word16 var2);
+Word40 L40_lshr( Word40 L40_var1, Word16 var2);
+
+static __inline Word40 L40_set( Word40 L40_var1);
+static __inline UWord16 Extract40_H( Word40 L40_var1);
+static __inline UWord16 Extract40_L( Word40 L40_var1);
+static __inline UWord32 L_Extract40( Word40 L40_var1);
+
+static __inline Word40 L40_deposit_h( Word16 var1);
+static __inline Word40 L40_deposit_l( Word16 var1);
+static __inline Word40 L40_deposit32( Word32 L_var1);
+
+static __inline Word40 L40_round( Word40 L40_var1);
+static __inline Word16 round40( Word40 L40_var1);
+
+
+Word40 L40_add( Word40 L40_var1, Word40 L40_var2);
+Word40 L40_sub( Word40 L40_var1, Word40 L40_var2);
+Word40 L40_abs( Word40 L40_var1);
+Word40 L40_negate( Word40 L40_var1);
+Word40 L40_max( Word40 L40_var1, Word40 L40_var2);
+Word40 L40_min( Word40 L40_var1, Word40 L40_var2);
+Word32 L_saturate40( Word40 L40_var1);
+Word16 norm_L40( Word40 L40_var1);
+
+
+
+/*#ifdef _MSC_VER*/
+static __inline Word40 L40_set( Word40 L40_var1)
+{
+ Word40 L40_var_out;
+
+#if defined(_MSC_VER) && (_MSC_VER <= 1200)
+ L40_var_out = L40_var1 & 0x000000ffffffffff;
+
+ if( L40_var1 & 0x8000000000)
+ L40_var_out = L40_var_out | 0xffffff0000000000;
+#else
+ L40_var_out = L40_var1 & 0x000000ffffffffffLL;
+
+ if( L40_var1 & 0x8000000000LL)
+ L40_var_out = L40_var_out | 0xffffff0000000000LL;
+#endif
+
+
+ return( L40_var_out);
+}
+/*#endif*/ /* ifdef _MSC_VER */
+
+
+
+static __inline UWord16 Extract40_H( Word40 L40_var1)
+{
+ UWord16 var_out;
+
+ var_out = ( UWord16)( L40_var1 >> 16);
+
+
+ return( var_out);
+}
+
+
+static __inline UWord16 Extract40_L( Word40 L40_var1)
+{
+ UWord16 var_out;
+
+ var_out = ( UWord16)( L40_var1);
+
+
+ return( var_out);
+}
+
+
+static __inline UWord32 L_Extract40( Word40 L40_var1)
+{
+ UWord32 L_var_out;
+
+ L_var_out = ( UWord32) L40_var1;
+
+
+ return(L_var_out);
+}
+
+
+static __inline Word40 L40_deposit_h( Word16 var1)
+{
+ Word40 L40_var_out;
+
+ L40_var_out = (( Word40) var1) << 16;
+
+#if defined(_MSC_VER) && (_MSC_VER <= 1200)
+ if( var1 & 0x8000)
+ {
+ L40_var_out = L40_set( L40_var_out | 0xff00000000);
+#else
+ if( var1 & 0x8000)
+ {
+ L40_var_out = L40_set( L40_var_out | 0xff00000000LL);
+#endif
+ }
+
+
+ return( L40_var_out);
+}
+
+
+static __inline Word40 L40_deposit_l( Word16 var1)
+{
+ Word40 L40_var_out;
+
+ L40_var_out = var1;
+
+#if defined(_MSC_VER) && (_MSC_VER <= 1200)
+ if( var1 & 0x8000)
+ {
+ L40_var_out = L40_set( L40_var_out | 0xffffff0000);
+#else
+ if( var1 & 0x8000)
+ {
+ L40_var_out = L40_set( L40_var_out | 0xffffff0000LL);
+#endif
+ }
+
+
+ return( L40_var_out);
+}
+
+
+static __inline Word40 L40_deposit32( Word32 L_var1)
+{
+ Word40 L40_var_out;
+
+ L40_var_out = ( Word40) L_var1;
+
+#if defined(_MSC_VER) && (_MSC_VER <= 1200)
+ if( L_var1 & 0x80000000)
+ {
+ L40_var_out = L40_set( L40_var_out | 0xff00000000);
+#else
+ if( L_var1 & 0x80000000)
+ {
+ L40_var_out = L40_set( L40_var_out | 0xff00000000LL);
+#endif
+ }
+
+
+ return( L40_var_out);
+}
+
+
+
+
+
+
+
+
+static __inline Word40 L40_round( Word40 L40_var1)
+{
+ Word40 L40_var_out;
+ Word40 L40_constant;
+
+#if defined(_MSC_VER) && (_MSC_VER <= 1200)
+ L40_constant = L40_set( 0xffffff0000);
+#else
+ L40_constant = L40_set( 0xffffff0000LL);
+#endif
+
+ L40_var_out = L40_add( 0x8000, L40_var1);
+ L40_var_out = L40_var_out & L40_constant;
+
+
+ return( L40_var_out);
+}
+
+
+static __inline Word16 round40( Word40 L40_var1)
+{
+ Word16 var_out;
+
+ var_out = extract_h( L_saturate40( L40_round( L40_var1)));
+
+
+ return( var_out);
+}
+
+
+static __inline Word40 L40_mult( Word16 var1, Word16 var2)
+{
+ Word32 L_var_out;
+ Word40 L40_var_out;
+
+ L_var_out = ( Word32) var1 * ( Word32) var2;
+ L40_var_out = ( Word40) L_var_out;
+
+ /* Below line can not overflow, so we can use << instead of L40_shl. */
+ L40_var_out = L40_var_out << 1;
+
+
+ return( L40_var_out);
+}
+
+
+
+
+
+
+
+
+
+
+
+
+static __inline Word40 L40_mac( Word40 L40_var1, Word16 var2, Word16 var3)
+{
+ Word40 L40_var_out;
+
+ L40_var_out = L40_mult( var2, var3);
+ L40_var_out = L40_add( L40_var1, L40_var_out);
+
+
+ return( L40_var_out);
+}
+
+
+
+
+
+
+static __inline Word16 mac_r40( Word40 L40_var1, Word16 var2, Word16 var3)
+{
+ Word40 L40_var_out;
+ Word16 var_out;
+
+ L40_var_out = L40_mac( L40_var1, var2, var3);
+ var_out = round40( L40_var_out);
+
+
+ return( var_out);
+}
+
+
+
+
+
+
+static __inline Word40 L40_msu( Word40 L40_var1, Word16 var2, Word16 var3)
+{
+ Word40 L40_var_out;
+
+ L40_var_out = L40_mult( var2, var3);
+ L40_var_out = L40_sub( L40_var1, L40_var_out);
+
+
+ return( L40_var_out);
+}
+
+
+
+
+
+
+static __inline Word16 msu_r40( Word40 L40_var1, Word16 var2, Word16 var3)
+{
+ Word40 L40_var_out;
+ Word16 var_out;
+
+ L40_var_out = L40_msu( L40_var1, var2, var3);
+ var_out = round40( L40_var_out);
+
+
+ return( var_out);
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#endif /*_ENH40_H*/
+
+
+/* end of file */
+
+
diff --git a/lib_com/__zaloha/move.h b/lib_com/__zaloha/move.h
new file mode 100644
index 0000000000000000000000000000000000000000..d9d2040f14a298a73acdc40bf36a922622819d92
--- /dev/null
+++ b/lib_com/__zaloha/move.h
@@ -0,0 +1,42 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#ifndef _MOVE_H
+#define _MOVE_H
+
+/* BASOP -> FLC brigde: data move counting */
+
+#include "stl.h"
+
+static __inline void move16( void)
+{
+}
+
+static __inline void move32( void)
+{
+}
+
+static __inline void test( void)
+{
+}
+
+static __inline void logic16( void)
+{
+}
+
+static __inline void logic32( void)
+{
+}
+
+
+/*-------- legacy ----------*/
+#define data_move() move16()
+#define L_data_move() move32()
+#define data_move_external() move16()
+#define compare_zero() test()
+/*-------- end legacy ----------*/
+
+#define cast16 move16
+
+#endif /* _MOVE_H */
diff --git a/lib_com/__zaloha/stl.h b/lib_com/__zaloha/stl.h
new file mode 100644
index 0000000000000000000000000000000000000000..4b66f442e7c79f2712bff6b56ac9a36dabddb144
--- /dev/null
+++ b/lib_com/__zaloha/stl.h
@@ -0,0 +1,38 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+/*
+ ===========================================================================
+ File: STL.H v.2.3 - 30.Nov.2009
+ ===========================================================================
+
+ ITU-T STL BASIC OPERATORS
+
+ MAIN HEADER FILE
+
+ History:
+ 07 Nov 04 v2.0 Incorporation of new 32-bit / 40-bit / control
+ operators for the ITU-T Standard Tool Library as
+ described in Geneva, 20-30 January 2004 WP 3/16 Q10/16
+ TD 11 document and subsequent discussions on the
+ wp3audio@yahoogroups.com email reflector.
+ March 06 v2.1 Changed to improve portability.
+
+ ============================================================================
+*/
+
+
+#ifndef _STL_H
+#define _STL_H
+
+#include "typedef.h"
+#include "basop32.h"
+#include "move.h"
+#include "control.h"
+#include "enh1632.h"
+#include "enh40.h"
+
+#endif /* ifndef _STL_H */
+
+
+/* end of file */
diff --git a/lib_com/ari.c b/lib_com/ari.c
new file mode 100644
index 0000000000000000000000000000000000000000..af9ea44d4e90cda5aac36f9cf2fc8f26884dc322
--- /dev/null
+++ b/lib_com/ari.c
@@ -0,0 +1,41 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include
+#include "wmc_auto.h"
+#include
+#include "cnst.h"
+#include "prot.h"
+#include "stat_com.h"
+#include "assert.h"
+#include "basop_util.h"
+
+#ifndef int32
+#define int32 int
+#endif
+
+#define WMC_TOOL_SKIP
+
+
+/*---------------------------------------------------------------
+ Ari 14 bits common routines
+ -------------------------------------------------------------*/
+
+/**
+ * \brief Integer Multiply
+ *
+ * \param[i] r
+ * \param[i] c
+ *
+ * \return r*c
+ */
+long mul_sbc_14bits(long r,long c)
+{
+ long temp;
+ /*function in line*/
+ temp = (((int32) r)*((int32) c))>>stat_bitsnew;
+ return temp;
+
+ /*function in line*/
+}
diff --git a/lib_com/ari_hm.c b/lib_com/ari_hm.c
new file mode 100644
index 0000000000000000000000000000000000000000..961a0f923d8969a73d1dbfeed99a371c80cf1c66
--- /dev/null
+++ b/lib_com/ari_hm.c
@@ -0,0 +1,277 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include
+#include
+#include "cnst.h"
+#include "stl.h"
+#include "basop_util.h"
+#include "prot.h"
+#include "rom_com.h"
+#include "options.h"
+#include "wmc_auto.h"
+
+
+/*-------------------------------------------------------------------*
+ * UnmapIndex()
+ *
+ *
+ *-------------------------------------------------------------------*/
+
+void UnmapIndex(
+ int PeriodicityIndex,
+ int Bandwidth,
+ short LtpPitchLag,
+ int SmallerLags,
+ int *FractionalResolution,
+ int *Lag)
+{
+ if ((LtpPitchLag > 0) && (PeriodicityIndex & kLtpHmFlag))
+ {
+ int LtpPitchIndex, Multiplier;
+ LtpPitchIndex = PeriodicityIndex >> 9;
+ Multiplier = PeriodicityIndex & 0xff;
+ assert(0 <= LtpPitchIndex && LtpPitchIndex <= 16);
+ assert(1 <= Multiplier && Multiplier <= (1 << NumRatioBits[Bandwidth][LtpPitchIndex]));
+ *FractionalResolution = kLtpHmFractionalResolution;
+ *Lag = (LtpPitchLag * (int)(4 * Ratios[Bandwidth][LtpPitchIndex][Multiplier-1])) >> 2;
+ }
+ else
+ {
+ if (PeriodicityIndex < 16)
+ {
+ *FractionalResolution = 3;
+ *Lag = PeriodicityIndex + GET_ADJ(0, 6);
+ }
+ else if (PeriodicityIndex < 80)
+ {
+ *FractionalResolution = 4;
+ *Lag = PeriodicityIndex + GET_ADJ(16, 8);
+ }
+ else if (PeriodicityIndex < 208)
+ {
+ *FractionalResolution = 3;
+ *Lag = PeriodicityIndex + GET_ADJ(80, 12);
+ }
+ else if (PeriodicityIndex < 224 || SmallerLags)
+ {
+ *FractionalResolution = 1;
+ *Lag = PeriodicityIndex + GET_ADJ(208, 28);
+ }
+ else
+ {
+ *FractionalResolution = 0;
+ *Lag = PeriodicityIndex + GET_ADJ(224, 188);
+ }
+ }
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------*
+ * ConfigureContextHm()
+ *
+ *
+ *-------------------------------------------------------------------*/
+
+void ConfigureContextHm(
+ int NumCoeffs, /* (I) Number of coefficients */
+ int TargetBits, /* (I) Target bit budget (excl. Done flag) */
+ int PeriodicityIndex, /* (I) Pitch related index */
+ short LtpPitchLag, /* (I) TCX-LTP pitch in F.D. */
+ CONTEXT_HM_CONFIG *hm_cfg /* (O) Context-based harmonic model configuration */
+)
+{
+ int Bandwidth, SmallerLags;
+ int i, Limit, Lag;
+ int j, Index, FractionalResolution;
+ int *tmp;
+
+ Bandwidth = 0;
+ if (NumCoeffs >= 256)
+ {
+ Bandwidth = 1;
+ }
+
+ SmallerLags = 0;
+
+ if (TargetBits <= kSmallerLagsTargetBitsThreshold || Bandwidth == 0)
+ {
+ SmallerLags = 1;
+ }
+
+ UnmapIndex(PeriodicityIndex, Bandwidth, LtpPitchLag, SmallerLags, &FractionalResolution, &Lag );
+
+ /* Set up and fill peakIndices */
+ hm_cfg->peakIndices = hm_cfg->indexBuffer;
+ tmp = hm_cfg->peakIndices;
+ Limit = (NumCoeffs - 1) << FractionalResolution;
+
+ for (i=Lag; i> FractionalResolution;
+ *tmp++ = Index - 1;
+ *tmp++ = Index;
+ *tmp++ = Index + 1;
+ }
+ hm_cfg->numPeakIndices = tmp - hm_cfg->indexBuffer;
+
+ /* Set up and fill holeIndices */
+ hm_cfg->holeIndices = hm_cfg->indexBuffer + hm_cfg->numPeakIndices;
+ tmp = hm_cfg->holeIndices;
+ Index = 0;
+
+ for (j=0; jnumPeakIndices; j+=3)
+ {
+ for (; IndexpeakIndices[j]; ++Index)
+ {
+ *tmp++ = Index;
+ }
+ Index += 3; /* Skip the peak */
+ }
+
+ for (; IndexnumHoleIndices = tmp - hm_cfg->holeIndices;
+ /* Add extremal element signaling the end of the buffer */
+ *tmp++ = NumCoeffs;
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------*
+ * CountIndexBits()
+ *
+ *
+ *-------------------------------------------------------------------*/
+
+int CountIndexBits(
+ int Bandwidth,
+ int PeriodicityIndex)
+{
+
+ if (PeriodicityIndex & kLtpHmFlag)
+ {
+ int LtpPitchIndex = PeriodicityIndex >> 9;
+ return NumRatioBits[Bandwidth][LtpPitchIndex];
+ }
+ return 8;
+}
+
+#define WMC_TOOL_SKIP
+
+#ifndef ANALYSIS_TOOL
+/*-------------------------------------------------------------------*
+ * tcx_hm_render()
+ *
+ *
+ *-------------------------------------------------------------------*/
+
+int tcx_hm_render(
+ int lag, /* i: pitch lag */
+ int fract_res, /* i: fractional resolution of the lag */
+ float LtpGain, /* i: LTP gain */
+ Word16 p[] /* o: harmonic model (Q13) */
+)
+{
+ int k;
+ Word32 f0, tmp32;
+ Word16 height, PeakDeviation, tmp;
+
+ /* Set up overall shape */
+ (void)LtpGain;
+
+ f0 = L_shl(lag, sub(15, fract_res)); /* Q15 */
+
+ tmp32 = Mpy_32_16(f0, -26474);
+ tmp32 = L_shr_r(BASOP_Util_InvLog2(L_shl(tmp32, 7)), 2);
+ tmp32 = L_sub(603979776L, tmp32);
+ tmp32 = L_add(L_add(tmp32, tmp32), Mpy_32_16(tmp32, 26214));
+ height = round_fx(tmp32); /* Q13 */
+
+ tmp32 = Mpy_32_16(f0, -18910);
+ tmp32 = L_shr_r(BASOP_Util_InvLog2(L_shl(tmp32, 7)), 2);
+ tmp32 = L_sub(1395864371L, tmp32);
+ PeakDeviation = round_fx(tmp32); /* Q14 */
+
+ IF( sub(13915,PeakDeviation) > 0 )
+ {
+ /* A bit error was encountered */
+ return 1;
+ }
+ ELSE
+ {
+ tmp = div_s(13915, PeakDeviation);
+ tmp = mult_r(tmp, tmp); /* Q15 */
+ }
+
+ /* Render the prototype peak */
+ p[kTcxHmParabolaHalfWidth] = height;
+
+ for (k=1; k<=kTcxHmParabolaHalfWidth; ++k)
+ {
+ p[kTcxHmParabolaHalfWidth+k] = round_fx(Mpy_32_16(BASOP_Util_InvLog2(L_shl(L_mult0(mult0(negate(k),k), tmp),10)), height));
+ }
+ /* Mirror */
+ for (k=-kTcxHmParabolaHalfWidth; k<0; ++k)
+ {
+ p[kTcxHmParabolaHalfWidth+k] = p[kTcxHmParabolaHalfWidth-k];
+ }
+
+ return 0;
+}
+
+
+/*-------------------------------------------------------------------*
+ * tcx_hm_modify_envelope()
+ *
+ *
+ *-------------------------------------------------------------------*/
+
+void tcx_hm_modify_envelope(
+ Word16 gain, /* i: HM gain (Q11) */
+ int lag,
+ int fract_res,
+ Word16 p[], /* i: harmonic model (Q13) */
+ Word32 env[], /* i/o: envelope (Q16) */
+ int L_frame /* i: number of spectral lines */
+)
+{
+ int k;
+ int h, x;
+ Word16 inv_shape[2*kTcxHmParabolaHalfWidth+1]; /* Q15 */
+
+ if (gain == 0)
+ {
+ return;
+ }
+
+ for (k=0; k<2*kTcxHmParabolaHalfWidth+1; ++k)
+ {
+ inv_shape[k] = div_s(512, add(512, round_fx(L_mult(gain, p[k]))));
+ }
+
+ h = 1;
+ k = lag >> fract_res;
+
+ while (k <= L_frame + kTcxHmParabolaHalfWidth - 1)
+ {
+
+ for (x=max(0, k-kTcxHmParabolaHalfWidth); x<=min(k+kTcxHmParabolaHalfWidth, L_frame-1); ++x)
+ {
+ env[x] = Mpy_32_16(env[x], inv_shape[x-k+kTcxHmParabolaHalfWidth]);
+ }
+ ++h;
+ k = (h * lag) >> fract_res;
+ }
+
+ return;
+}
+#endif /* ANALYSIS_TOOL */
+
+#undef WMC_TOOL_SKIP
diff --git a/lib_com/arith_coder.c b/lib_com/arith_coder.c
new file mode 100644
index 0000000000000000000000000000000000000000..684d20b4b35a6309968d77b3484fdc92aafdfcd9
--- /dev/null
+++ b/lib_com/arith_coder.c
@@ -0,0 +1,512 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include
+#include "wmc_auto.h"
+#include
+#include "options.h"
+#include "cnst.h"
+#include "prot.h"
+#include "basop_util.h"
+#include "basop_proto_func.h"
+
+
+#define WMC_TOOL_SKIP
+
+
+/*-------------------------------------------------------*
+ * expfp()
+ *
+ * Fixed point implementation of exp()
+ *-------------------------------------------------------*/
+
+Word16 expfp( /* o: Q15 */
+ Word16 x, /* i: mantissa Q15-e */
+ Word16 x_e) /* i: exponent Q0 */
+{
+ Word16 xi, xf, tmp;
+ Word16 b0, b1, b2, b3;
+ Word32 y, L_tmp;
+
+ assert(x <= 0);
+
+ L_tmp = L_negate(L_shl(L_deposit_h(x), sub(x_e, 15)));
+
+ /* split into integer and fractional parts */
+ xi = round_fx(L_tmp);
+ xf = extract_l(L_tmp);
+
+ BASOP_SATURATE_WARNING_OFF;
+ xf = negate(xf);
+ BASOP_SATURATE_WARNING_ON;
+
+ /* Fractional part */
+ /* y = 65536
+ + xf
+ + ((xf*xf) / (2*65536))
+ + ((((((xf*xf) / (2*65536))*xf) / 65536)*65536/3) / 65536)
+ + ((((((((xf*xf) / (2*65536))*xf) / 65536)*65536/3) / 65536)*xf) / (4*65536)); */
+ y = L_mac0(65536, xf, 1);
+ tmp = shr(mult(xf, xf), 2);
+ y = L_mac0(y, tmp, 1);
+ tmp = shr(mult(shr(mult(tmp, xf), 1), 65536/3), 1);
+ y = L_mac0(y, tmp, 1);
+ tmp = shr(mult(tmp, xf), 3);
+ y = L_mac0(y, tmp, 1);
+
+ /* Integer part */
+ b0 = s_and(xi, 1);
+ b1 = s_and(xi, 2);
+ b2 = s_and(xi, 4);
+ b3 = s_and(xi, 8);
+
+ if (b0 != 0) y = Mpy_32_16(y, 24109); /* exp(-1) in -1Q16 */
+ if (b1 != 0) y = Mpy_32_16(y, 17739); /* exp(-2) in -2Q17 */
+ if (b2 != 0) y = Mpy_32_16(y, 19205); /* exp(-4) in -5Q20 */
+ if (b3 != 0) y = Mpy_32_16(y, 22513); /* exp(-8) in -11Q26 */
+
+ /* scaling: -1*b0 - 2*b1 -5*b2 -11*b3 */
+ y = L_shr(y, add(add(xi, shr(xi, 2)), shr(b3, 3)));
+
+ /* zero for xi >= 16 */
+ if (shr(xi, 4) > 0)
+ {
+ y = L_deposit_l(0);
+ move16();
+ }
+
+ return round_fx(L_shl(y, 15));
+}
+
+
+/*-------------------------------------------------------*
+ * powfp_odd2()
+ *
+ * Fixed point implementation of pow(), where base is fixed point (16/16) and exponent a small *odd* integer
+ *-------------------------------------------------------*/
+/*
+ *
+ * Returns: *pout1 = ( (base/65536)^(2*exp - 1) ) * 65536
+ * *pout2 = ( (base/65536)^(2*exp + 1) ) * 65536
+ *
+ * NOTE: This function must be in sync with ari_decode_14bits_pow() */
+
+void powfp_odd2(
+ Word16 base, /* Q15 */
+ Word16 exp, /* Q0 */
+ Word16 *pout1, /* Q15 */
+ Word16 *pout2 /* Q15 */
+)
+{
+ /* this version is in sync with ari_enc_14bits_pow()
+ * that is, we have to start multiplication from the largest power-of-two, in order to
+ * get the rounding errors to appear at the same places */
+ Word16 pows[12]; /* powers of two exponents*/
+ Word16 exp2;
+ Word16 out, out2;
+ Word16 k, h, maxk;
+
+ assert(exp >= 0);
+
+ out = base;
+ move16();
+ out2 = 0x7FFF;
+ move16();
+ IF (exp != 0)
+ {
+ exp2 = sub(exp, 1);
+ maxk = sub(15, norm_s(exp));
+ assert(maxk < 12);
+
+ pows[0] = base;
+ move16();
+ FOR (k = 0; k < maxk; k++)
+ {
+ pows[k+1] = mult_r(pows[k], pows[k]);
+ move16();
+ }
+ k = sub(k, 1);
+ h = shl(1, k); /* highest bit of exp2 */
+ out2 = base;
+ move16();
+ out = mult_r(out, pows[k+1]); /* we already know that "exp" has the highest bit set to one since we calculated .. */
+ /* .. the effective length of "exp" earlier on, thus we omit the branch for out2 */
+ if (s_and(exp2, h) != 0)
+ {
+ out2 = mult_r(out2, pows[k+1]);
+ }
+
+ h = shr(h, 1);
+ FOR (k = sub(k, 1); k >= 0; k--)
+ {
+ if (s_and(exp, h) != 0)
+ {
+ out = mult_r(out, pows[k+1]);
+ }
+
+ if (s_and(exp2, h) != 0)
+ {
+ out2 = mult_r(out2, pows[k+1]);
+ }
+
+ h = shr(h, 1);
+ }
+ }
+
+ *pout1 = out2;
+ move16();
+ *pout2 = out;
+ move16();
+
+ return;
+}
+
+
+/*------------------------------------------------------------------------
+ * Function: tcx_arith_scale_envelope
+ *
+ * For optimal performance of the arithmetic coder, the envelope shape must
+ * be scaled such that the expected bit-consumption of a signal that
+ * follows the scaled shape coincides with the target bitrate.
+ * This function calculates a first-guess scaling and then uses the bi-section
+ * search to find the optimal scaling.
+ *
+ * We assume that lines follow the Laplacian distribution, whereby the expected
+ * bit-consumption would be log2(2*e*s[k]), where s[k] is the envelope value
+ * for the line in question. However, this theoretical formula assumes that
+ * all lines are encoded with magnitude+sign. Since the sign is unnecessary
+ * for 0-values, that estimate of bit-consumption is biased when s[k] is small.
+ * Analytical solution of the expectation for small s[k] is difficult, whereby
+ * we use the approximation log2(2*e*s[k] + 0.15 + 0.035 / s[k]) which is accurate
+ * on the range 0.08 to 1.0.
+ *
+ * NOTE: This function must be bit-exact on all platforms such that encoder
+ * and decoder remain synchronized.
+ *-------------------------------------------------------------------------*/
+
+void tcx_arith_scale_envelope(
+ Word16 L_spec_core, /* i: number of lines to scale Q0 */
+ Word16 L_frame, /* i: number of lines Q0 */
+ Word32 env[], /* i: unscaled envelope Q16 */
+ Word16 target_bits, /* i: number of available bits Q0 */
+ Word16 low_complexity, /* i: low-complexity Q0 */
+ Word16 s_env[], /* o: scaled envelope Q15-e */
+ Word16 *s_env_e /* o: scaled envelope exponent Q0 */
+)
+{
+ Word32 ienv[N_MAX_ARI];
+ Word16 scale, iscale, iscale_e, a_e, b, b_e;
+ Word16 lob, hib, adjust;
+ Word16 k, iter, max_iter, lob_bits, hib_bits;
+ Word16 statesi, bits;
+ Word32 mean, a, s, L_tmp;
+ Word16 mean_e, tmp, tmp2;
+
+
+ lob_bits = 0;
+ move16();
+ hib_bits = 0;
+ move16();
+
+ /* Boosting to account for expected spectrum truncation (kMax) */
+ /* target_bits = (int)(target_bits * (1.2f - 0.00045f * target_bits + 0.00000025f * target_bits * target_bits)); */
+ L_tmp = L_shr(Mpy_32_16(L_mult0(target_bits, target_bits), 17180), 6); /* Q15; 17180 -> 0.00000025f (Q36) */
+ L_tmp = L_sub(L_tmp, L_shr(L_mult0(target_bits, 30199), 11)); /* Q15; 30199 -> 0.00045f (Q26) */
+ L_tmp = L_add(L_tmp, 39322); /* Q15; 39322 -> 1.2f (Q15) */
+ L_tmp = Mpy_32_16(L_tmp, target_bits); /* Q0 */
+ assert(L_tmp < 32768);
+ target_bits = extract_l(L_tmp);
+
+ /* Calculate inverse envelope and find initial scale guess based on mean */
+ mean = L_deposit_l(0);
+ FOR (k = 0; k < L_frame; k++)
+ {
+ /* ienv[k] = 1.0f / env[k];
+ mean += ienv[k]; */
+
+ tmp = norm_l(env[k]);
+ tmp2 = sub(15, tmp);
+ tmp = Inv16(round_fx(L_shl(env[k], tmp)), &tmp2);
+ ienv[k] = L_shl(L_deposit_h(tmp), sub(tmp2, 15)); /* Q16 */ move32();
+ mean = L_add(mean, ienv[k]);
+ }
+ tmp = norm_s(L_frame);
+ tmp = shl(div_s(8192, shl(L_frame, tmp)), sub(tmp, 7));
+ mean = L_shr(Mpy_32_16(mean, tmp), 6); /* Q16 */
+
+ /* Rate dependent compensation to get closer to the target on average */
+ /* mean = (float)pow(mean, (float)L_frame / (float)target_bits * 0.357f); */
+ tmp = BASOP_Util_Divide1616_Scale(L_frame, target_bits, &tmp2);
+ tmp = mult_r(tmp, FL2WORD16(0.357f));
+ mean = BASOP_Util_fPow(mean, 15, L_deposit_h(tmp), tmp2, &mean_e);
+
+ /* Find first-guess scaling coefficient "scale" such that if "mean" is the
+ * mean of the envelope, then the mean bit-consumption is approximately
+ *
+ * log2(2*e*mean*scale + 0.15 + 0.035/(mean*scale)) * L_frame = target_bits
+ */
+ /* a = 2*2.71828183f*mean*mean; */
+ tmp = round_fx(mean);
+ a = L_mult(mult_r(tmp, FL2WORD16_SCALE(2.71828183f, 2)), tmp);
+ a_e = add(shl(mean_e, 1), 3);
+
+ /* b = (0.15f - (float)pow(2.0f, target_bits/(float)L_frame)) * mean; */
+ tmp = BASOP_Util_Divide1616_Scale(target_bits, L_frame, &tmp2);
+ tmp = round_fx(BASOP_util_Pow2(L_deposit_h(tmp), tmp2, &tmp2));
+ b_e = BASOP_Util_Add_MantExp(FL2WORD16(0.15f), 0, negate(tmp), tmp2, &b);
+ b = mult_r(b, round_fx(mean));
+ b_e = add(b_e, mean_e);
+
+ /* scale = (-b + (float)sqrt(b*b - 4.0f*a*0.035f)) / (2.0f * a); */
+ tmp = round_fx(BASOP_Util_Add_Mant32Exp(L_mult(b, b), shl(b_e, 1), Mpy_32_16(a, FL2WORD16(-4.0f*0.035f)), a_e, &tmp2));
+
+ IF( tmp <= 0 )
+ {
+ tmp = 0;
+
+ FOR( k=0; k 255, bit consumption is approx log2(2*e*s)
+ * further, we use round(log2(x)) = floor(log2(x)+0.5) = floor(log2(x*sqrt(2))) */
+ /* a = 5.436564f * s; */
+ L_tmp = Mpy_32_16(s, FL2WORD16_SCALE(5.436564f * 1.4142f, 3)); /* Q13 */
+ bits = add(bits, sub(17, norm_l(L_tmp)));
+ }
+ }
+
+ IF (sub(bits, target_bits) <= 0)
+ {
+ /* Bits leftover => scale is too small */
+ lob = scale;
+ move16();
+ lob_bits = bits;
+ move16();
+
+ IF (hib > 0) /* Bisection search */
+ {
+ adjust = div_s(sub(hib_bits, target_bits), sub(hib_bits, lob_bits));
+ scale = add(mult_r(sub(lob, hib), adjust), hib);
+ }
+ ELSE
+ {
+ /* Initial scale adaptation */
+ /* adjust = 1.05f * target_bits / (float)bits;
+ scale *= adjust; */
+ adjust = mult_r(FL2WORD16_SCALE(1.05f, 1), target_bits);
+ adjust = BASOP_Util_Divide1616_Scale(adjust, bits, &tmp);
+ scale = shl(mult_r(scale, adjust), add(1, tmp));
+ }
+ }
+ ELSE
+ {
+ /* Ran out of bits => scale is too large */
+ hib = scale;
+ move16();
+ hib_bits = bits;
+ move16();
+
+ IF (lob > 0) /* Bisection search */
+ {
+ adjust = div_s(sub(hib_bits, target_bits), sub(hib_bits, lob_bits));
+ scale = add(mult_r(sub(lob, hib), adjust), hib);
+ }
+ ELSE
+ { /* Initial scale adaptation */
+ test();
+ IF( target_bits <= 0 || bits <= 0 ) /* safety check in case of bit errors */
+ {
+ adjust = 0;
+ move16();
+
+ FOR( k=0; k weighted envelope factor */
+ Word16 gamma_uw, /* i: A_ind -> non-weighted envelope factor */
+ Word32 env[] /* o: shaped signal envelope */
+)
+{
+ Word16 k;
+ Word16 tmpA[M+2];
+ Word16 signal_env[FDNS_NPTS], signal_env_e[FDNS_NPTS];
+ Word16 gainlpc[FDNS_NPTS], gainlpc_e[FDNS_NPTS];
+
+
+ /* Compute perceptual LPC envelope, transform it into freq.-domain gains */
+ basop_weight_a(A_ind, tmpA, gamma_w);
+ basop_lpc2mdct(tmpA, M, NULL, NULL, gainlpc, gainlpc_e);
+
+ /* Add pre-emphasis tilt to LPC envelope, transform LPC into MDCT gains */
+ basop_weight_a_inv(A_ind, signal_env, gamma_uw);
+ basop_E_LPC_a_add_tilt(signal_env, tmpA, preemph_fac);
+ basop_lpc2mdct(tmpA, M+1, signal_env, signal_env_e, NULL, NULL);
+
+ /* Compute weighted signal envelope in perceptual domain */
+ FOR (k = 0; k < FDNS_NPTS; k++)
+ {
+ signal_env[k] = mult_r(signal_env[k], gainlpc[k]);
+ move16();
+ signal_env_e[k] = add(signal_env_e[k], gainlpc_e[k]);
+ move16();
+ }
+
+ /* Adaptive low frequency emphasis */
+ FOR (k = 0; k < L_frame; k++)
+ {
+ env[k] = 0x10000;
+ move32();
+ }
+
+ basop_PsychAdaptLowFreqDeemph(env, gainlpc, gainlpc_e, NULL);
+
+ /* Scale from FDNS_NPTS to L_frame and multiply LFE gains */
+ basop_mdct_noiseShaping_interp(env, L_frame, signal_env, signal_env_e);
+
+ FOR (k=L_frame; k
+#include
+#include "stl.h"
+#ifdef BASOP_NOGLOB
+#include
+#endif /* BASOP_NOGLOB */
+
+#define WMC_TOOL_SKIP
+
+#ifdef _MSC_VER
+#pragma warning( disable : 4310 )
+#endif
+
+/*___________________________________________________________________________
+ | |
+ | Local Functions |
+ |___________________________________________________________________________|
+*/
+#ifdef BASOP_NOGLOB
+static Word16 saturate_o( Word32 L_var1, Flag *Overflow );
+#endif /* BASOP_NOGLOB */
+static Word16 saturate( Word32 L_var1 );
+
+
+/*___________________________________________________________________________
+ | |
+ | Constants and Globals |
+ |___________________________________________________________________________|
+*/
+#ifndef BASOP_NOGLOB
+Flag Overflow = 0;
+Flag Carry = 0;
+
+#else /* BASOP_NOGLOB */
+/*
+Flag BASOP_Overflow = 0;
+Flag BASOP_Carry = 0;
+*/
+#endif /* BASOP_NOGLOB */
+
+/*___________________________________________________________________________
+ | |
+ | Functions |
+ |___________________________________________________________________________|
+*/
+
+#define PRINT_STACK_ID_ALL "*"
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : saturate |
+ | |
+ | Purpose : |
+ | |
+ | Limit the 32 bit input to the range of a 16 bit word. Must NOT be |
+ | referenced from outside applications. |
+ | |
+ | Inputs : |
+ | |
+ | L_var1 |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var1 <= 0x7fff ffff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+#ifndef BASOP_NOGLOB
+static Word16 saturate( Word32 L_var1 )
+#else /* BASOP_NOGLOB */
+static Word16 saturate_o( Word32 L_var1, Flag *Overflow )
+#endif /* BASOP_NOGLOB */
+{
+ Word16 var_out;
+
+ if ( L_var1 > 0X00007fffL )
+ {
+#ifndef BASOP_NOGLOB
+ Overflow = 1;
+#else /* BASOP_NOGLOB */
+ *Overflow = 1;
+#endif /* BASOP_NOGLOB */
+ var_out = MAX_16;
+ }
+ else if ( L_var1 < (Word32) 0xffff8000L )
+ {
+#ifndef BASOP_NOGLOB
+ Overflow = 1;
+#else /* BASOP_NOGLOB */
+ *Overflow = 1;
+#endif /* BASOP_NOGLOB */
+ var_out = MIN_16;
+ }
+ else
+ {
+ var_out = extract_l( L_var1 );
+#ifdef WMOPS
+ multiCounter[currCounter].extract_l--;
+#endif
+ }
+
+ BASOP_CHECK();
+
+ return ( var_out );
+}
+
+#ifdef BASOP_NOGLOB
+static Word16 saturate( Word32 L_var1 )
+{
+ Word16 var_out;
+
+ if ( L_var1 > 0X00007fffL )
+ {
+ assert( 0 );
+ var_out = MAX_16;
+ }
+ else if ( L_var1 < (Word32) 0xffff8000L )
+ {
+ assert( 0 );
+ var_out = MIN_16;
+ }
+ else
+ {
+ var_out = extract_l( L_var1 );
+#ifdef WMOPS
+ multiCounter[currCounter].extract_l--;
+#endif
+ }
+
+ BASOP_CHECK();
+
+ return ( var_out );
+}
+#endif /* BASOP_NOGLOB */
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : add |
+ | |
+ | Purpose : |
+ | |
+ | Performs the addition (var1+var2) with overflow control and saturation;|
+ | the 16 bit result is set at +32767 when overflow occurs or at -32768 |
+ | when underflow occurs. |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+#ifdef BASOP_NOGLOB
+Word16 add_o( Word16 var1, Word16 var2, Flag *Overflow )
+{
+ Word16 var_out;
+ Word32 L_sum;
+
+ L_sum = (Word32) var1 + var2;
+ var_out = saturate_o( L_sum, Overflow );
+
+#ifdef WMOPS
+ multiCounter[currCounter].add++;
+#endif
+ return ( var_out );
+}
+
+#endif /* BASOP_NOGLOB */
+Word16 add( Word16 var1, Word16 var2 )
+{
+ Word16 var_out;
+ Word32 L_sum;
+
+ L_sum = (Word32) var1 + var2;
+ var_out = saturate( L_sum );
+
+#ifdef WMOPS
+ multiCounter[currCounter].add++;
+#endif
+ return ( var_out );
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : sub |
+ | |
+ | Purpose : |
+ | |
+ | Performs the subtraction (var1+var2) with overflow control and satu- |
+ | ration; the 16 bit result is set at +32767 when overflow occurs or at |
+ | -32768 when underflow occurs. |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+#ifdef BASOP_NOGLOB
+Word16 sub_o( Word16 var1, Word16 var2, Flag *Overflow )
+{
+ Word16 var_out;
+ Word32 L_diff;
+
+ L_diff = (Word32) var1 - var2;
+ var_out = saturate_o( L_diff, Overflow );
+
+#ifdef WMOPS
+ multiCounter[currCounter].sub++;
+#endif
+ return ( var_out );
+}
+
+#endif /* BASOP_NOGLOB */
+Word16 sub( Word16 var1, Word16 var2 )
+{
+ Word16 var_out;
+ Word32 L_diff;
+
+ L_diff = (Word32) var1 - var2;
+ var_out = saturate( L_diff );
+
+#ifdef WMOPS
+ multiCounter[currCounter].sub++;
+#endif
+ return ( var_out );
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : abs_s |
+ | |
+ | Purpose : |
+ | |
+ | Absolute value of var1; abs_s(-32768) = 32767. |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0x0000 0000 <= var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+Word16 abs_s( Word16 var1 )
+{
+ Word16 var_out;
+
+ if ( var1 == (Word16) MIN_16 )
+ {
+ var_out = MAX_16;
+ }
+ else
+ {
+ if ( var1 < 0 )
+ {
+ var_out = -var1;
+ }
+ else
+ {
+ var_out = var1;
+ }
+ }
+
+#ifdef WMOPS
+ multiCounter[currCounter].abs_s++;
+#endif
+ BASOP_CHECK();
+
+
+ return ( var_out );
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : shl |
+ | |
+ | Purpose : |
+ | |
+ | Arithmetically shift the 16 bit input var1 left var2 positions.Zero fill|
+ | the var2 LSB of the result. If var2 is negative, arithmetically shift |
+ | var1 right by -var2 with sign extension. Saturate the result in case of |
+ | underflows or overflows. |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+#ifndef BASOP_NOGLOB
+Word16 shl( Word16 var1, Word16 var2 )
+#else /* BASOP_NOGLOB */
+Word16 shl_o( Word16 var1, Word16 var2, Flag *Overflow )
+#endif /* BASOP_NOGLOB */
+{
+ Word16 var_out;
+ Word32 result;
+
+ if ( var2 < 0 )
+ {
+ if ( var2 < -16 )
+ var2 = -16;
+ var2 = -var2;
+ var_out = shr( var1, var2 );
+
+#ifdef WMOPS
+ multiCounter[currCounter].shr--;
+#endif
+ }
+ else
+ {
+ result = (Word32) var1 * ( (Word32) 1 << var2 );
+
+ if ( ( var2 > 15 && var1 != 0 ) || ( result != (Word32) ( (Word16) result ) ) )
+ {
+#ifndef BASOP_NOGLOB
+ Overflow = 1;
+#else /* BASOP_NOGLOB */
+ *Overflow = 1;
+#endif /* BASOP_NOGLOB */
+ var_out = ( var1 > 0 ) ? MAX_16 : MIN_16;
+ }
+ else
+ {
+ var_out = extract_l( result );
+
+#ifdef WMOPS
+ multiCounter[currCounter].extract_l--;
+#endif
+ }
+ }
+
+#ifdef WMOPS
+ multiCounter[currCounter].shl++;
+#endif
+
+ BASOP_CHECK();
+
+
+ return ( var_out );
+}
+
+#ifdef BASOP_NOGLOB
+Word16 shl( Word16 var1, Word16 var2 )
+{
+ Word16 var_out;
+ Word32 result;
+
+ if ( var2 < 0 )
+ {
+ if ( var2 < -16 )
+ var2 = -16;
+ var2 = -var2;
+ var_out = shr( var1, var2 );
+
+#ifdef WMOPS
+ multiCounter[currCounter].shr--;
+#endif
+ }
+ else
+ {
+ result = (Word32) var1 * ( (Word32) 1 << var2 );
+
+ if ( ( var2 > 15 && var1 != 0 ) || ( result != (Word32) ( (Word16) result ) ) )
+ {
+ assert( 0 );
+ var_out = ( var1 > 0 ) ? MAX_16 : MIN_16;
+ }
+ else
+ {
+ var_out = extract_l( result );
+
+#ifdef WMOPS
+ multiCounter[currCounter].extract_l--;
+#endif
+ }
+ }
+
+#ifdef WMOPS
+ multiCounter[currCounter].shl++;
+#endif
+ BASOP_CHECK();
+
+
+ return ( var_out );
+}
+#endif /* BASOP_NOGLOB */
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : shr |
+ | |
+ | Purpose : |
+ | |
+ | Arithmetically shift the 16 bit input var1 right var2 positions with |
+ | sign extension. If var2 is negative, arithmetically shift var1 left by |
+ | -var2 with sign extension. Saturate the result in case of underflows or |
+ | overflows. |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+Word16 shr( Word16 var1, Word16 var2 )
+{
+ Word16 var_out;
+
+ if ( var2 < 0 )
+ {
+#ifdef BASOP_NOGLOB
+ assert( 0 );
+#endif /* BASOP_NOGLOB */
+ if ( var2 < -16 )
+ var2 = -16;
+ var2 = -var2;
+ var_out = shl( var1, var2 );
+
+#ifdef WMOPS
+ multiCounter[currCounter].shl--;
+#endif
+ }
+ else
+ {
+ if ( var2 >= 15 )
+ {
+ var_out = ( var1 < 0 ) ? -1 : 0;
+ }
+ else
+ {
+ if ( var1 < 0 )
+ {
+ var_out = ~( ( ~var1 ) >> var2 );
+ }
+ else
+ {
+ var_out = var1 >> var2;
+ }
+ }
+ }
+
+#ifdef WMOPS
+ multiCounter[currCounter].shr++;
+#endif
+
+ BASOP_CHECK();
+
+
+ return ( var_out );
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : mult |
+ | |
+ | Purpose : |
+ | |
+ | Performs the multiplication of var1 by var2 and gives a 16 bit result |
+ | which is scaled i.e.: |
+ | mult(var1,var2) = extract_l(L_shr((var1 times var2),15)) and |
+ | mult(-32768,-32768) = 32767. |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+#ifdef BASOP_NOGLOB
+Word16 mult_o( Word16 var1, Word16 var2, Flag *Overflow )
+{
+ Word16 var_out;
+ Word32 L_product;
+
+ L_product = (Word32) var1 * (Word32) var2;
+
+ L_product = ( L_product & (Word32) 0xffff8000L ) >> 15;
+
+ if ( L_product & (Word32) 0x00010000L )
+ L_product = L_product | (Word32) 0xffff0000L;
+
+ var_out = saturate_o( L_product, Overflow );
+
+#ifdef WMOPS
+ multiCounter[currCounter].mult++;
+#endif
+
+ return ( var_out );
+}
+
+#endif /* BASOP_NOGLOB */
+Word16 mult( Word16 var1, Word16 var2 )
+{
+ Word16 var_out;
+ Word32 L_product;
+
+ L_product = (Word32) var1 * (Word32) var2;
+
+ L_product = ( L_product & (Word32) 0xffff8000L ) >> 15;
+
+ if ( L_product & (Word32) 0x00010000L )
+ L_product = L_product | (Word32) 0xffff0000L;
+
+ var_out = saturate( L_product );
+
+#ifdef WMOPS
+ multiCounter[currCounter].mult++;
+#endif
+ return ( var_out );
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_mult |
+ | |
+ | Purpose : |
+ | |
+ | L_mult is the 32 bit result of the multiplication of var1 times var2 |
+ | with one shift left i.e.: |
+ | L_mult(var1,var2) = L_shl((var1 times var2),1) and |
+ | L_mult(-32768,-32768) = 2147483647. |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. |
+ |___________________________________________________________________________|
+*/
+#ifndef BASOP_NOGLOB
+Word32 L_mult( Word16 var1, Word16 var2 )
+#else /* BASOP_NOGLOB */
+Word32 L_mult_o( Word16 var1, Word16 var2, Flag *Overflow )
+#endif /* BASOP_NOGLOB */
+{
+ Word32 L_var_out;
+
+ L_var_out = (Word32) var1 * (Word32) var2;
+
+ if ( L_var_out != (Word32) 0x40000000L )
+ {
+ L_var_out *= 2;
+ }
+ else
+ {
+#ifndef BASOP_NOGLOB
+ Overflow = 1;
+#else /* BASOP_NOGLOB */
+ *Overflow = 1;
+#endif /* BASOP_NOGLOB */
+ L_var_out = MAX_32;
+ }
+
+#ifdef WMOPS
+ multiCounter[currCounter].L_mult++;
+#endif
+
+ BASOP_CHECK();
+
+ return ( L_var_out );
+}
+
+#ifdef BASOP_NOGLOB
+Word32 L_mult( Word16 var1, Word16 var2 )
+{
+ Word32 L_var_out;
+
+ L_var_out = (Word32) var1 * (Word32) var2;
+
+ if ( L_var_out != (Word32) 0x40000000L )
+ {
+ L_var_out *= 2;
+ }
+ else
+ {
+ assert( 0 );
+ L_var_out = MAX_32;
+ }
+
+#ifdef WMOPS
+ multiCounter[currCounter].L_mult++;
+#endif
+
+ BASOP_CHECK();
+
+ return ( L_var_out );
+}
+#endif /* BASOP_NOGLOB */
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : negate |
+ | |
+ | Purpose : |
+ | |
+ | Negate var1 with saturation, saturate in the case where input is -32768:|
+ | negate(var1) = sub(0,var1). |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+Word16 negate( Word16 var1 )
+{
+ Word16 var_out;
+
+ var_out = ( var1 == MIN_16 ) ? MAX_16 : -var1;
+
+
+#ifdef WMOPS
+ multiCounter[currCounter].negate++;
+#endif
+
+ BASOP_CHECK();
+
+
+ return ( var_out );
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : extract_h |
+ | |
+ | Purpose : |
+ | |
+ | Return the 16 MSB of L_var1. |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | L_var1 |
+ | 32 bit long signed integer (Word32 ) whose value falls in the |
+ | range : 0x8000 0000 <= L_var1 <= 0x7fff ffff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+Word16 extract_h( Word32 L_var1 )
+{
+ Word16 var_out;
+
+ var_out = (Word16) ( L_var1 >> 16 );
+
+#ifdef WMOPS
+ multiCounter[currCounter].extract_h++;
+#endif
+
+ BASOP_CHECK();
+
+
+ return ( var_out );
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : extract_l |
+ | |
+ | Purpose : |
+ | |
+ | Return the 16 LSB of L_var1. |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | L_var1 |
+ | 32 bit long signed integer (Word32 ) whose value falls in the |
+ | range : 0x8000 0000 <= L_var1 <= 0x7fff ffff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+Word16 extract_l( Word32 L_var1 )
+{
+ Word16 var_out;
+
+ var_out = (Word16) L_var1;
+
+#ifdef WMOPS
+ multiCounter[currCounter].extract_l++;
+#endif
+
+ BASOP_CHECK();
+
+
+ return ( var_out );
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : round_fx |
+ | |
+ | Purpose : |
+ | |
+ | Round the lower 16 bits of the 32 bit input number into the MS 16 bits |
+ | with saturation. Shift the resulting bits right by 16 and return the 16 |
+ | bit number: |
+ | round_fx(L_var1) = extract_h(L_add(L_var1,32768)) |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | L_var1 |
+ | 32 bit long signed integer (Word32 ) whose value falls in the |
+ | range : 0x8000 0000 <= L_var1 <= 0x7fff ffff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+#ifdef BASOP_NOGLOB
+Word16 round_fx_o( Word32 L_var1, Flag *Overflow )
+{
+ Word16 var_out;
+ Word32 L_rounded;
+
+ BASOP_SATURATE_WARNING_OFF
+ L_rounded = L_add_o( L_var1, (Word32) 0x00008000L, Overflow );
+ BASOP_SATURATE_WARNING_ON
+ var_out = extract_h( L_rounded );
+
+#ifdef WMOPS
+ multiCounter[currCounter].L_add--;
+ multiCounter[currCounter].extract_h--;
+ multiCounter[currCounter].round++;
+#endif
+
+ BASOP_CHECK();
+
+ return ( var_out );
+}
+
+#endif /* BASOP_NOGLOB */
+Word16 round_fx( Word32 L_var1 )
+{
+ Word16 var_out;
+ Word32 L_rounded;
+
+ BASOP_SATURATE_WARNING_OFF
+ L_rounded = L_add( L_var1, (Word32) 0x00008000L );
+ BASOP_SATURATE_WARNING_ON
+ var_out = extract_h( L_rounded );
+
+#ifdef WMOPS
+ multiCounter[currCounter].L_add--;
+ multiCounter[currCounter].extract_h--;
+ multiCounter[currCounter].round++;
+#endif
+ BASOP_CHECK();
+
+ return ( var_out );
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_mac |
+ | |
+ | Purpose : |
+ | |
+ | Multiply var1 by var2 and shift the result left by 1. Add the 32 bit |
+ | result to L_var3 with saturation, return a 32 bit result: |
+ | L_mac(L_var3,var1,var2) = L_add(L_var3,L_mult(var1,var2)). |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | L_var3 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. |
+ |___________________________________________________________________________|
+*/
+#ifdef BASOP_NOGLOB
+Word32 L_mac_o( Word32 L_var3, Word16 var1, Word16 var2, Flag *Overflow )
+{
+ Word32 L_var_out;
+ Word32 L_product;
+
+ L_product = L_mult_o( var1, var2, Overflow );
+ L_var_out = L_add_o( L_var3, L_product, Overflow );
+
+#ifdef WMOPS
+ multiCounter[currCounter].L_mult--;
+ multiCounter[currCounter].L_add--;
+ multiCounter[currCounter].L_mac++;
+#endif
+
+ return ( L_var_out );
+}
+
+#endif /* BASOP_NOGLOB */
+Word32 L_mac( Word32 L_var3, Word16 var1, Word16 var2 )
+{
+ Word32 L_var_out;
+ Word32 L_product;
+
+ L_product = L_mult( var1, var2 );
+ L_var_out = L_add( L_var3, L_product );
+
+#ifdef WMOPS
+ multiCounter[currCounter].L_mult--;
+ multiCounter[currCounter].L_add--;
+ multiCounter[currCounter].L_mac++;
+#endif
+ BASOP_CHECK();
+
+ return ( L_var_out );
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_msu |
+ | |
+ | Purpose : |
+ | |
+ | Multiply var1 by var2 and shift the result left by 1. Subtract the 32 |
+ | bit result from L_var3 with saturation, return a 32 bit result: |
+ | L_msu(L_var3,var1,var2) = L_sub(L_var3,L_mult(var1,var2)). |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | L_var3 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. |
+ |___________________________________________________________________________|
+*/
+#ifdef BASOP_NOGLOB
+Word32 L_msu_o( Word32 L_var3, Word16 var1, Word16 var2, Flag *Overflow )
+{
+ Word32 L_var_out;
+ Word32 L_product;
+
+ L_product = L_mult_o( var1, var2, Overflow );
+ L_var_out = L_sub_o( L_var3, L_product, Overflow );
+
+#ifdef WMOPS
+ multiCounter[currCounter].L_mult--;
+ multiCounter[currCounter].L_sub--;
+ multiCounter[currCounter].L_msu++;
+#endif
+
+ return ( L_var_out );
+}
+
+#endif /* BASOP_NOGLOB */
+Word32 L_msu( Word32 L_var3, Word16 var1, Word16 var2 )
+{
+ Word32 L_var_out;
+ Word32 L_product;
+
+ L_product = L_mult( var1, var2 );
+ L_var_out = L_sub( L_var3, L_product );
+
+#ifdef WMOPS
+ multiCounter[currCounter].L_mult--;
+ multiCounter[currCounter].L_sub--;
+ multiCounter[currCounter].L_msu++;
+#endif
+ BASOP_CHECK();
+
+ return ( L_var_out );
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_macNs |
+ | |
+ | Purpose : |
+ | |
+ | Multiply var1 by var2 and shift the result left by 1. Add the 32 bit |
+ | result to L_var3 without saturation, return a 32 bit result. Generate |
+ | carry and overflow values : |
+ | L_macNs(L_var3,var1,var2) = L_add_c(L_var3,L_mult(var1,var2)). |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | L_var3 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. |
+ | |
+ | Caution : |
+ | |
+#ifndef BASOP_NOGLOB
+ | In some cases the Carry flag has to be cleared or set before using |
+#else
+ | In some cases the BASOP_Carry flag has to be cleared or set before using |
+#endif
+ | operators which take into account its value. |
+ |___________________________________________________________________________|
+*/
+#ifndef BASOP_NOGLOB
+Word32 L_macNs( Word32 L_var3, Word16 var1, Word16 var2 )
+#else /* BASOP_NOGLOB */
+Word32 DEPR_L_macNs( Word32 L_var3, Word16 var1, Word16 var2, Flag *Carry )
+#endif /* BASOP_NOGLOB */
+{
+ Word32 L_var_out;
+
+ L_var_out = L_mult( var1, var2 );
+#ifndef BASOP_NOGLOB
+ L_var_out = L_add_c( L_var3, L_var_out );
+#else /* BASOP_NOGLOB */
+ L_var_out = DEPR_L_add_c( L_var3, L_var_out, Carry );
+#endif /* BASOP_NOGLOB */
+
+#ifdef WMOPS
+ multiCounter[currCounter].L_mult--;
+ multiCounter[currCounter].L_add_c--;
+ multiCounter[currCounter].L_macNs++;
+#endif
+
+ /* BASOP_CHECK(); Do not check for overflow here, function produces the carry bit instead */
+
+
+ return ( L_var_out );
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_msuNs |
+ | |
+ | Purpose : |
+ | |
+ | Multiply var1 by var2 and shift the result left by 1. Subtract the 32 |
+ | bit result from L_var3 without saturation, return a 32 bit result. Ge- |
+ | nerate carry and overflow values : |
+ | L_msuNs(L_var3,var1,var2) = L_sub_c(L_var3,L_mult(var1,var2)). |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | L_var3 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. |
+ | |
+ | Caution : |
+ | |
+#ifndef BASOP_NOGLOB
+ | In some cases the Carry flag has to be cleared or set before using |
+#else
+ | In some cases the BASOP_Carry flag has to be cleared or set before using |
+#endif
+ | operators which take into account its value. |
+ |___________________________________________________________________________|
+*/
+#ifndef BASOP_NOGLOB
+Word32 L_msuNs( Word32 L_var3, Word16 var1, Word16 var2 )
+#else /* BASOP_NOGLOB */
+Word32 DEPR_L_msuNs( Word32 L_var3, Word16 var1, Word16 var2, Flag *Carry )
+#endif /* BASOP_NOGLOB */
+{
+ Word32 L_var_out;
+
+ L_var_out = L_mult( var1, var2 );
+#ifndef BASOP_NOGLOB
+ L_var_out = L_sub_c( L_var3, L_var_out );
+#else /* BASOP_NOGLOB */
+ L_var_out = DEPR_L_sub_c( L_var3, L_var_out, Carry );
+#endif /* BASOP_NOGLOB */
+
+#ifdef WMOPS
+ multiCounter[currCounter].L_mult--;
+ multiCounter[currCounter].L_sub_c--;
+ multiCounter[currCounter].L_msuNs++;
+#endif
+
+ /* BASOP_CHECK(); Do not check for overflow here, function produces the carry bit instead */
+
+ return ( L_var_out );
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_add |
+ | |
+ | Purpose : |
+ | |
+ | 32 bits addition of the two 32 bits variables (L_var1+L_var2) with |
+ | overflow control and saturation; the result is set at +2147483647 when |
+ | overflow occurs or at -2147483648 when underflow occurs. |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | L_var1 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | L_var2 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. |
+ |___________________________________________________________________________|
+*/
+#ifndef BASOP_NOGLOB
+Word32 L_add( Word32 L_var1, Word32 L_var2 )
+#else /* BASOP_NOGLOB */
+Word32 L_add_o( Word32 L_var1, Word32 L_var2, Flag *Overflow )
+#endif /* BASOP_NOGLOB */
+{
+ Word32 L_var_out;
+
+ L_var_out = L_var1 + L_var2;
+
+ if ( ( ( L_var1 ^ L_var2 ) & MIN_32 ) == 0 )
+ {
+ if ( ( L_var_out ^ L_var1 ) & MIN_32 )
+ {
+ L_var_out = ( L_var1 < 0 ) ? MIN_32 : MAX_32;
+#ifndef BASOP_NOGLOB
+ Overflow = 1;
+#else /* BASOP_NOGLOB */
+ *Overflow = 1;
+#endif /* BASOP_NOGLOB */
+ }
+ }
+
+#ifdef WMOPS
+ multiCounter[currCounter].L_add++;
+#endif
+
+ BASOP_CHECK();
+
+
+ return ( L_var_out );
+}
+
+#ifdef BASOP_NOGLOB
+Word32 L_add( Word32 L_var1, Word32 L_var2 )
+{
+ Word32 L_var_out;
+
+ L_var_out = L_var1 + L_var2;
+
+ if ( ( ( L_var1 ^ L_var2 ) & MIN_32 ) == 0 )
+ {
+ if ( ( L_var_out ^ L_var1 ) & MIN_32 )
+ {
+ L_var_out = ( L_var1 < 0 ) ? MIN_32 : MAX_32;
+ assert( 0 );
+ }
+ }
+
+#ifdef WMOPS
+ multiCounter[currCounter].L_add++;
+#endif
+ return ( L_var_out );
+}
+#endif /* BASOP_NOGLOB */
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_sub |
+ | |
+ | Purpose : |
+ | |
+ | 32 bits subtraction of the two 32 bits variables (L_var1-L_var2) with |
+ | overflow control and saturation; the result is set at +2147483647 when |
+ | overflow occurs or at -2147483648 when underflow occurs. |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | L_var1 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | L_var2 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. |
+ |___________________________________________________________________________|
+*/
+#ifndef BASOP_NOGLOB
+Word32 L_sub( Word32 L_var1, Word32 L_var2 )
+#else /* BASOP_NOGLOB */
+Word32 L_sub_o( Word32 L_var1, Word32 L_var2, Flag *Overflow )
+#endif /* BASOP_NOGLOB */
+{
+ Word32 L_var_out;
+
+ L_var_out = L_var1 - L_var2;
+
+ if ( ( ( L_var1 ^ L_var2 ) & MIN_32 ) != 0 )
+ {
+ if ( ( L_var_out ^ L_var1 ) & MIN_32 )
+ {
+ L_var_out = ( L_var1 < 0L ) ? MIN_32 : MAX_32;
+#ifndef BASOP_NOGLOB
+ Overflow = 1;
+#else /* BASOP_NOGLOB */
+ *Overflow = 1;
+#endif /* BASOP_NOGLOB */
+ }
+ }
+
+#ifdef WMOPS
+ multiCounter[currCounter].L_sub++;
+#endif
+
+ BASOP_CHECK();
+
+ return ( L_var_out );
+}
+
+#ifdef BASOP_NOGLOB
+Word32 L_sub( Word32 L_var1, Word32 L_var2 )
+{
+ Word32 L_var_out;
+
+ L_var_out = L_var1 - L_var2;
+
+ if ( ( ( L_var1 ^ L_var2 ) & MIN_32 ) != 0 )
+ {
+ if ( ( L_var_out ^ L_var1 ) & MIN_32 )
+ {
+ L_var_out = ( L_var1 < 0L ) ? MIN_32 : MAX_32;
+ assert( 0 );
+ }
+ }
+
+#ifdef WMOPS
+ multiCounter[currCounter].L_sub++;
+#endif
+ BASOP_CHECK();
+
+ return ( L_var_out );
+}
+#endif /* BASOP_NOGLOB */
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_add_c |
+ | |
+ | Purpose : |
+ | |
+ | Performs 32 bits addition of the two 32 bits variables (L_var1+L_var2+C)|
+#ifndef BASOP_NOGLOB
+ | with carry. No saturation. Generate carry and Overflow values. The car- |
+#else
+ | with carry. No saturation. Generate carry and BASOP_Overflow values. The car- |
+#endif
+ | ry and overflow values are binary variables which can be tested and as- |
+ | signed values. |
+ | |
+ | Complexity weight : 2 |
+ | |
+ | Inputs : |
+ | |
+ | L_var1 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | L_var2 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. |
+ | |
+ | Caution : |
+ | |
+#ifndef BASOP_NOGLOB
+ | In some cases the Carry flag has to be cleared or set before using |
+#else
+ | In some cases the BASOP_Carry flag has to be cleared or set before using |
+#endif
+ | operators which take into account its value. |
+ |___________________________________________________________________________|
+*/
+#ifndef BASOP_NOGLOB
+Word32 L_add_c( Word32 L_var1, Word32 L_var2 )
+#else /* BASOP_NOGLOB */
+Word32 DEPR_L_add_c( Word32 L_var1, Word32 L_var2, Flag *Carry )
+#endif /* BASOP_NOGLOB */
+{
+ Word32 L_var_out;
+ Word32 L_test;
+ Flag carry_int = 0;
+
+#ifndef BASOP_NOGLOB
+ L_var_out = L_var1 + L_var2 + Carry;
+#else /* BASOP_NOGLOB */
+ L_var_out = L_var1 + L_var2 + *Carry;
+#endif /* BASOP_NOGLOB */
+
+ L_test = L_var1 + L_var2;
+
+ if ( ( L_var1 > 0 ) && ( L_var2 > 0 ) && ( L_test < 0 ) )
+ {
+#ifndef BASOP_NOGLOB
+ Overflow = 1;
+#endif /* ! BASOP_NOGLOB */
+ carry_int = 0;
+ }
+ else
+ {
+ if ( ( L_var1 < 0 ) && ( L_var2 < 0 ) )
+ {
+ if ( L_test >= 0 )
+ {
+#ifndef BASOP_NOGLOB
+ Overflow = 1;
+#endif /* ! BASOP_NOGLOB */
+ carry_int = 1;
+ }
+ else
+ {
+#ifndef BASOP_NOGLOB
+ Overflow = 0;
+#endif /* ! BASOP_NOGLOB */
+ carry_int = 1;
+ }
+ }
+ else
+ {
+ if ( ( ( L_var1 ^ L_var2 ) < 0 ) && ( L_test >= 0 ) )
+ {
+#ifndef BASOP_NOGLOB
+ Overflow = 0;
+#endif /* ! BASOP_NOGLOB */
+ carry_int = 1;
+ }
+ else
+ {
+#ifndef BASOP_NOGLOB
+ Overflow = 0;
+#endif /* ! BASOP_NOGLOB */
+ carry_int = 0;
+ }
+ }
+ }
+
+#ifndef BASOP_NOGLOB
+ if ( Carry )
+#else /* BASOP_NOGLOB */
+ if ( *Carry )
+#endif /* BASOP_NOGLOB */
+ {
+ if ( L_test == MAX_32 )
+ {
+#ifndef BASOP_NOGLOB
+ Overflow = 1;
+ Carry = carry_int;
+#else /* BASOP_NOGLOB */
+ *Carry = carry_int;
+#endif /* BASOP_NOGLOB */
+ }
+ else
+ {
+ if ( L_test == (Word32) 0xFFFFFFFFL )
+ {
+#ifndef BASOP_NOGLOB
+ Carry = 1;
+#else /* BASOP_NOGLOB */
+ *Carry = 1;
+#endif /* BASOP_NOGLOB */
+ }
+ else
+ {
+#ifndef BASOP_NOGLOB
+ Carry = carry_int;
+#else /* BASOP_NOGLOB */
+ *Carry = carry_int;
+#endif /* BASOP_NOGLOB */
+ }
+ }
+ }
+ else
+ {
+#ifndef BASOP_NOGLOB
+ Carry = carry_int;
+#else /* BASOP_NOGLOB */
+ *Carry = carry_int;
+#endif /* BASOP_NOGLOB */
+ }
+
+#ifdef WMOPS
+ multiCounter[currCounter].L_add_c++;
+#endif
+
+ /* BASOP_CHECK(); Do not check for overflow here, function produces the carry bit instead */
+
+
+ return ( L_var_out );
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_sub_c |
+ | |
+ | Purpose : |
+ | |
+ | Performs 32 bits subtraction of the two 32 bits variables with carry |
+#ifndef BASOP_NOGLOB
+ | (borrow) : L_var1-L_var2-C. No saturation. Generate carry and Overflow |
+#else
+ | (borrow) : L_var1-L_var2-C. No saturation. Generate carry and BASOP_Overflow |
+#endif
+ | values. The carry and overflow values are binary variables which can |
+ | be tested and assigned values. |
+ | |
+ | Complexity weight : 2 |
+ | |
+ | Inputs : |
+ | |
+ | L_var1 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | L_var2 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. |
+ | |
+ | Caution : |
+ | |
+#ifndef BASOP_NOGLOB
+ | In some cases the Carry flag has to be cleared or set before using |
+#else
+ | In some cases the BASOP_Carry flag has to be cleared or set before using |
+#endif
+ | operators which take into account its value. |
+ |___________________________________________________________________________|
+*/
+#ifndef BASOP_NOGLOB
+Word32 L_sub_c( Word32 L_var1, Word32 L_var2 )
+#else /* BASOP_NOGLOB */
+Word32 DEPR_L_sub_c( Word32 L_var1, Word32 L_var2, Flag *Carry )
+#endif /* BASOP_NOGLOB */
+{
+ Word32 L_var_out;
+ Word32 L_test;
+ Flag carry_int = 0;
+
+#ifndef BASOP_NOGLOB
+ if ( Carry )
+#else /* BASOP_NOGLOB */
+ if ( *Carry )
+#endif /* BASOP_NOGLOB */
+ {
+#ifndef BASOP_NOGLOB
+ Carry = 0;
+#else /* BASOP_NOGLOB */
+ *Carry = 0;
+#endif /* BASOP_NOGLOB */
+ if ( L_var2 != MIN_32 )
+ {
+#ifndef BASOP_NOGLOB
+ L_var_out = L_add_c( L_var1, -L_var2 );
+#else /* BASOP_NOGLOB */
+ L_var_out = DEPR_L_add_c( L_var1, -L_var2, Carry );
+#endif /* BASOP_NOGLOB */
+#ifdef WMOPS
+ multiCounter[currCounter].L_add_c--;
+#endif
+ }
+ else
+ {
+ L_var_out = L_var1 - L_var2;
+ if ( L_var1 > 0L )
+ {
+#ifndef BASOP_NOGLOB
+ Overflow = 1;
+ Carry = 0;
+#else /* BASOP_NOGLOB */
+ *Carry = 0;
+#endif /* BASOP_NOGLOB */
+ }
+ }
+ }
+ else
+ {
+ L_var_out = L_var1 - L_var2 - (Word32) 0X00000001L;
+ L_test = L_var1 - L_var2;
+
+ if ( ( L_test < 0 ) && ( L_var1 > 0 ) && ( L_var2 < 0 ) )
+ {
+#ifndef BASOP_NOGLOB
+ Overflow = 1;
+#endif /* ! BASOP_NOGLOB */
+ carry_int = 0;
+ }
+ else if ( ( L_test > 0 ) && ( L_var1 < 0 ) && ( L_var2 > 0 ) )
+ {
+#ifndef BASOP_NOGLOB
+ Overflow = 1;
+#endif /* ! BASOP_NOGLOB */
+ carry_int = 1;
+ }
+ else if ( ( L_test > 0 ) && ( ( L_var1 ^ L_var2 ) > 0 ) )
+ {
+#ifndef BASOP_NOGLOB
+ Overflow = 0;
+#endif /* ! BASOP_NOGLOB */
+ carry_int = 1;
+ }
+ if ( L_test == MIN_32 )
+ {
+#ifndef BASOP_NOGLOB
+ Overflow = 1;
+ Carry = carry_int;
+#else /* BASOP_NOGLOB */
+ *Carry = carry_int;
+#endif /* BASOP_NOGLOB */
+ }
+ else
+ {
+#ifndef BASOP_NOGLOB
+ Carry = carry_int;
+#else /* BASOP_NOGLOB */
+ *Carry = carry_int;
+#endif /* BASOP_NOGLOB */
+ }
+ }
+
+#ifdef WMOPS
+ multiCounter[currCounter].L_sub_c++;
+#endif
+
+ /* BASOP_CHECK(); Do not check for overflow here, function produces the carry bit instead */
+
+
+ return ( L_var_out );
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_negate |
+ | |
+ | Purpose : |
+ | |
+ | Negate the 32 bit variable L_var1 with saturation; saturate in the case |
+ | where input is -2147483648 (0x8000 0000). |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | L_var1 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. |
+ |___________________________________________________________________________|
+*/
+Word32 L_negate( Word32 L_var1 )
+{
+ Word32 L_var_out;
+
+ L_var_out = ( L_var1 == MIN_32 ) ? MAX_32 : -L_var1;
+
+
+#ifdef WMOPS
+ multiCounter[currCounter].L_negate++;
+#endif
+
+ BASOP_CHECK();
+
+ return ( L_var_out );
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : mult_r |
+ | |
+ | Purpose : |
+ | |
+ | Same as mult with rounding, i.e.: |
+ | mult_r(var1,var2) = extract_l(L_shr(((var1 * var2) + 16384),15)) and |
+ | mult_r(-32768,-32768) = 32767. |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0x8000 <= var_out <= 0x7fff. |
+ |___________________________________________________________________________|
+*/
+#ifdef BASOP_NOGLOB
+Word16 mult_ro( Word16 var1, Word16 var2, Flag *Overflow )
+{
+ Word16 var_out;
+ Word32 L_product_arr;
+
+ L_product_arr = (Word32) var1 * (Word32) var2; /* product */
+ L_product_arr += (Word32) 0x00004000L; /* round */
+ L_product_arr &= (Word32) 0xffff8000L;
+ L_product_arr >>= 15; /* shift */
+
+ if ( L_product_arr & (Word32) 0x00010000L ) /* sign extend when necessary */
+ {
+ L_product_arr |= (Word32) 0xffff0000L;
+ }
+ var_out = saturate_o( L_product_arr, Overflow );
+
+#ifdef WMOPS
+ multiCounter[currCounter].mult_r++;
+#endif
+
+ return ( var_out );
+}
+
+#endif /* BASOP_NOGLOB */
+Word16 mult_r( Word16 var1, Word16 var2 )
+{
+ Word16 var_out;
+ Word32 L_product_arr;
+
+ L_product_arr = (Word32) var1 * (Word32) var2; /* product */
+ L_product_arr += (Word32) 0x00004000L; /* round */
+ L_product_arr &= (Word32) 0xffff8000L;
+ L_product_arr >>= 15; /* shift */
+
+ if ( L_product_arr & (Word32) 0x00010000L ) /* sign extend when necessary */
+ {
+ L_product_arr |= (Word32) 0xffff0000L;
+ }
+ var_out = saturate( L_product_arr );
+
+#ifdef WMOPS
+ multiCounter[currCounter].mult_r++;
+#endif
+ return ( var_out );
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_shl |
+ | |
+ | Purpose : |
+ | |
+ | Arithmetically shift the 32 bit input L_var1 left var2 positions. Zero |
+ | fill the var2 LSB of the result. If var2 is negative, arithmetically |
+ | shift L_var1 right by -var2 with sign extension. Saturate the result in |
+ | case of underflows or overflows. |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | L_var1 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. |
+ |___________________________________________________________________________|
+*/
+#ifndef BASOP_NOGLOB
+Word32 L_shl( Word32 L_var1, Word16 var2 )
+#else /* BASOP_NOGLOB */
+Word32 L_shl_o( Word32 L_var1, Word16 var2, Flag *Overflow )
+#endif /* BASOP_NOGLOB */
+{
+
+ Word32 L_var_out = 0L;
+
+ if ( var2 <= 0 )
+ {
+ if ( var2 < -32 )
+ var2 = -32;
+ var2 = -var2;
+ L_var_out = L_shr( L_var1, var2 );
+#ifdef WMOPS
+ multiCounter[currCounter].L_shr--;
+#endif
+ }
+ else
+ {
+ for ( ; var2 > 0; var2-- )
+ {
+ if ( L_var1 > (Word32) 0X3fffffffL )
+ {
+#ifndef BASOP_NOGLOB
+ Overflow = 1;
+#else /* BASOP_NOGLOB */
+ *Overflow = 1;
+#endif /* BASOP_NOGLOB */
+ L_var_out = MAX_32;
+ break;
+ }
+ else
+ {
+ if ( L_var1 < (Word32) 0xc0000000L )
+ {
+#ifndef BASOP_NOGLOB
+ Overflow = 1;
+#else /* BASOP_NOGLOB */
+ *Overflow = 1;
+#endif /* BASOP_NOGLOB */
+ L_var_out = MIN_32;
+ break;
+ }
+ }
+ L_var1 *= 2;
+ L_var_out = L_var1;
+ }
+ }
+
+#ifdef WMOPS
+ multiCounter[currCounter].L_shl++;
+#endif
+
+ BASOP_CHECK();
+
+
+ return ( L_var_out );
+}
+
+#ifdef BASOP_NOGLOB
+Word32 L_shl( Word32 L_var1, Word16 var2 )
+{
+
+ Word32 L_var_out = 0L;
+
+ if ( var2 <= 0 )
+ {
+ if ( var2 < -32 )
+ var2 = -32;
+ var2 = -var2;
+ L_var_out = L_shr( L_var1, var2 );
+#ifdef WMOPS
+ multiCounter[currCounter].L_shr--;
+#endif
+ }
+ else
+ {
+ for ( ; var2 > 0; var2-- )
+ {
+ if ( L_var1 > (Word32) 0X3fffffffL )
+ {
+ assert( 0 );
+ L_var_out = MAX_32;
+ break;
+ }
+ else
+ {
+ if ( L_var1 < (Word32) 0xc0000000L )
+ {
+ assert( 0 );
+ L_var_out = MIN_32;
+ break;
+ }
+ }
+ L_var1 *= 2;
+ L_var_out = L_var1;
+ }
+ }
+
+#ifdef WMOPS
+ multiCounter[currCounter].L_shl++;
+#endif
+ BASOP_CHECK();
+
+
+ return ( L_var_out );
+}
+#endif /* BASOP_NOGLOB */
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_shr |
+ | |
+ | Purpose : |
+ | |
+ | Arithmetically shift the 32 bit input L_var1 right var2 positions with |
+ | sign extension. If var2 is negative, arithmetically shift L_var1 left |
+ | by -var2 and zero fill the -var2 LSB of the result. Saturate the result |
+ | in case of underflows or overflows. |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | L_var1 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. |
+ |___________________________________________________________________________|
+*/
+#ifdef BASOP_NOGLOB
+Word32 L_shr_o( Word32 L_var1, Word16 var2, Flag *Overflow )
+{
+ Word32 L_var_out;
+
+ if ( var2 < 0 )
+ {
+ if ( var2 < -32 )
+ var2 = -32;
+ var2 = -var2;
+ L_var_out = L_shl_o( L_var1, var2, Overflow );
+#ifdef WMOPS
+ multiCounter[currCounter].L_shl--;
+#endif
+ }
+ else
+ {
+ if ( var2 >= 31 )
+ {
+ L_var_out = ( L_var1 < 0L ) ? -1 : 0;
+ }
+ else
+ {
+ if ( L_var1 < 0 )
+ {
+ L_var_out = ~( ( ~L_var1 ) >> var2 );
+ }
+ else
+ {
+ L_var_out = L_var1 >> var2;
+ }
+ }
+ }
+
+#ifdef WMOPS
+ multiCounter[currCounter].L_shr++;
+#endif
+
+ BASOP_CHECK();
+
+
+ return ( L_var_out );
+}
+
+#endif /* BASOP_NOGLOB */
+Word32 L_shr( Word32 L_var1, Word16 var2 )
+{
+ Word32 L_var_out;
+
+ if ( var2 < 0 )
+ {
+ if ( var2 < -32 )
+ var2 = -32;
+ var2 = -var2;
+ L_var_out = L_shl( L_var1, var2 );
+#ifdef WMOPS
+ multiCounter[currCounter].L_shl--;
+#endif
+ }
+ else
+ {
+ if ( var2 >= 31 )
+ {
+ L_var_out = ( L_var1 < 0L ) ? -1 : 0;
+ }
+ else
+ {
+ if ( L_var1 < 0 )
+ {
+ L_var_out = ~( ( ~L_var1 ) >> var2 );
+ }
+ else
+ {
+ L_var_out = L_var1 >> var2;
+ }
+ }
+ }
+
+#ifdef WMOPS
+ multiCounter[currCounter].L_shr++;
+#endif
+ BASOP_CHECK();
+
+
+ return ( L_var_out );
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : shr_r |
+ | |
+ | Purpose : |
+ | |
+ | Same as shr(var1,var2) but with rounding. Saturate the result in case of|
+ | underflows or overflows : |
+ | - If var2 is greater than zero : |
+ | if (sub(shl(shr(var1,var2),1),shr(var1,sub(var2,1)))) |
+ | is equal to zero |
+ | then |
+ | shr_r(var1,var2) = shr(var1,var2) |
+ | else |
+ | shr_r(var1,var2) = add(shr(var1,var2),1) |
+ | - If var2 is less than or equal to zero : |
+ | shr_r(var1,var2) = shr(var1,var2). |
+ | |
+ | Complexity weight : 3 |
+ | |
+ | Inputs : |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+Word16 shr_r( Word16 var1, Word16 var2 )
+{
+ Word16 var_out;
+
+ if ( var2 > 15 )
+ {
+ var_out = 0;
+ }
+ else
+ {
+ var_out = shr( var1, var2 );
+
+#ifdef WMOPS
+ multiCounter[currCounter].shr--;
+#endif
+ if ( var2 > 0 )
+ {
+ if ( ( var1 & ( (Word16) 1 << ( var2 - 1 ) ) ) != 0 )
+ {
+ var_out++;
+ }
+ }
+ }
+
+#ifdef WMOPS
+ multiCounter[currCounter].shr_r++;
+#endif
+
+ BASOP_CHECK();
+
+ return ( var_out );
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : mac_r |
+ | |
+ | Purpose : |
+ | |
+ | Multiply var1 by var2 and shift the result left by 1. Add the 32 bit |
+ | result to L_var3 with saturation. Round the LS 16 bits of the result |
+ | into the MS 16 bits with saturation and shift the result right by 16. |
+ | Return a 16 bit result. |
+ | mac_r(L_var3,var1,var2) = round_fx(L_mac(L_var3,var1,var2)) |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | L_var3 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0x0000 8000 <= L_var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+#ifdef BASOP_NOGLOB
+Word16 mac_ro( Word32 L_var3, Word16 var1, Word16 var2, Flag *Overflow )
+{
+ Word16 var_out;
+
+ L_var3 = L_mac_o( L_var3, var1, var2, Overflow );
+ L_var3 = L_add_o( L_var3, (Word32) 0x00008000L, Overflow );
+ var_out = extract_h( L_var3 );
+
+#ifdef WMOPS
+ multiCounter[currCounter].L_mac--;
+ multiCounter[currCounter].L_add--;
+ multiCounter[currCounter].extract_h--;
+ multiCounter[currCounter].mac_r++;
+#endif
+
+ BASOP_CHECK();
+
+
+ return ( var_out );
+}
+
+#endif /* BASOP_NOGLOB */
+Word16 mac_r( Word32 L_var3, Word16 var1, Word16 var2 )
+{
+ Word16 var_out;
+
+ L_var3 = L_mac( L_var3, var1, var2 );
+ L_var3 = L_add( L_var3, (Word32) 0x00008000L );
+ var_out = extract_h( L_var3 );
+
+#ifdef WMOPS
+ multiCounter[currCounter].L_mac--;
+ multiCounter[currCounter].L_add--;
+ multiCounter[currCounter].extract_h--;
+ multiCounter[currCounter].mac_r++;
+#endif
+
+ BASOP_CHECK();
+
+
+ return ( var_out );
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : msu_r |
+ | |
+ | Purpose : |
+ | |
+ | Multiply var1 by var2 and shift the result left by 1. Subtract the 32 |
+ | bit result from L_var3 with saturation. Round the LS 16 bits of the res-|
+ | ult into the MS 16 bits with saturation and shift the result right by |
+ | 16. Return a 16 bit result. |
+ | msu_r(L_var3,var1,var2) = round_fx(L_msu(L_var3,var1,var2)) |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | L_var3 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0x0000 8000 <= L_var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+#ifdef BASOP_NOGLOB
+Word16 msu_ro( Word32 L_var3, Word16 var1, Word16 var2, Flag *Overflow )
+{
+ Word16 var_out;
+
+ L_var3 = L_msu_o( L_var3, var1, var2, Overflow );
+ L_var3 = L_add_o( L_var3, (Word32) 0x00008000L, Overflow );
+ var_out = extract_h( L_var3 );
+
+#ifdef WMOPS
+ multiCounter[currCounter].L_msu--;
+ multiCounter[currCounter].L_add--;
+ multiCounter[currCounter].extract_h--;
+ multiCounter[currCounter].msu_r++;
+#endif
+ BASOP_CHECK();
+
+ return ( var_out );
+}
+
+#endif /* BASOP_NOGLOB */
+Word16 msu_r( Word32 L_var3, Word16 var1, Word16 var2 )
+{
+ Word16 var_out;
+
+ L_var3 = L_msu( L_var3, var1, var2 );
+ L_var3 = L_add( L_var3, (Word32) 0x00008000L );
+ var_out = extract_h( L_var3 );
+
+#ifdef WMOPS
+ multiCounter[currCounter].L_msu--;
+ multiCounter[currCounter].L_add--;
+ multiCounter[currCounter].extract_h--;
+ multiCounter[currCounter].msu_r++;
+#endif
+ BASOP_CHECK();
+
+ return ( var_out );
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_deposit_h |
+ | |
+ | Purpose : |
+ | |
+ | Deposit the 16 bit var1 into the 16 MS bits of the 32 bit output. The |
+ | 16 LS bits of the output are zeroed. |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= var_out <= 0x7fff 0000. |
+ |___________________________________________________________________________|
+*/
+Word32 L_deposit_h( Word16 var1 )
+{
+ Word32 L_var_out;
+
+ L_var_out = (Word32) var1 << 16;
+
+#ifdef WMOPS
+ multiCounter[currCounter].L_deposit_h++;
+#endif
+
+ BASOP_CHECK();
+
+
+ return ( L_var_out );
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_deposit_l |
+ | |
+ | Purpose : |
+ | |
+ | Deposit the 16 bit var1 into the 16 LS bits of the 32 bit output. The |
+ | 16 MS bits of the output are sign extended. |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0xFFFF 8000 <= var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+Word32 L_deposit_l( Word16 var1 )
+{
+ Word32 L_var_out;
+
+ L_var_out = (Word32) var1;
+
+#ifdef WMOPS
+ multiCounter[currCounter].L_deposit_l++;
+#endif
+
+ BASOP_CHECK();
+
+
+ return ( L_var_out );
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_shr_r |
+ | |
+ | Purpose : |
+ | |
+ | Same as L_shr(L_var1,var2) but with rounding. Saturate the result in |
+ | case of underflows or overflows : |
+ | - If var2 is greater than zero : |
+ | if (L_sub(L_shl(L_shr(L_var1,var2),1),L_shr(L_var1,sub(var2,1))))|
+ | is equal to zero |
+ | then |
+ | L_shr_r(L_var1,var2) = L_shr(L_var1,var2) |
+ | else |
+ | L_shr_r(L_var1,var2) = L_add(L_shr(L_var1,var2),1) |
+ | - If var2 is less than or equal to zero : |
+ | L_shr_r(L_var1,var2) = L_shr(L_var1,var2). |
+ | |
+ | Complexity weight : 3 |
+ | |
+ | Inputs : |
+ | |
+ | L_var1 |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= var1 <= 0x7fff ffff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= var_out <= 0x7fff ffff. |
+ |___________________________________________________________________________|
+*/
+Word32 L_shr_r( Word32 L_var1, Word16 var2 )
+{
+ Word32 L_var_out;
+
+ if ( var2 > 31 )
+ {
+ L_var_out = 0;
+ }
+ else
+ {
+ L_var_out = L_shr( L_var1, var2 );
+
+#ifdef WMOPS
+ multiCounter[currCounter].L_shr--;
+#endif
+ if ( var2 > 0 )
+ {
+ if ( ( L_var1 & ( (Word32) 1 << ( var2 - 1 ) ) ) != 0 )
+ {
+ L_var_out++;
+ }
+ }
+ }
+
+#ifdef WMOPS
+ multiCounter[currCounter].L_shr_r++;
+#endif
+
+ BASOP_CHECK();
+
+
+ return ( L_var_out );
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_abs |
+ | |
+ | Purpose : |
+ | |
+ | Absolute value of L_var1; Saturate in case where the input is |
+ | -214783648 |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | L_var1 |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= var1 <= 0x7fff ffff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x0000 0000 <= var_out <= 0x7fff ffff. |
+ |___________________________________________________________________________|
+*/
+Word32 L_abs( Word32 L_var1 )
+{
+ Word32 L_var_out;
+
+ if ( L_var1 == MIN_32 )
+ {
+ L_var_out = MAX_32;
+ }
+ else
+ {
+ if ( L_var1 < 0 )
+ {
+ L_var_out = -L_var1;
+ }
+ else
+ {
+ L_var_out = L_var1;
+ }
+ }
+
+#ifdef WMOPS
+ multiCounter[currCounter].L_abs++;
+#endif
+
+ BASOP_CHECK();
+
+
+ return ( L_var_out );
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_sat |
+ | |
+ | Purpose : |
+ | |
+ | 32 bit L_var1 is set to 2147483647 if an overflow occured or to |
+ | -2147483648 if an underflow occured on the most recent L_add_c, |
+ | L_sub_c, L_macNs or L_msuNs operations. The carry and overflow values |
+ | are binary values which can be tested and assigned values. |
+ | |
+ | Complexity weight : 4 |
+ | |
+ | Inputs : |
+ | |
+ | L_var1 |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= var1 <= 0x7fff ffff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= var_out <= 0x7fff ffff. |
+ |___________________________________________________________________________|
+*/
+#ifndef BASOP_NOGLOB
+Word32 L_sat( Word32 L_var1 )
+#else /* BASOP_NOGLOB */
+Word32 DEPR_L_sat_co( Word32 L_var1, Flag Overflow, Flag Carry )
+#endif /* BASOP_NOGLOB */
+{
+ Word32 L_var_out;
+
+ L_var_out = L_var1;
+
+ if ( Overflow )
+ {
+
+ if ( Carry )
+ {
+ L_var_out = MIN_32;
+ }
+ else
+ {
+ L_var_out = MAX_32;
+ }
+#ifndef BASOP_NOGLOB
+
+ Carry = 0;
+ Overflow = 0;
+#endif /* ! BASOP_NOGLOB */
+ }
+
+#ifdef WMOPS
+ multiCounter[currCounter].L_sat++;
+#endif
+
+ BASOP_CHECK();
+
+
+ return ( L_var_out );
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : norm_s |
+ | |
+ | Purpose : |
+ | |
+ | Produces the number of left shift needed to normalize the 16 bit varia- |
+ | ble var1 for positive values on the interval with minimum of 16384 and |
+ | maximum of 32767, and for negative values on the interval with minimum |
+ | of -32768 and maximum of -16384; in order to normalize the result, the |
+ | following operation must be done : |
+ | norm_var1 = shl(var1,norm_s(var1)). |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0x0000 0000 <= var_out <= 0x0000 000f. |
+ |___________________________________________________________________________|
+*/
+Word16 norm_s( Word16 var1 )
+{
+ Word16 var_out;
+
+ if ( var1 == 0 )
+ {
+ var_out = 0;
+ }
+ else
+ {
+ if ( var1 == (Word16) 0xffff )
+ {
+ var_out = 15;
+ }
+ else
+ {
+ if ( var1 < 0 )
+ {
+ var1 = ~var1;
+ }
+ for ( var_out = 0; var1 < 0x4000; var_out++ )
+ {
+ var1 <<= 1;
+ }
+ }
+ }
+
+#ifdef WMOPS
+ multiCounter[currCounter].norm_s++;
+#endif
+
+ BASOP_CHECK();
+
+
+ return ( var_out );
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : div_s |
+ | |
+ | Purpose : |
+ | |
+ | Produces a result which is the fractional integer division of var1 by |
+ | var2; var1 and var2 must be positive and var2 must be greater or equal |
+ | to var1; the result is positive (leading bit equal to 0) and truncated |
+ | to 16 bits. |
+ | If var1 = var2 then div(var1,var2) = 32767. |
+ | |
+ | Complexity weight : 18 |
+ | |
+ | Inputs : |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0x0000 0000 <= var1 <= var2 and var2 != 0. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : var1 <= var2 <= 0x0000 7fff and var2 != 0. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0x0000 0000 <= var_out <= 0x0000 7fff. |
+ | It's a Q15 value (point between b15 and b14). |
+ |___________________________________________________________________________|
+*/
+Word16 div_s( Word16 var1, Word16 var2 )
+{
+ Word16 var_out = 0;
+ Word16 iteration;
+ Word32 L_num;
+ Word32 L_denom;
+
+ if ( ( var1 > var2 ) || ( var1 < 0 ) || ( var2 < 0 ) )
+ {
+ /* printf ("Division Error var1=%d var2=%d in ", var1, var2); printStack(); */
+ char text[60];
+ sprintf( text, "Division Error var1=%d var2=%d in ", var1, var2 );
+ abort(); /* exit (0); */
+ }
+ if ( var2 == 0 )
+ {
+ /* printf ("Division by 0, Fatal error in "); printStack(); */
+ abort(); /* exit (0); */
+ }
+ if ( var1 == 0 )
+ {
+ var_out = 0;
+ }
+ else
+ {
+ if ( var1 == var2 )
+ {
+ var_out = MAX_16;
+ }
+ else
+ {
+ L_num = L_deposit_l( var1 );
+ L_denom = L_deposit_l( var2 );
+
+#ifdef WMOPS
+ multiCounter[currCounter].L_deposit_l--;
+ multiCounter[currCounter].L_deposit_l--;
+#endif
+
+ for ( iteration = 0; iteration < 15; iteration++ )
+ {
+ var_out <<= 1;
+ L_num <<= 1;
+
+ if ( L_num >= L_denom )
+ {
+ L_num = L_sub( L_num, L_denom );
+ var_out = add( var_out, 1 );
+#ifdef WMOPS
+ multiCounter[currCounter].L_sub--;
+ multiCounter[currCounter].add--;
+#endif
+ }
+ }
+ }
+ }
+
+#ifdef WMOPS
+ multiCounter[currCounter].div_s++;
+#endif
+
+ BASOP_CHECK();
+
+
+ return ( var_out );
+}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : norm_l |
+ | |
+ | Purpose : |
+ | |
+ | Produces the number of left shifts needed to normalize the 32 bit varia-|
+ | ble L_var1 for positive values on the interval with minimum of |
+ | 1073741824 and maximum of 2147483647, and for negative values on the in-|
+ | terval with minimum of -2147483648 and maximum of -1073741824; in order |
+ | to normalize the result, the following operation must be done : |
+ | norm_L_var1 = L_shl(L_var1,norm_l(L_var1)). |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | L_var1 |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= var1 <= 0x7fff ffff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0x0000 0000 <= var_out <= 0x0000 001f. |
+ |___________________________________________________________________________|
+*/
+Word16 norm_l( Word32 L_var1 )
+{
+ Word16 var_out;
+
+ if ( L_var1 == 0 )
+ {
+ var_out = 0;
+ }
+ else
+ {
+ if ( L_var1 == (Word32) 0xffffffffL )
+ {
+ var_out = 31;
+ }
+ else
+ {
+ if ( L_var1 < 0 )
+ {
+ L_var1 = ~L_var1;
+ }
+ for ( var_out = 0; L_var1 < (Word32) 0x40000000L; var_out++ )
+ {
+ L_var1 <<= 1;
+ }
+ }
+ }
+
+#ifdef WMOPS
+ multiCounter[currCounter].norm_l++;
+#endif
+
+ BASOP_CHECK();
+
+
+ return ( var_out );
+}
+
+/*
+ ******************************************************************************
+ * Additional operators extracted from the G.723.1 Library
+ * Adapted for WMOPS calculations
+ ******************************************************************************
+ */
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_mls |
+ | |
+ | Purpose : |
+ | |
+ | Multiplies a 16 bit word v by a 32 bit word Lv and returns a 32 bit |
+ | word (multiplying 16 by 32 bit words gives 48 bit word; the function |
+ | extracts the 32 MSB and shift the result to the left by 1). |
+ | |
+ | A 32 bit word can be written as |
+ | Lv = a + b * 2^16 |
+ | where a= unsigned 16 LSBs and b= signed 16 MSBs. |
+ | The function returns v * Lv / 2^15 which is equivalent to |
+ | a*v / 2^15 + b*v*2 |
+ | |
+ | Complexity weight : 5 |
+ | |
+ | Inputs : |
+ | |
+ | Lv |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= var1 <= 0x7fff ffff. |
+ | v |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0x8000 <= var1 <= 0x7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= var_out <= 0x7fff ffff. |
+ | |
+ |___________________________________________________________________________|
+*/
+#ifdef BASOP_NOGLOB
+Word32 L_mls_o( Word32 Lv, Word16 v, Flag *Overflow )
+{
+ Word32 Temp;
+
+ Temp = Lv & (Word32) 0x0000ffff;
+ Temp = Temp * (Word32) v;
+ Temp = L_shr( Temp, (Word16) 15 );
+ Temp = L_mac_o( Temp, v, extract_h( Lv ), Overflow );
+
+#ifdef WMOPS
+ multiCounter[currCounter].L_shr--;
+ multiCounter[currCounter].L_mac--;
+ multiCounter[currCounter].extract_h--;
+ multiCounter[currCounter].L_mls++;
+#endif
+
+ BASOP_CHECK();
+
+ return Temp;
+}
+
+#endif /* BASOP_NOGLOB */
+Word32 L_mls( Word32 Lv, Word16 v )
+{
+ Word32 Temp;
+
+ Temp = Lv & (Word32) 0x0000ffff;
+ Temp = Temp * (Word32) v;
+ Temp = L_shr( Temp, (Word16) 15 );
+ Temp = L_mac( Temp, v, extract_h( Lv ) );
+
+#ifdef WMOPS
+ multiCounter[currCounter].L_shr--;
+ multiCounter[currCounter].L_mac--;
+ multiCounter[currCounter].extract_h--;
+ multiCounter[currCounter].L_mls++;
+#endif
+
+ BASOP_CHECK();
+
+ return Temp;
+}
+
+
+/*__________________________________________________________________________
+| |
+| Function Name : div_l |
+| |
+| Purpose : |
+| |
+| Produces a result which is the fractional integer division of L_var1 by |
+| var2; L_var1 and var2 must be positive and var2 << 16 must be greater or|
+| equal to L_var1; the result is positive (leading bit equal to 0) and |
+| truncated to 16 bits. |
+| If L_var1 == var2 << 16 then div_l(L_var1,var2) = 32767. |
+| |
+| Complexity weight : 32 |
+| |
+| Inputs : |
+| |
+| L_var1 |
+| 32 bit long signed integer (Word32) whose value falls in the |
+| range : 0x0000 0000 <= var1 <= (var2 << 16) and var2 != 0. |
+| L_var1 must be considered as a Q.31 value |
+| |
+| var2 |
+| 16 bit short signed integer (Word16) whose value falls in the |
+| range : var1 <= (var2<< 16) <= 0x7fff0000 and var2 != 0. |
+| var2 must be considered as a Q.15 value |
+| |
+| Outputs : |
+| |
+| none |
+| |
+| Return Value : |
+| |
+| var_out |
+| 16 bit short signed integer (Word16) whose value falls in the |
+| range : 0x0000 0000 <= var_out <= 0x0000 7fff. |
+| It's a Q15 value (point between b15 and b14). |
+|___________________________________________________________________________|
+*/
+Word16 div_l( Word32 L_num, Word16 den )
+{
+ Word16 var_out = (Word16) 0;
+ Word32 L_den;
+ Word16 iteration;
+
+#ifdef WMOPS
+ multiCounter[currCounter].div_l++;
+#endif
+
+ if ( den == (Word16) 0 )
+ {
+ /* printf("Division by 0 in div_l, Fatal error in "); printStack(); */
+ exit( -1 );
+ }
+
+ if ( ( L_num < (Word32) 0 ) || ( den < (Word16) 0 ) )
+ {
+ /* printf("Division Error in div_l, Fatal error in "); printStack(); */
+ exit( -1 );
+ }
+
+ L_den = L_deposit_h( den );
+#ifdef WMOPS
+ multiCounter[currCounter].L_deposit_h--;
+#endif
+
+ if ( L_num >= L_den )
+ {
+
+
+ BASOP_CHECK();
+ return MAX_16;
+ }
+ else
+ {
+ L_num = L_shr( L_num, (Word16) 1 );
+ L_den = L_shr( L_den, (Word16) 1 );
+#ifdef WMOPS
+ multiCounter[currCounter].L_shr -= 2;
+#endif
+ for ( iteration = (Word16) 0; iteration < (Word16) 15; iteration++ )
+ {
+ var_out = shl( var_out, (Word16) 1 );
+ L_num = L_shl( L_num, (Word16) 1 );
+#ifdef WMOPS
+ multiCounter[currCounter].shl--;
+ multiCounter[currCounter].L_shl--;
+#endif
+ if ( L_num >= L_den )
+ {
+ L_num = L_sub( L_num, L_den );
+ var_out = add( var_out, (Word16) 1 );
+#ifdef WMOPS
+ multiCounter[currCounter].L_sub--;
+ multiCounter[currCounter].add--;
+#endif
+ }
+ }
+
+
+ BASOP_CHECK();
+
+ return var_out;
+ }
+}
+
+
+/*__________________________________________________________________________
+| |
+| Function Name : i_mult |
+| |
+| Purpose : |
+| |
+| Integer 16-bit multiplication with overflow control. |
+| No overflow protection is performed if ORIGINAL_G7231 is defined. |
+| |
+| Complexity weight : 3 (it is performing something equivalent to |
+| extract_h( L_shl( L_mult0( v1, v2), 16)) |
+| |
+| Inputs : |
+| |
+| a |
+| 16 bit short signed integer (Word16). |
+| |
+| b |
+| 16 bit short signed integer (Word16). |
+| |
+| Outputs : |
+| |
+| none |
+| |
+| Return Value : |
+| |
+| 16 bit short signed integer (Word16). No overflow checks |
+| are performed if ORIGINAL_G7231 is defined. |
+|___________________________________________________________________________|
+*/
+#ifndef BASOP_NOGLOB
+Word16 i_mult( Word16 a, Word16 b )
+#else /* BASOP_NOGLOB */
+Word16 DEPR_i_mult( Word16 a, Word16 b )
+#endif /* BASOP_NOGLOB */
+{
+#ifdef ORIGINAL_G7231
+ return a * b;
+#else
+ Word32 /*register*/ c = a * b;
+#ifdef WMOPS
+ multiCounter[currCounter].i_mult++;
+#endif
+ return saturate( c );
+#endif
+}
+
+
+/*
+ ******************************************************************************
+ * The following three operators are not part of the original
+ * G.729/G.723.1 set of basic operators and implement shiftless
+ * accumulation operation.
+ ******************************************************************************
+ */
+
+/*___________________________________________________________________________
+ |
+ | Function Name : L_mult0
+ |
+ | Purpose :
+ |
+ | L_mult0 is the 32 bit result of the multiplication of var1 times var2
+ | without one left shift.
+ |
+ | Complexity weight : 1
+ |
+ | Inputs :
+ |
+ | var1 16 bit short signed integer (Word16) whose value falls in the
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff.
+ |
+ | var2 16 bit short signed integer (Word16) whose value falls in the
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff.
+ |
+ | Return Value :
+ |
+ | L_var_out
+ | 32 bit long signed integer (Word32) whose value falls in the
+ | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.
+ |___________________________________________________________________________
+*/
+Word32 L_mult0( Word16 var1, Word16 var2 )
+{
+ Word32 L_var_out;
+
+ L_var_out = (Word32) var1 * (Word32) var2;
+
+#ifdef WMOPS
+ multiCounter[currCounter].L_mult0++;
+#endif
+
+
+ return ( L_var_out );
+}
+
+
+/*___________________________________________________________________________
+ |
+ | Function Name : L_mac0
+ |
+ | Purpose :
+ |
+ | Multiply var1 by var2 (without left shift) and add the 32 bit result to
+ | L_var3 with saturation, return a 32 bit result:
+ | L_mac0(L_var3,var1,var2) = L_add(L_var3,(L_mult0(var1,var2)).
+ |
+ | Complexity weight : 1
+ |
+ | Inputs :
+ |
+ | L_var3 32 bit long signed integer (Word32) whose value falls in the
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.
+ |
+ | var1 16 bit short signed integer (Word16) whose value falls in the
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff.
+ |
+ | var2 16 bit short signed integer (Word16) whose value falls in the
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff.
+ |
+ | Return Value :
+ |
+ | L_var_out
+ | 32 bit long signed integer (Word32) whose value falls in the
+ | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.
+ |___________________________________________________________________________
+*/
+#ifdef BASOP_NOGLOB
+Word32 L_mac0_o( Word32 L_var3, Word16 var1, Word16 var2, Flag *Overflow )
+{
+ Word32 L_var_out;
+ Word32 L_product;
+
+ L_product = L_mult0( var1, var2 );
+ L_var_out = L_add_o( L_var3, L_product, Overflow );
+
+#ifdef WMOPS
+ multiCounter[currCounter].L_mac0++;
+ multiCounter[currCounter].L_mult0--;
+ multiCounter[currCounter].L_add--;
+#endif
+
+ BASOP_CHECK();
+
+ return ( L_var_out );
+}
+
+#endif /* BASOP_NOGLOB */
+Word32 L_mac0( Word32 L_var3, Word16 var1, Word16 var2 )
+{
+ Word32 L_var_out;
+ Word32 L_product;
+
+ L_product = L_mult0( var1, var2 );
+ L_var_out = L_add( L_var3, L_product );
+
+#ifdef WMOPS
+ multiCounter[currCounter].L_mac0++;
+ multiCounter[currCounter].L_mult0--;
+ multiCounter[currCounter].L_add--;
+#endif
+
+ BASOP_CHECK();
+
+
+ return ( L_var_out );
+}
+
+
+/*___________________________________________________________________________
+ |
+ | Function Name : L_msu0
+ |
+ | Purpose :
+ |
+ | Multiply var1 by var2 (without left shift) and subtract the 32 bit
+ | result to L_var3 with saturation, return a 32 bit result:
+ | L_msu0(L_var3,var1,var2) = L_sub(L_var3,(L_mult0(var1,var2)).
+ |
+ | Complexity weight : 1
+ |
+ | Inputs :
+ |
+ | L_var3 32 bit long signed integer (Word32) whose value falls in the
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.
+ |
+ | var1 16 bit short signed integer (Word16) whose value falls in the
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff.
+ |
+ | var2 16 bit short signed integer (Word16) whose value falls in the
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff.
+ |
+ | Return Value :
+ |
+ | L_var_out
+ | 32 bit long signed integer (Word32) whose value falls in the
+ | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.
+ |___________________________________________________________________________
+*/
+#ifdef BASOP_NOGLOB
+Word32 L_msu0_o( Word32 L_var3, Word16 var1, Word16 var2, Flag *Overflow )
+{
+ Word32 L_var_out;
+ Word32 L_product;
+
+ L_product = L_mult0( var1, var2 );
+ L_var_out = L_sub_o( L_var3, L_product, Overflow );
+
+#ifdef WMOPS
+ multiCounter[currCounter].L_msu0++;
+ multiCounter[currCounter].L_mult0--;
+ multiCounter[currCounter].L_sub--;
+#endif
+
+ BASOP_CHECK();
+
+ return ( L_var_out );
+}
+
+#endif /* BASOP_NOGLOB */
+Word32 L_msu0( Word32 L_var3, Word16 var1, Word16 var2 )
+{
+ Word32 L_var_out;
+ Word32 L_product;
+
+ L_product = L_mult0( var1, var2 );
+ L_var_out = L_sub( L_var3, L_product );
+
+#ifdef WMOPS
+ multiCounter[currCounter].L_msu0++;
+ multiCounter[currCounter].L_mult0--;
+ multiCounter[currCounter].L_sub--;
+#endif
+
+ BASOP_CHECK();
+
+
+ return ( L_var_out );
+}
+
+#undef WMC_TOOL_SKIP
diff --git a/lib_com/basop32.h b/lib_com/basop32.h
new file mode 100644
index 0000000000000000000000000000000000000000..376ac8c78dc3a4356effe8ff41bb43e2a0b6a825
--- /dev/null
+++ b/lib_com/basop32.h
@@ -0,0 +1,276 @@
+/******************************************************************************************************
+
+ (C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
+ Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
+ Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
+ Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
+ contributors to this repository. All Rights Reserved.
+
+ This software is protected by copyright law and by international treaties.
+ The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
+ Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
+ Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
+ Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
+ contributors to this repository retain full ownership rights in their respective contributions in
+ the software. This notice grants no license of any kind, including but not limited to patent
+ license, nor is any license granted by implication, estoppel or otherwise.
+
+ Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
+ contributions.
+
+ This software is provided "AS IS", without any express or implied warranties. The software is in the
+ development stage. It is intended exclusively for experts who have experience with such software and
+ solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
+ and fitness for a particular purpose are hereby disclaimed and excluded.
+
+ Any dispute, controversy or claim arising under or in relation to providing this software shall be
+ submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
+ accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
+ the United Nations Convention on Contracts on the International Sales of Goods.
+
+*******************************************************************************************************/
+
+/*
+ ===========================================================================
+ File: BASOP32.H v.2.3 - 30.Nov.2009
+ ===========================================================================
+
+ ITU-T STL BASIC OPERATORS
+
+ GLOBAL FUNCTION PROTOTYPES
+
+ History:
+ 26.Jan.00 v1.0 Incorporated to the STL from updated G.723.1/G.729
+ basic operator library (based on basic_op.h) and
+ G.723.1's basop.h.
+ 05.Jul.00 v1.1 Added 32-bit shiftless mult/mac/msub operators
+
+ 03 Nov 04 v2.0 Incorporation of new 32-bit / 40-bit / control
+ operators for the ITU-T Standard Tool Library as
+ described in Geneva, 20-30 January 2004 WP 3/16 Q10/16
+ TD 11 document and subsequent discussions on the
+ wp3audio@yahoogroups.com email reflector.
+ norm_s() weight reduced from 15 to 1.
+ norm_l() weight reduced from 30 to 1.
+ L_abs() weight reduced from 2 to 1.
+ L_add() weight reduced from 2 to 1.
+ L_negate() weight reduced from 2 to 1.
+ L_shl() weight reduced from 2 to 1.
+ L_shr() weight reduced from 2 to 1.
+ L_sub() weight reduced from 2 to 1.
+ mac_r() weight reduced from 2 to 1.
+ msu_r() weight reduced from 2 to 1.
+ mult_r() weight reduced from 2 to 1.
+ L_deposit_h() weight reduced from 2 to 1.
+ L_deposit_l() weight reduced from 2 to 1.
+ L_mls() weight of 5.
+ div_l() weight of 32.
+ i_mult() weight of 3.
+
+ 30 Nov 09 v2.3 round() function is now round_fx().
+ saturate() is not referencable from outside application
+
+ 13 Mar 12 Add Overflow2 flag for additional overflow checking.
+ ============================================================================
+*/
+
+
+#ifndef _BASIC_OP_H
+#define _BASIC_OP_H
+
+#include "typedef.h"
+#define BASOP_OVERFLOW2
+
+/*___________________________________________________________________________
+ | |
+ | Constants and Globals |
+ |___________________________________________________________________________|
+*/
+#ifndef BASOP_NOGLOB
+extern Flag Overflow, Overflow2;
+extern Flag Carry;
+
+#else /* BASOP_NOGLOB */
+/* DISABLED TO AVOID GLOBAL VARIABLES */
+/*
+extern Flag BASOP_Overflow, BASOP_Overflow2;
+extern Flag BASOP_Carry;
+*/
+#endif /* BASOP_NOGLOB */
+#define BASOP_SATURATE_WARNING_ON
+#define BASOP_SATURATE_WARNING_OFF
+#define BASOP_SATURATE_ERROR_ON
+#define BASOP_SATURATE_ERROR_OFF
+#define BASOP_CHECK()
+
+
+#define MAX_32 (Word32) 0x7fffffffL
+#define MIN_32 (Word32) 0x80000000L
+
+#define MAX_16 (Word16) 0x7fff
+#define MIN_16 (Word16) 0x8000
+
+/*___________________________________________________________________________
+ | |
+ | Prototypes for basic arithmetic operators |
+ |___________________________________________________________________________|
+*/
+
+#ifndef BASOP_NOGLOB
+Word16 add( Word16 var1, Word16 var2 ); /* Short add, 1 */
+Word16 sub( Word16 var1, Word16 var2 ); /* Short sub, 1 */
+Word16 abs_s( Word16 var1 ); /* Short abs, 1 */
+Word16 shl( Word16 var1, Word16 var2 ); /* Short shift left, 1 */
+Word16 shr( Word16 var1, Word16 var2 ); /* Short shift right, 1 */
+Word16 mult( Word16 var1, Word16 var2 ); /* Short mult, 1 */
+Word32 L_mult( Word16 var1, Word16 var2 ); /* Long mult, 1 */
+Word16 negate( Word16 var1 ); /* Short negate, 1 */
+Word16 extract_h( Word32 L_var1 ); /* Extract high, 1 */
+Word16 extract_l( Word32 L_var1 ); /* Extract low, 1 */
+Word16 round_fx( Word32 L_var1 ); /* Round, 1 */
+Word32 L_mac( Word32 L_var3, Word16 var1, Word16 var2 ); /* Mac, 1 */
+Word32 L_msu( Word32 L_var3, Word16 var1, Word16 var2 ); /* Msu, 1 */
+Word32 L_macNs( Word32 L_var3, Word16 var1, Word16 var2 ); /* Mac without
+ sat, 1 */
+#else /* BASOP_NOGLOB */
+Word16 add( Word16 var1, Word16 var2 ); /* Short add, 1 */
+Word16 sub( Word16 var1, Word16 var2 ); /* Short sub, 1 */
+Word16 abs_s( Word16 var1 ); /* Short abs, 1 */
+Word16 shl( Word16 var1, Word16 var2 ); /* Short shift left, 1 */
+Word16 shr( Word16 var1, Word16 var2 ); /* Short shift right, 1 */
+Word16 mult( Word16 var1, Word16 var2 ); /* Short mult, 1 */
+Word32 L_mult( Word16 var1, Word16 var2 ); /* Long mult, 1 */
+Word16 negate( Word16 var1 ); /* Short negate, 1 */
+Word16 extract_h( Word32 L_var1 ); /* Extract high, 1 */
+Word16 extract_l( Word32 L_var1 ); /* Extract low, 1 */
+Word16 round_fx( Word32 L_var1 ); /* Round, 1 */
+Word32 L_mac( Word32 L_var3, Word16 var1, Word16 var2 ); /* Mac, 1 */
+Word32 L_msu( Word32 L_var3, Word16 var1, Word16 var2 ); /* Msu, 1 */
+Word32 DEPR_L_macNs( Word32 L_var3, Word16 var1, Word16 var2, Flag *Carry ); /* Mac without
+ sat, 1 */
+#endif /* BASOP_NOGLOB */
+
+#ifndef BASOP_NOGLOB
+Word32 L_msuNs( Word32 L_var3, Word16 var1, Word16 var2 ); /* Msu without
+ sat, 1 */
+#else /* BASOP_NOGLOB */
+Word32 DEPR_L_msuNs( Word32 L_var3, Word16 var1, Word16 var2, Flag *Carry ); /* Msu without
+ sat, 1 */
+#endif /* BASOP_NOGLOB */
+#ifndef BASOP_NOGLOB
+Word32 L_add( Word32 L_var1, Word32 L_var2 ); /* Long add, 1 */
+Word32 L_sub( Word32 L_var1, Word32 L_var2 ); /* Long sub, 1 */
+Word32 L_add_c( Word32 L_var1, Word32 L_var2 ); /* Long add with c, 2 */
+Word32 L_sub_c( Word32 L_var1, Word32 L_var2 ); /* Long sub with c, 2 */
+Word32 L_negate( Word32 L_var1 ); /* Long negate, 1 */
+Word16 mult_r( Word16 var1, Word16 var2 ); /* Mult with round, 1 */
+Word32 L_shl( Word32 L_var1, Word16 var2 ); /* Long shift left, 1 */
+Word32 L_shr( Word32 L_var1, Word16 var2 ); /* Long shift right, 1 */
+Word16 shr_r( Word16 var1, Word16 var2 ); /* Shift right with
+ round, 2 */
+#else /* BASOP_NOGLOB */
+Word32 L_add( Word32 L_var1, Word32 L_var2 ); /* Long add, 1 */
+Word32 L_sub( Word32 L_var1, Word32 L_var2 ); /* Long sub, 1 */
+Word32 DEPR_L_add_c( Word32 L_var1, Word32 L_var2, Flag *Carry ); /* Long add with c, 2 */
+Word32 DEPR_L_sub_c( Word32 L_var1, Word32 L_var2, Flag *Carry ); /* Long sub with c, 2 */
+Word32 L_negate( Word32 L_var1 ); /* Long negate, 1 */
+Word16 mult_r( Word16 var1, Word16 var2 ); /* Mult with round, 1 */
+Word32 L_shl( Word32 L_var1, Word16 var2 ); /* Long shift left, 1 */
+Word32 L_shr( Word32 L_var1, Word16 var2 ); /* Long shift right, 1 */
+Word16 shr_r( Word16 var1, Word16 var2 ); /* Shift right with
+ round, 2 */
+#endif /* BASOP_NOGLOB */
+
+#ifndef BASOP_NOGLOB
+Word16 mac_r( Word32 L_var3, Word16 var1, Word16 var2 ); /* Mac with
+ rounding, 1 */
+#else /* BASOP_NOGLOB */
+Word16 mac_r( Word32 L_var3, Word16 var1, Word16 var2 ); /* Mac with
+ rounding, 1 */
+#endif /* BASOP_NOGLOB */
+#ifndef BASOP_NOGLOB
+Word16 msu_r( Word32 L_var3, Word16 var1, Word16 var2 ); /* Msu with
+ rounding, 1 */
+#else /* BASOP_NOGLOB */
+Word16 msu_r( Word32 L_var3, Word16 var1, Word16 var2 ); /* Msu with
+ rounding, 1 */
+#endif /* BASOP_NOGLOB */
+#ifndef BASOP_NOGLOB
+Word32 L_deposit_h( Word16 var1 ); /* 16 bit var1 -> MSB, 1 */
+Word32 L_deposit_l( Word16 var1 ); /* 16 bit var1 -> LSB, 1 */
+#else /* BASOP_NOGLOB */
+Word32 L_deposit_h( Word16 var1 ); /* 16 bit var1 -> MSB, 1 */
+Word32 L_deposit_l( Word16 var1 ); /* 16 bit var1 -> LSB, 1 */
+#endif /* BASOP_NOGLOB */
+
+#ifndef BASOP_NOGLOB
+Word32 L_shr_r( Word32 L_var1, Word16 var2 ); /* Long shift right with
+ round, 3 */
+#else /* BASOP_NOGLOB */
+Word32 L_shr_r( Word32 L_var1, Word16 var2 ); /* Long shift right with
+ round, 3 */
+#endif /* BASOP_NOGLOB */
+#ifndef BASOP_NOGLOB
+Word32 L_abs( Word32 L_var1 ); /* Long abs, 1 */
+Word32 L_sat( Word32 L_var1 ); /* Long saturation, 4 */
+Word16 norm_s( Word16 var1 ); /* Short norm, 1 */
+Word16 div_s( Word16 var1, Word16 var2 ); /* Short division, 18 */
+Word16 norm_l( Word32 L_var1 ); /* Long norm, 1 */
+#else /* BASOP_NOGLOB */
+Word32 L_abs( Word32 L_var1 ); /* Long abs, 1 */
+Word32 DEPR_L_sat_co( Word32 L_var1, Flag Overflow, Flag Carry ); /* Long saturation, 4 */
+Word16 norm_s( Word16 var1 ); /* Short norm, 1 */
+Word16 div_s( Word16 var1, Word16 var2 ); /* Short division, 18 */
+Word16 norm_l( Word32 L_var1 ); /* Long norm, 1 */
+#endif /* BASOP_NOGLOB */
+
+
+/*
+ * Additional G.723.1 operators
+ */
+#ifndef BASOP_NOGLOB
+Word32 L_mls( Word32, Word16 ); /* Weight FFS; currently assigned 5 */
+Word16 div_l( Word32, Word16 ); /* Weight FFS; currently assigned 32 */
+Word16 i_mult( Word16 a, Word16 b ); /* Weight FFS; currently assigned 3 */
+#else /* BASOP_NOGLOB */
+Word32 L_mls( Word32, Word16 ); /* Weight FFS; currently assigned 5 */
+Word16 div_l( Word32, Word16 ); /* Weight FFS; currently assigned 32 */
+Word16 DEPR_i_mult( Word16 a, Word16 b ); /* Weight FFS; currently assigned 3 */
+#endif /* BASOP_NOGLOB */
+
+/*
+ * New shiftless operators, not used in G.729/G.723.1
+ */
+Word32 L_mult0( Word16 v1, Word16 v2 ); /* 32-bit Multiply w/o shift 1 */
+Word32 L_mac0( Word32 L_v3, Word16 v1, Word16 v2 ); /* 32-bit Mac w/o shift 1 */
+Word32 L_msu0( Word32 L_v3, Word16 v1, Word16 v2 ); /* 32-bit Msu w/o shift 1 */
+#ifdef BASOP_NOGLOB
+
+/*
+ * Overflowing operators
+ */
+Word16 add_o( Word16 var1, Word16 var2, Flag *Overflow );
+Word16 sub_o( Word16 var1, Word16 var2, Flag *Overflow );
+Word16 shl_o( Word16 var1, Word16 var2, Flag *Overflow );
+Word16 mult_o( Word16 var1, Word16 var2, Flag *Overflow );
+Word32 L_mult_o( Word16 var1, Word16 var2, Flag *Overflow );
+Word16 round_fx_o( Word32 L_var1, Flag *Overflow );
+Word32 L_mac_o( Word32 L_var3, Word16 var1, Word16 var2, Flag *Overflow );
+Word32 L_msu_o( Word32 L_var3, Word16 var1, Word16 var2, Flag *Overflow );
+Word32 L_add_o( Word32 L_var1, Word32 L_var2, Flag *Overflow );
+Word32 L_sub_o( Word32 L_var1, Word32 L_var2, Flag *Overflow );
+Word32 L_shr_o( Word32 L_var1, Word16 var2, Flag *Overflow );
+Word32 L_shl_o( Word32 L_var1, Word16 var2, Flag *Overflow );
+Word32 L_mls_o( Word32 Lv, Word16 v, Flag *Overflow );
+Word32 L_mac0_o( Word32 L_var3, Word16 var1, Word16 var2, Flag *Overflow );
+Word32 L_msu0_o( Word32 L_var3, Word16 var1, Word16 var2, Flag *Overflow );
+Word16 mult_ro( Word16 var1, Word16 var2, Flag *Overflow );
+Word16 mac_ro( Word32 L_var3, Word16 var1, Word16 var2, Flag *Overflow );
+Word16 msu_ro( Word32 L_var3, Word16 var1, Word16 var2, Flag *Overflow );
+#endif /* BASOP_NOGLOB */
+
+
+#endif /* ifndef _BASIC_OP_H */
+
+
+/* end of file */
diff --git a/lib_com/basop_com_lpc.c b/lib_com/basop_com_lpc.c
new file mode 100644
index 0000000000000000000000000000000000000000..abdd1f4a69f7a55d94c653aba263717abf1e2921
--- /dev/null
+++ b/lib_com/basop_com_lpc.c
@@ -0,0 +1,263 @@
+/******************************************************************************************************
+
+ (C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
+ Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
+ Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
+ Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
+ contributors to this repository. All Rights Reserved.
+
+ This software is protected by copyright law and by international treaties.
+ The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
+ Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
+ Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
+ Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
+ contributors to this repository retain full ownership rights in their respective contributions in
+ the software. This notice grants no license of any kind, including but not limited to patent
+ license, nor is any license granted by implication, estoppel or otherwise.
+
+ Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
+ contributions.
+
+ This software is provided "AS IS", without any express or implied warranties. The software is in the
+ development stage. It is intended exclusively for experts who have experience with such software and
+ solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
+ and fitness for a particular purpose are hereby disclaimed and excluded.
+
+ Any dispute, controversy or claim arising under or in relation to providing this software shall be
+ submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
+ accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
+ the United Nations Convention on Contracts on the International Sales of Goods.
+
+*******************************************************************************************************/
+
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include
+#include
+#include "options.h"
+#include "typedef.h"
+#include "basop_proto_func.h"
+#include "cnst.h"
+#include "basop_util.h"
+#include "stl.h"
+
+#define WMC_TOOL_SKIP
+
+#define UNROLL_CHEBYSHEV_INNER_LOOP
+#define NC_MAX 8
+#define GUESS_TBL_SZ 256
+
+#define Madd_32_16( accu, x, y ) L_add( accu, Mpy_32_16( x, y ) )
+#define Msub_32_16( accu, x, y ) L_sub( accu, Mpy_32_16( x, y ) )
+
+
+/*
+ * weight_a
+ *
+ * Parameters:
+ * a I: LP filter coefficients Q12
+ * ap O: weighted LP filter coefficients Q12
+ * gamma I: weighting factor Q15
+ *
+ * Function:
+ * Weighting of LP filter coefficients, ap[i] = a[i] * (gamma^i).
+ *
+ * Returns:
+ * void
+ */
+void basop_weight_a( const Word16 *a, Word16 *ap, const Word16 gamma )
+{
+ Word16 i, fac;
+ Word32 Amax;
+ Word16 shift;
+
+
+ fac = gamma;
+ Amax = L_mult( 16384, a[0] );
+ FOR( i = 1; i < M; i++ )
+ {
+ Amax = L_max( Amax, L_abs( L_mult0( fac, a[i] ) ) );
+ fac = mult_r( fac, gamma );
+ }
+ Amax = L_max( Amax, L_abs( L_mult0( fac, a[M] ) ) );
+ shift = norm_l( Amax );
+ fac = gamma;
+ ap[0] = shl( a[0], sub( shift, 1 ) );
+ move16();
+ FOR( i = 1; i < M; i++ )
+ {
+ ap[i] = round_fx( L_shl( L_mult0( a[i], fac ), shift ) );
+ move16();
+ fac = mult_r( fac, gamma );
+ }
+ ap[M] = round_fx( L_shl( L_mult0( a[M], fac ), shift ) );
+ move16();
+
+
+ return;
+}
+
+/*
+ * weight_a_inv
+ *
+ * Parameters:
+ * a I: LP filter coefficients Q12
+ * ap O: weighted LP filter coefficients Q12
+ * inv_gamma I: inverse weighting factor Q14
+ *
+ * Function:
+ * Weighting of LP filter coefficients, ap[i] = a[i] * (inv_gamma^i).
+ *
+ * Returns:
+ * void
+ */
+void basop_weight_a_inv( const Word16 *a, Word16 *ap, const Word16 inv_gamma )
+{
+ Word16 i;
+ static const Word16 inv_gamma_tab_12k8[16] = { 17809, 19357, 21041, 22870, 24859, 27020, 29370, 31924, /* Q14 */
+ 17350, 18859, 20499, 22281, 24219, 26325, 28614, 31102 }; /* Q13 */
+ static const Word16 inv_gamma_tab_16k[16] = { 17430, 18542, 19726, 20985, 22324, 23749, 25265, 26878, /* Q14 */
+ 14297, 15209, 16180, 17213, 18312, 19480, 20724, 22047 }; /* Q13 */
+ const Word16 *inv_gamma_tab;
+ Word32 L_tmp;
+ Word32 Amax;
+ Word16 shift;
+
+
+ IF( inv_gamma == 16384 )
+ {
+ FOR( i = 0; i <= M; i++ )
+ {
+ ap[i] = a[i];
+ move16();
+ }
+ return;
+ }
+
+ assert( inv_gamma == GAMMA1_INV || inv_gamma == GAMMA16k_INV );
+
+ inv_gamma_tab = inv_gamma_tab_12k8;
+ move16();
+ if ( sub( inv_gamma, GAMMA16k_INV ) == 0 )
+ {
+ inv_gamma_tab = inv_gamma_tab_16k;
+ move16();
+ }
+
+ Amax = L_mult( 16384, a[0] );
+ FOR( i = 1; i < 9; i++ )
+ {
+ Amax = L_max( Amax, L_abs( L_mult( a[i], inv_gamma_tab[i - 1] ) ) );
+ }
+ FOR( i = 9; i < 17; i++ )
+ {
+ Amax = L_max( Amax, L_abs( L_shl( L_mult( a[i], inv_gamma_tab[i - 1] ), 1 ) ) );
+ }
+ shift = norm_l( Amax );
+ ap[0] = shl( a[0], sub( shift, 1 ) );
+ move16();
+ FOR( i = 1; i < 9; i++ )
+ {
+ L_tmp = L_mult( a[i], inv_gamma_tab[i - 1] );
+ ap[i] = round_fx( L_shl( L_tmp, shift ) );
+ move16();
+ }
+ shift = add( shift, 1 );
+ FOR( i = 9; i < 17; i++ )
+ {
+ L_tmp = L_mult( a[i], inv_gamma_tab[i - 1] );
+ ap[i] = round_fx( L_shl( L_tmp, shift ) );
+ move16();
+ }
+
+
+ return;
+}
+
+/*
+ * basop_E_LPC_a_add_tilt
+ *
+ * Parameters:
+ * a I: LP filter coefficients (m+1 coeffs)
+ * ap O: modified LP filter coefficients (m+2 coeffs)
+ * gamma I: tilt factor
+ *
+ * Function:
+ * Modified LP filter by adding 1st order pre-premphasis, Ap(z)=A(z).(1-gamma.z^(-1))
+ *
+ * Returns:
+ * void
+ */
+void basop_E_LPC_a_add_tilt( const Word16 *a, Word16 *ap, Word16 gamma )
+{
+ Word16 i;
+ Word32 Amax, Atmp[M + 2];
+ Word16 shift;
+
+
+ Amax = L_mult( 16384, a[0] );
+ FOR( i = 1; i <= M; i++ )
+ {
+ Atmp[i] = L_sub( L_mult( 16384, a[i] ), L_mult0( gamma, a[i - 1] ) );
+ move32();
+ Amax = L_max( Amax, L_abs( Atmp[i] ) );
+ }
+ Atmp[M + 1] = L_negate( L_mult0( gamma, a[M] ) );
+ move32();
+ Amax = L_max( Amax, L_abs( Atmp[M + 1] ) );
+ shift = norm_l( Amax );
+ ap[0] = shl( a[0], sub( shift, 1 ) );
+ move16();
+ FOR( i = 1; i <= M; i++ )
+ {
+ ap[i] = round_fx( L_shl( Atmp[i], shift ) );
+ move16();
+ }
+ ap[M + 1] = round_fx( L_shl( Atmp[M + 1], shift ) );
+ move16();
+
+ return;
+}
+
+
+static Word16 xsf_to_xsp( Word16 xsf )
+{
+ /* xsp = cos(xsf * 3.1415/6400); */
+ return getCosWord16R2( xsf );
+}
+
+/*
+ * lsf2lsp
+ *
+ * Parameters:
+ * lsf I: lsf[m] normalized (range: 0 <= val <= 0.5) x2.56
+ * lsp O: lsp[m] (range: -1 <= val < 1) Q15
+ *
+ * Function:
+ * Transformation lsf to lsp
+ *
+ * LSF are line spectral pair in frequency domain (0 to 6400).
+ * LSP are line spectral pair in cosine domain (-1 to 1).
+ *
+ * Returns:
+ * void
+ */
+void basop_lsf2lsp( const Word16 lsf[], Word16 lsp[] )
+{
+ Word16 i;
+
+
+ /* convert ISFs to the cosine domain */
+ FOR( i = 0; i < M; i++ )
+ {
+ *lsp++ = xsf_to_xsp( *lsf++ );
+ move16();
+ }
+
+
+ return;
+}
+
+#undef WMC_TOOL_SKIP
diff --git a/lib_com/basop_lsf_tools.c b/lib_com/basop_lsf_tools.c
new file mode 100644
index 0000000000000000000000000000000000000000..bf1555a8207ba5decd2e65911302ec4333e7f225
--- /dev/null
+++ b/lib_com/basop_lsf_tools.c
@@ -0,0 +1,313 @@
+/******************************************************************************************************
+
+ (C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
+ Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
+ Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
+ Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
+ contributors to this repository. All Rights Reserved.
+
+ This software is protected by copyright law and by international treaties.
+ The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
+ Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
+ Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
+ Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
+ contributors to this repository retain full ownership rights in their respective contributions in
+ the software. This notice grants no license of any kind, including but not limited to patent
+ license, nor is any license granted by implication, estoppel or otherwise.
+
+ Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
+ contributions.
+
+ This software is provided "AS IS", without any express or implied warranties. The software is in the
+ development stage. It is intended exclusively for experts who have experience with such software and
+ solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
+ and fitness for a particular purpose are hereby disclaimed and excluded.
+
+ Any dispute, controversy or claim arising under or in relation to providing this software shall be
+ submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
+ accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
+ the United Nations Convention on Contracts on the International Sales of Goods.
+
+*******************************************************************************************************/
+
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include
+#include
+#include "options.h"
+#include "basop_proto_func.h"
+#include "basop_util.h"
+
+#define WMC_TOOL_SKIP
+
+#define NC_MAX 8
+
+static Word16 E_LPC_f_lsp_pol_get( const Word16 lsp[], Word32 f[], const Word16 n, const Word16 past_Ovf, const Word16 isMODE1 );
+
+
+/*
+ * E_LPC_f_lsp_a_conversion
+ *
+ * Parameters:
+ * lsp I: Line spectral pairs Q15
+ * a O: Predictor coefficients (order = m) Qx (The Q factor of the output to be deduced from a(0))
+ * m I: order of LP filter
+ *
+ * Function:
+ * Convert ISPs to predictor coefficients a[]
+ *
+ * Returns:
+ * void
+ */
+void basop_E_LPC_f_lsp_a_conversion(
+ const Word16 *lsp,
+ Word16 *a,
+ const Word16 m )
+{
+ Word16 i, j, k;
+ Word32 f1[NC_MAX + 1], f2[NC_MAX + 1];
+ Word16 nc;
+ Word32 t0;
+ Word16 Ovf, Ovf2;
+
+
+ /*-----------------------------------------------------*
+ * Find the polynomials F1(z) and F2(z) *
+ *-----------------------------------------------------*/
+
+ nc = shr( m, 1 );
+
+ assert( m == 16 || m == 10 );
+
+ Ovf = 0;
+ move16();
+ Ovf = E_LPC_f_lsp_pol_get( &lsp[0], f1, nc, Ovf, 1 );
+ Ovf2 = E_LPC_f_lsp_pol_get( &lsp[1], f2, nc, Ovf, 1 );
+ IF( sub( Ovf2, Ovf ) != 0 )
+ {
+ /* to ensure similar scaling for f1 and f2 in case
+ an overflow would be detected only in f2,
+ but this case never happen on my dtb */
+ E_LPC_f_lsp_pol_get( &lsp[0], f1, nc, s_max( Ovf2, Ovf ), 1 );
+ }
+ /*-----------------------------------------------------*
+ * Multiply F1(z) by (1+z^-1) and F2(z) by (1-z^-1) *
+ *-----------------------------------------------------*/
+ /*modification*/
+ k = sub( nc, 1 );
+ FOR( i = 0; i <= k; i++ )
+ {
+ f1[nc - i] = L_add( f1[nc - i], f1[nc - i - 1] );
+ move32();
+ f2[nc - i] = L_sub( f2[nc - i], f2[nc - i - 1] );
+ move32();
+ }
+
+ /*-----------------------------------------------------*
+ * A(z) = (F1(z)+F2(z))/2 *
+ * F1(z) is symmetric and F2(z) is antisymmetric *
+ *-----------------------------------------------------*/
+
+ t0 = L_deposit_l( 0 );
+ FOR( i = 1; i <= nc; i++ )
+ {
+ t0 = L_max( t0, L_abs( L_add( f1[i], f2[i] ) ) );
+ t0 = L_max( t0, L_abs( L_sub( f1[i], f2[i] ) ) );
+ }
+ k = s_min( norm_l( t0 ), 6 );
+ a[0] = shl( 256, k );
+ move16();
+ test();
+ IF( Ovf || Ovf2 )
+ {
+ a[0] = shl( 256, sub( k, Ovf ) );
+ move16();
+ }
+ j = m;
+ FOR( i = 1; i <= nc; i++ )
+ {
+ /* a[i] = 0.5*(f1[i] + f2[i]) */
+ t0 = L_add( f1[i], f2[i] );
+ t0 = L_shl( t0, k );
+ a[i] = round_fx( t0 ); /* from Q23 to Qx and * 0.5 */
+
+ /* a[j] = 0.5*(f1[i] - f2[i]) */
+ t0 = L_sub( f1[i], f2[i] );
+ t0 = L_shl( t0, k );
+ a[j] = round_fx( t0 ); /* from Q23 to Qx and * 0.5 */
+ j--;
+ }
+
+ return;
+}
+
+
+/*---------------------------------------------------------------------------
+ * procedure reorder_lsf()
+ *
+ * To make sure that the lsfs are properly ordered and to keep a certain
+ * minimum distance between consecutive lsfs.
+ *--------------------------------------------------------------------------*/
+void basop_reorder_lsf(
+ Word16 *lsf, /* i/o: LSFs in the frequency domain (0..0.5) Q(x2.56)*/
+ const Word16 min_dist, /* i : minimum required distance x2.56*/
+ const Word16 n, /* i : LPC order */
+ const Word32 Fs /* i : sampling frequency */
+)
+{
+ Word16 i, lsf_min, n_m_1;
+ Word16 lsf_max;
+
+ lsf_min = min_dist;
+ move16();
+
+ /*-----------------------------------------------------------------------*
+ * Verify the LSF ordering and minimum GAP
+ *-----------------------------------------------------------------------*/
+
+ FOR( i = 0; i < n; i++ )
+ {
+ if ( sub( lsf[i], lsf_min ) < 0 )
+ {
+ lsf[i] = lsf_min;
+ move16();
+ }
+ lsf_min = add( lsf[i], min_dist );
+ }
+
+ /*-----------------------------------------------------------------------*
+ * Reverify the LSF ordering and minimum GAP in the reverse order (security)
+ *-----------------------------------------------------------------------*/
+
+ lsf_max = round_fx( L_sub( L_shr( L_mult0( extract_l( L_shr( Fs, 1 ) ), 1311 ), 9 - 16 ), L_deposit_h( min_dist ) ) ); /* Q0 + Q9 , 1311 is 2.56 in Q9 */
+
+ n_m_1 = sub( n, 1 );
+ IF( sub( lsf[n_m_1], lsf_max ) > 0 ) /* If danger of unstable filter in case of resonance in HF */
+ {
+ FOR( i = n_m_1; i >= 0; i-- ) /* Reverify the minimum LSF gap in the reverse direction */
+ {
+ if ( sub( lsf[i], lsf_max ) > 0 )
+ {
+ lsf[i] = lsf_max;
+ move16();
+ }
+ lsf_max = sub( lsf[i], min_dist );
+ }
+ }
+
+ return;
+}
+
+
+/*
+ * E_LPC_f_lsp_pol_get
+ *
+ * Parameters:
+ * lsp/isp I: Line spectral pairs (cosine domaine) Q15
+ * f O: the coefficients of F1 or F2 Q23
+ * n I: no of coefficients (m/2)
+ * == NC for F1(z); == NC-1 for F2(z)
+ * fact I: scaling factor
+ *
+ *-----------------------------------------------------------*
+ * procedure E_LPC_f_lsp_pol_get: *
+ * ~~~~~~~~~~~ *
+ * Find the polynomial F1(z) or F2(z) from the LSPs. *
+ * This is performed by expanding the product polynomials: *
+ * *
+ * F1(z) = product ( 1 - 2 LSF_i z^-1 + z^-2 ) *
+ * i=0,2,4,6,8 *
+ * F2(z) = product ( 1 - 2 LSF_i z^-1 + z^-2 ) *
+ * i=1,3,5,7,9 *
+ * *
+ * where LSP_i are the LSPs in the cosine domain. *
+ * *
+ *-----------------------------------------------------------*
+ * R.A.Salami October 1990 *
+ *-----------------------------------------------------------*
+ */
+static Word16 E_LPC_f_lsp_pol_get(
+ const Word16 lsp[],
+ Word32 f[],
+ const Word16 n,
+ const Word16 past_Ovf,
+ const Word16 isMODE1 )
+{
+ /* All computation in Q23 */
+ const Word16 *plsp;
+ Word16 i, j;
+ Word16 b;
+ Word32 b32;
+ Word16 Ovf = 0;
+ Word16 Q_out;
+ Word16 m2;
+#ifdef BASOP_NOGLOB
+ Flag Overflow;
+#endif /* BASOP_NOGLOB */
+
+
+ Q_out = 31 - 23;
+ move16();
+ Ovf = past_Ovf;
+ move16();
+
+ test();
+ if ( past_Ovf && isMODE1 ) /* Currently this feature is implemented only in MODE1 */
+ {
+ /* In some NB cases, overflow where detectected
+ in f1 or f2 polynomial computation when it
+ happen we reduce the precision of the computing
+ to limit the risk of saturation*/
+ Q_out = add( Q_out, past_Ovf );
+ }
+ Overflow = 0;
+ move16();
+ plsp = lsp;
+ f[0] = L_shl( 1, sub( 31, Q_out ) );
+ move32();
+ /*b = -2.0f * *plsp;*/
+ b = *plsp;
+ move16();
+ m2 = shl( -2, sub( 15, Q_out ) );
+ f[1] = L_mult( b, m2 );
+ move32();
+
+ FOR( i = 2; i <= n; i++ )
+ {
+ plsp += 2;
+ /*b = 2.0f * *plsp;*/
+ move16();
+ b = *plsp;
+ b32 = L_mult( b, m2 );
+
+ /*f[i] = -b*f[i-1] + 2.0f*f[i-2];*/
+ move32();
+ f[i] = L_shl( L_sub( f[i - 2], Mpy_32_16( f[i - 1], b ) ), 1 );
+
+ FOR( j = i - 1; j > 1; j-- )
+ {
+ /*f[j] += b*f[j-1] + f[j-2];*/
+ move32();
+ f[j] = L_add( f[j], L_sub( f[j - 2], L_shl( Mpy_32_16( f[j - 1], b ), 1 ) ) );
+ }
+ move32();
+ f[1] = L_add( f[1], b32 );
+ }
+
+
+ test();
+ IF( Overflow > 0 && isMODE1 )
+ {
+#ifdef BASOP_NOGLOB
+ assert( 0 );
+#endif /* BASOP_NOGLOB */
+ /* If an overflow is detected, redo the computation with 1 bit less */
+ Ovf = add( Ovf, 1 );
+ Ovf = E_LPC_f_lsp_pol_get( lsp, f, n, Ovf, isMODE1 );
+ }
+ return Ovf;
+}
+
+#undef WMC_TOOL_SKIP
diff --git a/lib_com/basop_mpy.c b/lib_com/basop_mpy.c
new file mode 100644
index 0000000000000000000000000000000000000000..17c5347d0f409b3651b176ea36e82e1b7b13bc7f
--- /dev/null
+++ b/lib_com/basop_mpy.c
@@ -0,0 +1,92 @@
+/******************************************************************************************************
+
+ (C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
+ Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
+ Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
+ Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
+ contributors to this repository. All Rights Reserved.
+
+ This software is protected by copyright law and by international treaties.
+ The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
+ Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
+ Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
+ Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
+ contributors to this repository retain full ownership rights in their respective contributions in
+ the software. This notice grants no license of any kind, including but not limited to patent
+ license, nor is any license granted by implication, estoppel or otherwise.
+
+ Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
+ contributions.
+
+ This software is provided "AS IS", without any express or implied warranties. The software is in the
+ development stage. It is intended exclusively for experts who have experience with such software and
+ solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
+ and fitness for a particular purpose are hereby disclaimed and excluded.
+
+ Any dispute, controversy or claim arising under or in relation to providing this software shall be
+ submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
+ accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
+ the United Nations Convention on Contracts on the International Sales of Goods.
+
+*******************************************************************************************************/
+
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include "basop_mpy.h"
+#include
+#include "options.h"
+#ifdef DEBUGGING
+#include "debug.h"
+#endif
+
+#define WMC_TOOL_SKIP
+
+Word32 Mpy_32_16_1( Word32 x, Word16 y )
+{
+ Word32 mh;
+ UWord16 ml;
+
+ Mpy_32_16_ss( x, y, &mh, &ml );
+
+ return ( mh );
+}
+
+Word32 Mpy_32_16( Word32 x, Word16 y )
+{
+ Word32 mh;
+ UWord16 ml;
+
+ Mpy_32_16_ss( x, y, &mh, &ml );
+
+ return ( mh );
+}
+
+Word32 Mpy_32_16_r( Word32 x, Word16 y )
+{
+ Word32 mh;
+ UWord16 ml;
+
+ Mpy_32_16_ss( x, y, &mh, &ml );
+
+ if ( s_and( ml, -32768 /* 0x8000 */ ) )
+ {
+ mh = L_add( mh, 1 );
+ }
+
+ return ( mh );
+}
+
+
+Word32 Mpy_32_32( Word32 x, Word32 y )
+{
+ Word32 mh;
+ UWord32 ml;
+
+ Mpy_32_32_ss( x, y, &mh, &ml );
+
+ return ( mh );
+}
+
+#undef WMC_TOOL_SKIP
diff --git a/lib_com/basop_mpy.h b/lib_com/basop_mpy.h
new file mode 100644
index 0000000000000000000000000000000000000000..726bf7ed3e8dab947a852d99a9a76acd08606930
--- /dev/null
+++ b/lib_com/basop_mpy.h
@@ -0,0 +1,100 @@
+/******************************************************************************************************
+
+ (C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
+ Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
+ Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
+ Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
+ contributors to this repository. All Rights Reserved.
+
+ This software is protected by copyright law and by international treaties.
+ The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
+ Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
+ Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
+ Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
+ contributors to this repository retain full ownership rights in their respective contributions in
+ the software. This notice grants no license of any kind, including but not limited to patent
+ license, nor is any license granted by implication, estoppel or otherwise.
+
+ Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
+ contributions.
+
+ This software is provided "AS IS", without any express or implied warranties. The software is in the
+ development stage. It is intended exclusively for experts who have experience with such software and
+ solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
+ and fitness for a particular purpose are hereby disclaimed and excluded.
+
+ Any dispute, controversy or claim arising under or in relation to providing this software shall be
+ submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
+ accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
+ the United Nations Convention on Contracts on the International Sales of Goods.
+
+*******************************************************************************************************/
+
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#ifndef __BASOP_MPY_H
+#define __BASOP_MPY_H
+
+#include "stl.h"
+#include
+#include "options.h"
+#ifdef DEBUGGING
+#include "debug.h"
+#endif
+
+/**
+ * \brief 32*16 Bit fractional Multiplication using 40 bit OPS
+ * Performs a multiplication of a 32-bit variable x by
+ * a 16-bit variable y, returning a 32-bit value.
+ *
+ * \param[i] x
+ * \param[i] y
+ *
+ * \return x*y
+ */
+Word32 Mpy_32_16_1( Word32 x, Word16 y );
+
+
+/**
+ * \brief 32*16 Bit fractional Multiplication using 40 bit OPS
+ * Performs a multiplication of a 32-bit variable x by
+ * a 16-bit variable y, returning a 32-bit value.
+ *
+ * \param[i] x
+ * \param[i] y
+ *
+ * \return x*y
+ */
+Word32 Mpy_32_16( Word32 x, Word16 y );
+
+
+/**
+ * \brief 32*16 Bit fractional Multiplication using 40 bit OPS
+ * Performs a multiplication of a 32-bit variable x by
+ * a 16-bit variable y including rounding, returning a 32-bit value.
+ *
+ * \param[i] x
+ * \param[i] y
+ *
+ * \return x*y
+ */
+Word32 Mpy_32_16_r( Word32 x, Word16 y );
+
+
+/**
+ * \brief 32*32 Bit fractional Multiplication using 40 bit OPS
+ *
+ * Performs a multiplication of a 32-bit variable x by
+ * a 32-bit variable y, returning a 32-bit value.
+ *
+ * \param[i] x
+ * \param[i] y
+ *
+ * \return x*y
+ */
+
+Word32 Mpy_32_32( Word32 x, Word32 y );
+
+#endif /* __BASOP_SETTINGS_H */
diff --git a/lib_com/basop_proto_func.h b/lib_com/basop_proto_func.h
new file mode 100644
index 0000000000000000000000000000000000000000..d8b9768a100ba661a77943698f2af6b0f2eb9b33
--- /dev/null
+++ b/lib_com/basop_proto_func.h
@@ -0,0 +1,70 @@
+/******************************************************************************************************
+
+ (C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
+ Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
+ Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
+ Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
+ contributors to this repository. All Rights Reserved.
+
+ This software is protected by copyright law and by international treaties.
+ The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
+ Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
+ Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
+ Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
+ contributors to this repository retain full ownership rights in their respective contributions in
+ the software. This notice grants no license of any kind, including but not limited to patent
+ license, nor is any license granted by implication, estoppel or otherwise.
+
+ Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
+ contributions.
+
+ This software is provided "AS IS", without any express or implied warranties. The software is in the
+ development stage. It is intended exclusively for experts who have experience with such software and
+ solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
+ and fitness for a particular purpose are hereby disclaimed and excluded.
+
+ Any dispute, controversy or claim arising under or in relation to providing this software shall be
+ submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
+ accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
+ the United Nations Convention on Contracts on the International Sales of Goods.
+
+*******************************************************************************************************/
+
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#ifndef BASOP_PROTO_FUNC_H
+#define BASOP_PROTO_FUNC_H
+
+#include
+#include "options.h"
+#include "stl.h"
+#include "basop_util.h"
+
+
+/* tcx_lpc_cdk.h */
+#define LSF_GAP_VAL( x ) ( Word16 )( (x) *2.0f * 1.28f )
+#define LSFM( x ) FL2WORD16_SCALE( x * 1.28, 15 - 1 ) /* 14Q1*1.28 */
+
+/* cnst.h */
+#define GAMMA1_INV 17809 /* weighting factor (numerator) default:0.92 (1Q14format) */
+#define GAMMA16k_INV 17430 /* weighting factor (numerator) default:0.94 (1Q14format) */
+#define INT_FS_FX 12800 /* internal sampling frequency */
+
+void basop_lsp2a_stab( const Word16 *lsp, Word16 *a );
+void basop_lsf2lsp( const Word16 lsf[], Word16 lsp[] );
+void basop_weight_a( const Word16 *a, Word16 *ap, const Word16 gamma );
+void basop_weight_a_inv( const Word16 *a, Word16 *ap, const Word16 inv_gamma );
+void basop_E_LPC_a_add_tilt( const Word16 *a, Word16 *ap, Word16 gamma );
+void basop_reorder_lsf( Word16 *lsf, const Word16 min_dist, const Word16 n, const Word32 Fs );
+void basop_E_LPC_f_lsp_a_conversion( const Word16 *lsp, Word16 *a, const Word16 m );
+
+/* tcx_utils.c */
+void basop_lpc2mdct( Word16 *lpcCoeffs, Word16 lpcOrder, Word16 *mdct_gains, Word16 *mdct_gains_exp, Word16 *mdct_inv_gains, Word16 *mdct_inv_gains_exp );
+
+void basop_PsychAdaptLowFreqDeemph( Word32 x[], const Word16 lpcGains[], const Word16 lpcGains_e[], Word16 lf_deemph_factors[] );
+void basop_mdct_noiseShaping_interp( Word32 x[], Word16 lg, Word16 gains[], Word16 gains_exp[] );
+
+
+#endif
diff --git a/lib_com/basop_settings.h b/lib_com/basop_settings.h
new file mode 100644
index 0000000000000000000000000000000000000000..59d871029e1f7ad8aa8c15c9035aade8ece1c5a3
--- /dev/null
+++ b/lib_com/basop_settings.h
@@ -0,0 +1,110 @@
+/******************************************************************************************************
+
+ (C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
+ Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
+ Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
+ Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
+ contributors to this repository. All Rights Reserved.
+
+ This software is protected by copyright law and by international treaties.
+ The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
+ Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
+ Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
+ Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
+ contributors to this repository retain full ownership rights in their respective contributions in
+ the software. This notice grants no license of any kind, including but not limited to patent
+ license, nor is any license granted by implication, estoppel or otherwise.
+
+ Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
+ contributions.
+
+ This software is provided "AS IS", without any express or implied warranties. The software is in the
+ development stage. It is intended exclusively for experts who have experience with such software and
+ solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
+ and fitness for a particular purpose are hereby disclaimed and excluded.
+
+ Any dispute, controversy or claim arising under or in relation to providing this software shall be
+ submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
+ accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
+ the United Nations Convention on Contracts on the International Sales of Goods.
+
+*******************************************************************************************************/
+
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#ifndef __BASOP_SETTINGS_H
+#define __BASOP_SETTINGS_H
+
+#include
+#include "options.h"
+#include "stl.h"
+#include "basop_mpy.h"
+
+#define WORD32_BITS 32
+#define MAXVAL_WORD32 ( (int32_t) 0x7FFFFFFF )
+#define MINVAL_WORD32 ( (int32_t) 0x80000000 )
+#define WORD32_FIX_SCALE ( (int64_t) ( 1 ) << ( WORD32_BITS - 1 ) )
+
+#define WORD16_BITS 16
+#define MAXVAL_WORD16 ( ( (int32_t) 0x7FFFFFFF ) >> 16 )
+#define MINVAL_WORD16 ( ( (int32_t) 0x80000000 ) >> 16 )
+#define WORD16_FIX_SCALE ( (int64_t) ( 1 ) << ( WORD16_BITS - 1 ) )
+
+#ifdef _MSC_VER
+#pragma warning( disable : 4310 )
+#endif
+
+/*!
+ \def Macro converts a float < 1 to Word32 fixed point with saturation and rounding
+*/
+#define FL2WORD32( val ) \
+ ( Word32 )( ( ( val ) >= 0 ) ? ( ( ( (double) ( val ) * ( WORD32_FIX_SCALE ) + 0.5 ) >= (double) ( MAXVAL_WORD32 ) ) ? (int32_t) ( MAXVAL_WORD32 ) : (int32_t) ( (double) ( val ) * (double) ( WORD32_FIX_SCALE ) + 0.5 ) ) : ( ( ( (double) ( val ) * (WORD32_FIX_SCALE) -0.5 ) <= (double) ( MINVAL_WORD32 ) ) ? (int32_t) ( MINVAL_WORD32 ) : (int32_t) ( (double) ( val ) * (double) (WORD32_FIX_SCALE) -0.5 ) ) )
+
+/*!
+ \def Macro converts a float < 1 to Word16 fixed point with saturation and rounding
+*/
+#define FL2WORD16( val ) \
+ ( Word16 )( ( ( val ) >= 0 ) ? ( ( ( (double) ( val ) * ( WORD16_FIX_SCALE ) + 0.5 ) >= (double) ( MAXVAL_WORD16 ) ) ? (int32_t) ( MAXVAL_WORD16 ) : (int32_t) ( (double) ( val ) * (double) ( WORD16_FIX_SCALE ) + 0.5 ) ) : ( ( ( (double) ( val ) * (WORD16_FIX_SCALE) -0.5 ) <= (double) ( MINVAL_WORD16 ) ) ? (int32_t) ( MINVAL_WORD16 ) : (int32_t) ( (double) ( val ) * (double) (WORD16_FIX_SCALE) -0.5 ) ) )
+
+/*!
+ \def Macro converts a Word32 fixed point to Word16 fixed point <1 with saturation
+*/
+#define WORD322WORD16( val ) \
+ ( ( ( ( ( ( val ) >> ( WORD32_BITS - WORD16_BITS - 1 ) ) + 1 ) > ( ( (int32_t) 1 << WORD16_BITS ) - 1 ) ) && ( (int32_t) ( val ) > 0 ) ) ? (Word16) (int16_t) ( ( (int32_t) 1 << ( WORD16_BITS - 1 ) ) - 1 ) : (Word16) (int16_t) ( ( ( ( val ) >> ( WORD32_BITS - WORD16_BITS - 1 ) ) + 1 ) >> 1 ) )
+
+/*!
+ \def Macro converts a Word32 fixed point < 1 to float shifts result left by scale
+*/
+#define WORD322FL_SCALE( x, scale ) ( ( (float) ( (int32_t) ( x ) ) ) / ( (int64_t) 1 << ( WORD32_BITS - 1 - ( scale ) ) ) )
+
+/*!
+ \def Macro converts a float < 1 to Word32 fixed point with saturation and rounding, shifts result right by scale
+*/
+/* Note: Both x and scale must be constants at compile time, scale must be in range -31..31 */
+#define FL2WORD32_SCALE( x, scale ) FL2WORD32( (double) ( x ) * ( (int64_t) 1 << ( WORD32_BITS - 1 - ( scale ) ) ) / ( (int64_t) 1 << ( WORD32_BITS - 1 ) ) )
+
+/*!
+ \def Macro converts a Word16 fixed point < 1 to float shifts result left by scale
+*/
+#define WORD162FL_SCALE( x, scale ) ( ( (float) ( (int32_t) ( x ) ) ) / ( (int64_t) 1 << ( WORD16_BITS - 1 - ( scale ) ) ) )
+
+/*!
+ \def Macro converts a float < 1 to Word16 fixed point with saturation and rounding, shifts result right by scale
+*/
+/* Note: At compile time, x must be a float constant and scale must be an integer constant in range -15..15 */
+#define FL2WORD16_SCALE( x, scale ) FL2WORD16( (float) ( x ) * ( (int64_t) 1 << ( WORD16_BITS - 1 - ( scale ) ) ) / ( (int64_t) 1 << ( WORD16_BITS - 1 ) ) )
+
+
+/* Word16 Packed Type */
+typedef struct
+{
+ struct
+ {
+ Word16 re;
+ Word16 im;
+ } v;
+} PWord16;
+
+#endif /* __BASOP_SETTINGS_H */
diff --git a/lib_com/basop_tcx_utils.c b/lib_com/basop_tcx_utils.c
new file mode 100644
index 0000000000000000000000000000000000000000..660f4ece53285072ee51ee290df2c9e16bd4f4b0
--- /dev/null
+++ b/lib_com/basop_tcx_utils.c
@@ -0,0 +1,441 @@
+/******************************************************************************************************
+
+ (C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
+ Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
+ Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
+ Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
+ contributors to this repository. All Rights Reserved.
+
+ This software is protected by copyright law and by international treaties.
+ The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
+ Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
+ Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
+ Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
+ contributors to this repository retain full ownership rights in their respective contributions in
+ the software. This notice grants no license of any kind, including but not limited to patent
+ license, nor is any license granted by implication, estoppel or otherwise.
+
+ Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
+ contributions.
+
+ This software is provided "AS IS", without any express or implied warranties. The software is in the
+ development stage. It is intended exclusively for experts who have experience with such software and
+ solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
+ and fitness for a particular purpose are hereby disclaimed and excluded.
+
+ Any dispute, controversy or claim arising under or in relation to providing this software shall be
+ submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
+ accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
+ the United Nations Convention on Contracts on the International Sales of Goods.
+
+*******************************************************************************************************/
+
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include
+#include
+#include "options.h"
+#ifdef DEBUGGING
+#include "debug.h"
+#endif
+#include "cnst.h"
+#include "basop_proto_func.h"
+#include "stl.h"
+#include "prot.h"
+#include "rom_com.h"
+
+#define WMC_TOOL_SKIP
+
+/* compare two positive normalized 16 bit mantissa/exponent values */
+/* return value: positive if first value greater, negative if second value greater, zero if equal */
+static Word16 compMantExp16Unorm( Word16 m1, Word16 e1, Word16 m2, Word16 e2 )
+{
+ Word16 tmp;
+
+ assert( ( m1 >= 0x4000 ) && ( m2 >= 0x4000 ) ); /* comparisons below work only for normalized mantissas */
+
+ tmp = sub( e1, e2 );
+ if ( tmp == 0 )
+ tmp = sub( m1, m2 );
+
+ return tmp;
+}
+
+void basop_lpc2mdct( Word16 *lpcCoeffs, Word16 lpcOrder, Word16 *mdct_gains, Word16 *mdct_gains_exp, Word16 *mdct_inv_gains, Word16 *mdct_inv_gains_exp )
+{
+ Word32 RealData[FDNS_NPTS];
+ Word32 ImagData[FDNS_NPTS];
+ Word16 i, j, k, step, scale, s, tmp16;
+ Word16 g, g_e, ig, ig_e;
+ Word32 tmp32;
+ const PWord16 *ptwiddle;
+
+
+ /* short-cut, to avoid calling of BASOP_getTables() */
+ ptwiddle = SineTable512_fx;
+ step = 8;
+
+ /*ODFT*/
+ assert( lpcOrder < FDNS_NPTS );
+
+ /* pre-twiddle */
+ FOR( i = 0; i <= lpcOrder; i++ )
+ {
+ RealData[i] = L_mult( lpcCoeffs[i], ptwiddle->v.re );
+ move32();
+ ImagData[i] = L_negate( L_mult( lpcCoeffs[i], ptwiddle->v.im ) );
+ move32();
+ ptwiddle += step;
+ }
+
+ /* zero padding */
+ FOR( ; i < FDNS_NPTS; i++ )
+ {
+ RealData[i] = 0;
+ move32();
+ ImagData[i] = 0;
+ move32();
+ }
+
+ /* half length FFT */
+ scale = add( norm_s( lpcCoeffs[0] ), 1 );
+ move16();
+ BASOP_cfft( RealData, ImagData, 1, &scale ); /* sizeOfFft == FDNS_NPTS == 8 */
+
+
+ /*Get amplitude*/
+ j = FDNS_NPTS - 1;
+ k = 0;
+ move16();
+
+ FOR( i = 0; i < FDNS_NPTS / 2; i++ )
+ {
+ s = sub( norm_l( L_max( L_abs( RealData[i] ), L_abs( ImagData[i] ) ) ), 1 );
+
+ tmp16 = extract_h( L_shl( RealData[i], s ) );
+ tmp32 = L_mult( tmp16, tmp16 );
+
+ tmp16 = extract_h( L_shl( ImagData[i], s ) );
+ tmp16 = mac_r( tmp32, tmp16, tmp16 );
+
+ s = shl( sub( scale, s ), 1 );
+
+ if ( tmp16 == 0 )
+ {
+ s = -16;
+ move16();
+ }
+ if ( tmp16 == 0 )
+ {
+ tmp16 = 1;
+ move16();
+ }
+
+ BASOP_Util_Sqrt_InvSqrt_MantExp( tmp16, s, &g, &g_e, &ig, &ig_e );
+
+ if ( mdct_gains != NULL )
+ {
+ mdct_gains[k] = g;
+ move16();
+ }
+
+ if ( mdct_gains_exp != NULL )
+ {
+ mdct_gains_exp[k] = g_e;
+ move16();
+ }
+
+ if ( mdct_inv_gains != NULL )
+ {
+ mdct_inv_gains[k] = ig;
+ move16();
+ }
+
+ if ( mdct_inv_gains_exp != NULL )
+ {
+ mdct_inv_gains_exp[k] = ig_e;
+ move16();
+ }
+
+ k = add( k, 1 );
+
+
+ s = sub( norm_l( L_max( L_abs( RealData[j] ), L_abs( ImagData[j] ) ) ), 1 );
+
+ tmp16 = extract_h( L_shl( RealData[j], s ) );
+ tmp32 = L_mult( tmp16, tmp16 );
+
+ tmp16 = extract_h( L_shl( ImagData[j], s ) );
+ tmp16 = mac_r( tmp32, tmp16, tmp16 );
+
+ s = shl( sub( scale, s ), 1 );
+
+ if ( tmp16 == 0 )
+ {
+ s = -16;
+ move16();
+ }
+ if ( tmp16 == 0 )
+ {
+ tmp16 = 1;
+ move16();
+ }
+
+ BASOP_Util_Sqrt_InvSqrt_MantExp( tmp16, s, &g, &g_e, &ig, &ig_e );
+
+ if ( mdct_gains != NULL )
+ {
+ mdct_gains[k] = g;
+ move16();
+ }
+
+ if ( mdct_gains_exp != NULL )
+ {
+ mdct_gains_exp[k] = g_e;
+ move16();
+ }
+
+ if ( mdct_inv_gains != NULL )
+ {
+ mdct_inv_gains[k] = ig;
+ move16();
+ }
+
+ if ( mdct_inv_gains_exp != NULL )
+ {
+ mdct_inv_gains_exp[k] = ig_e;
+ move16();
+ }
+
+ j = sub( j, 1 );
+ k = add( k, 1 );
+ }
+}
+
+
+void basop_mdct_noiseShaping_interp( Word32 x[], Word16 lg, Word16 gains[], Word16 gains_exp[] )
+{
+ Word16 i, j, jp, jn, k, l;
+ Word16 g, pg, ng, e, tmp;
+
+
+ assert( lg % FDNS_NPTS == 0 );
+ k = shr( lg, 6 ); /* FDNS_NPTS = 64 */
+
+ IF( gains != NULL )
+ {
+ /* Linear interpolation */
+ IF( sub( k, 4 ) == 0 )
+ {
+ jp = 0;
+ move16();
+ j = 0;
+ move16();
+ jn = 1;
+ move16();
+
+ FOR( i = 0; i < lg; i += 4 )
+ {
+ pg = gains[jp];
+ move16();
+ g = gains[j];
+ move16();
+ ng = gains[jn];
+ move16();
+
+ /* common exponent for pg and g */
+ tmp = sub( gains_exp[j], gains_exp[jp] );
+ if ( tmp > 0 )
+ pg = shr( pg, tmp );
+ if ( tmp < 0 )
+ g = shl( g, tmp );
+ e = s_max( gains_exp[j], gains_exp[jp] );
+
+ tmp = mac_r( L_mult( pg, FL2WORD16( 0.375f ) ), g, FL2WORD16( 0.625f ) );
+ x[i] = L_shl( Mpy_32_16( x[i], tmp ), e );
+ move32();
+
+ tmp = mac_r( L_mult( pg, FL2WORD16( 0.125f ) ), g, FL2WORD16( 0.875f ) );
+ x[i + 1] = L_shl( Mpy_32_16( x[i + 1], tmp ), e );
+ move32();
+
+ /* common exponent for g and ng */
+ g = gains[j];
+ move16();
+ tmp = sub( gains_exp[j], gains_exp[jn] );
+ if ( tmp > 0 )
+ ng = shr( ng, tmp );
+ if ( tmp < 0 )
+ g = shl( g, tmp );
+ e = s_max( gains_exp[j], gains_exp[jn] );
+
+ tmp = mac_r( L_mult( g, FL2WORD16( 0.875f ) ), ng, FL2WORD16( 0.125f ) );
+ x[i + 2] = L_shl( Mpy_32_16( x[i + 2], tmp ), e );
+ move32();
+
+ tmp = mac_r( L_mult( g, FL2WORD16( 0.625f ) ), ng, FL2WORD16( 0.375f ) );
+ x[i + 3] = L_shl( Mpy_32_16( x[i + 3], tmp ), e );
+ move32();
+
+ jp = j;
+ move16();
+ j = jn;
+ move16();
+ jn = s_min( add( jn, 1 ), FDNS_NPTS - 1 );
+ }
+ }
+ ELSE IF( sub( k, 5 ) == 0 )
+ {
+ jp = 0;
+ move16();
+ j = 0;
+ move16();
+ jn = 1;
+ move16();
+
+ FOR( i = 0; i < lg; i += 5 )
+ {
+ pg = gains[jp];
+ move16();
+ g = gains[j];
+ move16();
+ ng = gains[jn];
+ move16();
+
+ /* common exponent for pg and g */
+ tmp = sub( gains_exp[j], gains_exp[jp] );
+ if ( tmp > 0 )
+ pg = shr( pg, tmp );
+ if ( tmp < 0 )
+ g = shl( g, tmp );
+ e = s_max( gains_exp[j], gains_exp[jp] );
+
+ tmp = mac_r( L_mult( pg, FL2WORD16( 0.40f ) ), g, FL2WORD16( 0.60f ) );
+ x[i] = L_shl( Mpy_32_16( x[i], tmp ), e );
+ move32();
+
+ tmp = mac_r( L_mult( pg, FL2WORD16( 0.20f ) ), g, FL2WORD16( 0.80f ) );
+ x[i + 1] = L_shl( Mpy_32_16( x[i + 1], tmp ), e );
+ move32();
+
+
+ x[i + 2] = L_shl( Mpy_32_16( x[i + 2], gains[j] ), gains_exp[j] );
+ move32();
+
+ /* common exponent for g and ng */
+ g = gains[j];
+ move16();
+ tmp = sub( gains_exp[j], gains_exp[jn] );
+ if ( tmp > 0 )
+ ng = shr( ng, tmp );
+ if ( tmp < 0 )
+ g = shl( g, tmp );
+ e = s_max( gains_exp[j], gains_exp[jn] );
+
+ tmp = mac_r( L_mult( g, FL2WORD16( 0.80f ) ), ng, FL2WORD16( 0.20f ) );
+ x[i + 3] = L_shl( Mpy_32_16( x[i + 3], tmp ), e );
+ move32();
+
+ tmp = mac_r( L_mult( g, FL2WORD16( 0.60f ) ), ng, FL2WORD16( 0.40f ) );
+ x[i + 4] = L_shl( Mpy_32_16( x[i + 4], tmp ), e );
+ move32();
+
+ jp = j;
+ move16();
+ j = jn;
+ move16();
+ jn = s_min( add( jn, 1 ), FDNS_NPTS - 1 );
+ }
+ }
+ ELSE /* no interpolation */
+ {
+ FOR( i = 0; i < FDNS_NPTS; i++ )
+ {
+ FOR( l = 0; l < k; l++ )
+ {
+ *x = L_shl( Mpy_32_16( *x, *gains ), *gains_exp );
+ move32();
+ x++;
+ }
+
+ gains++;
+ gains_exp++;
+ }
+ }
+ }
+}
+
+
+void basop_PsychAdaptLowFreqDeemph( Word32 x[], const Word16 lpcGains[], const Word16 lpcGains_e[], Word16 lf_deemph_factors[] )
+{
+ Word16 i;
+ Word16 max_val, max_e, fac, min_val, min_e, tmp, tmp_e;
+ Word32 L_tmp;
+
+
+ assert( lpcGains[0] >= 0x4000 );
+
+ max_val = lpcGains[0];
+ move16();
+ max_e = lpcGains_e[0];
+ move16();
+ min_val = lpcGains[0];
+ move16();
+ min_e = lpcGains_e[0];
+ move16();
+
+ /* find minimum (min) and maximum (max) of LPC gains in low frequencies */
+ FOR( i = 1; i < 9; i++ )
+ {
+ IF( compMantExp16Unorm( lpcGains[i], lpcGains_e[i], min_val, min_e ) < 0 )
+ {
+ min_val = lpcGains[i];
+ move16();
+ min_e = lpcGains_e[i];
+ move16();
+ }
+
+ IF( compMantExp16Unorm( lpcGains[i], lpcGains_e[i], max_val, max_e ) > 0 )
+ {
+ max_val = lpcGains[i];
+ move16();
+ max_e = lpcGains_e[i];
+ move16();
+ }
+ }
+
+ min_e = add( min_e, 5 ); /* min *= 32.0f; */
+
+ test();
+ IF( ( compMantExp16Unorm( max_val, max_e, min_val, min_e ) < 0 ) && ( min_val > 0 ) )
+ {
+ /* fac = tmp = (float)pow(max / min, 0.0078125f); */
+ tmp_e = min_e;
+ move16();
+ tmp = Inv16( min_val, &tmp_e );
+ L_tmp = L_shl( L_mult( tmp, max_val ), add( tmp_e, max_e ) ); /* Q31 */
+ L_tmp = BASOP_Util_Log2( L_tmp ); /* Q25 */
+ L_tmp = L_shr( L_tmp, 7 ); /* 0.0078125f = 1.f/(1<<7) */
+ L_tmp = BASOP_Util_InvLog2( L_tmp ); /* Q31 */
+ tmp = round_fx( L_tmp ); /* Q15 */
+ fac = tmp; /* Q15 */
+ move16();
+
+ /* gradual lowering of lowest 32 bins; DC is lowered by (max/tmp)^1/4 */
+ FOR( i = 31; i >= 0; i-- )
+ {
+ x[i] = Mpy_32_16( x[i], fac );
+ move32();
+ if ( lf_deemph_factors != NULL )
+ {
+ lf_deemph_factors[i] = mult_r( lf_deemph_factors[i], fac );
+ move16();
+ }
+ fac = mult_r( fac, tmp );
+ }
+ }
+}
+
+#undef WMC_TOOL_SKIP
diff --git a/lib_com/basop_util.c b/lib_com/basop_util.c
new file mode 100644
index 0000000000000000000000000000000000000000..d7333490245c87410bc4641077f2a2c50e6b84d0
--- /dev/null
+++ b/lib_com/basop_util.c
@@ -0,0 +1,1112 @@
+/******************************************************************************************************
+
+ (C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
+ Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
+ Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
+ Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
+ contributors to this repository. All Rights Reserved.
+
+ This software is protected by copyright law and by international treaties.
+ The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
+ Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
+ Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
+ Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
+ contributors to this repository retain full ownership rights in their respective contributions in
+ the software. This notice grants no license of any kind, including but not limited to patent
+ license, nor is any license granted by implication, estoppel or otherwise.
+
+ Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
+ contributions.
+
+ This software is provided "AS IS", without any express or implied warranties. The software is in the
+ development stage. It is intended exclusively for experts who have experience with such software and
+ solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
+ and fitness for a particular purpose are hereby disclaimed and excluded.
+
+ Any dispute, controversy or claim arising under or in relation to providing this software shall be
+ submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
+ accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
+ the United Nations Convention on Contracts on the International Sales of Goods.
+
+*******************************************************************************************************/
+
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include
+#include
+#include "options.h"
+#ifdef DEBUGGING
+#include "debug.h"
+#endif
+#include "basop_util.h"
+#include "rom_com.h"
+#include "basop_settings.h"
+#include "basop_mpy.h"
+#include "stl.h"
+#include "cnst.h"
+
+#define WMC_TOOL_SKIP
+
+extern const Word32 SqrtTable[32];
+extern const Word16 SqrtDiffTable[32];
+
+extern const Word32 ISqrtTable[32];
+extern const Word16 ISqrtDiffTable[32];
+
+extern const Word32 InvTable[32];
+extern const Word16 InvDiffTable[32];
+
+
+Word32 BASOP_Util_Log2(
+ Word32 x )
+{
+ Word32 exp;
+ Word16 exp_e;
+ Word16 nIn;
+ Word16 accuSqr;
+ Word32 accuRes;
+
+ assert( x >= 0 );
+
+ if ( x == 0 )
+ {
+ return ( (Word32) MIN_32 );
+ }
+
+ /* normalize input, calculate integer part */
+ exp_e = norm_l( x );
+ x = L_shl( x, exp_e );
+ exp = L_deposit_l( exp_e );
+
+ /* calculate (1-normalized_input) */
+ nIn = extract_h( L_sub( MAX_32, x ) );
+
+ /* approximate ln() for fractional part (nIn *c0 + nIn^2*c1 + nIn^3*c2 + ... + nIn^8 *c7) */
+
+ /* iteration 1, no need for accumulation */
+ accuRes = L_mult( nIn, ldCoeff[0] ); /* nIn^i * coeff[0] */
+ accuSqr = mult( nIn, nIn ); /* nIn^2, nIn^3 .... */
+
+ /* iteration 2 */
+ accuRes = L_mac( accuRes, accuSqr, ldCoeff[1] ); /* nIn^i * coeff[1] */
+ accuSqr = mult( accuSqr, nIn ); /* nIn^2, nIn^3 .... */
+
+ /* iteration 3 */
+ accuRes = L_mac( accuRes, accuSqr, ldCoeff[2] ); /* nIn^i * coeff[2] */
+ accuSqr = mult( accuSqr, nIn ); /* nIn^2, nIn^3 .... */
+
+ /* iteration 4 */
+ accuRes = L_mac( accuRes, accuSqr, ldCoeff[3] ); /* nIn^i * coeff[3] */
+ accuSqr = mult( accuSqr, nIn ); /* nIn^2, nIn^3 .... */
+
+ /* iteration 5 */
+ accuRes = L_mac( accuRes, accuSqr, ldCoeff[4] ); /* nIn^i * coeff[4] */
+ accuSqr = mult( accuSqr, nIn ); /* nIn^2, nIn^3 .... */
+
+ /* iteration 6 */
+ accuRes = L_mac( accuRes, accuSqr, ldCoeff[5] ); /* nIn^i * coeff[5] */
+ accuSqr = mult( accuSqr, nIn ); /* nIn^2, nIn^3 .... */
+
+ /* iteration 7, no need to calculate accuSqr any more */
+ accuRes = L_mac( accuRes, accuSqr, ldCoeff[6] ); /* nIn^i * coeff[6] */
+
+ /* ld(fractional part) = ln(fractional part)/ln(2), 1/ln(2) = (1 + 0.44269504) */
+ accuRes = L_mac0( L_shr( accuRes, 1 ), extract_h( accuRes ), 14506 );
+
+ accuRes = L_shr( accuRes, LD_DATA_SCALE - 1 ); /* fractional part/LD_DATA_SCALE */
+ exp = L_shl( exp, ( 31 - LD_DATA_SCALE ) ); /* integer part/LD_DATA_SCALE */
+ accuRes = L_sub( accuRes, exp ); /* result = integer part + fractional part */
+
+ return ( accuRes );
+}
+
+
+Word32 BASOP_Util_InvLog2(
+ Word32 x )
+{
+ Word16 frac;
+ Word16 exp;
+ Word32 retVal;
+ UWord32 index3;
+ UWord32 index2;
+ UWord32 index1;
+ UWord32 lookup3f;
+ UWord32 lookup12;
+ UWord32 lookup;
+
+ if ( x < FL2WORD32( -31.0 / 64.0 ) )
+ {
+ return 0;
+ }
+ test();
+ if ( ( L_sub( x, FL2WORD32( 31.0 / 64.0 ) ) >= 0 ) || ( x == 0 ) )
+ {
+ return 0x7FFFFFFF;
+ }
+
+ frac = extract_l( L_and( x, 0x3FF ) );
+
+ index3 = L_and( L_shr( x, 10 ), 0x1F );
+ index2 = L_and( L_shr( x, 15 ), 0x1F );
+ index1 = L_and( L_shr( x, 20 ), 0x1F );
+
+ exp = extract_l( L_shr( x, 25 ) );
+ if ( x > 0 )
+ {
+ exp = sub( 31, exp );
+ }
+ if ( x < 0 )
+ {
+ exp = negate( exp );
+ }
+
+ lookup3f = L_add( exp2x_tab_long[index3], L_shr( Mpy_32_16( 0x0016302F, frac ), 1 ) );
+ lookup12 = Mpy_32_32( exp2_tab_long[index1], exp2w_tab_long[index2] );
+ lookup = Mpy_32_32( lookup12, lookup3f );
+
+ retVal = L_shr( lookup, sub( exp, 3 ) );
+
+ return retVal;
+}
+
+
+Word16 BASOP_Util_Add_MantExp /*!< Exponent of result */
+ ( Word16 a_m, /*!< Mantissa of 1st operand a */
+ Word16 a_e, /*!< Exponent of 1st operand a */
+ Word16 b_m, /*!< Mantissa of 2nd operand b */
+ Word16 b_e, /*!< Exponent of 2nd operand b */
+ Word16 *ptrSum_m ) /*!< Mantissa of result */
+{
+ Word32 L_lm, L_hm;
+ Word16 shift;
+
+ /* Compare exponents: the difference is limited to +/- 15
+ The Word16 mantissa of the operand with higher exponent is moved into the low
+ part of a Word32 and shifted left by the exponent difference. Then, the
+ unshifted mantissa of the operand with the lower exponent is added to the lower
+ 16 bits. The addition result is normalized and the upper Word16 of the result represents
+ the mantissa to return. The returned exponent takes into account all shift operations
+ including the final 16-bit extraction.
+ Note: The resulting mantissa may be inaccurate in the case, where the mantissa of the operand
+ with higher exponent is not really left-aligned, while the mantissa of the operand with
+ lower exponent is so. If in such a case, the difference in exponents is more than 15,
+ an inaccuracy is introduced.
+ Example:
+ A: a_e = 20, a_m = 0x0001
+ B: b_e = 0, b_m = 0x4000
+ correct: A+B=1*2^20+1*2^14=0x0010.0000+0x0000.4000=0x0010.4000=0x4100*2^6
+ previously: A+B=1*2^20+1*2^14=0x0001+0x0000=0x0001*2^20
+ this version: A+B=1*2^20+1*2^14=0x0000.8000+0x0000.4000=0x6000*2^6
+ */
+
+ shift = sub( a_e, b_e );
+ if ( shift >= 0 )
+ shift = s_min( 15, shift );
+
+ if ( shift < 0 )
+ shift = s_max( -15, shift );
+ a_e = s_max( a_e, b_e );
+ L_hm = L_deposit_l( a_m ); /* mantissa belonging to higher exponent */
+ L_lm = L_deposit_l( a_m ); /* mantissa belonging to lower exponent */
+ if ( shift >= 0 )
+ L_lm = L_deposit_l( b_m );
+ if ( shift < 0 )
+ L_hm = L_deposit_l( b_m );
+
+ if ( shift > 0 )
+ shift = negate( shift );
+
+ L_hm = L_shr( L_hm, shift ); /* shift left due to negative shift parameter */
+ a_e = add( a_e, shift );
+ L_hm = L_add( L_hm, L_lm );
+ shift = norm_l( L_hm );
+ L_hm = L_shl( L_hm, shift );
+ *ptrSum_m = extract_h( L_hm );
+ move16();
+
+ a_e = sub( a_e, shift );
+ if ( L_hm )
+ a_e = add( a_e, 16 );
+
+ return ( a_e );
+}
+
+
+/* local function for Sqrt16 */
+static Word16 Sqrt16_common(
+ Word16 m,
+ Word16 e )
+{
+ Word16 index, frac;
+#ifdef BASOP_NOGLOB
+ Flag Overflow;
+#endif /* BASOP_NOGLOB */
+
+ assert( ( m >= 0x4000 ) || ( m == 0 ) );
+
+ /* get table index (upper 6 bits minus 32) */
+ /* index = (m >> 9) - 32; */
+ index = mac_r( -32768 - ( 32 << 16 ), m, 1 << 6 );
+
+ /* get fractional part for interpolation (lower 9 bits) */
+ frac = s_and( m, 0x1FF ); /* Q9 */
+
+ /* interpolate */
+ if ( m != 0 )
+ {
+ BASOP_SATURATE_WARNING_OFF;
+#ifndef BASOP_NOGLOB
+ m = mac_r( SqrtTable[index], SqrtDiffTable[index], frac );
+#else /* BASOP_NOGLOB */
+ m = mac_ro( SqrtTable[index], SqrtDiffTable[index], frac, &Overflow );
+#endif /* BASOP_NOGLOB */
+ BASOP_SATURATE_WARNING_ON;
+ }
+
+ /* handle odd exponents */
+ if ( s_and( e, 1 ) != 0 )
+ m = mult_r( m, 0x5a82 );
+
+ return m;
+}
+
+
+Word16 Sqrt16( /*!< output mantissa */
+ Word16 mantissa, /*!< input mantissa */
+ Word16 *exponent /*!< pointer to exponent */
+)
+{
+ Word16 preShift, e;
+
+ assert( mantissa >= 0 );
+
+ /* normalize */
+ preShift = norm_s( mantissa );
+
+ e = sub( *exponent, preShift );
+ mantissa = shl( mantissa, preShift );
+
+ /* calc mantissa */
+ mantissa = Sqrt16_common( mantissa, e );
+
+ /* e = (e + 1) >> 1 */
+ *exponent = mult_r( e, 1 << 14 );
+ move16();
+
+ return mantissa;
+}
+
+Word16 Inv16( /*!< output mantissa */
+ Word16 mantissa, /*!< input mantissa */
+ Word16 *exponent /*!< pointer to exponent */
+)
+{
+ Word16 index, frac;
+ Word16 preShift;
+ Word16 m, e;
+
+ assert( mantissa != 0 );
+
+ /* absolute */
+ BASOP_SATURATE_WARNING_OFF;
+ m = abs_s( mantissa );
+ BASOP_SATURATE_WARNING_ON;
+
+ /* normalize */
+ preShift = norm_s( m );
+
+ e = sub( *exponent, preShift );
+ m = shl( m, preShift );
+
+ /* get table index (upper 6 bits minus 32) */
+ /* index = (m >> 9) - 32; */
+ index = mac_r( -32768 - ( 32 << 16 ), m, 1 << 6 );
+
+ /* get fractional part for interpolation (lower 9 bits) */
+ frac = shl( s_and( m, 0x1FF ), 1 ); /* Q10 */
+
+ /* interpolate */
+ m = msu_r( InvTable[index], InvDiffTable[index], frac );
+
+ /* restore sign */
+ if ( mantissa < 0 )
+ m = negate( m );
+
+ /* e = 1 - e */
+ *exponent = sub( 1, e );
+ move16();
+
+ return m;
+}
+
+
+void BASOP_Util_Sqrt_InvSqrt_MantExp(
+ Word16 mantissa, /*!< mantissa */
+ Word16 exponent, /*!< expoinent */
+ Word16 *sqrt_mant, /*!< Pointer to sqrt mantissa */
+ Word16 *sqrt_exp, /*!< Pointer to sqrt exponent */
+ Word16 *isqrt_mant, /*!< Pointer to 1/sqrt mantissa */
+ Word16 *isqrt_exp /*!< Pointer to 1/sqrt exponent */
+)
+{
+ Word16 index, frac;
+ Word16 preShift;
+ Word16 m, mi, e_odd;
+
+ assert( mantissa > 0 );
+
+ /* normalize */
+ preShift = norm_s( mantissa );
+
+ exponent = sub( exponent, preShift );
+ mantissa = shl( mantissa, preShift );
+
+ /* get table index (upper 6 bits minus 32) */
+ /* index = (m >> 9) - 32; */
+ index = mac_r( -32768 - ( 32 << 16 ), mantissa, 1 << 6 );
+
+ /* get fractional part for interpolation (lower 9 bits) */
+ frac = s_and( mantissa, 0x1FF ); /* Q9 */
+
+ /* interpolate */
+ BASOP_SATURATE_WARNING_OFF;
+ m = mac_r( SqrtTable[index], SqrtDiffTable[index], frac );
+ mi = msu_r( ISqrtTable[index], ISqrtDiffTable[index], frac );
+ BASOP_SATURATE_WARNING_ON;
+
+ /* handle even/odd exponents */
+ e_odd = s_and( exponent, 1 );
+ if ( e_odd != 0 )
+ m = mult_r( m, 0x5a82 );
+ if ( e_odd == 0 )
+ mi = mult_r( mi, 0x5a82 );
+
+ /* e = (e + 1) >> 1 */
+ *sqrt_exp = mult_r( exponent, 1 << 14 );
+ move16();
+
+ /* e = (2 - e) >> 1 */
+ *isqrt_exp = msu_r( 1L << 15, exponent, 1 << 14 );
+ move16();
+
+ /* Write result */
+ *sqrt_mant = m;
+ move16();
+ *isqrt_mant = mi;
+ move16();
+}
+
+/********************************************************************/
+/*!
+ \brief Calculates the scalefactor needed to normalize input array
+
+ The scalefactor needed to normalize the Word32 input array is returned
+ If the input array contains only '0', a scalefactor 0 is returned
+ Scaling factor is determined wrt a normalized target x: 1073741824 <= x <= 2147483647 for positive x
+ and -2147483648 <= x <= -1073741824 for negative x
+*/
+
+/*! r: measured headroom in range [0..31], 0 if all x[i] == 0 */
+Word16 getScaleFactor32(
+ const Word32 *x, /* i : array containing 32-bit data */
+ const Word16 len_x ) /* i : length of the array to scan */
+{
+ Word16 i, i_min, i_max;
+ Word32 x_min, x_max;
+
+ x_max = L_add( 0, 0 );
+ x_min = L_add( 0, 0 );
+ FOR( i = 0; i < len_x; i++ )
+ {
+ if ( x[i] >= 0 )
+ x_max = L_max( x_max, x[i] );
+ if ( x[i] < 0 )
+ x_min = L_min( x_min, x[i] );
+ }
+
+ i_max = 0x20;
+ move16();
+ i_min = 0x20;
+ move16();
+
+ if ( x_max != 0 )
+ i_max = norm_l( x_max );
+
+ if ( x_min != 0 )
+ i_min = norm_l( x_min );
+
+ i = s_and( s_min( i_max, i_min ), 0x1F );
+
+ return i;
+}
+
+
+Word16 BASOP_Util_Divide1616_Scale(
+ Word16 x,
+ Word16 y,
+ Word16 *s )
+{
+ Word16 z;
+ Word16 sx;
+ Word16 sy;
+ Word16 sign;
+
+ /* assert (x >= (Word16)0); */
+ assert( y != (Word16) 0 );
+
+ sign = 0;
+ move16();
+
+ IF( x < 0 )
+ {
+ x = negate( x );
+ sign = s_xor( sign, 1 );
+ }
+
+ IF( y < 0 )
+ {
+ y = negate( y );
+ sign = s_xor( sign, 1 );
+ }
+
+ IF( x == (Word16) 0 )
+ {
+ move16();
+ *s = 0;
+
+ return ( (Word16) 0 );
+ }
+
+ sx = norm_s( x );
+ x = shl( x, sx );
+ x = shr( x, 1 );
+ move16();
+ *s = sub( 1, sx );
+
+ sy = norm_s( y );
+ y = shl( y, sy );
+ move16();
+ *s = add( *s, sy );
+
+ z = div_s( x, y );
+
+ if ( sign != 0 )
+ {
+ z = negate( z );
+ }
+
+ return z;
+}
+
+
+void set_val_Word16(
+ Word16 X[],
+ const Word16 val,
+ Word16 n )
+{
+ Word16 i;
+
+
+ FOR( i = 0; i < n; i++ )
+ {
+ X[i] = val;
+ move16();
+ }
+
+
+ return;
+}
+
+void set_val_Word32(
+ Word32 X[],
+ const Word32 val,
+ Word16 n )
+{
+ Word16 i;
+
+
+ FOR( i = 0; i < n; i++ )
+ {
+ X[i] = val;
+ move32();
+ }
+
+
+ return;
+}
+
+Word16 mult0(
+ Word16 x,
+ Word16 y )
+{
+ return extract_l( L_mult0( x, y ) );
+}
+
+
+#define SINETAB SineTable512_fx
+#define LD 9
+
+/*
+ * Calculates coarse lookup values for sine/cosine and residual angle.
+ * \param x angle in radians with exponent = 2 or as radix 2 with exponent = 0.
+ * \param scale shall always be 2
+ * \param sine pointer to where the sine lookup value is stored into
+ * \param cosine pointer to where the cosine lookup value is stored into
+ * \param flag_radix2 flag indicating radix 2 angle if non-zero.
+ */
+static Word16 fixp_sin_cos_residual_16(
+ Word16 x,
+ const Word16 scale,
+ Word16 *sine,
+ Word16 *cosine,
+ Word8 flag_radix2 )
+{
+ Word16 residual;
+ Word16 s;
+ Word16 ssign;
+ Word16 csign;
+ Word16 tmp, cl = 0, sl = 0;
+ const Word16 shift = 15 - LD - 1 - scale;
+
+ if ( flag_radix2 == 0 )
+ {
+ x = mult_r( x, FL2WORD16( 1.0 / EVS_PI ) );
+ }
+ s = shr( x, shift );
+
+ residual = s_and( x, ( 1 << shift ) - 1 );
+ /* We assume "2+scale" is a constant */
+ residual = shl( residual, 2 + scale );
+ residual = mult_r( residual, FL2WORD16( EVS_PI / 4.0 ) );
+
+ /* Sine sign symmetry */
+ ssign = s_and( s, ( 1 << LD ) << 1 );
+
+ /* Cosine sign symmetry */
+ csign = s_and( add( s, ( 1 << LD ) ), ( 1 << LD ) << 1 );
+
+ /* Modulo EVS_PI */
+ s = s_and( s, ( 2 << LD ) - 1 );
+
+ /* EVS_PI/2 symmetry */
+ s = s_min( s, sub( 2 << LD, s ) );
+
+ {
+ tmp = s_min( sub( 1 << LD, s ), s );
+ s = sub( tmp, s );
+
+ if ( !s )
+ {
+ move16();
+ sl = SINETAB[tmp].v.im;
+ }
+ if ( !s )
+ {
+ move16();
+ cl = SINETAB[tmp].v.re;
+ }
+ if ( s )
+ {
+ move16();
+ sl = SINETAB[tmp].v.re;
+ }
+ if ( s )
+ {
+ move16();
+ cl = SINETAB[tmp].v.im;
+ }
+
+ if ( ssign )
+ {
+ sl = negate( sl );
+ }
+ if ( csign )
+ {
+ cl = negate( cl );
+ }
+
+ move16();
+ move16();
+ *sine = sl;
+ *cosine = cl;
+ }
+
+ return residual;
+}
+
+
+Word16 getCosWord16R2(
+ Word16 theta )
+{
+ Word16 result, residual, sine, cosine;
+
+ residual = fixp_sin_cos_residual_16( theta, 1, &sine, &cosine, 1 );
+ /* This negation prevents the subsequent addition from overflow */
+ /* The negation cannot overflow, sine is in range [0x0..0x7FFF] */
+ BASOP_SATURATE_WARNING_OFF
+ sine = negate( sine );
+ result = msu_r( L_mult( sine, residual ), cosine, -32768 );
+ BASOP_SATURATE_WARNING_ON
+
+ return result;
+}
+
+
+Word16 idiv1616U(
+ Word16 x,
+ Word16 y )
+{
+ Word16 s;
+ Word16 tmp;
+
+ /* make y > x */
+ s = add( sub( norm_s( y ), norm_s( x ) ), 1 );
+ s = s_max( s, 0 );
+
+ BASOP_SATURATE_WARNING_OFF
+ y = shl( y, s );
+ BASOP_SATURATE_WARNING_ON
+
+ /* divide and shift */
+ tmp = div_s( x, y );
+ y = shr( tmp, sub( 15, s ) );
+
+ return y;
+}
+
+Word32 BASOP_util_Pow2(
+ const Word32 exp_m,
+ const Word16 exp_e,
+ Word16 *result_e )
+{
+ static const Word16 pow2Coeff[8] = {
+ FL2WORD16( 0.693147180559945309417232121458177 ), /* ln(2)^1 /1! */
+ FL2WORD16( 0.240226506959100712333551263163332 ), /* ln(2)^2 /2! */
+ FL2WORD16( 0.0555041086648215799531422637686218 ), /* ln(2)^3 /3! */
+ FL2WORD16( 0.00961812910762847716197907157365887 ), /* ln(2)^4 /4! */
+ FL2WORD16( 0.00133335581464284434234122219879962 ), /* ln(2)^5 /5! */
+ FL2WORD16( 1.54035303933816099544370973327423e-4 ), /* ln(2)^6 /6! */
+ FL2WORD16( 1.52527338040598402800254390120096e-5 ), /* ln(2)^7 /7! */
+ FL2WORD16( 1.32154867901443094884037582282884e-6 ) /* ln(2)^8 /8! */
+ };
+
+ Word32 frac_part = 0, tmp_frac, result_m;
+ Word16 int_part = 0;
+
+ IF( exp_e > 0 )
+ {
+ /* "+ 1" compensates L_shr(,1) of the polynomial evaluation at the loop end. */
+
+ int_part = add( 1, extract_l( L_shr( exp_m, sub( 31, exp_e ) ) ) );
+ frac_part = L_lshl( exp_m, exp_e );
+ frac_part = L_and( 0x7FFFFFFF, frac_part );
+ }
+ if ( exp_e <= 0 )
+ frac_part = L_shl( exp_m, exp_e );
+ if ( exp_e <= 0 )
+ {
+ int_part = 1;
+ move16();
+ }
+
+ /* Best accuracy is around 0, so try to get there with the fractional part. */
+ IF( ( tmp_frac = L_sub( frac_part, FL2WORD32( 0.5 ) ) ) >= 0 )
+ {
+ int_part = add( int_part, 1 );
+ frac_part = L_sub( tmp_frac, FL2WORD32( 0.5 ) );
+ }
+ ELSE IF( ( tmp_frac = L_add( frac_part, FL2WORD32( 0.5 ) ) ) < 0 )
+ {
+ int_part = sub( int_part, 1 );
+ frac_part = L_add( tmp_frac, FL2WORD32( 0.5 ) );
+ }
+
+ /* Evaluate taylor polynomial which approximates 2^x */
+ {
+ Word32 p;
+ Word16 i;
+
+
+ /* First taylor series coefficient a_0 = 1.0, scaled by 0.5 due to L_shr(,1). */
+ result_m = L_add( FL2WORD32( 1.0 / 2.0 ), L_shr( Mpy_32_16( frac_part, pow2Coeff[0] ), 1 ) );
+ p = Mpy_32_32( frac_part, frac_part );
+ FOR( i = 1; i < 7; i++ )
+ {
+ /* next taylor series term: a_i * x^i, x=0 */
+ result_m = L_add( result_m, L_shr( Mpy_32_16( p, pow2Coeff[i] ), 1 ) );
+ p = Mpy_32_32( p, frac_part );
+ }
+ result_m = L_add( result_m, L_shr( Mpy_32_16( p, pow2Coeff[i] ), 1 ) );
+ }
+ *result_e = int_part;
+ move16();
+
+ return result_m;
+}
+
+/*! r: result of division x/y, not normalized */
+Word16 BASOP_Util_Divide3216_Scale(
+ Word32 x, /* i : numerator, signed */
+ Word16 y, /* i : denominator, signed */
+ Word16 *s ) /* o : scaling, 0, if x==0 */
+{
+ Word16 z;
+ Word16 sx;
+ Word16 sy;
+ Word16 sign;
+
+ /*assert (x > (Word32)0);
+ assert (y >= (Word16)0);*/
+
+ /* check, if numerator equals zero, return zero then */
+ IF( x == (Word32) 0 )
+ {
+ *s = 0;
+ move16();
+
+ return ( (Word16) 0 );
+ }
+
+ sign = s_xor( extract_h( x ), y ); /* just to exor the sign bits */
+ BASOP_SATURATE_WARNING_OFF
+ x = L_abs( x );
+ y = abs_s( y );
+ BASOP_SATURATE_WARNING_ON
+ sx = sub( norm_l( x ), 1 );
+ x = L_shl( x, sx );
+ sy = norm_s( y );
+ y = shl( y, sy );
+ *s = sub( sy, sx );
+ move16();
+
+ z = div_s( round_fx( x ), y );
+
+ if ( sign < 0 ) /* if sign bits differ, negate the result */
+ {
+ z = negate( z );
+ }
+
+ return z;
+}
+
+
+static const Word16 table_pow2[32] = {
+ 16384, 16743, 17109, 17484, 17867, 18258, 18658, 19066, 19484, 19911,
+ 20347, 20792, 21247, 21713, 22188, 22674, 23170, 23678, 24196, 24726,
+ 25268, 25821, 26386, 26964, 27554, 28158, 28774, 29405, 30048, 30706,
+ 31379, 32066
+};
+/* table of table_pow2[i+1] - table_pow2[i] */
+static const Word16 table_pow2_diff_x32[32] = {
+ 11488, 11712, 12000, 12256, 12512, 12800, 13056, 13376, 13664, 13952,
+ 14240, 14560, 14912, 15200, 15552, 15872, 16256, 16576, 16960, 17344,
+ 17696, 18080, 18496, 18880, 19328, 19712, 20192, 20576, 21056, 21536,
+ 21984, 22432
+};
+
+Word32 Pow2( /* o Q0 : result (range: 0<=val<=0x7fffffff) */
+ Word16 exponant, /* i Q0 : Integer part. (range: 0<=val<=30) */
+ Word16 fraction /* i Q15 : Fractional part. (range: 0.0<=val<1.0) */
+)
+{
+ Word16 exp, i, a;
+ Word32 L_x;
+
+ i = mac_r( -32768, fraction, 32 ); /* Extract b10-b16 of fraction */
+ a = s_and( fraction, 0x3ff ); /* Extract b0-b9 of fraction */
+
+ L_x = L_deposit_h( table_pow2[i] ); /* table[i] << 16 */
+ L_x = L_mac( L_x, table_pow2_diff_x32[i], a ); /* L_x -= diff*a*2 */
+
+ exp = sub( 30, exponant );
+
+ L_x = L_shr_r( L_x, exp );
+
+ return L_x;
+}
+
+/*************************************************************************
+ *
+ * FUNCTION: Log2_norm()
+ *
+ * PURPOSE: Computes log2(L_x, exp), where L_x is positive and
+ * normalized, and exp is the normalisation exponent
+ * If L_x is negative or zero, the result is 0.
+ *
+ * DESCRIPTION:
+ * The function Log2(L_x) is approximated by a table and linear
+ * interpolation. The following steps are used to compute Log2(L_x)
+ *
+ * 1- exponent = 30-norm_exponent
+ * 2- i = bit25-b31 of L_x; 32<=i<=63 (because of normalization).
+ * 3- a = bit10-b24
+ * 4- i -=32
+ * 5- fraction = table[i]<<16 - (table[i] - table[i+1]) * a * 2
+ *
+ *************************************************************************/
+
+static const Word32 L_table[32] = {
+ -32768L, 95322112L, 187793408L, 277577728L,
+ 364871680L, 449740800L, 532381696L, 612859904L,
+ 691306496L, 767787008L, 842432512L, 915308544L,
+ 986546176L, 1056210944L, 1124302848L, 1190887424L,
+ 1256095744L, 1319993344L, 1382580224L, 1443921920L,
+ 1504083968L, 1563131904L, 1621000192L, 1677885440L,
+ 1733722112L, 1788510208L, 1842380800L, 1895399424L,
+ 1947435008L, 1998618624L, 2049015808L, 2098626560L
+};
+
+static const Word16 table_diff[32] = {
+ 1455, 1411, 1370, 1332, 1295, 1261, 1228, 1197,
+ 1167, 1139, 1112, 1087, 1063, 1039, 1016, 995,
+ 975, 955, 936, 918, 901, 883, 868, 852,
+ 836, 822, 809, 794, 781, 769, 757, 744
+};
+
+Word16 Log2_norm_lc( /* o : Fractional part of Log2. (range: 0<=val<1) */
+ Word32 L_x /* i : input value (normalized) */
+)
+{
+ Word16 i, a;
+ Word16 y;
+
+
+ L_x = L_shr( L_x, 9 );
+ a = extract_l( L_x ); /* Extract b10-b24 of fraction */
+ a = lshr( a, 1 );
+
+ i = mac_r( L_x, -32 * 2 - 1, 16384 ); /* Extract b25-b31 minus 32 */
+
+ y = mac_r( L_table[i], table_diff[i], a ); /* table[i] << 16 - diff*a*2 */
+
+
+ return y;
+}
+
+
+Word32 BASOP_Util_fPow(
+ Word32 base_m,
+ Word16 base_e,
+ Word32 exp_m,
+ Word16 exp_e,
+ Word16 *result_e )
+{
+
+ Word16 ans_lg2_e, base_lg2_e;
+ Word32 base_lg2_m, ans_lg2_m, result_m;
+ Word16 shift;
+
+ test();
+ IF( ( base_m == 0 ) && ( exp_m != 0 ) )
+ {
+ *result_e = 0;
+ move16();
+ return 0;
+ }
+ /* Calc log2 of base */
+ shift = norm_l( base_m );
+ base_m = L_shl( base_m, shift );
+ base_e = sub( base_e, shift );
+ base_lg2_m = BASOP_Util_Log2( base_m );
+
+ /* shift: max left shift such that neither base_e or base_lg2_m saturate. */
+ shift = sub( s_min( norm_s( base_e ), WORD16_BITS - 1 - LD_DATA_SCALE ), 1 );
+ /* Compensate shift into exponent of result. */
+ base_lg2_e = sub( WORD16_BITS - 1, shift );
+ base_lg2_m = L_add( L_shr( base_lg2_m, sub( WORD16_BITS - 1 - LD_DATA_SCALE, shift ) ), L_deposit_h( shl( base_e, shift ) ) );
+
+ /* Prepare exp */
+ shift = norm_l( exp_m );
+ exp_m = L_shl( exp_m, shift );
+ exp_e = sub( exp_e, shift );
+
+ /* Calc base pow exp */
+ ans_lg2_m = Mpy_32_32( base_lg2_m, exp_m );
+ ans_lg2_e = add( exp_e, base_lg2_e );
+
+ /* Calc antilog */
+ result_m = BASOP_util_Pow2( ans_lg2_m, ans_lg2_e, result_e );
+
+ return result_m;
+}
+
+Word32 BASOP_Util_Add_Mant32Exp /* o : normalized result mantissa */
+ ( Word32 a_m, /* i : Mantissa of 1st operand a */
+ Word16 a_e, /* i : Exponent of 1st operand a */
+ Word32 b_m, /* i : Mantissa of 2nd operand b */
+ Word16 b_e, /* i : Exponent of 2nd operand b */
+ Word16 *ptr_e ) /* o : exponent of result */
+{
+ Word32 L_tmp;
+ Word16 shift;
+
+ /* Compare exponents: the difference is limited to +/- 30
+ The Word32 mantissa of the operand with lower exponent is shifted right by the exponent difference.
+ Then, the unshifted mantissa of the operand with the higher exponent is added. The addition result
+ is normalized and the result represents the mantissa to return. The returned exponent takes into
+ account all shift operations.
+ */
+
+ if ( !a_m )
+ a_e = add( b_e, 0 );
+
+ if ( !b_m )
+ b_e = add( a_e, 0 );
+
+ shift = sub( a_e, b_e );
+ shift = s_max( -31, shift );
+ shift = s_min( 31, shift );
+ if ( shift < 0 )
+ {
+ /* exponent of b is greater than exponent of a, shr a_m */
+ a_m = L_shl( a_m, shift );
+ }
+ if ( shift > 0 )
+ {
+ /* exponent of a is greater than exponent of b */
+ b_m = L_shr( b_m, shift );
+ }
+ a_e = add( s_max( a_e, b_e ), 1 );
+ L_tmp = L_add( L_shr( a_m, 1 ), L_shr( b_m, 1 ) );
+ shift = norm_l( L_tmp );
+ if ( shift )
+ L_tmp = L_shl( L_tmp, shift );
+ if ( L_tmp == 0 )
+ a_e = add( 0, 0 );
+ if ( L_tmp != 0 )
+ a_e = sub( a_e, shift );
+ *ptr_e = a_e;
+
+ return ( L_tmp );
+}
+
+static const Word32 L_table_isqrt[48] = {
+ 2147418112L, 2083389440L, 2024669184L, 1970667520L,
+ 1920794624L, 1874460672L, 1831403520L, 1791098880L,
+ 1753415680L, 1717960704L, 1684602880L, 1653145600L,
+ 1623326720L, 1595080704L, 1568276480L, 1542782976L,
+ 1518469120L, 1495334912L, 1473183744L, 1451950080L,
+ 1431633920L, 1412169728L, 1393491968L, 1375469568L,
+ 1358168064L, 1341521920L, 1325465600L, 1309933568L,
+ 1294991360L, 1280507904L, 1266548736L, 1252982784L,
+ 1239875584L, 1227161600L, 1214775296L, 1202847744L,
+ 1191182336L, 1179910144L, 1168965632L, 1158283264L,
+ 1147863040L, 1137770496L, 1127940096L, 1118306304L,
+ 1108934656L, 1099825152L, 1090912256L, 1082261504L
+};
+/* table of table_isqrt[i] - table_isqrt[i+1] */
+static const Word16 table_isqrt_diff[48] = {
+ 977, 896, 824, 761, 707, 657, 615, 575,
+ 541, 509, 480, 455, 431, 409, 389, 371,
+ 353, 338, 324, 310, 297, 285, 275, 264,
+ 254, 245, 237, 228, 221, 213, 207, 200,
+ 194, 189, 182, 178, 172, 167, 163, 159,
+ 154, 150, 147, 143, 139, 136, 132, 130
+};
+
+static const Word16 shift[] = { 9, 10 };
+
+Word32 Isqrt_lc1(
+ Word32 frac, /* i : Q31: normalized value (1.0 < frac <= 0.5) */
+ Word16 *exp /* i/o: exponent (value = frac x 2^exponent) */
+)
+{
+ Word16 i, a;
+ Word32 L_tmp;
+
+ IF( frac <= (Word32) 0 )
+ {
+ *exp = 0;
+ move16();
+ return 0x7fffffff; /*0x7fffffff*/
+ }
+
+ /* If exponant odd -> shift right by 10 (otherwise 9) */
+ L_tmp = L_shr( frac, shift[s_and( *exp, 1 )] );
+
+ /* 1) -16384 to shift left and change sign */
+ /* 2) 32768 to Add 1 to Exponent like it was divided by 2 */
+ /* 3) We let the mac_r add another 0.5 because it imitates */
+ /* the behavior of shr on negative number that should */
+ /* not be rounded towards negative infinity. */
+ /* It replaces: */
+ /* *exp = negate(shr(sub(*exp, 1), 1)); move16(); */
+ *exp = mac_r( 32768, *exp, -16384 );
+ move16();
+
+ a = extract_l( L_tmp ); /* Extract b10-b24 */
+ a = lshr( a, 1 );
+
+ i = mac_r( L_tmp, -16 * 2 - 1, 16384 ); /* Extract b25-b31 minus 16 */
+
+ L_tmp = L_msu( L_table_isqrt[i], table_isqrt_diff[i], a ); /* table[i] << 16 - diff*a*2 */
+
+ return L_tmp;
+}
+
+static const Word16 sqrt_table[49] = {
+ 16384, 16888, 17378, 17854, 18318, 18770, 19212,
+ 19644, 20066, 20480, 20886, 21283, 21674, 22058,
+ 22435, 22806, 23170, 23530, 23884, 24232, 24576,
+ 24915, 25249, 25580, 25905, 26227, 26545, 26859,
+ 27170, 27477, 27780, 28081, 28378, 28672, 28963,
+ 29251, 29537, 29819, 30099, 30377, 30652, 30924,
+ 31194, 31462, 31727, 31991, 32252, 32511, 32767
+};
+
+/*! r: output value, Q31 */
+Word32 Sqrt_l(
+ Word32 L_x, /* i : input value, Q31 */
+ Word16 *exp /* o : right shift to be applied to result, Q1 */
+)
+{
+ /*
+ y = sqrt(x)
+
+ x = f * 2^-e, 0.5 <= f < 1 (normalization)
+
+ y = sqrt(f) * 2^(-e/2)
+
+ a) e = 2k --> y = sqrt(f) * 2^-k (k = e div 2,
+ 0.707 <= sqrt(f) < 1)
+ b) e = 2k+1 --> y = sqrt(f/2) * 2^-k (k = e div 2,
+ 0.5 <= sqrt(f/2) < 0.707)
+ */
+
+ Word16 e, i, a, tmp;
+ Word32 L_y;
+
+ if ( L_x <= 0 )
+ {
+ *exp = 0;
+ move16();
+ return L_deposit_l( 0 );
+ }
+
+#if 0 /* original version creates an overflow warning */
+ e = s_and(norm_l(L_x), 0xFFFE); /* get next lower EVEN norm. exp */
+#else
+ e = s_and( norm_l( L_x ), 0x7FFE ); /* get next lower EVEN norm. exp */
+#endif
+ L_x = L_shl( L_x, e ); /* L_x is normalized to [0.25..1) */
+ *exp = e;
+ move16(); /* return 2*exponent (or Q1) */
+
+ L_x = L_shr( L_x, 9 );
+ a = extract_l( L_x ); /* Extract b10-b24 */
+ a = lshr( a, 1 );
+
+ i = mac_r( L_x, -16 * 2 - 1, 16384 ); /* Extract b25-b31 minus 16 */
+
+ L_y = L_deposit_h( sqrt_table[i] ); /* table[i] << 16 */
+ tmp = sub( sqrt_table[i], sqrt_table[i + 1] ); /* table[i] - table[i+1]) */
+ L_y = L_msu( L_y, tmp, a ); /* L_y -= tmp*a*2 */
+
+ /* L_y = L_shr (L_y, *exp); */ /* denormalization done by caller */
+
+ return ( L_y );
+}
+
+#undef WMC_TOOL_SKIP
diff --git a/lib_com/basop_util.h b/lib_com/basop_util.h
new file mode 100644
index 0000000000000000000000000000000000000000..0a20e526f8f931159342864b7c687148a59d4c53
--- /dev/null
+++ b/lib_com/basop_util.h
@@ -0,0 +1,418 @@
+/******************************************************************************************************
+
+ (C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
+ Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
+ Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
+ Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
+ contributors to this repository. All Rights Reserved.
+
+ This software is protected by copyright law and by international treaties.
+ The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
+ Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
+ Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
+ Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
+ contributors to this repository retain full ownership rights in their respective contributions in
+ the software. This notice grants no license of any kind, including but not limited to patent
+ license, nor is any license granted by implication, estoppel or otherwise.
+
+ Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
+ contributions.
+
+ This software is provided "AS IS", without any express or implied warranties. The software is in the
+ development stage. It is intended exclusively for experts who have experience with such software and
+ solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
+ and fitness for a particular purpose are hereby disclaimed and excluded.
+
+ Any dispute, controversy or claim arising under or in relation to providing this software shall be
+ submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
+ accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
+ the United Nations Convention on Contracts on the International Sales of Goods.
+
+*******************************************************************************************************/
+
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#ifndef __BASOP_UTIL_H__
+#define __BASOP_UTIL_H__
+
+#include
+#include "options.h"
+#include "basop_settings.h"
+#include "typedef.h"
+#include "basop32.h"
+#include "basop_mpy.h"
+
+
+#define LD_DATA_SCALE ( 6 )
+
+#define LD_DATA_SHIFT_I5 ( 7 )
+
+#define modDiv2( x ) sub( x, shl( shr( x, 1 ), 1 ) )
+#define modDiv8( x ) L_sub( x, L_shl( L_shr( x, 3 ), 3 ) )
+
+#ifndef CHEAP_NORM_SIZE
+#define CHEAP_NORM_SIZE 161
+#endif
+
+static __inline Word16 limitScale16( Word16 s )
+{
+ /* It is assumed, that s is calculated just before, therefore we can switch upon sign */
+ if ( s >= 0 )
+ s = s_min( s, WORD16_BITS - 1 );
+ if ( s < 0 )
+ s = s_max( s, 1 - WORD16_BITS );
+ return ( s );
+}
+
+static __inline Word16 limitScale32( Word16 s )
+{
+ /* It is assumed, that s is calculated just before, therefore we can switch upon sign */
+ if ( s >= 0 )
+ s = s_min( s, WORD32_BITS - 1 );
+ if ( s < 0 )
+ s = s_max( s, 1 - WORD32_BITS );
+ return ( s );
+}
+
+
+/*!**********************************************************************
+ \brief Add two values given by mantissa and exponent.
+
+ Mantissas are in 16-bit-fractional format with values between 0 and 1.
+ The base for exponents is 2. Example: \f$ a = a\_m * 2^{a\_e} \f$
+
+************************************************************************/
+Word16 BASOP_Util_Add_MantExp /*!< Exponent of result */
+ ( Word16 a_m, /*!< Mantissa of 1st operand a */
+ Word16 a_e, /*!< Exponent of 1st operand a */
+ Word16 b_m, /*!< Mantissa of 2nd operand b */
+ Word16 b_e, /*!< Exponent of 2nd operand b */
+ Word16 *ptrSum_m ); /*!< Mantissa of result */
+
+
+/************************************************************************/
+/*!
+ \brief Calculate the squareroot of a number given by mantissa and exponent
+
+ Mantissa is in 16/32-bit-fractional format with values between 0 and 1.
+ For *norm versions mantissa has to be between 0.5 and 1.
+ The base for the exponent is 2. Example: \f$ a = a\_m * 2^{a\_e} \f$
+ The exponent is addressed via pointers and will be overwritten with the result.
+*/
+Word16 Sqrt16( /*!< output mantissa */
+ Word16 mantissa, /*!< input mantissa */
+ Word16 *exponent /*!< pointer to exponent */
+);
+
+/*****************************************************************************/
+/*!
+ \brief Calculate the inverse of a number given by mantissa and exponent
+
+ Mantissa is in 16-bit-fractional format with values between 0 and 1.
+ The base for the exponent is 2. Example: \f$ a = a\_m * 2^{a\_e} \f$
+ The operand is addressed via pointers and will be overwritten with the result.
+
+ The function uses a table lookup and a newton iteration.
+*/
+Word16 Inv16( /*!< output mantissa */
+ Word16 mantissa, /*!< input mantissa */
+ Word16 *exponent /*!< pointer to exponent */
+);
+
+/******************************************************************************/
+/*!
+ \brief Calculate the squareroot and inverse of squareroot of a number given by mantissa and exponent
+
+ Mantissa is in 16-bit-fractional format with values between 0 and 1.
+ The base for the exponent is 2. Example: \f$ a = a\_m * 2^{a\_e} \f$
+*/
+void BASOP_Util_Sqrt_InvSqrt_MantExp( Word16 mantissa, /*!< mantissa */
+ Word16 exponent, /*!< expoinent */
+ Word16 *sqrt_mant, /*!< Pointer to sqrt mantissa */
+ Word16 *sqrt_exp, /*!< Pointer to sqrt exponent */
+ Word16 *isqrt_mant, /*!< Pointer to 1/sqrt mantissa */
+ Word16 *isqrt_exp /*!< Pointer to 1/sqrt exponent */
+);
+
+
+/********************************************************************/
+/*!
+ \brief Calculates the scalefactor needed to normalize input array
+
+ The scalefactor needed to normalize the Word32 input array is returned
+ If the input array contains only '0', a scalefactor 0 is returned
+ Scaling factor is determined wrt a normalized target x: 1073741824 <= x <= 2147483647 for positive x
+ and -2147483648 <= x <= -1073741824 for negative x
+*/
+
+/*! r: measured headroom in range [0..31], 0 if all x[i] == 0 */
+Word16 getScaleFactor32(
+ const Word32 *x, /* i : array containing 32-bit data */
+ const Word16 len_x ); /* i : length of the array to scan */
+
+/************************************************************************/
+/*!
+ \brief Binary logarithm with 7 iterations
+
+ \param x
+
+ \return log2(x)/64
+ */
+/************************************************************************/
+Word32 BASOP_Util_Log2( Word32 x );
+
+
+/****************************************************************************/
+/*!
+ \brief Does fractional division of Word16 arg1 by Word16 arg2
+
+
+ \return fractional Q15 Word16 z = arg1(Q15)/arg2(Q15) with scaling s
+*/
+Word16 BASOP_Util_Divide1616_Scale( Word16 x, /* i : Numerator*/
+ Word16 y, /* i : Denominator*/
+ Word16 *s ); /* o : Additional scalefactor difference*/
+
+/****************************************************************************/
+/*!
+ \brief Does fractional integer division of Word32 arg1 by Word16 arg2
+
+
+ \return fractional Word16 integer z = arg1(32bits)/arg2(16bits), z not normalized
+*/
+Word16 BASOP_Util_Divide3216_Scale( Word32 x, /*!< i : Numerator */
+ Word16 y, /*!< i : Denominator*/
+ Word16 *s ); /*!< o : Additional scalefactor difference*/
+
+
+/************************************************************************/
+/*!
+ * \brief Binary logarithm with 5 iterations
+ *
+ * \param[i] val
+ *
+ * \return basop_log2(val)/128
+ */
+/************************************************************************/
+Word32 BASOP_Util_log2_i5( Word32 val );
+
+/************************************************************************/
+/*!
+ \brief Binary power
+
+ Date: 06-JULY-2012 Arthur Tritthart, IIS Fraunhofer Erlangen
+
+ Version with 3 table lookup and 1 linear interpolations
+
+ Algorithm: compute power of 2, argument x is in Q7.25 format
+ result = 2^(x/64)
+ We split exponent (x/64) into 5 components:
+ integer part: represented by b31..b25 (exp)
+ fractional part 1: represented by b24..b20 (lookup1)
+ fractional part 2: represented by b19..b15 (lookup2)
+ fractional part 3: represented by b14..b10 (lookup3)
+ fractional part 4: represented by b09..b00 (frac)
+ => result = (lookup1*lookup2*(lookup3+C1*frac)<<3)>>exp
+
+ Due to the fact, that all lookup values contain a factor 0.5
+ the result has to be shifted by 3 to the right also.
+ Table exp2_tab_long contains the log2 for 0 to 1.0 in steps
+ of 1/32, table exp2w_tab_long the log2 for 0 to 1/32 in steps
+ of 1/1024, table exp2x_tab_long the log2 for 0 to 1/1024 in
+ steps of 1/32768. Since the 2-logarithm of very very small
+ negative value is rather linear, we can use interpolation.
+
+ Limitations:
+
+ For x <= 0, the result is fractional positive
+ For x > 0, the result is integer in range 1...7FFF.FFFF
+ For x < -31/64, we have to clear the result
+ For x = 0, the result is ~1.0 (0x7FFF.FFFF)
+ For x >= 31/64, the result is 0x7FFF.FFFF
+
+ \param x
+
+ \return pow(2,(x/64))
+ */
+/************************************************************************/
+Word32 BASOP_Util_InvLog2( Word32 x );
+
+
+/****************************************************************************/
+/*!
+ \brief Sets Array Word16 arg1 to value Word16 arg2 for Word16 arg3 elements
+*/
+void set_val_Word16( Word16 X[], /*!< Address of array */
+ const Word16 val, /*!< Value to copy into array */
+ Word16 n ); /*!< Number of elements to process */
+
+
+/****************************************************************************/
+/*!
+ \brief Sets Array Word32 arg1 to value Word32 arg2 for Word16 arg3 elements
+*/
+void set_val_Word32( Word32 X[], /*!< Address of array */
+ const Word32 val, /*!< Value to copy into array */
+ Word16 n ); /*!< Number of elements to process */
+
+/****************************************************************************/
+/*!
+ \brief Does a multiplication of Word16 input values
+
+ \return z16 = x16 * y16
+*/
+Word16 mult0( Word16 x, /* i : Multiplier */
+ Word16 y ); /* i : Multiplicand */
+
+/**
+ * \brief calculate cosine of angle. Tuned for ISF domain.
+ * \param theta Angle normalized to radix 2, theta = (angle in radians)*2.0/pi
+ * \return result with exponent 0.
+ */
+Word16 getCosWord16R2( Word16 theta );
+
+/****************************************************************************/
+/*!
+ \brief 16/16->16 unsigned integer division
+
+ x and y have to be positive, x has to be < 16384
+
+ \return 16/16->16 integer
+ */
+
+Word16 idiv1616U( Word16 x, Word16 y );
+
+
+/**
+ * \brief return 2 ^ (exp * 2^exp_e)
+ * \param exp_m mantissa of the exponent to 2.0f
+ * \param exp_e exponent of the exponent to 2.0f
+ * \param result_e pointer to a INT where the exponent of the result will be stored into
+ * \return mantissa of the result
+ */
+Word32 BASOP_util_Pow2(
+ const Word32 exp_m,
+ const Word16 exp_e,
+ Word16 *result_e );
+
+
+Word32 Isqrt_lc1(
+ Word32 frac, /* i : Q31: normalized value (1.0 < frac <= 0.5) */
+ Word16 *exp /* i/o: exponent (value = frac x 2^exponent) */
+);
+
+/*****************************************************************************/
+/*!
+
+ \brief Calculates pow(2,x)
+ ___________________________________________________________________________
+ | |
+ | Function Name : Pow2() |
+ | |
+ | L_x = pow(2.0, exponant.fraction) (exponent = interger part) |
+ | = pow(2.0, 0.fraction) << exponent |
+ |---------------------------------------------------------------------------|
+ | Algorithm: |
+ | |
+ | The function Pow2(L_x) is approximated by a table and linear |
+ | interpolation. |
+ | |
+ | 1- i = bit10-b15 of fraction, 0 <= i <= 31 |
+ | 2- a = bit0-b9 of fraction |
+ | 3- L_x = table[i]<<16 - (table[i] - table[i+1]) * a * 2 |
+ | 4- L_x = L_x >> (30-exponant) (with rounding) |
+ |___________________________________________________________________________|
+*/
+Word32 Pow2( /* o : Q0 : result (range: 0<=val<=0x7fffffff) */
+ Word16 exponant, /* i : Q0 : Integer part. (range: 0<=val<=30) */
+ Word16 fraction /* i : Q15 : Fractionnal part. (range: 0.0<=val<1.0) */
+);
+
+/*************************************************************************
+ *
+ * FUNCTION: Log2_norm()
+ *
+ * PURPOSE: Computes log2(L_x, exp), where L_x is positive and
+ * normalized, and exp is the normalisation exponent
+ * If L_x is negative or zero, the result is 0.
+ *
+ * DESCRIPTION:
+ * The function Log2(L_x) is approximated by a table and linear
+ * interpolation. The following steps are used to compute Log2(L_x)
+ *
+ * 1- exponent = 30-norm_exponent
+ * 2- i = bit25-b31 of L_x; 32<=i<=63 (because of normalization).
+ * 3- a = bit10-b24
+ * 4- i -=32
+ * 5- fraction = table[i]<<16 - (table[i] - table[i+1]) * a * 2
+ *
+ *************************************************************************/
+
+Word16 Log2_norm_lc( /* o : Fractional part of Log2. (range: 0<=val<1) */
+ Word32 L_x /* i : input value (normalized) */
+);
+
+/*************************************************************************
+ *
+ * FUNCTION: BASOP_Util_fPow()
+ */
+/**
+ * \brief BASOP_Util_fPow
+ *
+ * PURPOSE: Computes pow(base_m, base_e, exp_m, exp_e), where base_m and base_e
+ * specify the base, and exp_m and exp_e specify the exponent.
+ * The result is returned in a mantissa and exponent representation.
+ *
+ * DESCRIPTION:
+ * The function BASOP_Util_fPow(L_x) calculates the power function by
+ * calculating 2 ^ (log2(base)*exp)
+ *
+ * \param base_m mantissa of base
+ * \param base_e exponent of base
+ * \param exp_m mantissa of exponent
+ * \param exp_e exponent of exponent
+ * \param result_e pointer to exponent of result
+ * \return Word32 mantissa of result
+ *
+ *************************************************************************/
+
+Word32 BASOP_Util_fPow( /* o : mantissa of result */
+ Word32 base_m,
+ Word16 base_e, /* i : input value for base (mantissa and exponent) */
+ Word32 exp_m,
+ Word16 exp_e, /* i : input value for exponent (mantissa and exponent) */
+ Word16 *result_e /* o : output pointer to exponent of result */
+);
+
+/*!**********************************************************************
+ \brief Add two values given by mantissa and exponent.
+
+ Mantissas are in 32-bit-fractional format with values between 0 and 1.
+ The base for exponents is 2. Example: \f$ a = a\_m * 2^{a\_e} \f$
+
+************************************************************************/
+Word32 BASOP_Util_Add_Mant32Exp /* o : normalized result mantissa */
+ ( Word32 a_m, /* i : Mantissa of 1st operand a */
+ Word16 a_e, /* i : Exponent of 1st operand a */
+ Word32 b_m, /* i : Mantissa of 2nd operand b */
+ Word16 b_e, /* i : Exponent of 2nd operand b */
+ Word16 *ptr_e ); /* o : exponent of result */
+
+/****************************************************************************/
+/*!
+ \brief Accumulates multiplications
+
+ Accumulates the elementwise multiplications of Word32 Array X with Word16 Array Y
+ pointed to by arg1 and arg2 with specified headroom. Length of to be multiplied arrays is arg3,
+ headroom with has to be taken into account is specified in arg4
+
+ \return Word32 result of accumulated multiplications over Word32 array arg1 and Word16 array arg2 and Word16 pointer
+ to exponent correction factor which needs to be added to the exponent of the result vector
+*/
+Word32 dotWord32_16_guards( const Word32 *X, const Word16 *Y, Word16 n, Word16 hr, Word16 *shift );
+
+Word32 Sqrt_l( Word32 L_x, Word16 *exp );
+
+#endif /* __BASOP_UTIL_H__ */
diff --git a/lib_com/bitalloc.c b/lib_com/bitalloc.c
new file mode 100644
index 0000000000000000000000000000000000000000..91a9782ecbda5fa2a25790cea9d731cf5e98f3f8
--- /dev/null
+++ b/lib_com/bitalloc.c
@@ -0,0 +1,977 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include "options.h"
+#include "wmc_auto.h"
+#include "cnst.h"
+#include "rom_com.h"
+#include "prot.h"
+#include "basop_util.h"
+#include "basop_proto_func.h"
+
+
+/*--------------------------------------------------------------------------
+ * bitalloc()
+ *
+ * Adaptive bit allocation for 20kHz audio codec
+ *--------------------------------------------------------------------------*/
+
+void bitalloc (
+ short *y, /* i : reordered norm of sub-vectors */
+ short *idx, /* i : reordered sub-vector indices */
+ short sum, /* i : number of available bits */
+ short N, /* i : number of norms */
+ short K, /* i : maximum number of bits per dimension */
+ short *r, /* o : bit-allacation vector */
+ const short *sfmsize, /* i : band length */
+ const short hqswb_clas /* i : signal classification flag */
+)
+{
+ short i, j, k, n, m, v, im;
+ short diff, temp;
+ short fac;
+ short ii;
+ short SFM_thr = SFM_G1G2;
+
+ N -= 1;
+
+ if ( hqswb_clas == HQ_HARMONIC )
+ {
+ SFM_thr = 22;
+ }
+
+ fac = 3;
+ K -= 2;
+ im = 1;
+ diff = sum;
+ n = sum >> 3;
+ for ( i=0; i= sfmsize[j] && r[j] < K )
+ {
+ y[k] -= fac;
+ r[j]++;
+ if ( r[j] >= K )
+ {
+ y[k] = MIN16B;
+ }
+ sum -= sfmsize[j];
+ }
+ else
+ {
+ y[k] = MIN16B;
+ k++;
+ if ( k == im && im < N )
+ {
+ im++;
+ }
+ }
+
+ if ( sum < WID_G1 || diff == sum )
+ {
+ break;
+ }
+
+ diff = sum;
+ v = N - 1;
+
+ if (k > v)
+ {
+ for ( ii=0; ii<=N; ii++ )
+ {
+ if ( y[ii] > MIN16B )
+ {
+ if( ii < N )
+ {
+ im = ii + 1;
+ }
+
+ break;
+ }
+ }
+ }
+ }
+
+ if ( sum >= WID_G2)
+ {
+ for (i=0; i<=N; i++)
+ {
+ j = idx[i];
+ if ( j >= SFM_G1 && j < SFM_thr && r[j] == 0 )
+ {
+ r[j] = 1;
+ sum -= WID_G2;
+ if ( sum < WID_G2 )
+ {
+ break;
+ }
+ }
+ }
+ }
+
+ if ( sum >= WID_G2 )
+ {
+ for (i=0; i<=N; i++)
+ {
+ j = idx[i];
+ if ( j >= SFM_G1 && j < SFM_thr && r[j] == 1 )
+ {
+ r[j] = 2;
+ sum -= WID_G2;
+ if ( sum < WID_G2 )
+ {
+ break;
+ }
+ }
+ }
+ }
+
+ if ( sum >= WID_G1 )
+ {
+ for (i=0; i<=N; i++)
+ {
+ j = idx[i];
+ if ( j < SFM_G1 && r[j] == 0 )
+ {
+ r[j] = 1;
+ sum -= WID_G1;
+ if ( sum < WID_G1 )
+ {
+ break;
+ }
+ }
+ }
+ }
+
+ if ( sum >= WID_G1 )
+ {
+ for (i=0; i<=N; i++)
+ {
+ j = idx[i];
+ if ( j < SFM_G1 && r[j] == 1 )
+ {
+ r[j] = 2;
+ sum -= WID_G1;
+ if ( sum < WID_G1 )
+ {
+ break;
+ }
+ }
+ }
+ }
+
+ return;
+}
+
+#define WMC_TOOL_SKIP
+
+/*-------------------------------------------------------------------*
+ * BitAllocF()
+ *
+ * Fractional bit allocation
+ *-------------------------------------------------------------------*/
+
+short BitAllocF (
+ short *y, /* i : norm of sub-vectors */
+ long bit_rate, /* i : bitrate */
+ short B, /* i : number of available bits */
+ short N, /* i : number of sub-vectors */
+ short *R, /* o : bit-allocation indicator */
+ short *Rsubband, /* o : sub-band bit-allocation vector (Q3) */
+ const short hqswb_clas, /* i : hq swb class */
+ const short num_env_bands /* i : Number sub bands to be encoded for HQ_SWB_BWE */
+)
+{
+ Word16 fac;
+ Word16 i, n, Nmin, Bits, bs, low_rate = 0;
+
+ Word16 m_fx;
+ Word32 t_fx, B_fx;
+ Word32 L_tmp1, L_tmp2;
+ Word16 tmp, exp1, exp2;
+ Word32 Rsubband_w32_fx[NB_SFM]; /* Q15 */
+ Word16 B_w16_fx;
+
+ set_i( Rsubband_w32_fx, 0, NB_SFM);
+
+ fac = 3;
+ if (L_sub(bit_rate, 32000) < 0)
+ {
+ bs = 2;
+ }
+ else
+ {
+ bs = 3;
+ }
+ low_rate = 1;
+
+ Nmin = N;
+ if ( sub(Nmin,SFM_N) > 0)
+ {
+ Nmin = SFM_N;
+ }
+
+ /* Initial bits distribution */
+ if (sub(hqswb_clas , HQ_GEN_SWB) == 0 || sub(hqswb_clas , HQ_GEN_FB) == 0)
+ {
+ /* Initial bits distribution */
+ L_tmp1 = 0;
+ m_fx = 0;
+ for ( i = 0; i < num_env_bands ; i++)
+ {
+ L_tmp1 = L_mac0(L_tmp1, Nb[i], y[i]);
+ }
+ L_tmp1 = L_msu0(L_tmp1, fac, B);
+
+ t_fx = 0;
+ n = 0;
+ tmp = add(band_end_HQ[num_env_bands-1], shl(band_end_HQ[num_env_bands-1], 1));
+ exp1 = norm_s(tmp);
+ tmp = div_s(16384, shl(tmp, exp1));/*15 + 14 - exp1*/
+ exp2 = norm_s(tmp);
+ tmp = shl(tmp, exp2);
+ exp1 = add(29, sub(exp2, exp1));
+
+ for ( i = 0; i < N; i++)
+ {
+ L_tmp2 = L_sub(L_mult0(y[i], band_end_HQ[num_env_bands-1]), L_tmp1);
+ Rsubband_w32_fx[i] = L_mult0(extract_l(L_tmp2), Nb[i]);
+ move32();/*Q0*/
+ if (Rsubband_w32_fx[i] > 0)
+ {
+ n = add(n,Nb[i]);
+ Rsubband_w32_fx[i] = Mpy_32_16(Rsubband_w32_fx[i], tmp);
+ move32();/*exp1 - 15*/
+ Rsubband_w32_fx[i] = L_shl(Rsubband_w32_fx[i], sub(30, exp1));/*Q15*/
+
+ t_fx = L_add(t_fx, Rsubband_w32_fx[i]);/*Q0*/
+ }
+ else
+ {
+ Rsubband_w32_fx[i] = 0;
+ move32();
+ }
+ }
+ }
+ else
+ {
+ /* Initial bits distribution */
+ L_tmp1 = 0;
+ m_fx = 0;
+ for ( i = 0; i < N ; i++)
+ {
+ L_tmp1 = L_mac0(L_tmp1, Nb[i], y[i]);
+ }
+ L_tmp1 = L_msu0(L_tmp1, fac, B);
+
+
+ t_fx = 0;
+ n = 0;
+ tmp = add(band_end_HQ[N-1], shl(band_end_HQ[N-1], 1));
+ exp1 = norm_s(tmp);
+ tmp = div_s(16384, shl(tmp, exp1));/*15 + 14 - exp1*/
+ exp2 = norm_s(tmp);
+ tmp = shl(tmp, exp2);
+ exp1 = add(29, sub(exp2, exp1));
+ for ( i = 0; i < N; i++)
+ {
+ L_tmp2 = L_sub(L_mult0(y[i], band_end_HQ[N-1]), L_tmp1);
+ Rsubband_w32_fx[i] = L_mult0(extract_l(L_tmp2), Nb[i]);
+ move32();/*Q0*/
+ if (Rsubband_w32_fx[i] > 0)
+ {
+ n = add(n,Nb[i]);
+ Rsubband_w32_fx[i] = Mpy_32_16(Rsubband_w32_fx[i], tmp);
+ move32();/*exp1 - 15*/
+ Rsubband_w32_fx[i] = L_shl(Rsubband_w32_fx[i], sub(30, exp1));/*Q15*/
+
+ t_fx = L_add(t_fx, Rsubband_w32_fx[i]);/*Q0*/
+ }
+ else
+ {
+ Rsubband_w32_fx[i] = 0;
+ move32();
+ }
+ }
+ }
+
+ /* Distribute the remaining bits to subbands with non-zero bits */
+ B_fx = L_shl(B, 15);
+ WHILE (L_sub(L_shr(L_add(t_fx, 16384), 15) , B) != 0)
+ {
+ L_tmp1 = L_sub(t_fx, B_fx);
+ exp1 = sub(norm_l(L_tmp1), 1);
+ exp2 = norm_s(n);
+ tmp = div_s(extract_h(L_shl(L_tmp1, exp1)), shl(n, exp2));/*15 + 15 + exp1 - 16 - exp2*/
+ m_fx = shl(tmp, sub(exp2, exp1));/*Q14*/
+
+ t_fx = 0;
+ n = 0;
+ for ( i = 0; i < N; i++)
+ {
+ if (Rsubband_w32_fx[i] > 0)
+ {
+ Rsubband_w32_fx[i] = L_msu(Rsubband_w32_fx[i], m_fx, Nb[i]);
+ move32();
+
+ if (Rsubband_w32_fx[i] > 0)
+ {
+ n = add(n,Nb[i]);
+
+ t_fx = L_add(t_fx, Rsubband_w32_fx[i]);
+ }
+ else
+ {
+ Rsubband_w32_fx[i] = 0;
+ move32();
+ }
+ }
+ }
+ }
+ Bits = B;
+
+ /* Impose bit-constraints to subbands with less than minimum bits*/
+ t_fx = 0;
+ n = 0;
+ for ( i = 0; i < N; i++)
+ {
+ if (Rsubband_w32_fx[i] > 0)
+ {
+ test();
+ test();
+ if ((L_sub(Rsubband_w32_fx[i] , L_shl(add(bs, LNb[i]), 15)) <0) && (sub(low_rate,1) == 0))
+ {
+ Rsubband_w32_fx[i] = 0;
+ move32();
+ }
+ else if ( L_sub(Rsubband_w32_fx[i] , L_shl(Nb[i], 15)) <=0)
+ {
+ B = sub(B,Nb[i]);
+ Rsubband_w32_fx[i] = L_shl(Nb[i], 15);
+ move32();
+ }
+ else
+ {
+ n = add(n,Nb[i]);
+ t_fx = L_add(t_fx, Rsubband_w32_fx[i]);
+ }
+ }
+ }
+
+ /* Distribute the remaining bits to subbands with more than 1-bit per sample */
+ WHILE (L_sub(L_shr(L_add(t_fx, 16384), 15) ,B) != 0)
+ {
+ L_tmp1 = L_sub(t_fx, L_shl(B, 15));
+ L_tmp2 = L_abs(L_tmp1);
+
+ if( n>0 )
+ {
+ exp1 = sub(norm_l(L_tmp2), 1);
+ exp2 = norm_s(n);
+ tmp = div_s(extract_h(L_shl(L_tmp2, exp1)), shl(n, exp2));/*15 + 15 + exp1 - 16 - exp2*/
+ m_fx = shl(tmp, sub(exp2, exp1));/*Q14*/
+ if (L_tmp1 < 0)
+ {
+ m_fx = negate(m_fx);
+ }
+
+ t_fx = 0;
+ n = 0;
+ for( i = 0; i < N; i++)
+ {
+ if (L_sub(Rsubband_w32_fx[i] , L_shl(Nb[i], 15)) > 0)
+ {
+ Rsubband_w32_fx[i] = L_msu(Rsubband_w32_fx[i], m_fx, Nb[i]);
+ if (L_sub(Rsubband_w32_fx[i] ,L_shl(Nb[i], 15)) > 0)
+ {
+ n = add(n,Nb[i]);
+
+ t_fx = L_add(t_fx, Rsubband_w32_fx[i]);
+ }
+ else
+ {
+ B = sub(B,Nb[i]);
+
+ Rsubband_w32_fx[i] = L_shl(Nb[i], 15);
+ move32();
+ }
+ }
+ }
+ }
+ /*In case no subband has enough bits more than 1-bit per sample, take bits off the higher subbands */
+ if (t_fx == 0)
+ {
+ for ( i = N-1; i >= 0; i--)
+ {
+ if (Rsubband_w32_fx[i] > 0)
+ {
+ B = add( B, Nb[i] );
+ Rsubband_w32_fx[i] = 0;
+ move32();
+ if ( B >= 0)
+ {
+ BREAK;
+ }
+ }
+ }
+ BREAK;
+ }
+ }
+
+ /* fine redistribution of over-allocated or under-allocated bits */
+ tmp = 0;
+ for ( i = 0; i < N; i++)
+ {
+ Rsubband[i] = extract_l(L_shr(Rsubband_w32_fx[i], 12));
+ tmp = add(tmp, Rsubband[i]);
+ }
+
+ B = Bits;
+ B_w16_fx = shl(B, 3);
+ if (sub(tmp ,B_w16_fx)>0)
+ {
+ tmp = sub(tmp, B_w16_fx);
+ for ( i = 0; i < N; i++)
+ {
+ if (sub(Rsubband[i], add(shl(Nb[i], 3), tmp)) >= 0)
+ {
+ Rsubband[i] = sub(Rsubband[i], tmp);
+ BREAK;
+ }
+ }
+ }
+ else
+ {
+ tmp = sub(tmp, B_w16_fx);
+ for ( i = 0; i < N; i++)
+ {
+ if (Rsubband[i] > 0)
+ {
+ Rsubband[i] = sub(Rsubband[i], tmp);
+ BREAK;
+ }
+ }
+ }
+
+ /* Calculate total used bits and initialize R to be used for Noise Filling */
+ tmp = 0;
+ for ( i = 0; i < N; i++)
+ {
+ tmp = add(tmp, Rsubband[i]);
+ R[i] = shr(Rsubband[i], 3);
+ }
+
+ return shr(tmp, 3);
+}
+
+/*-------------------------------------------------------------------*
+ * Bit_group()
+ *
+ * bit allocation in group
+ *-------------------------------------------------------------------*/
+static void Bit_group_fx (
+ Word16 *y, /* i : norm of sub-band Q0*/
+ Word16 start_band, /* i : start band indices Q0*/
+ Word16 end_band, /* i : end band indices Q0*/
+ Word16 Bits, /* i : number of allocation bits in group Q0*/
+ Word16 thr, /* i : smallest bit number for allocation in group Q0*/
+ Word32 *Rsubband_fx, /* o : bit allocation of sub-band Q21*/
+ Word16 *fac_fx /* i : weight factor for norm of sub-band Q13*/
+)
+{
+ Word16 i, j, k, m, y_index[16], index[16], bit_band, band_num, norm_sum;
+ Word16 tmp,exp;
+ Word16 factor_fx;
+ Word32 R_temp_fx[16], R_sum_fx = 0, R_sum_org_fx = 0, Bits_avg_fx = 0;
+ Word32 L_tmp;
+ UWord32 lo;
+
+ /* initialization for bit allocation in one group*/
+ tmp = 6554;
+ move16(); /*Q15 1/5 */
+ IF(sub(thr,5) == 0)
+ {
+ tmp = 6554;
+ move16(); /*Q15 1/5 */
+ }
+ IF(sub(thr,6) == 0)
+ {
+ tmp = 5462;
+ move16();/*Q15 1/6 */
+ }
+ IF(sub(thr,7) == 0)
+ {
+ tmp = 4682;
+ move16();/*Q15 1/7 */
+ }
+ bit_band = mult(tmp, Bits); /*0+15-15=0, Q0 */
+ band_num = sub(end_band,start_band);
+
+ FOR( i = 0; i < band_num; i++ )
+ {
+ y_index[i] = y[add(i,start_band)];
+ move16();
+ index[i] = i;
+ move16();
+ }
+
+ /* Rearrange norm vector in decreasing order */
+ reordvct(y_index, band_num, index);
+ /* norm vector modification */
+
+ factor_fx = div_s(1, band_num);/*Q15 */
+ IF ( sub(thr,5) > 0 )
+ {
+ FOR ( i = 0; i < band_num; i++ )
+ {
+ L_tmp = L_mult(i,factor_fx);/*Q16 */
+ tmp = extract_h(L_shl(L_tmp, 13)); /*Q13 */
+ tmp = sub(fac_fx[1],tmp);/*Q13 */
+ L_tmp = L_mult(y_index[i],tmp);/*Q14 */
+ y_index[i] = extract_h(L_shl(L_tmp, 2));/*Q0 */
+ }
+ }
+ ELSE
+ {
+ FOR ( i = 0; i < band_num; i++ )
+ {
+ L_tmp = L_mult(i,factor_fx);/*Q16 */
+ tmp = extract_h(L_shl(L_tmp, 13)); /*Q13 */
+ tmp = sub(fac_fx[0],tmp);/*Q13 */
+ L_tmp = L_mult(y_index[i],tmp);/*Q14 */
+ y_index[i] = extract_h(L_shl(L_tmp, 2));/*Q0 */
+ }
+ }
+
+ /* bit allocation based on modified norm */
+ L_tmp = L_mult(band_num,24576);/*Q16 */
+ tmp = extract_h(L_shl(L_tmp,7));/*Q7 */
+ IF ( sub(shl(bit_band,7),tmp) >= 0 )
+ {
+ FOR ( j = 0; j < band_num; j++)
+ {
+ IF ( y_index[j] < 0 )
+ {
+ y_index[j] = 0;
+ move16();
+ }
+ R_temp_fx[j] = 2097152;
+ move16();/*Q21 = 1 move16(); */
+ }
+
+ i = sub(band_num,1);
+ norm_sum = 0;/*Q0 */
+ FOR (k = 0; k <= i; k++)
+ {
+ norm_sum = add(norm_sum,y_index[k]);
+ }
+
+ FOR (j = 0; j < band_num; j++)
+ {
+ IF(norm_sum == 0)
+ {
+ FOR (k = 0; k <= i; k++)
+ {
+ R_temp_fx[k] = 0;
+ move32();/*Q21 */
+ }
+ }
+ ELSE
+ {
+ exp = norm_s(norm_sum);
+ tmp = shl(norm_sum, exp);/*Q(exp) */
+ tmp = div_s(16384,tmp); /*Q(15+14-exp) */
+ Bits_avg_fx = L_mult(tmp, Bits);/*Q(30-exp) */
+
+ FOR (k = 0; k <= i; k++)
+ {
+ L_tmp = L_shl(L_deposit_l(y_index[k]),24);
+ Mpy_32_32_ss(Bits_avg_fx,L_tmp,&L_tmp,&lo);
+
+ R_temp_fx[k] = L_shl(L_tmp,sub(exp,2));
+ move32();/*Q21 */
+ }
+ }
+
+ L_tmp = L_shl(L_deposit_l(thr),21);/*Q21 */
+ IF ( L_sub(R_temp_fx[i],L_tmp) < 0 )
+ {
+ R_temp_fx[i] = 0;
+ move32();
+ norm_sum = sub(norm_sum,y_index[i]);
+ i--;
+ }
+ ELSE
+ {
+ BREAK;
+ }
+ }
+ }
+ ELSE
+ {
+ FOR ( j = 0; j < bit_band; j++ )
+ {
+ IF ( y_index[j] < 0 )
+ {
+ y_index[j] = 0;
+ move16();
+ }
+ R_temp_fx[j] = 2097152;
+ move32();/*Q21 = 1 */
+ }
+
+ FOR ( j = bit_band; j < band_num; j++ )
+ {
+ R_temp_fx[j] = 0;
+ move32();
+ }
+
+ norm_sum = 0;
+ FOR (k = 0; k < bit_band; k++)
+ {
+ norm_sum = add(norm_sum,y_index[k]);
+ }
+
+ i = bit_band;
+ FOR (j = 0; j < bit_band; j++)
+ {
+ IF(norm_sum == 0)
+ {
+ FOR (k = 0; k < i; k++)
+ {
+ R_temp_fx[k] = 0;
+ move32();/*Q21 */
+ }
+ }
+ ELSE
+ {
+ exp = norm_s(norm_sum);
+ tmp = shl(norm_sum, exp);/*Q(exp) */
+ tmp = div_s(16384,tmp); /*Q(15+14-exp) */
+ Bits_avg_fx = L_mult(tmp, Bits);/*Q(30-exp) */
+ FOR (k = 0; k < i; k++)
+ {
+ L_tmp = L_shl(L_deposit_l(y_index[k]),24);
+ Mpy_32_32_ss(Bits_avg_fx,L_tmp,&L_tmp,&lo);
+ R_temp_fx[k] = L_shl(L_tmp,sub(exp,2));
+ move32();/*Q21 */
+ }
+ }
+ R_sum_fx = 0;
+ L_tmp = L_shl(L_deposit_l(thr),21);/*Q21 */
+ FOR (k = 0; k < i; k++)
+ {
+ IF (L_sub(R_temp_fx[k],L_tmp) < 0)
+ {
+ FOR(m = k; m < i; m++)
+ {
+ norm_sum = sub(norm_sum,y_index[m]);
+ R_temp_fx[m] = 0;
+ move32();/*Q21 */
+ }
+ i = k;
+ BREAK;
+ }
+ ELSE
+ {
+ R_sum_fx = L_add(R_sum_fx,R_temp_fx[k]);
+ }
+ }
+ IF (L_sub(R_sum_fx,R_sum_org_fx) == 0)
+ {
+ BREAK;
+ }
+
+ R_sum_org_fx = R_sum_fx;
+ }
+ }
+
+ /* index comeback */
+ FOR ( k = 0 ; k < band_num; k++ )
+ {
+ j = index[k];
+ move16();
+ Rsubband_fx[add(j,start_band)] = R_temp_fx[k];
+ move32();
+ }
+
+ return;
+
+}
+
+/*-------------------------------------------------------------------*
+ * BitAllocWB()
+ *
+ * WB bit allocation
+ *-------------------------------------------------------------------*/
+
+short BitAllocWB (
+ short *y, /* i : norm of sub-vectors */
+ short B, /* i : number of available bits */
+ short N, /* i : number of sub-vectors */
+ short *R, /* o : bit-allocation indicator */
+ short *Rsubband /* o : sub-band bit-allocation vector (Q3) */
+)
+{
+ Word16 t_fx;
+ Word16 i, j, k, B1, B2, B3, B_saved;
+ Word16 Rsum_fx, Rsum_sub_fx[3];
+ Word32 Ravg_sub_32_fx[3], R_diff_32_fx[2];
+ Word16 factor_fx[2];/*Q13 */
+ Word16 BANDS;
+ Word16 tmp,exp;
+ Word32 L_tmp,L_tmp1;
+ Word32 Rsubband_buf[NB_SFM];
+ UWord16 lo;
+
+ BANDS = N;
+ move16();
+ IF( sub(BANDS,SFM_N) > 0)
+ {
+ BANDS = SFM_N;
+ move16();
+ }
+ /* Init Rsubband to non-zero values for bands to be allocated bits */
+ FOR (k = 0; k < BANDS; k++)
+ {
+ Rsubband_buf[k] = 2097152;
+ move32();/*Q21 */
+ }
+ /* Calculate the norm sum and average of sub-band */
+ Rsum_sub_fx[0] = 0;
+ FOR ( j = 0; j < SFM_G1; j++ )
+ {
+ IF ( y[j] > 0 )
+ {
+ Rsum_sub_fx[0] = add(Rsum_sub_fx[0],y[j]);
+ move16();/*Q0 */
+ }
+ }
+ Ravg_sub_32_fx[0] = L_mult(Rsum_sub_fx[0], 2048);
+ move32();/*Q16 0+15+1 , q15 1/16 =2048 */
+
+ Rsum_sub_fx[1] = 0;
+ move32();
+ FOR ( j = SFM_G1; j < SFM_G1G2; j++ )
+ {
+ IF ( y[j] > 0 )
+ {
+ Rsum_sub_fx[1] = add(Rsum_sub_fx[1],y[j]);
+ move16();/*Q0 */
+ }
+ }
+ Ravg_sub_32_fx[1] = L_mult(Rsum_sub_fx[1], 4096); /*16 0+15+1 , q15 1/8 =4096 */
+
+ Rsum_sub_fx[2] = 0;
+ move16();
+ FOR ( j = SFM_G1G2; j < BANDS; j++ )
+ {
+ IF ( y[j] > 0 )
+ {
+ Rsum_sub_fx[2] = add(Rsum_sub_fx[2],y[j]);
+ move16();/*Q0 */
+ }
+ }
+ tmp = div_s(1, BANDS-SFM_G1G2); /*Q15 */
+ Ravg_sub_32_fx[2] = L_mult(Rsum_sub_fx[2], tmp);
+ move32();/*Q16 */
+
+ /* Bit allocation for every group */
+ tmp = add(Rsum_sub_fx[0],Rsum_sub_fx[1]);
+ Rsum_fx = add(tmp,Rsum_sub_fx[2]);/*Q0 */
+
+ factor_fx[0] = 16384;/*Q13 move16(); */
+ factor_fx[1] = 24576;/*Q13 move16(); */
+ {
+ R_diff_32_fx[0] = L_sub(Ravg_sub_32_fx[0], Ravg_sub_32_fx[1]);
+ move32();/*Q16 */
+ R_diff_32_fx[1] = L_sub(Ravg_sub_32_fx[1], Ravg_sub_32_fx[2]);
+ move32();/*Q16 */
+
+ IF ( L_sub(R_diff_32_fx[0],393216) < 0 && L_sub(R_diff_32_fx[1],245760) < 0 )
+ {
+ IF(Rsum_fx == 0)
+ {
+ B1 = 0;
+ move16();
+ B2 = 0;
+ move16();
+ B3 = 0;
+ move16();
+ }
+ ELSE
+ {
+ exp = norm_s(Rsum_fx);
+ tmp = shl(Rsum_fx,exp);/*Q(exp) */
+ tmp = div_s(16384,tmp);/*Q(15+14-exp) */
+ L_tmp1 = L_mult(B,Rsum_sub_fx[0]);/*Q1 */
+ Mpy_32_16_ss(L_tmp1,tmp,&L_tmp,&lo);
+ B1 = extract_h(L_shl(L_tmp,add(exp,1)));/*Q0 */
+ IF(L_sub(L_tmp1,L_mult(B1,Rsum_fx)) > 0 && L_sub(L_tmp1,L_mult(add(B1,1),Rsum_fx)) >= 0)
+ {
+ B1 = add(B1,1);
+ }
+ L_tmp1 = L_mult(B,Rsum_sub_fx[1]);/*Q1 */
+ Mpy_32_16_ss(L_tmp1,tmp,&L_tmp,&lo);
+ B2 = extract_h(L_shl(L_tmp,add(exp,1)));/*Q0 */
+ IF(L_sub(L_tmp1,L_mult(B2,Rsum_fx)) > 0 && L_sub(L_tmp1,L_mult(add(B2,1),Rsum_fx)) >= 0)
+ {
+ B2 = add(B2,1);
+ }
+ L_tmp1 = L_mult(B,Rsum_sub_fx[2]);/*Q1 */
+ Mpy_32_16_ss(L_tmp1,tmp,&L_tmp,&lo);
+ B3 = extract_h(L_shl(L_tmp,add(exp,1)));/*Q0 */
+ IF(L_sub(L_tmp1,L_mult(B3,Rsum_fx)) > 0 && L_sub(L_tmp1,L_mult(add(B3,1),Rsum_fx)) >= 0)
+ {
+ B3 = add(B3,1);
+ }
+ }
+ IF ( L_sub(Ravg_sub_32_fx[2],786432) > 0 )
+ {
+ B_saved = 0;
+ move16();
+ IF ( sub(B1,288) > 0 )
+ {
+ B_saved = sub(B1,288);
+ B1 = 288;
+ move16();
+ }
+
+ IF ( sub(B2,256) > 0 )
+ {
+ tmp = sub(B2,256);
+ B_saved = add(B_saved,tmp);
+ B2 = 256;
+ move16();
+ }
+
+ IF ( sub(B3,96) > 0 )
+ {
+ tmp = sub(B3,96);
+ B_saved = add(B_saved,tmp);
+ B3 = 96;
+ move16();
+ }
+
+ IF ( B_saved > 0 )
+ {
+ IF ( sub(B1,288) == 0 )
+ {
+ tmp = shr(B_saved,1);
+ B2 = add(B2,tmp);
+ tmp = sub(B,B1);
+ B3 = sub(tmp,B2);
+ }
+ ELSE
+ {
+ tmp = shr(B_saved,1);
+ B1 = add(B1,tmp);
+ IF ( sub(B2,256) == 0 )
+ {
+ tmp = sub(B,B1);
+ B3 = sub(tmp,B2);
+ }
+ ELSE
+ {
+ tmp = sub(B,B1);
+ B2 = sub(tmp,B3);
+ }
+ }
+ }
+ }
+
+ factor_fx[0] = 16384;
+ move16();/*Q13 */
+ factor_fx[1] = 12288;
+ move16();/*Q13 */
+ }
+ ELSE
+ {
+ IF(Rsum_fx == 0)
+ {
+ B1 = 0;
+ move16();
+ B2 = 0;
+ move16();
+ B3 = B;
+ move16();
+ }
+ ELSE
+ {
+ exp = norm_s(Rsum_fx);
+ tmp = shl(Rsum_fx,exp);/*Q(exp) */
+ tmp = div_s(16384,tmp);/*Q(15+14-exp) */
+ L_tmp1 = L_mult(B,Rsum_sub_fx[0]);/*Q1 */
+ Mpy_32_16_ss(L_tmp1,tmp,&L_tmp,&lo);
+ B1 = extract_h(L_shl(L_tmp,add(exp,1)));/*Q0 */
+ IF(L_sub(L_tmp1,L_mult(B1,Rsum_fx)) > 0 && L_sub(L_tmp1,L_mult(add(B1,1),Rsum_fx)) >= 0)
+ {
+ B1 = add(B1,1);
+ }
+ Mpy_32_16_ss(1975684956,shl(B,5),&L_tmp1,&lo);
+ Mpy_32_16_ss(L_tmp1,shl(Rsum_sub_fx[1],7),&L_tmp1,&lo);
+ Mpy_32_16_ss(L_tmp1,tmp,&L_tmp,&lo);
+ B2 = extract_h(L_shl(L_tmp,sub(exp,11)));/*Q0 */
+ IF(L_sub(L_tmp1,L_shl(L_mult(B2,Rsum_fx),12)) > 0 && L_sub(L_add(L_tmp1,2),L_shl(L_mult(add(B2,1),Rsum_fx),12)) >= 0)
+ {
+ B2 = add(B2,1);
+ }
+ tmp = sub(B,B1);
+ B3 = sub(tmp,B2);
+ }
+ }
+ }
+
+ IF ( sub(Rsum_sub_fx[2],3) < 0 )
+ {
+ B2 = add(B2,B3);
+ B3 = 0;
+ move16();
+ }
+
+ /* Bit allocation in group */
+ Bit_group_fx( y, 0, SFM_G1, B1, 5, Rsubband_buf, factor_fx);
+ Bit_group_fx( y, SFM_G1, SFM_G1G2, B2, 6, Rsubband_buf, factor_fx);
+ Bit_group_fx( y, SFM_G1G2, BANDS, B3, 7, Rsubband_buf, factor_fx);
+ FOR (i = 0; i < BANDS; i++)
+ {
+ Rsubband[i] = extract_l(L_shr(Rsubband_buf[i], 18));
+ move16();
+ }
+
+ /* Calcuate total used bits and initialize R to be used for Noise Filling */
+ L_tmp = 0;
+ move32();
+ FOR( i = 0; i < N; i++)
+ {
+ L_tmp = L_add(L_tmp,Rsubband_buf[i]);/*Q21 */
+ R[i] = extract_h(L_shr(Rsubband_buf[i],5));/*Q0 */
+ }
+ t_fx = extract_h(L_shr(L_tmp, 5)); /*Q0 */
+
+ return (Word16)t_fx;
+}
+
+#undef WMC_TOOL_SKIP
diff --git a/lib_com/bitallocsum.c b/lib_com/bitallocsum.c
new file mode 100644
index 0000000000000000000000000000000000000000..8ff41e2a2f685e5ef9402693695038e5609a0cb3
--- /dev/null
+++ b/lib_com/bitallocsum.c
@@ -0,0 +1,61 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include "options.h"
+#include "wmc_auto.h"
+#include "cnst.h"
+#include "prot.h"
+
+
+/*--------------------------------------------------------------------------
+ * bitallocsum()
+ *
+ * Calculate the total number of bits allocated over frame
+ *--------------------------------------------------------------------------*/
+
+void bitallocsum(
+ short *R, /* i : bit-allocation vector */
+ const short nb_sfm, /* i : number of sub-vectors */
+ short *sum, /* o : total number of bits allocated */
+ short *Rsubband, /* o : rate per subband (Q3) */
+ const short v, /* i : bit rate */
+ const short length, /* i : length of spectrum (32 or 48 kHz samplerate) */
+ const short *sfmsize /* i : band length */
+)
+{
+ short i;
+ short total, tmp;
+ short diff;
+
+ total = 0;
+ for (i = 0; i < nb_sfm; i++)
+ {
+ tmp = R[i] * sfmsize[i];
+ Rsubband[i] = tmp*8;
+ total += tmp;
+ }
+ *sum = total;
+
+ if ( length <= L_FRAME32k )
+ {
+ diff = v - *sum;
+ i = 0;
+ while ( diff > 0 )
+ {
+ if ( R[i] > 0 )
+ {
+ Rsubband[i] += 8;
+ diff -= 1;
+ *sum += 1;
+ }
+ i++;
+ if ( i >= nb_sfm )
+ {
+ i = 0;
+ }
+ }
+ }
+
+ return;
+}
diff --git a/lib_com/bits_alloc.c b/lib_com/bits_alloc.c
new file mode 100644
index 0000000000000000000000000000000000000000..f1dabff4f05abe804cb3134abba22a9b8be1cebd
--- /dev/null
+++ b/lib_com/bits_alloc.c
@@ -0,0 +1,309 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include
+#include "wmc_auto.h"
+#include
+#include
+#include "options.h"
+#include "rom_com.h"
+#include "prot.h"
+
+/*-------------------------------------------------------------------*
+* Local function
+*--------------------------------------------------------------------*/
+
+static int BITS_ALLOC_adjust_acelp_fixed_cdk( int bits_frame, int *fixed_cdk_index, int nb_subfr );
+
+
+/*-------------------------------------------------------------------*
+* BITS_ALLOC_init_config_acelp()
+*
+* initial configuration for Mode 2 ACELP
+*--------------------------------------------------------------------*/
+
+void BITS_ALLOC_init_config_acelp(
+ int bit_rate,
+ int narrowBand,
+ int nb_subfr,
+ ACELP_config *acelp_cfg /*o: configuration structure of ACELP*/
+)
+{
+ short rate_mode_index;
+
+ if( bit_rate <= ACELP_9k60 )
+ {
+ rate_mode_index=0;
+ }
+ else
+ {
+ rate_mode_index=1;
+ }
+
+ acelp_cfg->mode_index=rate_mode_index;
+
+ /*LPC: midLpc should be swithced off?*/
+ acelp_cfg->midLpc_enable = 1;
+
+ /*ACELP ICB config*/
+ if( (rate_mode_index==0) || (narrowBand==1) )
+ {
+ acelp_cfg->pre_emphasis = 1;
+ acelp_cfg->formant_enh = 1;
+ acelp_cfg->formant_enh_num = FORMANT_SHARPENING_G1;
+ acelp_cfg->formant_enh_den = FORMANT_SHARPENING_G2;
+ acelp_cfg->formant_tilt = 0;
+ acelp_cfg->voice_tilt = 0;
+ }
+ else
+ {
+ acelp_cfg->pre_emphasis = 0;
+ acelp_cfg->formant_enh = 1;
+ acelp_cfg->formant_enh_num = FORMANT_SHARPENING_G1;
+ acelp_cfg->formant_enh_den = FORMANT_SHARPENING_G2;
+ acelp_cfg->formant_tilt = 1;
+ acelp_cfg->voice_tilt = 1;
+ }
+
+ /*Wide band @ 16kHz*/
+ if ( nb_subfr == NB_SUBFR16k )
+ {
+ acelp_cfg->pre_emphasis = 1;
+ acelp_cfg->formant_enh = 1;
+ acelp_cfg->formant_enh_num = FORMANT_SHARPENING_G1_16k;
+ acelp_cfg->formant_enh_den = FORMANT_SHARPENING_G2_16k;
+ acelp_cfg->formant_tilt = 0;
+ acelp_cfg->voice_tilt = 2;
+ }
+
+ return;
+}
+
+/*-------------------------------------------------------------------*
+* BITS_ALLOC_config_acelp()
+*
+* configure all Mode 2 ACELP modes and allocate the bits
+*--------------------------------------------------------------------*/
+
+int BITS_ALLOC_config_acelp(
+ const int bits_frame, /* i : remaining bit budget for the frame */
+ const short coder_type, /* i : acelp extended mode index */
+ ACELP_config *acelp_cfg, /* i/o: configuration structure of ACELP */
+ const short narrowBand, /* i : narrowband flag */
+ const short nb_subfr /* i : number of subframes */
+)
+{
+ short mode_index;
+ short band_index;
+ short i;
+ short remaining_bits, bits;
+
+ /*Sanity check*/
+
+ mode_index = acelp_cfg->mode_index;
+ band_index = (narrowBand==0);
+ bits = 0;
+
+ if ( band_index==0 )
+ {
+ if(coder_type == INACTIVE)
+ {
+ acelp_cfg->formant_enh = 0;
+ }
+ else
+ {
+ acelp_cfg->formant_enh = 1;
+ }
+ }
+
+ if( band_index==1 && nb_subfr == NB_SUBFR )
+ {
+
+ if( coder_type == INACTIVE)
+ {
+ acelp_cfg->pre_emphasis = 0;
+ acelp_cfg->formant_enh = 0;
+ acelp_cfg->formant_enh_num = FORMANT_SHARPENING_G1_16k;
+ acelp_cfg->formant_tilt = 1;
+ acelp_cfg->voice_tilt = 1;
+ }
+ else
+ {
+ acelp_cfg->pre_emphasis = 1;
+ acelp_cfg->formant_enh = 1;
+ acelp_cfg->formant_enh_num = FORMANT_SHARPENING_G1;
+ acelp_cfg->formant_tilt = 0;
+ acelp_cfg->voice_tilt = 0;
+ }
+ }
+
+ if( coder_type == UNVOICED )
+ {
+ if( ACELP_GAINS_MODE[mode_index][band_index][coder_type]==6 )
+ {
+ acelp_cfg->pitch_sharpening = 0;
+ acelp_cfg->phase_scrambling = 1;
+ }
+ else
+ {
+ acelp_cfg->pitch_sharpening = 0;
+ acelp_cfg->phase_scrambling = 0;
+ }
+ }
+ else
+ {
+ acelp_cfg->pitch_sharpening = 1;
+ acelp_cfg->phase_scrambling = 0;
+ }
+
+ if( coder_type > ACELP_MODE_MAX )
+ {
+ /* keep pitch sharpening for RF_ALLPRED mode */
+ acelp_cfg->pitch_sharpening = 0;
+ acelp_cfg->phase_scrambling = 0;
+ }
+
+ /*Allocate bits and different modes*/
+ acelp_cfg->bpf_mode=ACELP_BPF_MODE[mode_index][band_index][coder_type];
+ bits+=ACELP_BPF_BITS[acelp_cfg->bpf_mode];
+
+ acelp_cfg->nrg_mode=ACELP_NRG_MODE[mode_index][band_index][coder_type];
+ acelp_cfg->nrg_bits=ACELP_NRG_BITS[acelp_cfg->nrg_mode];
+ bits+=acelp_cfg->nrg_bits;
+
+ acelp_cfg->ltp_mode=ACELP_LTP_MODE[mode_index][band_index][coder_type];
+ acelp_cfg->ltp_bits=0;
+ acelp_cfg->ltf_mode=ACELP_LTF_MODE[mode_index][band_index][coder_type];
+ acelp_cfg->ltf_bits=ACELP_LTF_BITS[acelp_cfg->ltf_mode];
+
+ if( nb_subfr == NB_SUBFR16k && acelp_cfg->ltf_bits == 4 )
+ {
+ acelp_cfg->ltf_bits++;
+ }
+ bits+=acelp_cfg->ltf_bits;
+
+
+ for ( i=0; igains_mode[i] = ACELP_GAINS_MODE[mode_index][band_index][coder_type];
+
+ /* skip subframe 1, 3 gain encoding, and use from subframe 0, and 3, respectively */
+ if(coder_type >= ACELP_MODE_MAX && (i == 1 || i == 3))
+ {
+ acelp_cfg->gains_mode[i] = 0;
+ }
+
+ bits += ACELP_GAINS_BITS[acelp_cfg->gains_mode[i]];
+ bits += ACELP_LTP_BITS_SFR[acelp_cfg->ltp_mode][i];
+ acelp_cfg->ltp_bits += ACELP_LTP_BITS_SFR[acelp_cfg->ltp_mode][i];
+ }
+
+ /*Innovation*/
+ if( bits_frame < bits )
+ {
+ printf("\nWarning: bits per frame too low\n");
+ return -1;
+ }
+
+ if( coder_type == RF_ALLPRED )
+ {
+ set_i(acelp_cfg->fixed_cdk_index, -1, nb_subfr);
+ }
+ else if ( coder_type == RF_GENPRED )
+ {
+ acelp_cfg->fixed_cdk_index[0] = 0; /* 7 bits */
+ acelp_cfg->fixed_cdk_index[1] = -1;
+ acelp_cfg->fixed_cdk_index[2] = 0; /* 7 bits */
+ acelp_cfg->fixed_cdk_index[3] = -1;
+ acelp_cfg->fixed_cdk_index[4] = -1;
+ bits += 14;
+ }
+ else if( coder_type == RF_NOPRED )
+ {
+ set_i(acelp_cfg->fixed_cdk_index, 0, nb_subfr);
+ bits += 28;
+ }
+ else
+ {
+ bits += BITS_ALLOC_adjust_acelp_fixed_cdk(bits_frame - bits, acelp_cfg->fixed_cdk_index, nb_subfr );
+ }
+
+ remaining_bits = bits_frame-bits;
+
+ /*Sanity check*/
+ if( remaining_bits < 0 )
+ {
+ bits = -1;
+ }
+
+
+ return( bits );
+}
+
+/*-------------------------------------------------------------------*
+* BITS_ALLOC_adjust_acelp_fixed_cdk()
+*
+*
+*--------------------------------------------------------------------*/
+
+static int BITS_ALLOC_adjust_acelp_fixed_cdk(
+ int bits_frame, /*i: bit budget*/
+ int *fixed_cdk_index,
+ int nb_subfr
+)
+{
+ int bits_subframe2;
+ int sfr, k, bitsused, bits_currsubframe;
+
+ bits_subframe2 = bits_frame;
+
+ if( bits_subframe2 < ACELP_FIXED_CDK_BITS(0)*nb_subfr )
+ {
+ return(bits_frame+1 ); /* Not enough bits for lowest mode. -> trigger alarm*/
+ }
+
+ /* search cdk-index for first subframe */
+ for (k=0; k bits_subframe2)
+ {
+ k--; /* previous mode did not exceed bit-budget */
+ break;
+ }
+ }
+
+ if( ACELP_FIXED_CDK_BITS(k)*nb_subfr > bits_subframe2 )
+ {
+ k--; /* previous mode did not exceed bit-budget */
+ }
+ fixed_cdk_index[0] = k;
+ bitsused = ACELP_FIXED_CDK_BITS(k);
+
+ for (sfr=1; sfr < nb_subfr; sfr++)
+ {
+ bits_currsubframe = (sfr*bits_subframe2 + bits_subframe2) - bitsused*nb_subfr;
+
+ /* try increasing mode while below threshold */
+ while ( (k < ACELP_FIXED_CDK_NB-1) && (ACELP_FIXED_CDK_BITS(k+1)*nb_subfr <= bits_currsubframe) )
+ {
+ k++;
+ }
+
+ /* try decreasing mode until below threshold */
+ while (ACELP_FIXED_CDK_BITS(k)*nb_subfr > bits_currsubframe)
+ {
+ k--;
+ if ( k == 0 )
+ {
+ break;
+ }
+ }
+
+ /* store mode */
+ fixed_cdk_index[sfr] = k;
+ bitsused += ACELP_FIXED_CDK_BITS(k);
+ }
+
+ return bitsused;
+}
diff --git a/lib_com/bitstream.c b/lib_com/bitstream.c
new file mode 100644
index 0000000000000000000000000000000000000000..ce3b2fe0f7e2fc39c9840402d8217f414a8b5b7f
--- /dev/null
+++ b/lib_com/bitstream.c
@@ -0,0 +1,2264 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include
+#include "wmc_auto.h"
+#include "options.h"
+#include "cnst.h"
+#include "prot.h"
+#include "stat_enc.h"
+#include "stat_dec.h"
+#include "rom_com.h"
+#include "mime.h"
+
+
+
+
+/*-------------------------------------------------------------------*
+* pack_bit()
+*
+* insert a bit into packed octet
+*-------------------------------------------------------------------*/
+static void pack_bit(
+ const Word16 bit, /* i: bit to be packed */
+ UWord8 **pt, /* i/o: pointer to octet array into which bit will be placed */
+ UWord8 *omask /* i/o: output mask to indicate where in the octet the bit is to be written */
+)
+{
+ if (*omask == 0x80)
+ {
+ **pt = 0;
+ }
+ if (bit != 0)
+ {
+ **pt = **pt | *omask;
+ }
+ *omask >>= 1;
+ if (*omask == 0)
+ {
+ *omask = 0x80;
+ (*pt)++;
+ }
+
+ return;
+}
+
+/*-------------------------------------------------------------------*
+* unpack_bit()
+*
+* unpack a bit from packed octet
+*-------------------------------------------------------------------*/
+static Word16 unpack_bit(
+ UWord8 **pt, /* i/o: pointer to octet array from which bit will be read */
+ UWord8 *mask /* i/o: mask to indicate the bit in the octet */
+)
+{
+ Word16 bit;
+
+ bit = (**pt & *mask) != 0;
+ *mask >>= 1;
+ if (*mask == 0)
+ {
+ *mask = 0x80;
+ (*pt)++;
+ }
+
+ return bit;
+}
+
+/*-------------------------------------------------------------------*
+* rate2AMRWB_IOmode()
+*
+* lookup AMRWB IO mode
+*-------------------------------------------------------------------*/
+
+static Word16 rate2AMRWB_IOmode(
+ Word32 rate /* i: bit rate */
+)
+{
+ switch ( rate )
+ {
+ /* EVS AMR-WB IO modes */
+ case SID_1k75 :
+ return AMRWB_IO_SID;
+ case ACELP_6k60 :
+ return AMRWB_IO_6600;
+ case ACELP_8k85 :
+ return AMRWB_IO_8850;
+ case ACELP_12k65 :
+ return AMRWB_IO_1265;
+ case ACELP_14k25 :
+ return AMRWB_IO_1425;
+ case ACELP_15k85 :
+ return AMRWB_IO_1585;
+ case ACELP_18k25 :
+ return AMRWB_IO_1825;
+ case ACELP_19k85 :
+ return AMRWB_IO_1985;
+ case ACELP_23k05 :
+ return AMRWB_IO_2305;
+ case ACELP_23k85 :
+ return AMRWB_IO_2385;
+ }
+ return -1;
+}
+
+/*-------------------------------------------------------------------*
+* rate2EVSmode()
+*
+* lookup EVS mode
+*-------------------------------------------------------------------*/
+static Word16 rate2EVSmode(
+ Word32 rate /* i: bit rate */
+)
+{
+ switch ( rate )
+ {
+ /* EVS Primary modes */
+ case FRAME_NO_DATA :
+ return NO_DATA;
+ case SID_2k40 :
+ return PRIMARY_SID;
+ case PPP_NELP_2k80 :
+ return PRIMARY_2800;
+ case ACELP_7k20 :
+ return PRIMARY_7200;
+ case ACELP_8k00 :
+ return PRIMARY_8000;
+ case ACELP_9k60 :
+ return PRIMARY_9600;
+ case ACELP_13k20 :
+ return PRIMARY_13200;
+ case ACELP_16k40 :
+ return PRIMARY_16400;
+ case ACELP_24k40 :
+ return PRIMARY_24400;
+ case ACELP_32k :
+ return PRIMARY_32000;
+ case ACELP_48k :
+ return PRIMARY_48000;
+ case ACELP_64k :
+ return PRIMARY_64000;
+ case HQ_96k :
+ return PRIMARY_96000;
+ case HQ_128k :
+ return PRIMARY_128000;
+ }
+ return rate2AMRWB_IOmode(rate);
+}
+
+/*-------------------------------------------------------------------*
+ * push_indice()
+ *
+ * Push a new indice into the buffer
+ *-------------------------------------------------------------------*/
+
+void push_indice(
+ Encoder_State *st, /* i/o: encoder state structure */
+ short id, /* i : ID of the indice */
+ unsigned short value, /* i : value of the quantized indice */
+ short nb_bits /* i : number of bits used to quantize the indice */
+)
+{
+ short i;
+
+
+ if ( st->last_ind == id )
+ {
+ /* indice with the same name as the previous one */
+ i = st->next_ind;
+ }
+ else
+ {
+ /* new indice - find an empty slot in the list */
+ i = id;
+ while (st->ind_list[i].nb_bits != -1)
+ {
+ i++;
+ }
+ }
+
+ /* store the new indice in the list */
+ st->ind_list[i].value = value;
+ st->ind_list[i].nb_bits = nb_bits;
+
+ /* updates */
+ st->next_ind = i + 1;
+ st->last_ind = id;
+ st->nb_bits_tot += nb_bits;
+
+ return;
+}
+
+/*-------------------------------------------------------------------*
+ * push_next_indice()
+ *
+ * Push a new indice into the buffer at the next position
+ *-------------------------------------------------------------------*/
+
+void push_next_indice(
+ Encoder_State *st, /* i/o: encoder state structure */
+ unsigned short value, /* i : value of the quantized indice */
+ short nb_bits /* i : number of bits used to quantize the indice */
+)
+{
+
+ /* store the values in the list */
+ st->ind_list[st->next_ind].value = value;
+ st->ind_list[st->next_ind].nb_bits = nb_bits;
+ st->next_ind++;
+
+ /* update the total number of bits already written */
+ st->nb_bits_tot += nb_bits;
+
+ return;
+}
+
+/*-------------------------------------------------------------------*
+ * push_next_bits()
+ * Push a bit buffer into the buffer at the next position
+ *-------------------------------------------------------------------*/
+
+void push_next_bits(
+ Encoder_State *st, /* i/o: encoder state structure */
+ int bits[], /* i : bit buffer to pack, sequence of single bits */
+ short nb_bits /* i : number of bits to pack */
+)
+{
+ unsigned short code;
+ int i, nb_bits_m15;
+ Indice *ptr;
+
+ ptr = &st->ind_list[st->next_ind];
+ nb_bits_m15 = nb_bits - 15;
+
+ for (i=0; ivalue = code;
+ ptr->nb_bits = 16;
+ ++ptr;
+ }
+ for (; ivalue = bits[i];
+ ptr->nb_bits = 1;
+ ++ptr;
+ }
+ st->next_ind = (int)(ptr - st->ind_list);
+ st->nb_bits_tot = st->nb_bits_tot + nb_bits;
+}
+
+/*-------------------------------------------------------------------*
+ * get_next_indice()
+ *
+ * Get the next indice from the buffer
+ *-------------------------------------------------------------------*/
+
+unsigned short get_next_indice( /* o : value of the indice */
+ Decoder_State *st, /* i/o: decoder state structure */
+ short nb_bits /* i : number of bits that were used to quantize the indice */
+)
+{
+ unsigned short value;
+ short i;
+
+ assert(nb_bits <= 16);
+
+ /* detect corrupted bitstream */
+ if( st->next_bit_pos + nb_bits > st->total_brate/50 )
+ {
+ st->BER_detect = 1;
+ return(0);
+ }
+
+ value = 0;
+ for (i = 0; i < nb_bits; i++)
+ {
+ value <<= 1;
+ value += st->bit_stream[st->next_bit_pos+i];
+ }
+
+ /* update the position in the bitstream */
+ st->next_bit_pos += nb_bits;
+
+ return value;
+}
+
+/*-------------------------------------------------------------------*
+ * get_next_indice_1()
+ *
+ * Get the next 1-bit indice from the buffer
+ *-------------------------------------------------------------------*/
+
+unsigned short get_next_indice_1( /* o : value of the indice */
+ Decoder_State *st /* i/o: decoder state structure */
+)
+{
+
+ /* detect corrupted bitstream */
+ if(
+ ( st->next_bit_pos + 1 > st->total_brate/50 && st->codec_mode == MODE1 ) ||
+ ( (st->next_bit_pos + 1 > st->total_brate/50 + (2*8) ) && st->codec_mode == MODE2 ) /* add two zero bytes for arithmetic coder flush */
+ )
+ {
+ st->BER_detect = 1;
+ return(0);
+ }
+
+ return st->bit_stream[st->next_bit_pos++];
+}
+
+/*-------------------------------------------------------------------*
+ * get_next_indice_tmp()
+ *
+ * update the total number of bits and the position in the bitstream
+ *-------------------------------------------------------------------*/
+
+void get_next_indice_tmp(
+ Decoder_State *st, /* o : decoder state structure */
+ short nb_bits /* i : number of bits that were used to quantize the indice */
+)
+{
+ /* update the position in the bitstream */
+ st->next_bit_pos += nb_bits;
+
+}
+
+/*-------------------------------------------------------------------*
+ * get_indice()
+ *
+ * Get indice at specific position in the buffer
+ *-------------------------------------------------------------------*/
+
+unsigned short get_indice( /* o : value of the indice */
+ Decoder_State *st, /* i/o: decoder state structure */
+ short pos, /* i : absolute position in the bitstream (update after the read) */
+ short nb_bits /* i : number of bits that were used to quantize the indice */
+)
+{
+ unsigned short value;
+ int i;
+
+ assert(nb_bits <= 16);
+
+ /* detect corrupted bitstream */
+ if( pos + nb_bits > st->total_brate/50 )
+ {
+ st->BER_detect = 1;
+ return(0);
+ }
+
+ value = 0;
+ for (i = 0; i < nb_bits; i++)
+ {
+ value <<= 1;
+ value += st->bit_stream[pos+i];
+ }
+
+ return value;
+}
+
+/*-------------------------------------------------------------------*
+ * get_indice_1()
+ *
+ * Get a 1-bit indice at specific position in the buffer
+ *-------------------------------------------------------------------*/
+
+unsigned short get_indice_1( /* o : value of the indice */
+ Decoder_State *st, /* i/o: decoder state structure */
+ short pos /* i : absolute position in the bitstream (update after the read) */
+)
+{
+ /* detect corrupted bitstream */
+ if( pos+1 > st->total_brate/50 )
+ {
+ st->BER_detect = 1;
+ return(0);
+ }
+
+ return st->bit_stream[pos];
+}
+
+/*-------------------------------------------------------------------*
+ * reset_indices_enc()
+ *
+ * Reset the buffer of encoder indices
+ *-------------------------------------------------------------------*/
+
+void reset_indices_enc(
+ Encoder_State *st
+)
+{
+ short i;
+
+ st->nb_bits_tot = 0;
+ st->next_ind = 0;
+ st->last_ind = -1;
+
+ for (i=0; iind_list[i].nb_bits = -1;
+ }
+
+ return;
+}
+
+/*-------------------------------------------------------------------*
+ * reset_indices_dec()
+ *
+ * Reset the buffer of decoder indices
+ *-------------------------------------------------------------------*/
+
+void reset_indices_dec(
+ Decoder_State *st
+)
+{
+ st->next_bit_pos = 0;
+
+ return;
+}
+
+/*-------------------------------------------------------------------*
+* write_indices()
+*
+* Write the buffer of indices to a file
+*-------------------------------------------------------------------*/
+
+void write_indices(
+ Encoder_State *st, /* i/o: encoder state structure */
+ FILE *file, /* i : output bitstream file */
+ UWord8 *pFrame, /* i: byte array with bit packet and byte aligned coded speech data */
+ Word16 pFrame_size /* i: size of the binary encoded access unit [bits] */
+)
+{
+ short i, k;
+ unsigned short stream[2+MAX_BITS_PER_FRAME], *pt_stream;
+ int mask;
+ short value, nb_bits;
+ UWord8 header;
+
+ if( st->bitstreamformat == G192 )
+ {
+ /*-----------------------------------------------------------------*
+ * Encode Sync Header and Frame Length
+ *-----------------------------------------------------------------*/
+
+ pt_stream = stream;
+ for (i=0; i<(2 + MAX_BITS_PER_FRAME); ++i)
+ {
+ stream[i] = 0;
+ }
+ *pt_stream++ = SYNC_GOOD_FRAME;
+ *pt_stream++ = st->nb_bits_tot;
+
+ /*----------------------------------------------------------------*
+ * Bitstream packing (conversion of individual indices into a serial stream)
+ * Writing the serial stream into file
+ * Clearing of indices
+ *----------------------------------------------------------------*/
+
+ for (i=0; iind_list[i].value;
+ nb_bits = st->ind_list[i].nb_bits;
+ if (nb_bits != -1)
+ {
+ /* mask from MSB to LSB */
+ mask = 1 << (nb_bits - 1);
+
+ /* write bit by bit */
+ for (k=0; k < nb_bits; k++)
+ {
+ if ( value & mask )
+ {
+ *pt_stream++ = G192_BIN1;
+ }
+ else
+ {
+ *pt_stream++ = G192_BIN0;
+ }
+
+ mask >>= 1;
+ }
+ }
+ }
+
+ }
+ else
+ {
+ /* Create and write ToC header */
+ /* qbit always set to 1 on encoder side for AMRWBIO , no qbit in use for EVS, but set to 0(bad) */
+ header = (UWord8)(st->Opt_AMR_WB << 5 | st->Opt_AMR_WB << 4 | rate2EVSmode(st->nb_bits_tot * 50));
+ fwrite( &header, sizeof(UWord8), 1, file );
+ /* Write speech bits */
+ fwrite( pFrame, sizeof(UWord8), (pFrame_size + 7)>>3, file );
+ }
+ /* Clearing of indices */
+ for (i=0; iind_list[i].nb_bits = -1;
+ }
+
+ if( st->bitstreamformat == G192 )
+ {
+ /* write the serial stream into file */
+ fwrite( stream, sizeof(unsigned short), 2+stream[1], file );
+ }
+
+
+ /* reset index pointers */
+ st->nb_bits_tot = 0;
+ st->next_ind = 0;
+ st->last_ind = -1;
+
+ return;
+}
+
+/*-------------------------------------------------------------------*
+ * indices_to_serial()
+ *
+ * pack indices into serialized payload format
+ *-------------------------------------------------------------------*/
+
+void indices_to_serial(
+ const Encoder_State *st, /* i: encoder state structure */
+ UWord8 *pFrame, /* o: byte array with bit packet and byte aligned coded speech data */
+ Word16 *pFrame_size /* o: size of the binary encoded access unit [bits] */
+)
+{
+ Word16 i, k, j;
+ Word16 cmi = 0, core_mode=0;
+ Word32 mask;
+ Word16 amrwb_bits[(ACELP_23k85 / 50)];
+ UWord8 omask= 0x80;
+ UWord8 *pt_pFrame=pFrame;
+
+ if ( st->Opt_AMR_WB )
+ {
+ cmi = rate2EVSmode(st->total_brate);
+ core_mode = rate2EVSmode(st->nb_bits_tot * 50);
+
+ j=0;
+ for (i=0; iind_list[i].nb_bits != -1)
+ {
+ /* mask from MSB to LSB */
+ mask = 1 << (st->ind_list[i].nb_bits - 1);
+
+ /* temporarily save bit */
+ for (k=0; k < st->ind_list[i].nb_bits; k++)
+ {
+ amrwb_bits[j++] = (st->ind_list[i].value & mask) > 0;
+ mask >>= 1;
+ }
+ }
+ }
+ }
+
+ *pFrame_size = st->nb_bits_tot;
+
+ /*----------------------------------------------------------------*
+ * Bitstream packing (conversion of individual indices into a serial stream)
+ *----------------------------------------------------------------*/
+ j=0;
+ for (i=0; iind_list[i].nb_bits != -1)
+ {
+ /* mask from MSB to LSB */
+ mask = 1 << (st->ind_list[i].nb_bits - 1);
+
+ /* write bit by bit */
+ for (k=0; k < st->ind_list[i].nb_bits; k++)
+ {
+ if (st->Opt_AMR_WB )
+ {
+ pack_bit(amrwb_bits[sort_ptr[core_mode][j++]], &pt_pFrame, &omask);
+ }
+ else
+ {
+ pack_bit(st->ind_list[i].value & mask, &pt_pFrame, &omask);
+ j++;
+ }
+ mask >>= 1;
+ }
+ }
+ }
+
+ if ( st->Opt_AMR_WB && core_mode == AMRWB_IO_SID) /* SID frame */
+ {
+ /* insert STI bit and CMI */
+ pack_bit(1, &pt_pFrame, &omask);
+ for (mask=0x08; mask>0; mask >>= 1)
+ {
+ pack_bit(cmi & mask, &pt_pFrame, &omask);
+ }
+ }
+
+ return;
+}
+
+/*-------------------------------------------------------------------*
+ * indices_to_serial_generic()
+ *
+ * pack indices into serialized payload format
+ *-------------------------------------------------------------------*/
+
+void indices_to_serial_generic(
+ const Indice *ind_list, /* i: indices list */
+ const Word16 num_indices, /* i: number of indices to write */
+ UWord8 *pFrame, /* o: byte array with bit packet and byte aligned coded speech data */
+ Word16 *pFrame_size /* i/o: number of bits in the binary encoded access unit [bits] */
+)
+{
+ Word16 i, k, j;
+ Word32 mask;
+ UWord8 omask;
+ UWord8 *pt_pFrame = pFrame;
+ Word16 nb_bits_tot = 0;
+
+ omask = (0x80 >> (*pFrame_size & 0x7));
+ pt_pFrame += *pFrame_size >> 3;
+
+ /*----------------------------------------------------------------*
+ * Bitstream packing (conversion of individual indices into a serial stream)
+ *----------------------------------------------------------------*/
+ j=0;
+ for (i=0; i>= 1;
+ }
+ nb_bits_tot += ind_list[i].nb_bits;
+ }
+ }
+
+ *pFrame_size += nb_bits_tot;
+
+ return;
+}
+
+/*-------------------------------------------------------------------*
+ * decoder_selectCodec()
+ *
+ *
+ *-------------------------------------------------------------------*/
+
+static void decoder_selectCodec(
+ Decoder_State *st, /* i/o: decoder state structure */
+ const long total_brate, /* i : total bitrate */
+ const short bit0 /* i : first bit */
+)
+{
+ /* set the AMR-WB IO flag */
+ if( total_brate == SID_1k75 ||
+ total_brate == ACELP_6k60 || total_brate == ACELP_8k85 || total_brate == ACELP_12k65 ||
+ total_brate == ACELP_14k25 || total_brate == ACELP_15k85 || total_brate == ACELP_18k25 ||
+ total_brate == ACELP_19k85 || total_brate == ACELP_23k05 || total_brate == ACELP_23k85 )
+ {
+ st->Opt_AMR_WB = 1;
+ }
+ else if ( total_brate != FRAME_NO_DATA )
+ {
+ st->Opt_AMR_WB = 0;
+ }
+
+ if ( st->Opt_AMR_WB )
+ {
+ st->codec_mode = MODE1;
+ }
+ else
+ {
+ switch ( total_brate )
+ {
+ case 0:
+ st->codec_mode = st->last_codec_mode;
+ break;
+ case 2400:
+ st->codec_mode = st->last_codec_mode;
+ break;
+ case 2800:
+ st->codec_mode = MODE1;
+ break;
+ case 7200:
+ st->codec_mode = MODE1;
+ break;
+ case 8000:
+ st->codec_mode = MODE1;
+ break;
+ case 9600:
+ st->codec_mode = MODE2;
+ break;
+ case 13200:
+ st->codec_mode = MODE1;
+ break;
+ case 16400:
+ st->codec_mode = MODE2;
+ break;
+ case 24400:
+ st->codec_mode = MODE2;
+ break;
+ case 32000:
+ st->codec_mode = MODE1;
+ break;
+ case 48000:
+ st->codec_mode = MODE2;
+ break;
+ case 64000:
+ st->codec_mode = MODE1;
+ break;
+ case 96000:
+ st->codec_mode = MODE2;
+ break;
+ case 128000:
+ st->codec_mode = MODE2;
+ break;
+ default : /* validate that total_brate (derived from RTP packet or a file header) is one of the defined bit rates */
+ st->codec_mode = st->last_codec_mode;
+ st->bfi = 1;
+ break;
+ }
+ }
+
+ if( st->ini_frame == 0 )
+ {
+ if( st->codec_mode == -1 )
+ {
+ st->codec_mode = MODE1;
+ }
+ st->last_codec_mode = st->codec_mode;
+ }
+
+ /* set SID/CNG type */
+ if( total_brate == SID_2k40 )
+ {
+ if( bit0 == G192_BIN0 )
+ {
+ st->cng_type = LP_CNG;
+
+ /* force MODE1 when selecting LP_CNG */
+ st->codec_mode = MODE1;
+ }
+ else
+ {
+ st->cng_type = FD_CNG;
+ if ( st->last_codec_mode == MODE2 && st->last_total_brate == ACELP_13k20 )
+ {
+ st->codec_mode = MODE1;
+ }
+ }
+ st->last_cng_type = st->cng_type; /* CNG type switching at the first correctly received SID frame */
+ }
+
+
+ return;
+}
+
+/*-------------------------------------------------------------------*
+ * dec_prm_core()
+ *
+ *
+ *-------------------------------------------------------------------*/
+
+void dec_prm_core(
+ Decoder_State *st
+)
+{
+ int n, frame_size_index = -1;
+
+ st->core = -1;
+
+ if (st->total_brate == FRAME_NO_DATA)
+ {
+ st->m_frame_type = ZERO_FRAME;
+ }
+ else if (st->total_brate == SID_2k40)
+ {
+ st->m_frame_type = SID_FRAME;
+ }
+ else
+ {
+ st->m_frame_type = ACTIVE_FRAME;
+ for (n=0; ntotal_brate/50)
+ {
+ frame_size_index = n;
+ break;
+ }
+ }
+
+ /* Get bandwidth mode */
+ st->bwidth = get_next_indice(st, FrameSizeConfig[frame_size_index].bandwidth_bits);
+ st->bwidth += FrameSizeConfig[frame_size_index].bandwidth_min;
+ if (st->bwidth > FB)
+ {
+ st->bwidth = FB;
+ st->BER_detect = 1;
+ }
+
+ if (st->bwidth > SWB && st->total_brate < ACELP_16k40)
+ {
+ st->bwidth = SWB;
+ st->BER_detect = 1;
+ }
+ /* Skip reserved bit */
+ get_next_indice_tmp(st, FrameSizeConfig[frame_size_index].reserved_bits);
+
+ if (get_next_indice_1(st)) /* TCX */
+ {
+ if (get_next_indice_1(st))
+ {
+ st->core = HQ_CORE;
+ }
+ else
+ {
+ st->core = TCX_20_CORE;
+ }
+ }
+ else /* ACELP */
+ {
+ st->core = ACELP_CORE;
+ }
+ }
+
+ return;
+}
+
+/*-----------------------------------------------------------------*
+ * decision_matrix_core_dec()
+ *
+ * Read core mode signalling bits from the bitstream
+ * Set st->core, and st->bwidth if signalled together with the core.
+ *-----------------------------------------------------------------*/
+
+static void decision_matrix_core_dec(
+ Decoder_State *st /* i/o: decoder state structure */
+)
+{
+ short start_idx;
+ long ind;
+ short nBits;
+
+ assert(st->bfi != 1);
+
+ st->core = -1;
+ st->bwidth = -1;
+
+ if ( st->total_brate == FRAME_NO_DATA || st->total_brate == SID_2k40 )
+ {
+ st->core = ACELP_CORE;
+ }
+ /* SC-VBR */
+ else if ( st->total_brate == PPP_NELP_2k80 )
+ {
+ st->core = ACELP_CORE;
+ return;
+ }
+
+ /*---------------------------------------------------------------------*
+ * ACELP/HQ core selection
+ *---------------------------------------------------------------------*/
+
+ if ( st->total_brate < ACELP_24k40 )
+ {
+ st->core = ACELP_CORE;
+ }
+ else if ( st->total_brate >= ACELP_24k40 && st->total_brate <= ACELP_64k )
+ {
+ /* read the ACELP/HQ core selection bit */
+ st->core = ((short) get_next_indice( st, 1 ))*HQ_CORE;
+ }
+ else
+ {
+ st->core = HQ_CORE;
+ }
+
+ /*-----------------------------------------------------------------*
+ * Read ACELP signalling bits from the bitstream
+ *-----------------------------------------------------------------*/
+
+ if ( st->core == ACELP_CORE )
+ {
+ /* find the section in the ACELP signalling table corresponding to bitrate */
+ start_idx = 0;
+ while ( acelp_sig_tbl[start_idx] != st->total_brate )
+ {
+ start_idx++;
+ }
+
+ /* skip the bitrate */
+ start_idx += 1;
+
+ /* retrieve the number of bits */
+ nBits = (short) acelp_sig_tbl[start_idx++];
+
+ /* retrieve the signalling indice */
+ ind = acelp_sig_tbl[start_idx + get_next_indice( st, nBits )];
+ st->bwidth = (ind >> 3) & 0x7;
+
+ /* convert signalling indice into signalling information */
+ if ( (ind & 0x7) == LR_MDCT )
+ {
+ st->core = HQ_CORE;
+ }
+ }
+
+ /*-----------------------------------------------------------------*
+ * Read HQ signalling bits from the bitstream
+ * Set HQ core type
+ *-----------------------------------------------------------------*/
+
+ if ( st->core == HQ_CORE )
+ {
+ /* read the HQ/TCX core switching flag */
+ if ( get_next_indice( st, 1 ) )
+ {
+ st->core = TCX_20_CORE;
+ }
+
+ /* For TCX: read/set band-width (needed for different I/O sampling rate support) */
+ if( st->core == TCX_20_CORE && st->total_brate > ACELP_16k40 )
+ {
+ ind = get_next_indice( st, 2 );
+
+ if( ind == 0 )
+ {
+ st->bwidth = NB;
+ }
+ else if( ind == 1 )
+ {
+ st->bwidth = WB;
+ }
+ else if( ind == 2 )
+ {
+ st->bwidth = SWB;
+ }
+ else
+ {
+ st->bwidth = FB;
+ }
+ }
+ }
+
+ return;
+}
+
+/*-------------------------------------------------------------------*
+ * mdct_switching_dec()
+ *
+ * Set up MDCT core switching if indicated in the bit stream
+ *-------------------------------------------------------------------*/
+
+static void mdct_switching_dec(
+ Decoder_State *st /* i/o: decoder state structure */
+)
+{
+ if (st->Opt_AMR_WB)
+ {
+ return;
+ }
+
+ if (st->total_brate == ACELP_13k20 || st->total_brate == ACELP_32k)
+ {
+ st->mdct_sw_enable = MODE1;
+ }
+ else if (ACELP_16k40 <= st->total_brate && st->total_brate <= ACELP_24k40)
+ {
+ st->mdct_sw_enable = MODE2;
+ }
+
+ if ( st->codec_mode == MODE1 && st->mdct_sw_enable == MODE1 )
+ {
+ /* Read ahead core mode signaling */
+ short next_bit_pos_save = st->next_bit_pos;
+ short core_save = st->core;
+ short bwidth_save = st->bwidth;
+
+ decision_matrix_core_dec(st); /* sets st->core */
+
+ if (st->core == TCX_20_CORE)
+ {
+ /* Trigger TCX */
+ st->codec_mode = MODE2;
+ st->mdct_sw = MODE1;
+ }
+ else
+ {
+ /* Rewind bitstream */
+ st->next_bit_pos = next_bit_pos_save;
+ if (st->bfi)
+ {
+ st->core = core_save;
+ st->bwidth = bwidth_save;
+ }
+ }
+ }
+ else if (st->codec_mode == MODE2 && st->mdct_sw_enable == MODE2)
+ {
+ /* Read ahead core mode signaling */
+ short next_bit_pos_save = st->next_bit_pos;
+ short core_save = st->core;
+ short bwidth_save = st->bwidth;
+
+ dec_prm_core(st); /* sets st->core */
+
+ if (st->core == HQ_CORE)
+ {
+ /* Trigger HQ_CORE */
+ st->codec_mode = MODE1;
+ st->mdct_sw = MODE2;
+ }
+ else
+ {
+ /* Rewind bitstream */
+ st->next_bit_pos = next_bit_pos_save;
+ if (st->bfi)
+ {
+ st->core = core_save;
+ }
+
+ /* always reset bwidth, to not interfere with BER logic */
+ st->bwidth = bwidth_save;
+ }
+ }
+
+ return;
+}
+
+
+
+/*-------------------------------------------------------------------*
+ * read_indices()
+ *
+ * Read indices from an ITU-T G.192 bitstream to the buffer
+ * Simulate packet losses by inserting frame erasures
+ *-------------------------------------------------------------------*/
+
+short read_indices( /* o : 1 = reading OK, 0 = problem */
+ Decoder_State *st, /* i/o: decoder state structure */
+ FILE *file, /* i : bitstream file */
+ const short rew_flag /* i : rewind flag (rewind file after reading)*/
+)
+{
+ short k;
+ unsigned short utmp, stream[2+MAX_BITS_PER_FRAME], *pt_stream;
+ unsigned short *bit_stream_ptr;
+ unsigned short num_bits;
+ long total_brate;
+ short curr_ft_good_sp, curr_ft_bad_sp;
+ short g192_sid_first,sid_upd_bad, sid_update;
+ short speech_bad, speech_lost;
+ unsigned short num_bits_read;
+
+ st->bfi = 0;
+ st->BER_detect = 0;
+ st->mdct_sw_enable = 0;
+ st->mdct_sw = 0;
+ reset_indices_dec( st );
+
+ /* read the Sync Header field from the bitstream */
+ /* in case rew_flag is set, read until first good frame is encountered */
+ do
+ {
+ /* read the Sync header */
+ if ( fread( &utmp, sizeof(unsigned short), 1, file ) != 1 )
+ {
+ if( ferror( file ) )
+ {
+ /* error during reading */
+ fprintf(stderr, "\nError reading the bitstream !");
+ exit(-1);
+ }
+ else
+ {
+ /* end of file reached */
+ return 0;
+ }
+ }
+
+ /* set the BFI indicator according the value of Sync Header */
+ if ( utmp == SYNC_BAD_FRAME )
+ {
+ st->bfi = 1;
+ }
+
+
+
+ else
+ {
+ st->bfi = 0;
+ }
+
+ /* read the Frame Length field from the bitstream */
+ if ( fread( &num_bits, sizeof(unsigned short), 1, file ) != 1 )
+ {
+ if( ferror( file ) )
+ {
+ /* error during reading */
+ fprintf(stderr, "\nError reading the bitstream !");
+ exit(-1);
+ }
+ else
+ {
+ /* end of file reached */
+ return 0;
+ }
+ }
+
+ /* convert the frame length to total bitrate */
+ total_brate = (long)(num_bits * 50);
+
+ /* read ITU-T G.192 serial stream of indices from file to the local buffer */
+ /* Validate that the G.192 length is within the defined bit rate range
+ to not allow writing past the end of the "stream" buffer */
+ if( num_bits > MAX_BITS_PER_FRAME )
+ {
+ fprintf(stderr, "\nError, too large G.192 frame (size(%d))! Exiting ! \n", num_bits);
+ exit(-1);
+ }
+
+ /* verify that a valid num bits value is present in the G.192 file */
+ /* only AMRWB or EVS bit rates or 0(NO DATA) are allowed in G.192 file frame reading */
+ if( rate2EVSmode(total_brate) < 0 ) /* negative value means that a valid rate was not found */
+ {
+ fprintf(stderr, "\nError, illegal bit rate (%ld) in the G.192 frame ! Exiting ! \n", total_brate);
+ exit(-1);
+ }
+ pt_stream = stream;
+ num_bits_read = (unsigned short) fread( pt_stream, sizeof(unsigned short), num_bits, file );
+ if( num_bits_read != num_bits )
+ {
+ fprintf(stderr, "\nError, invalid number of bits read ! Exiting ! \n");
+ exit(-1);
+ }
+
+ }
+ while ( rew_flag && (st->bfi || total_brate < 2800) );
+
+ /* G.192 RX DTX handler*/
+ if( !rew_flag )
+ {
+ /* handle SID_FIRST, SID_BAD, SPEECH_LOST, NO_DATA as properly as possible for the ITU-T G.192 format */
+ /* (total_brate, bfi , st_CNG) = rx_handler(received frame type, [previous frame type], past CNG state, past core) */
+ curr_ft_good_sp = 0;
+ curr_ft_bad_sp = 0;
+
+ if( total_brate > SID_2k40 )
+ {
+ if( st->bfi == 0 )
+ {
+ curr_ft_good_sp = 1;
+ }
+ else
+ {
+ curr_ft_bad_sp = 1;
+ }
+ }
+
+ sid_update = 0;
+ sid_upd_bad = 0;
+ if( total_brate == SID_1k75 || total_brate == SID_2k40 )
+ {
+ if( st->bfi == 0 )
+ {
+ sid_update = 1;
+ }
+ else
+ {
+ sid_upd_bad = 1; /* this frame type may happen in ETSI/3GPP CS cases , a corrupt sid frames */
+ }
+ }
+ /* all zero indeces/bits iSP AMRWB SID_update results in a valid LP filter with extremely high LP-filter-gain */
+ /* all zero indeces/bits may be a result of CS bit errors and/or erroneously injected by gateways or by a bad dejitter handlers */
+ if (total_brate == SID_1k75 && sid_update == 1)
+ {
+ /* valid sid_update received, check for very risky but formally valid content */
+ short sum = 0;
+ for (k = 0; k < num_bits; ++k)
+ {
+ sum += (pt_stream[k] == G192_BIN1);/* check of 35 zeroes */
+ }
+ if( sum == 0 )
+ { /* all zeros */
+ sid_upd_bad = 1; /* initial signal as corrupt (BER likely) */
+ }
+ }
+
+ /* AMRWB 26.173 G.192 file reader (read_serial) does not declare/use SID_BAD ft,
+ it declares every bad synch marked frame initially as a lost_speech frame,
+ and then the RXDTX handler CNG state decides the decoding mode CNG/SPEECH.
+ While In the AMRWB ETSI/3GPP format eid a CRC error in a detected SID_UPDATE frames triggers SID_BAD.
+
+ Here we inhibit use of the SID-length info, even though it is available in the G.192 file format after STL/EID-XOR .
+ */
+ if ( sid_upd_bad )
+ {
+ sid_upd_bad = 0;
+ total_brate = FRAME_NO_DATA ; /* treat SID_BAD as a stolen signaling frame --> SPEECH LOST */
+
+ }
+
+ g192_sid_first = 0;
+ if( st->core == AMR_WB_CORE && st->prev_ft_speech && total_brate == FRAME_NO_DATA && st->bfi == 0 )
+ {
+ g192_sid_first = 1; /* SID_FIRST detected for previous AMRWB/AMRWBIO active frames only */
+ /*
+ It is not possible to perfectly simulate rate switching conditions EVS->AMRWBIO where:
+ the very first SID_FIRST detection is based on a past EVS active frame
+ and a good length 0 "SID_FIRST"(NO_DATA) frame is sent in AMRWBIO,
+ , due to the one frame state memory in the AMRWB legacy G.192 SID_FIRST encoding
+ */
+ }
+
+ speech_bad = 0;
+ if( total_brate > SID_2k40 && st->bfi != 0 ) /* CS-type of CRC failure frame */
+ {
+ speech_bad = 1; /* initial ft assumption, CNG_state decides what to do */
+ }
+
+ speech_lost = 0;
+ if( total_brate == 0 && st->bfi != 0 ) /* unsent NO_DATA or stolen NO_DATA/signaling frame */
+ {
+ speech_lost = 1; /* initial ft assumption, CNG_state decides what to do */
+ }
+
+ /* Do not allow decoder to enter CNG-synthesis for any instantly received GOOD+LENGTH==0 frame
+ as this frame was never transmitted, one can not know it is good and has a a length of zero ) */
+
+ if( st->CNG != 0 )
+ {
+ /* We were in CNG synthesis */
+ if( curr_ft_good_sp != 0 )
+ {
+ /* only a good speech frame makes you leave CNG synthesis */
+ st->CNG = 0;
+ }
+ }
+ else
+ {
+ /* We were in SPEECH synthesis */
+ /* only a received/detected SID frame can make the decoder enter into CNG synthsis */
+ if( g192_sid_first || sid_update || sid_upd_bad )
+ {
+ st->CNG = 1;
+ }
+ }
+
+ /* set bfi, total_brate pair for proper decoding */
+ /* handle the G.192 _simulated_ untransmitted NO_DATA frame, setting for decoder SPEECH synthesis */
+ if ( (st->CNG==0) && (total_brate==0 && st->bfi == 0 ) )
+ {
+ st->bfi= 1; /* SPEECH PLC code will now become active as in a real system */
+ /* total_brate= 0 */
+ }
+
+ /* handle bad/lost speech frame(and CS bad sid frame) in the decoders CNG synthesis settings pair (total_brate, bfi) */
+ if( ((st->CNG != 0) && ( (speech_bad != 0) || (speech_lost != 0) )) || /* SP_BAD or SPEECH_LOST) --> stay in CNG */
+ ( sid_upd_bad != 0 )) /* SID_UPD_BAD --> start CNG */
+ {
+ st->bfi = 0; /* bfi=0 needed to activate CNG code */
+ total_brate = 0;
+ }
+ /* update for next frame's G.192 file format's odd SID_FIRST detection (primarily for AMRWBIO) */
+ st->prev_ft_speech = ((curr_ft_good_sp != 0) || (curr_ft_bad_sp != 0));
+
+ /* st->total brate= total_brate ; updated in a good frame below */
+ } /* rew_flag */
+
+ if ( st->bfi == 0 && !rew_flag )
+ {
+ /* select Mode 1 or Mode 2 */
+ decoder_selectCodec( st, total_brate, *pt_stream );
+ }
+
+ /* in case rew_flag is set, rewind the file and return */
+ /* (used in io_enc() to print out info about technologies and to initialize the codec) */
+ if ( rew_flag )
+ {
+ rewind( file );
+ st->total_brate = total_brate;
+ return 1;
+ }
+
+ /* GOOD frame */
+ if ( st->bfi == 0 )
+ {
+ /* GOOD frame - convert ITU-T G.192 words to short values */
+ bit_stream_ptr = st->bit_stream;
+
+ for ( k = 0; k < (short)num_bits; ++k )
+ {
+ *bit_stream_ptr++ = (*pt_stream++ == G192_BIN1);
+ }
+
+ /* add two zero bytes for arithmetic coder flush */
+ for (k=0; k<8*2; ++k)
+ {
+ *bit_stream_ptr++ = 0;
+ }
+ /* a change of the total bitrate should not be
+ known to the decoder, if the received frame was
+ lost */
+ st->total_brate = total_brate;
+
+ mdct_switching_dec(st);
+ }
+
+ return 1;
+}
+
+
+/*-------------------------------------------------------------------*
+ * read_indices_mime_handle_dtx()
+ *
+ * Handle DTX for MIME and RTP_DUMP decoding.
+ * Returns the actual total_brate.
+ *-------------------------------------------------------------------*/
+
+static Word32 read_indices_mime_handle_dtx(
+ Decoder_State *st,
+ Word16 isAMRWB_IOmode,
+ Word16 core_mode,
+ Word32 total_brate,
+ Word16 sti,
+ Word16 speech_lost,
+ Word16 no_data
+)
+{
+ Word16 curr_ft_good_sp = 0;
+ Word16 speech_bad = 0;
+ Word16 sid_upd_bad = 0, sid_update = 0;
+ Word16 amrwb_sid_first = 0; /* derived from sti SID_FIRST indicator in AMRWB payload */
+
+ /* keep st->CNG , st_bfi and total_brate updated for proper synthesis in DTX and FER */
+ if( total_brate > SID_2k40 )
+ {
+ if( st->bfi != 1 ) /* so far derived from q bit in AMRWB/AMRWBIO cases */
+ {
+ curr_ft_good_sp = 1;
+ }
+ }
+
+ /* handle q_bit and lost_sp clash , assume worst case */
+ if( speech_lost != 0 ) /* overrides a good q_bit */
+ {
+ curr_ft_good_sp = 0;
+ st->bfi = 1; /* override qbit */
+ }
+
+ /* now_bfi_fx has been set based on q_bit and ToC fields */
+
+ /* SID_UPDATE check */
+ if( total_brate == SID_1k75 || total_brate == SID_2k40 )
+ {
+ if( st->bfi == 0 )
+ {
+ /* typically from q bit */
+ sid_update = 1;
+ }
+ else
+ {
+ sid_upd_bad = 1; /* may happen in saving from e.g. a CS-connection */
+ }
+ }
+
+ if( isAMRWB_IOmode && total_brate == 0 && sti == 0 )
+ {
+ if( st->bfi )
+ {
+ sid_upd_bad = 1; /* corrupt sid_first, signaled as bad sid */
+ }
+ else
+ {
+ amrwb_sid_first = 1; /* 1-sti */
+ }
+ }
+
+ if ( sid_upd_bad != 0 && (
+ (isAMRWB_IOmode != 0 && st->Opt_AMR_WB==0 ) || /* switch to AMRWBIO */
+ (isAMRWB_IOmode != 1 && st->Opt_AMR_WB==1) /* switch from AMRWBIO */
+ ) )
+ {
+ /* do not allow a normal start of CNG synthesis if this SID(with BER or FER) is a switch to/from AMRWBIO */
+ sid_upd_bad = 0; /* revert this detection due to AMRWBIO/EVS mode switch */
+ total_brate = 0;
+ no_data = 1;
+ assert( st->bfi==1); /* bfi stays 1 */
+ }
+
+ if( total_brate > SID_2k40 && st->bfi == 1 ) /* typically from q bit */
+ {
+ speech_bad = 1; /* initial assumption, CNG synt state decides what to actually do */
+ }
+ /* all frame types decoded */
+
+ /* update CNG synthesis state */
+ /* Decoder can only enter CNG-synthesis for CNG frame types (sid_upd, sid_bad, sid_first) */
+ if( st->CNG != 0 )
+ {
+ /* We were in CNG synthesis */
+ if( curr_ft_good_sp != 0 )
+ {
+ /* only a good speech frame makes decoder leave CNG synthesis */
+ st->CNG = 0;
+ }
+ }
+ else
+ {
+ /* We were in SPEECH synthesis */
+ /* only a received SID frame can make the decoder enter into CNG synthesis */
+ if( amrwb_sid_first || sid_update || sid_upd_bad )
+ {
+ st->CNG = 1;
+ }
+ }
+
+ /* Now modify bfi flag for the decoder's SPEECH/CNG synthesis logic */
+ /* in SPEECH synthesis, make sure to activate speech plc for a received no_data frame,
+ no_data frames may be injected by the network or by the dejitter buffer */
+ /* modify bfi_flag to stay/move into the correct decoder PLC section */
+ if ( (st->CNG == 0) && ( no_data != 0 ) )
+ {
+ /* treat no_data received in speech synthesis as SP_LOST frames, SPEECH PLC code will now become active */
+ st->bfi = 1;
+ /* total_brate= 0; always zero for no_data */
+ }
+
+ /* in CNG */
+ /* handle bad speech frame(and bad sid frame) in the decoders CNG synthesis settings pair (total_brate, bfi) */
+ if( ( st->CNG != 0 && ( speech_bad || speech_lost || no_data )) || /* SP_BAD or SPEECH_LOST) --> stay in CNG */
+ sid_upd_bad ) /* SID_UPD_BAD --> start/stay CNG */
+ {
+ st->bfi = 0; /* mark as good to not start speech PLC */
+ total_brate = 0; /* this zeroing needed for speech_bad, sid_bad frames */
+ }
+
+
+ /* now bfi, total_brate are set by RX-DTX handler::
+ bfi==0, total_brate!=0 cng or speech pending bitrate
+ bfi==0, total_brate==0 cng will continue or start(sid_first, sid_bad)
+ bfi==1, total_brate!=0 speech plc
+ bfi==1, total_brate==0 , speech plc
+ */
+
+
+
+ /* handle available AMRWB/AMRWBIO MIME header ToC rate-info at startup */
+ if( ( st->bfi == 1 && st->ini_frame == 0) &&
+ ( (st->amrwb_rfc4867_flag != 0) || (st->amrwb_rfc4867_flag == 0 && isAMRWB_IOmode != 0 )) ) /*AMRWB ToC */
+ {
+ Word32 init_rate;
+
+ init_rate = total_brate; /* default , may have been modified from original ToC value */
+ if (speech_lost !=0 || no_data != 0 )
+ {
+ init_rate = ACELP_12k65; /* make sure the decoder starts up in a selected AMRWB mode */
+ }
+ else if( speech_bad !=0 )
+ {
+ init_rate = AMRWB_IOmode2rate[core_mode]; /* read from from ToC */
+ }
+ st->total_brate = init_rate; /* not updated on bfi as decoderSelectCodec is not called below */
+ st->core_brate = init_rate;
+ }
+
+ return total_brate;
+}
+
+
+/*-------------------------------------------------------------------*
+ * read_indices_mime_handle_sti_and_all_zero_bits()
+ *
+ * Handle STI and frames with all zero bits for MIME and RTP_DUMP decoding.
+ *-------------------------------------------------------------------*/
+static void read_indices_mime_handle_sti_and_all_zero_bits(
+ Decoder_State *st,
+ Word32 *total_brate,
+ Word16 sti
+)
+{
+ Word16 k, sum = 0;
+
+ if( sti == 0 )
+ {
+ *total_brate = 0; /* signal received SID_FIRST as a good frame with no bits */
+ for(k=0; k<35; k++)
+ {
+ st->bfi |= st->bit_stream[k] ; /* partity check of 35 zeroes, any single 1 gives BFI */
+ }
+ }
+ /* all zero bit SID_update results in a valid LP filter with extremely high LP-filter-gain */
+ /* all zero bits signal may be a result of CS bit errors or erronesouly injected by gateways or bad dejitter handlers */
+ if (sti == 1)
+ { /*sid_update received */
+ for (k = 0; k < 35; k++)
+ {
+ sum += st->bit_stream[k]; /* check of 35 zeroes */
+ }
+
+ if ( sum == 0 )
+ {
+ st->bfi = 1; /* eventually becomes SID_UPD_BAD */
+ }
+ }
+}
+
+
+/*-------------------------------------------------------------------*
+ * read_indices_mime()
+ *
+ * Read indices from MIME formatted bitstream to the buffer
+ *-------------------------------------------------------------------*/
+
+Word16 read_indices_mime( /* o : 1 = reading OK, 0 = problem */
+ Decoder_State *st, /* i/o: decoder state structure */
+ FILE *file, /* i : bitstream file */
+ Word16 rew_flag /* i : rewind flag (rewind file after reading)*/
+)
+{
+ Word16 k, isAMRWB_IOmode, cmi, core_mode = -1, qbit,sti;
+ UWord8 header;
+ UWord8 pFrame[(MAX_BITS_PER_FRAME + 7) >> 3];
+ UWord8 mask= 0x80, *pt_pFrame=pFrame;
+ UWord16 *bit_stream_ptr;
+ Word16 num_bits;
+ Word32 total_brate;
+ Word16 speech_lost = 0, no_data = 0;
+ Word16 num_bytes_read;
+
+ st->BER_detect = 0;
+ st->bfi = 0;
+ st->mdct_sw_enable = 0;
+ st->mdct_sw = 0;
+ reset_indices_dec( st );
+
+ /* read the FT Header field from the bitstream */
+ /* read the FT header */
+ if ( fread( &header, sizeof(UWord8), 1, file ) != 1 )
+ {
+ if( ferror( file ) )
+ {
+ /* error during reading */
+ fprintf(stderr, "\nError reading the bitstream !");
+ exit(-1);
+ }
+ else
+ {
+ /* end of file reached */
+ return 0;
+ }
+ }
+
+
+ /* init local RXDTX flags */
+ sti = -1;
+
+ if( st->amrwb_rfc4867_flag != 0 )
+ {
+ /* RFC 4867
+ 5.3 ....
+ Each stored speech frame starts with a one-octet frame header with
+ the following format:
+ 0 1 2 3 4 5 6 7
+ +-+-+-+-+-+-+-+-+
+ |P| FT |Q|P|P|
+ +-+-+-+-+-+-+-+-+
+ The FT field and the Q bit are defined in the same way as in
+ Section 4.3.2. The P bits are padding and MUST be set to 0, and MUST be ignored. */
+
+ isAMRWB_IOmode = 1;
+ qbit = (header>>2)&0x01 ; /* b2 bit (b7 is the F bit ) */
+ st->bfi = !qbit;
+ core_mode = ((header>>3) & 0x0F); /* b6..b3 */
+ total_brate = AMRWB_IOmode2rate[core_mode]; /* get the frame length from the header */
+ }
+ else
+ {
+ /*0 1 2 3 4 5 6 7 MS-bit ---> LS-bit
+ +-+-+-+-+-+-+-+-+
+ |H|F|E|x| brate |
+ +-+-+-+-+-+-+-+-+
+ where :
+ "E|x| brate " is the 6 bit "FT" -field
+ x is unused if E=0, (should be 0 )
+ x is the q-bit if E=1, q==1(good), Q==0(bad, maybe bit errors in payload )
+ H,F always 0 in RTP format.
+ */
+ isAMRWB_IOmode = (header & 0x20) > 0; /* get EVS mode-from header */ /* b2 */
+ core_mode = (header & 0x0F); /* b4,b5,b6,b7 */
+
+ if( isAMRWB_IOmode )
+ {
+ qbit = (header & 0x10) > 0; /* get Q bit, valid for IO rates */ /* b3 */
+ total_brate = AMRWB_IOmode2rate[core_mode];
+ }
+ else
+ {
+ qbit = 1; /* assume good q_bit for the unused EVS-mode bit, complete ToC validity checked later */
+ total_brate = PRIMARYmode2rate[ core_mode ];
+ }
+ st->bfi = !qbit;
+ }
+
+ /* set up RX-DTX-handler input */
+ if( core_mode == 14 )
+ {
+ /* SP_LOST */
+ speech_lost=1;
+ }
+ if ( core_mode == 15)
+ {
+ /* NO_DATA unsent CNG frame OR any frame marked or injected as no_data by e.g a signaling layer or dejitter buffer */
+ no_data=1;
+ }
+
+ num_bits = (Word16)(total_brate/50);
+ if( total_brate < 0 )
+ {
+ /* validate that total_brate (derived from RTP packet or a file header) is one of the defined bit rates */
+ fprintf(stderr, "\n Error illegal total bit rate (= %d) in MIME ToC header \n", total_brate );
+ num_bits = -1;
+ }
+
+ /* Check correctness of ToC headers */
+ if( st->amrwb_rfc4867_flag == 0 )
+ {
+ /* EVS ToC header (FT field(b2-b7), H bit (b0), F bit (b1) , (EVS-modebit(b2)=0 unused(Qbit)(b3)==0) */
+ if ( (isAMRWB_IOmode == 0) && ((num_bits < 0) || ((header & 0x80) > 0) || ((header & 0x40) > 0) || (header & 0x30) != 0x00 ) )
+ {
+ /* incorrect FT header */
+ fprintf(stderr, "\nError in EVS FT ToC header(%02x) ! ",header);
+ exit(-1);
+ }
+ else if( (isAMRWB_IOmode != 0) && ( (num_bits < 0) || ((header & 0x80) > 0) || ((header & 0x40) > 0) ) ) /* AMRWBIO */
+ {
+ /* incorrect IO FT header */
+ fprintf(stderr, "\nError in EVS(AMRWBIO) FT ToC header(%02x) ! ",header);
+ exit(-1);
+ }
+ }
+ else
+ {
+ /* legacy AMRWB ToC, is only using Padding bits which MUST be ignored */
+ if ( num_bits < 0 )
+ {
+ /* incorrect FT header */
+ fprintf(stderr, "\nError in AMRWB RFC4867 Toc(FT) header(%02x) !", header);
+ exit(-1);
+ }
+ }
+
+
+
+ /* read serial stream of indices from file to the local buffer */
+ num_bytes_read = (Word16) fread( pFrame, sizeof(UWord8), (num_bits + 7)>>3, file );
+ if( num_bytes_read != (num_bits + 7)>>3 )
+ {
+ fprintf(stderr, "\nError, invalid number of bytes read ! Exiting ! \n");
+ exit(-1);
+ }
+
+
+
+
+ /* in case rew_flag is set, rewind the file and return */
+ if ( rew_flag )
+ {
+
+ st->total_brate = total_brate;
+ /* select MODE1 or MODE2 */
+ if( st->bfi == 0 && speech_lost == 0 && no_data == 0 )
+ {
+ decoder_selectCodec( st, total_brate, unpack_bit(&pt_pFrame,&mask) ? G192_BIN1 : G192_BIN0);
+ }
+ return 1;
+ }
+
+ /* unpack speech data */
+ bit_stream_ptr = st->bit_stream;
+ for( k=0; kbit_stream[sort_ptr[core_mode][k]] = unpack_bit(&pt_pFrame,&mask);
+ bit_stream_ptr++;
+ }
+ else
+ {
+ *bit_stream_ptr++ = unpack_bit(&pt_pFrame,&mask);
+ }
+ }
+
+ /* unpack auxiliary bits */
+ /* Note: these cmi bits are unpacked for demo purposes; they are actually not needed */
+ if( isAMRWB_IOmode && total_brate == SID_1k75 )
+ {
+ sti = unpack_bit(&pt_pFrame,&mask);
+ cmi = unpack_bit(&pt_pFrame,&mask) << 3;
+ cmi |= unpack_bit(&pt_pFrame,&mask) << 2;
+ cmi |= unpack_bit(&pt_pFrame,&mask) << 1;
+ cmi |= unpack_bit(&pt_pFrame,&mask);
+
+ read_indices_mime_handle_sti_and_all_zero_bits( st, &total_brate, sti );
+ }
+
+ /*add two zero bytes for arithmetic coder flush*/
+ for( k=0; k< 2*8; ++k )
+ {
+ *bit_stream_ptr++ = 0;
+ }
+ /* MIME RX_DTX handler */
+ if( !rew_flag )
+ {
+ total_brate = read_indices_mime_handle_dtx( st, isAMRWB_IOmode, core_mode, total_brate, sti, speech_lost, no_data );
+ }
+ if( st->bfi == 0 )
+ {
+ /* select MODE1 or MODE2 in MIME */
+
+ decoder_selectCodec( st, total_brate, *st->bit_stream ? G192_BIN1 : G192_BIN0);
+
+ /* a change of the total bitrate should not be known to the decoder, if the received frame was truly lost */
+ st->total_brate = total_brate;
+ mdct_switching_dec(st);
+ }
+ /* else{ bfi stay in past synthesis mode(SP,CNG) } */
+
+ return 1;
+}
+
+
+
+/*-------------------------------------------------------------------*
+* get_rfFrameType()
+*
+* Extract the rf frame type
+*-------------------------------------------------------------------*/
+
+static void get_rfFrameType(
+ Decoder_State *st, /* i : decoder state structure */
+ short *rf_frame_type /* o : RF frame type */
+)
+{
+ short num_bits;
+ num_bits = st->total_brate/50;
+
+ if( st->rf_flag == 1)
+ {
+ /* the last three bits in a packet is the RF frame type */
+ *rf_frame_type = get_indice( st, num_bits - 3, 3 );
+ }
+ else
+ {
+ *rf_frame_type = 0;
+ }
+
+ return;
+}
+
+/*-------------------------------------------------------------------*
+* get_rfFlag()
+*
+* Check if rf flag is present in the bitstream
+*-------------------------------------------------------------------*/
+
+static void get_rfFlag(
+ Decoder_State *st, /* i: decoder state structure */
+ short *rf_flag, /* o : check for the RF flag */
+ short *nBits,
+ long *ind
+)
+{
+ short start_idx, nBits_tmp;
+ long ind_tmp;
+
+ /* Init */
+ *rf_flag = 0;
+
+ /* check for rf_flag in the packet and extract the rf_frame_type and rf_fec_offset */
+ if( st->total_brate == ACELP_13k20 && (st->bfi == FRAMEMODE_NORMAL || st->bfi == FRAMEMODE_FUTURE) )
+ {
+ /* find the section in the ACELP signalling table corresponding to bitrate */
+ start_idx = 0;
+ while ( acelp_sig_tbl[start_idx] != st->total_brate )
+ {
+ start_idx++;
+ assert((start_idx < MAX_ACELP_SIG) && "ERROR: start_idx larger than acelp_sig_tbl[].\n");
+ }
+
+ /* skip the bitrate */
+ start_idx += 1;
+
+ /* retrieve the number of bits */
+ nBits_tmp = (short) acelp_sig_tbl[start_idx++];
+
+ /* retrieve the signalling indice */
+ ind_tmp = acelp_sig_tbl[start_idx + get_indice( st, 0, nBits_tmp )];
+
+ /* convert signalling indice into RF flag. */
+ *rf_flag = (ind_tmp >> 7) & 0x1;
+
+ if( ind )
+ {
+ *ind = ind_tmp;
+ }
+
+ if( nBits )
+ {
+ *nBits = nBits_tmp;
+ }
+ }
+
+ return;
+}
+
+/*-------------------------------------------------------------------*
+* get_rf_fec_offset()
+*
+* Extract the FEC offset
+*-------------------------------------------------------------------*/
+
+static void get_rf_fec_offset(
+ Decoder_State *st, /* i : decoder state structure */
+ short *rf_fec_offset /* o : RF fec offset */
+)
+{
+ short num_bits, tmp;
+ num_bits = st->total_brate/50;
+
+ if( st->rf_flag == 1)
+ {
+ /* the two bits before the rf frame type contains the fec offset */
+ tmp = get_indice( st, num_bits - 5, 2 );
+
+ if (tmp == 0)
+ {
+ *rf_fec_offset = 2;
+ }
+ else
+ {
+ *rf_fec_offset = 2*tmp + 1;
+ }
+
+ }
+ else
+ {
+ *rf_fec_offset = 0;
+ }
+
+ return;
+}
+
+/*-------------------------------------------------------------------*
+* get_rfTargetBits()
+*
+* Return the number of RF target bits
+*-------------------------------------------------------------------*/
+
+static void get_rfTargetBits(
+ short rf_frame_type, /* i : RF frame type */
+ short *rf_target_bits /* o : Number of RF target bits */
+)
+{
+ /* Number of RF bits for different RF coder types */
+
+ switch (rf_frame_type)
+ {
+ case RF_NO_DATA:
+ *rf_target_bits = 5;
+ break;
+ case RF_TCXFD:
+ *rf_target_bits = 27;
+ break;
+ case RF_TCXTD1:
+ *rf_target_bits = 16;
+ break;
+ case RF_TCXTD2:
+ *rf_target_bits = 16;
+ break;
+ case RF_ALLPRED:
+ /* Es_pred bits 3 bits, LTF: 1, pitch: 8,5,5,5, FCB: 0, gain: 7,0,7,0, Diff GFr: 4*/
+ *rf_target_bits = 63;
+ break;
+ case RF_NOPRED:
+ /* Es_pred bits 3 bits, LTF: 0, pitch: 0, FCB: 7,7,7,7, gain: 6,0,6,0, Diff GFr: 2*/
+ *rf_target_bits = 66;
+ break;
+ case RF_GENPRED:
+ /* Es_pred bits 3 bits, LTF: 1, pitch: 8,0,8,0, FCB: 6,7,5,5, gain: 5,0,5,0, Diff GFr: 0*/
+ *rf_target_bits = 70;
+ break;
+ case RF_NELP:
+ /* gain: 19, Diff GFr: 5 */
+ *rf_target_bits = 45;
+ break;
+ }
+
+ return;
+}
+
+/*-------------------------------------------------------------------*
+* berCheck()
+*
+* Check for bit errors in channel aware signalling.
+*-------------------------------------------------------------------*/
+
+static void berCheck(
+ Decoder_State *st, /* i/o: decoder state structure */
+ short *coder_type /* i/o: coder type */
+)
+{
+ /* In case of RF flag = 1, and valid RF packet with primary and partial copy */
+ if( st->bwidth == NB || st->bwidth == FB || *coder_type >= TRANSITION )
+ {
+ if( st->use_partial_copy == 1 )
+ {
+ st->use_partial_copy = 0;
+ }
+
+ st->bfi = 1;
+ st->bwidth = st->last_bwidth;
+ st->BER_detect = 1;
+ *coder_type = GENERIC;
+ }
+
+ return;
+}
+
+/*-------------------------------------------------------------------*
+ * getPartialCopyInfo()
+ *
+ * Check if the frame includes a partial copy for channel aware processing.
+ *-------------------------------------------------------------------*/
+
+void getPartialCopyInfo(
+ Decoder_State *st, /* i/o: decoder state structure */
+ short *coder_type,
+ short *sharpFlag
+)
+{
+ short nBits = 0;
+ long ind = 0;
+
+ /* check the rf flag in the packet */
+ get_rfFlag( st, &(st->rf_flag), &nBits , &ind);
+
+ /* get rf frame type info */
+ get_rfFrameType( st, &(st->rf_frame_type) );
+
+ /* Get the FEC offset info */
+ get_rf_fec_offset( st, &(st->rf_fec_offset) );
+
+ /* reset number of target bits in case of rate switching */
+ st->rf_target_bits = 0;
+
+ /* Get the number of bits used for RF*/
+ if( st->rf_flag == 1 )
+ {
+ *coder_type = ind & 0x7;
+ st->bwidth = (ind >> 3) & 0x7;
+ *sharpFlag = (ind >> 6) & 0x1;
+ st->codec_mode = MODE2;
+ get_rfTargetBits( st->rf_frame_type, &(st->rf_target_bits) );
+
+ if( st->bfi == FRAMEMODE_FUTURE )
+ {
+ st->use_partial_copy = 1;
+ /* now set the frame mode to normal mode */
+ if(st->rf_frame_type >= RF_TCXFD && st->rf_frame_type <= RF_TCXTD2)
+ {
+ st->bfi = 1;
+ st->core = 1;
+ }
+ else
+ {
+ st->bfi = FRAMEMODE_NORMAL;
+ st->core = 0;
+ }
+ }
+
+ /* check for bit errors */
+ berCheck( st, coder_type );
+
+ get_next_indice_tmp(st, nBits);
+ }
+
+ return;
+}
+
+/*-------------------------------------------------------------------*
+ * get_NextCoderType()
+ *
+ * Extract the coder type of next frame
+ *-------------------------------------------------------------------*/
+
+void get_NextCoderType(
+ unsigned char *bitsteam, /* i : bitstream */
+ short *next_coder_type /* o : next coder type */
+)
+{
+ short k;
+ short start_idx;
+ char bit_stream[ACELP_13k20/50];
+ long tmp;
+ short nBits_tmp;
+
+
+ for( k = 0; k < ACELP_13k20/50; k++ )
+ {
+ bit_stream[k] = (bitsteam[k / 8] >> (7 - (k % 8))) & 0x1;
+ }
+ start_idx = 0;
+ while ( acelp_sig_tbl[start_idx] != ACELP_13k20 )
+ {
+ start_idx++;
+ assert((start_idx < MAX_ACELP_SIG) && "ERROR: start_idx larger than acelp_sig_tbl[].\n");
+ }
+
+ /* skip the bitrate */
+ start_idx += 1;
+
+ tmp = 0;
+ nBits_tmp = (short) acelp_sig_tbl[start_idx++];
+ for (k = 0; k < nBits_tmp; k++)
+ {
+ tmp <<= 1;
+ tmp += bit_stream[k];
+ }
+
+ /* retrieve the signalling indice */
+ *next_coder_type = acelp_sig_tbl[start_idx + tmp] & 0x7;
+
+ return;
+}
+
+/*-------------------------------------------------------------------*
+ * read_indices_from_djb()
+ *
+ * Read indices from the de-jitter buffer payload (works also for AMR-WB IO mode)
+ *-------------------------------------------------------------------*/
+void read_indices_from_djb(
+ Decoder_State *st, /* i/o: decoder state structure */
+ unsigned char *pt_stream, /* i : bitstream file */
+ int num_bits, /* i : input frame length in bits */
+ Word16 isAMRWB_IOmode,
+ Word16 core_mode,
+ Word16 qbit,
+ short partialframe, /* i : partial frame information */
+ short next_coder_type /* i : next coder type information */
+)
+{
+ int k;
+ UWord8 mask = 0x80;
+ Word16 no_data = 0;
+ Word16 sti = -1;
+ unsigned short *bit_stream_ptr;
+ Word32 total_brate;
+ short speech_lost = 0;
+
+ st->bfi = 0;
+ st->BER_detect = 0;
+ st->mdct_sw_enable = 0;
+ st->mdct_sw = 0;
+ reset_indices_dec(st);
+
+ st->bfi = !qbit;
+ total_brate = (Word32)(num_bits) * 50;
+
+ if( num_bits == 0 ) /* guess type of missing frame for SP_LOST and NO_DATA */
+ {
+ speech_lost = st->CNG == 0;
+ no_data = st->CNG != 0;
+ }
+
+ if( partialframe || st->prev_use_partial_copy)
+ {
+ st->next_coder_type = next_coder_type;
+ }
+ else
+ {
+ st->next_coder_type = INACTIVE;
+ }
+
+ if (partialframe == 1)
+ {
+ st->bfi = 2;
+ }
+
+ /* unpack speech data */
+ bit_stream_ptr = st->bit_stream;
+ /* convert bitstream from compact bytes to short values and store it in decoder state */
+ for( k = 0; k < num_bits; k++ )
+ {
+ if( st->bitstreamformat == VOIP_RTPDUMP && isAMRWB_IOmode )
+ {
+ st->bit_stream[sort_ptr[core_mode][k]] = unpack_bit(&pt_stream, &mask);
+ bit_stream_ptr++;
+ }
+ else
+ {
+ *bit_stream_ptr++ = unpack_bit(&pt_stream, &mask);
+ }
+ }
+
+ /* unpack auxiliary bits */
+ if( isAMRWB_IOmode && total_brate == SID_1k75 )
+ {
+ if( st->bitstreamformat == VOIP_RTPDUMP )
+ {
+ /* A.2.2.1.3: AMR-WB SID_1k75 frame is followed by STI bit and CMI bits */
+ sti = unpack_bit(&pt_stream, &mask);
+ }
+ else
+ {
+ /* VOIP_G192_RTP does not contain STI and CMI */
+ sti = 1;
+
+ }
+ read_indices_mime_handle_sti_and_all_zero_bits(st, &total_brate, sti);
+
+ }
+
+ /* add two zero bytes for arithmetic coder flush */
+ for( k=0; k < 8*2; ++k )
+ {
+ *bit_stream_ptr++ = 0;
+ }
+
+ total_brate = read_indices_mime_handle_dtx(st, isAMRWB_IOmode, core_mode, total_brate, sti, speech_lost, no_data);
+ /* st->CNG set inside */
+
+ if ( st->bfi != 1 )
+ {
+ /* select Mode 1 or Mode 2 */
+ decoder_selectCodec( st, total_brate, *st->bit_stream ? G192_BIN1 : G192_BIN0);
+
+ /* a change of the total bitrate should not be known to the decoder, if the received frame was truly lost */
+ st->total_brate = total_brate;
+
+ mdct_switching_dec(st);
+ }
+
+ return;
+}
+
+/*-------------------------------------------------------------------*
+ * get_indice_preview()
+ *
+ * Indices preview to parse for the presence of partial copy
+ *-------------------------------------------------------------------*/
+static unsigned short get_indice_preview(
+ unsigned char *bitstream,
+ int bitstreamSize,
+ short pos,
+ short nb_bits
+)
+{
+ unsigned short value;
+ int i;
+ unsigned short bitstreamShort[MAX_BITS_PER_FRAME+16];
+ unsigned short *bitstreamShortPtr;
+
+ /* convert bitstream from compact bytes to short values */
+ bitstreamShortPtr = bitstreamShort;
+ for( i = 0; i < bitstreamSize; i++ )
+ {
+ *bitstreamShortPtr++ = (bitstream[i / 8] >> (7 - (i % 8))) & 0x1;
+ }
+
+ assert(nb_bits <= 16);
+ value = 0;
+ for (i = 0; i < nb_bits; i++)
+ {
+ value <<= 1;
+ value += bitstreamShort[pos+i];
+ }
+ return value;
+}
+
+/*-------------------------------------------------------------------*
+ * evs_dec_previewFrame()
+ *
+ * Signalling index preview
+ *-------------------------------------------------------------------*/
+void evs_dec_previewFrame(
+ unsigned char *bitstream,
+ int bitstreamSize,
+ short *partialCopyFrameType,
+ short *partialCopyOffset
+)
+{
+ long total_brate;
+ short start_idx, nBits;
+ long ind;
+ short rf_flag;
+
+ rf_flag = 0;
+ *partialCopyFrameType = 0;
+ *partialCopyOffset = 0;
+ total_brate = bitstreamSize * 50;
+
+ if( total_brate == ACELP_13k20 )
+ {
+ /* find the section in the ACELP signalling table corresponding to bitrate */
+ start_idx = 0;
+ while ( acelp_sig_tbl[start_idx] != total_brate )
+ {
+ start_idx++;
+ assert((start_idx < MAX_ACELP_SIG) && "ERROR: start_idx larger than acelp_sig_tbl[].\n");
+ }
+
+ /* skip the bitrate */
+ start_idx += 1;
+ /* retrieve the number of bits */
+ nBits = (short) acelp_sig_tbl[start_idx++];
+
+ /* retrieve the signalling indice */
+ ind = acelp_sig_tbl[start_idx + get_indice_preview( bitstream, bitstreamSize, 0, nBits )];
+
+ /* convert signalling indice into RF flag. */
+ rf_flag = (ind >> 7) & 0x1;
+ if(rf_flag != 0)
+ {
+ /* read the fec offset at which the partial copy is received */
+ ind = get_indice_preview( bitstream, bitstreamSize, (bitstreamSize-5), 2 );
+ if (ind == 0)
+ {
+ *partialCopyOffset = 2;
+ }
+ else if (ind == 1)
+ {
+ *partialCopyOffset = 3;
+ }
+ else if (ind == 2)
+ {
+ *partialCopyOffset = 5;
+ }
+ else if (ind == 3)
+ {
+ *partialCopyOffset = 7;
+ }
+ /* the last three bits in a packet is the RF frame type */
+ *partialCopyFrameType = get_indice_preview( bitstream, bitstreamSize, bitstreamSize - 3, 3 );
+ }
+ }
+
+ return;
+}
diff --git a/lib_com/calc_st_com.c b/lib_com/calc_st_com.c
new file mode 100644
index 0000000000000000000000000000000000000000..38d48af8e8b4cbdd3d130bbc04391ad1d3c7d580
--- /dev/null
+++ b/lib_com/calc_st_com.c
@@ -0,0 +1,274 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include
+#include "wmc_auto.h"
+#include "options.h"
+#include "cnst.h"
+#include "prot.h"
+
+
+
+/*----------------------------------------------------------------------------
+ * calc_rc0_h()
+ *
+ * computes 1st parcor from composed filter impulse response
+ *---------------------------------------------------------------------------*/
+
+static void calc_rc0_h(
+ const float *h, /* i : impulse response of composed filter */
+ float *rc0 /* o : 1st parcor */
+)
+{
+ float acf0, acf1;
+ float temp, temp2;
+ const float *ptrs;
+ int i;
+
+ /* computation of the autocorrelation function acf */
+ temp = (float) 0.;
+ for (i = 0; i < LONG_H_ST; i++)
+ {
+ temp += h[i] * h[i];
+ }
+ acf0 = temp;
+
+ temp = (float) 0.;
+ ptrs = h;
+ for (i = 0; i < LONG_H_ST - 1; i++)
+ {
+ temp2 = *ptrs++;
+ temp += temp2 * (*ptrs);
+ }
+ acf1 = temp;
+
+ /* Initialisation of the calculation */
+ if (acf0 == (float) 0.)
+ {
+ *rc0 = (float) 0.;
+ return;
+ }
+
+ /* Compute 1st parcor */
+ if (acf0 < (float) fabs (acf1))
+ {
+ *rc0 = (float) 0.0;
+ return;
+ }
+ *rc0 = -acf1 / acf0;
+
+ return;
+}
+
+
+/*----------------------------------------------------------------------------
+ * calc_st_filt()
+ *
+ * computes impulse response of A(gamma2) / A(gamma1)
+ * controls gain : computation of energy impulse response as
+ * SUMn (abs (h[n])) and computes parcor0
+ *---------------------------------------------------------------------------- */
+
+void calc_st_filt(
+ const float *apond2, /* i : coefficients of numerator */
+ const float *apond1, /* i : coefficients of denominator */
+ float *parcor0, /* o : 1st parcor calcul. on composed filter */
+ float *sig_ltp_ptr, /* i/o: input of 1/A(gamma1) : scaled by 1/g0 */
+ float *mem_zero, /* i/o: All zero memory */
+ const short L_subfr, /* i : the length of subframe */
+ const short extl /* i : extension layer info */
+
+)
+{
+ float h[LONG_H_ST];
+ float g0, temp;
+ int i;
+
+ /* compute i.r. of composed filter apond2 / apond1 */
+ if( extl == SWB_TBE )
+ {
+ syn_filt( apond1, LPC_SHB_ORDER, apond2, h, LONG_H_ST, mem_zero, 0 );
+ }
+ else
+ {
+ syn_filt( apond1, M, apond2, h, LONG_H_ST, mem_zero, 0 );
+ }
+
+ /* compute 1st parcor */
+ calc_rc0_h( h, parcor0 );
+
+ /* compute g0 */
+ g0 = (float) 0.;
+ for (i = 0; i < LONG_H_ST; i++)
+ {
+ g0 += (float) fabs (h[i]);
+ }
+
+ /* Scale signal input of 1/A(gamma1) */
+ if (g0 > (float) 1.)
+ {
+ temp = (float) 1. / g0;
+
+ for (i = 0; i < L_subfr; i++)
+ {
+ sig_ltp_ptr[i] = sig_ltp_ptr[i] * temp;
+ }
+ }
+
+ return;
+}
+
+/*----------------------------------------------------------------------------
+ * filt_mu()
+ *
+ * tilt filtering with : (1 + mu z-1) * (1/1-|mu|)
+ * computes y[n] = (1/1-|mu|) (x[n]+mu*x[n-1])
+ *---------------------------------------------------------------------------*/
+
+void filt_mu(
+ const float *sig_in, /* i : signal (beginning at sample -1) */
+ float *sig_out, /* o : output signal */
+ const float parcor0, /* i : parcor0 (mu = parcor0 * gamma3) */
+ const short L_subfr, /* i : the length of subframe */
+ const short extl /* i : extension layer info */
+)
+{
+ short n;
+ float mu, ga, temp;
+ const float *ptrs;
+
+ if( extl == SWB_TBE )
+ {
+ if(parcor0 > 0.0f)
+ {
+ mu = parcor0 * GAMMA3_PLUS_WB;
+ }
+ else
+ {
+ mu = parcor0 * GAMMA3_MINUS_WB;
+ }
+ }
+ else
+ {
+ if (parcor0 > 0.0f)
+ {
+ mu = parcor0 * GAMMA3_PLUS;
+ }
+ else
+ {
+ mu = parcor0 * GAMMA3_MINUS;
+ }
+ }
+
+ ga = (float) 1. / ((float) 1. - (float) fabs (mu));
+
+ ptrs = sig_in; /* points on sig_in(-1) */
+
+ for (n = 0; n < L_subfr; n++)
+ {
+ temp = mu * (*ptrs++);
+ temp += (*ptrs);
+ sig_out[n] = ga * temp;
+ }
+
+ return;
+}
+
+
+
+
+/*----------------------------------------------------------------------------
+ * scale_st()
+ *
+ * control of the subframe gain
+ * gain[n] = AGC_FAC_FX * gain[n-1] + (1 - AGC_FAC_FX) g_in/g_out
+ *---------------------------------------------------------------------------*/
+
+void scale_st(
+ const float *sig_in, /* i : postfilter input signal */
+ float *sig_out, /* i/o: postfilter output signal */
+ float *gain_prec, /* i/o: last value of gain for subframe */
+ const short L_subfr, /* i : the length of subframe */
+ const short extl /* i : extension layer info */
+)
+{
+ int i;
+ float gain_in, gain_out;
+ float g0, gain;
+ float agc_fac1_para = 0.0f;
+ float agc_fac_para = 0.0f;
+
+ if( extl == SWB_TBE )
+ {
+ agc_fac1_para = AGC_FAC1_WB;
+ agc_fac_para = AGC_FAC_WB;
+ }
+ else
+ {
+ agc_fac1_para = AGC_FAC1;
+ agc_fac_para = AGC_FAC;
+ }
+
+ /* compute input gain */
+ gain_in = (float) 0.;
+ for (i = 0; i < L_subfr; i++)
+ {
+ gain_in += (float) fabs (sig_in[i]);
+ }
+
+ if ( gain_in == 0.0f )
+ {
+ g0 = 0.0f;
+ }
+ else
+ {
+ /* Compute output gain */
+ gain_out = 0.0f;
+ for (i = 0; i < L_subfr; i++)
+ {
+ gain_out += (float) fabs (sig_out[i]);
+ }
+
+ if (gain_out == 0.0f)
+ {
+ *gain_prec = 0.0f;
+ return;
+ }
+
+ g0 = gain_in / gain_out;
+ g0 *= agc_fac1_para;
+ }
+
+ /* compute gain(n) = AGC_FAC gain(n-1) + (1-AGC_FAC)gain_in/gain_out */
+ /* sig_out(n) = gain(n) sig_out(n) */
+ gain = *gain_prec;
+ for (i = 0; i < L_subfr; i++)
+ {
+ gain *= agc_fac_para;
+ gain += g0;
+ sig_out[i] *= gain;
+ }
+
+ *gain_prec = gain;
+
+ return;
+}
+
+void blend_subfr2( float *sigIn1, float *sigIn2, float *sigOut)
+{
+
+ float fac1 = 1.f - (1.f / L_SUBFR);
+ float fac2 = 0.f + (1.f / L_SUBFR);
+ float step = 1.f / (L_SUBFR/2);
+ int i;
+
+ for(i=0; i
+#include "wmc_auto.h"
+#include
+#include "stat_dec.h"
+#include "prot.h"
+#include "rom_com.h"
+#include "string.h"
+#include
+
+#if defined __ICL
+#define restrict __restrict
+#else
+#define restrict
+#endif
+
+#ifdef _MSC_VER
+#pragma warning(disable : 4305) /* disable truncation from double to float warning (VC++)*/
+#endif
+
+
+/*-------------------------------------------------------------------*
+ * local prototypes
+ *--------------------------------------------------------------------*/
+
+static void cldfb_init_proto_and_twiddles(HANDLE_CLDFB_FILTER_BANK hs);
+
+static float GetEnergyCldfb( float *energyValuesSum, float *energyLookahead, float **realValues, float **imagValues,
+ int numberBands, int numberCols, HANDLE_TEC_ENC hTecEnc );
+
+/*-------------------------------------------------------------------*
+ * cplxMult()
+ *
+ * Conduct complex multiplication
+ *--------------------------------------------------------------------*/
+static void cplxMult(
+ float *yr, /* o : real output */
+ float *yi, /* o : imag output */
+ float xr, /* i : real input 1*/
+ float xi, /* i : imag input 1*/
+ float cr, /* i : real input 1*/
+ float ci /* i : imag input 1*/
+)
+{
+ *yr = xr*cr - xi*ci;
+ *yi = xr*ci + xi*cr;
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------*
+ * cldfbAnalysis()
+ *
+ * Conduct multple overlap cmplex low delay MDCT
+ *--------------------------------------------------------------------*/
+void cldfbAnalysis(
+ const float *timeIn, /* i : time buffer */
+ float **realBuffer, /* o : real value buffer */
+ float **imagBuffer, /* o : imag value buffer */
+ int samplesToProcess, /* i : samples to process */
+ HANDLE_CLDFB_FILTER_BANK h_cldfb /* i : filterbank state */
+)
+{
+ short i, k;
+ short L2, M1, M2, M4;
+ short no_col = h_cldfb->no_col;
+
+ float r1, r2, rr12, ir12;
+ float i1, i2, ri12, ii12;
+ float rBuffer[2*CLDFB_NO_CHANNELS_MAX];
+ float iBuffer[2*CLDFB_NO_CHANNELS_MAX];
+ const float *rot_vctr_re;
+ const float *rot_vctr_im;
+ const float *ptr_pf;
+ float *timeBuffer = h_cldfb->cldfb_state;
+ int offset = h_cldfb->p_filter_length - h_cldfb->no_channels;
+ int frameSize = h_cldfb->no_channels * h_cldfb->no_col;
+
+ /* prepare input buffer */
+ mvr2r( timeBuffer + frameSize, timeBuffer, offset );
+
+ if( samplesToProcess > -1 )
+ {
+ mvr2r( timeIn, timeBuffer + offset, samplesToProcess );
+ set_f( timeBuffer+offset+samplesToProcess, 0.0f, (frameSize-samplesToProcess) );
+ }
+ else
+ {
+ mvr2r( timeIn, timeBuffer + offset, frameSize );
+ }
+
+ /* only process needed cols */
+ if( samplesToProcess > -1 )
+ {
+ no_col = min(no_col, (samplesToProcess + h_cldfb->no_channels - 1) / h_cldfb->no_channels);
+ }
+
+ M1 = h_cldfb->no_channels;
+ M2 = M1 >> 1;
+ M4 = M1 >> 2;
+ L2 = M1 << 1;
+
+ if( M2 & 1 )
+ {
+ M4 += 1;
+ }
+
+ rot_vctr_re = h_cldfb->rot_vec_ana_re;
+ rot_vctr_im = h_cldfb->rot_vec_ana_im;
+
+ ptr_pf = h_cldfb->p_filter;
+
+ for( i = 0; i < no_col; i++ )
+ {
+ for (k=0; k < M4; k++ )
+ {
+ /* prototype filter */
+ r1 = 0 - ptr_pf[(L2-M2-1-(2*k) + 0 * L2)] * timeBuffer[L2-M2-1-(2*k) + 0 * L2];
+ r1 = r1 - ptr_pf[(L2-M2-1-(2*k) + 1 * L2)] * timeBuffer[L2-M2-1-(2*k) + 1 * L2];
+ r1 = r1 - ptr_pf[(L2-M2-1-(2*k) + 2 * L2)] * timeBuffer[L2-M2-1-(2*k) + 2 * L2];
+ r1 = r1 - ptr_pf[(L2-M2-1-(2*k) + 3 * L2)] * timeBuffer[L2-M2-1-(2*k) + 3 * L2];
+ r1 = r1 - ptr_pf[(L2-M2-1-(2*k) + 4 * L2)] * timeBuffer[L2-M2-1-(2*k) + 4 * L2];
+
+ r2 = 0 - ptr_pf[(L2-M2+(2*k) + 0 * L2)] * timeBuffer[L2-M2+(2*k) + 0 * L2];
+ r2 = r2 - ptr_pf[(L2-M2+(2*k) + 1 * L2)] * timeBuffer[L2-M2+(2*k) + 1 * L2];
+ r2 = r2 - ptr_pf[(L2-M2+(2*k) + 2 * L2)] * timeBuffer[L2-M2+(2*k) + 2 * L2];
+ r2 = r2 - ptr_pf[(L2-M2+(2*k) + 3 * L2)] * timeBuffer[L2-M2+(2*k) + 3 * L2];
+ r2 = r2 - ptr_pf[(L2-M2+(2*k) + 4 * L2)] * timeBuffer[L2-M2+(2*k) + 4 * L2];
+
+ i1 = 0 - ptr_pf[(L2-3*M2+(2*k) + 0 * L2)] * timeBuffer[L2-3*M2+(2*k) + 0 * L2];
+ i1 = i1 - ptr_pf[(L2-3*M2+(2*k) + 1 * L2)] * timeBuffer[L2-3*M2+(2*k) + 1 * L2];
+ i1 = i1 - ptr_pf[(L2-3*M2+(2*k) + 2 * L2)] * timeBuffer[L2-3*M2+(2*k) + 2 * L2];
+ i1 = i1 - ptr_pf[(L2-3*M2+(2*k) + 3 * L2)] * timeBuffer[L2-3*M2+(2*k) + 3 * L2];
+ i1 = i1 - ptr_pf[(L2-3*M2+(2*k) + 4 * L2)] * timeBuffer[L2-3*M2+(2*k) + 4 * L2];
+
+ i2 = 0 - ptr_pf[(L2-3*M2-1-(2*k) + 0 * L2)] * timeBuffer[L2-3*M2-1-(2*k) + 0 * L2];
+ i2 = i2 - ptr_pf[(L2-3*M2-1-(2*k) + 1 * L2)] * timeBuffer[L2-3*M2-1-(2*k) + 1 * L2];
+ i2 = i2 - ptr_pf[(L2-3*M2-1-(2*k) + 2 * L2)] * timeBuffer[L2-3*M2-1-(2*k) + 2 * L2];
+ i2 = i2 - ptr_pf[(L2-3*M2-1-(2*k) + 3 * L2)] * timeBuffer[L2-3*M2-1-(2*k) + 3 * L2];
+ i2 = i2 - ptr_pf[(L2-3*M2-1-(2*k) + 4 * L2)] * timeBuffer[L2-3*M2-1-(2*k) + 4 * L2];
+
+ /* folding + pre modulation of DST IV */
+ rr12 = r1 - r2;
+ ri12 = -i1 - i2;
+ cplxMult(&rBuffer[2*k],&rBuffer[2*k+1],rr12,ri12,rot_vctr_re[k],rot_vctr_im[k]);
+
+ /* folding + pre modulation of DCT IV */
+ ir12 = r1 + r2;
+ ii12 = i1 - i2;
+ cplxMult(&iBuffer[2*k],&iBuffer[2*k+1],ir12,ii12,rot_vctr_re[k],rot_vctr_im[k]);
+ }
+
+ for (k=M4; k < M2; k++)
+ {
+ /* prototype filter */
+ r1 = 0 - ptr_pf[(L2-M2-1-(2*k) + 0 * L2)] * timeBuffer[L2-M2-1-(2*k) + 0 * L2];
+ r1 = r1 - ptr_pf[(L2-M2-1-(2*k) + 1 * L2)] * timeBuffer[L2-M2-1-(2*k) + 1 * L2];
+ r1 = r1 - ptr_pf[(L2-M2-1-(2*k) + 2 * L2)] * timeBuffer[L2-M2-1-(2*k) + 2 * L2];
+ r1 = r1 - ptr_pf[(L2-M2-1-(2*k) + 3 * L2)] * timeBuffer[L2-M2-1-(2*k) + 3 * L2];
+ r1 = r1 - ptr_pf[(L2-M2-1-(2*k) + 4 * L2)] * timeBuffer[L2-M2-1-(2*k) + 4 * L2];
+
+ r2 = 0 - ptr_pf[(L2-5*M2+(2*k) + 0 * L2)] * timeBuffer[L2-5*M2+(2*k) + 0 * L2];
+ r2 = r2 - ptr_pf[(L2-5*M2+(2*k) + 1 * L2)] * timeBuffer[L2-5*M2+(2*k) + 1 * L2];
+ r2 = r2 - ptr_pf[(L2-5*M2+(2*k) + 2 * L2)] * timeBuffer[L2-5*M2+(2*k) + 2 * L2];
+ r2 = r2 - ptr_pf[(L2-5*M2+(2*k) + 3 * L2)] * timeBuffer[L2-5*M2+(2*k) + 3 * L2];
+ r2 = r2 - ptr_pf[(L2-5*M2+(2*k) + 4 * L2)] * timeBuffer[L2-5*M2+(2*k) + 4 * L2];
+
+ i1 = 0 - ptr_pf[(L2+M2-1-(2*k) + 0 * L2)] * timeBuffer[L2+M2-1-(2*k) + 0 * L2];
+ i1 = i1 - ptr_pf[(L2+M2-1-(2*k) + 1 * L2)] * timeBuffer[L2+M2-1-(2*k) + 1 * L2];
+ i1 = i1 - ptr_pf[(L2+M2-1-(2*k) + 2 * L2)] * timeBuffer[L2+M2-1-(2*k) + 2 * L2];
+ i1 = i1 - ptr_pf[(L2+M2-1-(2*k) + 3 * L2)] * timeBuffer[L2+M2-1-(2*k) + 3 * L2];
+ i1 = i1 - ptr_pf[(L2+M2-1-(2*k) + 4 * L2)] * timeBuffer[L2+M2-1-(2*k) + 4 * L2];
+
+ i2 = 0 - ptr_pf[(L2-3*M2+(2*k) + 0 * L2)] * timeBuffer[L2-3*M2+(2*k) + 0 * L2];
+ i2 = i2 - ptr_pf[(L2-3*M2+(2*k) + 1 * L2)] * timeBuffer[L2-3*M2+(2*k) + 1 * L2];
+ i2 = i2 - ptr_pf[(L2-3*M2+(2*k) + 2 * L2)] * timeBuffer[L2-3*M2+(2*k) + 2 * L2];
+ i2 = i2 - ptr_pf[(L2-3*M2+(2*k) + 3 * L2)] * timeBuffer[L2-3*M2+(2*k) + 3 * L2];
+ i2 = i2 - ptr_pf[(L2-3*M2+(2*k) + 4 * L2)] * timeBuffer[L2-3*M2+(2*k) + 4 * L2];
+
+ /* folding + pre modulation of DST IV */
+ rr12 = r1 + r2;
+ ri12 = i1 - i2;
+ cplxMult(&rBuffer[2*k],&rBuffer[2*k+1],rr12,ri12,rot_vctr_re[k],rot_vctr_im[k]);
+
+ /* folding + pre modulation of DCT IV */
+ ir12 = r1 - r2;
+ ii12 = i1 + i2;
+ cplxMult(&iBuffer[2*k],&iBuffer[2*k+1],ir12,ii12,rot_vctr_re[k],rot_vctr_im[k]);
+ }
+
+ /* FFT of DST IV */
+ fft_cldfb(rBuffer, M2);
+
+ /* post modulation of DST IV */
+ for (k=0; k < M2; k++)
+ {
+ cplxMult(&realBuffer[i][M1-1-(2*k)],&realBuffer[i][2*k],rBuffer[2*k],rBuffer[2*k+1],rot_vctr_re[k],rot_vctr_im[k]);
+ }
+
+ /* FFT of DCT IV */
+ fft_cldfb(iBuffer, M2);
+
+ /* post modulation of DCT IV */
+ for (k=0; k < M2; k++)
+ {
+ /* do it inplace */
+ cplxMult(&imagBuffer[i][2*k],&imagBuffer[i][M1-1-(2*k)],iBuffer[2*k],iBuffer[2*k+1],rot_vctr_re[k],rot_vctr_im[k]);
+ }
+
+ timeBuffer += L2 * 5;
+ timeBuffer += h_cldfb->no_channels - h_cldfb->p_filter_length;
+ }
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------*
+ * cldfbSynthesis()
+ *
+ * Conduct inverse multple overlap cmplex low delay MDCT
+ *--------------------------------------------------------------------*/
+void cldfbSynthesis(
+ float **realBuffer, /* i : real values */
+ float **imagBuffer, /* i : imag values */
+ float *timeOut, /* o : output time domain samples */
+ int samplesToProcess, /* i : number of processed samples */
+ HANDLE_CLDFB_FILTER_BANK h_cldfb /* i : filter bank state */
+)
+{
+ int i;
+ int k;
+ int L2;
+ int M1;
+ int M2;
+ int M41;
+ int M42;
+ int Mz;
+
+ float rBuffer[2*CLDFB_NO_CHANNELS_MAX];
+ float iBuffer[2*CLDFB_NO_CHANNELS_MAX];
+ const float *rot_vctr_re;
+ const float *rot_vctr_im;
+ float rr12, ir12;
+ float ri12, ii12;
+
+ float *synthesisBuffer;
+ float new_samples[2*CLDFB_NO_CHANNELS_MAX];
+
+ float *ptr_time_out;
+ const float *p_filter;
+
+ float accu0, accu1, accu2, accu3, accu4;
+ int no_col = h_cldfb->no_col;
+
+ M1 = h_cldfb->no_channels;
+ L2 = M1 << 1;
+ M2 = M1 >> 1;
+ M41 = M2>>1;
+ M42 = M2-M41;
+ Mz = M1 - h_cldfb->bandsToZero;
+
+ /* only process needed cols */
+ if(samplesToProcess > -1)
+ {
+ no_col = min(no_col, (samplesToProcess + h_cldfb->no_channels - 1) / h_cldfb->no_channels);
+ }
+
+ rot_vctr_re = h_cldfb->rot_vec_syn_re;
+ rot_vctr_im = h_cldfb->rot_vec_syn_im;
+
+ synthesisBuffer = h_cldfb->cldfb_state;
+ p_filter = h_cldfb->p_filter;
+ ptr_time_out = timeOut;
+
+ mvr2r( synthesisBuffer, synthesisBuffer + M1 * h_cldfb->no_col, h_cldfb->p_filter_length );
+
+ synthesisBuffer += M1 * h_cldfb->no_col;
+
+ for (k=0; k < no_col; k++)
+ {
+ for (i=Mz; i < M1; i++)
+ {
+ realBuffer[k][i] = 0.0f;
+ imagBuffer[k][i] = 0.0f;
+ }
+
+ for (i=0; i < M2; i++)
+ {
+ /* pre modulation of DST IV */
+ cplxMult(&rBuffer[2*i], &rBuffer[2*i+1], realBuffer[k][2*i], realBuffer[k][M1-1-2*i], rot_vctr_re[i], rot_vctr_im[i]);
+
+ /* pre modulation of DCT IV */
+ cplxMult(&iBuffer[2*i], &iBuffer[2*i+1],-imagBuffer[k][2*i], imagBuffer[k][M1-1-2*i], rot_vctr_re[i], rot_vctr_im[i]);
+ }
+
+ /* FFT of DST IV */
+ fft_cldfb(rBuffer, M2);
+
+ /* FFT of DCT IV */
+ fft_cldfb(iBuffer, M2);
+
+ /* folding */
+ for (i=0; ino_col = CLDFB_NO_COL_MAX;
+ h_cldfb->bandsToZero = 0;
+ h_cldfb->nab = 0;
+
+ h_cldfb->no_channels = samplerate * INV_CLDFB_BANDWIDTH + 0.5f;
+ h_cldfb->p_filter_length = 10*h_cldfb->no_channels;
+
+ cldfb_init_proto_and_twiddles (h_cldfb);
+
+ h_cldfb->scale = 0.f;
+ for ( k=0; kp_filter_length; k++ )
+ {
+ h_cldfb->scale += h_cldfb->p_filter[k] * h_cldfb->p_filter[k];
+ }
+
+ h_cldfb->scale *= (float)(6400/h_cldfb->no_channels);
+ h_cldfb->scale = (float)sqrt( h_cldfb->scale );
+
+ return;
+}
+
+/*-------------------------------------------------------------------*
+ * openClfdb()
+ *
+ * open and configures a CLDFB handle
+ *--------------------------------------------------------------------*/
+int openCldfb(
+ HANDLE_CLDFB_FILTER_BANK *h_cldfb, /* i/o : filter bank handle */
+ CLDFB_TYPE type, /* i : analysis or synthesis */
+ int samplerate /* i : max samplerate to oeprate */
+)
+{
+ HANDLE_CLDFB_FILTER_BANK hs;
+ short buf_len;
+
+ hs = (HANDLE_CLDFB_FILTER_BANK) calloc(1, sizeof (CLDFB_FILTER_BANK));
+ if( hs == NULL )
+ {
+ return (1);
+ }
+
+ hs->type = type;
+
+ configureCldfb (hs, samplerate);
+ hs->memory = NULL;
+ hs->memory_length = 0;
+
+ if (type == CLDFB_ANALYSIS)
+ {
+ short timeOffset = hs->p_filter_length - hs->no_channels;
+ buf_len = (hs->no_channels*hs->no_col+timeOffset);
+ }
+ else
+ {
+ buf_len = (hs->p_filter_length + hs->no_channels*hs->no_col);
+ }
+
+ hs->cldfb_state = (float *) calloc( buf_len, sizeof (float));
+ if (hs->cldfb_state == NULL)
+ {
+ return (1);
+ }
+
+ set_f(hs->cldfb_state, 0.0f, buf_len);
+
+ *h_cldfb = hs;
+
+ return (0);
+}
+
+
+/*-------------------------------------------------------------------*
+* resampleCldfb()
+*
+* Change sample rate of filter bank
+*--------------------------------------------------------------------*/
+void resampleCldfb(
+ HANDLE_CLDFB_FILTER_BANK hs,
+ int newSamplerate
+)
+{
+ short timeOffset, newframeSize;
+
+ /* keep old parameters before switching*/
+ int timeOffsetold = hs->p_filter_length - hs->no_channels;
+ int old_no_channels = hs->no_channels;
+
+ /* new settings */
+ configureCldfb (hs, newSamplerate);
+ timeOffset = hs->p_filter_length - hs->no_channels;
+ newframeSize = hs->no_channels * hs->no_col;
+
+ /*low complexity-resampling only stored previous samples that are needed for next frame modulation */
+ lerp(hs->cldfb_state+(old_no_channels*hs->no_col),hs->cldfb_state+(old_no_channels*hs->no_col),timeOffset, timeOffsetold);
+ mvr2r(hs->cldfb_state+(old_no_channels*hs->no_col),hs->cldfb_state+newframeSize,timeOffset);
+
+ return;
+}
+
+/*-------------------------------------------------------------------*
+* analysisCLDFBEncoder()
+*
+* Encoder CLDFB analysis + energy stage
+*--------------------------------------------------------------------*/
+
+void analysisCldfbEncoder(
+ Encoder_State *st, /* i/o: encoder state structure */
+ const float *timeIn,
+ int samplesToProcess,
+ float realBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX],
+ float imagBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX],
+ float *ppBuf_Ener
+)
+{
+ short i;
+ float *ppBuf_Real[CLDFB_NO_COL_MAX];
+ float *ppBuf_Imag[CLDFB_NO_COL_MAX];
+
+ for( i=0; icldfbAnaEnc );
+
+ st->currEnergyHF = GetEnergyCldfb( ppBuf_Ener, &st->currEnergyLookAhead, ppBuf_Real, ppBuf_Imag,
+ st->cldfbAnaEnc->no_channels, st->cldfbAnaEnc->no_col, &(st->tecEnc) );
+
+ return;
+}
+
+/*-------------------------------------------------------------------*
+* GetEnergyCldfb()
+*
+* Conduct energy from complex data
+*--------------------------------------------------------------------*/
+static float GetEnergyCldfb(
+ float *energyValuesSum,/*!< the result of the operation */
+ float *energyLookahead, /*!< the result in the core look-ahead slot */
+ float **realValues, /*!< the real part of the subsamples */
+ float **imagValues, /*!< the imaginary part of the subsamples */
+ int numberBands, /*!< number of bands */
+ int numberCols, /*!< number of subsamples */
+ HANDLE_TEC_ENC hTecEnc
+)
+{
+ short j, k;
+ float energyValues[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
+ short numLookahead = 1;
+
+ for (k = 0; k < numberCols; k++)
+ {
+ for (j = 0; j < numberBands; j++)
+ {
+ energyValues[k][j] = realValues[k][j] * realValues[k][j] +
+ imagValues[k][j] * imagValues[k][j];
+ }
+ }
+
+ if(numberBands >= freqTable[1])
+ {
+ float *tempEnergyValuesArry[CLDFB_NO_COL_MAX];
+
+ assert(numberCols == CLDFB_NO_COL_MAX);
+ for (j=0; jloBuffer, hTecEnc->hiTempEnv );
+ }
+
+ for (j = 0; j < numberBands; j++)
+ {
+ energyValuesSum[j]=0;
+ for (k = 0; k < CLDFB_NO_COL_MAX; k++)
+ {
+ energyValuesSum[j] += energyValues[k][j];
+ }
+ }
+
+ if (numberBands > 20)
+ {
+ float energyHF = *energyLookahead; /* energy above 8 kHz */
+ numberCols -= numLookahead;
+ *energyLookahead = 6.1e-5f; /* process look-ahead region */
+
+ for (j = 20; j < min(40, numberBands); j++)
+ {
+ energyHF += energyValuesSum[j];
+
+ for (k = numberCols; k < CLDFB_NO_COL_MAX; k++)
+ {
+ energyHF -= energyValues[k][j];
+ *energyLookahead += energyValues[k][j];
+ }
+ }
+
+ return energyHF * OUTMAX_SQ_INV;
+ }
+
+ return 65535.0f;
+}
+
+
+/*-------------------------------------------------------------------*
+* GetEnergyCldfb()
+*
+* Remove handle
+*--------------------------------------------------------------------*/
+void deleteCldfb(
+ HANDLE_CLDFB_FILTER_BANK * h_cldfb
+)
+{
+ HANDLE_CLDFB_FILTER_BANK hs = *h_cldfb;
+
+ if (hs)
+ {
+ if (hs->cldfb_state)
+ {
+ free(hs->cldfb_state);
+ }
+ free(hs);
+ *h_cldfb = NULL;
+ }
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------*
+* cldfb_init_proto_and_twiddles()
+*
+* Initializes rom pointer
+*--------------------------------------------------------------------*/
+static void cldfb_init_proto_and_twiddles(
+ HANDLE_CLDFB_FILTER_BANK hs
+)
+{
+
+ /*find appropriate set of rotVecs*/
+ switch(hs->no_channels)
+ {
+ case 10:
+ hs->rot_vec_ana_re = rot_vec_ana_re_L10;
+ hs->rot_vec_ana_im = rot_vec_ana_im_L10;
+ hs->rot_vec_syn_re = rot_vec_syn_re_L10;
+ hs->rot_vec_syn_im = rot_vec_syn_im_L10;
+ hs->p_filter = CLDFB80_10;
+ break;
+
+ case 16:
+ hs->rot_vec_ana_re = rot_vec_ana_re_L16;
+ hs->rot_vec_ana_im = rot_vec_ana_im_L16;
+ hs->rot_vec_syn_re = rot_vec_syn_re_L16;
+ hs->rot_vec_syn_im = rot_vec_syn_im_L16;
+ hs->p_filter = CLDFB80_16;
+ break;
+
+ case 20:
+ hs->rot_vec_ana_re = rot_vec_ana_re_L20;
+ hs->rot_vec_ana_im = rot_vec_ana_im_L20;
+ hs->rot_vec_syn_re = rot_vec_syn_re_L20;
+ hs->rot_vec_syn_im = rot_vec_syn_im_L20;
+ hs->p_filter = CLDFB80_20;
+ break;
+
+ case 30:
+ hs->rot_vec_ana_re = rot_vec_ana_re_L30;
+ hs->rot_vec_ana_im = rot_vec_ana_im_L30;
+ hs->rot_vec_syn_re = rot_vec_syn_re_L30;
+ hs->rot_vec_syn_im = rot_vec_syn_im_L30;
+ hs->p_filter = CLDFB80_30;
+ break;
+
+ case 32:
+ hs->rot_vec_ana_re = rot_vec_ana_re_L32;
+ hs->rot_vec_ana_im = rot_vec_ana_im_L32;
+ hs->rot_vec_syn_re = rot_vec_syn_re_L32;
+ hs->rot_vec_syn_im = rot_vec_syn_im_L32;
+ hs->p_filter = CLDFB80_32;
+ break;
+
+ case 40:
+ hs->rot_vec_ana_re = rot_vec_ana_re_L40;
+ hs->rot_vec_ana_im = rot_vec_ana_im_L40;
+ hs->rot_vec_syn_re = rot_vec_syn_re_L40;
+ hs->rot_vec_syn_im = rot_vec_syn_im_L40;
+ hs->p_filter = CLDFB80_40;
+ break;
+
+ case 60:
+ hs->rot_vec_ana_re = rot_vec_ana_re_L60;
+ hs->rot_vec_ana_im = rot_vec_ana_im_L60;
+ hs->rot_vec_syn_re = rot_vec_syn_re_L60;
+ hs->rot_vec_syn_im = rot_vec_syn_im_L60;
+ hs->p_filter = CLDFB80_60;
+ break;
+
+ }
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------*
+* cldfb_save_memory()
+*
+* Save the memory of filter; to be restored with cldfb_restore_memory()
+*--------------------------------------------------------------------*/
+int cldfb_save_memory(
+ HANDLE_CLDFB_FILTER_BANK hs /* i/o: cldfb handle */
+)
+{
+ unsigned int offset = hs->p_filter_length - hs->no_channels;
+ unsigned int frameSize = hs->no_channels * hs->no_col;
+
+ if (hs->memory != NULL || hs->memory_length!=0)
+ {
+ /* memory already stored; Free memory first */
+ return 1;
+ }
+
+
+ if (hs->type == CLDFB_ANALYSIS)
+ {
+ hs->memory_length = offset + frameSize;
+ }
+ else
+ {
+ hs->memory_length = hs->p_filter_length;
+ }
+
+ hs->memory = (float *) calloc( hs->memory_length, sizeof (float));
+ if (hs->memory == NULL)
+ {
+ /* memory cannot be allocated */
+ return (1);
+ }
+
+ /* save the memory */
+ mvr2r (hs->cldfb_state, hs->memory, hs->memory_length);
+
+ return 0;
+}
+
+
+/*-------------------------------------------------------------------*
+* cldfb_restore_memory()
+*
+* Restores the memory of filter; memory to be save by cldfb_save_memory()
+*--------------------------------------------------------------------*/
+int cldfb_restore_memory(
+ HANDLE_CLDFB_FILTER_BANK hs /* i/o: cldfb handle */
+)
+{
+ unsigned int offset = hs->p_filter_length - hs->no_channels;
+ unsigned int frameSize = hs->no_channels * hs->no_col;
+ unsigned int size;
+
+ if (hs->memory == NULL || hs->memory_length==0)
+ {
+ /* memory not allocated */
+ return 1;
+ }
+
+ if ( hs->type == CLDFB_ANALYSIS )
+ {
+ size = offset + frameSize;
+ }
+ else
+ {
+ size = hs->p_filter_length;
+ }
+
+ /* read the memory */
+ mvr2r (hs->memory, hs->cldfb_state, hs->memory_length);
+
+ /* adjust sample rate if it was changed in the meanwhile */
+ if (hs->memory_length != size)
+ {
+ lerp(hs->cldfb_state, hs->cldfb_state, size, hs->memory_length);
+ }
+
+ hs->memory_length = 0;
+ free(hs->memory);
+ hs->memory = NULL;
+
+ return 0;
+}
+
+
+/*-------------------------------------------------------------------*
+* cldfb_reset_memory()
+*
+* Resets the memory of filter.
+*--------------------------------------------------------------------*/
+int cldfb_reset_memory(
+ HANDLE_CLDFB_FILTER_BANK hs /* i/o: cldfb handle */
+)
+{
+ unsigned int offset = hs->p_filter_length - hs->no_channels;
+ unsigned int frameSize = hs->no_channels * hs->no_col;
+ int memory_length;
+
+ if (hs->type == CLDFB_ANALYSIS)
+ {
+ memory_length = offset + frameSize;
+ }
+ else
+ {
+ memory_length = hs->p_filter_length;
+ }
+
+ /* save the memory */
+ set_f (hs->cldfb_state, 0, memory_length);
+
+ return 0;
+}
diff --git a/lib_com/cng_exc.c b/lib_com/cng_exc.c
new file mode 100644
index 0000000000000000000000000000000000000000..f193b861b11da05ec2221a2b77f56436bfd1b9b4
--- /dev/null
+++ b/lib_com/cng_exc.c
@@ -0,0 +1,558 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include
+#include "wmc_auto.h"
+#include
+#include "options.h"
+#include "cnst.h"
+#include "prot.h"
+#include "rom_com.h"
+
+/*---------------------------------------------------------------------*
+ * Local constants
+ *---------------------------------------------------------------------*/
+
+#define A2 0.2f
+#define GAIN_VAR 0.000011f
+
+/*-------------------------------------------------------*
+ * CNG_exc()
+ *
+ * Comfort noise generation routine
+ *-------------------------------------------------------*/
+
+void CNG_exc(
+ const long core_brate, /* i : core bitrate */
+ const short L_frame, /* i : length of the frame */
+ float *Enew, /* i/o: decoded SID energy */
+ short *seed, /* i/o: random generator seed */
+ float exc[], /* o : current non-enhanced excitation */
+ float exc2[], /* o : current enhanced excitation */
+ float *lp_ener, /* i/o: LP filtered E */
+ const long last_core_brate, /* i : previous frame core bitrate */
+ short *first_CNG, /* i/o: first CNG frame flag for energy init. */
+ short *cng_ener_seed, /* i/o: random generator seed for CNG energy */
+ float bwe_exc[], /* o : excitation for SWB TBE */
+ const short allow_cn_step, /* i : allow CN step */
+ short *last_allow_cn_step, /* i/o: last allow step */
+ const short num_ho, /* i : number of selected hangover frames */
+ float q_env[],
+ float *lp_env,
+ float *old_env,
+ float *exc_mem,
+ float *exc_mem1,
+ short *sid_bw,
+ short *cng_ener_seed1,
+ float exc3[],
+ short Opt_AMR_WB
+)
+{
+ float enr;
+ short i;
+ float ener_lp;
+ short i_subfr;
+ short pit_max;
+ float ftmp;
+ float *ptR,*ptI;
+ float fft_io[L_FRAME16k];
+ float itmp[129];
+ float env[NUM_ENV_CNG];
+ float enr1;
+ float denv[NUM_ENV_CNG];
+
+ /*------------------------------------------------------------------*
+ * Initializations
+ *------------------------------------------------------------------*/
+
+ if( L_frame == L_FRAME )
+ {
+ pit_max = PIT_MAX;
+ }
+ else /* L_frame == L_FRAME16k */
+ {
+ pit_max = PIT16k_MAX;
+ }
+
+ /*---------------------------------------------------------------------*
+ * Initialization of CNG energy for the first CNG frame
+ *---------------------------------------------------------------------*/
+
+ if( *first_CNG == 0 )
+ {
+ if( core_brate == FRAME_NO_DATA )
+ {
+ /* needed only in decoder when the very first SID frame was erased and this frame is FRAME_NO_DATA frame */
+ *Enew = dotp( exc-pit_max, exc-pit_max, pit_max ) / pit_max;
+ }
+
+ *lp_ener = *Enew;
+ }
+
+ /*---------------------------------------------------------------------*
+ * Update CNG energy
+ *---------------------------------------------------------------------*/
+
+ if( last_core_brate != SID_1k75 && last_core_brate != FRAME_NO_DATA && last_core_brate != SID_2k40 )
+ {
+ /* Partially reset CNG energy after active speech period */
+ if ( allow_cn_step == 0 && *last_allow_cn_step == 0 )
+ {
+ if( num_ho < 3 || *Enew < 1.5f * *lp_ener )
+ {
+ *lp_ener = 0.8f * *lp_ener + 0.2f * *Enew;
+ }
+ else
+ {
+ *lp_ener = 0.95f * *lp_ener + 0.05f * *Enew;
+ }
+ }
+ else
+ {
+ *lp_ener = *Enew;
+ *last_allow_cn_step = 0;
+ }
+ }
+ else
+ {
+ /* normal CNG update */
+ if ( *last_allow_cn_step == 0 )
+ {
+ *lp_ener = (float)(A2 **Enew + (1-A2) **lp_ener);
+ }
+ else
+ {
+ if ( core_brate == SID_1k75 || core_brate == SID_2k40 )
+ {
+ *last_allow_cn_step = 0;
+ }
+
+ *lp_ener = *Enew;
+
+ }
+ }
+
+ if ( allow_cn_step == 1 )
+ {
+ *last_allow_cn_step = 1;
+ }
+
+ /*---------------------------------------------------------------------*
+ * Generate white noise vector
+ *---------------------------------------------------------------------*/
+
+ for ( i=0; i 1 )
+ {
+ enr = 1;
+ }
+ }
+
+ for ( i=0; i 1 )
+ {
+ enr = 1;
+ }
+
+ ftmp = sqrt(enr);
+ for (i=0; i ACELP_13k20 )
+ {
+ CNG_mode = 4;
+ }
+ else if( last_active_brate > ACELP_9k60 )
+ {
+ CNG_mode = 3;
+ }
+ else if( last_active_brate > ACELP_8k00 )
+ {
+ CNG_mode = 2;
+ }
+ else if( last_active_brate > ACELP_7k20 )
+ {
+ CNG_mode = 1;
+ }
+ else
+ {
+ CNG_mode = 0;
+ }
+
+ att = 1/pow(2,ENR_ATT[CNG_mode]);
+
+ for ( i=0; i HO_HIST_SIZE)
+ {
+ *cng_buf_cnt = HO_HIST_SIZE;
+ }
+ mvr2r( exc2, &(cng_exc2_buf[(*ho_circ_ptr)*L_FFT]), L_FFT );
+ cng_brate_buf[*ho_circ_ptr] = last_active_brate;
+ }
+ else
+ {
+
+ /* calculate the spectrum of residual signal */
+ mvr2r(exc2, fft_io, L_frame);
+
+ fft_rel(fft_io, L_FFT, LOG2_L_FFT);
+
+ ptR = &fft_io[1];
+ ptI = &fft_io[L_FFT-1];
+ for (i=0; i ACELP_13k20 )
+ {
+ CNG_mode = 4;
+ }
+ else if( last_active_brate > ACELP_9k60 )
+ {
+ CNG_mode = 3;
+ }
+ else if( last_active_brate > ACELP_8k00 )
+ {
+ CNG_mode = 2;
+ }
+ else if( last_active_brate > ACELP_7k20 )
+ {
+ CNG_mode = 1;
+ }
+ else
+ {
+ CNG_mode = 0;
+ }
+
+ att = 1/pow(2,ENR_ATT[CNG_mode]);
+
+ for ( i=0; i HO_HIST_SIZE )
+ {
+ *ho_circ_size = HO_HIST_SIZE;
+ }
+
+ return;
+}
diff --git a/lib_com/cnst.h b/lib_com/cnst.h
new file mode 100644
index 0000000000000000000000000000000000000000..21d2eaf9ca48f8aa2a1050e6e45f8cdf3ff0acf0
--- /dev/null
+++ b/lib_com/cnst.h
@@ -0,0 +1,2005 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#ifndef CNST_H
+#define CNST_H
+
+#include "options.h"
+
+/*----------------------------------------------------------------------------------*
+ * General constants
+ *----------------------------------------------------------------------------------*/
+
+#define MODE1 1
+#define MODE2 2
+
+#define EVS_PI 3.14159265358979323846264338327950288f
+
+#define PI2 (2*EVS_PI)
+#define RANDOM_INITSEED 21845 /* Seed for random generators */
+#ifndef FLT_MIN
+#define FLT_MIN (1.175494351e-38F)
+#endif
+#ifndef FLT_MAX
+#define FLT_MAX (3.402823466e+38F)
+#endif
+#define TRUE 1
+#define FALSE 0
+
+
+#define MAX_FRAME_COUNTER 200
+#define MAX_BITS_PER_FRAME 2560
+
+#define ENC 0 /* Index for "encoder" */
+#define DEC 1 /* Index for "decoder" */
+
+#define NB 0 /* Indicator of 4 kHz bandwidth */
+#define WB 1 /* Indicator of 8 kHz bandwidth */
+#define SWB 2 /* Indicator of 14 kHz bandwidth */
+#define FB 3 /* Indicator of 20 kHz bandwidth */
+
+/* Conversion of bandwidth string into numerical constant */
+#define CONV_BWIDTH(bw) ( !strcmp(bw, "NB") ? NB : !strcmp(bw, "WB") ? WB : !strcmp(bw, "SWB") ? SWB : !strcmp(bw, "FB") ? FB : -1)
+
+#define L_FRAME48k 960 /* Frame size in samples at 48kHz */
+#define L_FRAME32k 640 /* Frame size in samples at 32kHz */
+#define L_FRAME16k 320 /* Frame size in samples at 16kHz */
+#define L_FRAME8k 160 /* Frame size in samples at 8kHz */
+
+/* Conversion of ns to samples for a given sampling frequency */
+#define NS2SA(fs,x) (short)((((long)(fs)/100L) * ((x)/100L)) / 100000L)
+
+#define SYNC_GOOD_FRAME (unsigned short) 0x6B21 /* synchronization word of a "good" frame */
+#define SYNC_BAD_FRAME (unsigned short) 0x6B20 /* synchronization word of a "bad" frame */
+#define G192_BIN0 (unsigned short) 0x007F /* binary "0" according to ITU-T G.192 */
+#define G192_BIN1 (unsigned short) 0x0081 /* binary "1" according to ITU-T G.192 */
+
+#define ACTIVE_FRAME 0xFF
+#define SID_FRAME 0xFA
+#define ZERO_FRAME 0xF0
+#define FRAME_SIZE_NB 13
+
+#define RATE_MODE_MAX 2 /* Number of rate mode */
+#define BANDWIDTH_MODE_MAX 2 /* Number of different bandwidth (NB/WB-FB) */
+
+#define MIN_LOG_60dB 0.000001f
+#define MIN_LOG_VAL_60dB -60.0f
+
+#define INV_LOG_2 1.442695040888963f /* 1/log(2) */
+
+
+/*----------------------------------------------------------------------------------*
+ * Layers
+ *----------------------------------------------------------------------------------*/
+
+#define ACELP_CORE 0 /* ACELP core layer */
+#define TCX_20_CORE 1 /* TCX 20ms core layer */
+#define TCX_10_CORE 2 /* TCX 10ms core layer */
+#define HQ_CORE 3 /* HQ core layer */
+#define AMR_WB_CORE 4 /* AMR-WB IO core */
+
+
+#define WB_TBE 5 /* WB TBE layer (16/32/48kHz signals) */
+#define WB_BWE 6 /* WB BWE layer optimized for music (16/32/48kHz signals) */
+
+#define SWB_CNG 7 /* SWB CNG layer (32/48kHz signals) */
+#define SWB_TBE 8 /* SWB TBE layer optimized for speech (32/48kHz signals) */
+#define SWB_BWE 9 /* SWB BWE layer optimized for music (32/48kHz signals) */
+#define SWB_BWE_HIGHRATE 10 /* SWB BWE layer optimized for highrate speech (32/48kHz) */
+
+#define FB_TBE 11 /* FB TBE layer (48kHz signals) */
+#define FB_BWE 12 /* FB BWE layer optimized for music (48kHz) */
+#define FB_BWE_HIGHRATE 13 /* FB BWE layer optimized for highrate speech (48kHz) */
+
+#define IGF_BWE 14 /* IGF layer for music (16.4 and 24.4kbps), 32kHz signals */
+
+#define LP_CNG 0 /* LP-based CNG in DTX operation */
+#define FD_CNG 1 /* FD-based CNG in DTX operation */
+
+/*----------------------------------------------------------------------------------*
+ * Bitrates
+ *----------------------------------------------------------------------------------*/
+
+#define FRAME_NO_DATA 0 /* Frame with no data */
+#define SID_1k75 1750 /* SID at 1.75 kbps (used only in AMR-WB IO mode */
+#define SID_2k40 2400 /* SID at 2.40 kbps */
+#define PPP_NELP_2k80 2800 /* PPP and NELP at 2.80 kbps (used only for SC-VBR) */
+#define ACELP_5k90 5900 /* ACELP core layer at average bitrate of 5.90 kbps (used only in SC-VBR mode) */
+#define ACELP_6k60 6600 /* ACELP core layer at 6.60 kbps (used only in AMR-WB IO mode) */
+#define ACELP_7k20 7200 /* ACELP core layer at 7.20 kbps */
+#define ACELP_8k00 8000 /* ACELP core layer at 8 kbps */
+#define ACELP_8k85 8850 /* ACELP core layer at 8.85 kbps (used only in AMR-WB IO mode) */
+#define ACELP_9k60 9600 /* ACELP core layer at 9.60 kbps */
+#define ACELP_11k60 11600 /* ACELP core layer at 11.60 kbps (used for SWB TBE) */
+#define ACELP_12k15 12150 /* ACELP core layer at 12.15 kbps (used for WB TBE) */
+#define ACELP_12k65 12650 /* ACELP core layer at 12.65 kbps (used only in AMR-WB IO mode) */
+#define ACELP_12k85 12850 /* ACELP core layer at 12.85 kbps (used for WB BWE) */
+#define ACELP_13k20 13200 /* ACELP core layer at 13.20 kbps */
+#define ACELP_14k25 14250 /* ACELP core layer at 14.25 kbps (used only in AMR-WB IO mode) */
+#define ACELP_14k80 14800 /* ACELP core layer at 14.80 kbps (used only in core switching) */
+#define ACELP_15k85 15850 /* ACELP core layer at 15.85 kbps (used only in AMR-WB IO mode) */
+#define ACELP_16k40 16400 /* ACELP core layer at 16.40 kbps */
+#define ACELP_18k25 18250 /* ACELP core layer at 18.25 kbps (used only in AMR-WB IO mode) */
+#define ACELP_19k85 19850 /* ACELP core layer at 19.85 kbps (used only in AMR-WB IO mode) */
+#define ACELP_22k60 22600 /* ACELP core layer at 22.60 kbps (used only in core switching) */
+#define ACELP_23k05 23050 /* ACELP core layer at 23.05 kbps (used only in AMR-WB IO mode) */
+#define ACELP_23k85 23850 /* ACELP core layer at 23.85 kbps (used only in AMR-WB IO mode) */
+#define ACELP_24k40 24400 /* ACELP core layer at 24.40 kbps */
+#define ACELP_29k00 29000 /* ACELP core layer at 29.00 kbps (used for FB + SWB TBE) */
+#define ACELP_29k20 29200 /* ACELP core layer at 29.20 kbps (used for SWB TBE) */
+#define ACELP_30k20 30200 /* ACELP core layer at 30.20 kbps (used for FB + SWB BWE) */
+#define ACELP_30k40 30400 /* ACELP core layer at 30.40 kbps (used for SWB BWE) */
+#define ACELP_32k 32000 /* ACELP core layer at 32 kbps */
+#define ACELP_48k 48000 /* ACELP core layer at 48 kbps */
+#define ACELP_64k 64000 /* ACELP core layer at 64 kbps */
+
+#define HQ_16k40 16400 /* HQ core at 16.4 kbps */
+#define HQ_13k20 13200 /* HQ core at 13.2 kbps */
+#define HQ_24k40 24400 /* HQ core at 24.4 kbps */
+#define HQ_32k 32000 /* HQ core at 32 kbps */
+#define HQ_48k 48000 /* HQ core at 48 kbps */
+#define HQ_64k 64000 /* HQ core at 64 kbps */
+#define HQ_96k 96000 /* HQ core at 96 kbps */
+#define HQ_128k 128000 /* HQ core at 128 kbps */
+
+#define WB_TBE_0k35 350 /* WB TBE layer (used only at 9.6 kbps on top of ACELP@12k8 core for 16kHz signals) */
+#define WB_BWE_0k35 350 /* WB BWE layer (used only on top of ACELP@12k8 core for 16kHz signals) */
+#define WB_TBE_1k05 1050 /* WB TBE layer (used only on top of ACELP@12k8 core for 16kHz signals) */
+#define SWB_TBE_1k6 1600 /* SWB TBE layer */
+#define SWB_BWE_1k6 1600 /* SWB BWE layer */
+#define FB_TBE_1k8 1800 /* SWB+FB TBE layer (used only for 48kHz signals) */
+#define FB_BWE_1k8 1800 /* SWB+FB BWE layer (used only for 48kHz signals) */
+#define SWB_TBE_2k8 2800 /* SWB TBE layer @32kbps */
+#define FB_TBE_3k0 3000 /* SWB+FB TBE layer @32kbps (used only for 48kHz signals) */
+#define SWB_BWE_16k 16000 /* SWB BWE layer for highrate SWB speech */
+
+#define SIZE_BRATE_TBL 11
+
+#define BRATE2IDX(brate) ( brate == ACELP_7k20 ? 0: \
+ brate == ACELP_8k00 ? 1 : \
+ brate == ACELP_11k60 ? 2 : \
+ brate == ACELP_12k15 ? 3 : \
+ brate == ACELP_12k85 ? 4 : \
+ brate == ACELP_13k20 ? 5 : \
+ brate == ACELP_14k80 ? 6 : \
+ brate == ACELP_16k40 ? 7 : \
+ brate == ACELP_22k60 ? 8 : \
+ brate == ACELP_24k40 ? 9 : \
+ brate == ACELP_29k00 ? 10 : \
+ brate == ACELP_29k20 ? 11 : \
+ brate == ACELP_30k20 ? 12 : \
+ brate == ACELP_30k40 ? 13 : \
+ brate == ACELP_32k ? 14 : \
+ brate == ACELP_48k ? 15 : \
+ brate == ACELP_64k ? 16 : \
+ brate == HQ_96k ? 17 : \
+ brate == HQ_128k ? 18 : -1 )
+
+#define BRATE2IDX16k( brate ) ( brate == ACELP_8k00 ? 0 : \
+ brate == ACELP_14k80 || brate == ACELP_16k40? 1 : \
+ brate == ACELP_22k60 ? 2 : \
+ brate == ACELP_24k40 ? 3 : \
+ brate == ACELP_29k00 ? 4 : \
+ brate == ACELP_29k20 ? 5 : \
+ brate == ACELP_30k20 ? 6 : \
+ brate == ACELP_30k40 ? 7 : \
+ brate == ACELP_32k ? 8 : \
+ brate == ACELP_48k ? 9 : \
+ brate == ACELP_64k ? 10: -1 )
+
+/* Combine parameters into a single index (used to retrieve number of bits from bit allocation tables) */
+#define LSF_BIT_ALLOC_IDX(brate, ctype) ( 6*BRATE2IDX(brate) + (ctype) )
+
+#define BIT_ALLOC_IDX(brate, ctype, sfrm, tc) \
+ ( ( sfrm != -1 ? NB_SUBFR : 1 ) * \
+ ( ( tc == -1 ? 4 : 10 ) * BRATE2IDX(brate) + (ctype == INACTIVE ? GENERIC : ctype) - 1 + (tc == -1 ? 0 : tc) ) + \
+ ( sfrm != -1 ? sfrm/L_SUBFR : 0 ) )
+
+#define BIT_ALLOC_IDX_16KHZ(brate, ctype, sfrm, tc) \
+ ( ( sfrm > -1 ? NB_SUBFR16k : 1 ) * \
+ ( ( tc == -1 ? 3 : 7 ) * BRATE2IDX16k(brate) + (ctype == TRANSITION ? 2 : (ctype == GENERIC ? 1 :0) ) + (tc == -1 ? 0 : tc) ) + \
+ ( sfrm != -1 ? sfrm/L_SUBFR : 0 ) )
+
+/* Combine coder_type, bandwidth, formant sharpening flag, and channel-aware flag into one indice */
+#define SIG2IND(ctype, bw, sf, ca_rf) ( ctype | (bw << 3) | (sf << 6) | (ca_rf << 7) )
+
+#define MAX_ACELP_SIG 100
+
+/*----------------------------------------------------------------------------------*
+ * Bitstream indices
+ *----------------------------------------------------------------------------------*/
+#define MAX_PVQ_PUSH_IND 320 /* Maximum number of (fwd+reverse) calls to push_indices for the PVQ_range encoder */
+enum
+{
+ IND_CORE,
+ IND_PPP_NELP_MODE,
+ IND_SID_TYPE,
+ IND_ACELP_16KHZ,
+ IND_ACELP_SIGNALLING,
+ IND_MDCT_CORE,
+ IND_BWE_FLAG,
+ IND_HQ_SWITCHING_FLG,
+ IND_LAST_L_FRAME,
+ IND_VAD_FLAG,
+ IND_HQ_BWIDTH,
+ IND_TC_SUBFR,
+ IND_LSF_PREDICTOR_SELECT_BIT = IND_TC_SUBFR + 4,
+ IND_LSF,
+ IND_MID_FRAME_LSF_INDEX = IND_LSF + 17,
+
+ IND_ISF_0_0,
+ IND_ISF_0_1,
+ IND_ISF_0_2,
+ IND_ISF_0_3,
+ IND_ISF_0_4,
+ IND_ISF_1_0,
+ IND_ISF_1_1,
+ IND_ISF_1_2,
+ IND_ISF_1_3,
+ IND_ISF_1_4,
+
+ IND_GSC_ATTACK,
+ IND_GSC_SWB_SPEECH,
+ IND_NOISE_LEVEL,
+ IND_HF_NOISE,
+ IND_PIT_CONTR_IDX,
+ IND_FEC_CLAS,
+ IND_FEC_ENR,
+ IND_FEC_POS,
+ IND_ES_PRED,
+ IND_HARM_FLAG_ACELP,
+ /* ------------- Loop for alg. codebook indices at 24.4 kbps (special case) -------------- */
+ TAG_ALG_CDBK_4T64_24KBIT_START,
+ IND_ALG_CDBK_4T64_1_24KBIT = TAG_ALG_CDBK_4T64_24KBIT_START,
+ IND_ALG_CDBK_4T64_2_24KBIT = TAG_ALG_CDBK_4T64_24KBIT_START,
+ TAG_ALG_CDBK_4T64_24KBIT_END = TAG_ALG_CDBK_4T64_24KBIT_START + 40,
+ /* ------------------------------------------------ */
+
+ /* ------------- ACELP subframe loop -------------- */
+ TAG_ACELP_SUBFR_LOOP_START,
+ IND_PITCH = TAG_ACELP_SUBFR_LOOP_START,
+ IND_LP_FILT_SELECT = TAG_ACELP_SUBFR_LOOP_START,
+ IND_ALG_CDBK_1T64 = TAG_ACELP_SUBFR_LOOP_START,
+ IND_ALG_CDBK_2T32 = TAG_ACELP_SUBFR_LOOP_START,
+ IND_ALG_CDBK_4T64 = TAG_ACELP_SUBFR_LOOP_START,
+ IND_ALG_CDBK_4T64_1 = TAG_ACELP_SUBFR_LOOP_START,
+ IND_ALG_CDBK_4T64_2 = TAG_ACELP_SUBFR_LOOP_START,
+ IND_ALG_CDBK_4T64_1BIT = TAG_ACELP_SUBFR_LOOP_START,
+ IND_GAUS_CDBK_INDEX = TAG_ACELP_SUBFR_LOOP_START,
+ IND_TILT_FACTOR = TAG_ACELP_SUBFR_LOOP_START,
+ IND_GAIN = TAG_ACELP_SUBFR_LOOP_START,
+ IND_GAIN_CODE = TAG_ACELP_SUBFR_LOOP_START,
+ IND_TC_IMP_SHAPE = TAG_ACELP_SUBFR_LOOP_START,
+ IND_TC_IMP_POS = TAG_ACELP_SUBFR_LOOP_START,
+ IND_TC_IMP_SIGN = TAG_ACELP_SUBFR_LOOP_START,
+ IND_TC_IMP_GAIN = TAG_ACELP_SUBFR_LOOP_START,
+ IND_GAIN_PIT = TAG_ACELP_SUBFR_LOOP_START,
+ IND_PIT_IDX = TAG_ACELP_SUBFR_LOOP_START,
+ IND_AVQ_GAIN = TAG_ACELP_SUBFR_LOOP_START,
+ IND_I = TAG_ACELP_SUBFR_LOOP_START,
+ IND_KV = TAG_ACELP_SUBFR_LOOP_START,
+ IND_NQ = TAG_ACELP_SUBFR_LOOP_START,
+ IND_HF_GAIN_MODIFICATION = TAG_ACELP_SUBFR_LOOP_START,
+ TAG_ACELP_SUBFR_LOOP_END = TAG_ACELP_SUBFR_LOOP_START + 300,
+ /* ------------------------------------------------ */
+
+ IND_MEAN_GAIN2,
+ IND_Y_GAIN_TMP = IND_MEAN_GAIN2 + 32,
+ IND_Y_GAIN_HF = IND_Y_GAIN_TMP + 32,
+ IND_HQ_VOICING_FLAG,
+ IND_HQ_SWB_CLAS,
+ IND_NF_IDX,
+ IND_LC_MODE,
+ IND_YNRM,
+ IND_HQ_SWB_EXC_SP_CLAS = IND_YNRM + 44,
+ IND_HQ_SWB_EXC_CLAS = IND_HQ_SWB_EXC_SP_CLAS,
+ IND_SWB_FENV_HQ = IND_HQ_SWB_EXC_CLAS,
+ IND_FB_FENV_HQ = IND_SWB_FENV_HQ + 5,
+ IND_DELTA_ENV_HQ = IND_FB_FENV_HQ + 5,
+ IND_HVQ_BWE_NL,
+ IND_NUM_PEAKS = IND_HVQ_BWE_NL + 2,
+ IND_POS_IDX,
+ IND_FLAGN = IND_POS_IDX + 280,
+ IND_PG_IDX,
+ IND_HVQ_PEAKS = IND_PG_IDX + 27,
+ IND_HVQ_NF_GAIN = IND_HVQ_PEAKS + 54,
+ IND_HQ2_SWB_CLAS = IND_HVQ_NF_GAIN + 2,
+ IND_HQ2_DENG_MODE,
+ IND_HQ2_DENG_8SMODE,
+ IND_HQ2_DENG_8SMODE_N0,
+ IND_HQ2_DENG_8SMODE_N1,
+ IND_HQ2_DENG_8SPOS,
+ IND_HQ2_DENG_8SDEPTH,
+ IND_HQ2_DENG_HMODE,
+ IND_HQ2_DIFF_ENERGY,
+ IND_HQ2_P2A_FLAGS = IND_HQ2_DIFF_ENERGY + 100,
+ IND_HQ2_LAST_BA_MAX_BAND = IND_HQ2_P2A_FLAGS + 60,
+ IND_RC_START = IND_HQ2_LAST_BA_MAX_BAND + 2,
+ IND_RC_END = IND_RC_START + MAX_PVQ_PUSH_IND ,
+ IND_HVQ_PVQ_GAIN = IND_RC_END+1,
+ IND_NOISINESS = IND_HVQ_PVQ_GAIN + 8,
+ IND_ENERGY,
+ IND_CNG_HO,
+ IND_SID_BW,
+ IND_CNG_ENV1,
+ IND_WB_FENV,
+ IND_WB_CLASS,
+ IND_IG1,
+ IND_IG2A,
+ IND_IG2B,
+ IND_NELP_FID,
+ IND_DELTALAG,
+ IND_POWER,
+ IND_AMP0,
+ IND_AMP1,
+ IND_GLOBAL_ALIGNMENT,
+ IND_PVQ_FINE_GAIN,
+ IND_UV_FLAG,
+ IND_SHB_SUBGAIN = IND_PVQ_FINE_GAIN + 44,
+ IND_SHB_FRAMEGAIN,
+ IND_SHB_ENER_SF,
+ IND_SHB_RES_GS1,
+ IND_SHB_RES_GS2,
+ IND_SHB_RES_GS3,
+ IND_SHB_RES_GS4,
+ IND_SHB_RES_GS5,
+ IND_SHB_VF,
+ IND_SHB_LSF,
+ IND_SHB_MIRROR = IND_SHB_LSF + 5,
+ IND_SHB_GRID,
+ IND_SWB_CLASS,
+ IND_SWB_TENV,
+ IND_SWB_FENV = IND_SWB_TENV + 4,
+ IND_SHB_CNG_GAIN = IND_SWB_FENV + 4,
+ IND_DITHERING,
+ IND_FB_SLOPE,
+
+ IND_HQ2_SPT_SHORTEN,
+ IND_HQ2_SUBBAND_TCQ,
+ IND_HQ2_SUBBAND_GAIN = IND_HQ2_SUBBAND_TCQ + 100,
+ IND_HQ2_DUMMY = IND_HQ2_SUBBAND_GAIN + 20,
+
+ IND_LAGINDICES,
+ IND_NOISEG,
+ IND_AUDIO_GAIN,
+ IND_AUDIO_DELAY,
+
+ /* ------------- HR SWB BWE loop -------------- */
+ TAG_HR_BWE_LOOP_START = IND_AUDIO_DELAY + 4,
+ IND_HR_IS_TRANSIENT = TAG_HR_BWE_LOOP_START,
+ IND_HR_GAIN = TAG_HR_BWE_LOOP_START,
+ IND_HR_ENVELOPE = TAG_HR_BWE_LOOP_START,
+ IND_HR_HF_GAIN = TAG_HR_BWE_LOOP_START,
+ IND_I2 = TAG_HR_BWE_LOOP_START,
+ IND_KV2 = TAG_HR_BWE_LOOP_START,
+ IND_NQ2 = TAG_HR_BWE_LOOP_START,
+ TAG_HR_BWE_LOOP_END = TAG_HR_BWE_LOOP_START + 200,
+ /* ------------------------------------------------ */
+
+ IND_CORE_SWITCHING_CELP_SUBFRAME,
+ IND_CORE_SWITCHING_AUDIO_DELAY = IND_CORE_SWITCHING_CELP_SUBFRAME + 20,
+ IND_CORE_SWITCHING_AUDIO_GAIN,
+
+ IND_UNUSED,
+ MAX_NUM_INDICES = IND_UNUSED + 127
+};
+
+/*----------------------------------------------------------------------------------*
+ * Delays
+ *----------------------------------------------------------------------------------*/
+
+#define FRAME_SIZE_NS 20000000L
+
+#define ACELP_LOOK_NS 8750000L
+#define DELAY_FIR_RESAMPL_NS 937500L
+#define DELAY_CLDFB_NS 1250000L
+
+#define DELAY_SWB_TBE_12k8_NS 1250000L
+#define DELAY_SWB_TBE_16k_NS 1125000L
+#define MAX_DELAY_TBE_NS 1312500L
+#define DELAY_BWE_TOTAL_NS 2312500L
+#define DELAY_FD_BWE_ENC_12k8_NS (DELAY_BWE_TOTAL_NS - (MAX_DELAY_TBE_NS - DELAY_SWB_TBE_12k8_NS))
+#define DELAY_FD_BWE_ENC_16k_NS (DELAY_BWE_TOTAL_NS - (MAX_DELAY_TBE_NS - DELAY_SWB_TBE_16k_NS))
+#define DELAY_FD_BWE_ENC_NS 2250000L
+
+#define L_LOOK_12k8 NS2SA(INT_FS_12k8, ACELP_LOOK_NS) /* look-ahead length at 12.8kHz */
+#define L_LOOK_16k NS2SA(INT_FS_16k, ACELP_LOOK_NS) /* look-ahead length at 16kHz */
+
+/* core switching constants @16kHz */
+#define SWITCH_GAP_LENGTH_NS 6250000L /* lenght of ACELP->HQ switching gap in ms */
+#define HQ_DELAY_COMP NS2SA(8000, DELAY_CLDFB_NS)
+#define HQ_DELTA_MAX 6 /* maximum multiplication factor (==48kHz/8kHz) for core switching modules */
+
+#define N_ZERO_MDCT_NS 5625000L /* number of zeros in ms for MDCT */
+#define NL_BUFF_OFFSET 12
+
+#define N_WS2N_FRAMES 40 /* number of frames for attenuation during the band-width switching */
+#define N_NS2W_FRAMES 20 /* number of frames for attenuation during the band-width switching */
+
+/*----------------------------------------------------------------------------------*
+ * Coder types (only for ACELP core when not running in AMR-WB IO mode)
+ *----------------------------------------------------------------------------------*/
+
+#define INACTIVE 0 /* inactive */
+#define UNVOICED 1 /* unvoiced */
+#define VOICED 2 /* purely voiced */
+#define GENERIC 3 /* generic */
+#define TRANSITION 4 /* transition */
+#define AUDIO 5 /* audio (GSC) */
+#define LR_MDCT 6 /* low-rate MDCT core */
+
+/*--------------------------------------------------*
+ * Partial copy frame types (only for ACELP core )
+ *--------------------------------------------------*/
+
+#define ACELP_MODE_MAX 4
+#define RF_MODE_MAX 4
+
+/* TCX partial copy frame types */
+#define RF_NO_DATA 0
+#define RF_TCXFD 1
+#define RF_TCXTD1 2
+#define RF_TCXTD2 3
+
+/* ACELP partial copy frame types */
+#define RF_ALLPRED ACELP_MODE_MAX
+#define RF_NOPRED ACELP_MODE_MAX + 1
+#define RF_GENPRED ACELP_MODE_MAX + 2
+#define RF_NELP ACELP_MODE_MAX + 3
+
+
+/*--------------------------------------------------------------*
+ * Frame length constants in mode 2
+ *---------------------------------------------------------------*/
+
+#define ACELP_TCX_TRANS_NS 1250000 /* Duration of the ACELP->TCX overlap - 1.25 ms */
+#define L_FRAME_MAX 960 /* Max 20ms frame size @48kHz */
+#define L_FRAME_PLUS 1200 /* Max frame size (long TCX frame) */
+#define L_MDCT_OVLP_MAX NS2SA(48000,ACELP_LOOK_NS) /* = Max mdct overlap */
+#define N_TCX10_MAX 480 /* Max size of TCX10 MDCT spectrum */
+#define BITS_TEC 1 /* number of bits for TEC */
+#define BITS_TFA 1 /* number of bits for TTF */
+#define N_TEC_TFA_SUBFR 16 /* number of subframes of TEC/TFA */
+#define L_TEC_TFA_SUBFR16k (L_FRAME16k/N_TEC_TFA_SUBFR) /* TEC/TFA subframe size @ 16kHz*/
+#define MAX_TEC_SMOOTHING_DEG 6 /* max degree of smoothing for TEC */
+#define N_MAX 1200 /* Max size of MDCT spectrum = 25ms @ 48kHz */
+#define N_MAX_TCX 1000 /* Max size of TCX/IGF coded lines */
+#define IGF_START_MN 164 /* MDCT lines not used by IGF*/
+#define IGF_START_MX 800 /* max. MDCT lines used by IGF*/
+
+#define NUM_DCT_LENGTH 24
+
+#define NB_DIV 2 /* number of division (frame) per 20ms frame */
+#define L_MDCT_HALF_OVLP_MAX (L_MDCT_OVLP_MAX/2) /* Size of the MDCT half overlap @ 48 kHz */
+#define L_MDCT_MIN_OVLP_MAX 60 /* Size of the MDCT minimal overlap @ 48 kHz - 1.25ms */
+#define L_MDCT_TRANS_OVLP_MAX NS2SA(48000, ACELP_TCX_TRANS_NS) /* Size of the ACELP->MDCT transition overlap - 1.25ms */
+
+#define L_NEXT_MAX_16k NS2SA(16000, ACELP_LOOK_NS) /* 140 */ /* maximum encoder lookahead at 16kHz */
+#define L_NEXT_MAX_32k NS2SA(32000, ACELP_LOOK_NS) /* 280 */ /* maximum encoder lookahead at 32kHz */
+#define L_PAST_MAX_32k 360 /* maximum encoder past samples at 32kHz */
+
+/*----------------------------------------------------------------------------------*
+ * ACELP core constants
+ *----------------------------------------------------------------------------------*/
+
+#define SAFETY_NET 0
+#define MOVING_AVERAGE 1
+#define AUTO_REGRESSIVE 2
+
+#define INT_FS_12k8 12800 /* internal sampling frequency */
+#define M 16 /* order of the LP filter @ 12.8kHz */
+#define L_FRAME 256 /* frame size at 12.8kHz */
+#define NB_SUBFR 4 /* number of subframes per frame */
+#define L_SUBFR (L_FRAME/NB_SUBFR) /* subframe size */
+
+#define L_INP_MEM (L_LOOK_16k + ((L_LP_16k - (NS2SA(INT_FS_16k, ACELP_LOOK_NS) + L_SUBFR16k/2)) - 3*L_SUBFR16k/2)) /* length of memory of input signal, given by the Look-Ahead + the past memory (max needed for the LP window at 16 kHz) */
+#define L_INP_12k8 (L_INP_MEM + L_FRAME) /* length of input signal buffer @12.8kHz */
+#define L_INP (L_INP_MEM + L_FRAME32k) /* length of input signal buffer @32kHz */
+
+#define L_EXC_MEM L_FRAME16k /* length of memory of excitation signal @16kHz */
+#define L_EXC_MEM_12k8 (PIT_MAX + L_INTERPOL) /* length of memory of excitation signal @12.8kHz */
+#define L_EXC_MEM_DEC (3*L_FRAME16k/2) /*Half-frame needed for PLC in case of TCX->ACELP*/
+#define L_EXC (L_EXC_MEM + L_FRAME16k + 1) /* length of encoder excitation signal buffer @16kHz*/
+#define L_EXC_DEC (L_EXC_MEM_DEC + L_FRAME16k + 1 + L_SUBFR) /* length of decoder excitation signal buffer @16kHz*/
+#define L_SYN_MEM NS2SA(48000,DELAY_CLDFB_NS) /* synthesis memory length, 1.25ms @ 48kHz */
+#define L_SYN (L_SYN_MEM + L_FRAME16k) /* length of synthesis signal buffer @16kHz */
+#define L_WSP_MEM (PIT_MAX + L_INTERPOL) /* length of memory for weighted input signal @12.8kHz*/
+#define L_WSP (L_WSP_MEM + L_FRAME + L_LOOK_12k8) /* length of weighted input signal buffer @12.8kHz*/
+
+#define OLD_SYNTH_SIZE_DEC (2*L_FRAME_MAX) /* decoder past synthesis; needed for LTP, PLC and rate switching*/
+#define OLD_SYNTH_INTERNAL_DEC (2*L_FRAME32k) /* decoder past synthesis @ internal sampling rate; needed for LTP, PLC and rate switching*/
+#define OLD_SYNTH_SIZE_ENC L_FRAME32k+L_FRAME32k/4 /* encoder synth memory */
+#define OLD_EXC_SIZE_DEC (3*L_FRAME_MAX/2+2*L_FIR_FER2) /*old excitation needed for decoder for PLC*/
+
+#define TILT_CODE 0.3f /* ACELP code preemphasis factor */
+
+#define L_SUBFR16k (L_FRAME16k/NB_SUBFR) /* subframe size at 16kHz */
+#define L_HALFR16k (2*L_SUBFR16k) /* half-frame size at 16kHz */
+
+#define L_INTERPOL2 16 /* Length of filter for interpolation */
+#define L_INTERPOL (L_INTERPOL2+1) /* Length of filter for interpolation */
+#define TILT_FAC 0.68f /* tilt factor (denominator) */
+#define M16k 20 /* order of the LP filter @ 16kHz */
+#define PIT_SHARP 0.85f /* pitch sharpening factor */
+#define PIT_UP_SAMP 4 /* upsampling factor for 1/4 interpolation filter */
+#define PIT_L_INTERPOL2 16
+#define PIT_FIR_SIZE2 (PIT_UP_SAMP*PIT_L_INTERPOL2+1)
+#define PIT_UP_SAMP6 6
+#define PIT_L_INTERPOL6_2 17
+#define PIT_FIR_SIZE6_2 (PIT_UP_SAMP6*PIT_L_INTERPOL6_2+1)
+#define E_MIN 0.0035f /* minimum allowable energy */
+#define STEP_DELTA 0.0625f /* quantization step for tilt compensation of gaussian cb. excitation */
+#define GAMMA_EV 0.92f /* weighting factor for core synthesis error weighting */
+#define FORMANT_SHARPENING_NOISE_THRESHOLD 21.0f /* lp_noise level above which formant sharpening is deactivated */
+#define BWD_N_BINS_MAX 13
+#define LP_NOISE_THRESH 20.f
+
+#define L_FILT_UP8k 24 /* Resampling - delay of filter for 8 kHz output signals (at 12.8 kHz sampling rate) */
+#define LEN_WIN_SSS 120
+#define L_FILT 12 /* Resampling - delay of the resampling low-pass filter @12.8kHz */
+#define L_FILT16k 15 /* Resampling - delay of filter for 16 kHz input signals (at 16kHz sampling rate) */
+#define L_FILT32k 30 /* Resampling - delay of filter for 32 kHz input signals (at 32kHz sampling rate) */
+#define L_FILT48k 45 /* Resampling - delay of filter for 48 kHz input signals (at 48kHz sampling rate) */
+#define L_FILT_UP16k 12 /* Resampling - delay of filter for 16 kHz output signals (at 12.8 kHz sampling rate) */
+#define L_FILT_UP32k 12 /* Resampling - delay of filter for 32 kHz output signals (at 12.8 kHz sampling rate) */
+#define L_FILT_UP48k 12 /* Resampling - delay of filter for 48 kHz output signals (at 12.8 kHz sampling rate) */
+#define L_FILT_MAX L_FILT48k /* Resampling - maximum length of all filters - for memories */
+#define RS_INV_FAC 0x8000 /* Resampling - flag needed in rom_com and modif_fs to allow pre-scaled and non pre-scaled filters */
+
+#define CLDFB_NO_CHANNELS_MAX 60 /* CLDFB resampling - max number of CLDFB channels */
+#define CLDFB_NO_COL_MAX 16 /* CLDFB resampling - max number of CLDFB col. */
+#define CLDFB_NO_COL_MAX_SWITCH 6 /* CLDFB resampling - max number of CLDFB col. for switching */
+#define CLDFB_NO_COL_MAX_SWITCH_BFI 8 /* CLDFB resampling - max number of CLDFB col. for switching, BFI */
+#define INV_CLDFB_BANDWIDTH (1.f/800.f)
+
+typedef enum
+{
+ CLDFB_ANALYSIS,
+ CLDFB_SYNTHESIS
+} CLDFB_TYPE;
+
+#define L_FFT 256 /* Spectral analysis - length of the FFT */
+#define LOG2_L_FFT 8 /* Spectral analysis - log2 of L_FFT */
+
+#define BIN (INT_FS_12k8/L_FFT)/* Spectral analysis - Width of one frequency bin in Hz */
+#define NB_BANDS 20 /* Spectral analysis - number of frequency bands */
+#define VOIC_BINS 74 /* Spectral analysis - max number of frequency bins considered as voiced (related to VOIC_BAND and L_FFT) */
+#define VOIC_BAND 17 /* Spectral analysis - number of critical bands considered as voiced (related to VOIC_BINS) */
+#define VOIC_BINS_8k 115 /* Spectral analysis - max number of frequency bins considered as voiced in NB (related to VOIC_BAND_8k and L_FFT) */
+#define VOIC_BAND_8k 17 /* Spectral analysis - number of critical bands considered as voiced in NB (related to VOIC_BINS_8k) */
+
+#define M_ALPHA 0.9f /* Multi-harm analysis - forgetting factor of LT correlation map */
+#define M_GAMMA 0.99f /* Multi-harm analysis - forgetting factor of active speech decision predictor */
+#define THR_CORR 56 /* Multi-harm analysis - starting threshold of multi-harm. correlation */
+
+#define L_LP 320 /* LP analysis - LP window size */
+#define L_LP_16k 400 /* LP analysis @16kHz - LP window size for 16kHz */
+#define L_LP_AMR_WB 384 /* LP analysis - windows size (only for AMR-WB IO mode) */
+#define GRID50_POINTS 51 /* LP analysis - half-number of points to evaluate Chebyshev polynomials used in the LP coefs. conversion */
+#define GRID40_POINTS 41 /* LP analysis - half-number of points to evaluate Chebyshev polynomials used in the LP coefs. conversion */
+#define GRID100_POINTS 100 /* LP analysis - number of points to evaluate Chebyshev polynomials */
+
+#define PIT_MIN 34 /* OL pitch analysis - Minimum pitch lag */
+#define PIT_MAX 231 /* OL pitch analysis - Maximum pitch lag */
+#define PIT_MIN_EXTEND 20 /* OL pitch analysis - Minimum pitch lag of extended range */
+#define PIT_MIN_DOUBLEEXTEND 17 /* OL pitch analysis - Minimum pitch lag of double-extended range */
+#define OPL_DECIM 2 /* OL pitch analysis - decimation factor */
+#define L_INTERPOL1 4 /* OL pitch analysis - interval to compute normalized correlation */
+#define FIR_SIZE1 (PIT_UP_SAMP*L_INTERPOL1+1) /* OL pitch analysis - total length of the 1/4 interpolation filter */
+
+#define PIT_MIN_SHORTER 29 /* OL pitch analysis - minimum for wider pitch */
+
+#define PIT_MIN_12k8 29 /* Minimum pitch lag with resolution 1/4 */
+#define PIT_FR2_12k8 121 /* Minimum pitch lag with resolution 1/2 */
+#define PIT_FR1_12k8 154 /* Minimum pitch lag with resolution 1 */
+#define PIT_MAX_12k8 231 /* Maximum pitch lag */
+#define PIT_FR1_8b_12k8 82 /* Minimum pitch lag with resolution 1 for low bit-rate pitch delay codings*/
+#define PIT_MIN_16k 36
+#define PIT_FR2_16k 36
+#define PIT_FR1_16k 165
+#define PIT_FR1_8b_16k 165
+#define PIT_MIN_25k6 58
+#define PIT_FR2_25k6 58
+#define PIT_FR1_25k6 164
+#define PIT_MAX_25k6 463
+#define PIT_FR1_8b_25k6 164
+#define PIT_MIN_32k 72
+#define PIT_FR2_32k 72
+#define PIT_FR1_32k 75
+#define PIT_MAX_32k 577
+#define PIT_FR1_8b_32k 75
+#define PIT_MAX_MAX PIT_MAX_32k
+
+#define PIT_FR1_8b 92 /* Pitch encoding - Minimum pitch lag with resolution 1 */
+#define PIT_FR2_9b 128 /* Pitch encoding - Minimum pitch lag with resolution 1/2 */
+#define PIT_FR1_9b 160 /* Pitch encoding - Minimum pitch lag with resolution 1 */
+#define PIT_FR1_EXTEND_8b 64 /* Pitch encoding - Minimum pitch lag with resolution 1 of extended range */
+#define PIT_FR2_EXTEND_9b 116 /* Pitch encoding - Minimum pitch lag with resolution 1/2 of extended range */
+#define PIT_FR1_EXTEND_9b 128 /* Pitch encoding - Minimum pitch lag with resolution 1 of extended range */
+#define PIT_FR1_DOUBLEEXTEND_8b 58 /* Pitch encoding - Minimum pitch lag with resolution 1 of double-extended range */
+#define PIT_FR2_DOUBLEEXTEND_9b 112 /* Pitch encoding - Minimum pitch lag with resolution 1/2 of double-extended range */
+#define PIT_FR1_DOUBLEEXTEND_9b 124 /* Pitch encoding - Minimum pitch lag with resolution 1 of double-extended range */
+
+#define LOW_PASS 0 /* LP filtering - flag for low-pass filtering of the excitation */
+#define FULL_BAND 1 /* LP filtering - flag for no low-pass filtering of the excitation */
+#define NORMAL_OPERATION 2 /* LP filtering - flag for selecting the best of the two above */
+
+#define NB_TRACK_FCB_2T 2 /* Algebraic codebook - number of tracks in algebraic fixed codebook search with 2 tracks */
+#define NB_POS_FCB_2T 32 /* Algebraic codebook - number of positions in algebraic fixed codebook search with 2 tracks */
+#define NB_TRACK_FCB_4T 4 /* Algebraic codebook - number of tracks in algebraic fixed codebook search with 4 tracks */
+#define NB_POS_FCB_4T 16 /* Algebraic codebook - number of positions in algebraic fixed codebook search with 4 tracks */
+#define NB_PULSE_MAX 36
+#define NPMAXPT ((NB_PULSE_MAX+NB_TRACK_FCB_4T-1)/NB_TRACK_FCB_4T)
+#define MAX_IDX_LEN 9
+
+#define GAIN_PRED_ORDER 4 /* Gain quantization - prediction order for gain quantizer (only for AMR-WB IO mode) */
+#define MEAN_ENER 30 /* Gain quantization - average innovation energy */
+
+#define DTX_HIST_SIZE 8 /* CNG & DTX - number of last signal frames used for CNG averaging */
+#define CNG_ISF_FACT 0.9f /* CNG & DTX - CNG spectral envelope smoothing factor */
+#define STEP_AMR_WB_SID 2.625f /* CNG & DTX - CNG energy quantization step */
+#define HO_HIST_SIZE 8 /* CNG & DTX - maximal number of hangover frames used for averaging */
+#define NUM_ENV_CNG 20
+#define BUF_L_NRG 0.7f /* CNG & DTX - lower threshold factor for hangover updates */
+#define BUF_H_NRG 1.03f /* CNG & DTX - higher threshold factor for hangover updates */
+
+#define BUF_DEC_RATE 25 /* CNG & DTX - buffer size decrease rate for active frames */
+#define STEP_SID 5.25f /* CNG & DTX - CNG energy quantization step */
+
+#define MIN_ACT_CNG_UPD 20 /* DTX - Minimum number of consecutive active frames for CNG mode update */
+#define FIXED_SID_RATE 8 /* DTX SID rate */
+
+#define TOTALNOISE_HIST_SIZE 4
+
+#define UNKNOWN_NOISE 0 /* unknown noisy type */
+#define SILENCE 1 /* speech with high SNR */
+#define CLDFBVAD_NB_ID 1
+#define CLDFBVAD_WB_ID 2
+#define CLDFBVAD_SWB_ID 3
+#define CLDFBVAD_FB_ID 4
+#define SP_CENTER_NUM 4 /* number of spectral centroid */
+#define TONA_NUM 3 /* number of tonal */
+#define PRE_SNR_NUM 32 /* number of snr to calculate average SNR of all sub-bands */
+#define POWER_NUM 56 /* number of energy of several frames*/
+#define PRE_SPEC_DIF_NUM 56 /* number of energy of several frames*/
+
+#define MAX_SUBBAND_NUM 12 /* max number of sub-band divided non-uniformly*/
+#define BG_ENG_NUM MAX_SUBBAND_NUM /* number of energy of sub-band divided non-uniformly*/
+#define MIN_AMP_ID 5
+#define MAX_AMP_ID 64
+#define SPEC_AMP_NUM (MAX_AMP_ID-MIN_AMP_ID+1)
+#define STABLE_NUM 4 /* number of time-domain stable rate*/
+#define SFM_NUM 3 /* number of spectral flatness */
+
+
+#define START_NG 5 /* Stationary noise UV modification */
+#define FULL_NG 10 /* Stationary noise UV modification */
+#define ISP_SMOOTHING_QUANT_A1 0.9f /* Stationary noise UV modification */
+
+#define FFT_15PONIT_WNK1 0.55901699f /* EDCT & EMDCT constants */
+#define FFT_15PONIT_WNK2 0.95105652f /* EDCT & EMDCT constants */
+#define FFT_15PONIT_WNK3 0.58778525f /* EDCT & EMDCT constants */
+#define FFT_15PONIT_WNK4 0.86602540f /* EDCT & EMDCT constants */
+#define FFT_15PONIT_WNK5 0.25000000f /* EDCT & EMDCT constants */
+
+#define FEC_BITS_CLS 2 /* FEC - number of bits for clas information */
+#define FEC_BITS_ENR 5 /* FEC - number of bits for energy information */
+#define FEC_ENR_STEP (96.0f/(1<= use MA-predictor */
+
+#define NC16k (M16k/2)
+#define NO_ITER 4 /* number of iterations for tracking the root */
+#define SPC 0.0234952f
+#define SPC_plus SPC * 1.001f
+#define ALPHA_SQ ((0.5f / PI2) * (0.5f / PI2))
+
+#define NC M/2
+#define LSF_GAP 50.0f
+#define LSF_BITS_CNG 29
+
+#define MU_MA (1.0f/3.0f) /* original prediction factor (only for AMR-WB IO mode) */
+#define ISF_GAP 50 /* Minimum ISF separation for end-frame ISFs (only in AMR-WB IO mode) */
+#define LSF_GAP_MID 80.0f /* Minimum LSF separation for mid-frame LSFs */
+#define MODE1_LSF_GAP 70.0f /* Minimum LSF separation for end-frame ISFs */
+#define PREFERSFNET 1.05
+#define SFNETLOWLIMIT_WB 35000 /* new sampling rate dependent thresholds used in LSF codebook decision logic, WB case */
+#define SFNETLOWLIMIT_NB 38000 /* new sampling rate dependent thresholds used in LSF codebook decision logic, NB case */
+#define LSFMBEST 2 /* number of survivors from one stage to another */
+#define STREAKLEN 3 /* Allow this many predictive frames, before starting limiting */
+#define STREAKMULT 0.8f /* Exponential limiting multiplier */
+
+#define LSFMBEST_MAX 16
+
+#define TCXLPC_NUMSTAGES 3
+#define TCXLPC_NUMBITS 13
+#define TCXLPC_IND_NUMSTAGES 1
+#define TCXLPC_IND_NUMBITS 2
+#define TCXLPC_LSF_GAP 80.0f
+
+#define MAX_VQ_STAGES 4
+#define MAX_VQ_STAGES_USED 9 /* this is the maximum number of stages currently used and changing this will affect the memory allocated
+ MAX_VQ_STAGES is also used as offset for addressing some arrays, so this should NOT be changed*/
+#define MIDLSF_NBITS 5
+#define ENDLSF_NBITS 31
+
+#define LEN_INDICE 15
+#define LATTICE_DIM 8
+#define NO_LEADERS 49
+#define MAX_NO_BR_LVQ 28
+#define MAX_NO_SCALES 3
+#define MAX_NO_VALS 4
+#define WB_LIMIT_LSF 6350
+#define CNG_LVQ_MODES 16
+
+#define MAX_NO_MODES 128
+#define START_CNG 112
+#define MAX_NO_MODES_p 145
+#define NO_CODING_MODES 6
+#define LVQ_COD_MODES 18
+
+/* BC-TCVQ */
+#define N_STAGE_VQ 8
+#define N_DIM 2
+#define NUM_SUBSET 8
+#define OP_LOOP_THR_HVO 3784536.3f /* 80% : Open-loop Threshold */
+#define NUM_STATE 16 /* BC-TCQ - Number of state of the Trellis */
+#define N_STAGE 16 /* BC-TCQ - Smaple number in a frame */
+
+#define SIZE_BK1 256
+#define SIZE_BK2 256
+#define SIZE_BK21 64
+#define SIZE_BK22 128
+#define SIZE_BK23 128
+#define SIZE_BK24 32
+#define SIZE_BK25 32
+#define SIZE_BK21_36b 128
+#define SIZE_BK22_36b 128
+#define SIZE_BK23_36b 64
+
+#define NB_QUA_GAIN5B 32 /* Number of quantization level */
+#define NB_QUA_GAIN6B 64 /* Number of quantization level */
+#define NB_QUA_GAIN7B 128 /* Number of quantization level */
+
+/*----------------------------------------------------------------------------------*
+ * Transient detection
+ *----------------------------------------------------------------------------------*/
+
+#define NSUBBLOCKS 8 /* Number of subblocks per frame, one transient per a sub-block can be found */
+#define MAX_TD_DELAY 2*NSUBBLOCKS /* Maximum allowed delay (in number of subblocks) of the transient detection, affects required memory */
+
+#define NO_TCX 0
+#define TCX_20 1
+#define TCX_10 2
+#define TCX_5 3
+
+#define TRANSITION_OVERLAP (-2)
+#define RECTANGULAR_OVERLAP (-1)
+#define FULL_OVERLAP 0
+#define NOT_SUPPORTED 1
+#define MIN_OVERLAP 2
+#define HALF_OVERLAP 3
+#define ALDO_WINDOW 4
+
+#define SWITCH_OVERLAP_8k 15 /* == NS2SA(8000, SWITCH_GAP_LENGTH_NS) - NS2SA(8000, 10000000.0f - N_ZERO_MDCT_NS) */
+#define SWITCH_GAP_LENGTH_8k 50
+
+/*----------------------------------------------------------------------------------*
+ * FEC constants
+ *----------------------------------------------------------------------------------*/
+
+#define UNVOICED_CLAS 0 /* Unvoiced, silence, noise, voiced offset */
+#define UNVOICED_TRANSITION 1 /* Transition from unvoiced to voiced components - possible onset, but too small */
+#define VOICED_TRANSITION 2 /* Transition from voiced - still voiced, but with very weak voiced characteristics */
+#define VOICED_CLAS 3 /* Voiced frame, previous frame was also voiced or ONSET */
+#define ONSET 4 /* Voiced onset sufficiently well built to follow with a voiced concealments */
+#define SIN_ONSET 5 /* Artificial harmonic+noise onset (used only in decoder) */
+#define INACTIVE_CLAS 6 /* Inactive frame (used only in decoder) */
+#define AUDIO_CLAS 7 /* Audio frame (used only in AMR-WB IO mode) */
+
+#define BETA_FEC 0.75f /* FEC - weighting factor for LSF estimation in FER */
+#define STAB_FAC_LIMIT 0.25f /* FEC - limit at which safety net is forced for next frame */
+
+#define MODE1_L_FIR_FER 5 /* FEC - impulse response length for low- and high-pass filters in FEC */
+#define L_FIR_FER 3 /* impulse response length for low- & high-pass filters in FER concealment */
+#define L_FIR_FER2 11 /* new filter tuning: 11*/
+#define MAX_UPD_CNT 5 /* FEC - maximum number of frames since last pitch update */
+#define ALPHA_S 0.6f /* FEC - damping factor for SIN_ONSET frames */
+#define ALPHA_V 1.0f /* FEC - damping factor for VOICED_CLAS frames */
+#define ALPHA_VT 0.4f /* FEC - damping factor for VOICED_TRANSITION frames */
+#define ALPHA_UT 0.8f /* FEC - damping factor for UNVOICED_TRANSITION frames */
+#define ALPHA_U 0.4f /* FEC - damping factor for UNVOICED_CLAS frames */
+#define ALPHA_UU 1.0f /* FEC - damping factor for UNVOICED_CLAS frames */
+
+#define AGC 0.98f
+
+#define PLC_MIN_CNG_LEV 0.01f /* minimum background level */
+#define PLC_MIN_STAT_BUFF_SIZE 50 /* buffer size for minimum statistics */
+#define PLC_MIN_CNG_LEV 0.01f
+#define G_LPC_RECOVERY_BITS 1
+
+/*----------------------------------------------------------------------------------*
+ * Transition mode (TC) constants
+ *----------------------------------------------------------------------------------*/
+
+/* Conversion of tc_subfr to index */
+#define TC_SUBFR2IDX(x) ( x == 0 ? 0 : \
+ x == 1 ? 0 : \
+ x == 2 ? 1 : \
+ x == 3 ? 2 : \
+ x == 4 ? 3 : \
+ x == 64 ? 4 : \
+ x == 128 ? 5 : \
+ x == 192 ? 6 : \
+ x == 256 ? 7 : 0 )
+
+#define TC_SUBFR2IDX_16KHZ(x) ( x == 0 ? 0 : \
+ x == 64 ? 1 : \
+ x == 128 ? 2 : \
+ x == 192 ? 3 : \
+ x == 256 ? 4 : 0 )
+
+#define L_IMPULSE 17 /* TC - length of one prototype impulse */
+#define L_IMPULSE2 8 /* TC - half-length of one prototype impulse == floor(L_IMPULSE/2) */
+#define NUM_IMPULSE 8 /* TC - number of prototype impulses */
+#define N_GAIN_CODE_TC 8 /* TC - number of levels for gain_code quantization for subrames without glot. impulse(s) - */
+#define N_GAIN_TC 8 /* TC - number of levels for gain_trans quantization */
+/* TC - attention: DO NOT CHANGE the following constants - needed for correct bit-allocations */
+#define TC_0_0 1 /* TC - subframe ID for TC: first glottal impulse in the 1st subframe, second in the 1st subframe */
+#define TC_0_64 2 /* TC - subframe ID for TC: first glottal impulse in the 1st subframe, second in the 2nd subframe */
+#define TC_0_128 3 /* TC - subframe ID for TC: first glottal impulse in the 1st subframe, second in the 3rd subframe */
+#define TC_0_192 4 /* TC - subframe ID for TC: first glottal impulse in the 1st subframe, second in the 4th subframe */
+
+/*----------------------------------------------------------------------------------*
+ * AVQ constants
+ *----------------------------------------------------------------------------------*/
+
+#define NB_LDQ3 9 /* RE8 constants */
+#define NB_SPHERE 32
+#define NB_LEADER 36
+#define NB_LDQ4 27
+#define FAC_LOG2 3.321928095f
+
+#define NSV_MAX 34 /* maximal number of sub-vectors used by the AVQ */
+
+/*----------------------------------------------------------------------------------*
+ * Arithmetic coder
+ *----------------------------------------------------------------------------------*/
+
+#define A_THRES_SHIFT 2
+#define A_THRES (1<= END_FREQ_BWE_FULL/(8*50) + NSV_OVERLAP ! */
+#define N_BANDS_BWE_HR 4 /* number of frequency bands in non-transient frame */
+#define N_BANDS_TRANS_BWE_HR 2 /* number of frequency bands in transient frame */
+#define END_FREQ_BWE 14400 /* maximum frequency coded by AVQ */
+#define END_FREQ_BWE_FULL 16000 /* maximum frequency coded by HR SWB BWE */
+#define END_FREQ_BWE_FULL_FB 20000 /* maximum frequency coded by HR FB BWE */
+
+#define NBITS_GLOB_GAIN_BWE_HR 5 /* number of bits of the global gain quantizer */
+#define MIN_GLOB_GAIN_BWE_HR 3 /* minimum value of the global gain quantizer */
+#define MAX_GLOB_GAIN_BWE_HR 500 /* maximum value of the global gain quantizer */
+
+#define NBITS_ENVELOPE_BWE_HR1 6 /* number of bits for envelope VQ - first two subbands in non-transient frame */
+#define NBITS_ENVELOPE_BWE_HR2 5 /* number of bits for envelope VQ - second two subbands in non-transient frame */
+#define NBITS_ENVELOPE_BWE_HR_TR 4 /* number of bits for envelope VQ - two subbands in transient frame */
+#define NUM_ENVLOPE_CODE_HR1 64 /* dimension of envelope VQ - first two subbands in non-transient frame */
+#define NUM_ENVLOPE_CODE_HR2 32 /* dimension of envelope VQ - second two subbands in non-transient frame */
+#define NUM_ENVLOPE_CODE_HR_TR 16 /* dimension of envelope VQ - two subbands in transient frame */
+#define NUM_ENVLOPE_CODE_HR_TR2 8 /* dimension of envelope VQ - two subbands in transient frame */
+
+#define NUM_NONTRANS_START_FREQ_COEF (L_FRAME32k/2 - NSV_OVERLAP*WIDTH_BAND) /* start frequency coefficient (==7.6kHz) in non-transient frame */
+#define NUM_NONTRANS_END_FREQ_COEF (L_FRAME32k*END_FREQ_BWE/END_FREQ_BWE_FULL) /* end frequency coefficient (==14.4kHz) in non-transient frame */
+#define NUM_TRANS_START_FREQ_COEF (NUM_NONTRANS_START_FREQ_COEF/NUM_TIME_SWITCHING_BLOCKS) /* start frequency coefficient (==7.6kHz) in transient frame */
+#define NUM_TRANS_END_FREQ_COEF (NUM_NONTRANS_END_FREQ_COEF/NUM_TIME_SWITCHING_BLOCKS) /* end frequency coefficient (==14.4kHz) in transient frame */
+#define NUM_TRANS_END_FREQ_COEF_EFF 140
+#define WIDTH_NONTRANS_FREQ_COEF ((NUM_NONTRANS_END_FREQ_COEF - NUM_NONTRANS_START_FREQ_COEF)/N_BANDS_BWE_HR) /* number of coefficients per band in non-transient frame */
+#define WIDTH_TRANS_FREQ_COEF ((NUM_TRANS_END_FREQ_COEF - NUM_TRANS_START_FREQ_COEF)/N_BANDS_TRANS_BWE_HR) /* number of coefficients per band in transient frame */
+
+#define NBITS_THRESH_BWE_HR 400 /* BWE HR number of bits threshold */
+
+#define NBITS_HF_GAIN_BWE_HR 2 /* number of bits for HF (noncoded) energy estimation */
+#define BWE_HR_TRANS_EN_LIMIT1 0.1f /* HF (noncoded) energy equalization limit 1, transient frames */
+#define BWE_HR_TRANS_EN_LIMIT2 0.3f /* HF (noncoded) energy equalization limit 2, transient frames */
+#define BWE_HR_TRANS_EN_LIMIT3 0.5f /* HF (noncoded) energy equalization limit 3, transient frames */
+#define BWE_HR_NONTRANS_EN_LIMIT1 0.5f /* HF (noncoded) energy equalization limit 1, non-transient frames */
+#define BWE_HR_NONTRANS_EN_LIMIT2 1.2f /* HF (noncoded) energy equalization limit 2, non-transient frames */
+#define BWE_HR_NONTRANS_EN_LIMIT3 0.8f /* HF (noncoded) energy equalization limit 3, non-transient frames */
+
+/*----------------------------------------------------------------------------------*
+ * FD CNG
+ *----------------------------------------------------------------------------------*/
+
+#define OUTMAX_INV 0.000030517578125f /* 1/2^15 */
+#define OUTMAX_SQ 1073741824.f /* 2^30 */
+#define OUTMAX_SQ_INV 0.00000000093132257461547852f /* 1/2^30 */
+#define DELTA (1e-20f)
+
+#define CLDFB_SCALING (1.5f)
+
+#define FFTLEN 640
+#define FFTLEN2 (FFTLEN/2)
+#define CORECLDFBLEN 20
+#define TOTCLDFBLEN 40
+#define FFTCLDFBLEN (FFTLEN2+TOTCLDFBLEN-CORECLDFBLEN)
+#define PERIODOGLEN (FFTLEN2-2)
+#define NPART 24
+#define NPARTCLDFB 10
+#define NPART_SHAPING 62
+
+#define MSSUBFRLEN 12
+#define MSNUMSUBFR 6
+#define MSBUFLEN 5
+#define MSALPHACORALPHA 0.7f
+#define MSALPHACORMAX 0.3f
+#define MSALPHAMAX 0.96f
+#define MSALPHAHATMIN 0.05f /* It is used for all bands except the first one to get a stable bass */
+#define MSQEQINVMAX (1.f/5.f)
+#define MSAV 2.12f
+#define MSBETAMAX 0.8f
+#define MSSNREXP (-0.02f/0.064f)
+
+#define NB_LAST_BAND_SCALE 0.8f
+#define SWB_13k2_LAST_BAND_SCALE 0.8f
+
+#define CNG_LOG_SCALING 512.f /*2^9*/
+
+#define M_MAX 32
+#define N_GAIN_MIN 4
+#define N_GAIN_MAX 17
+
+#define CHEAP_NORM_SIZE 161
+
+#define CNA_MAX_BRATE ACELP_13k20
+
+/*----------------------------------------------------------------------------------*
+ * Bass post-filter constants
+ *----------------------------------------------------------------------------------*/
+
+#define NBPSF_PIT_MAX (PIT16k_MAX+1) /* maximum pitch value for bass post-filter */
+#define L_TRACK_HIST 10
+
+/*----------------------------------------------------------------------------------*
+ * NB post-filter constants
+ *----------------------------------------------------------------------------------*/
+
+#define THRESCRIT 0.5f /* NB post-filter - threshold LT pst switch off */
+#define AGC_FAC 0.9875f /* NB post-filter - gain adjustment factor */
+#define AGC_FAC1 (1.0f-AGC_FAC) /* NB post-filter - gain adjustment factor complement */
+#define LONG_H_ST 20 /* NB post-filter - impulse response length */
+#define POST_G1 0.75f /* NB post-filter - denominator weighting factor 12kbps */
+#define POST_G2 0.7f /* NB post-filter - numerator weighting factor 12kbps */
+#define GAMMA1_PST 0.7f /* denominator weighting factor */
+#define GAMMA2_PST 0.55f /* numerator weighting factor */
+#define GAMMA3_PLUS 0.2f /* NB post-filter - tilt weighting factor when k1>0 */
+#define GAMMA3_MINUS 0.9f /* NB post-filter - tilt weighting factor when k1<0 */
+#define F_UP_PST 8 /* NB post-filter - resolution for fractionnal delay */
+#define LH2_S 4 /* NB post-filter - length of INT16 interp. subfilters */
+#define LH2_L 16 /* NB post-filter - length of long interp. subfilters */
+#define MIN_GPLT (1.0f/1.5f) /* NB post-filter - LT gain minimum */
+#define LH_UP_S (LH2_S/2)
+#define LH_UP_L (LH2_L/2)
+#define LH2_L_P1 (LH2_L + 1)
+#define DECMEM_RES2 (PIT16k_MAX + 2 + LH_UP_L)
+#define SIZ_RES2 (DECMEM_RES2 + L_SUBFR)
+#define SIZ_Y_UP ((F_UP_PST-1) * (L_SUBFR+1))
+#define SIZ_TAB_HUP_L ((F_UP_PST-1) * LH2_L)
+#define SIZ_TAB_HUP_S ((F_UP_PST-1) * LH2_S)
+#define POST_G1_MIN 0.65f
+#define POST_G2_MIN 0.55f
+#define POST_G1_NOIS 0.15f
+#define POST_G2_NOIS 0.10f
+#define BG1 (-0.01f)
+#define BG2 (-0.05f)
+#define CG1 0.9f
+#define CG2 1.45f
+#define C_LP_NOISE (0.1f/4.0f)
+#define K_LP_NOISE 15.0f
+#define LP_NOISE_THR 25.0f
+
+/*----------------------------------------------------------------------------------*
+ * Stability estimation
+ *----------------------------------------------------------------------------------*/
+
+#define NB_BFI_THR 2 /* threshold for counter of last bad frames */
+#define MAX_LT 40
+#define INV_MAX_LT (1.0f/MAX_LT)
+
+#define TH_0_MIN 2.5f
+#define TH_1_MIN 1.875f
+#define TH_2_MIN 1.5625f
+#define TH_3_MIN 1.3125f
+
+/*----------------------------------------------------------------------------------*
+ * Speech/music classifier constants
+ *----------------------------------------------------------------------------------*/
+
+#define N_FEATURES 12 /* number of features */
+#define N_MIXTURES 6 /* number of mixtures */
+#define M_LSP_SPMUS 6 /* number of LSPs used in speech/music classifier */
+#define NB_BANDS_SPMUS 15
+#define START_BAND_SPMUS 2
+#define N_OLD_BIN_E 42 /* == (L_FFT/2-2)/3 */
+
+#define LOWEST_FBIN 3 /* lowest frequency bin for feature vector preparation */
+#define HIGHEST_FBIN 70 /* highest frequency bin for feature vector preparation */
+#define HANG_LEN_INIT 8 /* number of frames for hang-over (causes delay of decision) */
+#define HANG_LEN 8
+#define BUF_LEN 60
+#define L_OVR 8
+
+/*----------------------------------------------------------------------------------*
+ * LD music post-filter constants
+ *----------------------------------------------------------------------------------*/
+
+#define TH_0_MIN2 1.875f
+#define TH_1_MIN2 1.25f
+#define TH_2_MIN2 0.9375f
+#define TH_3_MIN2 0.625f
+
+#define DCT_L_POST 640
+#define OFFSET2 192
+
+#define VOIC_BINS_HR 640
+#define BIN_16kdct (6400.0f/DCT_L_POST)
+#define NB_LIMIT_BAND 16
+#define MBANDS_GN_LD 20 /* number of bands for gain coding in the postfilter */
+
+/*----------------------------------------------------------------------------------*
+ * AC mode (GSC) constants
+ *----------------------------------------------------------------------------------*/
+
+#define NOISE_LEVEL_SP0 8
+#define NOISE_LEVEL_SP1a 9
+#define NOISE_LEVEL_SP1 10
+#define NOISE_LEVEL_SP2 12
+#define NOISE_LEVEL_SP3 14
+
+#define MAX_DYNAMIC 82
+#define MIN_DYNAMIC 50
+#define DYNAMIC_RANGE (MAX_DYNAMIC-MIN_DYNAMIC)
+#define MAX_GSC_NF_BITS 3
+#define GSC_NF_STEPS (1 << MAX_GSC_NF_BITS)
+
+#define CRIT_NOIS_BAND 23
+
+#define SSF 32 /* Sub-subframe length for energy estimation in UC decision */
+#define NB_SSF (L_FRAME / SSF) /* number of sub-subframes per frame */
+
+#define MBANDS_GN 16 /* Number of band for gain coding in GSC */
+#define BAND1k2 3
+
+#define MBANDS_LOC (MBANDS_GN-1)
+#define BIN_SIZE 25.0f
+#define SWNB_SUBFR 1
+
+#define VAR_COR_LEN 10
+
+#define CFREQ_BITRATE ACELP_11k60
+
+#define LT_UV_THR 100
+#define LT_UV_THRMID 70
+
+#define PIT_EXC_L_SUBFR L_FRAME
+#define LOCAL_CT VOICED
+
+/*----------------------------------------------------------------------------------*
+ * Core switching constants
+ *----------------------------------------------------------------------------------*/
+
+#define SWITCH_MAX_GAP 360 /* 6.25 + 1.25 of filter mem max == NS2SA(48000, SWITCH_GAP_LENGTH_NS+DELAY_CLDFB_NS) */
+
+/*----------------------------------------------------------------------------------*
+ * HQ core constants
+ *----------------------------------------------------------------------------------*/
+
+#define HQ_NORMAL 0
+#define HQ_TRANSIENT 1
+#define HQ_HARMONIC 2
+#define HQ_HVQ 3
+#define HQ_GEN_SWB 4
+#define HQ_GEN_FB 5
+
+#define PREECHO_SMOOTH_LEN 20
+#define INV_PREECHO_SMOOTH_LENP1 (1 / (PREECHO_SMOOTH_LEN + 1.0));
+
+#define MAX16B 32767
+#define MIN16B (-32768)
+
+#define EPSILON 0.000000000000001f
+
+#define MAX_SEGMENT_LENGTH 480
+#define NUM_TIME_SWITCHING_BLOCKS 4
+#define NUM_MAP_BANDS 20
+#define NUM_MAP_BANDS_HQ_24k4 17
+#define NUM_MAP_BANDS_HQ_32k 18
+#define FREQ_LENGTH 800
+
+#define STOP_BAND 800
+
+#define SFM_G1 16
+#define SFM_G1G2 24
+#define SFM_N_NB 18
+#define SFM_N_WB 26
+#define SFM_N_STA_8k 27
+#define SFM_N_STA_10k 30
+#define SFM_N_ENV_STAB SFM_N_STA_8k /* Number of bands for env_stab stability measure */
+#define SFM_N_ENV_STAB_WB SFM_N_WB /* Number of bands for env_stab stability measure used in HQPLC decision for WB signals */
+#define SFM_N_HARMONIC 39
+#define SFM_N 36
+
+#define L_HQ_WB_BWE 20 /* == band_end_wb[SFM_N_WB-1] - (band_start_wb[SFM_N_WB-1]+12) */
+#define N_INTL_GRP_16 2 /* Number of interleaving band groups at 16kHz samplerate */
+#define N_INTL_GRP_32 2 /* Number of interleaving band groups at 32kHz samplerate */
+#define N_INTL_GRP_48 3 /* Number of interleaving band groups at 48kHz samplerate */
+#define SFM_N_SWB 39
+#define SFM_N_HARM 31
+#define SFM_N_HARM_FB 33
+#define NB_SFM 44
+#define NB_SFM_MAX 58
+#define WID_G1 8
+#define WID_G2 16
+#define WID_G3 24
+#define WID_GX 32
+#define NUMC_N 544
+#define HQ_MAX_BAND_LEN 96 /* Largest bandwidth in HQ mode (band_len_harm[32]) */
+#define HVQ_PVQ_BUF_LEN (HVQ_PVQ_COEFS*(MAX_PVQ_BANDS-1) + HQ_MAX_BAND_LEN) /* 24*7+96 = 216 */
+
+#define QBIT_MAX2 9
+
+#define FLAGN_BITS 1
+#define GAIN0_BITS 5
+#define GAINI_BITS 5
+
+#define FLAGS_BITS 2
+#define FLAGS_BITS_FB 3
+#define NORM0_BITS 5
+#define NORMI_BITS 5
+#define NUMNRMIBITS_SWB_STA_8k 5*(SFM_N_STA_8k-1)
+#define NUMNRMIBITS_SWB_STA_10k 5*(SFM_N_STA_10k-1)
+#define NUMNRMIBITS_SWB_HARMONIC 185
+#define NUMNRMIBITS_SWB 190
+#define NUMNRMIBITS 215
+#define NUMNRMIBITS_WB 125
+
+#define NOHUFCODE 0
+#define HUFCODE 1
+#define HUFF_THR 10
+#define NOSUPERPOSITION 40
+
+#define MAXVALUEOFFIRSTGAIN 2.5f
+#define MINVALUEOFFIRSTGAIN -2.5f
+#define NOOFGAINBITS1 6
+
+#define AUDIODELAYBITS 6
+#define DELTAOFFIRSTGAIN (float)(MAXVALUEOFFIRSTGAIN - MINVALUEOFFIRSTGAIN) / (float)((1 << NOOFGAINBITS1) - 1)
+
+#define MAX_D1M_16k ((L_FRAME16k>>1) - NS2SA(16000,SWITCH_GAP_LENGTH_NS) - 16)
+#define MAX_D1M_12k8 ((L_FRAME16k>>1) - NS2SA(16000,SWITCH_GAP_LENGTH_NS) - 20)
+
+#define MAX_P_ATT 40 /* Maximum number of pulses for gain attenuation factor */
+#define NB_G 4 /* Number of band groups */
+#define MAX_GAIN_BITS 5 /* Maximum number of gain bits */
+
+#define ENV_ADJ_START 6 /* Number of consecutive bands for which the attenuation is maximum */
+#define ENV_ADJ_INCL 5 /* Inclination for mapping between attenuation region width and attenuation limit */
+
+#define ENV_SMOOTH_FAC 0.1f /* Smoothing factor for envelope stability measure */
+#define L_STAB_TBL 10 /* Number of elements in stability transition table */
+#define M_STAB_TBL_FX ((Word16)21068) /* Q13, 2.571756 */
+#define D_STAB_TBL_FX ((Word16) 845) /* Q13 0.1013138 */
+#define HALF_D_STAB_TBL_FX ((Word16) 422) /* Q13 0.1013138/2.0 */
+#define NUM_ENV_STAB_PLC_STATES 2 /* Number of states of markov model */
+
+#define ATT_LIM_HANGOVER 150 /* Number of hangover frames for disabling stability dependent attenuation */
+#define DELTA_TH 5.0f /* Delta energy threshold for transient detection for envelope stability */
+#define ENERGY_TH 100.0f /* Energy threshold for transient detection */
+#define ENERGY_LT_BETA 0.93f /* Smoothing factor for long-term energy measure */
+
+#define START_EXC 60
+#define L_HARMONIC_EXC 202
+
+#define HQ_GENERIC_OFFSET 2
+#define HQ_GENERIC_END_FREQ 560
+#define HQ_GENERIC_END_FREQ_14P2KHZ 568
+#define HQ_GENERIC_END_FREQ_16P0KHZ 640
+
+#define HQ_GENERIC_FOFFSET_24K4 80
+#define HQ_GENERIC_FOFFSET_32K 144
+#define HQ_GENERIC_SWB_NBITS 31
+#define HQ_GENERIC_SWB_NBITS2 30
+#define HQ_GENERIC_FB_NBITS 5
+
+#define HQ_GENERIC_ST_FREQ 224
+#define HQ_GENERIC_LOW0 80
+#define HQ_GENERIC_HIGH0 240
+#define HQ_GENERIC_HIGH1 368
+#define HQ_GENERIC_HIGH2 496
+#define HQ_GENERIC_LEN0 128
+#define HQ_GENERIC_NVQIDX 6
+
+#define HQ_GENERIC_EXC0 0
+#define HQ_GENERIC_EXC1 1
+#define HQ_GENERIC_SP_EXC 2
+
+#define LF_EMP_FAC 1.2f
+
+#define DIM_FB 3
+#define HQ_FB_FENV SWB_FENV + DIM_FB
+#define N_CB_FB 32
+
+#define HVQ_THRES_BIN_24k 224
+#define HVQ_THRES_SFM_24k 22
+#define HVQ_THRES_BIN_32k 320
+#define HVQ_THRES_SFM_32k 25
+#define HVQ_MIN_PEAKS 2
+#define HVQ_MAX_PEAKS_32k 23
+#define HVQ_MAX_PEAKS_24k 17
+#define HVQ_MAX_PEAKS_24k_CLAS 20 /* Limit for HVQ mode */
+#define HVQ_MAX_PEAKS HVQ_MAX_PEAKS_32k + 1
+#define HVQ_NUM_SFM_24k (SFM_N_HARMONIC - 1 - HVQ_THRES_SFM_24k)
+#define HVQ_NUM_SFM_32k (SFM_N_HARMONIC - 1 - HVQ_THRES_SFM_32k)
+#define HVQ_E_PEAK_SMOOTH_FAC (0.3f)
+
+#define HVQ_MAX_RATE 32000
+
+#define NUMNRMIBITS_SWB_HVQ_24k 35
+#define NUMNRMIBITS_SWB_HVQ_32k 25
+
+#define MAX_PVQ_BANDS 8
+#define HVQ_MAX_PVQ_WORDS ((HVQ_MAX_RATE/50)/16 + MAX_PVQ_BANDS)
+#define HVQ_MAX_POS_WORDS 40
+#define HVQ_PVQ_COEFS 24
+#define HVQ_BAND_MIN_PULSES 2
+#define HVQ_BAND_MAX_BITS_24k 80
+#define HVQ_BAND_MAX_BITS_32k 95
+#define HVQ_NEW_BAND_BIT_THR 30
+
+#define HVQ_NF_GROUPS 2
+#define HVQ_NF_WEIGHT1 0.9578f /* HVQ Classifier - Noise floor estimate weight 1 */
+#define HVQ_NF_WEIGHT2 0.6472f /* HVQ Classifier - Noise floor estimate weight 2 */
+#define HVQ_PE_WEIGHT1 0.42237f /* HVQ Classifier - Peak envelope estimate weight 1 */
+#define HVQ_PE_WEIGHT2 0.80285f /* HVQ Classifier - Peak envelope estimate weight 2 */
+#define HVQ_THR_POW 0.88f /* HVQ Classifier power factor for threshold calc */
+#define HVQ_SHARP_THRES 9 /* HVQ Classifier - Sharpness threshold */
+
+#define HVQ_PA_FAC 0.7071f /* HVQ Classifier peak allocation factor */
+#define HVQ_PA_PEAKS_SHARP1 9 /* HVQ Classifier - Maximum number of peaks for band with high sharpness */
+#define HVQ_PA_PEAKS_SHARP2 3 /* HVQ Classifier - Maximum number of peaks for band with medium sharpness */
+#define HVQ_PA_PEAKS_SHARP3 2 /* HVQ Classifier - Maximum number of peaks for band with low sharpness */
+#define HVQ_PA_SHARP_THRES2 16.0f /* HVQ Classifier - Sharpness threshold for band with medium sharpness */
+#define HVQ_PA_SHARP_THRES3 12.0f /* HVQ Classifier - Sharpness threshold for band with low sharpness */
+
+#define HVQ_BW 32 /* HVQ Classifier subband bandwidth */
+#define HVQ_NSUB_32k 10
+#define HVQ_NSUB_24k 7 /* HVQ Classifier number of subbands */
+
+#define HVQ_BWE_NOISE_BANDS 2 /* Number of BWE noise bands */
+#define HVQ_BWE_WEIGHT1 0.95f
+#define HVQ_BWE_WEIGHT2 0.2f
+#define HVQ_NFPE_FACTOR 6.4f
+#define HVQ_LB_NFPE_FACTOR 3.2f
+
+#define HVQ_VQ_DIM 5 /* HVQ peak VQ dimension */
+#define HVQ_PVQ_GAIN_BITS 5 /* Number of bits to encode PVQ gains in HVQ */
+#define HVQ_NUM_CLASS 4 /* Number of codebook classes */
+#define HVQ_CB_SIZE 256
+
+#define NUM_PG_HUFFLEN 9 /* Number of Huffman codewords for peak gains */
+#define MAX_PG_HUFFLEN 12 /* Length of the longest codeword for peak gain Huffman coding */
+
+#define HVQ_CP_HUFF_OFFSET 3 /* HVQ Code Pos - Delta offset */
+#define HVQ_CP_HUFF_MAX 51 /* HVQ Code Pos - Maximum delta for huffman coding */
+#define HVQ_CP_HUFF_MAX_CODE 13 /* HVQ Code Pos - Size of largest code word */
+#define HVQ_CP_HUFF_NUM_LEN 11 /* HVQ Code Pos - Number of different huffman lengths */
+#define HVQ_CP_L2_MAX 64 /* HVQ Code Pos - Layer 2 maximum size */
+#define HVQ_CP_L1_LEN 5 /* HVQ Code Pos - Layer 1 block size */
+#define HVQ_CP_MAP_LEN 8 /* HVQ Code Pos - Mapping table size */
+#define HVQ_CP_MAP_IDX_LEN 3 /* HVQ Code Pos - Mapping index size */
+#define HVQ_CP_DELTA 0 /* HVQ Code Pos - Use Delta coding */
+#define HVQ_CP_SPARSE 1 /* HVQ Code Pos - Use Sparse coding */
+
+#define MAX_SPLITS 10 /* Maximum number of PVQ band splits */
+#define QUANTAQ3OFFSET 1
+enum QuantaMode { NEAREST = 0, CONS };
+#define DS_INDEX_LINEAR_END 21
+#define PYR_OFFSET 1
+#define RCF_INIT_SHIFT 14
+#define THR_ADD_SPLIT 7 /* Threshold for using additional split */
+#define PVQ_MAX_BAND_SIZE 64 /* Maxiumum supported band size for PVQ search */
+#define MIN_BAND_SIZE 1 /* Minimum supported band size for PVQ search */
+#define RC_BITS_RESERVED 1
+#define MAX_PVQ_BITS_PER_COEFFICIENT 80 /* Maximum bits per coefficient allocated per PVQ band. Q3. */
+#define MAX_SRT_LEN NB_SFM_MAX /* Maximum length of input for srt_vec_ind() */
+
+/* index_pvq constants */
+#define KMAX 512
+#define KMAX_NON_DIRECT 96 /* max K for non-direct indexing recursion rows */
+#define ODD_DIV_SIZE 48 /* ind0=1/1 ind1 =1/3 ... ind47=1/95 */
+
+
+/* TCQ */
+#define TCQ_MAX_BAND_SIZE 120 /* Maxiumum supported band size for TCQ+USQ search */
+#define STATES 8
+#define MAX_AR_FREQ 16383
+#define AR_BITS 16
+#define STATES_LSB 4
+#define TCQ_LSB_SIZE 24
+#define TCQ_AMP 10
+#define QTCQ (0.2f)
+
+#define AR_TOP ( ( 1 << AR_BITS ) - 1 )
+#define AR_FIRST ( AR_TOP / 4 + 1 )
+#define AR_HALF ( 2 * AR_FIRST )
+#define AR_THIRD ( 3 * AR_FIRST )
+
+#define MAX_SIZEBUF_PBITSTREAM 1024
+
+/*----------------------------------------------------------------------------------*
+ * SWB BWE for LR MDCT core
+ *----------------------------------------------------------------------------------*/
+
+#define G1_RANGE 4
+#define G1G2_RANGE 15
+#define GRP_SB 4 /*Maximum subband groups*/
+#define THR1 4 /* Bit allocation threshold value */
+#define THR2 5 /* Bit allocation threshold value */
+#define THR3 6 /* Bit allocation threshold value */
+
+#define NB_SWB_SUBBANDS 4 /* maximum number of subbands in normal2 subband coding */
+#define SWB_SB_LEN0_12KBPS 55/* length of subband number X in lowest bit rate operation */
+#define SWB_SB_LEN1_12KBPS 68
+#define SWB_SB_LEN2_12KBPS 84
+#define SWB_SB_LEN3_12KBPS 105
+#define SWB_HIGHBAND_12KBPS (SWB_SB_LEN0_12KBPS+SWB_SB_LEN1_12KBPS+SWB_SB_LEN2_12KBPS+SWB_SB_LEN3_12KBPS)
+#define SWB_LOWBAND_12KBPS (HQ_GENERIC_END_FREQ_14P2KHZ - SWB_HIGHBAND_12KBPS)
+#define SWB_HIGHBAND_MAX SWB_HIGHBAND_12KBPS
+#define SWB_LOWBAND_MAX SWB_LOWBAND_12KBPS
+
+#define SWB_SB_OFF0_12KBPS 0 /* subband offsets are based on the subband lengths */
+#define SWB_SB_OFF1_12KBPS (SWB_SB_OFF0_12KBPS + SWB_SB_LEN0_12KBPS)
+#define SWB_SB_OFF2_12KBPS (SWB_SB_OFF1_12KBPS + SWB_SB_LEN1_12KBPS)
+#define SWB_SB_OFF3_12KBPS (SWB_SB_OFF2_12KBPS + SWB_SB_LEN2_12KBPS)
+#define SWB_SB_OFF4_12KBPS (SWB_SB_OFF3_12KBPS + SWB_SB_LEN3_12KBPS)
+
+/* 16.4 kbps */
+#define SWB_SB_LEN0_16KBPS 59/* length of subband number X in lowest bit rate operation */
+#define SWB_SB_LEN1_16KBPS 74
+#define SWB_SB_LEN2_16KBPS 92
+#define SWB_SB_LEN3_16KBPS 115
+#define SWB_HIGHBAND_16KBPS (SWB_SB_LEN0_16KBPS+SWB_SB_LEN1_16KBPS+SWB_SB_LEN2_16KBPS+SWB_SB_LEN3_16KBPS)
+#define SWB_LOWBAND_16KBPS (HQ_GENERIC_END_FREQ_16P0KHZ - SWB_HIGHBAND_16KBPS)
+
+#define SWB_SB_OFF0_16KBPS 0 /* subband offsets are based on the subband lengths */
+#define SWB_SB_OFF1_16KBPS (SWB_SB_OFF0_16KBPS + SWB_SB_LEN0_16KBPS)
+#define SWB_SB_OFF2_16KBPS (SWB_SB_OFF1_16KBPS + SWB_SB_LEN1_16KBPS)
+#define SWB_SB_OFF3_16KBPS (SWB_SB_OFF2_16KBPS + SWB_SB_LEN2_16KBPS)
+#define SWB_SB_OFF4_16KBPS (SWB_SB_OFF3_16KBPS + SWB_SB_LEN3_16KBPS)
+
+/* SpectrumSmoothing */
+#define L_SB 12 /* subband length for SpectrumSmoothing */
+
+/* SpectrumSmoothing for NSS */
+#define L_SB_NSS 8
+#define L_SB_NSS_HALF (L_SB_NSS/2)
+#define NUM_SUBBAND_SMOOTH_MAX (SWB_HIGHBAND_12KBPS/L_SB_NSS+1)
+#define MA_LEN 7
+
+/* Harmonic mode */
+#define NB_SWB_SUBBANDS_HAR_SEARCH_SB 2 /* search number of subbands in harmonic subband coding */
+#define NB_SWB_SUBBANDS_HAR 4 /* maximum number of subbands in harmonic subband coding */
+#define N_NBIGGEST_PULSEARCH 18
+#define N_NBIGGEST_SEARCH_LRG_B 32
+
+
+/* 13.2 kbps */
+#define SWB_SB_BW_LEN0_12KBPS_HAR 56 /* Group 1 length for BWE */
+#define SWB_SB_BW_LEN1_12KBPS_HAR 100 /* Group 2 Length for BWE */
+#define SWB_SB_BW_LEN2_12KBPS_HAR SWB_SB_BW_LEN1_12KBPS_HAR
+#define SWB_SB_BW_LEN3_12KBPS_HAR SWB_SB_BW_LEN0_12KBPS_HAR
+
+/* 16.4 kbps */
+#define SWB_SB_BW_LEN0_16KBPS_HAR 60 /* Group 1 length for BWE */
+#define SWB_SB_BW_LEN1_16KBPS_HAR 110 /* Group 2 Length for BWE */
+#define SWB_SB_BW_LEN2_16KBPS_HAR SWB_SB_BW_LEN1_16KBPS_HAR
+#define SWB_SB_BW_LEN3_16KBPS_HAR SWB_SB_BW_LEN0_16KBPS_HAR
+
+#define SWB_SB_OFF0_SUB5_12KBPS_HAR 0 /* subband offsets are based on the subband lengths */
+#define SWB_SB_OFF1_SUB5_12KBPS_HAR (SWB_SB_OFF0_SUB5_12KBPS_HAR + SWB_SB_BW_LEN0_12KBPS_HAR)
+#define SWB_SB_OFF2_SUB5_12KBPS_HAR (SWB_SB_OFF1_SUB5_12KBPS_HAR + SWB_SB_BW_LEN1_12KBPS_HAR)
+#define SWB_SB_OFF3_SUB5_12KBPS_HAR (SWB_SB_OFF2_SUB5_12KBPS_HAR + SWB_SB_BW_LEN2_12KBPS_HAR)
+
+#define SWB_SB_OFF0_SUB5_16KBPS_HAR 0 /* subband offsets are based on the subband lengths */
+#define SWB_SB_OFF1_SUB5_16KBPS_HAR (SWB_SB_OFF0_SUB5_16KBPS_HAR + SWB_SB_BW_LEN0_16KBPS_HAR)
+#define SWB_SB_OFF2_SUB5_16KBPS_HAR (SWB_SB_OFF1_SUB5_16KBPS_HAR + SWB_SB_BW_LEN1_16KBPS_HAR)
+#define SWB_SB_OFF3_SUB5_16KBPS_HAR (SWB_SB_OFF2_SUB5_16KBPS_HAR + SWB_SB_BW_LEN2_16KBPS_HAR)
+
+#define LR_BLK_LEN 16
+#define LR_HLF_PK_BLK_LEN 8
+#define LR_LOWBAND_DIF_PK_LEN 10
+#define SWB_HAR_RAN1 80
+#define SWB_HAR_RAN2 140
+#define SWB_HAR_RAN3 200
+#define SPT_SHORTEN_SBNUM 4
+
+/* LRMDCT fix precision */
+#define SWB_BWE_LR_Qs 12
+#define SWB_BWE_LR_Qbe 14
+#define SWB_BWE_LR_QRk 16
+
+
+/*----------------------------------------------------------------------------------*
+ * FEC for HQ core
+ *----------------------------------------------------------------------------------*/
+
+#define MAX_PGF 7
+#define MAX_ROW 2
+
+#define MAX_SB_NB 3
+
+#define NELP_LP_ORDER 8
+#define NUM_NELP_GAINS 10
+
+#define MINIMUM_RATE_TO_ENCODE_VOICING_FLAG 45000
+#define FRAC_BWE_SMOOTH 2.0f /* >= 1 */
+#define FRAMECTTOSTART_MDCT 3
+
+/*----------------------------------------------------------------------------------*
+ * Channel aware mode (FEC)
+ *----------------------------------------------------------------------------------*/
+
+#define FEC_OFFSET 3
+#define MAX_RF_FEC_OFFSET 9
+
+
+/*----------------------------------------------------------------------------------*
+ * HQ FEC
+ *----------------------------------------------------------------------------------*/
+
+#define POST_HQ_DELAY_NS DELAY_BWE_TOTAL_NS /* delay of post processing after core HQ coding */
+#define PH_ECU_ALDO_OLP2_NS (ACELP_LOOK_NS/2) /* half length of ALDO WINDOW overlap */
+#define PH_ECU_LOOKAHEAD_NS (11*ACELP_LOOK_NS/(7*2)) /* Number of nanoseconds look-ahead ahead from the end of the past synthesized frame */
+#define PH_ECU_MEM_NS ((L_PROT48k/48 - 20)*1000000-PH_ECU_LOOKAHEAD_NS) /* Number of nanoseconds memory for Phase ECU before the old_synthFB_fx pointer */
+
+#define N_LEAD_NB 70 /* (N_LEAD_MDCT*(L_FRAME8k/20)) */
+#define N_ZERO_NB 45 /* (N_ZERO_MDCT*(L_FRAME8k/20)) */
+#define N_LEAD_O_NB 90 /* (20.f-N_LEAD_MDCT)*(L_FRAME8k/20) */
+#define N_ZERO_O_NB 35 /* (10.f-N_ZERO_MDCT)*(L_FRAME8k/20) */
+#define N_Z_L_NB 115 /* (N_Z_L_MDCT*(float)(L/20)) = N_ZERO_NB + N_LEAD_NB*/
+#define N_Z_L_O_NB 205 /* (N_Z_L_O_MDCT*(float)(L/20)) = N_ZERO_NB + N_LEAD_NB + N_LEAD_O_NB */
+
+#define L_PROT32k 1024 /* HQ phase ECU prototype frame length */
+#define MAX_PLOCS L_PROT48k/4+1 /* maximum number of spectral peaks to be searched */
+#define QUOT_LPR_LTR 4
+#define LGW_MAX 9 /* maximum number frequency group widths */
+#define BETA_MUTE_FAC_INI 0.5f /* initial noise attenuation factor */
+#define L_TRANA32k (L_PROT32k/QUOT_LPR_LTR) /* transient analysis frame length */
+#define L_TRANA16k (L_TRANA32k/2)
+#define L_TRANA8k (L_TRANA32k/4)
+#define L_PROT_HAMM_LEN2_48k NS2SA(48000,6000000L)
+#define L_PROT_HAMM_LEN2_32k NS2SA(32000,6000000L)
+#define L_PROT_HAMM_LEN2_16k NS2SA(16000,6000000L)
+#define L_PROT48k L_PROT32k * 3/2 /* HQ phase ECU prototype frame length */
+#define L_PROT48k_2 L_PROT48k/2
+#define L_TRANA48k (L_PROT48k/QUOT_LPR_LTR) /* transient analysis frame length */
+#define PH_ECU_SPEC_SIZE L_PROT48k
+#define T_SIN_PI_2 (PH_ECU_SPEC_SIZE/4)
+#define HQ_FEC_SIGN_SFM 16
+#define OFF_FRAMES_LIMIT 30 /* HQ phase ECU, burst length for muting to zero */
+#define PH_ECU_MUTE_START 15 /* HQ phase ECU, burst length to start steep muting */
+
+#define SCALE_DOWN_3dB 0.7071f
+#define MAX_TILT 0.f
+#define ED_THRES 1.0f
+
+#define ED_THRES_12P 0.032209f
+#define ED_THRES_50P 0.159063f
+#define ED_THRES_90P 0.532669
+#define MAXDELAY_FEC 224
+
+#define RANDOM_START 1
+#define HQ_FEC_SIGN_THRES 6
+#define HQ_FEC_SIGN_THRES_TRANS 3
+#define HQ_FEC_BAND_SIZE 4
+
+
+/*--------------------------------------------------------------*
+ * Tonal MDCT PLC
+ *---------------------------------------------------------------*/
+
+#define MAX_NUMBER_OF_IDX 30
+#define GROUP_LENGTH 7
+#define MAX_PEAKS_FROM_PITCH 10
+#define LAST_HARMONIC_POS_TO_CHECK 128 /* 128 because we check harmonics only up to 3.2 kHz */
+#define ALLOWED_SIDE_LOBE_FLUCTUATION 3.0f /* 4.8 dB */
+#define LEVEL_ABOVE_ENVELOPE 7.59f /* 8.8 dB */
+#define UNREACHABLE_THRESHOLD 16.0f /* 12 dB Increase of LEVEL_ABOVE_ENVELOPE so that the threshold is not reached */
+#define SMALL_THRESHOLD 1.10f /* 0.41 dB Increase of LEVEL_ABOVE_ENVELOPE for the peak detection at a definitive peak in the estimated spectrum */
+#define BIG_THRESHOLD 1.5f /* 1.76 dB Increase of LEVEL_ABOVE_ENVELOPE for the peak detection at a probable peak in the estimated spectrum */
+
+#define kSmallerLagsTargetBitsThreshold 150
+#define kCtxHmOlRSThr 2.6f
+
+
+#define kTcxHmNumGainBits 2 /* Number of bits for the gain index */
+#define kTcxHmParabolaHalfWidth 4 /* Parabola half width */
+#define kLtpHmGainThr 0.46f /* Use the LTP pitch lag in the harmonic model? */
+
+#define LOWRATE_TCXLPC_MAX_BR ACELP_9k60
+
+/*--------------------------------------------------------------*
+ * Waveform-adjustment MDCT PLC
+ *---------------------------------------------------------------*/
+
+#define DEC_STATE_LEN 10
+#define MAX_POST_LEN 3
+#define TCX_TONALITY_INIT_CNT 7
+
+#define TCX_NONTONAL 0
+#define TCX_TONAL 1
+
+/*---------------------------------------------------------------*
+ * IGF *
+ *---------------------------------------------------------------*/
+
+#define IGF_MAX_TILES 5
+#define IGF_MAX_GRANULE_LEN 1200
+#define IGF_TRANS_FAK 2
+#define IGF_MAX_SFB 23
+#define IGF_NOF_GRIDS 3
+#define IGF_MAX_SUBFRAMES 2
+
+#define IGF_MODE_WB 1
+#define IGF_MODE_SWB 2
+#define IGF_MODE_FB 3
+
+#define IGF_BITRATE_WB_9600 0
+#define IGF_BITRATE_RF_WB_13200 1
+#define IGF_BITRATE_SWB_9600 2
+#define IGF_BITRATE_SWB_13200 3
+#define IGF_BITRATE_RF_SWB_13200 4
+#define IGF_BITRATE_SWB_16400 5
+#define IGF_BITRATE_SWB_24400 6
+#define IGF_BITRATE_SWB_32000 7
+#define IGF_BITRATE_SWB_48000 8
+#define IGF_BITRATE_FB_16400 9
+#define IGF_BITRATE_FB_24400 10
+#define IGF_BITRATE_FB_32000 11
+#define IGF_BITRATE_FB_48000 12
+#define IGF_BITRATE_FB_96000 13
+#define IGF_BITRATE_FB_128000 14
+#define IGF_BITRATE_UNKNOWN 15
+
+#define IGF_WHITENING_OFF 0
+#define IGF_WHITENING_MID 1
+#define IGF_WHITENING_STRONG 2
+
+#define IGF_GRID_LB_NORM 0
+#define IGF_GRID_LB_TRAN 1
+#define IGF_GRID_LB_SHORT 2
+
+/* constants for IGFSCFDecoder and IGFSCFEncoder */
+#define IGF_CTX_OFFSET 3 /* offset added to make the context values nonnegative, for array indexing */
+#define IGF_CTX_COUNT (2 * IGF_CTX_OFFSET + 1) /* number of contexts for the AC statistical model */
+#define IGF_MIN_ENC_SEPARATE -12 /* minimum residual value coded separately, without escape coding */
+#define IGF_MAX_ENC_SEPARATE +12 /* maximum residual value coded separately, without escape coding */
+#define IGF_SYMBOLS_IN_TABLE (1 + (IGF_MAX_ENC_SEPARATE - IGF_MIN_ENC_SEPARATE + 1) + 1) /* alphabet size */
+
+/*----------------------------------------------------------------------------------*
+ * SC-VBR
+ *----------------------------------------------------------------------------------*/
+
+#define UVG1_CBSIZE 32 /* NELP unvoiced gain-1 codebook size */
+#define UVG2_CBSIZE 64 /* NELP unvoiced gain-2 codebook size */
+
+/* PPP constants */
+#define NUM_ERB_WB 24 /* Number of ERB bands in wideband */
+#define NUM_ERB_NB 22 /* Number of ERB bands in narrowband */
+
+#define VBR_ADR_MAX_TARGET 6.15f /* max target ADR for VBR. This rate is used in the closed loop rate control */
+#define PPP_LAG_THRLD 180 /* max lag allowed for PPP coding */
+
+#define MAXLAG_WI (PPP_LAG_THRLD/2 + 12) /* Maximum lag used in waveform interpolation */
+#define MAX_LAG_PIT (PPP_LAG_THRLD + 21) /* Max possible pitch lag after adding delta lag */
+
+/*----------------------------------------------------------------------------------*
+ * JBM
+ *----------------------------------------------------------------------------------*/
+
+#define MAX_JBM_SLOTS 100 /* every primary copy and partial copy stored in JBM needs one slot */
+#define MAX_AU_SIZE (128000/50/8) /* max frame size in bytes */
+
+/*----------------------------------------------------------------------------------*
+ * TEC/TFA
+ *----------------------------------------------------------------------------------*/
+#define DELAY_TEMP_ENV_BUFF_TEC 9
+#define EXT_DELAY_HI_TEMP_ENV 2
+
+
+/*----------------------------------------------------------------------------------*
+ * BASOP ROM Tables
+ *----------------------------------------------------------------------------------*/
+
+#define LD_INT_TAB_LEN 120
+#define INV_TABLE_SIZE 256
+#define SQRT_TABLE_SIZE 256
+
+
+/*----------------------------------------------------------------------------------*
+ * Decoder modes
+ *----------------------------------------------------------------------------------*/
+
+
+enum
+{
+ PRIMARY_2800,
+ PRIMARY_7200,
+ PRIMARY_8000,
+ PRIMARY_9600,
+ PRIMARY_13200,
+ PRIMARY_16400,
+ PRIMARY_24400,
+ PRIMARY_32000,
+ PRIMARY_48000,
+ PRIMARY_64000,
+ PRIMARY_96000,
+ PRIMARY_128000,
+ PRIMARY_SID,
+ PRIMARY_FUT1,
+ SPEECH_LOST,
+ NO_DATA
+};
+
+enum
+{
+ AMRWB_IO_6600,
+ AMRWB_IO_8850,
+ AMRWB_IO_1265,
+ AMRWB_IO_1425,
+ AMRWB_IO_1585,
+ AMRWB_IO_1825,
+ AMRWB_IO_1985,
+ AMRWB_IO_2305,
+ AMRWB_IO_2385,
+ AMRWB_IO_SID/*,
+ AMRWB_IO_FUT1,
+ AMRWB_IO_FUT2,
+ AMRWB_IO_FUT3,
+ AMRWB_IO_FUT4,
+ SPEECH_LOST,
+ NO_DATA */
+};
+
+enum
+{
+ G192,
+ MIME
+ , VOIP_G192_RTP
+ , VOIP_RTPDUMP
+};
+
+#endif /* CNST_H */
diff --git a/lib_com/codec_tcx_common.c b/lib_com/codec_tcx_common.c
new file mode 100644
index 0000000000000000000000000000000000000000..ac9cf85dc1052fdce84c922109935fa30c337f93
--- /dev/null
+++ b/lib_com/codec_tcx_common.c
@@ -0,0 +1,174 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include
+#include "wmc_auto.h"
+#include "prot.h"
+#include "options.h"
+
+/*-------------------------------------------------------------------*
+ * tcxGetNoiseFillingTilt()
+ *
+ *
+ *-------------------------------------------------------------------*/
+
+int tcxGetNoiseFillingTilt(
+ float A[],
+ int L_frame,
+ int mode,
+ float *noiseTiltFactor
+)
+{
+ int firstLine;
+
+ if (mode)
+ {
+ firstLine = L_frame / 6;
+ *noiseTiltFactor = 0.5625f;
+ }
+ else
+ {
+ firstLine = L_frame / 8;
+ *noiseTiltFactor = get_gain( A+1, A, M, NULL );
+ *noiseTiltFactor = min(1.0f, (*noiseTiltFactor) + 0.09375f);
+ }
+
+ return firstLine;
+}
+
+/*-------------------------------------------------------------------*
+ * tcxFormantEnhancement()
+ *
+ *
+ *-------------------------------------------------------------------*/
+
+void tcxFormantEnhancement(
+ float xn_buf[],
+ float gainlpc[],
+ float spectrum[],
+ int L_frame
+)
+{
+ int k;
+ int i, j, l = 0;
+ float fac, step;
+
+ k = L_frame / FDNS_NPTS;
+
+ /* Formant enhancement via square root of the LPC gains */
+ xn_buf[0] = (float)sqrt(gainlpc[0]);
+ xn_buf[1] = (float)sqrt(gainlpc[1]);
+ fac = 1.0f / min(xn_buf[0], xn_buf[1]);
+
+ for (i = 1; i < FDNS_NPTS - 1; i++)
+ {
+ xn_buf[i+1] = (float)sqrt(gainlpc[i+1]);
+
+ if ((xn_buf[i-1] <= xn_buf[i]) && (xn_buf[i+1] <= xn_buf[i]))
+ {
+ step = max(xn_buf[i-1], xn_buf[i+1]);
+ step = (1.0f / step - fac) / (float)(i - l);
+ xn_buf[l] = 1.0f;
+ fac += step;
+ for (j = l + 1; j < i; j++)
+ {
+ xn_buf[j] = min(1.0f, xn_buf[j] * fac);
+ fac += step;
+ }
+ l = i;
+ }
+ }
+
+ /* i = tcx_cfg->fdns_npts - 1; Completing changes to gains */
+ step = min(xn_buf[i-1], xn_buf[i]);
+ step = (1.0f / step - fac) / (float)(i - l);
+ xn_buf[l] = 1.0f;
+ fac += step;
+ for (j = l + 1; j < i; j++)
+ {
+ xn_buf[j] = min(1.0f, xn_buf[j] * fac);
+ fac += step;
+ }
+ xn_buf[i] = 1.0f;
+
+ /* Application of changed gains onto decoded MDCT lines */
+ for (i = j = 0; i < L_frame; j++)
+ {
+ for (l = 0; l < k; i++, l++)
+ {
+ spectrum[i] *= xn_buf[j];
+ }
+ }
+
+ return;
+}
+
+/*-------------------------------------------------------------------*
+ * tcxGetNoiseFillingTilt()
+ *
+ *
+ *-------------------------------------------------------------------*/
+
+void tcxInvertWindowGrouping(
+ TCX_config *tcx_cfg,
+ float xn_buf[],
+ float spectrum[],
+ int L_frame,
+ int fUseTns,
+ int last_core,
+ int index,
+ int frame_cnt,
+ int bfi
+)
+{
+ short i, w, t_integer;
+ int L_win, L_spec;
+
+ if (frame_cnt && !bfi && last_core!=0)
+ {
+ /* fix sub-window overlap */
+ tcx_cfg->tcx_last_overlap_mode = tcx_cfg->tcx_curr_overlap_mode;
+ }
+
+ if (((!bfi) &&((tcx_cfg->tcx_last_overlap_mode != FULL_OVERLAP) ||
+ ((tcx_cfg->tcx_curr_overlap_mode == FULL_OVERLAP) && (frame_cnt == 0) && (index == 0))))
+ ||
+ ((bfi) &&((tcx_cfg->tcx_last_overlap_mode != FULL_OVERLAP) &&
+ !(tcx_cfg->tcx_curr_overlap_mode == FULL_OVERLAP))))
+ {
+
+ /* ungroup sub-windows: deinterleave MDCT bins into separate windows */
+ for (t_integer = w = 0; w < 2; w++)
+ {
+ for (i = w; i < L_frame; i += 2)
+ {
+ xn_buf[t_integer++] = spectrum[i];
+ }
+ }
+
+ mvr2r( xn_buf, spectrum, L_frame );
+
+ if( tcx_cfg->fIsTNSAllowed && !bfi && fUseTns )
+ {
+ L_win = L_frame >> 1;
+ L_spec = tcx_cfg->tnsConfig[0][0].iFilterBorders[0];
+
+ /* rearrange LF sub-window lines prior to TNS synthesis filtering */
+ if( L_spec < L_frame )
+ {
+ mvr2r( spectrum+8, spectrum+16, L_spec/2-8 );
+ mvr2r( spectrum+L_frame/2, spectrum+8, 8 );
+ mvr2r( spectrum+L_frame/2+8, spectrum+L_spec/2+8, L_spec/2-8 );
+ }
+ else
+ {
+ mvr2r( spectrum+8, xn_buf, L_win );
+ mvr2r( xn_buf, spectrum+16, L_win-8 );
+ mvr2r( xn_buf+L_win-8, spectrum+8, 8);
+ }
+ }
+ }
+
+ return;
+}
diff --git a/lib_com/core_com_config.c b/lib_com/core_com_config.c
new file mode 100644
index 0000000000000000000000000000000000000000..8546169d8619ad8ac441d85bf180cf9247e7c787
--- /dev/null
+++ b/lib_com/core_com_config.c
@@ -0,0 +1,420 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include
+#include "wmc_auto.h"
+#include
+#include
+#include
+
+#include "options.h"
+#include "rom_com.h"
+#include "prot.h"
+
+/*-------------------------------------------------------------------*
+ * getTcxonly()
+ *
+ *
+ *-------------------------------------------------------------------*/
+
+short getTcxonly(
+ const int bitrate
+)
+{
+ short tcxonly = 0;
+
+ if( bitrate > ACELP_32k )
+ {
+ tcxonly = 1;
+ }
+
+ return tcxonly;
+}
+
+
+/*-------------------------------------------------------------------*
+ * getCtxHm()
+ *
+ *
+ *-------------------------------------------------------------------*/
+
+short getCtxHm(
+ const int bitrate,
+ const short rf_flag
+)
+{
+ short ctx_hm = 0;
+ if( (bitrate > LPC_SHAPED_ARI_MAX_RATE) && (bitrate <= 64000) && !rf_flag)
+ {
+ ctx_hm = 1;
+ }
+
+ return ctx_hm;
+}
+
+/*-------------------------------------------------------------------*
+ * getResq()
+ *
+ *
+ *-------------------------------------------------------------------*/
+
+short getResq(
+ const int bitrate
+)
+{
+ short resq = 0;
+
+ if(bitrate <= HQ_64k)
+ {
+ resq = 1;
+ }
+
+ return resq;
+}
+
+/*-------------------------------------------------------------------*
+ * getTnsAllowed()
+ *
+ *
+ *-------------------------------------------------------------------*/
+
+short getTnsAllowed(
+ const int bitrate,
+ const short igf
+)
+{
+ short tnsAllowed = 0;
+
+ if( igf )
+ {
+ if( bitrate > HQ_16k40 )
+ {
+ tnsAllowed = 1;
+ }
+ }
+ else if( bitrate > HQ_32k )
+ {
+ tnsAllowed = 1;
+ }
+
+ return tnsAllowed;
+}
+
+/*-------------------------------------------------------------------*
+ * getRestrictedMode()
+ *
+ *
+ *-------------------------------------------------------------------*/
+
+short getRestrictedMode(
+ const int bitrate,
+ const short Opt_AMR_WB
+)
+{
+ short restrictedMode = 3;
+
+ if ( !Opt_AMR_WB && (bitrate > HQ_32k) )
+ {
+ restrictedMode = 6;
+ }
+ else if ( Opt_AMR_WB )
+ {
+ restrictedMode = 1;
+ }
+
+ return restrictedMode;
+}
+
+/*-------------------------------------------------------------------*
+ * getMdctWindowLength()
+ *
+ *
+ *-------------------------------------------------------------------*/
+
+short getMdctWindowLength(
+ const float fscale
+)
+{
+
+ short mdctWindowLength;
+
+ mdctWindowLength = (L_LOOK_12k8 * fscale)/FSCALE_DENOM;
+
+ return mdctWindowLength;
+}
+
+/*-------------------------------------------------------------------*
+ * sr2fscale()
+ *
+ *
+ *-------------------------------------------------------------------*/
+
+short sr2fscale(
+ const int sr
+)
+{
+
+ return (FSCALE_DENOM*sr)/12800;
+}
+
+/*-------------------------------------------------------------------*
+ * getCoreSamplerateMode2()
+ *
+ *
+ *-------------------------------------------------------------------*/
+
+int getCoreSamplerateMode2(
+ const int bitrate,
+ const int bandwidth,
+ const short rf_mode
+)
+{
+ int sr_core = 0;
+
+ if( bandwidth == NB )
+ {
+ sr_core = 12800;
+ }
+ else if( (bandwidth == WB && bitrate < ACELP_13k20) ||
+ (bandwidth == SWB && bitrate <= ACELP_13k20) || (rf_mode == 1) )
+ {
+ sr_core = 12800;
+ }
+ else if( bandwidth == WB || (bandwidth == SWB && bitrate <= ACELP_32k)
+ || (bandwidth == FB && bitrate <= ACELP_32k) )
+ {
+ sr_core = 16000;
+ }
+ else if( (bandwidth == SWB || bandwidth == FB) && bitrate <= HQ_64k)
+ {
+ sr_core = 25600;
+ }
+ else if( bandwidth == SWB || bandwidth == FB )
+ {
+ sr_core = 32000;
+ }
+
+ return sr_core;
+}
+
+/*-------------------------------------------------------------------*
+ * getTcxBandwidth()
+ *
+ *
+ *-------------------------------------------------------------------*/
+
+float getTcxBandwidth(
+ const int bandwidth
+)
+{
+ float tcxBandwidth = 0.5f;
+
+ if( bandwidth == NB )
+ {
+ tcxBandwidth = 0.3125f;
+ }
+
+ return tcxBandwidth;
+}
+
+/*-------------------------------------------------------------------*
+ * getIgfPresent()
+ *
+ *
+ *-------------------------------------------------------------------*/
+
+short getIgfPresent(
+ const int bitrate,
+ const int bandwidth,
+ const short rf_mode
+)
+{
+ short igfPresent = 0;
+
+ if( bandwidth == SWB && bitrate >= ACELP_9k60 && bitrate < HQ_64k )
+ {
+ igfPresent = 1;
+ }
+ else if( bandwidth == FB && bitrate >= ACELP_16k40 )
+ {
+ igfPresent = 1;
+ }
+ else if( bandwidth == WB && bitrate == ACELP_9k60 )
+ {
+ igfPresent = 1;
+ }
+ if( ((bandwidth == WB) || (bandwidth == SWB)) && (rf_mode == 1) && (bitrate == ACELP_13k20) )
+ {
+ igfPresent = 1;
+ }
+
+ return igfPresent;
+}
+
+/*-------------------------------------------------------------------*
+ * getCnaPresent()
+ *
+ *
+ *-------------------------------------------------------------------*/
+
+short getCnaPresent(
+ const int bitrate,
+ const int bandwidth
+)
+{
+ short flag_cna = 0;
+
+ if( bandwidth == NB && bitrate <= ACELP_13k20 )
+ {
+ flag_cna = 1;
+ }
+
+ if( bandwidth == WB && bitrate <= ACELP_13k20 )
+ {
+ flag_cna = 1;
+ }
+
+ if( bandwidth == SWB && bitrate <= ACELP_13k20 )
+ {
+ flag_cna = 1;
+ }
+
+ return flag_cna;
+}
+
+/*-------------------------------------------------------------------*
+ * getTcxLtp()
+ *
+ *
+ *-------------------------------------------------------------------*/
+short getTcxLtp(
+ const int sr_core
+)
+{
+ short tcxltp = 0;
+
+ if ( (sr_core <= 25600) )
+ {
+ tcxltp = 1;
+ }
+
+ return tcxltp;
+}
+
+/*-------------------------------------------------------------------*
+ * initPitchLagParameters()
+ *
+ *
+ *-------------------------------------------------------------------*/
+
+short initPitchLagParameters(
+ const int sr_core,
+ int *pit_min,
+ int *pit_fr1,
+ int *pit_fr1b,
+ int *pit_fr2,
+ int *pit_max
+)
+{
+
+ short pit_res_max;
+
+
+ if (sr_core==12800)
+ {
+ *pit_min = PIT_MIN_12k8;
+ *pit_max = PIT_MAX_12k8;
+ *pit_fr2 = PIT_FR2_12k8;
+ *pit_fr1 = PIT_FR1_12k8;
+ *pit_fr1b = PIT_FR1_8b_12k8;
+ pit_res_max = 4;
+ }
+ else if (sr_core==16000)
+ {
+ *pit_min = PIT_MIN_16k;
+ *pit_max = PIT16k_MAX;
+ *pit_fr2 = PIT_FR2_16k;
+ *pit_fr1 = PIT_FR1_16k;
+ *pit_fr1b = PIT_FR1_8b_16k;
+ pit_res_max = 6;
+ }
+ else if (sr_core==25600)
+ {
+ *pit_min = PIT_MIN_25k6;
+ *pit_max = PIT_MAX_25k6;
+ *pit_fr2 = PIT_FR2_25k6;
+ *pit_fr1 = PIT_FR1_25k6;
+ *pit_fr1b = PIT_FR1_8b_25k6;
+ pit_res_max = 4;
+ }
+ else /* sr_core==32000 */
+ {
+ *pit_min = PIT_MIN_32k;
+ *pit_max = PIT_MAX_32k;
+ *pit_fr2 = PIT_FR2_32k;
+ *pit_fr1 = PIT_FR1_32k;
+ *pit_fr1b = PIT_FR1_8b_32k;
+ pit_res_max = 6;
+ }
+
+ return pit_res_max;
+}
+
+/*-------------------------------------------------------------------*
+ * getNumTcxCodedLines()
+ *
+ *
+ *-------------------------------------------------------------------*/
+
+short getNumTcxCodedLines(
+ const short bwidth
+)
+{
+ short tcx_coded_lines;
+
+ switch (bwidth)
+ {
+ case NB:
+ tcx_coded_lines = 160;
+ break;
+ case WB:
+ tcx_coded_lines = 320;
+ break;
+ case SWB:
+ tcx_coded_lines = 640;
+ break;
+ case FB:
+ tcx_coded_lines = 960;
+ break;
+ default:
+ tcx_coded_lines = 0;
+ break;
+ }
+
+ return tcx_coded_lines;
+}
+
+/*-------------------------------------------------------------------*
+ * getTcxLpcShapedAri()
+ *
+ *
+ *-------------------------------------------------------------------*/
+
+short getTcxLpcShapedAri(
+ const int total_brate,
+ const short bwidth,
+ const short rf_mode
+)
+{
+ short tcx_lpc_shaped_ari = 0;
+
+ (void) bwidth;
+
+ if( total_brate <= LPC_SHAPED_ARI_MAX_RATE || rf_mode )
+ {
+ tcx_lpc_shaped_ari = 1;
+ }
+
+ return tcx_lpc_shaped_ari;
+}
diff --git a/lib_com/deemph.c b/lib_com/deemph.c
new file mode 100644
index 0000000000000000000000000000000000000000..9109ba2ab30595e456b668cde78c7b88d0fdfce0
--- /dev/null
+++ b/lib_com/deemph.c
@@ -0,0 +1,38 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include "options.h"
+#include "wmc_auto.h"
+#include "prot.h"
+
+/*-------------------------------------------------------------------*
+ * deemph()
+ *
+ * Deemphasis: filtering through 1/(1-mu z^-1)
+ *-------------------------------------------------------------------*/
+
+void deemph(
+ float *signal, /* i/o: signal */
+ const float mu, /* i : deemphasis factor */
+ const short L, /* i : vector size */
+ float *mem /* i/o: memory (y[-1]) */
+)
+{
+ short i;
+
+ signal[0] = signal[0] + mu * (*mem);
+ for (i=1; i -1e-10) )
+ {
+ *mem = 0;
+ }
+
+ return;
+}
diff --git a/lib_com/delay_comp.c b/lib_com/delay_comp.c
new file mode 100644
index 0000000000000000000000000000000000000000..ef5dd06fe336f9eeade16e2b35f367efb9c0597a
--- /dev/null
+++ b/lib_com/delay_comp.c
@@ -0,0 +1,40 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include "options.h"
+#include "wmc_auto.h"
+#include "prot.h"
+
+
+/*--------------------------------------------------------------------------
+ * get_delay()
+ *
+ * Function returns various types of delays in the codec in ms.
+ *--------------------------------------------------------------------------*/
+
+float get_delay( /* o : delay value in ms */
+ const short what_delay, /* i : what delay? (ENC or DEC) */
+ const int io_fs /* i : input/output sampling frequency */
+)
+{
+ float delay = 0;
+
+ if( what_delay == ENC )
+ {
+ delay = (DELAY_FIR_RESAMPL_NS + ACELP_LOOK_NS);
+ }
+ else
+ {
+ if( io_fs == 8000 )
+ {
+ delay = DELAY_CLDFB_NS;
+ }
+ else
+ {
+ delay = DELAY_BWE_TOTAL_NS;
+ }
+ }
+
+ return delay;
+}
diff --git a/lib_com/disclaimer.c b/lib_com/disclaimer.c
new file mode 100644
index 0000000000000000000000000000000000000000..7340db511e6e59ee59091a81f170bef73512fc7e
--- /dev/null
+++ b/lib_com/disclaimer.c
@@ -0,0 +1,19 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+
+#include "wmc_auto.h"
+#include "options.h"
+#include "prot.h"
+
+int print_disclaimer(FILE *fPtr)
+{
+
+ fprintf(fPtr, "\n===========================================================================\n");
+ fprintf(fPtr, " EVS Codec (Floating Point) 3GPP TS26.443 November 04, 2021.\n");
+ fprintf(fPtr, " Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0\n");
+ fprintf(fPtr, "===========================================================================\n\n\n");
+
+ return 0;
+}
diff --git a/lib_com/dlpc_bfi.c b/lib_com/dlpc_bfi.c
new file mode 100644
index 0000000000000000000000000000000000000000..9c7e0be31e13457abf0581d8081fad9a83c16629
--- /dev/null
+++ b/lib_com/dlpc_bfi.c
@@ -0,0 +1,49 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include
+#include "wmc_auto.h"
+#include
+#include
+#include "options.h"
+#include "prot.h"
+#include "rom_com.h"
+
+
+/*---------------------------------------------------------------------*
+* routine: dlpc_bfi()
+*
+*
+*---------------------------------------------------------------------*/
+
+void dlpc_bfi(
+ int L_frame,
+ float *lsf_q, /* o : quantized lsfs */
+ const float *lsfold, /* i : past quantized lsf */
+ const short last_good, /* i : last good received frame */
+ const short nbLostCmpt, /* i : counter of consecutive bad frames */
+ float mem_MA[], /* i/o: quantizer memory for MA model */
+ float *mem_AR, /* i/o: quantizer memory for AR model */
+ float *stab_fac, /* i : lsf stability factor */
+ float *lsf_adaptive_mean,/* i : lsf adaptive mean, updated when BFI==0 */
+ int numlpc, /* i : Number of division per superframe */
+ float lsf_cng[],
+ int plcBackgroundNoiseUpdated,
+ float *lsf_q_cng, /* o : quantized lsfs of background noise */
+ float *old_lsf_q_cng, /* o : old quantized lsfs for background noise */
+ const float lsfBase[] /* i : base for differential lsf coding */
+)
+{
+ lsf_dec_bfi( MODE2, &lsf_q[0], lsfold, lsf_adaptive_mean, lsfBase, mem_MA, mem_AR, *stab_fac, 0, L_frame, last_good,
+ nbLostCmpt, plcBackgroundNoiseUpdated, lsf_q_cng, lsf_cng, old_lsf_q_cng, 0, 0, 0 );
+
+ if( numlpc == 2 )
+ {
+ /* Decode the second LPC */
+ lsf_dec_bfi( MODE2, &lsf_q[M], &lsf_q[0], lsf_adaptive_mean, lsfBase, mem_MA, mem_AR, *stab_fac, 0, L_frame, last_good,
+ nbLostCmpt+1, plcBackgroundNoiseUpdated, lsf_q_cng, lsf_cng, old_lsf_q_cng, 0, 0, 0 );
+ }
+
+ return;
+}
diff --git a/lib_com/edct.c b/lib_com/edct.c
new file mode 100644
index 0000000000000000000000000000000000000000..472f507d07d751ed2096eaa5f7008c683ead4e95
--- /dev/null
+++ b/lib_com/edct.c
@@ -0,0 +1,194 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include
+#include "wmc_auto.h"
+#include
+#include "options.h"
+#include "cnst.h"
+#include "rom_com.h"
+#include "prot.h"
+
+static float const * get_edct_table(short length)
+{
+ float const * edct_table = NULL;
+ switch (length)
+ {
+ case 1200:
+ edct_table = edct_table_600;
+ break;
+ case 960:
+ edct_table = edct_table_480;
+ break;
+ case 640:
+ edct_table = edct_table_320;
+ break;
+ case 320:
+ edct_table = edct_table_160;
+ break;
+ case 256:
+ edct_table = edct_table_128;
+ break;
+ case 240:
+ edct_table = edct_table_120;
+ break;
+ case 200:
+ edct_table = edct_table_100;
+ break;
+ case 160:
+ edct_table = edct_table_80;
+ break;
+ case 40:
+ edct_table = edct_table_20;
+ break;
+ case 800:
+ edct_table = edct_table_400;
+ break;
+ case 512:
+ edct_table = edct_table_256;
+ break;
+ case 480:
+ edct_table = edct_table_240;
+ break;
+ case 400:
+ edct_table = edct_table_200;
+ break;
+ case 128:
+ edct_table = edct_table_64;
+ break;
+ case 80:
+ edct_table = edct_table_40;
+ break;
+ default:
+ fprintf(stderr, "edct/edst(): length is not in table!");
+ exit(-1);
+ break;
+ }
+ return edct_table;
+}
+
+/*-----------------------------------------------------------------*
+ * edct()
+ *
+ * DCT transform
+ *-----------------------------------------------------------------*/
+
+void edct(
+ const float *x, /* i : input signal */
+ float *y, /* o : output transform */
+ short length /* i : length */
+)
+{
+ short i;
+ float re[L_FRAME_PLUS/2];
+ float im[L_FRAME_PLUS/2];
+ const float *edct_table = 0;
+ float local;
+
+ edct_table = get_edct_table(length);
+
+ /* Twiddling and Pre-rotate */
+ for (i = 0; i < length/2; i++)
+ {
+ re[i] = x[2*i] * edct_table[i] + x[length-1-2*i] * edct_table[length/2-1-i];
+ im[i] = x[length-1-2*i] * edct_table[i] - x[2*i] * edct_table[length/2-1-i];
+ }
+
+ DoFFT(re, im, length/2);
+
+ local = (0.75f * EVS_PI)/ length;
+
+ for (i = 0; i < length/2; i++)
+ {
+ float tmp;
+ tmp = re[i] - im[i] * local; /* 3*pi/(4*length) is a constant */
+ im[i] = im[i] + re[i] * local;
+ re[i] = tmp;
+ }
+
+ /* Post-rotate and obtain the output data */
+ for (i = 0; i < length/2; i++)
+ {
+ y[2*i] = re[i] * edct_table[i] + im[i] * edct_table[length/2-1-i];
+ y[length-1-2*i] = re[i] * edct_table[length/2-1-i] - im[i] * edct_table[i];
+ }
+
+ return;
+}
+
+/*-------------------------------------------------------------------------*
+ * FUNCTION : edst()
+ *
+ * PURPOSE : DST_IV transform
+ *-------------------------------------------------------------------------*/
+void edst(
+ const float *x, /* i : input signal */
+ float *y, /* o : output transform */
+ short length /* i : length */
+)
+{
+ short i;
+ float re[L_FRAME_PLUS/2];
+ float im[L_FRAME_PLUS/2];
+ const float *edct_table = 0;
+ float local;
+
+ edct_table = get_edct_table(length);
+
+ /* Twiddling and Pre-rotate */
+ for (i = 0; i < length/2; i++)
+ {
+ re[i] = x[length-1-2*i] * edct_table[i] + x[2*i] *edct_table[length/2-1-i];
+ im[i] = x[2*i] * edct_table[i] - x[length-1-2*i] * edct_table[length/2-1-i];
+ }
+
+ DoFFT(re, im, length/2);
+
+ local = (0.75f * EVS_PI)/ length;
+
+ for (i = 0; i < length/2; i++)
+ {
+ float tmp;
+ tmp = re[i] - im[i] * local; /* 3*pi/(4*length) is a constant */
+ im[i] = im[i] + re[i] * local;
+ re[i] = tmp;
+ }
+
+ /* Post-rotate and obtain the output data */
+ for (i = 0; i < length/2; i++)
+ {
+ y[2*i] = re[i] * edct_table[i] + im[i] * edct_table[length/2-1-i];
+ y[length-1-2*i] = im[i] * edct_table[i] - re[i] * edct_table[length/2-1-i];
+ }
+
+ return;
+}
+
+/*-----------------------------------------------------------------*
+ * iedct_short()
+ *
+ * Inverse EDCT for short frames
+ *-----------------------------------------------------------------*/
+
+void iedct_short(
+ const float *in, /* i : input vector */
+ float *out, /* o : output vector */
+ const short segment_length /* i : length */
+)
+{
+ float alias[MAX_SEGMENT_LENGTH];
+ short i;
+
+ edct(in, alias, segment_length/2);
+
+ for (i = 0; i < segment_length/4; i++)
+ {
+ out[i] = alias[segment_length/4 + i];
+ out[segment_length/4 + i] = -alias[segment_length/2 - 1 - i];
+ out[segment_length/2 + i] = -alias[segment_length/4 - 1 - i];
+ out[3*segment_length/4 + i] = -alias[i];
+ }
+
+ return;
+}
diff --git a/lib_com/enh1632.c b/lib_com/enh1632.c
new file mode 100644
index 0000000000000000000000000000000000000000..f0c389c80c2d9a60932af52bdffb637bf47187cd
--- /dev/null
+++ b/lib_com/enh1632.c
@@ -0,0 +1,710 @@
+/******************************************************************************************************
+
+ (C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
+ Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
+ Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
+ Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
+ contributors to this repository. All Rights Reserved.
+
+ This software is protected by copyright law and by international treaties.
+ The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
+ Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
+ Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
+ Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
+ contributors to this repository retain full ownership rights in their respective contributions in
+ the software. This notice grants no license of any kind, including but not limited to patent
+ license, nor is any license granted by implication, estoppel or otherwise.
+
+ Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
+ contributions.
+
+ This software is provided "AS IS", without any express or implied warranties. The software is in the
+ development stage. It is intended exclusively for experts who have experience with such software and
+ solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
+ and fitness for a particular purpose are hereby disclaimed and excluded.
+
+ Any dispute, controversy or claim arising under or in relation to providing this software shall be
+ submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
+ accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
+ the United Nations Convention on Contracts on the International Sales of Goods.
+
+*******************************************************************************************************/
+
+/*
+ ===========================================================================
+ File: ENH1632.C v.2.3 - 30.Nov.2009
+ ===========================================================================
+
+ ITU-T STL BASIC OPERATORS
+
+ ENHANCED 16-BIT & 32-BIT ARITHMETIC OPERATORS
+
+ History:
+ 07 Nov 04 v2.0 Incorporation of new 32-bit / 40-bit / control
+ operators for the ITU-T Standard Tool Library as
+ described in Geneva, 20-30 January 2004 WP 3/16 Q10/16
+ TD 11 document and subsequent discussions on the
+ wp3audio@yahoogroups.com email reflector.
+
+ ============================================================================
+*/
+
+
+/*****************************************************************************
+ *
+ * Enhanced 16/32 bit operators :
+ * s_max()
+ * s_min()
+ * L_max()
+ * L_min()
+ * shl_r()
+ * L_shl_r()
+ * L_mac0()
+ * L_mult0()
+ * L_msu0()
+ * s_and()
+ * s_or()
+ * s_xor()
+ * L_and()
+ * L_or()
+ * lshl()
+ * lshr()
+ * L_lshl()
+ * L_lshr()
+ * rotr()
+ * rotl()
+ * L_rotr()
+ * L_rotl()
+ *
+ *****************************************************************************/
+
+
+/*****************************************************************************
+ *
+ * Include-Files
+ *
+ *****************************************************************************/
+
+#include
+#include
+#include "stl.h"
+
+#define WMC_TOOL_SKIP
+
+/*****************************************************************************
+ *
+ * Constants and Globals
+ *
+ *****************************************************************************/
+
+
+/*****************************************************************************
+ *
+ * Functions
+ *
+ *****************************************************************************/
+
+
+/*****************************************************************************
+ *
+ * Function Name : lshl
+ *
+ * Purpose :
+ *
+ * Logically shifts left var1 by var2 positions.
+ * - If var2 is negative, var1 is shifted to the LSBits by (-var2)
+ * positions with insertion of 0 at the MSBit.
+ * - If var2 is positive, var1 is shifted to the MSBits by (var2)
+ * positions.
+ *
+ * Complexity weight : 1
+ *
+ * Inputs :
+ *
+ * var1 16 bit short signed integer (Word16) whose value falls in
+ * the range 0xffff 8000 <= var1 <= 0x0000 7fff.
+ *
+ * var2 16 bit short signed integer (Word16) whose value falls in
+ * the range 0xffff 8000 <= var2 <= 0x0000 7fff.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value:
+ *
+ * var_out 16 bit short signed integer (Word16) whose value falls in
+ * the range 0xffff 8000 <= var_out <= 0x0000 7fff.
+ *
+ *****************************************************************************/
+Word16 lshl( Word16 var1, Word16 var2 )
+{
+ Word16 var_out = 0;
+
+ if ( var2 < 0 )
+ {
+ var2 = -var2;
+ var_out = lshr( var1, var2 );
+#ifdef WMOPS
+ multiCounter[currCounter].lshr--;
+#endif
+ }
+ else
+ {
+ if ( var2 == 0 || var1 == 0 )
+ {
+ var_out = var1;
+ }
+ else if ( var2 >= 16 )
+ {
+ var_out = 0;
+ }
+ else
+ {
+ var_out = var1 << var2;
+ }
+ }
+
+#ifdef WMOPS
+ multiCounter[currCounter].lshl++;
+#endif
+
+ BASOP_CHECK();
+
+
+ return ( var_out );
+}
+
+/*****************************************************************************
+ *
+ * Function Name : lshr
+ *
+ * Purpose :
+ *
+ * Logically shifts right var1 by var2 positions.
+ * - If var2 is positive, var1 is shifted to the LSBits by (var2)
+ * positions with insertion of 0 at the MSBit.
+ * - If var2 is negative, var1 is shifted to the MSBits by (-var2)
+ * positions.
+ *
+ * Complexity weight : 1
+ *
+ * Inputs :
+ *
+ * var1 16 bit short signed integer (Word16) whose value falls in
+ * the range 0xffff 8000 <= var1 <= 0x0000 7fff.
+ *
+ * var2 16 bit short signed integer (Word16) whose value falls in
+ * the range 0xffff 8000 <= var2 <= 0x0000 7fff.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value:
+ *
+ * var_out 16 bit short signed integer (Word16) whose value falls in
+ * the range 0xffff 8000 <= var_out <= 0x0000 7fff.
+ *
+ *****************************************************************************/
+Word16 lshr( Word16 var1, Word16 var2 )
+{
+ Word16 var_out;
+
+ if ( var2 < 0 )
+ {
+ var2 = -var2;
+ var_out = lshl( var1, var2 );
+#ifdef WMOPS
+ multiCounter[currCounter].lshl--;
+#endif
+ }
+ else
+ {
+ if ( var2 == 0 || var1 == 0 )
+ {
+ var_out = var1;
+ }
+ else if ( var2 >= 16 )
+ {
+ var_out = 0;
+ }
+ else
+ {
+ var_out = var1 >> 1;
+ var_out = var_out & 0x7fff;
+ var_out = var_out >> ( var2 - 1 );
+ }
+ }
+
+#ifdef WMOPS
+ multiCounter[currCounter].lshr++;
+#endif
+
+ BASOP_CHECK();
+
+
+ return ( var_out );
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : L_lshl
+ *
+ * Purpose :
+ *
+ * Logically shifts left L_var1 by var2 positions.
+ * - If var2 is negative, L_var1 is shifted to the LSBits by (-var2)
+ * positions with insertion of 0 at the MSBit.
+ * - If var2 is positive, L_var1 is shifted to the MSBits by (var2)
+ * positions.
+ *
+ * Complexity weight : 1
+ *
+ * Inputs :
+ *
+ * L_var1 32 bit long signed integer (Word32) whose value falls in
+ * the range 0x8000 0000 <= L_var1 <= 0x7fff ffff.
+ *
+ * var2 16 bit short signed integer (Word16) whose value falls in
+ * the range 0xffff 8000 <= var2 <= 0x0000 7fff.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value:
+ *
+ * L_var_out 32 bit long signed integer (Word32) whose value falls in
+ * the range 0x8000 0000 <= L_var_out <= 0x7fff ffff.
+ *
+ *****************************************************************************/
+Word32 L_lshl( Word32 L_var1, Word16 var2 )
+{
+ Word32 L_var_out = 0;
+
+ if ( var2 < 0 )
+ {
+ var2 = -var2;
+ L_var_out = L_lshr( L_var1, var2 );
+#ifdef WMOPS
+ multiCounter[currCounter].L_lshr--;
+#endif
+ }
+ else
+ {
+ if ( var2 == 0 || L_var1 == 0 )
+ {
+ L_var_out = L_var1;
+ }
+ else if ( var2 >= 32 )
+ {
+ L_var_out = 0;
+ }
+ else
+ {
+ L_var_out = L_var1 << var2;
+ }
+ }
+
+#ifdef WMOPS
+ multiCounter[currCounter].L_lshl++;
+#endif
+
+ BASOP_CHECK();
+
+ return ( L_var_out );
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : L_lshr
+ *
+ * Purpose :
+ *
+ * Logically shifts right L_var1 by var2 positions.
+ * - If var2 is positive, L_var1 is shifted to the LSBits by (var2)
+ * positions with insertion of 0 at the MSBit.
+ * - If var2 is negative, L_var1 is shifted to the MSBits by (-var2)
+ * positions.
+ *
+ * Complexity weight : 1
+ *
+ * Inputs :
+ *
+ * L_var1 32 bit long signed integer (Word32) whose value falls in
+ * the range 0x8000 0000 <= L_var1 <= 0x7fff ffff.
+ *
+ * var2 16 bit short signed integer (Word16) whose value falls in
+ * the range 0xffff 8000 <= var2 <= 0x0000 7fff.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value:
+ *
+ * L_var_out 32 bit long signed integer (Word32) whose value falls in
+ * the range 0x8000 0000 <= L_var_out <= 0x7fff ffff.
+ *
+ *****************************************************************************/
+Word32 L_lshr( Word32 L_var1, Word16 var2 )
+{
+ Word32 L_var_out;
+
+ if ( var2 < 0 )
+ {
+ var2 = -var2;
+ L_var_out = L_lshl( L_var1, var2 );
+#ifdef WMOPS
+ multiCounter[currCounter].L_lshl--;
+#endif
+ }
+ else
+ {
+ if ( var2 == 0 || L_var1 == 0 )
+ {
+ L_var_out = L_var1;
+ }
+ else if ( var2 >= 32 )
+ {
+ L_var_out = 0;
+ }
+ else
+ {
+ L_var_out = L_var1 >> 1;
+ L_var_out = L_var_out & 0x7fffffff;
+ L_var_out = L_var_out >> ( var2 - 1 );
+ }
+ }
+
+#ifdef WMOPS
+ multiCounter[currCounter].L_lshr++;
+#endif
+
+ BASOP_CHECK();
+
+
+ return ( L_var_out );
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : shl_r
+ *
+ * Purpose :
+ *
+ * Identical to shl( var1, var2) but with rounding. Saturates the result
+ * in case of underflows or overflows.
+ *
+ * Complexity weight : 3
+ *
+ * Inputs :
+ *
+ * var1 16 bit short signed integer (Word16) whose value falls in
+ * the range : 0xffff 8000 <= var1 <= 0x0000 7fff.
+ *
+ * var2 16 bit short signed integer (Word16) whose value falls in
+ * the range : 0xffff 8000 <= var2 <= 0x0000 7fff.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value :
+ *
+ * var_out 16 bit short signed integer (Word16) whose value falls in
+ * the range : 0xffff 8000 <= var_out <= 0x0000 7fff.
+ *
+ *****************************************************************************/
+Word16 shl_r( Word16 var1, Word16 var2 )
+{
+ Word16 var_out;
+
+ if ( var2 >= 0 )
+ {
+ var_out = shl( var1, var2 );
+#ifdef WMOPS
+ multiCounter[currCounter].shl--;
+#endif
+ }
+ else
+ {
+ var2 = -var2;
+ var_out = shr_r( var1, var2 );
+#ifdef WMOPS
+ multiCounter[currCounter].shr_r--;
+#endif
+ }
+
+#ifdef WMOPS
+ multiCounter[currCounter].shl_r++;
+#endif
+
+ return ( var_out );
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : L_shl_r
+ *
+ * Purpose :
+ *
+ * Same as L_shl( var1, var2) but with rounding. Saturates the result in
+ * case of underflows or overflows.
+ *
+ * Complexity weight : 3
+ *
+ * Inputs :
+ *
+ * L_var1 32 bit long signed integer (Word32) whose value falls in
+ * the range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.
+ *
+ * var2 16 bit short signed integer (Word16) whose value falls in
+ * the range : 0xffff 8000 <= var2 <= 0x0000 7fff.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value :
+ *
+ * L_var_out 32 bit long signed integer (Word32) whose value falls in
+ * the range : 0x8000 0000 <= var_out <= 0x7fff ffff.
+ *
+ *****************************************************************************/
+Word32 L_shl_r( Word32 L_var1, Word16 var2 )
+{
+ Word32 var_out;
+
+ if ( var2 >= 0 )
+ {
+ var_out = L_shl( L_var1, var2 );
+#ifdef WMOPS
+ multiCounter[currCounter].L_shl--;
+#endif
+ }
+ else
+ {
+ var2 = -var2;
+ var_out = L_shr_r( L_var1, var2 );
+#ifdef WMOPS
+ multiCounter[currCounter].L_shr_r--;
+#endif
+ }
+
+#ifdef WMOPS
+ multiCounter[currCounter].L_shl_r++;
+#endif
+
+ return ( var_out );
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : rotr
+ *
+ * Purpose :
+ *
+ * Performs a 16-bit logical rotation of var1 by 1 bit to the LSBits. The
+ * MSBit is set to var2 bit 0. The LSBit of var1 is kept in *var3 bit 0.
+ *
+ * Complexity weight : 3
+ *
+ * Inputs :
+ *
+ * var1 16 bit short signed integer (Word16) whose value falls in
+ * the range : 0xffff 8000 <= var1 <= 0x0000 7fff.
+ *
+ * var2 16 bit short signed integer (Word16) whose value must be 0
+ * or 1.
+ *
+ * Outputs :
+ *
+ * *var3 Points on a 16 bit short signed integer (Word16) whose
+ * value will be 0 or 1.
+ *
+ * Return Value :
+ *
+ * var_out 16 bit short signed integer (Word16) whose value falls in
+ * the range : 0xffff 8000 <= var_out <= 0x0000 7fff.
+ *
+ *****************************************************************************/
+Word16 rotr( Word16 var1, Word16 var2, Word16 *var3 )
+{
+ Word16 var_out;
+
+ *var3 = s_and( var1, 0x1 );
+ var_out = s_or( lshr( var1, 1 ), lshl( var2, 15 ) );
+
+#ifdef WMOPS
+ multiCounter[currCounter].s_and--;
+ multiCounter[currCounter].lshl--;
+ multiCounter[currCounter].lshr--;
+ multiCounter[currCounter].s_or--;
+ multiCounter[currCounter].rotr++;
+#endif
+
+ return ( var_out );
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : rotl
+ *
+ * Purpose :
+ *
+ * Performs a 16-bit logical rotation of var1 by 1 bit to the MSBits. The
+ * LSBit is set to var2 bit 0. The MSBit of var1 is kept in *var3 bit 0.
+ *
+ * Complexity weight : 3
+ *
+ * Inputs :
+ *
+ * var1 16 bit short signed integer (Word16) whose value falls in
+ * the range : 0xffff 8000 <= var1 <= 0x0000 7fff.
+ *
+ * var2 16 bit short signed integer (Word16) whose value must be 0
+ * or 1.
+ *
+ * Outputs :
+ *
+ * *var3 Points on a 16 bit short signed integer (Word16) whose
+ * value will be 0 or 1.
+ *
+ * Return Value :
+ *
+ * var_out 16 bit short signed integer (Word16) whose value falls in
+ * the range : 0xffff 8000 <= var_out <= 0x0000 7fff.
+ *
+ *****************************************************************************/
+Word16 rotl( Word16 var1, Word16 var2, Word16 *var3 )
+{
+ Word16 var_out;
+
+ *var3 = lshr( var1, 15 );
+
+ var_out = s_or( lshl( var1, 1 ), s_and( var2, 0x1 ) );
+
+#ifdef WMOPS
+ multiCounter[currCounter].lshr--;
+ multiCounter[currCounter].s_and--;
+ multiCounter[currCounter].lshl--;
+ multiCounter[currCounter].s_or--;
+ multiCounter[currCounter].rotl++;
+#endif
+
+ return ( var_out );
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : L_rotr
+ *
+ * Purpose :
+ *
+ * Performs a 32-bit logical rotation of L_var1 by 1 bit to the LSBits. The
+ * MSBit is set to var2 bit 0. The LSBit of L_var1 is kept in *var3 bit 0.
+ *
+ * Complexity weight : 3
+ *
+ * Inputs :
+ *
+ * L_var1 32 bit long signed integer (Word32) whose value falls in
+ * the range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.
+ *
+ * var2 16 bit short signed integer (Word16) whose value must be 0
+ * or 1.
+ *
+ * Outputs :
+ *
+ * *var3 Points on a 16 bit short signed integer (Word16) whose
+ * value will be 0 or 1.
+ *
+ * Return Value :
+ *
+ * L_var_out 32 bit long signed integer (Word32) whose value falls in
+ * the range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.
+ *
+ *****************************************************************************/
+Word32 L_rotr( Word32 L_var1, Word16 var2, Word16 *var3 )
+{
+ Word32 L_var_out;
+
+ *var3 = s_and( extract_l( L_var1 ), 0x1 );
+
+ L_var_out = L_or( L_lshr( L_var1, 1 ), L_lshl( L_deposit_l( var2 ), 31 ) );
+
+#ifdef WMOPS
+ multiCounter[currCounter].extract_l--;
+ multiCounter[currCounter].s_and--;
+ multiCounter[currCounter].L_deposit_l--;
+ multiCounter[currCounter].L_lshl--;
+ multiCounter[currCounter].L_lshr--;
+ multiCounter[currCounter].L_or--;
+ multiCounter[currCounter].L_rotr++;
+#endif
+
+ return ( L_var_out );
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : L_rotl
+ *
+ * Purpose :
+ *
+ * Performs a 32-bit logical rotation of L_var1 by 1 bit to the MSBits. The
+ * LSBit is set to var2 bit 0. The MSBit of L_var1 is kept in *var3 bit 0.
+ *
+ * Complexity weight : 3
+ *
+ * Inputs :
+ *
+ * L_var1 32 bit long signed integer (Word32) whose value falls in
+ * the range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.
+ *
+ * var2 16 bit short signed integer (Word16) whose value must be 0
+ * or 1.
+ *
+ * Outputs :
+ *
+ * *var3 Points on a 16 bit short signed integer (Word16) whose
+ * value will be 0 or 1.
+ *
+ * Return Value :
+ *
+ * L_var_out 32 bit long signed integer (Word32) whose value falls in
+ * the range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.
+ *
+ *****************************************************************************/
+Word32 L_rotl( Word32 L_var1, Word16 var2, Word16 *var3 )
+{
+ Word32 L_var_out;
+
+ *var3 = extract_l( L_lshr( L_var1, 31 ) );
+
+ L_var_out = L_or( L_lshl( L_var1, 1 ), L_deposit_l( s_and( var2, 0x1 ) ) );
+
+#ifdef WMOPS
+ multiCounter[currCounter].L_lshr--;
+ multiCounter[currCounter].extract_l--;
+ multiCounter[currCounter].s_and--;
+ multiCounter[currCounter].L_deposit_l--;
+ multiCounter[currCounter].L_lshl--;
+ multiCounter[currCounter].L_or--;
+ multiCounter[currCounter].L_rotl++;
+#endif
+
+ return ( L_var_out );
+}
+
+#undef WMC_TOOL_SKIP
diff --git a/lib_com/enh1632.h b/lib_com/enh1632.h
new file mode 100644
index 0000000000000000000000000000000000000000..d21bf1157d58885bdf4ee78405996e37b026440e
--- /dev/null
+++ b/lib_com/enh1632.h
@@ -0,0 +1,538 @@
+/******************************************************************************************************
+
+ (C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
+ Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
+ Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
+ Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
+ contributors to this repository. All Rights Reserved.
+
+ This software is protected by copyright law and by international treaties.
+ The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
+ Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
+ Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
+ Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
+ contributors to this repository retain full ownership rights in their respective contributions in
+ the software. This notice grants no license of any kind, including but not limited to patent
+ license, nor is any license granted by implication, estoppel or otherwise.
+
+ Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
+ contributions.
+
+ This software is provided "AS IS", without any express or implied warranties. The software is in the
+ development stage. It is intended exclusively for experts who have experience with such software and
+ solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
+ and fitness for a particular purpose are hereby disclaimed and excluded.
+
+ Any dispute, controversy or claim arising under or in relation to providing this software shall be
+ submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
+ accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
+ the United Nations Convention on Contracts on the International Sales of Goods.
+
+*******************************************************************************************************/
+
+/*
+ ===========================================================================
+ File: ENH1632.H v.2.3 - 30.Nov.2009
+ ===========================================================================
+
+ ITU-T STL BASIC OPERATORS
+
+ ENHANCED 16-BIT & 32-BIT ARITHMETIC OPERATORS
+
+ History:
+ 07 Nov 04 v2.0 Incorporation of new 32-bit / 40-bit / control
+ operators for the ITU-T Standard Tool Library as
+ described in Geneva, 20-30 January 2004 WP 3/16 Q10/16
+ TD 11 document and subsequent discussions on the
+ wp3audio@yahoogroups.com email reflector.
+ March 06 v2.1 Changed to improve portability.
+ Some counters incrementations were missing (s_and,
+ s_or, s_xor).
+ 30 Nov 09 v2.3 saturate() removed
+
+ ============================================================================
+*/
+
+
+#ifndef _ENH1632_H
+#define _ENH1632_H
+
+
+/*****************************************************************************
+ *
+ * Constants and Globals
+ *
+ *****************************************************************************/
+
+
+#include "stl.h"
+
+
+/*****************************************************************************
+ *
+ * Prototypes for enhanced 16/32 bit arithmetic operators
+ *
+ *****************************************************************************/
+Word16 shl_r( Word16 var1, Word16 var2 );
+Word32 L_shl_r( Word32 L_var1, Word16 var2 );
+
+
+Word16 lshl( Word16 var1, Word16 var2 );
+Word16 lshr( Word16 var1, Word16 var2 );
+Word32 L_lshl( Word32 L_var1, Word16 var2 );
+Word32 L_lshr( Word32 L_var1, Word16 var2 );
+
+Word16 rotr( Word16 var1, Word16 var2, Word16 *var3 );
+Word16 rotl( Word16 var1, Word16 var2, Word16 *var3 );
+Word32 L_rotr( Word32 var1, Word16 var2, Word16 *var3 );
+Word32 L_rotl( Word32 var1, Word16 var2, Word16 *var3 );
+
+
+/*****************************************************************************
+ *
+ * Functions
+ *
+ *****************************************************************************/
+
+/*****************************************************************************
+ *
+ * Function Name : s_max
+ *
+ * Purpose :
+ *
+ * Compares var1 and var2 and returns the maximum value.
+ *
+ * Complexity weight : 1
+ *
+ * Inputs :
+ *
+ * var1 16 bit short signed integer (Word16) whose value falls in
+ * the range : 0x8000 <= var1 <= 0x7fff.
+ *
+ * var2 16 bit short signed integer (Word16) whose value falls in
+ * the range : 0x8000 <= var2 <= 0x7fff.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value :
+ *
+ * var_out 16 bit short signed integer (Word16) whose value falls in
+ * the range : 0x8000 <= L_var_out <= 0x7fff.
+ *
+ *****************************************************************************/
+static __inline Word16 s_max( Word16 var1, Word16 var2 )
+{
+ Word16 var_out;
+
+ if ( var1 >= var2 )
+ var_out = var1;
+ else
+ var_out = var2;
+
+#ifdef WMOPS
+ multiCounter[currCounter].s_max++;
+#endif
+
+ return ( var_out );
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : s_min
+ *
+ * Purpose :
+ *
+ * Compares var1 and var2 and returns the minimum value.
+ *
+ * Complexity weight : 1
+ *
+ * Inputs :
+ *
+ * var1 16 bit short signed integer (Word16) whose value falls in
+ * the range : 0x8000 <= var1 <= 0x7fff.
+ *
+ * var2 16 bit short signed integer (Word16) whose value falls in
+ * the range : 0x8000 <= var2 <= 0x7fff.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value :
+ *
+ * var_out 16 bit short signed integer (Word16) whose value falls in
+ * the range : 0x8000 <= var_out <= 0x7fff.
+ *
+ *****************************************************************************/
+static __inline Word16 s_min( Word16 var1, Word16 var2 )
+{
+ Word16 var_out;
+
+ if ( var1 <= var2 )
+ var_out = var1;
+ else
+ var_out = var2;
+
+#ifdef WMOPS
+ multiCounter[currCounter].s_min++;
+#endif
+
+ return ( var_out );
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : L_max
+ *
+ * Purpose :
+ *
+ * Compares L_var1 and L_var2 and returns the maximum value.
+ *
+ * Complexity weight : 1
+ *
+ * Inputs :
+ *
+ * L_var1 32 bit long signed integer (Word32) whose value falls in the
+ * range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.
+ *
+ * L_var2 32 bit long signed integer (Word32) whose value falls in the
+ * range : 0x8000 0000 <= L_var2 <= 0x7fff ffff.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value :
+ *
+ * L_var_out 32 bit long signed integer (Word32) whose value falls in the
+ * range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.
+ *
+ *****************************************************************************/
+static __inline Word32 L_max( Word32 L_var1, Word32 L_var2 )
+{
+ Word32 L_var_out;
+
+ if ( L_var1 >= L_var2 )
+ L_var_out = L_var1;
+ else
+ L_var_out = L_var2;
+
+#ifdef WMOPS
+ multiCounter[currCounter].L_max++;
+#endif
+
+ return ( L_var_out );
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : L_min
+ *
+ * Purpose :
+ *
+ * Compares L_var1 and L_var2 and returns the minimum value.
+ *
+ * Complexity weight : 1
+ *
+ * Inputs :
+ *
+ * L_var1 32 bit long signed integer (Word32) whose value falls in the
+ * range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.
+ *
+ * L_var2 32 bit long signed integer (Word32) whose value falls in the
+ * range : 0x8000 0000 <= L_var2 <= 0x7fff ffff.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value :
+ *
+ * L_var_out 32 bit long signed integer (Word32) whose value falls in the
+ * range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.
+ *
+ *****************************************************************************/
+static __inline Word32 L_min( Word32 L_var1, Word32 L_var2 )
+{
+ Word32 L_var_out;
+
+ if ( L_var1 <= L_var2 )
+ L_var_out = L_var1;
+ else
+ L_var_out = L_var2;
+
+#ifdef WMOPS
+ multiCounter[currCounter].L_min++;
+#endif
+
+ return ( L_var_out );
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : s_and
+ *
+ * Purpose :
+ *
+ * Performs logical AND of the two 16 bit input variables.
+ * var_out = var1 & var2
+ *
+ * Complexity weight : 1
+ *
+ * Inputs :
+ *
+ * var1 16 bit short signed integer (Word16) whose value
+ * falls in the range 0xffff 8000 <= var1 <= 0x0000 7fff.
+ *
+ * var2 16 bit short signed integer (Word16) whose value
+ * falls in the range 0xffff 8000 <= var2 <= 0x0000 7fff.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value :
+ *
+ * var_out 16 bit short signed integer (Word16) whose value
+ * falls in the range 0xffff 8000 <= var_out <= 0x0000 7fff.
+ *
+ *****************************************************************************/
+static __inline Word16 s_and( Word16 var1, Word16 var2 )
+{
+ Word16 var_out;
+
+ var_out = var1 & var2;
+
+#ifdef WMOPS
+ multiCounter[currCounter].s_and++;
+#endif
+
+ return ( var_out );
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : L_and
+ *
+ * Purpose :
+ *
+ * Performs logical AND of the two 32 bit input variables.
+ * L_var_out = L_var1 & L_var2
+ *
+ * Complexity weight : 1
+ *
+ * Inputs :
+ *
+ * L_var1 32 bit long signed integer (Word32) whose value
+ * falls in the range 0x8000 0000 <= L_var1 <= 0x7fff ffff.
+ *
+ * L_var2 32 bit long signed integer (Word32) whose value
+ * falls in the range 0x8000 0000 <= L_var2 <= 0x7fff ffff.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value :
+ *
+ * L_var_out 32 bit long signed integer (Word32) whose value
+ * falls in the range 0x8000 0000 <= L_var_out <= 0x7fff ffff.
+ *
+ *****************************************************************************/
+static __inline Word32 L_and( Word32 L_var1, Word32 L_var2 )
+{
+ Word32 L_var_out;
+
+ L_var_out = L_var1 & L_var2;
+
+#ifdef WMOPS
+ multiCounter[currCounter].L_and++;
+#endif
+
+ return ( L_var_out );
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : s_or
+ *
+ * Purpose :
+ *
+ * Performs logical OR of the two 16 bit input variables.
+ * var_out = var1 | var2
+ *
+ * Complexity weight : 1
+ *
+ * Inputs :
+ *
+ * var1 16 bit short signed integer (Word16) whose value
+ * falls in the range 0xffff 8000 <= var1 <= 0x0000 7fff.
+ *
+ * var2 16 bit short signed integer (Word16) whose value
+ * falls in the range 0xffff 8000 <= var2 <= 0x0000 7fff.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value :
+ *
+ * var_out 16 bit short signed integer (Word16) whose value
+ * falls in the range 0xffff 8000 <= var_out <= 0x0000 7fff.
+ *
+ *****************************************************************************/
+static __inline Word16 s_or( Word16 var1, Word16 var2 )
+{
+ Word16 var_out;
+
+ var_out = var1 | var2;
+
+#ifdef WMOPS
+ multiCounter[currCounter].s_or++;
+#endif
+
+ return ( var_out );
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : L_or
+ *
+ * Purpose :
+ *
+ * Performs logical OR of the two 32 bit input variables.
+ * L_var_out = L_var1 | L_var2
+ *
+ * Complexity weight : 1
+ *
+ * Inputs :
+ *
+ * L_var1 32 bit long signed integer (Word32) whose value
+ * falls in the range 0x8000 0000 <= L_var1 <= 0x7fff ffff.
+ *
+ * L_var2 32 bit long signed integer (Word32) whose value
+ * falls in the range 0x8000 0000 <= L_var2 <= 0x7fff ffff.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value :
+ *
+ * L_var_out 32 bit long signed integer (Word32) whose value
+ * falls in the range 0x8000 0000 <= L_var_out <= 0x7fff ffff.
+ *
+ *****************************************************************************/
+static __inline Word32 L_or( Word32 L_var1, Word32 L_var2 )
+{
+
+ Word32 L_var_out;
+
+ L_var_out = L_var1 | L_var2;
+
+#ifdef WMOPS
+ multiCounter[currCounter].L_or++;
+#endif
+
+ return ( L_var_out );
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : s_xor
+ *
+ * Purpose :
+ *
+ * Performs logical XOR of the two 16 bit input variables.
+ * var_out = var1 ^ var2
+ *
+ * Complexity weight : 1
+ *
+ * Inputs :
+ *
+ * var1 16 bit short signed integer (Word16) whose value
+ * falls in the range 0xffff 8000 <= var1 <= 0x0000 7fff.
+ *
+ * var2 16 bit short signed integer (Word16) whose value
+ * falls in the range 0xffff 8000 <= var2 <= 0x0000 7fff.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value :
+ *
+ * var_out 16 bit short signed integer (Word16) whose value
+ * falls in the range 0xffff 8000 <= var_out <= 0x0000 7fff.
+ *
+ *****************************************************************************/
+static __inline Word16 s_xor( Word16 var1, Word16 var2 )
+{
+ Word16 var_out;
+
+ var_out = var1 ^ var2;
+
+#ifdef WMOPS
+ multiCounter[currCounter].s_xor++;
+#endif
+
+ return ( var_out );
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : L_xor
+ *
+ * Purpose :
+ *
+ * Performs logical OR of the two 32 bit input variables.
+ * L_var_out = L_var1 ^ L_var2
+ *
+ * Complexity weight : 1
+ *
+ * Inputs :
+ *
+ * L_var1 32 bit long signed integer (Word32) whose value
+ * falls in the range 0x8000 0000 <= L_var1 <= 0x7fff ffff.
+ *
+ * L_var2 32 bit long signed integer (Word32) whose value
+ * falls in the range 0x8000 0000 <= L_var2 <= 0x7fff ffff.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value :
+ *
+ * L_var_out 32 bit long signed integer (Word32) whose value
+ * falls in the range 0x8000 0000 <= L_var_out <= 0x7fff ffff.
+ *
+ *****************************************************************************/
+static __inline Word32 L_xor( Word32 L_var1, Word32 L_var2 )
+{
+ Word32 L_var_out;
+
+ L_var_out = L_var1 ^ L_var2;
+
+#ifdef WMOPS
+ multiCounter[currCounter].L_xor++;
+#endif
+
+ return ( L_var_out );
+}
+
+
+#endif /*_ENH1632_H*/
+
+/* end of file */
diff --git a/lib_com/enh40.c b/lib_com/enh40.c
new file mode 100644
index 0000000000000000000000000000000000000000..929e3a950652d6fd12162aadbaa2e7a3c2ffdb57
--- /dev/null
+++ b/lib_com/enh40.c
@@ -0,0 +1,1395 @@
+/******************************************************************************************************
+
+ (C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
+ Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
+ Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
+ Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
+ contributors to this repository. All Rights Reserved.
+
+ This software is protected by copyright law and by international treaties.
+ The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
+ Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
+ Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
+ Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
+ contributors to this repository retain full ownership rights in their respective contributions in
+ the software. This notice grants no license of any kind, including but not limited to patent
+ license, nor is any license granted by implication, estoppel or otherwise.
+
+ Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
+ contributions.
+
+ This software is provided "AS IS", without any express or implied warranties. The software is in the
+ development stage. It is intended exclusively for experts who have experience with such software and
+ solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
+ and fitness for a particular purpose are hereby disclaimed and excluded.
+
+ Any dispute, controversy or claim arising under or in relation to providing this software shall be
+ submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
+ accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
+ the United Nations Convention on Contracts on the International Sales of Goods.
+
+*******************************************************************************************************/
+
+/*
+ ===========================================================================
+ File: ENH40.C v.2.3 - 30.Nov.2009
+ ===========================================================================
+
+ ITU-T STL BASIC OPERATORS
+
+ 40-BIT ARITHMETIC OPERATORS
+
+ History:
+ 07 Nov 04 v2.0 Incorporation of new 32-bit / 40-bit / control
+ operators for the ITU-T Standard Tool Library as
+ described in Geneva, 20-30 January 2004 WP 3/16 Q10/16
+ TD 11 document and subsequent discussions on the
+ wp3audio@yahoogroups.com email reflector.
+
+ ============================================================================
+*/
+
+
+/*****************************************************************************
+ *
+ * Enhanced 40 bit operators :
+ *
+ * L40_add()
+ * L40_sub()
+ * L40_abs()
+ * L40_negate()
+ * L40_max()
+ * L40_min()
+ * L40_shr()
+ * L40_shr_r()
+ * L40_shl()
+ * L40_shl_r()
+ * norm_L40()
+ * L40_mult()
+ * L40_mac()
+ * L40_msu()
+ * mac_r40()
+ * msu_r40()
+ * Mpy_32_16_ss()
+ * Mpy_32_32_ss()
+ * L40_lshl()
+ * L40_lshr()
+ * L40_round()
+ * L_saturate40()
+ * L40_set()
+ * Extract40_H()
+ * Extract40_L()
+ * L_Extract40()
+ * L40_deposit_h()
+ * L40_deposit_l()
+ * L40_deposit32()
+ *
+ *****************************************************************************/
+
+
+/*****************************************************************************
+ *
+ * Include-Files
+ *
+ *****************************************************************************/
+
+#include
+#include
+#include "stl.h"
+#ifdef BASOP_NOGLOB
+#include
+#endif /* BASOP_NOGLOB */
+
+#define WMC_TOOL_SKIP
+
+#ifdef _MSC_VER
+#pragma warning( disable : 4310 )
+#endif
+
+/*****************************************************************************
+ *
+ * Local Functions
+ *
+ *****************************************************************************/
+
+
+/*****************************************************************************
+ *
+ * Constants and Globals
+ *
+ *****************************************************************************/
+
+
+/*****************************************************************************
+ *
+ * Functions
+ *
+ *****************************************************************************/
+
+/*****************************************************************************
+ *
+ * Function Name : L40_shl
+ *
+ * Purpose :
+ *
+ * Arithmetically shifts left L40_var1 by var2 positions.
+ * - If var2 is negative, L40_var1 is shifted to the LSBits by (-var2)
+ * positions with extension of the sign bit.
+ * - If var2 is positive, L40_var1 is shifted to the MSBits by (var2)
+ * positions.
+ * Calls the macro L40_UNDERFLOW_OCCURED() in case of underflow on 40-bit.
+ * Calls the macro L40_OVERFLOW_OCCURED() in case of overflow on 40-bit.
+ *
+ * Complexity weight : 1
+ *
+ * Inputs :
+ *
+ * L40_var1 40 bit long signed integer (Word40) whose value falls in the
+ * range : MIN_40 <= L40_var1 <= MAX_40.
+ *
+ * var2 16 bit short signed integer (Word16) whose value falls in
+ * the range : MIN_16 <= var2 <= MAX_16.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value :
+ *
+ * L40_var_out 40 bit long signed integer (Word40) whose value falls in
+ * the range : MIN_40 <= L40_var_out <= MAX_40.
+ *
+ *****************************************************************************/
+#ifndef BASOP_NOGLOB
+Word40 L40_shl( Word40 L40_var1, Word16 var2 )
+#else /* BASOP_NOGLOB */
+Word40 L40_shl_o( Word40 L40_var1, Word16 var2, Flag *Overflow )
+#endif /* BASOP_NOGLOB */
+{
+
+ Word40 L40_var_out;
+ Word40 L40_constant;
+
+#if defined( _MSC_VER ) && ( _MSC_VER <= 1200 )
+ L40_constant = L40_set( 0xc000000000 );
+#else
+ L40_constant = L40_set( 0xc000000000LL );
+#endif
+
+ if ( var2 < 0 )
+ {
+ var2 = -var2;
+ L40_var_out = L40_shr( L40_var1, var2 );
+ }
+
+ else
+ {
+ L40_var_out = L40_var1;
+
+ for ( ; var2 > 0; var2-- )
+ {
+#if defined( _MSC_VER ) && ( _MSC_VER <= 1200 )
+ if ( L40_var_out > 0x003fffffffff )
+#else
+ if ( L40_var_out > 0x003fffffffffLL )
+#endif
+ {
+#ifndef BASOP_NOGLOB
+ Overflow = 1;
+ exit( 1 );
+ /* L40_var_out = L40_OVERFLOW_OCCURED( L40_var_out); */
+#else /* BASOP_NOGLOB */
+ *Overflow = 1;
+ L40_var_out = MAX_40;
+#endif /* BASOP_NOGLOB */
+ break;
+ }
+
+ else if ( L40_var_out < L40_constant )
+ {
+#ifndef BASOP_NOGLOB
+ Overflow = 1;
+ exit( 2 );
+ /* L40_var_out = L40_UNDERFLOW_OCCURED( L40_var_out); */
+#else /* BASOP_NOGLOB */
+ *Overflow = 1;
+ L40_var_out = MIN_40;
+#endif /* BASOP_NOGLOB */
+ break;
+ }
+
+ else
+ {
+ L40_var_out = L40_var_out << 1;
+ }
+ }
+ }
+
+#ifdef WMOPS
+ multiCounter[currCounter].L40_shl++;
+#endif
+
+ BASOP_CHECK();
+
+ return ( L40_var_out );
+}
+
+#ifdef BASOP_NOGLOB
+Word40 L40_shl( Word40 L40_var1, Word16 var2 )
+{
+
+ Word40 L40_var_out;
+ Word40 L40_constant;
+
+#if defined( _MSC_VER ) && ( _MSC_VER <= 1200 )
+ L40_constant = L40_set( 0xc000000000 );
+#else
+ L40_constant = L40_set( 0xc000000000LL );
+#endif
+
+ if ( var2 < 0 )
+ {
+ var2 = -var2;
+ L40_var_out = L40_shr( L40_var1, var2 );
+ }
+
+ else
+ {
+ L40_var_out = L40_var1;
+
+ for ( ; var2 > 0; var2-- )
+ {
+#if defined( _MSC_VER ) && ( _MSC_VER <= 1200 )
+ if ( L40_var_out > 0x003fffffffff )
+#else
+ if ( L40_var_out > 0x003fffffffffLL )
+#endif
+ {
+ assert( 0 );
+ L40_var_out = MAX_40;
+ break;
+ }
+
+ else if ( L40_var_out < L40_constant )
+ {
+ assert( 0 );
+ L40_var_out = MIN_40;
+ break;
+ }
+
+ else
+ {
+ L40_var_out = L40_var_out << 1;
+ }
+ }
+ }
+
+#ifdef WMOPS
+ multiCounter[currCounter].L40_shl++;
+#endif
+
+ BASOP_CHECK();
+
+
+ return ( L40_var_out );
+}
+#endif /* BASOP_NOGLOB */
+
+/*****************************************************************************
+ *
+ * Function Name : L40_shr
+ *
+ * Purpose :
+ *
+ * Arithmetically shifts right L40_var1 by var2 positions.
+ * - If var2 is positive, L40_var1 is shifted to the LSBits by (var2)
+ * positions with extension of the sign bit.
+ * - If var2 is negative, L40_var1 is shifted to the MSBits by (-var2)
+ * positions.
+ * Calls the macro L40_UNDERFLOW_OCCURED() in case of underflow on 40-bit.
+ * Calls the macro L40_OVERFLOW_OCCURED() in case of overflow on 40-bit.
+ *
+ * Complexity weight : 1
+ *
+ * Inputs :
+ *
+ * L40_var1 40 bit long signed integer (Word40) whose value falls in the
+ * range : MIN_40 <= L40_var1 <= MAX_40.
+ *
+ * var2 16 bit short signed integer (Word16) whose value falls in
+ * the range : MIN_16 <= var2 <= MAX_16.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value :
+ *
+ * L40_var_out 40 bit long signed integer (Word40) whose value falls in
+ * the range : MIN_40 <= L40_var_out <= MAX_40.
+ *
+ *****************************************************************************/
+Word40 L40_shr( Word40 L40_var1, Word16 var2 )
+{
+ Word40 L40_var_out;
+
+ if ( var2 < 0 )
+ {
+ var2 = -var2;
+ L40_var_out = L40_shl( L40_var1, var2 );
+ }
+ else
+ {
+ L40_var_out = L40_var1 >> var2;
+ }
+
+#ifdef WMOPS
+ multiCounter[currCounter].L40_shr++;
+#endif
+
+ return ( L40_var_out );
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : L40_negate
+ *
+ * Purpose :
+ *
+ * Negates L40_var1.
+ * Calls the macro L40_UNDERFLOW_OCCURED() in case of underflow on 40-bit.
+ * Calls the macro L40_OVERFLOW_OCCURED() in case of overflow on 40-bit.
+ *
+ * Complexity weight : 1
+ *
+ * Inputs :
+ *
+ * L40_var1 40 bit long signed integer (Word40) whose value falls in the
+ * range : MIN_40 <= L40_var1 <= MAX_40.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value :
+ *
+ * L40_var_out 40 bit long signed integer (Word40) whose value falls in
+ * the range : MIN_40 <= L40_var_out <= MAX_40.
+ *
+ *****************************************************************************/
+Word40 L40_negate( Word40 L40_var1 )
+{
+ Word40 L40_var_out;
+
+ L40_var_out = L40_add( ~L40_var1, 0x01 );
+
+#ifdef WMOPS
+ multiCounter[currCounter].L40_negate++;
+#endif
+
+ return ( L40_var_out );
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : L40_add
+ *
+ * Purpose :
+ *
+ * Adds L40_var1 and L40_var2 and returns the 40-bit result.
+ * Calls the macro L40_UNDERFLOW_OCCURED() in case of underflow on 40-bit.
+ * Calls the macro L40_OVERFLOW_OCCURED() in case of overflow on 40-bit.
+ *
+ * Complexity weight : 1
+ *
+ * Inputs :
+ *
+ * L40_var1 40 bit long signed integer (Word40) whose value falls in the
+ * range : MIN_40 <= L40_var1 <= MAX_40.
+ *
+ * L40_var2 40 bit long signed integer (Word40) whose value falls in the
+ * range : MIN_40 <= L40_var2 <= MAX_40.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value :
+ *
+ * L40_var_out 40 bit long signed integer (Word40) whose value falls in
+ * the range : MIN_40 <= L40_var_out <= MAX_40.
+ *
+ *****************************************************************************/
+#ifdef BASOP_NOGLOB
+
+Word40 L40_add_o( Word40 L40_var1, Word40 L40_var2, Flag *Overflow )
+{
+ Word40 L40_var_out;
+
+ L40_var_out = L40_var1 + L40_var2;
+
+#if defined( _MSC_VER ) && ( _MSC_VER <= 1200 )
+ if ( ( ( ( L40_var1 & 0x8000000000 ) >> 39 ) != 0 ) && ( ( ( L40_var2 & 0x8000000000 ) >> 39 ) != 0 ) && ( ( ( L40_var_out & 0x8000000000 ) >> 39 ) == 0 ) )
+ {
+ *Overflow = 1;
+ L40_var_out = MIN_40;
+ }
+ else if ( ( ( ( L40_var1 & 0x8000000000 ) >> 39 ) == 0 ) && ( ( ( L40_var2 & 0x8000000000 ) >> 39 ) == 0 ) && ( ( ( L40_var_out & 0x8000000000 ) >> 39 ) != 0 ) )
+ {
+ *Overflow = 1;
+ L40_var_out = MAX_40;
+ }
+#else
+ if ( ( ( ( L40_var1 & 0x8000000000LL ) >> 39 ) != 0 ) && ( ( ( L40_var2 & 0x8000000000LL ) >> 39 ) != 0 ) && ( ( ( L40_var_out & 0x8000000000LL ) >> 39 ) == 0 ) )
+ {
+ *Overflow = 1;
+ L40_var_out = MIN_40;
+ }
+ else if ( ( ( ( L40_var1 & 0x8000000000LL ) >> 39 ) == 0 ) && ( ( ( L40_var2 & 0x8000000000LL ) >> 39 ) == 0 ) && ( ( ( L40_var_out & 0x8000000000LL ) >> 39 ) != 0 ) )
+ {
+ *Overflow = 1;
+ L40_var_out = MAX_40;
+ }
+#endif
+
+#ifdef WMOPS
+ multiCounter[currCounter].L40_add++;
+#endif
+
+
+ BASOP_CHECK();
+
+
+ return ( L40_var_out );
+}
+
+#endif /* BASOP_NOGLOB */
+Word40 L40_add( Word40 L40_var1, Word40 L40_var2 )
+{
+ Word40 L40_var_out;
+
+ L40_var_out = L40_var1 + L40_var2;
+
+#if defined( _MSC_VER ) && ( _MSC_VER <= 1200 )
+ if ( ( ( ( L40_var1 & 0x8000000000 ) >> 39 ) != 0 ) && ( ( ( L40_var2 & 0x8000000000 ) >> 39 ) != 0 ) && ( ( ( L40_var_out & 0x8000000000 ) >> 39 ) == 0 ) )
+ {
+#ifndef BASOP_NOGLOB
+ Overflow = 1;
+ exit( 2 );
+ /* L40_var_out = L40_UNDERFLOW_OCCURED( L40_var_out); */
+#else /* BASOP_NOGLOB */
+ assert( 0 );
+ L40_var_out = MIN_40;
+#endif /* BASOP_NOGLOB */
+ }
+ else if ( ( ( ( L40_var1 & 0x8000000000 ) >> 39 ) == 0 ) && ( ( ( L40_var2 & 0x8000000000 ) >> 39 ) == 0 ) && ( ( ( L40_var_out & 0x8000000000 ) >> 39 ) != 0 ) )
+ {
+#ifndef BASOP_NOGLOB
+ Overflow = 1;
+ exit( 1 );
+ /* L40_var_out = L40_OVERFLOW_OCCURED( L40_var_out); */
+#else /* BASOP_NOGLOB */
+ assert( 0 );
+ L40_var_out = MAX_40;
+#endif /* BASOP_NOGLOB */
+ }
+#else
+ if ( ( ( ( L40_var1 & 0x8000000000LL ) >> 39 ) != 0 ) && ( ( ( L40_var2 & 0x8000000000LL ) >> 39 ) != 0 ) && ( ( ( L40_var_out & 0x8000000000LL ) >> 39 ) == 0 ) )
+ {
+#ifndef BASOP_NOGLOB
+ Overflow = 1;
+ exit( 2 );
+ /* L40_var_out = L40_UNDERFLOW_OCCURED( L40_var_out); */
+#else /* BASOP_NOGLOB */
+ assert( 0 );
+ L40_var_out = MIN_40;
+#endif /* BASOP_NOGLOB */
+ }
+ else if ( ( ( ( L40_var1 & 0x8000000000LL ) >> 39 ) == 0 ) && ( ( ( L40_var2 & 0x8000000000LL ) >> 39 ) == 0 ) && ( ( ( L40_var_out & 0x8000000000LL ) >> 39 ) != 0 ) )
+ {
+#ifndef BASOP_NOGLOB
+ Overflow = 1;
+ exit( 1 );
+ /* L40_var_out = L40_OVERFLOW_OCCURED( L40_var_out); */
+#else /* BASOP_NOGLOB */
+ assert( 0 );
+ L40_var_out = MAX_40;
+#endif /* BASOP_NOGLOB */
+ }
+#endif
+
+#ifdef WMOPS
+ multiCounter[currCounter].L40_add++;
+#endif
+
+ BASOP_CHECK();
+
+
+ return ( L40_var_out );
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : L40_sub
+ *
+ * Purpose :
+ *
+ * Subtracts L40_var2 from L40_var1.
+ * Calls the macro L40_UNDERFLOW_OCCURED() in case of underflow on 40-bit.
+ * Calls the macro L40_OVERFLOW_OCCURED() in case of overflow on 40-bit.
+ *
+ * Complexity weight : 1
+ *
+ * Inputs :
+ *
+ * L40_var1 40 bit long signed integer (Word40) whose value falls in the
+ * range : MIN_40 <= L40_var1 <= MAX_40.
+ *
+ * L40_var2 40 bit long signed integer (Word40) whose value falls in the
+ * range : MIN_40 <= L40_var2 <= MAX_40.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value :
+ *
+ * L40_var_out 40 bit long signed integer (Word40) whose value falls in
+ * the range : MIN_40 <= L40_var_out <= MAX_40.
+ *
+ *****************************************************************************/
+#ifndef BASOP_NOGLOB
+Word40 L40_sub( Word40 L40_var1, Word40 L40_var2 )
+#else /* BASOP_NOGLOB */
+Word40 L40_sub_o( Word40 L40_var1, Word40 L40_var2, Flag *Overflow )
+#endif /* BASOP_NOGLOB */
+{
+ Word40 L40_var_out;
+
+ L40_var_out = L40_var1 - L40_var2;
+
+#if defined( _MSC_VER ) && ( _MSC_VER <= 1200 )
+ if ( ( ( ( L40_var1 & 0x8000000000 ) >> 39 ) != 0 ) && ( ( ( L40_var2 & 0x8000000000 ) >> 39 ) == 0 ) && ( ( ( L40_var_out & 0x8000000000 ) >> 39 ) == 0 ) )
+ {
+#ifndef BASOP_NOGLOB
+ Overflow = 1;
+ exit( 2 );
+ /* L40_var_out = L40_UNDERFLOW_OCCURED( L40_var_out); */
+#else /* BASOP_NOGLOB */
+ *Overflow = 1;
+ L40_var_out = MIN_40;
+#endif /* BASOP_NOGLOB */
+ }
+ else if ( ( ( ( L40_var1 & 0x8000000000 ) >> 39 ) == 0 ) && ( ( ( L40_var2 & 0x8000000000 ) >> 39 ) != 0 ) && ( ( ( L40_var_out & 0x8000000000 ) >> 39 ) != 0 ) )
+ {
+#ifndef BASOP_NOGLOB
+ Overflow = 1;
+ exit( 1 );
+ /* L40_var_out = L40_OVERFLOW_OCCURED( L40_var_out); */
+#else /* BASOP_NOGLOB */
+ *Overflow = 1;
+ L40_var_out = MAX_40;
+#endif /* BASOP_NOGLOB */
+ }
+#else
+ if ( ( ( ( L40_var1 & 0x8000000000LL ) >> 39 ) != 0 ) && ( ( ( L40_var2 & 0x8000000000LL ) >> 39 ) == 0 ) && ( ( ( L40_var_out & 0x8000000000LL ) >> 39 ) == 0 ) )
+ {
+#ifndef BASOP_NOGLOB
+ Overflow = 1;
+ exit( 2 );
+ /* L40_var_out = L40_UNDERFLOW_OCCURED( L40_var_out); */
+#else /* BASOP_NOGLOB */
+ *Overflow = 1;
+ L40_var_out = MIN_40;
+#endif /* BASOP_NOGLOB */
+ }
+ else if ( ( ( ( L40_var1 & 0x8000000000LL ) >> 39 ) == 0 ) && ( ( ( L40_var2 & 0x8000000000LL ) >> 39 ) != 0 ) && ( ( ( L40_var_out & 0x8000000000LL ) >> 39 ) != 0 ) )
+ {
+#ifndef BASOP_NOGLOB
+ Overflow = 1;
+ exit( 1 );
+ /* L40_var_out = L40_OVERFLOW_OCCURED( L40_var_out); */
+#else /* BASOP_NOGLOB */
+ *Overflow = 1;
+ L40_var_out = MAX_40;
+#endif /* BASOP_NOGLOB */
+ }
+#endif
+
+#ifdef WMOPS
+ multiCounter[currCounter].L40_sub++;
+#endif
+
+ BASOP_CHECK();
+
+
+ return ( L40_var_out );
+}
+
+#ifdef BASOP_NOGLOB
+Word40 L40_sub( Word40 L40_var1, Word40 L40_var2 )
+{
+ Word40 L40_var_out;
+
+ L40_var_out = L40_var1 - L40_var2;
+
+#if defined( _MSC_VER ) && ( _MSC_VER <= 1200 )
+ if ( ( ( ( L40_var1 & 0x8000000000 ) >> 39 ) != 0 ) && ( ( ( L40_var2 & 0x8000000000 ) >> 39 ) == 0 ) && ( ( ( L40_var_out & 0x8000000000 ) >> 39 ) == 0 ) )
+ {
+ assert( 0 );
+ L40_var_out = MIN_40;
+ }
+ else if ( ( ( ( L40_var1 & 0x8000000000 ) >> 39 ) == 0 ) && ( ( ( L40_var2 & 0x8000000000 ) >> 39 ) != 0 ) && ( ( ( L40_var_out & 0x8000000000 ) >> 39 ) != 0 ) )
+ {
+ assert( 0 );
+ L40_var_out = MAX_40;
+ }
+#else
+ if ( ( ( ( L40_var1 & 0x8000000000LL ) >> 39 ) != 0 ) && ( ( ( L40_var2 & 0x8000000000LL ) >> 39 ) == 0 ) && ( ( ( L40_var_out & 0x8000000000LL ) >> 39 ) == 0 ) )
+ {
+ assert( 0 );
+ L40_var_out = MIN_40;
+ }
+ else if ( ( ( ( L40_var1 & 0x8000000000LL ) >> 39 ) == 0 ) && ( ( ( L40_var2 & 0x8000000000LL ) >> 39 ) != 0 ) && ( ( ( L40_var_out & 0x8000000000LL ) >> 39 ) != 0 ) )
+ {
+ assert( 0 );
+ L40_var_out = MAX_40;
+ }
+#endif
+
+#ifdef WMOPS
+ multiCounter[currCounter].L40_sub++;
+#endif
+
+ BASOP_CHECK();
+
+
+ return ( L40_var_out );
+}
+#endif /* BASOP_NOGLOB */
+
+/*****************************************************************************
+ *
+ * Function Name : L40_abs
+ *
+ * Purpose :
+ *
+ * Returns the absolute value of L40_var1.
+ * Calls the macro L40_UNDERFLOW_OCCURED() in case of underflow on 40-bit.
+ * Calls the macro L40_OVERFLOW_OCCURED() in case of overflow on 40-bit.
+ *
+ * Complexity weight : 1
+ *
+ * Inputs :
+ *
+ * L40_var1 40 bit long signed integer (Word40) whose value falls in the
+ * range : MIN_40 <= L40_var1 <= MAX_40.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value :
+ *
+ * L40_var_out 40 bit long signed integer (Word40) whose value falls in
+ * the range : 0x00 0000 0000 <= L40_var_out <= MAX_40.
+ *
+ *****************************************************************************/
+Word40 L40_abs( Word40 L40_var1 )
+{
+ Word40 L40_var_out;
+
+ if ( L40_var1 < 0 )
+ {
+ L40_var_out = L40_negate( L40_var1 );
+ }
+ else
+ {
+ L40_var_out = L40_var1;
+ }
+
+#ifdef WMOPS
+ multiCounter[currCounter].L40_abs++;
+#endif
+
+ return ( L40_var_out );
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : L40_max
+ *
+ * Purpose :
+ *
+ * Compares L40_var1 and L40_var2 and returns the maximum value.
+ *
+ *
+ * Complexity weight : 1
+ *
+ * Inputs :
+ *
+ * L40_var1 40 bit long signed integer (Word40) whose value falls in the
+ * range : MIN_40 <= L40_var1 <= MAX_40.
+ *
+ * L40_var2 40 bit long signed integer (Word40) whose value falls in the
+ * range : MIN_40 <= L40_var2 <= MAX_40.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value :
+ *
+ * L40_var_out 40 bit long signed integer (Word40) whose value falls in
+ * the range : MIN_40 <= L40_var_out <= MAX_40.
+ *
+ *****************************************************************************/
+Word40 L40_max( Word40 L40_var1, Word40 L40_var2 )
+{
+ Word40 L40_var_out;
+
+ if ( L40_var1 < L40_var2 )
+ L40_var_out = L40_var2;
+ else
+ L40_var_out = L40_var1;
+
+#ifdef WMOPS
+ multiCounter[currCounter].L40_max++;
+#endif
+
+ return ( L40_var_out );
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : L40_min
+ *
+ * Purpose :
+ *
+ * Compares L40_var1 and L40_var2 and returns the minimum value.
+ *
+ *
+ * Complexity weight : 1
+ *
+ * Inputs :
+ *
+ * L40_var1 40 bit long signed integer (Word40) whose value falls in the
+ * range : MIN_40 <= L40_var1 <= MAX_40.
+ *
+ * L40_var2 40 bit long signed integer (Word40) whose value falls in the
+ * range : MIN_40 <= L40_var2 <= MAX_40.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value :
+ *
+ * L40_var_out 40 bit long signed integer (Word40) whose value falls in
+ * the range : MIN_40 <= L40_var_out <= MAX_40.
+ *
+ *****************************************************************************/
+Word40 L40_min( Word40 L40_var1, Word40 L40_var2 )
+{
+ Word40 L40_var_out;
+
+ if ( L40_var1 < L40_var2 )
+ L40_var_out = L40_var1;
+ else
+ L40_var_out = L40_var2;
+
+#ifdef WMOPS
+ multiCounter[currCounter].L40_min++;
+#endif
+
+ return ( L40_var_out );
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : L_saturate40
+ *
+ * Purpose :
+ *
+ * If L40_var1 is greater than MAX_32, returns MAX_32.
+ * If L40_var1 is lower than MIN_32, returns MIN_32.
+ * If not, returns L_Extract40( L40_var1).
+ *
+ * Complexity weight : 1
+ *
+ * Inputs :
+ *
+ * L40_var1 40 bit long signed integer (Word40) whose value falls in the
+ * range : MIN_40 <= L40_var1 <= MAX_40.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value :
+ *
+ * L_var_out 32 bit long signed integer (Word32) whose value falls in
+ * the range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.
+ *
+ *****************************************************************************/
+#ifndef BASOP_NOGLOB
+Word32 L_saturate40( Word40 L40_var1 )
+#else /* BASOP_NOGLOB */
+
+Word32 L_saturate40_o( Word40 L40_var1, Flag *Overflow )
+#endif /* BASOP_NOGLOB */
+{
+ Word32 L_var_out;
+
+ Word40 UNDER_L40_var2 = ( Word40 ) ~( ( ( (Word40) 1 ) << 31 ) - (Word40) 1 );
+ Word40 OVER_L40_var2 = (Word40) ( ( ( (Word40) 1 ) << 31 ) - (Word40) 1 );
+
+ if ( L40_var1 < UNDER_L40_var2 )
+ {
+ L40_var1 = UNDER_L40_var2;
+#ifndef BASOP_NOGLOB
+ Overflow = 1;
+#else /* BASOP_NOGLOB */
+ *Overflow = 1;
+#endif /* BASOP_NOGLOB */
+ }
+
+ if ( L40_var1 > OVER_L40_var2 )
+ {
+ L40_var1 = OVER_L40_var2;
+#ifndef BASOP_NOGLOB
+ Overflow = 1;
+#else /* BASOP_NOGLOB */
+ *Overflow = 1;
+#endif /* BASOP_NOGLOB */
+ }
+
+ L_var_out = L_Extract40( L40_var1 );
+
+#ifdef WMOPS
+ multiCounter[currCounter].L_saturate40++;
+#endif
+
+ BASOP_CHECK();
+
+
+ return ( L_var_out );
+}
+
+#ifdef BASOP_NOGLOB
+Word32 L_saturate40( Word40 L40_var1 )
+{
+ Word32 L_var_out;
+
+ Word40 UNDER_L40_var2 = ( Word40 ) ~( ( ( (Word40) 1 ) << 31 ) - (Word40) 1 );
+ Word40 OVER_L40_var2 = (Word40) ( ( ( (Word40) 1 ) << 31 ) - (Word40) 1 );
+
+ if ( L40_var1 < UNDER_L40_var2 )
+ {
+ L40_var1 = UNDER_L40_var2;
+ assert( 0 );
+ }
+
+ if ( L40_var1 > OVER_L40_var2 )
+ {
+ L40_var1 = OVER_L40_var2;
+ assert( 0 );
+ }
+
+ L_var_out = L_Extract40( L40_var1 );
+
+#ifdef WMOPS
+ multiCounter[currCounter].L_saturate40++;
+#endif
+
+ BASOP_CHECK();
+
+
+ return ( L_var_out );
+}
+#endif /* BASOP_NOGLOB */
+
+/*****************************************************************************
+ *
+ * Function Name : Mpy_32_16_ss
+ *
+ * Purpose :
+ *
+ * Multiplies the 2 signed values L_var1 and var2 with saturation control
+ * on 48-bit. The operation is performed in fractional mode :
+ * - L_var1 is supposed to be in 1Q31 format.
+ * - var2 is supposed to be in 1Q15 format.
+ * - The result is produced in 1Q47 format : L_varout_h points to the
+ * 32 MSBits while varout_l points to the 16 LSBits.
+ *
+ * Complexity weight : 2
+ *
+ * Inputs :
+ *
+ * L_var1 32 bit long signed integer (Word32) whose value falls in
+ * the range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.
+ *
+ * var2 16 bit short signed integer (Word16) whose value falls in
+ * the range : 0xffff 8000 <= var2 <= 0x0000 7fff.
+ *
+ * Outputs :
+ *
+ * *L_varout_h 32 bit long signed integer (Word32) whose value falls in
+ * the range : 0x8000 0000 <= L_varout_h <= 0x7fff ffff.
+ *
+ * *varout_l 16 bit short unsigned integer (UWord16) whose value falls in
+ * the range : 0x0000 0000 <= varout_l <= 0x0000 ffff.
+ *
+ * Return Value :
+ *
+ * none
+ *
+ *****************************************************************************/
+void Mpy_32_16_ss( Word32 L_var1, Word16 var2, Word32 *L_varout_h, UWord16 *varout_l )
+{
+ Word16 var1_h;
+ UWord16 uvar1_l;
+ Word40 L40_var1;
+
+ if ( ( L_var1 == (Word32) 0x80000000 ) && ( var2 == (Word16) 0x8000 ) )
+ {
+ *L_varout_h = 0x7fffffff;
+ *varout_l = (UWord16) 0xffff;
+ }
+ else
+ {
+ uvar1_l = extract_l( L_var1 );
+ var1_h = extract_h( L_var1 );
+
+ /* Below line can not overflow, so we can use << instead of L40_shl. */
+ L40_var1 = ( (Word40) ( (Word32) var2 * (Word32) uvar1_l ) ) << 1;
+
+ *varout_l = Extract40_L( L40_var1 );
+
+ L40_var1 = L40_shr( L40_var1, 16 );
+ L40_var1 = L40_mac( L40_var1, var2, var1_h );
+
+ *L_varout_h = L_Extract40( L40_var1 );
+
+#ifdef WMOPS
+ multiCounter[currCounter].extract_l--;
+ multiCounter[currCounter].extract_h--;
+ multiCounter[currCounter].Extract40_L--;
+ multiCounter[currCounter].L40_shr--;
+ multiCounter[currCounter].L40_mac--;
+ multiCounter[currCounter].L_Extract40--;
+#endif
+ }
+
+#ifdef WMOPS
+ multiCounter[currCounter].Mpy_32_16_ss++;
+#endif
+
+ return;
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : Mpy_32_32_ss
+ *
+ * Purpose :
+ *
+ * Multiplies the 2 signed values L_var1 and L_var2 with saturation control
+ * on 64-bit. The operation is performed in fractional mode :
+ * - L_var1 and L_var2 are supposed to be in 1Q31 format.
+ * - The result is produced in 1Q63 format : L_varout_h points to the
+ * 32 MSBits while L_varout_l points to the 32 LSBits.
+ *
+ * Complexity weight : 4
+ *
+ * Inputs :
+ *
+ * L_var1 32 bit long signed integer (Word32) whose value falls in the
+ * range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.
+ *
+ * L_var2 32 bit long signed integer (Word32) whose value falls in the
+ * range : 0x8000 0000 <= L_var2 <= 0x7fff ffff.
+ *
+ * Outputs :
+ *
+ * *L_varout_h 32 bit long signed integer (Word32) whose value falls in
+ * the range : 0x8000 0000 <= L_varout_h <= 0x7fff ffff.
+ *
+ * *L_varout_l 32 bit short unsigned integer (UWord32) whose value falls in
+ * the range : 0x0000 0000 <= L_varout_l <= 0xffff ffff.
+ *
+ *
+ * Return Value :
+ *
+ * none
+ *
+ *****************************************************************************/
+void Mpy_32_32_ss( Word32 L_var1, Word32 L_var2, Word32 *L_varout_h, UWord32 *L_varout_l )
+{
+ UWord16 uvar1_l, uvar2_l;
+ Word16 var1_h, var2_h;
+ Word40 L40_var1;
+
+ if ( ( L_var1 == (Word32) 0x80000000 ) && ( L_var2 == (Word32) 0x80000000 ) )
+ {
+ *L_varout_h = 0x7fffffff;
+ *L_varout_l = (UWord32) 0xffffffff;
+ }
+ else
+ {
+
+ uvar1_l = extract_l( L_var1 );
+ var1_h = extract_h( L_var1 );
+ uvar2_l = extract_l( L_var2 );
+ var2_h = extract_h( L_var2 );
+
+ /* Below line can not overflow, so we can use << instead of L40_shl. */
+ L40_var1 = ( (Word40) ( (UWord32) uvar2_l * (UWord32) uvar1_l ) ) << 1;
+
+ *L_varout_l = 0x0000ffff & L_Extract40( L40_var1 );
+
+ L40_var1 = L40_shr( L40_var1, 16 );
+ L40_var1 = L40_add( L40_var1, ( (Word40) ( (Word32) var2_h * (Word32) uvar1_l ) ) << 1 );
+ L40_var1 = L40_add( L40_var1, ( (Word40) ( (Word32) var1_h * (Word32) uvar2_l ) ) << 1 );
+ *L_varout_l |= ( L_Extract40( L40_var1 ) ) << 16;
+
+ L40_var1 = L40_shr( L40_var1, 16 );
+ L40_var1 = L40_mac( L40_var1, var1_h, var2_h );
+
+ *L_varout_h = L_Extract40( L40_var1 );
+
+#ifdef WMOPS
+ multiCounter[currCounter].extract_l -= 2;
+ multiCounter[currCounter].extract_h -= 2;
+ multiCounter[currCounter].L_Extract40 -= 3;
+ multiCounter[currCounter].L40_shr -= 2;
+ multiCounter[currCounter].L40_add -= 2;
+ multiCounter[currCounter].L40_mac--;
+#endif
+ }
+
+#ifdef WMOPS
+ multiCounter[currCounter].Mpy_32_32_ss++;
+#endif
+
+ return;
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : L40_lshl
+ *
+ * Purpose :
+ *
+ * Logically shifts left L40_var1 by var2 positions.
+ * - If var2 is negative, L40_var1 is shifted to the LSBits by (-var2)
+ * positions with insertion of 0 at the MSBit.
+ * - If var2 is positive, L40_var1 is shifted to the MSBits by (var2)
+ * positions.
+ *
+ * Complexity weight : 1
+ *
+ * Inputs :
+ *
+ * L40_var1 40 bit long signed integer (Word40) whose value falls in the
+ * range : MIN_40 <= L40_var1 <= MAX_40.
+ *
+ * var2 16 bit short signed integer (Word16) whose value falls in
+ * the range : MIN_16 <= var2 <= MAX_16.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value :
+ *
+ * L_var_out 32 bit long unsigned integer (UWord32) whose value falls in
+ * the range : MIN_40 <= L40_var_out <= MAX_40.
+ *
+ *****************************************************************************/
+Word40 L40_lshl( Word40 L40_var1, Word16 var2 )
+{
+ Word40 L40_var_out;
+
+ if ( var2 <= 0 )
+ {
+ var2 = -var2;
+ L40_var_out = L40_lshr( L40_var1, var2 );
+#ifdef WMOPS
+ multiCounter[currCounter].L40_lshr--;
+#endif
+ }
+ else
+ {
+ if ( var2 >= 40 )
+ L40_var_out = 0x0000000000;
+ else
+ {
+ L40_var_out = L40_var1 << var2;
+ }
+ L40_var_out = L40_set( L40_var_out );
+ }
+
+#ifdef WMOPS
+ multiCounter[currCounter].L40_lshl++;
+#endif
+
+ BASOP_CHECK();
+
+
+ return ( L40_var_out );
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : L40_lshr
+ *
+ * Purpose :
+ *
+ * Logically shifts right L40_var1 by var2 positions.
+ * - If var2 is positive, L40_var1 is shifted to the LSBits by (var2)
+ * positions with insertion of 0 at the MSBit.
+ * - If var2 is negative, L40_var1 is shifted to the MSBits by (-var2)
+ * positions.
+ *
+ * Complexity weight : 1
+ *
+ * Inputs :
+ *
+ * L40_var1 40 bit long signed integer (Word40) whose value falls in the
+ * range : MIN_40 <= L40_var1 <= MAX_40.
+ *
+ * var2 16 bit short signed integer (Word16) whose value falls in
+ * the range : MIN_16 <= var2 <= MAX_16.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value :
+ *
+ * L40_var_out 40 bit long signed integer (Word40) whose value falls in
+ * the range : MIN_40 <= L40_var_out <= MAX_40.
+ *
+ *****************************************************************************/
+Word40 L40_lshr( Word40 L40_var1, Word16 var2 )
+{
+ Word40 L40_var_out;
+
+ if ( var2 < 0 )
+ {
+ var2 = -var2;
+ L40_var_out = L40_lshl( L40_var1, var2 );
+#ifdef WMOPS
+ multiCounter[currCounter].L40_lshl--;
+#endif
+ }
+ else
+ {
+ if ( var2 >= 40 )
+ L40_var_out = 0x0000000000;
+ else
+ {
+#if defined( _MSC_VER ) && ( _MSC_VER <= 1200 )
+ L40_var_out = ( L40_var1 & 0xffffffffff ) >> var2;
+#else
+ L40_var_out = ( L40_var1 & 0xffffffffffLL ) >> var2;
+#endif
+ }
+ }
+
+#ifdef WMOPS
+ multiCounter[currCounter].L40_lshr++;
+#endif
+
+ BASOP_CHECK();
+
+
+ return ( L40_var_out );
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : norm_L40
+ *
+ * Purpose :
+ *
+ * Produces the number of left shifts needed to normalize in 32 bit format
+ * the 40 bit variable L40_var1. This returned value can be used to scale
+ * L_40_var1 into the following intervals :
+ * - [(MAX_32+1)/2 .. MAX_32 ] for positive values.
+ * - [ MIN_32 .. (MIN_32/2)+1 ] for negative values.
+ * - [ 0 .. 0 ] for null values.
+ * In order to normalize the result, the following operation must be done :
+ * normelized_L40_var1 = L40_shl( L40_var1, norm_L40( L40_var1))
+ *
+ * Complexity weight : 1
+ *
+ * Inputs :
+ *
+ * L40_var1 40 bit long signed integer (Word40) whose value falls in the
+ * range : MIN_40 <= L40_var1 <= MAX_40.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value :
+ *
+ * var_out 16 bit short signed integer (Word16) whose value falls in
+ * the range : -8 <= var_out <= 31.
+ *
+ *****************************************************************************/
+Word16 norm_L40( Word40 L40_var1 )
+{
+ Word16 var_out;
+
+ var_out = 0;
+
+ if ( L40_var1 != 0 )
+ {
+ while ( ( L40_var1 > (Word32) 0x80000000L ) && ( L40_var1 < (Word32) 0x7fffffffL ) )
+ {
+
+ L40_var1 = L40_shl( L40_var1, 1 );
+ var_out++;
+ }
+
+ while ( ( L40_var1 < (Word32) 0x80000000L ) || ( L40_var1 > (Word32) 0x7fffffffL ) )
+ {
+
+ L40_var1 = L40_shl( L40_var1, -1 );
+ var_out--;
+ }
+ }
+
+
+ return ( var_out );
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : L40_shr_r
+ *
+ * Purpose :
+ *
+ * Arithmetically shifts right L40_var1 by var2 positions and rounds the
+ * result. It is equivalent to L40_shr( L40_var1, var2) except that if the
+ * last bit shifted out to the LSBit is 1, then the shifted result is
+ * incremented by 1.
+ * Calls the macro L40_UNDERFLOW_OCCURED() in case of underflow on 40-bit.
+ * Calls the macro L40_OVERFLOW_OCCURED() in case of overflow on 40-bit.
+ *
+ * Complexity weight : 3
+ *
+ * Inputs :
+ *
+ * L40_var1 40 bit long signed integer (Word40) whose value falls in the
+ * range : MIN_40 <= L40_var1 <= MAX_40.
+ *
+ * var2 16 bit short signed integer (Word16) whose value falls in
+ * the range : 0xffff 8000 <= var2 <= 0x0000 7fff.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value :
+ *
+ * L40_var_out 40 bit long signed integer (Word40) whose value falls in
+ * the range : MIN_40 <= L40_var_out <= MAX_40.
+ *
+ *****************************************************************************/
+Word40 L40_shr_r( Word40 L40_var1, Word16 var2 )
+{
+ Word40 L40_var_out;
+
+ if ( var2 > 39 )
+ {
+ L40_var_out = 0;
+ }
+ else
+ {
+ L40_var_out = L40_shr( L40_var1, var2 );
+
+ if ( var2 > 0 )
+ {
+ if ( ( L40_var1 & ( (Word40) 1 << ( var2 - 1 ) ) ) != 0 )
+ {
+ /* below line can not generate overflows on 40-bit */
+ L40_var_out++;
+ }
+ }
+ }
+
+ BASOP_CHECK();
+
+
+ return ( L40_var_out );
+}
+
+
+/*****************************************************************************
+ *
+ * Function Name : L40_shl_r
+ *
+ * Purpose :
+ *
+ * Arithmetically shifts left L40_var1 by var2 positions and rounds the
+ * result. It is equivalent to L40_shl( L40_var1, var2) except if var2 is
+ * negative. In that case, it does the same as
+ * L40_shr_r( L40_var1, (-var2)).
+ * Calls the macro L40_UNDERFLOW_OCCURED() in case of underflow on 40-bit.
+ * Calls the macro L40_OVERFLOW_OCCURED() in case of overflow on 40-bit.
+ *
+ * Complexity weight : 3
+ *
+ * Inputs :
+ *
+ * L40_var1 40 bit long signed integer (Word40) whose value falls in the
+ * range : MIN_40 <= L40_var1 <= MAX_40.
+ *
+ * var2 16 bit short signed integer (Word16) whose value falls in
+ * the range : 0xffff 8000 <= var2 <= 0x0000 7fff.
+ *
+ * Outputs :
+ *
+ * none
+ *
+ * Return Value :
+ *
+ * L40_var_out 40 bit long signed integer (Word40) whose value falls in
+ * the range : MIN_40 <= L40_var_out <= MAX_40.
+ *
+ *****************************************************************************/
+Word40 L40_shl_r( Word40 L40_var1, Word16 var2 )
+{
+ Word40 L40_var_out;
+
+ if ( var2 >= 0 )
+ {
+ L40_var_out = L40_shl( L40_var1, var2 );
+ }
+ else
+ {
+ var2 = -var2;
+ L40_var_out = L40_shr_r( L40_var1, var2 );
+ }
+
+
+ return ( L40_var_out );
+}
+
+
+#undef WMC_TOOL_SKIP
diff --git a/lib_com/enh40.h b/lib_com/enh40.h
new file mode 100644
index 0000000000000000000000000000000000000000..ca78cb33e757efa0b842cccef662c45d1d96fa50
--- /dev/null
+++ b/lib_com/enh40.h
@@ -0,0 +1,409 @@
+/******************************************************************************************************
+
+ (C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
+ Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
+ Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
+ Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
+ contributors to this repository. All Rights Reserved.
+
+ This software is protected by copyright law and by international treaties.
+ The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
+ Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
+ Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
+ Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
+ contributors to this repository retain full ownership rights in their respective contributions in
+ the software. This notice grants no license of any kind, including but not limited to patent
+ license, nor is any license granted by implication, estoppel or otherwise.
+
+ Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
+ contributions.
+
+ This software is provided "AS IS", without any express or implied warranties. The software is in the
+ development stage. It is intended exclusively for experts who have experience with such software and
+ solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
+ and fitness for a particular purpose are hereby disclaimed and excluded.
+
+ Any dispute, controversy or claim arising under or in relation to providing this software shall be
+ submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
+ accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
+ the United Nations Convention on Contracts on the International Sales of Goods.
+
+*******************************************************************************************************/
+
+/*
+ ===========================================================================
+ File: ENH40.H v.2.3 - 30.Nov.2009
+ ===========================================================================
+
+ ITU-T STL BASIC OPERATORS
+
+ 40-BIT ARITHMETIC OPERATORS
+
+ History:
+ 07 Nov 04 v2.0 Incorporation of new 32-bit / 40-bit / control
+ operators for the ITU-T Standard Tool Library as
+ described in Geneva, 20-30 January 2004 WP 3/16 Q10/16
+ TD 11 document and subsequent discussions on the
+ wp3audio@yahoogroups.com email reflector.
+ March 06 v2.1 Changed to improve portability.
+
+ ============================================================================
+*/
+
+
+#ifndef _ENH40_H
+#define _ENH40_H
+
+#include "stl.h"
+
+#if defined( BASOP_NOGLOB ) || defined( _MSC_VER )
+#define MAX_40 ( 0x0000007fffffffff )
+#define MIN_40 ( 0xffffff8000000000 )
+#endif
+
+#define L40_OVERFLOW_OCCURED( L40_var1 ) ( Overflow = 1, exit( 1 ), L40_var1 )
+#define L40_UNDERFLOW_OCCURED( L40_var1 ) ( Overflow = 1, exit( 2 ), L40_var1 )
+
+/*****************************************************************************
+ *
+ * Prototypes for enhanced 40 bit arithmetic operators
+ *
+ *****************************************************************************/
+Word40 L40_shr( Word40 L40_var1, Word16 var2 );
+Word40 L40_shr_r( Word40 L40_var1, Word16 var2 );
+Word40 L40_shl( Word40 L40_var1, Word16 var2 );
+Word40 L40_shl_r( Word40 L40_var1, Word16 var2 );
+
+static __inline Word40 L40_mult( Word16 var1, Word16 var2 );
+
+static __inline Word40 L40_mac( Word40 L40_var1, Word16 var1, Word16 var2 );
+static __inline Word16 mac_r40( Word40 L40_var1, Word16 var1, Word16 var2 );
+
+static __inline Word40 L40_msu( Word40 L40_var1, Word16 var1, Word16 var2 );
+static __inline Word16 msu_r40( Word40 L40_var1, Word16 var1, Word16 var2 );
+
+
+void Mpy_32_16_ss( Word32 L_var1, Word16 var2, Word32 *L_varout_h, UWord16 *varout_l );
+void Mpy_32_32_ss( Word32 L_var1, Word32 L_var2, Word32 *L_varout_h, UWord32 *L_varout_l );
+
+
+Word40 L40_lshl( Word40 L40_var1, Word16 var2 );
+Word40 L40_lshr( Word40 L40_var1, Word16 var2 );
+
+static __inline Word40 L40_set( Word40 L40_var1 );
+static __inline UWord16 Extract40_H( Word40 L40_var1 );
+static __inline UWord16 Extract40_L( Word40 L40_var1 );
+static __inline UWord32 L_Extract40( Word40 L40_var1 );
+
+static __inline Word40 L40_deposit_h( Word16 var1 );
+static __inline Word40 L40_deposit_l( Word16 var1 );
+static __inline Word40 L40_deposit32( Word32 L_var1 );
+
+static __inline Word40 L40_round( Word40 L40_var1 );
+static __inline Word16 round40( Word40 L40_var1 );
+
+
+Word40 L40_add( Word40 L40_var1, Word40 L40_var2 );
+Word40 L40_sub( Word40 L40_var1, Word40 L40_var2 );
+Word40 L40_abs( Word40 L40_var1 );
+Word40 L40_negate( Word40 L40_var1 );
+Word40 L40_max( Word40 L40_var1, Word40 L40_var2 );
+Word40 L40_min( Word40 L40_var1, Word40 L40_var2 );
+Word32 L_saturate40( Word40 L40_var1 );
+Word16 norm_L40( Word40 L40_var1 );
+#ifdef BASOP_NOGLOB
+/*
+ * Overflowing operators
+ */
+Word40 L40_shl_o( Word40 L40_var1, Word16 var2, Flag *Overflow );
+Word40 L40_add_o( Word40 L40_var1, Word40 L40_var2, Flag *Overflow );
+Word40 L40_sub_o( Word40 L40_var1, Word40 L40_var2, Flag *Overflow );
+Word32 L_saturate40_o( Word40 L40_var1, Flag *Overflow );
+#endif /* BASOP_NOGLOB */
+/*#ifdef _MSC_VER*/
+static __inline Word40 L40_set( Word40 L40_var1 )
+{
+ Word40 L40_var_out;
+
+#if defined( _MSC_VER ) && ( _MSC_VER <= 1200 )
+ L40_var_out = L40_var1 & 0x000000ffffffffff;
+
+ if ( L40_var1 & 0x8000000000 )
+ L40_var_out = L40_var_out | 0xffffff0000000000;
+#else
+ L40_var_out = L40_var1 & 0x000000ffffffffffLL;
+
+ if ( L40_var1 & 0x8000000000LL )
+ L40_var_out = L40_var_out | 0xffffff0000000000LL;
+#endif
+
+#ifdef WMOPS
+ multiCounter[currCounter].L40_set++;
+#endif
+
+ return ( L40_var_out );
+}
+/*#endif*/ /* ifdef _MSC_VER */
+
+
+static __inline UWord16 Extract40_H( Word40 L40_var1 )
+{
+ UWord16 var_out;
+
+ var_out = (UWord16) ( L40_var1 >> 16 );
+
+#ifdef WMOPS
+ multiCounter[currCounter].Extract40_H++;
+#endif
+
+ return ( var_out );
+}
+
+
+static __inline UWord16 Extract40_L( Word40 L40_var1 )
+{
+ UWord16 var_out;
+
+ var_out = (UWord16) ( L40_var1 );
+
+#ifdef WMOPS
+ multiCounter[currCounter].Extract40_L++;
+#endif
+
+ return ( var_out );
+}
+
+
+static __inline UWord32 L_Extract40( Word40 L40_var1 )
+{
+ UWord32 L_var_out;
+
+ L_var_out = (UWord32) L40_var1;
+
+#ifdef WMOPS
+ multiCounter[currCounter].L_Extract40++;
+#endif
+
+ return ( L_var_out );
+}
+
+
+static __inline Word40 L40_deposit_h( Word16 var1 )
+{
+ Word40 L40_var_out;
+
+ L40_var_out = ( (Word40) var1 ) << 16;
+
+#if defined( _MSC_VER ) && ( _MSC_VER <= 1200 )
+ if ( var1 & 0x8000 )
+ {
+ L40_var_out = L40_set( L40_var_out | 0xff00000000 );
+
+#ifdef WMOPS
+ multiCounter[currCounter].L40_set--;
+#endif
+ }
+#else
+ if ( var1 & 0x8000 )
+ {
+ L40_var_out = L40_set( L40_var_out | 0xff00000000LL );
+
+#ifdef WMOPS
+ multiCounter[currCounter].L40_set--;
+#endif
+ }
+#endif
+
+#ifdef WMOPS
+ multiCounter[currCounter].L40_deposit_h++;
+#endif
+
+ return ( L40_var_out );
+}
+
+
+static __inline Word40 L40_deposit_l( Word16 var1 )
+{
+ Word40 L40_var_out;
+
+ L40_var_out = var1;
+
+#if defined( _MSC_VER ) && ( _MSC_VER <= 1200 )
+ if ( var1 & 0x8000 )
+ {
+ L40_var_out = L40_set( L40_var_out | 0xffffff0000 );
+
+#ifdef WMOPS
+ multiCounter[currCounter].L40_set--;
+#endif
+ }
+#else
+ if ( var1 & 0x8000 )
+ {
+ L40_var_out = L40_set( L40_var_out | 0xffffff0000LL );
+
+#ifdef WMOPS
+ multiCounter[currCounter].L40_set--;
+#endif
+ }
+#endif
+
+#ifdef WMOPS
+ multiCounter[currCounter].L40_deposit_l++;
+#endif
+
+ return ( L40_var_out );
+}
+
+
+static __inline Word40 L40_deposit32( Word32 L_var1 )
+{
+ Word40 L40_var_out;
+
+ L40_var_out = (Word40) L_var1;
+
+#if defined( _MSC_VER ) && ( _MSC_VER <= 1200 )
+ if ( L_var1 & 0x80000000 )
+ {
+ L40_var_out = L40_set( L40_var_out | 0xff00000000 );
+
+#ifdef WMOPS
+ multiCounter[currCounter].L40_set--;
+#endif
+ }
+#else
+ if ( L_var1 & 0x80000000 )
+ {
+ L40_var_out = L40_set( L40_var_out | 0xff00000000LL );
+
+#ifdef WMOPS
+ multiCounter[currCounter].L40_set--;
+#endif
+ }
+#endif
+
+#ifdef WMOPS
+ multiCounter[currCounter].L40_deposit32++;
+#endif
+
+ return ( L40_var_out );
+}
+
+
+static __inline Word40 L40_round( Word40 L40_var1 )
+{
+ Word40 L40_var_out;
+ Word40 L40_constant;
+
+#if defined( _MSC_VER ) && ( _MSC_VER <= 1200 )
+ L40_constant = L40_set( 0xffffff0000 );
+#else
+ L40_constant = L40_set( 0xffffff0000LL );
+#endif
+
+ L40_var_out = L40_add( 0x8000, L40_var1 );
+ L40_var_out = L40_var_out & L40_constant;
+
+#ifdef WMOPS
+ multiCounter[currCounter].L40_set--;
+ multiCounter[currCounter].L40_add--;
+ multiCounter[currCounter].L40_round++;
+#endif
+
+ return ( L40_var_out );
+}
+
+
+static __inline Word16 round40( Word40 L40_var1 )
+{
+ Word16 var_out;
+
+ var_out = extract_h( L_saturate40( L40_round( L40_var1 ) ) );
+
+#ifdef WMOPS
+ multiCounter[currCounter].L40_round--;
+ multiCounter[currCounter].L_saturate40--;
+ multiCounter[currCounter].extract_h--;
+ multiCounter[currCounter].round40++;
+#endif
+
+ return ( var_out );
+}
+
+
+static __inline Word40 L40_mult( Word16 var1, Word16 var2 )
+{
+ Word32 L_var_out;
+ Word40 L40_var_out;
+
+ L_var_out = (Word32) var1 * (Word32) var2;
+ L40_var_out = (Word40) L_var_out;
+
+ /* Below line can not overflow, so we can use << instead of L40_shl. */
+ L40_var_out = L40_var_out << 1;
+
+#ifdef WMOPS
+ multiCounter[currCounter].L40_mult++;
+#endif
+
+ return ( L40_var_out );
+}
+
+
+static __inline Word40 L40_mac( Word40 L40_var1, Word16 var2, Word16 var3 )
+{
+ Word40 L40_var_out;
+
+ L40_var_out = L40_mult( var2, var3 );
+ L40_var_out = L40_add( L40_var1, L40_var_out );
+
+#ifdef WMOPS
+ multiCounter[currCounter].L40_mac++;
+#endif
+
+ return ( L40_var_out );
+}
+
+
+static __inline Word16 mac_r40( Word40 L40_var1, Word16 var2, Word16 var3 )
+{
+ Word40 L40_var_out;
+ Word16 var_out;
+
+ L40_var_out = L40_mac( L40_var1, var2, var3 );
+ var_out = round40( L40_var_out );
+
+
+ return ( var_out );
+}
+
+
+static __inline Word40 L40_msu( Word40 L40_var1, Word16 var2, Word16 var3 )
+{
+ Word40 L40_var_out;
+
+ L40_var_out = L40_mult( var2, var3 );
+ L40_var_out = L40_sub( L40_var1, L40_var_out );
+
+
+ return ( L40_var_out );
+}
+
+
+static __inline Word16 msu_r40( Word40 L40_var1, Word16 var2, Word16 var3 )
+{
+ Word40 L40_var_out;
+ Word16 var_out;
+
+ L40_var_out = L40_msu( L40_var1, var2, var3 );
+ var_out = round40( L40_var_out );
+
+
+ return ( var_out );
+}
+
+
+#endif /*_ENH40_H*/
+
+
+/* end of file */
diff --git a/lib_com/enhancer.c b/lib_com/enhancer.c
new file mode 100644
index 0000000000000000000000000000000000000000..e8bae9e3de1bcd98c4a2ce4dbac382a423e77dae
--- /dev/null
+++ b/lib_com/enhancer.c
@@ -0,0 +1,244 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include
+#include "wmc_auto.h"
+#include "options.h"
+#include "cnst.h"
+#include "prot.h"
+#include "rom_com.h"
+
+/*---------------------------------------------------------------------*
+ * Local functions
+ *---------------------------------------------------------------------*/
+
+static void agc2( const float *sig_in, float *sig_out,const short l_trm );
+
+/*---------------------------------------------------------------------*
+ * enhancer()
+ *
+ * Enhancement of the excitation signal before synthesis
+ *---------------------------------------------------------------------*/
+
+void enhancer(
+ const short codec_mode, /* i : flag indicating Codec Mode */
+ const long core_brate, /* i : core bitrate */
+ const short cbk_index, /* i : */
+ const short Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */
+ const short coder_type, /* i : coding type */
+ const short L_frame, /* i : frame size */
+ const float voice_fac, /* i : subframe voicing estimation */
+ const float stab_fac, /* i : LP filter stablility measure */
+ const float norm_gain_code, /* i : normalized innovative cb. gain */
+ const float gain_inov, /* i : gain of the unscaled innovation */
+ float *gc_threshold, /* i/o: code threshold */
+ float *code, /* i/o: innovation */
+ float *pt_exc2, /* i/o: adapt. excitation/total exc. */
+ const float gain_pit, /* i : Quantized pitch gain */
+ float *dispMem /* i/o: Phase dispersion algorithm memory */
+)
+{
+ float tmp, gain_code, new_norm_gain_code, fac;
+ short i;
+ float pit_sharp;
+ float excp[L_SUBFR];
+
+ pit_sharp = gain_pit;
+
+ /*-----------------------------------------------------------------*
+ * Phase dispersion
+ *
+ * Enhance noise at low bit rates
+ *-----------------------------------------------------------------*/
+
+ i = 2; /* no dispersion */
+ if( Opt_AMR_WB )
+ {
+ if ( core_brate <= ACELP_6k60 )
+ {
+ i = 0; /* high dispersion */
+ }
+ else if ( core_brate <= ACELP_8k85 )
+ {
+ i = 1; /* low dispersion */
+ }
+ }
+ else if( codec_mode == MODE1 && coder_type != UNVOICED )
+ {
+ if ( core_brate <= ACELP_7k20 )
+ {
+ i = 0; /* high dispersion */
+ }
+ else if ( ( coder_type == GENERIC || coder_type == TRANSITION || coder_type == AUDIO || coder_type == INACTIVE ) && core_brate <= ACELP_9k60 )
+ {
+ i = 1; /* low dispersion */
+ }
+ }
+ else if( codec_mode == MODE2 )
+ {
+ if( ((coder_type!=VOICED) && cbk_index<=2) || ((coder_type==UNVOICED) && L_frame==L_FRAME && cbk_index<=10) || ((coder_type==UNVOICED) && L_frame==L_FRAME16k && cbk_index<=14))
+ {
+ i = 0; /* high dispersion */
+ }
+ else if( (coder_type!=VOICED) && (cbk_index<=7) )
+ {
+ i = 1; /* low dispersion */
+ }
+ }
+
+ phase_dispersion( norm_gain_code, gain_pit, code, i, dispMem );
+
+ /*------------------------------------------------------------
+ * Noise enhancer
+ *
+ * Enhance excitation on noise (modify code gain). If signal is noisy and LPC filter is stable,
+ * move code gain 1.5 dB towards its threshold. This decreases by 3 dB noise energy variation.
+ *-----------------------------------------------------------*/
+
+ if ( norm_gain_code < *gc_threshold )
+ {
+ new_norm_gain_code = (float)(norm_gain_code * 1.19f);
+ if ( new_norm_gain_code > *gc_threshold )
+ {
+ new_norm_gain_code = *gc_threshold;
+ }
+ }
+ else
+ {
+ new_norm_gain_code = (float)(norm_gain_code / 1.19f);
+ if ( new_norm_gain_code < *gc_threshold )
+ {
+ new_norm_gain_code = *gc_threshold;
+ }
+ }
+ *gc_threshold = new_norm_gain_code;
+
+ /* calculate new code gain */
+ fac = stab_fac * (0.5f * (1.0f - voice_fac)); /* 1 = unvoiced, 0 = voiced */
+ gain_code = fac * new_norm_gain_code + (1.0f - fac) * norm_gain_code;
+ gain_code *= gain_inov;
+
+ for (i=0; i 1.0 )
+ {
+ pit_sharp = 1.0;
+ }
+
+ if ( pit_sharp > 0.5 )
+ {
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ excp[i] = pt_exc2[i] * pit_sharp * 0.25f;
+ }
+ }
+ }
+
+ /*-----------------------------------------------------------------
+ * Do a simple noncasual "sharpening": effectively an FIR
+ * filter with coefs [-tmp 1.0 -tmp] where tmp = 0 ... 0.25
+ * This is applied to code and added to exc2
+ *-----------------------------------------------------------------*/
+ if( L_frame == L_FRAME16k )
+ {
+ tmp = (float)(0.150f*(1.0f+voice_fac)); /* 0.30=voiced, 0=unvoiced */
+ }
+ else
+ {
+ tmp = (float)(0.125f * (1.0f + voice_fac)); /* 0.25=voiced, 0=unvoiced */
+ }
+ pt_exc2[0] += code[0] - (tmp * code[1]);
+ for ( i=1; i 0.5f )
+ {
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ excp[i] += pt_exc2[i];
+ }
+
+ agc2( pt_exc2, excp, L_SUBFR );
+ mvr2r( excp, pt_exc2, L_SUBFR );
+ }
+ }
+ }
+
+ return;
+}
+
+/*-----------------------------------------------------------------------*
+ * agc2()
+ *
+ * Adaptive gain control
+ *-----------------------------------------------------------------------*/
+
+static void agc2(
+ const float *sig_in, /* i : postfilter input signal */
+ float *sig_out, /* i/o: postfilter output signal */
+ const short l_trm /* i : subframe size */
+)
+{
+ short i;
+ float gain_in, gain_out;
+ float g0, gain;
+
+
+ gain_out = 0.0f;
+ for(i=0; i
+#include "wmc_auto.h"
+#include "options.h"
+#include "cnst.h"
+#include "rom_com.h"
+#include "prot.h"
+
+
+/*--------------------------------------------------------------------------*
+ * env_adj()
+ *
+ * Adjust the band energies of noise-fill and low resolution bands
+ *--------------------------------------------------------------------------*/
+
+void env_adj (
+ const short *pulses, /* i : number of pulses per band */
+ const short length, /* i : length of spectrum */
+ const short last_sfm, /* i : index of the last band */
+ float *adj, /* o : adjustment factors for the envelope */
+ const float env_stab, /* i : Envelope stability parameter */
+ const short *sfmsize /* i : Band widths */
+)
+{
+ short i, j, group;
+ int npul;
+ short att_state;
+ short start, len;
+ float tmp;
+ float gain_adj;
+ short idx;
+
+ att_state = 0;
+ len = 0;
+ start = 0;
+
+ /* Find attenuation levels */
+ for( i = 0; i <= last_sfm ; i++ )
+ {
+ group = (sfmsize[i] >> 3) - 1;
+ npul = pulses[i];
+
+ if( length == L_FRAME32k )
+ {
+ if( npul == 0 )
+ {
+ /* Noise filled band */
+ if ( group <= 1 )
+ {
+ if ( i > 0 && pulses[i-1] != 0 && pulses[i+1] != 0 )
+ {
+ adj[i] = 0.36f;
+ }
+ else if ( i > 0 && ( pulses[i-1] == 0 || pulses[i+1] == 0) )
+ {
+ adj[i] = 0.54f;
+ }
+ else
+ {
+ adj[i] = 0.72f;
+ }
+ }
+ else if (i < last_sfm)
+ {
+ if ( pulses[i-1] != 0 && pulses[i+1] != 0 )
+ {
+ adj[i] = 0.54f;
+ }
+ else
+ {
+ adj[i] = 0.72f;
+ }
+ }
+ else
+ {
+ adj[i] = 0.72f;
+ }
+
+ if( att_state == 0 )
+ {
+ start = i;
+ }
+
+ len++;
+ att_state = 1;
+ }
+ else
+ {
+ adj[i] = 1.0f;
+ if(att_state == 1) /* End of attenuation region found */
+ {
+ tmp = min(1, max(0, len-ENV_ADJ_START)*(1.0f/ENV_ADJ_INCL));
+ for( j = start; j < i ; j++ )
+ {
+ adj[j] = max(tmp + (1-tmp)*adj[j],env_stab);
+ }
+ len = 0;
+ att_state = 0;
+ }
+ }
+ }
+ /* length == L_FRAME16k */
+ else
+ {
+ /* Calculate low accuracy band attenuation */
+ gain_adj = 1.0f;
+ if( npul > 0 && npul < MAX_P_ATT )
+ {
+ idx = (short)(npul * att_step[group] + 0.5f) - 1;
+ if( idx < MAX_P_ATT )
+ {
+ gain_adj = gain_att[idx];
+ }
+ }
+ adj[i] = gain_adj;
+ }
+ }
+
+ /* Check if the sequence ended with an attenuation region */
+ if( att_state == 1 )
+ {
+ tmp = min(1, max(0, len-ENV_ADJ_START)*(1.0f/ENV_ADJ_INCL));
+
+ for( j = start; j < i ; j++ )
+ {
+ adj[j] = max(tmp + (1-tmp)*adj[j],env_stab);
+ }
+ }
+
+ return;
+}
diff --git a/lib_com/env_stab.c b/lib_com/env_stab.c
new file mode 100644
index 0000000000000000000000000000000000000000..5f52e4253c8f4fdd3ae86aea6d6ca1925c870cf4
--- /dev/null
+++ b/lib_com/env_stab.c
@@ -0,0 +1,169 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include "options.h"
+#include "wmc_auto.h"
+#include "cnst.h"
+#include "prot.h"
+#include "rom_com.h"
+#include
+
+/*--------------------------------------------------------------------------*
+ * Local constants
+ *--------------------------------------------------------------------------*/
+
+#define ENV_STAB_SMO_HO 10 /* number of hangover frames when switching from music to speech state */
+
+/*--------------------------------------------------------------------------*/
+/* Function env_stability() */
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~ */
+/* */
+/* Envelope stability measure */
+/*--------------------------------------------------------------------------*/
+
+float env_stability(
+ const short *ynrm, /*i : Norm vector for current frame */
+ const short nb_sfm, /*i : Number of sub-bands */
+ short *mem_norm, /*i/o: Norm vector memory from past frame */
+ short *mem_env_delta /*i/o: Envelope stability memory for smoothing (Q12)*/
+)
+{
+ Word16 env_delta;
+ Word16 env_stab;
+ Word16 tmp, tmp_stab;
+ Word16 i;
+
+ Word16 exp, exp2;
+ Word32 L_tmp, L_env_delta;
+ Word16 inv_nb_sfm;
+ float env_stab_f;
+
+ /* Calculate envelope stability parameter */
+ L_env_delta = L_deposit_l(0);
+ for (i = 0; i < nb_sfm; i++)
+ {
+ tmp = sub(mem_norm[i],ynrm[i]);
+ L_env_delta = L_mac0(L_env_delta, tmp, tmp);
+ mem_norm[i] = ynrm[i];
+ }
+
+ inv_nb_sfm = 19418; /* Q19 */
+ if (nb_sfm == 26)
+ {
+ inv_nb_sfm = 20165; /* Q19 */
+ }
+ exp = norm_l(L_env_delta);
+ L_env_delta = Mult_32_16(L_shl(L_env_delta, exp), inv_nb_sfm); /* 0+exp+19-15 */
+
+ L_tmp = Sqrt_l(L_env_delta, &exp2); /* exp+4+31+exp2 */
+
+ exp = add(35, add(exp, exp2));
+ if ( sub(s_and(exp, 1), 1) == 0 )
+ {
+ L_tmp = Mult_32_16(L_tmp, 23170); /* 1/sqrt(2) in Q15 */
+ }
+ exp = shr(exp, 1);
+
+ env_delta = round_fx(L_shl(L_tmp, sub(26, exp))); /* Q10 */
+
+ L_tmp = L_mult0(26214, env_delta); /* 26214 is 0.1 in Q18. Q28 */
+ L_tmp = L_mac(L_tmp, 29491, *mem_env_delta); /* 29491 is 0.9 in Q15. Q28 */
+
+ *mem_env_delta = round_fx(L_tmp); /* Q12 */
+ Overflow = 0;
+ env_delta = round_fx(L_shl(L_tmp, 1)); /* Q13 */
+
+ if (Overflow != 0) /* Saturated due to the above up-shifting operation. */
+ {
+ env_stab = stab_trans_fx[L_STAB_TBL-1]; /* The highest quantized index. */
+ env_stab_f = ((float)env_stab)/32768.0f; /* Convert env_stab(Q15) to float */
+ return env_stab_f;
+ }
+
+ /* If tmp_stab > (D_STAB_TBL*L_STAB_TBL + M_STAB_TBL), i.e., 0.103138*10+2.51757=3.603137,
+ * the quantized index is equal to 9. Hence, we only need to worry about any tmpStab < 4.
+ * In this case, Q13 is good enough.
+ */
+ tmp_stab = sub(env_delta, M_STAB_TBL_FX); /* in Q13 */
+ tmp_stab = abs_s(tmp_stab);
+
+ /* Table lookup for smooth transitions
+ * First, find the quantization level, i, of tmpStab. */
+#if L_STAB_TBL > 10
+#error env_stability_fx: Use more efficient usquant()
+#endif
+ tmp_stab = sub(tmp_stab, HALF_D_STAB_TBL_FX); /* in Q13 */
+ for (i = 0; i < L_STAB_TBL-1; i++)
+ {
+ if (tmp_stab < 0)
+ {
+ break;
+ }
+ else
+ {
+ tmp_stab = sub(tmp_stab, D_STAB_TBL_FX); /* in Q13 */
+ }
+ }
+
+ env_stab = stab_trans_fx[i];
+ if(sub(env_delta, M_STAB_TBL_FX) < 0)
+ {
+ env_stab = sub(0x7FFF,stab_trans_fx[i]);
+ }
+
+ env_stab_f = ((float)env_stab)/32768.0f; /* Convert env_stab(Q15) to float */
+
+ return env_stab_f;
+}
+
+/*--------------------------------------------------------------------------*
+ * env_stab_smo_fx()
+ *
+ *
+ *--------------------------------------------------------------------------*/
+
+float env_stab_smo(
+ float env_stab, /*i : env_stab value */
+ float *env_stab_state_p, /*i/o: env_stab state probabilities */
+ short *ho_cnt /*i/o: hangover counter for speech state */
+)
+{
+ short state, prev_state;
+ float maxval, pp[NUM_ENV_STAB_PLC_STATES], pa[NUM_ENV_STAB_PLC_STATES];
+ /* get previous state */
+ prev_state = maximum(env_stab_state_p,NUM_ENV_STAB_PLC_STATES,&maxval);
+
+ /* assume two states: speech(0), music(1) */
+ /* set a posteriori likelihoods for the two states according to env_stab */
+ env_stab = (env_stab - stab_trans[L_STAB_TBL-1])/(1-2*stab_trans[L_STAB_TBL-1]);
+ pp[0] = 1.0f-env_stab;
+ pp[1] = env_stab;
+
+ /* calculate a priori likelihoods */
+ pa[0] = dotp(env_stab_tp[0],env_stab_state_p,NUM_ENV_STAB_PLC_STATES);
+ pa[1] = dotp(env_stab_tp[1],env_stab_state_p,NUM_ENV_STAB_PLC_STATES);
+
+ /* multiply elementwise with a posteriori likelihoods */
+ v_mult(pa,pp,env_stab_state_p,NUM_ENV_STAB_PLC_STATES);
+
+ /* renormalize state probabilities */
+ v_multc(env_stab_state_p,1.0f/sum_f(env_stab_state_p,NUM_ENV_STAB_PLC_STATES),env_stab_state_p,NUM_ENV_STAB_PLC_STATES);
+
+ /* find maximum index as return value */
+ state = maximum(env_stab_state_p,NUM_ENV_STAB_PLC_STATES,&maxval);
+
+ /* apply some hangover for speech */
+ if (state==0 && prev_state==1)
+ {
+ *ho_cnt=ENV_STAB_SMO_HO;
+ }
+ if (*ho_cnt>0)
+ {
+ pp[0]=1;
+ pp[1]=0;
+ (*ho_cnt)--;
+ }
+
+ return state;
+}
diff --git a/lib_com/env_stab_trans.c b/lib_com/env_stab_trans.c
new file mode 100644
index 0000000000000000000000000000000000000000..b7fb5dfd6b8f3245cd493bb2d29e3371568404c0
--- /dev/null
+++ b/lib_com/env_stab_trans.c
@@ -0,0 +1,124 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include "options.h"
+#include "wmc_auto.h"
+#include "cnst.h"
+#include "prot.h"
+#include "rom_com.h"
+#include
+
+
+/*--------------------------------------------------------------------------*
+ * env_stab_transient_detect()
+ *
+ * Transient detector for envelope stability measure
+ *--------------------------------------------------------------------------*/
+
+void env_stab_transient_detect(
+ const short is_transient, /* i: Transient flag */
+ const short length, /* i : Length of spectrum (32 or 48 kHz) */
+ const short norm[], /* i : quantization indices for norms */
+ short *no_att_hangover, /* i/o: Frame counter for attenuation hangover */
+ float *energy_lt, /* i/o: Long-term energy measure for transient detection */
+ const short HQ_mode, /* i : HQ coding mode */
+ const short bin_th, /* i : HVQ cross-over frequency bin */
+ const float *coeff /* i : Coded spectral coefficients */
+)
+{
+ float d_max;
+ float e_frame;
+ short blk;
+ short i;
+ float E_sub[4];
+ float delta_e_sub;
+ short norm_ind;
+
+ short num_subframes = 4;
+ short bands_per_subframe = 9;
+
+ if( HQ_mode == HQ_HVQ )
+ {
+ e_frame = 0.0f;
+
+ for (i = 0; i < bin_th; i++)
+ {
+ e_frame += coeff[i]*coeff[i];
+ }
+
+ e_frame = (float)sqrt(e_frame / bin_th);
+
+ if (e_frame > ENERGY_TH)
+ {
+ *energy_lt = ENERGY_LT_BETA*(*energy_lt) + (1-ENERGY_LT_BETA)*e_frame;
+ }
+
+ if (*no_att_hangover > 0)
+ {
+ (*no_att_hangover)--;
+ }
+ }
+ else
+ {
+ d_max = 0.0f;
+ e_frame = 0.0f;
+ if (is_transient && length == L_FRAME32k)
+ {
+ /* Measure subframe energies */
+ for (blk = 0; blk < num_subframes; blk++)
+ {
+ E_sub[blk] = 0.0f;
+ for (i=0; i ENERGY_TH * num_subframes)
+ {
+ for (blk = 0; blk < num_subframes-1; blk++)
+ {
+ delta_e_sub = (E_sub[blk+1]-E_sub[blk]) / *energy_lt;
+ if (delta_e_sub > d_max)
+ {
+ d_max = delta_e_sub;
+ }
+ }
+ }
+ }
+ else
+ {
+ /* Update long-term energy measure */
+ e_frame = 0.0f;
+
+ for (i = 0; i < SFM_N_ENV_STAB; i++)
+ {
+ e_frame += dicn[norm[i]];
+ }
+
+ e_frame = e_frame / SFM_N_ENV_STAB;
+
+ if (e_frame > ENERGY_TH)
+ {
+ *energy_lt = ENERGY_LT_BETA*(*energy_lt) + (1-ENERGY_LT_BETA)*e_frame;
+ }
+ }
+
+ /* Add hang-over for conservative application of stability-dependent attenuation */
+ if(d_max > DELTA_TH)
+ {
+ *no_att_hangover = ATT_LIM_HANGOVER;
+ }
+ else if (*no_att_hangover > 0)
+ {
+ (*no_att_hangover)--;
+ }
+
+ }
+
+ return;
+}
diff --git a/lib_com/est_tilt.c b/lib_com/est_tilt.c
new file mode 100644
index 0000000000000000000000000000000000000000..36543070094e1929102973c8894d2b0a06e854a5
--- /dev/null
+++ b/lib_com/est_tilt.c
@@ -0,0 +1,57 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include "options.h"
+#include "wmc_auto.h"
+#include "cnst.h"
+#include "prot.h"
+
+
+/*-------------------------------------------------------------------*
+ * est_tilt()
+ *
+ * Estimate spectral tilt based on the relative E of adaptive
+ * and innovative excitations
+ *-------------------------------------------------------------------*/
+
+float est_tilt( /* o : tilt of the code */
+ const float *adpt_exc, /* i : adaptive excitation vector */
+ const float gain_pit, /* i : adaptive gain */
+ const float *fixe_exc, /* i : algebraic exctitation vector */
+ const float gain_code, /* i : algebraic code gain */
+ float *voice_fac, /* o : voicing factor */
+ const short L_subfr, /* i : subframe size */
+ const short flag_tilt /* i : flag for special tilt */
+)
+{
+ float ener, tmp, tilt_code;
+
+ ener = dotp( adpt_exc, adpt_exc, L_subfr );
+ ener *= gain_pit * gain_pit; /* energy of pitch excitation */
+
+ tmp = dotp( fixe_exc, fixe_exc, L_subfr );
+ tmp *= gain_code * gain_code; /* energy of innovative code excitation */
+
+ /* find voice factor (1=voiced, -1=unvoiced) */
+ *voice_fac = (float)((ener - tmp) / (ener + tmp + 0.01f));
+
+ /* find tilt of code for next subframe */
+ if (flag_tilt==0)
+ {
+ /*Between 0 (=unvoiced) and 0.5 (=voiced)*/
+ tilt_code = (float)(0.25f*(1.0f + *voice_fac));
+ }
+ else if (flag_tilt==1)
+ {
+ /*Between 0.25 (=unvoiced) and 0.5 (=voiced)*/
+ tilt_code = (float)(0.25f + (*voice_fac+1.0f)*0.125f);
+ }
+ else
+ {
+ /*Between 0.28 (=unvoiced) and 0.56 (=voiced)*/
+ tilt_code = (float)(0.28f + (*voice_fac+1.0f)*0.14f);
+ }
+
+ return tilt_code;
+}
diff --git a/lib_com/fd_cng_com.c b/lib_com/fd_cng_com.c
new file mode 100644
index 0000000000000000000000000000000000000000..6d7bf29d6812b1f5d652852a9f5d2d3bf6f6c1bb
--- /dev/null
+++ b/lib_com/fd_cng_com.c
@@ -0,0 +1,1081 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include
+#include "wmc_auto.h"
+#include
+#include "options.h"
+#include "prot.h"
+#include "rom_com.h"
+
+
+
+/*-------------------------------------------------------------------
+ * Local functions
+ *-------------------------------------------------------------------*/
+
+static void mhvals( int d, float * m );
+
+
+/*-------------------------------------------------------------------
+ * createFdCngCom()
+ *
+ * Create an instance of type FD_CNG_COM
+ *-------------------------------------------------------------------*/
+
+void createFdCngCom(
+ HANDLE_FD_CNG_COM * hFdCngCom
+)
+{
+ HANDLE_FD_CNG_COM hs;
+
+ /* Allocate memory */
+ hs = (HANDLE_FD_CNG_COM) calloc(1, sizeof (FD_CNG_COM));
+
+ *hFdCngCom = hs;
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------
+ * initFdCngCom()
+ *
+ *
+ *-------------------------------------------------------------------*/
+
+void initFdCngCom(
+ HANDLE_FD_CNG_COM hs, /* i/o: Contains the variables related to the FD-based CNG process */
+ float scale
+)
+{
+
+ /* Calculate FFT scaling factor */
+ hs->scalingFactor = 1 / (scale*scale*8.f);
+
+ /* Initialize the overlap-add */
+ set_f( hs->timeDomainBuffer, 0.0f, L_FRAME16k );
+ set_f( hs->olapBufferAna, 0.0f, FFTLEN );
+ set_f( hs->olapBufferSynth, 0.0f, FFTLEN );
+ set_f( hs->olapBufferSynth2, 0.0f, FFTLEN );
+
+ /* Initialize the comfort noise generation */
+ set_f( hs->fftBuffer, 0.0f, FFTLEN );
+ set_f( hs->cngNoiseLevel, 0.0f, FFTCLDFBLEN );
+
+ /* Initialize quantizer */
+ set_f( hs->sidNoiseEst, 0.0f, NPART );
+ set_f( hs->A_cng, 0.0f, M+1 );
+ hs->A_cng[0] = 1.f;
+
+ /* Set some counters and flags */
+ hs->inactive_frame_counter = 0; /* Either SID or zero frames */
+ hs->active_frame_counter = 0;
+ hs->frame_type_previous = ACTIVE_FRAME;
+ hs->flag_noisy_speech = 0;
+ hs->likelihood_noisy_speech = 0.f;
+ hs->numCoreBands = 0;
+ hs->stopBand = 0;
+ hs->startBand = 0;
+ hs->stopFFTbin = 0;
+ hs->frameSize = 0;
+ hs->fftlen = 0;
+
+ /* Initialize noise estimation algorithm */
+ set_f( hs->periodog, 0.0f, PERIODOGLEN );
+ mhvals(MSNUMSUBFR*MSSUBFRLEN, &(hs->msM_win));
+ mhvals(MSSUBFRLEN, &(hs->msM_subwin));
+ set_f( hs->msPeriodogSum, 0.0f, 2 );
+ set_f( hs->msPsdSum, 0.0f, 2 );
+ set_f( hs->msSlope, 0.0f, 2 );
+ set_f( hs->msQeqInvAv, 0.0f, 2 );
+ hs->msFrCnt_init_counter = 0;
+ hs->msFrCnt_init_thresh = 1;
+ hs->init_old = 0;
+ hs->offsetflag = 0;
+ hs->msFrCnt = MSSUBFRLEN;
+ hs->msMinBufferPtr = 0;
+ set_f( hs->msAlphaCor, 0.3f, 2 );
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------
+ * deleteFdCngCom()
+ *
+ * Delete an instance of type FD_CNG_COM
+ *-------------------------------------------------------------------*/
+
+void deleteFdCngCom(
+ HANDLE_FD_CNG_COM * hFdCngCom /* i/o: Contains the variables related to the FD-based CNG process */
+)
+{
+ HANDLE_FD_CNG_COM hsCom = *hFdCngCom;
+ if (hsCom != NULL)
+ {
+ free(hsCom);
+ *hFdCngCom = NULL;
+ }
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------
+ * initPartitions()
+ *
+ * Initialize the spectral partitioning
+ *-------------------------------------------------------------------*/
+
+void initPartitions(
+ const int * part_in,
+ int npart_in,
+ int startBand,
+ int stopBand,
+ int * part_out,
+ int * npart_out,
+ int * midband,
+ float * psize,
+ float * psize_inv,
+ int stopBandFR
+)
+{
+ int i, j, len_out;
+
+ if (part_in != NULL)
+ {
+ if (stopBandFR > startBand)
+ {
+ len_out = stopBandFR - startBand; /*part_out*/
+ for(i = 0 ; i < len_out ; i++)
+ {
+ part_out[i] = i;
+ }
+ }
+ else
+ {
+ len_out = 0;
+ } /*npart_in,part_out*/
+ for(j=0 ; j= stopBandFR && part_in[j] >= startBand)
+ {
+ part_out[len_out++] = part_in[j] - startBand;
+ }
+ }
+ }
+ else
+ {
+ len_out = stopBand - startBand; /*part_out*/
+ for (i = 0 ; i < len_out ; i++)
+ {
+ part_out[i] = i;
+ }
+ }
+ *npart_out = len_out;
+ getmidbands(part_out, len_out, midband, psize, psize_inv);
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------
+ * compress_range()
+ *
+ * Apply some dynamic range compression based on the log
+ *-------------------------------------------------------------------*/
+
+void compress_range(
+ float* in,
+ float* out,
+ int len
+)
+{
+ float* ptrIn = in;
+ float* ptrOut = out;
+ int i;
+
+ /* out = log2( 1 + in ) */
+ for(i = 0 ; i < len ; i++)
+ {
+ *ptrOut = (float)log10(*ptrIn + 1.f);
+ ptrIn++;
+ ptrOut++;
+ }
+ v_multc(out, 1.f/(float)log10(2.f), out, len);
+
+ /* Quantize to simulate a fixed-point representation 6Q9 */
+ v_multc(out, CNG_LOG_SCALING, out, len);
+ for(ptrOut = out ; ptrOut < out + len ; ptrOut++)
+ {
+ *ptrOut = (float)((int)(*ptrOut+0.5f));
+ if ( *ptrOut == 0.f )
+ {
+ *ptrOut = 1.f;
+ }
+ }
+ v_multc(out, 1./CNG_LOG_SCALING, out, len);
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------
+ * expand_range()
+ *
+ * Apply some dynamic range expansion to undo the compression
+ *-------------------------------------------------------------------*/
+
+void expand_range(
+ float* in,
+ float* out,
+ int len
+)
+{
+ float* ptrIn = in;
+ float* ptrOut = out;
+ int i;
+
+ /* out = (2^(in) - 1) */
+ for(i = 0 ; i < len ; i++)
+ {
+ *ptrOut = (float)pow(2.f,*ptrIn) - 1.f;
+ if ( *ptrOut < 0.0003385080526823181f )
+ {
+ *ptrOut = 0.0003385080526823181f;
+ }
+ ptrIn++;
+ ptrOut++;
+ }
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------
+ * minimum_statistics()
+ *
+ * Noise estimation using Minimum Statistics (MS)
+ *-------------------------------------------------------------------*/
+
+void minimum_statistics(
+ int len, /* i : Vector length */
+ int lenFFT, /* i : Length of the FFT part of the vectors */
+ float * psize,
+ float * msPeriodog, /* i : Periodograms */
+ float * msNoiseFloor,
+ float * msNoiseEst, /* o : Noise estimates */
+ float * msAlpha,
+ float * msPsd,
+ float * msPsdFirstMoment,
+ float * msPsdSecondMoment,
+ float * msMinBuf,
+ float * msBminWin,
+ float * msBminSubWin,
+ float * msCurrentMin,
+ float * msCurrentMinOut,
+ float * msCurrentMinSubWindow,
+ int * msLocalMinFlag,
+ int * msNewMinFlag,
+ float * msPeriodogBuf,
+ int * msPeriodogBufPtr,
+ HANDLE_FD_CNG_COM st /* i/o: FD_CNG structure containing all buffers and variables */
+)
+{
+ float msM_win = st->msM_win;
+ float msM_subwin = st->msM_subwin;
+ float * msPsdSum = st->msPsdSum;
+ float * msPeriodogSum = st->msPeriodogSum;
+ float slope;
+ float * ptr;
+ float msAlphaCorAlpha = MSALPHACORALPHA;
+ float msAlphaCorAlpha2 = 1.f-MSALPHACORALPHA;
+
+ short i,j,k;
+ float scalar, scalar2, scalar3;
+ float snr, BminCorr, QeqInv, QeqInvAv;
+ float beta;
+ float msAlphaHatMin2;
+ int len2 = MSNUMSUBFR*len;
+ int current_len;
+ short start, stop, cnt;
+ int totsize;
+
+ /* No minimum statistics at initialization */
+ if (st->msFrCnt_init_counter < st->msFrCnt_init_thresh)
+ {
+ mvr2r(msPeriodog, msPsd, len);
+ mvr2r(msPeriodog, msNoiseFloor, len);
+ mvr2r(msPeriodog, msNoiseEst, len);
+ mvr2r(msPeriodog, msPsdFirstMoment, len);
+ set_f( msPsdSecondMoment, 0.0f, len);
+ msPeriodogSum[0] = dotp(msPeriodog, psize, lenFFT);
+ msPsdSum[0] = msPeriodogSum[0];
+ if (lenFFT ignore them */
+ if (msPeriodog[0]init_old)
+ {
+ set_f(msCurrentMinOut, FLT_MAX, len);
+ set_f(msCurrentMin, FLT_MAX, len);
+ set_f(msMinBuf, FLT_MAX, len2);
+ set_f(msCurrentMinSubWindow, FLT_MAX, len);
+ st->msFrCnt_init_counter++;
+ }
+ st->init_old = msPeriodog[0];
+ }
+
+ else
+ {
+
+ /* Consider the FFT and CLDFB bands separately
+ - first iteration for FFT bins,
+ - second one for CLDFB bands in SWB mode */
+ start = 0;
+ stop = lenFFT;
+ totsize = st->stopFFTbin-st->startBand;
+ cnt = 0; /*msAlphaCor*/
+ while (stop > start)
+ {
+ current_len = stop-start;
+
+ /* Compute smoothed correction factor for PSD smoothing */
+ msPeriodogSum[cnt] = dotp(msPeriodog+start, psize+start, current_len);
+ scalar = msPeriodogSum[cnt]*msPeriodogSum[cnt] + DELTA;
+ scalar2 = msPsdSum[cnt] - msPeriodogSum[cnt];
+ scalar = max(scalar / (scalar + scalar2*scalar2) , MSALPHACORMAX);
+ st->msAlphaCor[cnt] = msAlphaCorAlpha*st->msAlphaCor[cnt] + msAlphaCorAlpha2*scalar;
+
+ /* Compute SNR */
+ snr = dotp(msNoiseFloor+start, psize+start, current_len);
+ snr = (msPsdSum[cnt] + DELTA) / (snr + DELTA);
+ snr = (float)pow(snr, MSSNREXP);
+ msAlphaHatMin2 = min( MSALPHAHATMIN, snr );
+ scalar = MSALPHAMAX * st->msAlphaCor[cnt]; /*msAlpha,msPsd,msPeriodog,msNoiseFloor*/
+ for(j=start ; jmsQeqInvAv[cnt] = QeqInvAv;
+
+ /* New minimum? */
+ BminCorr = 1.f + MSAV * (float)sqrt(QeqInvAv); /*msPsd,msBminWin,msNewMinFlag,msCurrentMin,msCurrentMinSubWindow*/
+ for(j=start ; jmsFrCnt >= MSSUBFRLEN)
+ {
+ i = 0;
+ while (i < 3)
+ {
+ if (st->msQeqInvAv[cnt] < msQeqInvAv_thresh[i])
+ {
+ break;
+ }
+ else
+ {
+ i++;
+ }
+ }
+ st->msSlope[cnt] = msNoiseSlopeMax[i];
+ }
+
+ /* Consider the FFT and CLDFB bands separately */
+ start = stop;
+ stop = len;
+ totsize = st->stopBand - st->stopFFTbin;
+ cnt++;
+ } /*while (stop > start)*/
+
+ /* Update minimum between sub windows */
+ if( st->msFrCnt > 1 && st->msFrCnt < MSSUBFRLEN )
+ {
+ /*msNewMinFlag,msCurrentMinSubWindow,msCurrentMinOut*/
+ for(j=0 ; j 0)
+ {
+ msLocalMinFlag[j] = 1;
+ }
+ if (msCurrentMinSubWindow[j] < msCurrentMinOut[j])
+ {
+ msCurrentMinOut[j] = msCurrentMinSubWindow[j];
+ }
+ }
+ /* Get the current noise floor */
+ mvr2r(msCurrentMinOut, msNoiseFloor, len);
+ }
+
+ /* sub window complete */
+ else
+ {
+ if (st->msFrCnt >= MSSUBFRLEN)
+ {
+ /* Collect buffers */
+ mvr2r(msCurrentMinSubWindow, msMinBuf+len*st->msMinBufferPtr, len);
+
+ /* Compute minimum among all buffers */
+ mvr2r(msMinBuf, msCurrentMinOut, len);
+ ptr = msMinBuf + len;
+ for (i=1 ; imsSlope[0]; /*msLocalMinFlag,msNewMinFlag,msCurrentMinSubWindow,msCurrentMinOut*/
+ for(j=0 ; jmsSlope[1];
+ }
+ if ( msLocalMinFlag[j] && !msNewMinFlag[j] &&
+ msCurrentMinSubWindow[j]msCurrentMinOut[j] )
+ {
+ msCurrentMinOut[j] = msCurrentMinSubWindow[j];
+ i = j;
+ for(k=0 ; k50.f*msPeriodogSum[0])
+ {
+ if (st->offsetflag>0)
+ {
+ mvr2r(msPeriodog, msPsd, len);
+ mvr2r(msPeriodog, msCurrentMinOut, len);
+ set_f( st->msAlphaCor, 1.0f, cnt);
+ set_f( msAlpha, 0.0f, len);
+ mvr2r(msPeriodog, msPsdFirstMoment, len);
+ set_f( msPsdSecondMoment, 0.0f, len);
+ msPsdSum[0] = dotp(msPeriodog, psize, lenFFT);
+ if (lenFFToffsetflag = 1;
+ }
+ else
+ {
+ st->offsetflag = 0;
+ }
+
+
+ /* Increment frame counter */
+ if (st->msFrCnt == MSSUBFRLEN)
+ {
+ st->msFrCnt = 1;
+ st->msMinBufferPtr++;
+ if (st->msMinBufferPtr==MSNUMSUBFR)
+ {
+ st->msMinBufferPtr = 0;
+ }
+ }
+ else
+ {
+ (st->msFrCnt)++;
+ }
+
+ {
+ /* Smooth noise estimate during CNG phases */ /*msNoiseEst,msNoiseFloor*/
+ for(j=0 ; jscalar)
+ {
+ msNoiseEst[j] = scalar;
+ }
+ assert(msNoiseEst[j] >= 0);
+ }
+ }
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------
+ * apply_scale()
+ *
+ * Apply bitrate-dependent scale
+ *-------------------------------------------------------------------*/
+
+void apply_scale(
+ float *scale,
+ int bandwidth,
+ int bitrate
+)
+{
+ int i;
+ int scaleTableSize = sizeof (scaleTable) / sizeof (scaleTable[0]);
+
+ for (i = 0 ; i < scaleTableSize ; i++)
+ {
+ if ( (bandwidth == scaleTable[i].bwmode) &&
+ (bitrate >= scaleTable[i].bitrateFrom) &&
+ (bitrate < scaleTable[i].bitrateTo) )
+ {
+ break;
+ }
+ }
+
+ *scale += scaleTable[i].scale;
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------
+ * bandcombinepow()
+ *
+ * Compute the power for each partition
+ *-------------------------------------------------------------------*/
+
+void bandcombinepow(
+ float* bandpow, /* i : Power for each band */
+ int nband, /* i : Number of bands */
+ int* part, /* i : Partition upper boundaries (band indices starting from 0) */
+ int npart, /* i : Number of partitions */
+ float* psize_inv, /* i : Inverse partition sizes */
+ float* partpow /* o : Power for each partition */
+)
+{
+
+ int i, p;
+ float temp;
+
+ if (nband == npart)
+ {
+ mvr2r(bandpow, partpow, nband);
+ }
+ else
+ {
+ /* Compute the power in each partition */
+ i = 0; /*part,partpow,psize_inv*/
+ for (p = 0; p < npart; p++)
+ {
+ /* Arithmetic averaging of power for all bins in partition */
+ temp = 0;
+ for ( ; i <= part[p]; i++)
+ {
+ temp += bandpow[i];
+ }
+ partpow[p] = temp*psize_inv[p];
+ }
+ }
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------
+ * scalebands()
+ *
+ * Scale partitions (with smoothing)
+ *-------------------------------------------------------------------*/
+
+void scalebands(
+ float* partpow, /* i : Power for each partition */
+ int* part, /* i : Partition upper boundaries (band indices starting from 0) */
+ int npart, /* i : Number of partitions */
+ int* midband, /* i : Central band of each partition */
+ int nFFTpart, /* i : Number of FFT partitions */
+ int nband, /* i : Number of bands */
+ float* bandpow, /* o : Power for each band */
+ short flag_fft_en
+)
+{
+ int i, j=0, nint, startBand, startPart, stopPart;
+ float val, delta = 0.f;
+
+
+ /* Interpolate the bin/band-wise levels from the partition levels */
+ if (nband == npart)
+ {
+ mvr2r(partpow, bandpow, npart);
+ }
+ else
+ {
+ startBand = 0;
+ startPart = 0;
+ stopPart = nFFTpart;
+ while (startBand < nband)
+ {
+ if (flag_fft_en || startPart>=nFFTpart)
+ {
+
+ /* first half partition */
+ j = startPart;
+ val = partpow[j];
+ for (i = startBand; i <= midband[j]; i++)
+ {
+ bandpow[i] = val;
+ }
+ j++;
+
+ delta = 1;
+ /* inner partitions */
+ for ( ; j < stopPart ; j++)
+ {
+ nint = midband[j] - midband[j-1];
+ /* log-linear interpolation */ /* Only one new LOG needs to be computed per loop iteration */
+ delta = (float)exp( (log(partpow[j]+DELTA) - log(partpow[j-1]+DELTA)) * normReciprocal[nint] );
+ val = partpow[j-1];
+ for ( ; i < midband[j]; i++)
+ {
+ val *= delta;
+ bandpow[i] = val;
+ }
+ bandpow[i++] = partpow[j];
+ }
+ if ( delta>1.f )
+ {
+ delta = 1.f;
+ }
+
+ /* last half partition */
+ val = partpow[stopPart-1];
+ for ( ; i <= part[stopPart-1]; i++)
+ {
+ val *= delta;
+ bandpow[i] = val;
+ }
+ }
+ startBand = part[stopPart-1]+1;
+ startPart = stopPart;
+ stopPart = npart;
+ }
+ }
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------
+ * getmidbands()
+ *
+ * Get central band for each partition
+ *-------------------------------------------------------------------*/
+
+void getmidbands(
+ int* part, /* i : Partition upper boundaries (band indices starting from 0) */
+ int npart, /* i : Number of partitions */
+ int* midband, /* o : Central band of each partition */
+ float* psize, /* o : Partition sizes */
+ float* psize_inv /* o : Inverse of partition sizes */
+)
+{
+ int j;
+
+
+ /* first half partition */
+ midband[0] = part[0];
+ psize[0] = (float)part[0] + 1.f;
+ psize_inv[0] = normReciprocal[part[0] + 1];
+ /* inner partitions */ /*part,midband,psize_inv*/
+ for (j = 1; j < npart; j++)
+ {
+ midband[j] = (part[j-1]+1 + part[j]) >> 1;
+ psize[j] = (float)(part[j] - part[j-1]);
+ psize_inv[j] = normReciprocal[part[j] - part[j-1]];
+ }
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------
+ * AnalysisSTFT()
+ *
+ * STFT analysis filterbank
+ *-------------------------------------------------------------------*/
+
+void AnalysisSTFT(
+ const float * timeDomainInput,
+ float * fftBuffer, /* o : FFT bins */
+ HANDLE_FD_CNG_COM st /* i/o: FD_CNG structure containing all buffers and variables */
+)
+{
+ float *olapBuffer = st->olapBufferAna;
+ const float *olapWin = st->olapWinAna;
+
+ /* Shift and cascade for overlap-add */
+ mvr2r(olapBuffer+st->frameSize, olapBuffer, st->fftlen-st->frameSize);
+ mvr2r(timeDomainInput, olapBuffer+st->fftlen-st->frameSize, st->frameSize);
+
+ /* Window the signal */
+ v_mult(olapBuffer, olapWin, fftBuffer, st->fftlen);
+
+
+ /* Perform FFT */
+ RFFTN(fftBuffer, st->fftSineTab, st->fftlen, -1);
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------
+ * SynthesisSTFT()
+ *
+ * STFT synthesis filterbank
+ *-------------------------------------------------------------------*/
+
+void SynthesisSTFT(
+ float * fftBuffer, /* i : FFT bins */
+ float * timeDomainOutput,
+ float * olapBuffer,
+ const float * olapWin,
+ int tcx_transition,
+ HANDLE_FD_CNG_COM st /* i/o: FD_CNG structure containing all buffers and variables */
+)
+{
+ short i;
+ float buf[M+1+320], tmp;
+
+ /* Perform IFFT */
+ RFFTN(fftBuffer, st->fftSineTab, st->fftlen, 1);
+
+ /* Perform overlap-add */
+ mvr2r(olapBuffer+st->frameSize, olapBuffer, st->frameSize);
+ set_f( olapBuffer+st->frameSize, 0.0f, st->frameSize); /*olapBuffer, fftBuffer, olapWin*/
+ if ( tcx_transition )
+ {
+ for (i=0 ; i<5*st->frameSize/4 ; i++)
+ {
+ olapBuffer[i] = fftBuffer[i];
+ }
+ }
+ else
+ {
+ for (i=st->frameSize/4 ; i<3*st->frameSize/4 ; i++)
+ {
+ olapBuffer[i] += fftBuffer[i] * olapWin[i-st->frameSize/4];
+ }
+ for ( ; i<5*st->frameSize/4 ; i++)
+ {
+ olapBuffer[i] = fftBuffer[i];
+ }
+ }
+ for ( ; i<7*st->frameSize/4 ; i++)
+ {
+ olapBuffer[i] = fftBuffer[i] * olapWin[i-3*st->frameSize/4];
+ }
+
+ for ( ; ifftlen ; i++)
+ {
+ olapBuffer[i] = 0;
+ }
+
+ /* Get time-domain signal */
+ v_multc( olapBuffer+st->frameSize/4, (float)(st->fftlen/2), timeDomainOutput, st->frameSize);
+
+ /* Get excitation */
+ v_multc( olapBuffer+st->frameSize/4-(M+1), (float)(st->fftlen/2), buf, M+1+st->frameSize );
+ tmp = buf[0];
+ preemph( buf+1, PREEMPH_FAC, M+st->frameSize, &tmp );
+ residu( st->A_cng, M, buf+1+M, st->exc_cng, st->frameSize );
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------
+ * mhvals()
+ *
+ * Compute some values used in the bias correction of the minimum statistics algorithm
+ *-------------------------------------------------------------------*/
+
+static void mhvals(
+ int d,
+ float * m
+)
+{
+ int i, j;
+ float qi, qj, q;
+ int len = sizeof(d_array)/sizeof(int);
+
+ i = 0;
+ for (i=0 ; iA_cng, Aq+i*(M+1), M+1 );
+ }
+ a2lsp_stab( Aq, lsp_new, lsp_old );
+ if( first_CNG == 0 )
+ {
+ mvr2r( lsp_old, lspCNG, M );
+ }
+ for( i=0; iexc_cng, exc, L_frame );
+ mvr2r( hs->exc_cng, exc2, L_frame );
+ if( L_frame == L_FRAME )
+ {
+ interp_code_5over2( exc2, bwe_exc, L_frame );
+ }
+ else
+ {
+ interp_code_4over2( exc2, bwe_exc, L_frame );
+ }
+
+ return;
+}
diff --git a/lib_com/fft.c b/lib_com/fft.c
new file mode 100644
index 0000000000000000000000000000000000000000..54b3016f780866d41b1f9161d8029e7190ccf06d
--- /dev/null
+++ b/lib_com/fft.c
@@ -0,0 +1,3619 @@
+ /*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+ #include
+ #include "wmc_auto.h"
+ #include
+ #include "options.h"
+ #include "cnst.h"
+ #include "prot.h"
+ #include "rom_com.h"
+
+ /*-----------------------------------------------------------------*
+ * Local functions
+ *-----------------------------------------------------------------*/
+
+ static void cdftForw( short n, float *a, const short *ip, const float *w );
+ static void bitrv2_SR( short n, const short *ip, float *a );
+ static void cftfsub( short n, float *a, const float *w );
+ static void cft1st(short n, float *a, const float *w);
+ static void cftmdl(short n, short l, float *a, const float *w);
+ static void fft16( float *x, float *y, const short *Idx );
+ static void fft5_shift1( int n1, float *zRe, float *zIm, const short *Idx );
+ static void fft8( float *x, float *y, const short *Idx );
+ static void fft15_shift2( int n1, float *zRe, float *zIm, const short *Idx );
+ static void fft15_shift8( int n1, float *zRe, float *zIm, const short *Idx );
+ static void fft5_shift4( int n1, float *zRe, float *zIm, const short *Idx );
+ static void fft5_32( float *zRe, float *zIm, const short *Idx );
+ static void fft64( float *x, float *y, const short *Idx );
+ static void fft32_15( float *x, float *y, const short *Idx );
+ static void fft32_5( float *x, float *y, const short *Idx );
+ static void fft8_5( float *x, float *y, const short *Idx );
+ static void fft5_8( int n1, float *zRe, float *zIm, const short *Idx );
+ static void fft4_5( float *x, float *y, const short *Idx );
+ static void fft5_4( int n1, float *zRe, float *zIm, const short *Idx );
+
+ static float fmac(float a, float b, float c)
+ {
+ return (((a) * (b)) + (c));
+ }
+
+ static float fnms(float a, float b, float c)
+ {
+ return ((c) - ((a) * (b)));
+ }
+
+ /*-----------------------------------------------------------------*
+ * fft15_shift2()
+ * 15-point FFT with 2-point circular shift
+ *-----------------------------------------------------------------*/
+
+ static void fft15_shift2(
+ int n1, /* i : length of data */
+ float *zRe, /* i/o : real part of input and output data */
+ float *zIm, /* i/o : imaginary part of input and output data */
+ const short *Idx /* i : pointer of the address table */
+ )
+ {
+ short in0, in8, in16, in24, in32, in1, in9, in17, in25, in33, in2, in10, in18, in26, in34;
+ float fi1, fi2, fi3, fi4, fi5, fi6, fi7, fi8, fi9, fi10, fi11, fi12, fi13, fi14, fi15;
+ float fi16, fi17, fi18, fi19, fi20, fi21, fi22, fi23, fi24, fi25, fi26, fi27, fi28, fi29, fi30;
+ float f2i1, f2i2, f2i3, f2i4, f2i5, f2i6, f2i7, f2i8, f2i9, f2i10, f2i11, f2i12;
+ float f2i13, f2i14, f2i15, f2i16, f2i17, f2i18, f2i19, f2i20, f2i21, f2i22, f2i23, f2i24;
+ float f3i1, f3i2, f3i3, f3i4, f3i5, f3i6, f3i7, f3i8, f3i9, f3i10, f3i11, f3i12, f3i13, f3i14, f3i15; //CR
+ float f4i1,f4i2, f4i3, f4i4, f4i5,f4i6, f4i7, f4i8, f4i9;
+ float f4i10, f4i11, f4i12, f4i13, f4i14, f4i15, f4i16, f4i17, f4i18, f4i19, f4i20, fo1, fo2, fo3, fo4;
+ float fo5,fo6, fo7, fo8, fo9,fo10, fo11, fo12, fo13, fo14, fo15, fo16, fo17, fo18;
+ float f2o1, f2o2, f2o3, f2o4, f2o5, f2o6, f2o7, f2o8, f2o9,f2o10, f2o11, f2o12, f2o13;
+ float f2o14, f2o15, f3o1, f3o2, f3o3, f3o4, f3o5, f3o6, f3o7,f3o8, f3o9, f3o10, f3o11;
+ float f3o12, f3o13, f3o14, f3o15, f4o1,f4o2, f4o3, f4o4, f4o5, f4o6;
+ float f4o7, f4o8, f4o9, f4o10,f4o11, f4o12, f4o13, f4o14, f4o15, f4o16, f4o17, f4o18, f4o19;
+
+ in0 = Idx[0];
+ in8 = Idx[n1];
+ in16 = Idx[n1*2];
+ in24 = Idx[n1*3];
+ in32 = Idx[n1*4];
+ in1 = Idx[n1*5];
+ in9 = Idx[n1*6];
+ in17 = Idx[n1*7];
+ in25 = Idx[n1*8];
+ in33 = Idx[n1*9];
+ in2 = Idx[n1*10];
+ in10 = Idx[n1*11];
+ in18 = Idx[n1*12];
+ in26 = Idx[n1*13];
+ in34 = Idx[n1*14];
+
+ f2i13 = zRe[in0];
+ f2i14 = zIm[in0];
+ f2i21 = zRe[in1];
+ f2i22 = zRe[in2];
+ f2i23 = zIm[in1];
+ f2i24 = zIm[in2];
+
+ f2i15 = f2i21 + f2i22;
+ f2i16 = FFT_15PONIT_WNK4 * (f2i22 - f2i21);
+ f2i17 = FFT_15PONIT_WNK4 * (f2i23 - f2i24);
+ f2i18 = f2i23 + f2i24;
+ fi1 = f2i13 + f2i15;
+ fi2 = f2i14 + f2i18;
+
+ f2i19 = fnms(0.5f, f2i15, f2i13);
+ f2i20 = fnms(0.5f, f2i18, f2i14);
+ fi3 = f2i19 - f2i17;
+ fi4 = f2i19 + f2i17;
+ fi5 = f2i16 + f2i20;
+ fi6 = f2i20 - f2i16;
+
+ f3i1 = zRe[in9];
+ f4i2 = zRe[in10];
+ f4i3 = zRe[in8];
+ f3i2 = f4i2 + f4i3;
+ f3i3 = fnms(0.5f, f3i2, f3i1);
+ f3i4 = FFT_15PONIT_WNK4 * (f4i3 - f4i2);
+
+ f3i5 = zIm[in9];
+ f4i4 = zIm[in10];
+ f4i5 = zIm[in8];
+ f3i6 = f4i4 + f4i5;
+ f3i7 = FFT_15PONIT_WNK4 * (f4i4 - f4i5);
+ f3i8 = fnms(0.5f, f3i6, f3i5);
+
+ f3i9 = zRe[in33];
+ f4i6 = zRe[in34];
+ f4i7 = zRe[in32];
+ f3i10 = f4i6 + f4i7;
+ f3i11 = fnms(0.5f, f3i10, f3i9);
+ f3i12 = FFT_15PONIT_WNK4 * (f4i7 - f4i6);
+
+ f3i13 = zIm[in33];
+ f4i8 = zIm[in34];
+ f4i9 = zIm[in32];
+ f3i14 = f4i8 + f4i9;
+ f3i15 = FFT_15PONIT_WNK4 * (f4i8 - f4i9);
+ f4i1 = fnms(0.5f, f3i14, f3i13);
+
+ fi7 = f3i1 + f3i2;
+ fi8 = f3i9 + f3i10;
+ fi9 = fi7 + fi8;
+ fi10 = f3i3 - f3i7;
+ fi11 = f3i11 - f3i15;
+ fi12 = fi10 + fi11;
+ fi13 = f3i5 + f3i6;
+ fi14 = f3i13 + f3i14;
+ fi15 = fi13 + fi14;
+ fi16 = f3i8 - f3i4;
+ fi17 = f4i1 - f3i12;
+ fi18 = fi16 + fi17;
+ fi19 = f3i4 + f3i8;
+ fi20 = f3i12 + f4i1;
+ fi21 = fi19 + fi20;
+ fi22 = f3i3 + f3i7;
+ fi23 = f3i11 + f3i15;
+ fi24 = fi22 + fi23;
+
+ f4i10 = zRe[in24];
+ fo6 = zRe[in25];
+ fo7 = zRe[in26];
+ f4i11 = fo6 + fo7;
+ f4i12 = fnms(0.5f, f4i11, f4i10);
+ f4i13 = FFT_15PONIT_WNK4 * (fo7 - fo6);
+
+ f4i14 = zIm[in24];
+ fo8 = zIm[in25];
+ fo9 = zIm[in26];
+ f4i15 = fo8 + fo9;
+ f4i16 = FFT_15PONIT_WNK4 * (fo8 - fo9);
+ f4i17 = fnms(0.5f, f4i15, f4i14);
+
+ f4i18 = zRe[in18];
+ f2o10 = zRe[in16];
+ f2o11 = zRe[in17];
+ f4i19 = f2o10 + f2o11;
+ f4i20 = fnms(0.5f, f4i19, f4i18);
+ fo1 = FFT_15PONIT_WNK4 * (f2o11 - f2o10);
+
+ fo2 = zIm[in18];
+ f2o12 = zIm[in16];
+ f2o13 = zIm[in17];
+ fo3 = f2o12 + f2o13;
+ fo4 = FFT_15PONIT_WNK4 * (f2o12 - f2o13);
+ fo5 = fnms(0.5f, fo3, fo2);
+
+ fi25 = f4i10 + f4i11;
+ fi26 = f4i18 + f4i19;
+ fi27 = fi25 + fi26;
+ fi28 = f4i12 - f4i16;
+ fi29 = f4i20 - fo4;
+ fi30 = fi28 + fi29;
+ f2i1 = f4i14 + f4i15;
+ f2i2 = fo2 + fo3;
+ f2i3 = f2i1 + f2i2;
+ f2i4 = f4i17 - f4i13;
+ f2i5 = fo5 - fo1;
+ f2i6 = f2i4 + f2i5;
+ f2i7 = f4i13 + f4i17;
+ f2i8 = fo1 + fo5;
+ f2i9 = f2i7 + f2i8;
+ f2i10 = f4i12 + f4i16;
+ f2i11 = f4i20 + fo4;
+ f2i12 = f2i10 + f2i11;
+
+ fo10 = FFT_15PONIT_WNK1 * (fi27 - fi9);
+ fo11 = fi27 + fi9;
+ fo12 = fnms(FFT_15PONIT_WNK5, fo11, fi1);
+ fo15 = fi13 - fi14;
+ fo16 = f2i1 - f2i2;
+ fo13 = fnms(FFT_15PONIT_WNK3, fo16, FFT_15PONIT_WNK2 * fo15);
+ fo14 = fmac(FFT_15PONIT_WNK2, fo16, FFT_15PONIT_WNK3 * fo15);
+
+ zRe[in0] = fi1 + fo11;
+ fo17 = fo10 + fo12;
+ zRe[in18] = fo17 - fo14;
+ zRe[in24] = fo17 + fo14;
+ fo18 = fo12 - fo10;
+ zRe[in9] = fo18 - fo13;
+ zRe[in33] = fo18 + fo13;
+
+ f2o1 = FFT_15PONIT_WNK1 * (f2i3 - fi15);
+ f2o2 = f2i3 + fi15;
+ f2o3 = fnms(FFT_15PONIT_WNK5, f2o2, fi2);
+ f2o6 = fi7 - fi8;
+ f2o7 = fi25 - fi26;
+ f2o4 = fnms(FFT_15PONIT_WNK3, f2o7, FFT_15PONIT_WNK2 * f2o6);
+ f2o5 = fmac(FFT_15PONIT_WNK2, f2o7, FFT_15PONIT_WNK3 * f2o6);
+ zIm[in0] = fi2 + f2o2;
+ f2o8 = f2o1 + f2o3;
+ zIm[in24] = f2o8 - f2o5;
+ zIm[in18] = f2o5 + f2o8;
+ f2o9 = f2o3 - f2o1;
+ zIm[in33] = f2o9 - f2o4;
+ zIm[in9] = f2o4 + f2o9;
+
+ f2o14 = FFT_15PONIT_WNK1 * (fi30 - fi12);
+ f2o15 = fi30 + fi12;
+ f3o1 = fnms(FFT_15PONIT_WNK5, f2o15, fi3);
+ f3o4 = fi16 - fi17;
+ f3o5 = f2i4 - f2i5;
+ f3o2 = fnms(FFT_15PONIT_WNK3, f3o5, FFT_15PONIT_WNK2 * f3o4);
+ f3o3 = fmac(FFT_15PONIT_WNK2, f3o5, FFT_15PONIT_WNK3 * f3o4);
+ zRe[in2] = fi3 + f2o15;
+ f3o6 = f2o14 + f3o1;
+ zRe[in17] = f3o6 - f3o3;
+ zRe[in26] = f3o6 + f3o3;
+ f3o7 = f3o1 - f2o14;
+ zRe[in8] = f3o7 - f3o2;
+ zRe[in32] = f3o7 + f3o2;
+
+ f3o8 = FFT_15PONIT_WNK1 * (f2i6 - fi18);
+ f3o9 = f2i6 + fi18;
+ f3o10 = fnms(FFT_15PONIT_WNK5, f3o9, fi6);
+ f3o13 = fi10 - fi11;
+ f3o14 = fi28 - fi29;
+ f3o11 = fnms(FFT_15PONIT_WNK3, f3o14, FFT_15PONIT_WNK2 * f3o13);
+ f3o12 = fmac(FFT_15PONIT_WNK2, f3o14, FFT_15PONIT_WNK3 * f3o13);
+ zIm[in2] = fi6 + f3o9;
+ f3o15 = f3o8 + f3o10;
+ zIm[in26] = f3o15 - f3o12;
+ zIm[in17] = f3o12 + f3o15;
+ f4o1 = f3o10 - f3o8;
+ zIm[in8] = f3o11 + f4o1;
+ zIm[in32] = f4o1 - f3o11;
+
+ f4o2 = FFT_15PONIT_WNK1 * (f2i9 - fi21);
+ f4o3 = f2i9 + fi21;
+ f4o4 = fnms(FFT_15PONIT_WNK5, f4o3, fi5);
+ f4o7 = f2i10 - f2i11;
+ f4o8 = fi22 - fi23;
+ f4o5 = fmac(FFT_15PONIT_WNK2, f4o7, FFT_15PONIT_WNK3 * f4o8);
+ f4o6 = fnms(FFT_15PONIT_WNK3, f4o7, FFT_15PONIT_WNK2 * f4o8);
+ zIm[in1] = fi5 + f4o3;
+ f4o9 = f4o4 - f4o2;
+ f4o10 = f4o2 + f4o4;
+
+ zIm[in10] = f4o6 + f4o9;
+ zIm[in34] = f4o9 - f4o6;
+ zIm[in25] = f4o10 - f4o5;
+ zIm[in16] = f4o5 + f4o10;
+
+ f4o11 = FFT_15PONIT_WNK1 * (f2i12 - fi24);
+ f4o12 = f2i12 + fi24;
+ f4o13 = fnms(FFT_15PONIT_WNK5, f4o12, fi4);
+ f4o16 = f2i7 - f2i8;
+ f4o17 = fi19 - fi20;
+ f4o14 = fmac(FFT_15PONIT_WNK2, f4o16, FFT_15PONIT_WNK3 * f4o17);
+ f4o15 = fnms(FFT_15PONIT_WNK3, f4o16, FFT_15PONIT_WNK2 * f4o17);
+ zRe[in1] = fi4 + f4o12;
+ f4o18 = f4o13 - f4o11;
+ f4o19 = f4o11 + f4o13;
+
+ zRe[in10] = f4o18 - f4o15;
+ zRe[in34] = f4o18 + f4o15;
+ zRe[in16] = f4o19 - f4o14;
+ zRe[in25] = f4o19 + f4o14;
+
+ return;
+ }
+
+ /*-----------------------------------------------------------------*
+ * fft15_shift8()
+ * 15-point FFT with 8-point circular shift
+ *-----------------------------------------------------------------*/
+
+ static void fft15_shift8(
+ int n1, /* i : length of data */
+ float *zRe, /* i/o : real part of input and output data */
+ float *zIm, /* i/o : imaginary part of input and output data */
+ const short *Idx /* i : pointer of the address table */
+ )
+ {
+ short in0, in8, in16, in24, in32, in1, in9, in17, in25, in33, in2, in10, in18, in26, in34;
+ float fi1, fi2, fi3, fi4, fi5, fi6, fi7, fi8, fi9, fi10, fi11, fi12, fi13, fi14, fi15;
+ float fi16, fi17, fi18, fi19, fi20, fi21, fi22, fi23, fi24, fi25, fi26, fi27, fi28, fi29, fi30;
+ float f2i1, f2i2, f2i3, f2i4, f2i5, f2i6, f2i7, f2i8, f2i9, f2i10, f2i11, f2i12;
+ float f2i13, f2i14, f2i15, f3i1, f3i2, f3i3, f3i4, f3i5, f3i6, f3i7, f3i8, f3i9;
+ float f3i10, f3i11, f3i12, f3i13, f3i14, f3i15, f4i1, f4i2, f4i3, f4i4, f4i5, f4i6, f4i7, f4i8, f4i9;
+ float f4i10, f4i11, f4i12, f4i13, f4i14, f4i15, fo1, fo2, fo3, fo4, fo5, fo6;
+ float fo7, fo8, fo9, fo10, fo11, fo12, fo13, fo14, fo15, f2o1, f2o2, f2o3, f2o4;
+ float f2o5, f2o6, f2o7, f2o8, f2o9, f2o10, f2o11, f2o12, f2o13, f2o14, f2o15;
+ float f3o1, f3o2, f3o3, f3o4, f3o5, f3o6, f3o7, f3o8, f3o9, f3o10, f3o11, f3o12;
+ float f3o13, f3o14, f3o15, f4o1, f4o2, f4o3, f4o4, f4o5, f4o6, f4o7, f4o8, f4o9;
+ float f4o10, f4o11, f4o12, f4o13, f4o14, f4o15, f5o1, f5o2, f5o3, f5o4, f5o5, f5o6, f5o7;
+ float f5o8, f5o9, f5o10, f5o11, f5o12, f5o13, f5o14, f5o15, f5o16, f5o17, f5o18, f5o19, f5o21, f5o22;
+
+ in0 = Idx[0] ;
+ in8 = Idx[n1];
+ in16 = Idx[n1*2];
+ in24 = Idx[n1*3];
+ in32 = Idx[n1*4];
+ in1 = Idx[n1*5];
+ in9 = Idx[n1*6];
+ in17 = Idx[n1*7];
+ in25 = Idx[n1*8];
+ in33 = Idx[n1*9];
+ in2 = Idx[n1*10];
+ in10 = Idx[n1*11];
+ in18 = Idx[n1*12];
+ in26 = Idx[n1*13];
+ in34 = Idx[n1*14];
+
+ f2i13 = zRe[in0];
+ f2i14 = zIm[in0];
+ f3i6 = zRe[in1];
+ f3i7 = zRe[in2];
+ f3i8 = zIm[in1];
+ f3i9 = zIm[in2];
+
+ f2i15 = f3i6 + f3i7;
+ f3i1 = FFT_15PONIT_WNK4 * (f3i7 - f3i6);
+ f3i2 = FFT_15PONIT_WNK4 * (f3i8 - f3i9);
+ f3i3 = f3i8 + f3i9;
+
+ fi1 = f2i13 + f2i15;
+ fi2 = f2i14 + f3i3;
+ f3i4 = fnms(0.5f, f2i15, f2i13);
+ fi3 = f3i4 - f3i2;
+ fi4 = f3i4 + f3i2;
+ f3i5 = fnms(0.5f, f3i3, f2i14);
+ fi5 = f3i1 + f3i5;
+ fi6 = f3i5 - f3i1;
+
+ f3i10 = zRe[in9];
+ f4i11 = zRe[in10];
+ f4i12 = zRe[in8];
+ f3i14 = zIm[in9];
+ f4i13 = zIm[in10];
+ f4i14 = zIm[in8];
+ f4i3 = zRe[in33];
+ f4i15 = zRe[in34];
+ fo1 = zRe[in32];
+ f4i7 = zIm[in33];
+ fo2 = zIm[in34];
+ fo3 = zIm[in32];
+
+
+ f3i11 = f4i11 + f4i12;
+ f3i12 = fnms(0.5f, f3i11, f3i10);
+ f3i13 = FFT_15PONIT_WNK4 * (f4i12 - f4i11);
+ f3i15 = f4i13 + f4i14;
+ f4i1 = FFT_15PONIT_WNK4 * (f4i13 - f4i14);
+ f4i2 = fnms(0.5f, f3i15, f3i14);
+ f4i4 = f4i15 + fo1;
+ f4i5 = fnms(0.5f, f4i4, f4i3);
+ f4i6 = FFT_15PONIT_WNK4 * (fo1 - f4i15);
+ f4i8 = fo2 + fo3;
+ f4i9 = FFT_15PONIT_WNK4 * (fo2 - fo3);
+ f4i10 = fnms(0.5f, f4i8, f4i7);
+
+ fi7 = f3i10 + f3i11;
+ fi8 = f4i3 + f4i4;
+ fi9 = fi7 + fi8;
+ fi10 = f3i12 - f4i1;
+ fi11 = f4i5 - f4i9;
+ fi12 = fi10 + fi11;
+ fi13 = f3i14 + f3i15;
+ fi14 = f4i7 + f4i8;
+ fi15 = fi13 + fi14;
+ fi16 = f4i2 - f3i13;
+ fi17 = f4i10 - f4i6;
+ fi18 = fi16 + fi17;
+ fi19 = f3i13 + f4i2;
+ fi20 = f4i6 + f4i10;
+ fi21 = fi19 + fi20;
+ fi22 = f3i12 + f4i1;
+ fi23 = f4i5 + f4i9;
+ fi24 = fi22 + fi23;
+
+ fo4 = zRe[in24];
+ f2o5 = zRe[in25];
+ f2o6 = zRe[in26];
+ fo8 = zIm[in24];
+ f2o7 = zIm[in25];
+ f2o8 = zIm[in26];
+ fo12 = zRe[in18];
+ f2o9 = zRe[in16];
+ f2o10 = zRe[in17];
+ f2o1 = zIm[in18];
+ f2o11 = zIm[in16];
+ f2o12 = zIm[in17];
+
+
+ fo5 = f2o5 + f2o6;
+ fo6 = fnms(0.5f, fo5, fo4);
+ fo7 = FFT_15PONIT_WNK4 * (f2o6 - f2o5);
+ fo9 = f2o7 + f2o8;
+ fo10 = FFT_15PONIT_WNK4 * (f2o7 - f2o8);
+ fo11 = fnms(0.5f, fo9, fo8);
+ fo13 = f2o9 + f2o10;
+ fo14 = fnms(0.5f, fo13, fo12);
+ fo15 = FFT_15PONIT_WNK4 * (f2o10 - f2o9);
+ f2o2 = f2o11 + f2o12;
+ f2o3 = FFT_15PONIT_WNK4 * (f2o11 - f2o12);
+ f2o4 = fnms(0.5f, f2o2, f2o1);
+
+ fi25 = fo4 + fo5;
+ fi26 = fo12 + fo13;
+ fi27 = fi25 + fi26;
+ fi28 = fo6 - fo10;
+ fi29 = fo14 - f2o3;
+ fi30 = fi28 + fi29;
+ f2i1 = fo8 + fo9;
+ f2i2 = f2o1 + f2o2;
+ f2i3 = f2i1 + f2i2;
+ f2i4 = fo11 - fo7;
+ f2i5 = f2o4 - fo15;
+ f2i6 = f2i4 + f2i5;
+ f2i7 = fo7 + fo11;
+ f2i8 = fo15 + f2o4;
+ f2i9 = f2i7 + f2i8;
+ f2i10 = fo6 + fo10;
+ f2i11 = fo14 + f2o3;
+ f2i12 = f2i10 + f2i11;
+
+ f2o13 = FFT_15PONIT_WNK1 * (fi27 - fi9);
+ f2o14 = fi27 + fi9;
+ f2o15 = fnms(FFT_15PONIT_WNK5, f2o14, fi1);
+ f3o3 = fi13 - fi14;
+ f3o4 = f2i1 - f2i2;
+ f3o1 = fnms(FFT_15PONIT_WNK3, f3o4, FFT_15PONIT_WNK2 * f3o3);
+ f3o2 = fmac(FFT_15PONIT_WNK2, f3o4, FFT_15PONIT_WNK3 * f3o3);
+ zRe[in0] = fi1 + f2o14;
+ f3o5 = f2o13 + f2o15;
+ zRe[in24] = f3o5 - f3o2;
+ zRe[in18] = f3o5 + f3o2;
+ f3o6 = f2o15 - f2o13;
+ zRe[in33] = f3o6 - f3o1;
+ zRe[in9] = f3o6 + f3o1;
+
+ f3o7 = FFT_15PONIT_WNK1 * (f2i3 - fi15);
+ f3o8 = f2i3 + fi15;
+ f3o9 = fnms(FFT_15PONIT_WNK5, f3o8, fi2);
+ f3o12 = fi7 - fi8;
+ f3o13 = fi25 - fi26;
+ f3o10 = fnms(FFT_15PONIT_WNK3, f3o13, FFT_15PONIT_WNK2 * f3o12);
+ f3o11 = fmac(FFT_15PONIT_WNK2, f3o13, FFT_15PONIT_WNK3 * f3o12);
+ zIm[in0] = fi2 + f3o8;
+ f3o14 = f3o7 + f3o9;
+ zIm[in18] = f3o14 - f3o11;
+ zIm[in24] = f3o11 + f3o14;
+ f3o15 = f3o9 - f3o7;
+ zIm[in9] = f3o15 - f3o10;
+ zIm[in33] = f3o10 + f3o15;
+
+ f4o1 = FFT_15PONIT_WNK1 * (fi30 - fi12);
+ f4o2 = fi30 + fi12;
+ f4o3 = fnms(FFT_15PONIT_WNK5, f4o2, fi3);
+ f4o6 = fi16 - fi17;
+ f4o7 = f2i4 - f2i5;
+ f4o4 = fnms(FFT_15PONIT_WNK3, f4o7, FFT_15PONIT_WNK2 * f4o6);
+ f4o5 = fmac(FFT_15PONIT_WNK2, f4o7, FFT_15PONIT_WNK3 * f4o6);
+ zRe[in2] = fi3 + f4o2;
+ f4o8 = f4o1 + f4o3;
+ zRe[in26] = f4o8 - f4o5;
+ zRe[in17] = f4o8 + f4o5;
+ f4o9 = f4o3 - f4o1;
+ zRe[in32] = f4o9 - f4o4;
+ zRe[in8] = f4o9 + f4o4;
+
+ f4o10 = FFT_15PONIT_WNK1 * (f2i6 - fi18);
+ f4o11 = f2i6 + fi18;
+ f4o12 = fnms(FFT_15PONIT_WNK5, f4o11, fi6);
+ f4o15 = fi10 - fi11;
+ f5o1 = fi28 - fi29;
+ f4o13 = fnms(FFT_15PONIT_WNK3, f5o1, FFT_15PONIT_WNK2 * f4o15);
+ f4o14 = fmac(FFT_15PONIT_WNK2, f5o1, FFT_15PONIT_WNK3 * f4o15);
+ zIm[in2] = fi6 + f4o11;
+ f5o2 = f4o10 + f4o12;
+ zIm[in17] = f5o2 - f4o14;
+ zIm[in26] = f4o14 + f5o2;
+ f5o3 = f4o12 - f4o10;
+ zIm[in32] = f4o13 + f5o3;
+ zIm[in8] = f5o3 - f4o13;
+
+ f5o4 = FFT_15PONIT_WNK1 * (f2i9 - fi21);
+ f5o5 = f2i9 + fi21;
+ f5o6 = fnms(FFT_15PONIT_WNK5, f5o5, fi5);
+ f5o9 = f2i10 - f2i11;
+ f5o10 = fi22 - fi23;
+ f5o7 = fmac(FFT_15PONIT_WNK2, f5o9, FFT_15PONIT_WNK3 * f5o10);
+ f5o8 = fnms(FFT_15PONIT_WNK3, f5o9, FFT_15PONIT_WNK2 * f5o10);
+ zIm[in1] = fi5 + f5o5;
+ f5o11 = f5o6 - f5o4;
+ f5o12 = f5o4 + f5o6;
+ zIm[in34] = f5o8 + f5o11;
+ zIm[in10] = f5o11 - f5o8;
+
+ zIm[in16] = f5o12 - f5o7;
+ zIm[in25] = f5o7 + f5o12;
+
+ f5o13 = FFT_15PONIT_WNK1 * (f2i12 - fi24);
+ f5o14 = f2i12 + fi24;
+ f5o15 = fnms(FFT_15PONIT_WNK5, f5o14, fi4);
+ f5o18 = f2i7 - f2i8;
+ f5o19 = fi19 - fi20;
+ f5o16 = fmac(FFT_15PONIT_WNK2, f5o18, FFT_15PONIT_WNK3 * f5o19);
+ f5o17 = fnms(FFT_15PONIT_WNK3, f5o18, FFT_15PONIT_WNK2 * f5o19);
+ zRe[in1] = fi4 + f5o14;
+ f5o21 = f5o15 - f5o13;
+ f5o22 = f5o13 + f5o15;
+
+ zRe[in34] = f5o21 - f5o17;
+ zRe[in10] = f5o21 + f5o17;
+ zRe[in25] = f5o22 - f5o16;
+ zRe[in16] = f5o22 + f5o16;
+
+ return;
+ }
+
+ /*-----------------------------------------------------------------*
+ * fft5_shift1()
+ * 5-point FFT with 1-point circular shift
+ *-----------------------------------------------------------------*/
+
+ static void fft5_shift1(
+ int n1, /* i : length of data */
+ float *zRe, /* i/o : real part of input and output data */
+ float *zIm, /* i/o : imaginary part of input and output data */
+ const short *Idx /* i : pointer of the address table */
+ )
+ {
+ float fi1, fi2, fi3, fi4, fi5, fi6, fi7, fi8;
+ float fo1, fo2, fo3, fo4, fo5, fo6, fo7, fo8;
+ short in1,in2,in3,in4,in5;
+
+ in1 = Idx[0];
+ in2 = Idx[n1];
+ in3 = Idx[n1*2];
+ in4 = Idx[n1*3];
+ in5 = Idx[n1*4];
+
+ fi1 = zRe[in1];
+ fi2 = zIm[in1];
+ fo3 = zRe[in2];
+ fo4 = zRe[in5];
+ fo6 = zRe[in3];
+ fo7 = zRe[in4];
+
+ fo5 = fo3 + fo4;
+ fo8 = fo6 + fo7;
+ fi3 = fo5 + fo8;
+ fi4 = fo6 - fo7;
+ fi5 = FFT_15PONIT_WNK1 * (fo5 - fo8);
+ fi6 = fo3 - fo4;
+
+ fo3 = zIm[in2];
+ fo4 = zIm[in5];
+ fo6 = zIm[in3];
+ fo7 = zIm[in4];
+
+ fo5 = fo3 + fo4;
+ fo8 = fo6 + fo7;
+ fi7 = fo3 - fo4;
+ fi8 = fo5 + fo8;
+ fo1 = fo6 - fo7;
+ fo2 = FFT_15PONIT_WNK1 * (fo5 - fo8);
+
+ zRe[in1] = fi1 + fi3;
+ zIm[in1] = fi2 + fi8;
+
+ fo3 = FFT_15PONIT_WNK2*fi7 + FFT_15PONIT_WNK3*fo1;
+ fo4 = FFT_15PONIT_WNK2*fo1 - FFT_15PONIT_WNK3*fi7;
+ fo7 = fi1-fi3/4;
+ fo5 = fi5 + fo7;
+ fo6 = fo7 - fi5;
+
+ zRe[in2] = fo5 + fo3;
+ zRe[in3] = fo6 - fo4;
+ zRe[in4] = fo6 + fo4;
+ zRe[in5] = fo5 - fo3;
+
+ fo3 = FFT_15PONIT_WNK2 * fi6 + FFT_15PONIT_WNK3 * fi4;
+ fo4 = FFT_15PONIT_WNK2 * fi4 - FFT_15PONIT_WNK3 * fi6;
+ fo7 = fi2-fi8/4;
+ fo5 = fo2 + fo7;
+ fo6 = fo7 - fo2;
+
+ zIm[in2] = fo5 - fo3;
+ zIm[in3] = fo4 + fo6;
+ zIm[in4] = fo6 - fo4;
+ zIm[in5] = fo3 + fo5;
+
+ return;
+ }
+
+ /*-----------------------------------------------------------------*
+ * fft5_shift4()
+ * 5-point FFT with 4-point circular shift
+ *-----------------------------------------------------------------*/
+
+ static void fft5_shift4(
+ int n1, /* i : length of data */
+ float *zRe, /* i/o : real part of input and output data */
+ float *zIm, /* i/o : imaginary part of input and output data */
+ const short *Idx /* i : pointer of the address table */
+ )
+ {
+ float fi1, fi2, fi3, fi4, fi5, fi6, fi7, fi8;
+ float fo1, fo2, fo3, fo4, fo5, fo6, fo7, fo8;
+ short in1,in2,in3,in4,in5;
+
+ in1 = Idx[0];
+ in2 = Idx[n1];
+ in3 = Idx[n1*2];
+ in4 = Idx[n1*3];
+ in5 = Idx[n1*4];
+
+ fi1 = zRe[in1];
+ fi2 = zIm[in1];
+ fo3 = zRe[in2];
+ fo4 = zRe[in5];
+ fo6 = zRe[in3];
+ fo7 = zRe[in4];
+
+ fo5 = fo3 + fo4;
+ fo8 = fo6 + fo7;
+ fi3 = fo5 + fo8;
+ fi4 = fo6 - fo7;
+ fi5 = FFT_15PONIT_WNK1 * (fo5 - fo8);
+ fi6 = fo3 - fo4;
+
+ fo3 = zIm[in2];
+ fo4 = zIm[in5];
+ fo6 = zIm[in3];
+ fo7 = zIm[in4];
+
+ fo5 = fo3 + fo4;
+ fo8 = fo6 + fo7;
+ fi7 = fo3 - fo4;
+ fi8 = fo5 + fo8;
+ fo1 = fo6 - fo7;
+ fo2 = FFT_15PONIT_WNK1 * (fo5 - fo8);
+
+ zRe[in1] = fi1 + fi3;
+ zIm[in1] = fi2 + fi8;
+
+ fo3 = FFT_15PONIT_WNK2*fi7 + FFT_15PONIT_WNK3*fo1;
+ fo4 = FFT_15PONIT_WNK2*fo1 - FFT_15PONIT_WNK3*fi7;
+ fo7 = fi1-fi3/4;
+ fo5 = fi5 + fo7;
+ fo6 = fo7 - fi5;
+ zRe[in2] = fo5 - fo3;
+ zRe[in4] = fo6 - fo4;
+ zRe[in3] = fo6 + fo4;
+ zRe[in5] = fo5 + fo3;
+
+ fo3 = FFT_15PONIT_WNK2 * fi6 + FFT_15PONIT_WNK3 * fi4;
+ fo4 = FFT_15PONIT_WNK2 * fi4 - FFT_15PONIT_WNK3 * fi6;
+ fo7 = fi2-fi8/4;
+ fo5 = fo2 + fo7;
+ fo6 = fo7 - fo2;
+
+ zIm[in3] = fo6 - fo4;
+ zIm[in2] = fo3 + fo5;
+ zIm[in4] = fo4 + fo6;
+ zIm[in5] = fo5 - fo3;
+
+ return;
+ }
+
+ /*-----------------------------------------------------------------*
+ * fft5_32()
+ * 5-point FFT called for 32 times
+ *-----------------------------------------------------------------*/
+
+ static void fft5_32(
+ float *zRe, /* i/o : real part of input and output data */
+ float *zIm, /* i/o : imaginary part of input and output data */
+ const short *Idx /* i : pointer of the address table */
+ )
+ {
+ float fi1, fi2, fi3, fi4, fi5, fi6, fi7, fi8;
+ float fo1, fo2, fo3, fo4, fo5, fo6, fo7, fo8;
+ short in1,in2,in3,in4,in5;
+
+ in1 = Idx[0];
+ in2 = Idx[32];
+ in3 = Idx[64];
+ in4 = Idx[96];
+ in5 = Idx[128];
+
+ fi1 = zRe[in1];
+ fi2 = zIm[in1];
+ fo3 = zRe[in2];
+ fo4 = zRe[in5];
+ fo6 = zRe[in3];
+ fo7 = zRe[in4];
+
+ fo5 = fo3 + fo4;
+ fo8 = fo6 + fo7;
+ fi3 = fo5 + fo8;
+ fi4 = fo6 - fo7;
+ fi5 = FFT_15PONIT_WNK1 * (fo5 - fo8);
+ fi6 = fo3 - fo4;
+
+ fo3 = zIm[in2];
+ fo4 = zIm[in5];
+ fo6 = zIm[in3];
+ fo7 = zIm[in4];
+
+ fo5 = fo3 + fo4;
+ fo8 = fo6 + fo7;
+ fi7 = fo3 - fo4;
+ fi8 = fo5 + fo8;
+ fo1 = fo6 - fo7;
+ fo2 = FFT_15PONIT_WNK1 * (fo5 - fo8);
+
+ zRe[in1] = fi1 + fi3;
+ zIm[in1] = fi2 + fi8;
+
+ fo3 = FFT_15PONIT_WNK2*fi7 + FFT_15PONIT_WNK3*fo1;
+ fo4 = FFT_15PONIT_WNK2*fo1 - FFT_15PONIT_WNK3*fi7;
+ fo7 = fi1-fi3/4;
+ fo5 = fi5 + fo7;
+ fo6 = fo7 - fi5;
+
+ zRe[in2] = fo6 + fo4;
+ zRe[in3] = fo5 + fo3;
+ zRe[in4] = fo5 - fo3;
+ zRe[in5] = fo6 - fo4;
+
+ fo3 = FFT_15PONIT_WNK2 * fi6 + FFT_15PONIT_WNK3 * fi4;
+ fo4 = FFT_15PONIT_WNK2 * fi4 - FFT_15PONIT_WNK3 * fi6;
+ fo7 = fi2-fi8/4;
+ fo5 = fo2 + fo7;
+ fo6 = fo7 - fo2;
+
+ zIm[in2] = fo6 - fo4;
+ zIm[in3] = fo5 - fo3;
+ zIm[in4] = fo3 + fo5;
+ zIm[in5] = fo4 + fo6;
+
+ return;
+ }
+
+ /*-----------------------------------------------------------------*
+ * fft64()
+ * 64-point FFT
+ *-----------------------------------------------------------------*/
+
+ static void fft64(
+ float *x, /* i/o : real part of input and output data */
+ float *y, /* i/o : imaginary part of input and output data */
+ const short *Idx /* i : pointer of the address table */
+ )
+ {
+ short i,id,jd;
+ float z[128];
+ for ( i=0; i<64; i++ )
+ {
+ id = Idx[i];
+ z[2*i] = x[id];
+ z[2*i+1] = y[id];
+ }
+
+ cdftForw(128,z,Ip_fft64,w_fft64);
+
+ for( i=0; i<64 ; i++)
+ {
+ jd = Odx_fft64[i];
+ id = Idx[jd];
+ x[id]=z[2*i];
+ y[id]=z[2*i+1];
+ }
+
+ return;
+ }
+
+
+ /*-----------------------------------------------------------------*
+ * fft32_15()
+ * 32-point FFT called for 15 times
+ *-----------------------------------------------------------------*/
+
+ static void fft32_15(
+ float *x, /* i/o : real part of input and output data */
+ float *y, /* i/o : imaginary part of input and output data */
+ const short *Idx /* i : pointer of the address table */
+ )
+ {
+ short i,id,jd;
+ float z[64];
+
+ for( i=0; i<32; i++ )
+ {
+ id = Idx[i];
+ z[2*i] = x[id];
+ z[2*i+1] = y[id];
+ }
+
+ cdftForw(64,z,Ip_fft32,w_fft32);
+
+ for( i=0; i<32; i++ )
+ {
+ jd = Odx_fft32_15[i];
+ id = Idx[jd];
+ x[id]=z[2*i];
+ y[id]=z[2*i+1];
+ }
+
+ return;
+ }
+
+ /*-----------------------------------------------------------------*
+ * fft32_5()
+ * 32-point FFT called for 5 times
+ *-----------------------------------------------------------------*/
+
+ static void fft32_5(
+ float *x, /* i/o : real part of input and output data */
+ float *y, /* i/o : imaginary part of input and output data */
+ const short *Idx /* i : pointer of the address table */
+ )
+ {
+ short i,id,jd;
+ float z[64];
+
+ for( i=0; i<32; i++ )
+ {
+ id = Idx[i];
+ z[2*i] = x[id];
+ z[2*i+1] = y[id];
+ }
+
+ cdftForw(64,z,Ip_fft32,w_fft32);
+
+ for( i=0; i<32; i++ )
+ {
+ jd = Odx_fft32_5[i];
+ id = Idx[jd];
+ x[id]=z[2*i];
+ y[id]=z[2*i+1];
+ }
+
+ return;
+ }
+
+ /*-----------------------------------------------------------------*
+ * fft16()
+ * 16-point FFT
+ *-----------------------------------------------------------------*/
+
+ static void fft16(
+ float *x, /* i/o : real part of input and output data */
+ float *y, /* i/o : imaginary part of input and output data */
+ const short *Idx /* i : pointer of the address table */
+ )
+ {
+ short i,id,jd;
+ float z[32];
+
+ for(i=0; i<16 ; i++)
+ {
+ id = Idx[i];
+ z[2*i] = x[id];
+ z[2*i+1] = y[id];
+ }
+
+ cdftForw(32,z,Ip_fft16,w_fft16);
+
+ for(i=0; i<16; i++)
+ {
+ jd = Odx_fft16[i];
+ id = Idx[jd];
+ x[id]=z[2*i];
+ y[id]=z[2*i+1];
+ }
+
+ return;
+ }
+
+ /*-----------------------------------------------------------------*
+ * fft8()
+ * 8-point FFT
+ *-----------------------------------------------------------------*/
+
+ static void fft8(
+ float *x, /* i/o : real part of input and output data */
+ float *y, /* i/o : imaginary part of input and output data */
+ const short *Idx /* i : pointer of the address table */
+ )
+ {
+ short i,id;
+ float z[16];
+
+ for(i=0; i<8; i++)
+ {
+ id = Idx[i];
+ z[2*i] = x[id];
+ z[2*i+1] = y[id];
+ }
+
+ cdftForw(16,z,Ip_fft8,w_fft8);
+
+ for(i=0; i<8; i++)
+ {
+ id = Idx[i];
+ x[id]=z[2*i];
+ y[id]=z[2*i+1];
+ }
+
+ return;
+ }
+
+ /*-----------------------------------------------------------------*
+ * fft8_5()
+ * 8-point FFT with shift 5
+ *-----------------------------------------------------------------*/
+
+ static void fft8_5(
+ float *x, /* i/o : real part of input and output data */
+ float *y, /* i/o : imaginary part of input and output data */
+ const short *Idx /* i : pointer of the address table */
+ )
+ {
+ short i,id,jd;
+ float z[16];
+
+ for(i=0; i<8; i++)
+ {
+ id = Idx[i];
+ z[2*i] = x[id];
+ z[2*i+1] = y[id];
+ }
+
+ cdftForw(16,z,Ip_fft8,w_fft8);
+
+ for(i=0; i<8; i++)
+ {
+ jd = Odx_fft8_5[i];
+ id = Idx[jd];
+ x[id]=z[2*i];
+ y[id]=z[2*i+1];
+ }
+ return;
+ }
+
+ /*-----------------------------------------------------------------*
+ * fft5_8()
+ * 5-point FFT with shift 2
+ *-----------------------------------------------------------------*/
+
+ static void fft5_8(
+ int n1, /* i : length of data */
+ float *zRe, /* i/o : real part of input and output data */
+ float *zIm, /* i/o : imaginary part of input and output data */
+ const short *Idx /* i : pointer of the address table */
+ )
+ {
+ float fi1, fi2, fi3, fi4, fi5, fi6, fi7, fi8;
+ float fo1, fo2, fo3, fo4, fo5, fo6, fo7, fo8;
+ short in1,in2,in3,in4,in5;
+
+ in1 = Idx[0];
+ in2 = Idx[n1];
+ in3 = Idx[n1*2];
+ in4 = Idx[n1*3];
+ in5 = Idx[n1*4];
+
+ fi1 = zRe[in1];
+ fi2 = zIm[in1];
+ fo3 = zRe[in2];
+ fo4 = zRe[in5];
+ fo6 = zRe[in3];
+ fo7 = zRe[in4];
+
+ fo5 = fo3 + fo4;
+ fo8 = fo6 + fo7;
+ fi3 = fo5 + fo8;
+ fi4 = fo6 - fo7;
+ fi5 = FFT_15PONIT_WNK1 * (fo5 - fo8);
+ fi6 = fo3 - fo4;
+
+ fo3 = zIm[in2];
+ fo4 = zIm[in5];
+ fo6 = zIm[in3];
+ fo7 = zIm[in4];
+
+ fo5 = fo3 + fo4;
+ fo8 = fo6 + fo7;
+ fi7 = fo3 - fo4;
+ fi8 = fo5 + fo8;
+ fo1 = fo6 - fo7;
+ fo2 = FFT_15PONIT_WNK1 * (fo5 - fo8);
+
+ zRe[in1] = fi1 + fi3;
+ zIm[in1] = fi2 + fi8;
+
+ fo3 = FFT_15PONIT_WNK2*fi7 + FFT_15PONIT_WNK3*fo1;
+ fo4 = FFT_15PONIT_WNK2*fo1 - FFT_15PONIT_WNK3*fi7;
+ fo7 = fi1-fi3/4;
+ fo5 = fi5 + fo7;
+ fo6 = fo7 - fi5;
+
+ zRe[in2] = fo6 - fo4;
+ zRe[in3] = fo5 - fo3;
+ zRe[in5] = fo6 + fo4;
+ zRe[in4] = fo5 + fo3;
+
+ fo3 = FFT_15PONIT_WNK2 * fi6 + FFT_15PONIT_WNK3 * fi4;
+ fo4 = FFT_15PONIT_WNK2 * fi4 - FFT_15PONIT_WNK3 * fi6;
+ fo7 = fi2-fi8/4;
+ fo5 = fo2 + fo7;
+ fo6 = fo7 - fo2;
+
+ zIm[in2] = fo4 + fo6;
+ zIm[in3] = fo3 + fo5;
+ zIm[in4] = fo5 - fo3;
+ zIm[in5] = fo6 - fo4;
+
+ return;
+ }
+
+ /*-----------------------------------------------------------------*
+ * fft4_5()
+ * 8-point FFT with shift 1
+ *-----------------------------------------------------------------*/
+
+ static void fft4_5(
+ float *x, /* i/o : real part of input and output data */
+ float *y, /* i/o : imaginary part of input and output data */
+ const short *Idx /* i : pointer of the address table */
+ )
+ {
+ short i,id,jd;
+ float z[8];
+
+ for(i=0; i<4; i++)
+ {
+ id = Idx[i];
+ z[2*i] = x[id];
+ z[2*i+1] = y[id];
+ }
+
+ cdftForw(8,z,Ip_fft4,w_fft4);
+
+ for(i=0; i<4; i++)
+ {
+ jd = Odx_fft4_5[i];
+ id = Idx[jd];
+ x[id]=z[2*i];
+ y[id]=z[2*i+1];
+ }
+ return;
+ }
+
+ /*-----------------------------------------------------------------*
+ * fft5_4()
+ * 5-point FFT with shift 4
+ *-----------------------------------------------------------------*/
+
+ static void fft5_4( int n1, float *zRe, float *zIm, const short *Idx )
+ {
+ float fi1, fi2, fi3, fi4, fi5, fi6, fi7, fi8;
+ float fo1, fo2, fo3, fo4, fo5, fo6, fo7, fo8;
+ short in1,in2,in3,in4,in5;
+
+ in1 = Idx[0];
+ in2 = Idx[n1];
+ in3 = Idx[n1*2];
+ in4 = Idx[n1*3];
+ in5 = Idx[n1*4];
+
+ fi1 = zRe[in1];
+ fi2 = zIm[in1];
+ fo3 = zRe[in2];
+ fo4 = zRe[in5];
+ fo6 = zRe[in3];
+ fo7 = zRe[in4];
+
+ fo5 = fo3 + fo4;
+ fo8 = fo6 + fo7;
+ fi3 = fo5 + fo8;
+ fi4 = fo6 - fo7;
+ fi5 = FFT_15PONIT_WNK1 * (fo5 - fo8);
+ fi6 = fo3 - fo4;
+
+ fo3 = zIm[in2];
+ fo4 = zIm[in5];
+ fo6 = zIm[in3];
+ fo7 = zIm[in4];
+
+ fo5 = fo3 + fo4;
+ fo8 = fo6 + fo7;
+ fi7 = fo3 - fo4;
+ fi8 = fo5 + fo8;
+ fo1 = fo6 - fo7;
+ fo2 = FFT_15PONIT_WNK1 * (fo5 - fo8);
+
+ zRe[in1] = fi1 + fi3;
+ zIm[in1] = fi2 + fi8;
+
+ fo3 = FFT_15PONIT_WNK2*fi7 + FFT_15PONIT_WNK3*fo1;
+ fo4 = FFT_15PONIT_WNK2*fo1 - FFT_15PONIT_WNK3*fi7;
+ fo7 = fi1-fi3/4;
+ fo5 = fi5 + fo7;
+ fo6 = fo7 - fi5;
+
+ zRe[in2] = fo5 - fo3;
+ zRe[in4] = fo6 - fo4;
+ zRe[in3] = fo6 + fo4;
+ zRe[in5] = fo5 + fo3;
+
+ fo3 = FFT_15PONIT_WNK2 * fi6 + FFT_15PONIT_WNK3 * fi4;
+ fo4 = FFT_15PONIT_WNK2 * fi4 - FFT_15PONIT_WNK3 * fi6;
+ fo7 = fi2-fi8/4;
+ fo5 = fo2 + fo7;
+ fo6 = fo7 - fo2;
+
+ zIm[in2] = fo3 + fo5;
+ zIm[in3] = fo6 - fo4;
+ zIm[in4] = fo4 + fo6;
+ zIm[in5] = fo5 - fo3;
+
+ return;
+ }
+
+
+ /*-----------------------------------------------------------------*
+ * DoRTFT80()
+ * a low complexity 2-dimensional DFT of 80 points
+ *-----------------------------------------------------------------*/
+
+ void DoRTFT80(
+ float *x, /* i/o : real part of input and output data */
+ float *y /* i/o : imaginary part of input and output data */
+ )
+ {
+ short j;
+
+ /* Applying 16-point FFT for 5 times based on the address table Idx_dortft80 */
+ for(j=0; j<5; j++)
+ {
+ fft16(x,y,Idx_dortft80+16*j);
+ }
+
+ /* Applying 5-point FFT for 16 times based on the address table Idx_dortft80 */
+ for(j=0; j<16; j++)
+ {
+ fft5_shift1(16,x,y,Idx_dortft80+j);
+ }
+
+ return;
+ }
+
+ /*-----------------------------------------------------------------*
+ * DoRTFT120()
+ * a low complexity 2-dimensional DFT of 120 points
+ *-----------------------------------------------------------------*/
+
+ void DoRTFT120(
+ float *x, /* i/o : real part of input and output data */
+ float *y /* i/o : imaginary part of input and output data */
+ )
+ {
+ short j;
+
+ /* Applying 8-point FFT for 15 times based on the address table Idx_dortft120 */
+ for(j=0; j<15; j++)
+ {
+ fft8(x,y,Idx_dortft120+8*j);
+ }
+
+ /* Applying 15-point FFT for 8 times based on the address table Idx_dortft120 */
+ for(j=0; j<8; j++)
+ {
+ fft15_shift2(8,x,y,Idx_dortft120+j);
+ }
+
+ return;
+ }
+
+ /*-----------------------------------------------------------------*
+ * DoRTFT160()
+ * a low complexity 2-dimensional DFT of 160 points
+ *-----------------------------------------------------------------*/
+
+ void DoRTFT160(
+ float x[], /* i/o : real part of input and output data */
+ float y[] /* i/o : imaginary part of input and output data */
+ )
+ {
+ short j;
+
+ /* Applying 32-point FFT for 5 times based on the address table Idx_dortft160 */
+ for(j=0; j<5; j++)
+ {
+ fft32_5(x,y,Idx_dortft160+32*j);
+ }
+
+ /* Applying 5-point FFT for 32 times based on the address table Idx_dortft160 */
+ for(j=0; j<32; j++)
+ {
+ fft5_32(x,y,Idx_dortft160+j);
+ }
+
+ return;
+ }
+
+ /*-----------------------------------------------------------------*
+ * DoRTFT320()
+ * a low complexity 2-dimensional DFT of 320 points
+ *-----------------------------------------------------------------*/
+
+ void DoRTFT320(
+ float *x, /* i/o : real part of input and output data */
+ float *y /* i/o : imaginary part of input and output data */
+ )
+ {
+ short j;
+
+ /* Applying 64-point FFT for 5 times based on the address table Idx_dortft160 */
+ for(j=0; j<5; j++)
+ {
+ fft64(x,y,Idx_dortft320+64*j);
+ }
+
+ /* Applying 5-point FFT for 64 times based on the address table Idx_dortft160 */
+ for(j=0; j<64; j++)
+ {
+ fft5_shift4(64,x,y,Idx_dortft320+j);
+ }
+
+ return;
+ }
+
+ /*-----------------------------------------------------------------*
+ * DoRTFT480()
+ * a low complexity 2-dimensional DFT of 480 points
+ *-----------------------------------------------------------------*/
+
+ void DoRTFT480(
+ float *x, /* i/o : real part of input and output data */
+ float *y /* i/o : imaginary part of input and output data */
+ )
+ {
+ short j;
+
+ /* Applying 32-point FFT for 15 times based on the address table Idx_dortft160 */
+ for(j=0; j<15; j++)
+ {
+ fft32_15(x,y,Idx_dortft480+32*j);
+ }
+
+ /* Applying 5-point FFT for 32 times based on the address table Idx_dortft160 */
+ for(j=0; j<32; j++)
+ {
+ fft15_shift8(32,x,y,Idx_dortft480+j);
+ }
+
+ return;
+ }
+
+ /*-----------------------------------------------------------------*
+ * DoRTFT40()
+ * a low complexity 2-dimensional DFT of 40 points
+ *-----------------------------------------------------------------*/
+
+ void DoRTFT40(
+ float *x, /* i/o : real part of input and output data */
+ float *y /* i/o : imaginary part of input and output data */
+ )
+ {
+ short j;
+ /* Applying 8-point FFT for 5 times based on the address table Idx_dortft40 */
+ for(j=0; j<5; j++)
+ {
+ fft8_5(x,y,Idx_dortft40+8*j);
+ }
+
+ /* Applying 5-point FFT for 8 times based on the address table Idx_dortft40 */
+ for(j=0; j<8; j++)
+ {
+ fft5_8(8,x,y,Idx_dortft40+j);
+ }
+
+ return;
+ }
+
+ /*-----------------------------------------------------------------*
+ * DoRTFT20()
+ * a low complexity 2-dimensional DFT of 20 points
+ *-----------------------------------------------------------------*/
+
+ void DoRTFT20(
+ float *x, /* i/o : real part of input and output data */
+ float *y /* i/o : imaginary part of input and output data */
+ )
+ {
+ short j;
+
+ /* Applying 4-point FFT for 5 times based on the address table Idx_dortft20 */
+ for(j=0; j<5; j++)
+ {
+ fft4_5(x,y,Idx_dortft20+4*j);
+ }
+
+ /* Applying 5-point FFT for 4 times based on the address table Idx_dortft20 */
+ for(j=0; j<4; j++)
+ {
+ fft5_4(4,x,y,Idx_dortft20+j);
+ }
+
+ return;
+ }
+
+ /*-----------------------------------------------------------------*
+ * DoRTFT128()
+ * FFT with 128 points
+ *-----------------------------------------------------------------*/
+
+ void DoRTFT128(
+ float *x, /* i/o : real part of input and output data */
+ float *y /* i/o : imaginary part of input and output data */
+ )
+ {
+
+ int i;
+ float z[256];
+
+ for ( i=0; i<128; i++ )
+ {
+ z[2*i] = x[i];
+ z[2*i+1] = y[i];
+ }
+
+ cdftForw(256,z,Ip_fft128,w_fft128);
+
+ x[0]=z[0];
+ y[0]=z[1];
+ for( i=1; i<128 ; i++)
+ {
+ x[128-i]=z[2*i];
+ y[128-i]=z[2*i+1];
+ }
+
+ return;
+ }
+
+ /*-----------------------------------------------------------------*
+ * cdftForw()
+ * Main fuction of Complex Discrete Fourier Transform
+ *-----------------------------------------------------------------*/
+
+ static void cdftForw(
+ short n, /* i : data length of real and imag */
+ float *a, /* i/o : input/output data */
+ const short *ip, /* i : work area for bit reversal */
+ const float *w /* i : cos/sin table */
+ )
+ {
+ /* bit reversal */
+ bitrv2_SR(n, ip + 2, a);
+
+ /* Do FFT */
+ cftfsub(n, a, w);
+ }
+
+ /*-----------------------------------------------------------------*
+ * bitrv2_SR()
+ * Bit reversal
+ *-----------------------------------------------------------------*/
+
+ static void bitrv2_SR(
+ short n, /* i : data length of real and imag */
+ const short *ip, /* i/o : work area for bit reversal */
+ float *a /* i/o : input/output data */
+ )
+ {
+ short j, j1, k, k1, m, m2;
+ short l;
+ float xr, xi, yr, yi;
+
+ if (n == 64)
+ {
+ m = 4;
+ l = -1;
+ }
+ else if (n == 256)
+ {
+ m = 8;
+ l = -1;
+ }
+ else if (n == 16)
+ {
+ m = 2;
+ l = -1;
+ }
+ else
+ {
+ l = n;
+ m = 1;
+
+ while ((m << 3) < l)
+ {
+ l >>= 1;
+ m <<= 1;
+ }
+ l -= m * 8;
+ }
+
+ m2 = 2 * m;
+
+ if (l == 0)
+ {
+ for (k = 0; k < m; k++)
+ {
+ for (j = 0; j < k; j++)
+ {
+ j1 = 2 * j + ip[k];
+ k1 = 2 * k + ip[j];
+ xr = a[j1];
+ xi = a[j1 + 1];
+ yr = a[k1];
+ yi = a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 += m2;
+ k1 += 2 * m2;
+ xr = a[j1];
+ xi = a[j1 + 1];
+ yr = a[k1];
+ yi = a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 += m2;
+ k1 -= m2;
+ xr = a[j1];
+ xi = a[j1 + 1];
+ yr = a[k1];
+ yi = a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 += m2;
+ k1 += 2 * m2;
+ xr = a[j1];
+ xi = a[j1 + 1];
+ yr = a[k1];
+ yi = a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ }
+
+ j1 = 2 * k + m2 + ip[k];
+ k1 = j1 + m2;
+ xr = a[j1];
+ xi = a[j1 + 1];
+ yr = a[k1];
+ yi = a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ }
+ }
+ else
+ {
+ for (k = 1; k < m; k++)
+ {
+ for (j = 0; j < k; j++)
+ {
+ j1 = 2 * j + ip[k];
+ k1 = 2 * k + ip[j];
+ xr = a[j1];
+ xi = a[j1 + 1];
+ yr = a[k1];
+ yi = a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 += m2;
+ k1 += m2;
+ xr = a[j1];
+ xi = a[j1 + 1];
+ yr = a[k1];
+ yi = a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ }
+ }
+ }
+
+ return;
+ }
+
+ /*-----------------------------------------------------------------*
+ * cftfsub()
+ * Complex Discrete Fourier Transform
+ *-----------------------------------------------------------------*/
+
+ static void cftfsub(
+ short n, /* i : data length of real and imag */
+ float *a, /* i/o : input/output data */
+ const float *w /* i : cos/sin table */
+ )
+ {
+ short j, j1, j2, j3, l;
+ float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
+
+ l = 2;
+ if (n > 8)
+ {
+ cft1st(n, a, w);
+
+ l = 8;
+ while ((l << 2) < n)
+ {
+ cftmdl(n, l, a, w);
+ l <<= 2;
+ }
+ }
+
+ if ((l << 2) == n)
+ {
+ for (j = 0; j < l; j += 2)
+ {
+ j1 = j + l;
+ j2 = j1 + l;
+ j3 = j2 + l;
+ x0r = a[j] + a[j1];
+ x0i = a[j + 1] + a[j1 + 1];
+ x1r = a[j] - a[j1];
+ x1i = a[j + 1] - a[j1 + 1];
+ x2r = a[j2] + a[j3];
+ x2i = a[j2 + 1] + a[j3 + 1];
+ x3r = a[j2] - a[j3];
+ x3i = a[j2 + 1] - a[j3 + 1];
+ a[j] = x0r + x2r;
+ a[j + 1] = x0i + x2i;
+ a[j2] = x0r - x2r;
+ a[j2 + 1] = x0i - x2i;
+ a[j1] = x1r - x3i;
+ a[j1 + 1] = x1i + x3r;
+ a[j3] = x1r + x3i;
+ a[j3 + 1] = x1i - x3r;
+ }
+ }
+ else
+ {
+ for (j = 0; j < l; j += 2)
+ {
+ j1 = j + l;
+ x0r = a[j] - a[j1];
+ x0i = a[j + 1] - a[j1 + 1];
+ a[j] += a[j1];
+ a[j + 1] += a[j1 + 1];
+ a[j1] = x0r;
+ a[j1 + 1] = x0i;
+ }
+ }
+
+ return;
+ }
+
+ /*-----------------------------------------------------------------*
+ * cft1st()
+ * Subfunction of Complex Discrete Fourier Transform
+ *-----------------------------------------------------------------*/
+
+ static void cft1st(
+ short n, /* i : data length of real and imag */
+ float *a, /* i/o : input/output data */
+ const float *w /* i : cos/sin table */
+ )
+ {
+ short j, k1, k2;
+ float wk1r, wk1i, wk2r, wk2i, wk3r, wk3i;
+ float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
+
+ x0r = a[0] + a[2];
+ x0i = a[1] + a[3];
+ x1r = a[0] - a[2];
+ x1i = a[1] - a[3];
+ x2r = a[4] + a[6];
+ x2i = a[5] + a[7];
+ x3r = a[4] - a[6];
+ x3i = a[5] - a[7];
+ a[0] = x0r + x2r;
+ a[1] = x0i + x2i;
+ a[4] = x0r - x2r;
+ a[5] = x0i - x2i;
+ a[2] = x1r - x3i;
+ a[3] = x1i + x3r;
+ a[6] = x1r + x3i;
+ a[7] = x1i - x3r;
+ wk1r = w[2];
+ x0r = a[8] + a[10];
+ x0i = a[9] + a[11];
+ x1r = a[8] - a[10];
+ x1i = a[9] - a[11];
+ x2r = a[12] + a[14];
+ x2i = a[13] + a[15];
+ x3r = a[12] - a[14];
+ x3i = a[13] - a[15];
+ a[8] = x0r + x2r;
+ a[9] = x0i + x2i;
+ a[12] = x2i - x0i;
+ a[13] = x0r - x2r;
+ x0r = x1r - x3i;
+ x0i = x1i + x3r;
+ a[10] = wk1r * (x0r - x0i);
+ a[11] = wk1r * (x0r + x0i);
+ x0r = x3i + x1r;
+ x0i = x3r - x1i;
+ a[14] = wk1r * (x0i - x0r);
+ a[15] = wk1r * (x0i + x0r);
+ k1 = 0;
+
+ for (j = 16; j < n; j += 16)
+ {
+ k1 += 2;
+ k2 = 2 * k1;
+ wk2r = w[k1];
+ wk2i = w[k1 + 1];
+ wk1r = w[k2];
+ wk1i = w[k2 + 1];
+ wk3r = wk1r - 2 * wk2i * wk1i;
+ wk3i = 2 * wk2i * wk1r - wk1i;
+ x0r = a[j] + a[j + 2];
+ x0i = a[j + 1] + a[j + 3];
+ x1r = a[j] - a[j + 2];
+ x1i = a[j + 1] - a[j + 3];
+ x2r = a[j + 4] + a[j + 6];
+ x2i = a[j + 5] + a[j + 7];
+ x3r = a[j + 4] - a[j + 6];
+ x3i = a[j + 5] - a[j + 7];
+ a[j] = x0r + x2r;
+ a[j + 1] = x0i + x2i;
+ x0r -= x2r;
+ x0i -= x2i;
+ a[j + 4] = wk2r * x0r - wk2i * x0i;
+ a[j + 5] = wk2r * x0i + wk2i * x0r;
+ x0r = x1r - x3i;
+ x0i = x1i + x3r;
+ a[j + 2] = wk1r * x0r - wk1i * x0i;
+ a[j + 3] = wk1r * x0i + wk1i * x0r;
+ x0r = x1r + x3i;
+ x0i = x1i - x3r;
+ a[j + 6] = wk3r * x0r - wk3i * x0i;
+ a[j + 7] = wk3r * x0i + wk3i * x0r;
+ wk1r = w[k2 + 2];
+ wk1i = w[k2 + 3];
+ wk3r = wk1r - 2 * wk2r * wk1i;
+ wk3i = 2 * wk2r * wk1r - wk1i;
+ x0r = a[j + 8] + a[j + 10];
+ x0i = a[j + 9] + a[j + 11];
+ x1r = a[j + 8] - a[j + 10];
+ x1i = a[j + 9] - a[j + 11];
+ x2r = a[j + 12] + a[j + 14];
+ x2i = a[j + 13] + a[j + 15];
+ x3r = a[j + 12] - a[j + 14];
+ x3i = a[j + 13] - a[j + 15];
+ a[j + 8] = x0r + x2r;
+ a[j + 9] = x0i + x2i;
+ x0r -= x2r;
+ x0i -= x2i;
+ a[j + 12] = -wk2i * x0r - wk2r * x0i;
+ a[j + 13] = -wk2i * x0i + wk2r * x0r;
+ x0r = x1r - x3i;
+ x0i = x1i + x3r;
+ a[j + 10] = wk1r * x0r - wk1i * x0i;
+ a[j + 11] = wk1r * x0i + wk1i * x0r;
+ x0r = x1r + x3i;
+ x0i = x1i - x3r;
+ a[j + 14] = wk3r * x0r - wk3i * x0i;
+ a[j + 15] = wk3r * x0i + wk3i * x0r;
+ }
+
+ return;
+ }
+
+ /*-----------------------------------------------------------------*
+ * cftmdl()
+ * Subfunction of Complex Discrete Fourier Transform
+ *-----------------------------------------------------------------*/
+
+ static void cftmdl(
+ short n, /* i : data length of real and imag */
+ short l, /* i : initial shift for processing */
+ float *a, /* i/o : input/output data */
+ const float *w /* i : cos/sin table */
+ )
+ {
+ short j, j1, j2, j3, k, k1, k2, m, m2;
+ float wk1r, wk1i, wk2r, wk2i, wk3r, wk3i;
+ float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
+
+ m = l << 2;
+ for (j = 0; j < l; j += 2)
+ {
+ j1 = j + l;
+ j2 = j1 + l;
+ j3 = j2 + l;
+ x0r = a[j] + a[j1];
+ x0i = a[j + 1] + a[j1 + 1];
+ x1r = a[j] - a[j1];
+ x1i = a[j + 1] - a[j1 + 1];
+ x2r = a[j2] + a[j3];
+ x2i = a[j2 + 1] + a[j3 + 1];
+ x3r = a[j2] - a[j3];
+ x3i = a[j2 + 1] - a[j3 + 1];
+ a[j] = x0r + x2r;
+ a[j + 1] = x0i + x2i;
+ a[j2] = x0r - x2r;
+ a[j2 + 1] = x0i - x2i;
+ a[j1] = x1r - x3i;
+ a[j1 + 1] = x1i + x3r;
+ a[j3] = x1r + x3i;
+ a[j3 + 1] = x1i - x3r;
+ }
+
+ wk1r = w[2];
+ for (j = m; j < l + m; j += 2)
+ {
+ j1 = j + l;
+ j2 = j1 + l;
+ j3 = j2 + l;
+ x0r = a[j] + a[j1];
+ x0i = a[j + 1] + a[j1 + 1];
+ x1r = a[j] - a[j1];
+ x1i = a[j + 1] - a[j1 + 1];
+ x2r = a[j2] + a[j3];
+ x2i = a[j2 + 1] + a[j3 + 1];
+ x3r = a[j2] - a[j3];
+ x3i = a[j2 + 1] - a[j3 + 1];
+ a[j] = x0r + x2r;
+ a[j + 1] = x0i + x2i;
+ a[j2] = x2i - x0i;
+ a[j2 + 1] = x0r - x2r;
+ x0r = x1r - x3i;
+ x0i = x1i + x3r;
+ a[j1] = wk1r * (x0r - x0i);
+ a[j1 + 1] = wk1r * (x0r + x0i);
+ x0r = x3i + x1r;
+ x0i = x3r - x1i;
+ a[j3] = wk1r * (x0i - x0r);
+ a[j3 + 1] = wk1r * (x0i + x0r);
+ }
+
+ k1 = 0;
+ m2 = 2 * m;
+ for (k = m2; k < n; k += m2)
+ {
+ k1 += 2;
+ k2 = 2 * k1;
+ wk2r = w[k1];
+ wk2i = w[k1 + 1];
+ wk1r = w[k2];
+ wk1i = w[k2 + 1];
+ wk3r = wk1r - 2 * wk2i * wk1i;
+ wk3i = 2 * wk2i * wk1r - wk1i;
+ for (j = k; j < l + k; j += 2)
+ {
+ j1 = j + l;
+ j2 = j1 + l;
+ j3 = j2 + l;
+ x0r = a[j] + a[j1];
+ x0i = a[j + 1] + a[j1 + 1];
+ x1r = a[j] - a[j1];
+ x1i = a[j + 1] - a[j1 + 1];
+ x2r = a[j2] + a[j3];
+ x2i = a[j2 + 1] + a[j3 + 1];
+ x3r = a[j2] - a[j3];
+ x3i = a[j2 + 1] - a[j3 + 1];
+ a[j] = x0r + x2r;
+ a[j + 1] = x0i + x2i;
+ x0r -= x2r;
+ x0i -= x2i;
+ a[j2] = wk2r * x0r - wk2i * x0i;
+ a[j2 + 1] = wk2r * x0i + wk2i * x0r;
+ x0r = x1r - x3i;
+ x0i = x1i + x3r;
+ a[j1] = wk1r * x0r - wk1i * x0i;
+ a[j1 + 1] = wk1r * x0i + wk1i * x0r;
+ x0r = x1r + x3i;
+ x0i = x1i - x3r;
+ a[j3] = wk3r * x0r - wk3i * x0i;
+ a[j3 + 1] = wk3r * x0i + wk3i * x0r;
+ }
+
+ wk1r = w[k2 + 2];
+ wk1i = w[k2 + 3];
+ wk3r = wk1r - 2 * wk2r * wk1i;
+ wk3i = 2 * wk2r * wk1r - wk1i;
+ for (j = k + m; j < l + (k + m); j += 2)
+ {
+ j1 = j + l;
+ j2 = j1 + l;
+ j3 = j2 + l;
+ x0r = a[j] + a[j1];
+ x0i = a[j + 1] + a[j1 + 1];
+ x1r = a[j] - a[j1];
+ x1i = a[j + 1] - a[j1 + 1];
+ x2r = a[j2] + a[j3];
+ x2i = a[j2 + 1] + a[j3 + 1];
+ x3r = a[j2] - a[j3];
+ x3i = a[j2 + 1] - a[j3 + 1];
+ a[j] = x0r + x2r;
+ a[j + 1] = x0i + x2i;
+ x0r -= x2r;
+ x0i -= x2i;
+ a[j2] = -wk2i * x0r - wk2r * x0i;
+ a[j2 + 1] = -wk2i * x0i + wk2r * x0r;
+ x0r = x1r - x3i;
+ x0i = x1i + x3r;
+ a[j1] = wk1r * x0r - wk1i * x0i;
+ a[j1 + 1] = wk1r * x0i + wk1i * x0r;
+ x0r = x1r + x3i;
+ x0i = x1i - x3r;
+ a[j3] = wk3r * x0r - wk3i * x0i;
+ a[j3 + 1] = wk3r * x0i + wk3i * x0r;
+ }
+ }
+
+ return;
+ }
+
+ static
+ void cftbsub(
+ short n,
+ float *a,
+ const float *w /* i : cos/sin table */
+ )
+ {
+ short j, j1, j2, j3, l;
+ float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
+
+ l = 2;
+ if (n > 8)
+ {
+ cft1st(n, a, w);
+ l = 8;
+
+ while ((l << 2) < n)
+ {
+ cftmdl(n, l, a, w);
+ l <<= 2;
+ }
+ }
+
+ if ((l << 2) == n)
+ {
+ for (j = 0; j < l; j += 2)
+ {
+ j1 = j + l;
+ j2 = j1 + l;
+ j3 = j2 + l;
+ x0r = a[j] + a[j1];
+ x0i = -a[j + 1] - a[j1 + 1];
+ x1r = a[j] - a[j1];
+ x1i = -a[j + 1] + a[j1 + 1];
+ x2r = a[j2] + a[j3];
+ x2i = a[j2 + 1] + a[j3 + 1];
+ x3r = a[j2] - a[j3];
+ x3i = a[j2 + 1] - a[j3 + 1];
+ a[j] = x0r + x2r;
+ a[j + 1] = x0i - x2i;
+ a[j2] = x0r - x2r;
+ a[j2 + 1] = x0i + x2i;
+ a[j1] = x1r - x3i;
+ a[j1 + 1] = x1i - x3r;
+ a[j3] = x1r + x3i;
+ a[j3 + 1] = x1i + x3r;
+ }
+ }
+ else
+ {
+ for (j = 0; j < l; j += 2)
+ {
+ j1 = j + l;
+ x0r = a[j] - a[j1];
+ x0i = -a[j + 1] + a[j1 + 1];
+ a[j] += a[j1];
+ a[j + 1] = -a[j + 1] - a[j1 + 1];
+ a[j1] = x0r;
+ a[j1 + 1] = x0i;
+ }
+ }
+ }
+
+ static
+ void rftfsub(
+ short n,
+ float *a,
+ short nc,
+ const float *c
+ )
+ {
+ short j, k, kk, ks, m;
+ float wkr, wki, xr, xi, yr, yi;
+
+ m = n >> 1;
+ ks = 2 * nc / m;
+ kk = 0;
+ for (j = 2; j < m; j += 2)
+ {
+ k = n - j;
+ kk += ks;
+ wkr = 0.5f - c[nc - kk];
+ wki = c[kk];
+ xr = a[j] - a[k];
+ xi = a[j + 1] + a[k + 1];
+ yr = wkr * xr - wki * xi;
+ yi = wkr * xi + wki * xr;
+ a[j] -= yr;
+ a[j + 1] -= yi;
+ a[k] += yr;
+ a[k + 1] -= yi;
+ }
+ }
+
+
+ static
+ void rftbsub(
+ short n,
+ float *a,
+ short nc,
+ const float *c
+ )
+ {
+ short j, k, kk, ks, m;
+ float wkr, wki, xr, xi, yr, yi;
+
+ a[1] = -a[1];
+ m = n >> 1;
+ ks = 2 * nc / m;
+ kk = 0;
+ for (j = 2; j < m; j += 2)
+ {
+ k = n - j;
+ kk += ks;
+ wkr = 0.5f - c[nc - kk];
+ wki = c[kk];
+ xr = a[j] - a[k];
+ xi = a[j + 1] + a[k + 1];
+ yr = wkr * xr + wki * xi;
+ yi = wkr * xi - wki * xr;
+ a[j] -= yr;
+ a[j + 1] = yi - a[j + 1];
+ a[k] += yr;
+ a[k + 1] = yi - a[k + 1];
+ }
+ a[m + 1] = -a[m + 1];
+ }
+
+
+ static
+ void dctsub(
+ short n,
+ float *a,
+ short nc,
+ const float *c
+ )
+ {
+ short j, k, kk, ks, m;
+ float wkr, wki, xr;
+
+ m = n >> 1;
+ ks = nc / n;
+ kk = 0;
+ for (j = 1; j < m; j++)
+ {
+ k = n - j;
+ kk += ks;
+ wkr = c[kk] - c[nc - kk];
+ wki = c[kk] + c[nc - kk];
+ xr = wki * a[j] - wkr * a[k];
+ a[j] = wkr * a[j] + wki * a[k];
+ a[k] = xr;
+ }
+ a[m] *= c[0];
+ }
+
+
+ /*-----------------------------------------------------------------*
+ * edct2()
+ *
+ * Transformation of the signal to DCT domain
+ * OR Inverse EDCT-II for short frames
+ *-----------------------------------------------------------------*/
+
+ void edct2(
+ short n,
+ short isgn,
+ float *in,
+ float *a,
+ const short *ip,
+ const float *w
+ )
+ {
+ short j, nw, nc;
+ float xr;
+
+ mvr2r(in, a, n);
+
+ nw = ip[0];
+ if (n > (nw << 2))
+ {
+ nw = n >> 2;
+ }
+
+ nc = ip[1];
+ if (n > nc)
+ {
+ nc = n;
+ }
+
+ if (isgn < 0)
+ {
+ xr = a[n - 1];
+ for (j = n - 2; j >= 2; j -= 2)
+ {
+ a[j + 1] = a[j] - a[j - 1];
+ a[j] += a[j - 1];
+ }
+ a[1] = a[0] - xr;
+ a[0] += xr;
+
+ if (n > 4)
+ {
+ rftbsub(n, a, nc, w + nw);
+ bitrv2_SR(n, ip + 2, a);
+ cftbsub(n, a, w);
+ }
+ else if (n == 4)
+ {
+ cftfsub(n, a, w);
+ }
+ }
+
+ if (isgn >= 0)
+ {
+ a[0] *= 0.5f;
+ }
+
+ dctsub(n, a, nc, w + nw);
+
+ if (isgn >= 0)
+ {
+ if (n > 4)
+ {
+ bitrv2_SR(n, ip + 2, a);
+ cftfsub(n, a, w);
+ rftfsub(n, a, nc, w + nw);
+ }
+ else if (n == 4)
+ {
+ cftfsub(n, a, w);
+ }
+ xr = a[0] - a[1];
+ a[0] += a[1];
+ for (j = 2; j < n; j += 2)
+ {
+ a[j - 1] = a[j] - a[j + 1];
+ a[j] += a[j + 1];
+ }
+ a[n - 1] = xr;
+
+ for (j = 0; j < n; j ++)
+ {
+ a[j] /= 32.0f;
+ }
+ }
+ }
+
+
+ void DoRTFTn(
+ float *x, /* i/o : real part of input and output data */
+ float *y, /* i/o : imaginary part of input and output data */
+ const short n /* i : size of the FFT up to 1024 */
+ )
+ {
+
+ int i;
+ float z[2048];
+
+ for ( i=0; i 0);
+
+ if (len == 640)
+ {
+ float x[320], y[320];
+ int i;
+
+ if (sign != -1)
+ {
+ rfft_pre(sine_table, data, len);
+ }
+
+ for (i = 0; i < 320; i++)
+ {
+ x[i] = data[2*i];
+ y[i] = data[2*i+1];
+ }
+ DoRTFT320(x, y);
+ for (i = 0; i < 320; i++)
+ {
+ data[2*i] = x[i];
+ data[2*i+1] = y[i];
+ }
+
+ if (sign == -1)
+ {
+ rfft_post(sine_table, data, len);
+ }
+ }
+ else
+ {
+ if (len == 512)
+ {
+ int i;
+ int const log2 = 9;
+ float reordered_data[512];
+
+ if (sign == -1)
+ {
+ fft_rel(data, len, log2);
+ reordered_data[0] = data[0];
+ reordered_data[1] = data[len/2];
+ for (i = 1; i < len/2; i++)
+ {
+ reordered_data[2*i] = data[i];
+ reordered_data[2*i+1] = data[len-i];
+ }
+ }
+ else
+ {
+ reordered_data[0] = data[0];
+ reordered_data[len/2] = data[1];
+ for (i = 1; i < len/2; i++)
+ {
+ reordered_data[i] = data[2*i];
+ reordered_data[len-i] = data[2*i+1];
+ }
+ ifft_rel(reordered_data, len, log2);
+ }
+ mvr2r(reordered_data, data, len);
+ }
+ else
+ {
+ assert(!"Not supported FFT length!");
+ }
+ }
+
+ return 0;
+ }
+
+ static void butterfly(const float a, const float b, float *aPlusb, float *aMinusb)
+ {
+ *aPlusb = a + b;
+ *aMinusb = a - b;
+ }
+
+ static void fft2(float *pInOut)
+ {
+ /* FFT MATRIX:
+ 1.0000 1.0000
+ 1.0000 -1.0000
+ */
+ float re1, im1;
+ float re2, im2;
+
+ re1 = pInOut[0];
+ im1 = pInOut[1];
+ re2 = pInOut[2];
+ im2 = pInOut[3];
+ pInOut[0] = re1 + re2;
+ pInOut[1] = im1 + im2;
+
+ pInOut[2] = re1 - re2;
+ pInOut[3] = im1 - im2;
+
+ }
+
+ static const float C31 = 0.5f; /* cos(PI/3); sin(2*PI/3) */
+static const float C32 = 0.866025403784439f; /* cos(PI/3); sin(2*PI/3) */
+
+ static void fft3_2(float *pInOut)
+ {
+ float re1, im1;
+ float re2, im2;
+ float re3, im3;
+
+ float tmp1, tmp2;
+ float tmp3, tmp4;
+
+ re1 = pInOut[0];
+ im1 = pInOut[1];
+ re2 = pInOut[2];
+ im2 = pInOut[3];
+ re3 = pInOut[4];
+ im3 = pInOut[5];
+
+ /* FFT MATRIX:
+ 1.0000 1.0000 1.0000
+ C31 C32
+ 1.0000 -0.5000 - 0.8660i -0.5000 + 0.8660i
+ 1.0000 -0.5000 + 0.8660i -0.5000 - 0.8660i
+ */
+ tmp1 = re2 + re3;
+ tmp3 = im2 + im3;
+ tmp2 = re2 - re3;
+ tmp4 = im2 - im3;
+ pInOut[0] = re1 + tmp1;
+ pInOut[1] = im1 + tmp3;
+ pInOut[2] = re1 - C31 * tmp1 + C32 * tmp4;
+ pInOut[4] = re1 - C31 * tmp1 - C32 * tmp4;
+
+ pInOut[3] = im1 - C32 * tmp2 - C31 * tmp3;
+ pInOut[5] = im1 + C32 * tmp2 - C31 * tmp3;
+
+ }
+
+
+ static void fft4(float *pInOut)
+ {
+ float re1, im1;
+ float re2, im2;
+ float re3, im3;
+ float re4, im4;
+
+ float tmp1, tmp2;
+ float tmp3, tmp4;
+ float tmp5, tmp6;
+ float tmp7, tmp8;
+
+ re1 = pInOut[0];
+ im1 = pInOut[1];
+ re2 = pInOut[2];
+ im2 = pInOut[3];
+ re3 = pInOut[4];
+ im3 = pInOut[5];
+ re4 = pInOut[6];
+ im4 = pInOut[7];
+
+ /*
+ 1.0000 1.0000 1.0000 1.0000
+ 1.0000 -1.0000i -1.0000 1.0000i
+ 1.0000 -1.0000 1.0000 -1.0000
+ 1.0000 1.0000i -1.0000 -1.0000i
+ */
+ tmp1 = re1 + re3;
+ tmp3 = re2 + re4;
+ tmp5 = im1 + im3;
+ tmp7 = im2 + im4;
+ pInOut[0] = tmp1 + tmp3;
+ pInOut[4] = tmp1 - tmp3;
+
+ pInOut[1] = tmp5 + tmp7;
+ pInOut[5] = tmp5 - tmp7;
+ tmp2 = re1 - re3;
+ tmp4 = re2 - re4;
+ tmp6 = im1 - im3;
+ tmp8 = im2 - im4;
+ pInOut[2] = tmp2 + tmp8;
+ pInOut[6] = tmp2 - tmp8;
+
+ pInOut[3] = -tmp4 + tmp6;
+ pInOut[7] = tmp4 + tmp6;
+
+ }
+
+ static const float C51 = 0.309016994374947f; /* cos(2*PI/5); */
+static const float C52 = 0.951056516295154f; /* sin(2*PI/5); */
+static const float C53 = 0.809016994374947f; /* cos( PI/5); */
+static const float C54 = 0.587785252292473f; /* sin( PI/5); */
+
+ static void fft5(float *pInOut)
+ {
+ float re1, im1;
+ float re2, im2;
+ float re3, im3;
+ float re4, im4;
+ float re5, im5;
+
+ float tmp1, tmp2;
+ float tmp3, tmp4;
+ float tmp5, tmp6;
+ float tmp7, tmp8;
+
+
+ re1 = pInOut[0];
+ im1 = pInOut[1];
+ re2 = pInOut[2];
+ im2 = pInOut[3];
+ re3 = pInOut[4];
+ im3 = pInOut[5];
+ re4 = pInOut[6];
+ im4 = pInOut[7];
+ re5 = pInOut[8];
+ im5 = pInOut[9];
+
+ /*
+ 1.0000 1.0000 1.0000 1.0000 1.0000
+ C51 C52 C53 C54
+ 1.0000 0.3090 - 0.9511i -0.8090 - 0.5878i -0.8090 + 0.5878i 0.3090 + 0.9511i
+ 1.0000 -0.8090 - 0.5878i 0.3090 + 0.9511i 0.3090 - 0.9511i -0.8090 + 0.5878i
+ 1.0000 -0.8090 + 0.5878i 0.3090 - 0.9511i 0.3090 + 0.9511i -0.8090 - 0.5878i
+ 1.0000 0.3090 + 0.9511i -0.8090 + 0.5878i -0.8090 - 0.5878i 0.3090 - 0.9511i
+ */
+ tmp1 = re2 + re5;
+ tmp2 = re2 - re5;
+ tmp3 = im2 + im5;
+ tmp4 = im2 - im5;
+ tmp5 = re3 + re4;
+ tmp6 = re3 - re4;
+ tmp7 = im3 + im4;
+ tmp8 = im3 - im4;
+
+
+ pInOut[0] = re1 + tmp1 + tmp5;
+ pInOut[1] = im1 + tmp3 + tmp7;
+
+ pInOut[2] = re1 + C51 * tmp1 - C53 * tmp5 + C52 * tmp4 + C54 * tmp8;
+ pInOut[8] = re1 + C51 * tmp1 - C53 * tmp5 - C52 * tmp4 - C54 * tmp8;
+ pInOut[3] = im1 - C52 * tmp2 - C54 * tmp6 + C51 * tmp3 - C53 * tmp7;
+ pInOut[9] = im1 + C52 * tmp2 + C54 * tmp6 + C51 * tmp3 - C53 * tmp7;
+ pInOut[4] = re1 - C53 * tmp1 + C51 * tmp5 + C54 * tmp4 - C52 * tmp8;
+ pInOut[6] = re1 - C53 * tmp1 + C51 * tmp5 - C54 * tmp4 + C52 * tmp8;
+ pInOut[5] = im1 - C54 * tmp2 + C52 * tmp6 - C53 * tmp3 + C51 * tmp7;
+ pInOut[7] = im1 + C54 * tmp2 - C52 * tmp6 - C53 * tmp3 + C51 * tmp7;
+
+
+ }
+
+ static const float C81 = 0.707106781186548f; /* cos(PI/4); */
+
+ static void fft8_2(float *pInOut)
+ {
+ float re0, im0, re4, im4;
+
+ float re1_7p, re1_7m;
+ float im1_7p, im1_7m;
+ float re2_6p, re2_6m;
+ float im2_6p, im2_6m;
+ float re3_5p, re3_5m;
+ float im3_5p, im3_5m;
+
+ re0 = pInOut[0];
+ im0 = pInOut[1];
+ re4 = pInOut[8];
+ im4 = pInOut[9];
+ butterfly(pInOut[1*2 ], pInOut[7*2 ],&re1_7p, &re1_7m);
+ butterfly(pInOut[1*2+1], pInOut[7*2+1],&im1_7p, &im1_7m);
+ butterfly(pInOut[2*2 ], pInOut[6*2 ],&re2_6p, &re2_6m);
+ butterfly(pInOut[2*2+1], pInOut[6*2+1],&im2_6p, &im2_6m);
+ butterfly(pInOut[3*2 ], pInOut[5*2 ],&re3_5p, &re3_5m);
+ butterfly(pInOut[3*2+1], pInOut[5*2+1],&im3_5p, &im3_5m);
+
+ /*
+ 0: 1 + 0i 1 + 0i 1 + 0i 1 + 0i 1 + 0i 1 + 0i 1 + 0i 1 + 0i
+ 1: 1 + 0i C81 - C81i 0 - 1i -C81 - C81i -1 - 0i -C81 + C81i - 0 + 1i C81 + C81i
+ 2: 1 + 0i 0 - 1i -1 - 0i - 0 + 1i 1 + 0i 0 - 1i - 1 - 0i - 0 + 1i
+ 3: 1 + 0i -C81 - C81i -0 + 1i C81 - C81i -1 - 0i C81 + C81i 0 - 1i -C81 + C81i
+ 4: 1 + 0i - 1 - 0i 1 + 0i - 1 - 0i 1 + 0i - 1 - 0i 1 + 0i - 1 - 0i
+ 5: 1 + 0i -C81 + C81i 0 - 1i C81 + C81i -1 - 0i C81 - C81i - 0 + 1i -C81 - C81i
+ 6: 1 + 0i - 0 + 1i -1 - 0i 0 - 1i 1 + 0i - 0 + 1i - 1 - 0i - 0 - 1i
+ 7: 1 + 0i C81 + C81i -0 + 1i -C81 + C81i -1 - 0i -C81 - C81i - 0 - 1i C81 - C81i
+ */
+ pInOut[ 0] = re0 + re4 + re1_7p + re2_6p + re3_5p;
+ pInOut[ 1] = im0 + im4 + im1_7p + im2_6p + im3_5p;
+
+ pInOut[ 2] = re0 + C81*(re1_7p - re3_5p) - re4 + C81*( im1_7m + im3_5m) + im2_6m;
+ pInOut[ 3] = im0 + C81*(im1_7p - im3_5p) - im4 - C81* (re1_7m + re3_5m) - re2_6m;
+
+ pInOut[ 4] = re0 - re2_6p + re4 + im1_7m - im3_5m;
+ pInOut[ 5] = im0 - im2_6p + im4 - re1_7m + re3_5m;
+
+ pInOut[ 6] = re0 + C81*(-re1_7p + re3_5p) - re4 + C81*( im1_7m + im3_5m) - im2_6m;
+ pInOut[ 7] = im0 + C81*(-im1_7p + im3_5p) - im4 - C81* (re1_7m + re3_5m) + re2_6m;
+
+ pInOut[ 8] = re0 - re1_7p + re2_6p - re3_5p + re4;
+ pInOut[ 9] = im0 - im1_7p + im2_6p - im3_5p + im4;
+
+ pInOut[10] = re0 + C81*(-re1_7p + re3_5p) - re4 - C81*( im1_7m + im3_5m) + im2_6m;
+ pInOut[11] = im0 + C81*(-im1_7p + im3_5p) - im4 + C81* (re1_7m + re3_5m) - re2_6m;
+
+ pInOut[12] = re0 - re2_6p + re4 - im1_7m + im3_5m;
+ pInOut[13] = im0 - im2_6p + im4 + re1_7m - re3_5m;
+
+ pInOut[14] = re0 + C81*(re1_7p - re3_5p) - re4 - C81*( im1_7m + im3_5m) - im2_6m;
+ pInOut[15] = im0 + C81*(im1_7p - im3_5p) - im4 + C81* (re1_7m + re3_5m) + re2_6m;
+
+ }
+
+ static void nextFFT(float *x, int length)
+ {
+ switch(length)
+ {
+ case 2:
+ fft2(x);
+ break;
+ case 3:
+ fft3_2(x);
+ break;
+ case 4:
+ fft4(x);
+ break;
+ case 5:
+ fft5(x);
+ break;
+ case 8:
+ fft8_2(x);
+ break;
+ default:
+ assert(!"length not supported");
+ break;
+ }
+ }
+
+ static const int CTFFTfactors[] = {9,8,7,5,4,3,2,0};
+
+ static __inline int findFactor(const int length)
+ {
+ int i = 0;
+ int factor = 0;
+
+ while(CTFFTfactors[i]!=0)
+ {
+ if(0==(length%CTFFTfactors[i]))
+ {
+ factor = CTFFTfactors[i];
+ break;
+ }
+ i++;
+ }
+ return factor;
+ }
+
+ static __inline void twiddle(float *x, const int length, const int n1, const int n2)
+ {
+ int i, ii;
+ double pi = 4. * atan(1.);
+ float sinValOrg, cosValOrg;
+ float sinVal=0.f, cosVal=1.f;
+ float twReal=0.f, twImag=1.f;
+
+ cosValOrg = (float) cos(-2*pi*1./(double)length);
+ sinValOrg = (float) sin(-2*pi*1./(double)length);
+ for(i=1; i0&&(length/factor>1))
+ {
+ n1 = factor;
+ n2 = length/factor;
+
+ /* DATA Resorting for stage1 */
+ dest = scratch;
+ for (i=0; i<2*n1; i+=2)
+ {
+ src = x+i;
+ for(ii=0; ii1)
+ {
+ float *tmp = scratch1;
+ int n1_inv=1, n2_inv=1;
+ int n2 = factor[0/*idx*/];
+ int n1 = length/n2;
+ int idx, incr;
+
+ while(((n1_inv*n1)%n2)!=1)
+ {
+ n1_inv++;
+ }
+ while(((n2_inv*n2)%n1)!=1)
+ {
+ n2_inv++;
+ }
+ idx = 0;
+ incr = n1*n1_inv;
+ cnt = 0;
+ for(i=0; ilength)
+ {
+ idx -= length;
+ }
+ }
+ tmp[cnt++] = x[2*idx ];
+ tmp[cnt++] = x[2*idx+1];
+ idx++;
+ }
+ for(cnt=0; cntlength)
+ {
+ idx -= length;
+ }
+ }
+ }
+ for(cnt=0; cnt
+ #include "wmc_auto.h"
+ #include
+ #include "prot.h"
+
+
+
+ #if defined __ICL
+ #define restrict __restrict
+ #else
+ #define restrict
+ #endif
+
+ #ifdef _MSC_VER
+ #pragma warning(disable : 4305) /* disable truncation from double to float warning (VC++)*/
+ #endif
+
+ static void fft8(float *vec);
+ static void fft10(float *vec);
+ static void fft16(float *vec);
+ static void fft20(float *vec);
+ static void fft30(float *vec);
+ static void fft5s(float *x, int stride);
+
+
+ static const float INV_SQRT2 = 7.071067811865475e-1;
+static const float COS_PI_DIV8 = 9.238795325112867e-1;
+static const float COS_3PI_DIV8 = 3.826834323650898e-1;
+static const float SQRT2PLUS1 = 2.414213562373095;
+static const float SQRT2MINUS1 = 4.142135623730952e-1;
+
+
+ #ifdef _MSC_VER
+ #pragma warning(default : 4305)
+ #endif
+
+ /*******************************************************************************
+ Functionname: fft8
+ *******************************************************************************
+
+ Description: 8-point FFT. Complex-valued input takes 52 real additions
+ and 4 real multiplications.
+
+ Arguments: vec - pointer to data (interleaved real / imaginary parts)
+
+ Return: none
+
+ *******************************************************************************/
+ static void fft8(float * restrict vec)
+ {
+ float temp1[16];
+ float temp2[16];
+
+
+ /* Pre-additions */
+ temp1[0] = vec[0] + vec[8];
+ temp1[2] = vec[0] - vec[8];
+ temp1[1] = vec[1] + vec[9];
+ temp1[3] = vec[1] - vec[9];
+ temp1[4] = vec[2] + vec[10];
+ temp1[6] = vec[2] - vec[10];
+ temp1[5] = vec[3] + vec[11];
+ temp1[7] = vec[3] - vec[11];
+ temp1[8] = vec[4] + vec[12];
+ temp1[10] = vec[4] - vec[12];
+ temp1[9] = vec[5] + vec[13];
+ temp1[11] = vec[5] - vec[13];
+ temp1[12] = vec[6] + vec[14];
+ temp1[14] = vec[6] - vec[14];
+ temp1[13] = vec[7] + vec[15];
+ temp1[15] = vec[7] - vec[15];
+
+ /* Pre-additions and core multiplications */
+ temp2[0] = temp1[0] + temp1[8];
+ temp2[4] = temp1[0] - temp1[8];
+ temp2[1] = temp1[1] + temp1[9];
+ temp2[5] = temp1[1] - temp1[9];
+ temp2[8] = temp1[2] - temp1[11];
+ temp2[10] = temp1[2] + temp1[11];
+ temp2[9] = temp1[3] + temp1[10];
+ temp2[11] = temp1[3] - temp1[10];
+ temp2[2] = temp1[4] + temp1[12];
+ temp2[7] = temp1[4] - temp1[12];
+ temp2[3] = temp1[5] + temp1[13];
+ temp2[6] = temp1[13]- temp1[5];
+
+ temp1[1] = temp1[6] + temp1[14];
+ temp1[2] = temp1[6] - temp1[14];
+ temp1[0] = temp1[7] + temp1[15];
+ temp1[3] = temp1[7] - temp1[15];
+
+ temp2[12] = (temp1[0] + temp1[2]) * INV_SQRT2;
+ temp2[14] = (temp1[0] - temp1[2]) * INV_SQRT2;
+ temp2[13] = (temp1[3] - temp1[1]) * INV_SQRT2;
+ temp2[15] = (temp1[1] + temp1[3]) * -INV_SQRT2;
+
+ /* Post-additions */
+ vec[0] = temp2[0] + temp2[2];
+ vec[8] = temp2[0] - temp2[2];
+ vec[1] = temp2[1] + temp2[3];
+ vec[9] = temp2[1] - temp2[3];
+ vec[4] = temp2[4] - temp2[6];
+ vec[12] = temp2[4] + temp2[6];
+ vec[5] = temp2[5] - temp2[7];
+ vec[13] = temp2[5] + temp2[7];
+ vec[6] = temp2[8] + temp2[14];
+ vec[14] = temp2[8] - temp2[14];
+ vec[7] = temp2[9] + temp2[15];
+ vec[15] = temp2[9] - temp2[15];
+ vec[2] = temp2[10]+ temp2[12];
+ vec[10] = temp2[10]- temp2[12];
+ vec[3] = temp2[11]+ temp2[13];
+ vec[11] = temp2[11]- temp2[13];
+
+ }
+
+
+
+ /*******************************************************************************
+ Functionname: fft16
+ *******************************************************************************
+
+ Description: 16-point FFT. Complex-valued input takes 144 real additions and
+ 24 real multiplications.
+
+ Arguments: vec - pointer to data (interleaved real / imaginary parts)
+
+ Return: none
+
+ *******************************************************************************/
+ /* fast implementation, completely unrolled and inlined */
+ static void fft16(float * restrict vec)
+ {
+ float temp10, temp11, temp12, temp13, temp14, temp15, temp16, temp17,
+ temp18, temp19, temp110, temp111, temp112, temp113, temp114, temp115;
+ float temp20, temp21, temp22, temp23, temp24, temp25, temp26, temp27,
+ temp28, temp29, temp210, temp211, temp212, temp213, temp214, temp215;
+ float vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7,
+ vec8, vec9, vec10, vec11, vec12, vec13, vec14, vec15;
+
+
+ /* even */
+ vec0 = vec[0] + vec[16];
+ vec1 = vec[1] + vec[17];
+ vec2 = vec[2] + vec[18];
+ vec3 = vec[3] + vec[19];
+ vec4 = vec[4] + vec[20];
+ vec5 = vec[5] + vec[21];
+ vec6 = vec[6] + vec[22];
+ vec7 = vec[7] + vec[23];
+ vec8 = vec[8] + vec[24];
+ vec9 = vec[9] + vec[25];
+ vec10 = vec[10] + vec[26];
+ vec11 = vec[11] + vec[27];
+ vec12 = vec[12] + vec[28];
+ vec13 = vec[13] + vec[29];
+ vec14 = vec[14] + vec[30];
+ vec15 = vec[15] + vec[31];
+
+ /* Pre-additions */
+ temp10 = vec0 + vec8;
+ temp12 = vec0 - vec8;
+ temp11 = vec1 + vec9;
+ temp13 = vec1 - vec9;
+ temp14 = vec2 + vec10;
+ temp16 = vec2 - vec10;
+ temp15 = vec3 + vec11;
+ temp17 = vec3 - vec11;
+ temp18 = vec4 + vec12;
+ temp110 = vec4 - vec12;
+ temp19 = vec5 + vec13;
+ temp111 = vec5 - vec13;
+ temp112 = vec6 + vec14;
+ temp114 = vec6 - vec14;
+ temp113 = vec7 + vec15;
+ temp115 = vec7 - vec15;
+
+ /* Pre-additions and core multiplications */
+ temp20 = temp10 + temp18;
+ temp24 = temp10 - temp18;
+ temp21 = temp11 + temp19;
+ temp25 = temp11 - temp19;
+ temp28 = temp12 - temp111;
+ temp210 = temp12 + temp111;
+ temp29 = temp13 + temp110;
+ temp211 = temp13 - temp110;
+ temp22 = temp14 + temp112;
+ temp27 = temp14 - temp112;
+ temp23 = temp15 + temp113;
+ temp26 = temp113- temp15;
+
+ temp11 = temp16 + temp114;
+ temp12 = temp16 - temp114;
+ temp10 = temp17 + temp115;
+ temp13 = temp17 - temp115;
+
+ temp212 = (temp10 + temp12) * INV_SQRT2;
+ temp214 = (temp10 - temp12) * INV_SQRT2;
+ temp213 = (temp13 - temp11) * INV_SQRT2;
+ temp215 = (temp11 + temp13) * -INV_SQRT2;
+
+
+
+ /* odd */
+ vec0 = vec[0] - vec[16];
+ vec1 = vec[1] - vec[17];
+ vec2 = vec[2] - vec[18];
+ vec3 = vec[3] - vec[19];
+ vec4 = vec[4] - vec[20];
+ vec5 = vec[5] - vec[21];
+ vec6 = vec[6] - vec[22];
+ vec7 = vec[7] - vec[23];
+ vec8 = vec[8] - vec[24];
+ vec9 = vec[9] - vec[25];
+ vec10 = vec[10] - vec[26];
+ vec11 = vec[11] - vec[27];
+ vec12 = vec[12] - vec[28];
+ vec13 = vec[13] - vec[29];
+ vec14 = vec[14] - vec[30];
+ vec15 = vec[15] - vec[31];
+
+ /* Pre-additions and core multiplications */
+ temp19 = (vec2 + vec14) * -COS_3PI_DIV8;
+ temp110 = (vec2 - vec14) * COS_PI_DIV8;
+ temp18 = (vec3 + vec15) * COS_3PI_DIV8;
+ temp111 = (vec3 - vec15) * COS_PI_DIV8;
+ temp15 = (vec4 + vec12) * -INV_SQRT2;
+ temp16 = (vec4 - vec12) * INV_SQRT2;
+ temp14 = (vec5 + vec13) * INV_SQRT2;
+ temp17 = (vec5 - vec13) * INV_SQRT2;
+ temp113 = (vec6 + vec10) * -COS_PI_DIV8;
+ temp114 = (vec6 - vec10) * COS_3PI_DIV8;
+ temp112 = (vec7 + vec11) * COS_PI_DIV8;
+ temp115 = (vec7 - vec11) * COS_3PI_DIV8;
+
+ /* Core multiplications */
+ vec2 = temp18 * SQRT2PLUS1 - temp112 * SQRT2MINUS1;
+ vec3 = temp19 * SQRT2PLUS1 - temp113 * SQRT2MINUS1;
+ vec4 = temp110 * SQRT2MINUS1 - temp114 * SQRT2PLUS1;
+ vec5 = temp111 * SQRT2MINUS1 - temp115 * SQRT2PLUS1;
+
+ /* Post-additions */
+ temp18 += temp112;
+ temp19 += temp113;
+ temp110+= temp114;
+ temp111+= temp115;
+
+ vec6 = vec0 + temp14;
+ vec10 = vec0 - temp14;
+ vec7 = vec1 + temp15;
+ vec11 = vec1 - temp15;
+
+ vec12 = temp16 - vec9;
+ vec14 = temp16 + vec9;
+ vec13 = vec8 + temp17;
+ vec15 = vec8 - temp17;
+
+ temp10 = vec6 - vec14;
+ temp12 = vec6 + vec14;
+ temp11 = vec7 + vec15;
+ temp13 = vec7 - vec15;
+ temp14 = vec10 + vec12;
+ temp16 = vec10 - vec12;
+ temp15 = vec11 + vec13;
+ temp17 = vec11 - vec13;
+
+ vec10 = temp18 + temp110;
+ temp110 = temp18 - temp110;
+ vec11 = temp19 + temp111;
+ temp111 = temp19 - temp111;
+
+ temp112 = vec2 + vec4;
+ temp114 = vec2 - vec4;
+ temp113 = vec3 + vec5;
+ temp115 = vec3 - vec5;
+
+
+ /* Post-additions */
+ *vec++ = temp20 + temp22;
+ *vec++ = temp21 + temp23;
+ *vec++ = temp12 + vec10;
+ *vec++ = temp13 + vec11;
+ *vec++ = temp210+ temp212;
+ *vec++ = temp211+ temp213;
+ *vec++ = temp10 + temp112;
+ *vec++ = temp11 + temp113;
+ *vec++ = temp24 - temp26;
+ *vec++ = temp25 - temp27;
+ *vec++ = temp16 + temp114;
+ *vec++ = temp17 + temp115;
+ *vec++ = temp28 + temp214;
+ *vec++ = temp29 + temp215;
+ *vec++ = temp14 + temp110;
+ *vec++ = temp15 + temp111;
+ *vec++ = temp20 - temp22;
+ *vec++ = temp21 - temp23;
+ *vec++ = temp12 - vec10;
+ *vec++ = temp13 - vec11;
+ *vec++ = temp210- temp212;
+ *vec++ = temp211- temp213;
+ *vec++ = temp10 - temp112;
+ *vec++ = temp11 - temp113;
+ *vec++ = temp24 + temp26;
+ *vec++ = temp25 + temp27;
+ *vec++ = temp16 - temp114;
+ *vec++ = temp17 - temp115;
+ *vec++ = temp28 - temp214;
+ *vec++ = temp29 - temp215;
+ *vec++ = temp14 - temp110;
+ *vec++ = temp15 - temp111;
+
+ }
+
+
+ /*******************************************************************************
+ Functionname: fft15
+ *******************************************************************************
+
+ Description: 15-point FFT. Complex-valued input takes 176 real additions
+ and 34 real multiplications.
+
+ Arguments: vec - pointer to data (interleaved real / imaginary parts)
+
+ Return: none
+
+ *******************************************************************************/
+ static void fft15(float * restrict vec)
+ {
+
+ float r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15, r16, r17;
+ float i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15, i16, i17;
+ float tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9,
+ tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16, tmp17, tmp18, tmp19,
+ tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26, tmp27, tmp28, tmp29;
+
+
+ /* Pre-additions real part */
+ r1 = vec[2] + vec[8];
+ r2 = vec[2] - vec[8];
+ r3 = vec[4] + vec[16];
+ r4 = vec[4] - vec[16];
+ r5 = vec[6] + vec[24];
+ r6 = vec[6] - vec[24];
+ r7 = vec[10] + vec[20];
+ r8 = vec[10] - vec[20];
+ r9 = vec[12] + vec[18];
+ r10 = vec[12] - vec[18];
+ r11 = vec[14] + vec[26];
+ r12 = vec[14] - vec[26];
+ r13 = vec[22] + vec[28];
+ r14 = vec[22] - vec[28];
+
+ tmp2 = r1 + r3;
+ tmp4 = r1 - r3;
+ tmp6 = r2 + r14;
+ tmp8 = r2 - r14;
+ tmp10 = r4 + r12;
+ tmp12 = r4 - r12;
+ tmp14 = r5 + r9;
+ tmp16 = r5 - r9;
+ tmp18 = r11 + r13;
+ tmp20 = r11 - r13;
+
+ /* Pre-additions imaginary part */
+ i1 = vec[3] + vec[9];
+ i2 = vec[3] - vec[9];
+ i3 = vec[5] + vec[17];
+ i4 = vec[5] - vec[17];
+ i5 = vec[7] + vec[25];
+ i6 = vec[7] - vec[25];
+ i7 = vec[11] + vec[21];
+ i8 = vec[11] - vec[21];
+ i9 = vec[13] + vec[19];
+ i10 = vec[13] - vec[19];
+ i11 = vec[15] + vec[27];
+ i12 = vec[15] - vec[27];
+ i13 = vec[23] + vec[29];
+ i14 = vec[23] - vec[29];
+
+ tmp3 = i1 + i3;
+ tmp5 = i1 - i3;
+ tmp7 = i2 + i14;
+ tmp9 = i2 - i14;
+ tmp11 = i4 + i12;
+ tmp13 = i4 - i12;
+ tmp15 = i5 + i9;
+ tmp17 = i5 - i9;
+ tmp19 = i11 + i13;
+ tmp21 = i11 - i13;
+
+
+ /* Pre-additions and core multiplications */
+ tmp28= tmp4 + tmp20;
+ tmp29= tmp5 + tmp21;
+ r4 = tmp2 + tmp18;
+ i4 = tmp3 + tmp19;
+ r3 = (r4 + tmp14) * -1.25f;
+ i3 = (i4 + tmp15) * -1.25f;
+ r2 = (tmp29 - i8) * -8.660254037844387e-1f;
+ i2 = (tmp28 - r8) * 8.660254037844387e-1f;
+ r1 = r4 + r7;
+ i1 = i4 + i7;
+ r0 = r1 + vec[0] + tmp14;
+ i0 = i1 + vec[1] + tmp15;
+ r7 = tmp4 - tmp20;
+ i7 = tmp5 - tmp21;
+ r8 = (tmp3 - tmp19) * -4.841229182759272e-1f;
+ i8 = (tmp2 - tmp18) * 4.841229182759272e-1f;
+ tmp0 = tmp6 + r10;
+ tmp1 = tmp7 + i10;
+ tmp2 = r6 - tmp10;
+ tmp3 = i6 - tmp11;
+ r10 = tmp7 * -2.308262652881440f;
+ i10 = tmp6 * 2.308262652881440f;
+ r11 = tmp8 * 1.332676064001459f;
+ i11 = tmp9 * 1.332676064001459f;
+ r6 = (r7 - tmp16) * 5.590169943749475e-1f;
+ i6 = (i7 - tmp17) * 5.590169943749475e-1f;
+ r12 = (tmp1 + tmp3) * 5.877852522924733e-1f;
+ i12 = (tmp0 + tmp2) * -5.877852522924733e-1f;
+ r13 = (tmp7 - tmp11) * -8.816778784387098e-1f;
+ i13 = (tmp6 - tmp10) * 8.816778784387098e-1f;
+ r14 = (tmp8 + tmp12) * 5.090369604551274e-1f;
+ i14 = (tmp9 + tmp13) * 5.090369604551274e-1f;
+ r16 = tmp11 * 5.449068960040204e-1f;
+ i16 = tmp10 * -5.449068960040204e-1f;
+ r17 = tmp12 * 3.146021430912046e-1f;
+ i17 = tmp13 * 3.146021430912046e-1f;
+
+ r4 *= 1.875f;
+ i4 *= 1.875f;
+ r1 *= -1.5f;
+ i1 *= -1.5f;
+ r7 *= -8.385254915624212e-1f;
+ i7 *= -8.385254915624212e-1f;
+ r5 = tmp29 * 1.082531754730548f;
+ i5 = tmp28 * -1.082531754730548f;
+ r9 = tmp1 * 1.538841768587627f;
+ i9 = tmp0 * -1.538841768587627f;
+ r15 = tmp3 * 3.632712640026803e-1f;
+ i15 = tmp2 * -3.632712640026803e-1f;
+
+
+ /* Post-additions real part */
+ tmp2 = r0 + r1;
+ tmp4 = r3 + r6;
+ tmp6 = r3 - r6;
+ tmp8 = r4 + r5;
+ tmp10 = r4 - r5;
+ tmp12 = r7 + r8;
+ tmp14 = r7 - r8;
+ tmp16 = r13 + r16;
+ tmp18 = r14 + r17;
+ tmp20 = r10 - r13;
+ tmp22 = r11 - r14;
+ tmp24 = r12 + r15;
+ tmp26 = r12 - r9;
+
+ r1 = tmp2 + r2;
+ r2 = tmp2 - r2;
+ r3 = tmp4 + tmp26;
+ r4 = tmp4 - tmp26;
+ r5 = tmp6 + tmp24;
+ r6 = tmp6 - tmp24;
+ r7 = tmp16 + tmp18;
+ r8 = tmp16 - tmp18;
+ r9 = tmp20 - tmp22;
+ r10 = tmp20 + tmp22;
+ r11 = r1 + tmp8;
+ r12 = r2 + tmp10;
+ r13 = r11 - tmp12;
+ r14 = r12 - tmp14;
+ r15 = r12 + tmp14;
+ r16 = r11 + tmp12;
+
+ /* Post-additions imaginary part */
+ tmp3 = i0 + i1;
+ tmp5 = i3 + i6;
+ tmp7 = i3 - i6;
+ tmp9 = i4 + i5;
+ tmp11 = i4 - i5;
+ tmp13 = i7 + i8;
+ tmp15 = i7 - i8;
+ tmp17 = i13 + i16;
+ tmp19 = i14 + i17;
+ tmp21 = i10 - i13;
+ tmp23 = i11 - i14;
+ tmp25 = i12 + i15;
+ tmp27 = i12 - i9;
+
+ i1 = tmp3 + i2;
+ i2 = tmp3 - i2;
+ i3 = tmp5 + tmp27;
+ i4 = tmp5 - tmp27;
+ i5 = tmp7 + tmp25;
+ i6 = tmp7 - tmp25;
+ i7 = tmp17 + tmp19;
+ i8 = tmp17 - tmp19;
+ i9 = tmp21 - tmp23;
+ i10 = tmp21 + tmp23;
+ i11 = i1 + tmp9;
+ i12 = i2 + tmp11;
+ i13 = i11 - tmp13;
+ i14 = i12 - tmp15;
+ i15 = i12 + tmp15;
+ i16 = i11 + tmp13;
+
+ *vec++ = r0;
+ *vec++ = i0;
+ *vec++ = r13 + r5 + r7;
+ *vec++ = i13 + i5 + i7;
+ *vec++ = r15 + r3 - r9;
+ *vec++ = i15 + i3 - i9;
+ *vec++ = r0 + r4;
+ *vec++ = i0 + i4;
+ *vec++ = r13 + r6 - r7;
+ *vec++ = i13 + i6 - i7;
+ *vec++ = r2;
+ *vec++ = i2;
+ *vec++ = r0 + r5;
+ *vec++ = i0 + i5;
+ *vec++ = r16 + r3 - r10;
+ *vec++ = i16 + i3 - i10;
+ *vec++ = r15 + r4 + r9;
+ *vec++ = i15 + i4 + i9;
+ *vec++ = r0 + r6;
+ *vec++ = i0 + i6;
+ *vec++ = r1;
+ *vec++ = i1;
+ *vec++ = r14 + r5 + r8;
+ *vec++ = i14 + i5 + i8;
+ *vec++ = r0 + r3;
+ *vec++ = i0 + i3;
+ *vec++ = r16 + r4 + r10;
+ *vec++ = i16 + i4 + i10;
+ *vec++ = r14 + r6 - r8;
+ *vec++ = i14 + i6 - i8;
+
+
+ }
+
+ /*******************************************************************************
+ Functionname: fft5s
+ *******************************************************************************
+
+ Description: 5-point FFT.
+
+ Arguments: x - pointer to input data (interleaved real / imaginary parts)
+ stride - stride for input data
+
+ Return: none
+
+ *******************************************************************************/
+ static const float C51 = 0.9510565162951535f;
+static const float C52 = -1.5388417685876270f;
+static const float C53 = -0.3632712640026803f;
+static const float C54 = 0.5590169943749475f;
+static const float C55 = -1.25f;
+
+ static void fft5s(float *x, int stride)
+ {
+ float r1,r2,r3,r4;
+ float s1,s2,s3,s4;
+ float t;
+ /* real part */
+ r1 = x[1*stride] + x[4*stride];
+ r4 = x[1*stride] - x[4*stride];
+ r3 = x[2*stride] + x[3*stride];
+ r2 = x[2*stride] - x[3*stride];
+ t = (r1-r3) * C54;
+ r1 = r1 + r3;
+ x[0] = x[0] + r1;
+ r1 = x[0] + (r1 * C55);
+ r3 = r1 - t;
+ r1 = r1 + t;
+ t = (r4 + r2) * C51;
+ r4 = t + (r4 * C52);
+ r2 = t + (r2 * C53);
+
+ /* imaginary part */
+ s1 = x[1*stride+1] + x[4*stride+1];
+ s4 = x[1*stride+1] - x[4*stride+1];
+ s3 = x[2*stride+1] + x[3*stride+1];
+ s2 = x[2*stride+1] - x[3*stride+1];
+ t = (s1 - s3) * C54;
+ s1 = s1 + s3;
+ x[1] = x[1] + s1;
+ s1 = x[1] + (s1 * C55);
+ s3 = s1 - t;
+ s1 = s1 + t;
+ t = (s4 + s2) * C51;
+ s4 = t + (s4 * C52);
+ s2 = t + (s2 * C53);
+
+ /* combination */
+ x[1*stride] = r1 + s2;
+ x[4*stride] = r1 - s2;
+ x[2*stride] = r3 - s4;
+ x[3*stride] = r3 + s4;
+
+ x[1*stride+1] = s1 - r2;
+ x[4*stride+1] = s1 + r2;
+ x[2*stride+1] = s3 + r4;
+ x[3*stride+1] = s3 - r4;
+ }
+
+
+ /**
+ * \brief Function performs a complex 10-point FFT
+ * The FFT is performed inplace. The result of the FFT
+ * is scaled by SCALEFACTOR10 bits.
+ *
+ * WOPS FLC version: 1093 cycles
+ * WOPS with 32x16 bit multiplications: 196 cycles
+ *
+ * \param [i/o] re real input / output
+ * \param [i/o] im imag input / output
+ * \param [i ] s stride real and imag input / output
+ *
+ * \return void
+ */
+ static void fft10(float * restrict vec)
+ {
+ float t;
+ float r1,r2,r3,r4;
+ float s1,s2,s3,s4;
+ float y00,y01,y02,y03,y04,y05,y06,y07,y08,y09;
+ float y10,y11,y12,y13,y14,y15,y16,y17,y18,y19;
+
+ /* 2 fft5 stages */
+
+ /* real part */
+ r1 = vec[12] + vec[8];
+ r4 = vec[12] - vec[8];
+ r3 = vec[4] + vec[16];
+ r2 = vec[4] - vec[16];
+ t = (r1 - r3) * C54;
+ r1 = r1 + r3;
+ y00 = vec[0] + r1;
+ r1 = y00 + (r1 * C55);
+ r3 = r1 - t;
+ r1 = r1 + t;
+ t = (r4 + r2) * C51;
+ r4 = t + (r4 * C52);
+ r2 = t + (r2 * C53);
+
+ /* imaginary part */
+ s1 = vec[13] + vec[9];
+ s4 = vec[13] - vec[9];
+ s3 = vec[5] + vec[17];
+ s2 = vec[5] - vec[17];
+ t = (s1 - s3) * C54;
+ s1 = s1 + s3;
+ y01 = vec[1] + s1;
+ s1 = y01 + (s1 * C55);
+ s3 = s1 - t;
+ s1 = s1 + t;
+ t = (s4 + s2) * C51;
+ s4 = t + (s4 * C52);
+ s2 = t + (s2 * C53);
+
+ /* combination */
+ y04 = r1 + s2;
+ y16 = r1 - s2;
+ y08 = r3 - s4;
+ y12 = r3 + s4;
+ y05 = s1 - r2;
+ y17 = s1 + r2;
+ y09 = s3 + r4;
+ y13 = s3 - r4;
+
+ /* real part */
+ r1 = vec[2] + vec[18];
+ r4 = vec[2] - vec[18];
+ r3 = vec[14] + vec[6];
+ r2 = vec[14] - vec[6];
+ t = (r1 - r3) * C54;
+ r1 = r1 + r3;
+ y02 = vec[10] + r1;
+ r1 = y02 + (r1 * C55);
+ r3 = r1 - t;
+ r1 = r1 + t;
+ t = (r4 + r2) * C51;
+ r4 = t + (r4 * C52);
+ r2 = t + (r2 * C53);
+
+ /* imaginary part */
+ s1 = vec[3] + vec[19];
+ s4 = vec[3] - vec[19];
+ s3 = vec[15] + vec[7];
+ s2 = vec[15] - vec[7];
+ t = (s1 - s3) * C54;
+ s1 = s1 + s3;
+ y03 = vec[11] + s1;
+ s1 = y03 + (s1 * C55);
+ s3 = s1 - t;
+ s1 = s1 + t;
+ t = (s4 + s2) * C51;
+ s4 = t + (s4 * C52);
+ s2 = t + (s2 * C53);
+
+ /* combination */
+ y06 = r1 + s2;
+ y18 = r1 - s2;
+ y10 = r3 - s4;
+ y14 = r3 + s4;
+ y07 = s1 - r2;
+ y19 = s1 + r2;
+ y11 = s3 + r4;
+ y15 = s3 - r4;
+
+ /* 5 fft2 stages */
+ vec[0] = y00 + y02;
+ vec[1] = y01 + y03;
+ vec[2] = y12 - y14;
+ vec[3] = y13 - y15;
+ vec[4] = y04 + y06;
+ vec[5] = y05 + y07;
+ vec[6] = y16 - y18;
+ vec[7] = y17 - y19;
+ vec[8] = y08 + y10;
+ vec[9] = y09 + y11;
+ vec[10] = y00 - y02;
+ vec[11] = y01 - y03;
+ vec[12] = y12 + y14;
+ vec[13] = y13 + y15;
+ vec[14] = y04 - y06;
+ vec[15] = y05 - y07;
+ vec[16] = y16 + y18;
+ vec[17] = y17 + y19;
+ vec[18] = y08 - y10;
+ vec[19] = y09 - y11;
+ }
+
+ /**
+ * \brief Function performs a complex 20-point FFT
+ * The FFT is performed inplace. The result of the FFT
+ * is scaled by SCALEFACTOR20 bits.
+ *
+ * WOPS FLC version: 1509 cycles
+ * WOPS with 32x16 bit multiplications: 432 cycles
+ *
+ * \param [i/o] re real input / output
+ * \param [i/o] im imag input / output
+ * \param [i ] s stride real and imag input / output
+ *
+ * \return void
+ */
+ static void fft20(float *signal)
+ {
+ const int s = 2;
+ float *re = signal, *im = signal+1;
+ float r1,r2,r3,r4;
+ float s1,s2,s3,s4;
+ float x0,x1,x2,x3,x4;
+ float t,t0,t1,t2,t3,t4,t5,t6,t7;
+ float y00,y01,y02,y03,y04,y05,y06,y07,y08,y09;
+ float y10,y11,y12,y13,y14,y15,y16,y17,y18,y19;
+ float y20,y21,y22,y23,y24,y25,y26,y27,y28,y29;
+ float y30,y31,y32,y33,y34,y35,y36,y37,y38,y39;
+
+ /* */
+
+ /* 1. FFT5 stage */
+
+ /* real part */
+ x0 = re[s* 0];
+ x1 = re[s*16];
+ x2 = re[s*12];
+ x3 = re[s* 8];
+ x4 = re[s* 4];
+ r1 = x1 + x4;
+ r4 = x1 - x4;
+ r3 = x2 + x3;
+ r2 = x2 - x3;
+ t = (r1 - r3) * C54;
+ r1 = r1 + r3;
+ y00 = x0 + r1;
+ r1 = y00 + (r1 * C55);
+ r3 = r1 - t;
+ r1 = r1 + t;
+ t = (r4 + r2) * C51;
+ r4 = t + (r4 * C52);
+ r2 = t + (r2 * C53);
+
+ /* imaginary part */
+ x0 = im[s* 0];
+ x1 = im[s*16];
+ x2 = im[s*12];
+ x3 = im[s* 8];
+ x4 = im[s* 4];
+ s1 = x1 + x4;
+ s4 = x1 - x4;
+ s3 = x2 + x3;
+ s2 = x2 - x3;
+ t = (s1 - s3) * C54;
+ s1 = (s1 + s3);
+ y01 = (x0 + s1);
+ s1 = y01 + (s1 * C55);
+ s3 = (s1 - t);
+ s1 = (s1 + t);
+ t = (s4 + s2) * C51;
+ s4 = t + (s4 * C52);
+ s2 = t + (s2 * C53);
+
+ /* combination */
+ y08 = (r1 + s2);
+ y32 = (r1 - s2);
+ y16 = (r3 - s4);
+ y24 = (r3 + s4);
+
+ y09 = (s1 - r2);
+ y33 = (s1 + r2);
+ y17 = (s3 + r4);
+ y25 = (s3 - r4);
+
+ /* 2. FFT5 stage */
+
+ /* real part */
+ x0 = re[s* 5];
+ x1 = re[s* 1];
+ x2 = re[s*17];
+ x3 = re[s*13];
+ x4 = re[s* 9];
+ r1 = (x1 + x4);
+ r4 = (x1 - x4);
+ r3 = (x2 + x3);
+ r2 = (x2 - x3);
+ t = (r1 - r3) * C54;
+ r1 = (r1 + r3);
+ y02 = (x0 + r1);
+ r1 = y02 + (r1 * C55);
+ r3 = (r1 - t);
+ r1 = (r1 + t);
+ t = (r4 + r2) * C51;
+ r4 = t + (r4 * C52);
+ r2 = t + (r2 * C53);
+
+ /* imaginary part */
+ x0 = im[s* 5];
+ x1 = im[s* 1];
+ x2 = im[s*17];
+ x3 = im[s*13];
+ x4 = im[s* 9];
+ s1 = (x1 + x4);
+ s4 = (x1 - x4);
+ s3 = (x2 + x3);
+ s2 = (x2 - x3);
+ t = (s1 - s3) * C54;
+ s1 = (s1 + s3);
+ y03 = (x0 + s1);
+ s1 = y03 + (s1 * C55);
+ s3 = (s1 - t);
+ s1 = (s1 + t);
+ t = (s4 + s2) * C51;
+ s4 = t + (s4 * C52);
+ s2 = t + (s2 * C53);
+
+ /* combination */
+ y10 = (r1 + s2);
+ y34 = (r1 - s2);
+ y18 = (r3 - s4);
+ y26 = (r3 + s4);
+
+ y11 = (s1 - r2);
+ y35 = (s1 + r2);
+ y19 = (s3 + r4);
+ y27 = (s3 - r4);
+
+ /* 3. FFT5 stage */
+
+ /* real part */
+ x0 = re[s*10];
+ x1 = re[s* 6];
+ x2 = re[s* 2];
+ x3 = re[s*18];
+ x4 = re[s*14];
+ r1 = (x1 + x4);
+ r4 = (x1 - x4);
+ r3 = (x2 + x3);
+ r2 = (x2 - x3);
+ t = (r1 - r3) * C54;
+ r1 = (r1 + r3);
+ y04 = (x0 + r1);
+ r1 = y04 + (r1 * C55);
+ r3 = (r1 - t);
+ r1 = (r1 + t);
+ t = (r4 + r2) * C51;
+ r4 = t + (r4 * C52);
+ r2 = t + (r2 * C53);
+
+ /* imaginary part */
+ x0 = im[s*10];
+ x1 = im[s* 6];
+ x2 = im[s* 2];
+ x3 = im[s*18];
+ x4 = im[s*14];
+ s1 = (x1 + x4);
+ s4 = (x1 - x4);
+ s3 = (x2 + x3);
+ s2 = (x2 - x3);
+ t = (s1 - s3) * C54;
+ s1 = (s1 + s3);
+ y05 = (x0 + s1);
+ s1 = y05 + (s1 * C55);
+ s3 = (s1 - t);
+ s1 = (s1 + t);
+ t = (s4 + s2) * C51;
+ s4 = t + (s4 * C52);
+ s2 = t + (s2 * C53);
+
+ /* combination */
+ y12 = (r1 + s2);
+ y36 = (r1 - s2);
+ y20 = (r3 - s4);
+ y28 = (r3 + s4);
+
+ y13 = (s1 - r2);
+ y37 = (s1 + r2);
+ y21 = (s3 + r4);
+ y29 = (s3 - r4);
+
+ /* 4. FFT5 stage */
+
+ /* real part */
+ x0 = re[s*15];
+ x1 = re[s*11];
+ x2 = re[s* 7];
+ x3 = re[s* 3];
+ x4 = re[s*19];
+ r1 = (x1 + x4);
+ r4 = (x1 - x4);
+ r3 = (x2 + x3);
+ r2 = (x2 - x3);
+ t = (r1 - r3) * C54;
+ r1 = (r1 + r3);
+ y06 = (x0 + r1);
+ r1 = y06 + (r1 * C55);
+ r3 = (r1 - t);
+ r1 = (r1 + t);
+ t = (r4 + r2) * C51;
+ r4 = t + (r4 * C52);
+ r2 = t + (r2 * C53);
+
+ /* imaginary part */
+ x0 = im[s*15];
+ x1 = im[s*11];
+ x2 = im[s* 7];
+ x3 = im[s* 3];
+ x4 = im[s*19];
+ s1 = (x1 + x4);
+ s4 = (x1 - x4);
+ s3 = (x2 + x3);
+ s2 = (x2 - x3);
+ t = (s1 - s3) * C54;
+ s1 = (s1 + s3);
+ y07 = (x0 + s1);
+ s1 = y07 + (s1 * C55);
+ s3 = (s1 - t);
+ s1 = (s1 + t);
+ t = (s4 + s2) * C51;
+ s4 = t + (s4 * C52);
+ s2 = t + (s2 * C53);
+
+ /* combination */
+ y14 = (r1 + s2);
+ y38 = (r1 - s2);
+ y22 = (r3 - s4);
+ y30 = (r3 + s4);
+
+ y15 = (s1 - r2);
+ y39 = (s1 + r2);
+ y23 = (s3 + r4);
+ y31 = (s3 - r4);
+
+
+ /* 1. FFT4 stage */
+
+ /* Pre-additions */
+ t0 = (y00 + y04);
+ t2 = (y00 - y04);
+ t1 = (y01 + y05);
+ t3 = (y01 - y05);
+ t4 = (y02 + y06);
+ t7 = (y02 - y06);
+ t5 = (y07 + y03);
+ t6 = (y07 - y03);
+
+ /* Post-additions */
+ re[s* 0] = (t0 + t4);
+ im[s* 0] = (t1 + t5);
+ re[s* 5] = (t2 - t6);
+ im[s* 5] = (t3 - t7);
+ re[s*10] = (t0 - t4);
+ im[s*10] = (t1 - t5);
+ re[s*15] = (t2 + t6);
+ im[s*15] = (t3 + t7);
+
+ /* 2. FFT4 stage */
+
+ /* Pre-additions */
+ t0 = (y08 + y12);
+ t2 = (y08 - y12);
+ t1 = (y09 + y13);
+ t3 = (y09 - y13);
+ t4 = (y10 + y14);
+ t7 = (y10 - y14);
+ t5 = (y15 + y11);
+ t6 = (y15 - y11);
+
+ /* Post-additions */
+ re[s* 4] = (t0 + t4);
+ im[s* 4] = (t1 + t5);
+ re[s* 9] = (t2 - t6);
+ im[s* 9] = (t3 - t7);
+ re[s*14] = (t0 - t4);
+ im[s*14] = (t1 - t5);
+ re[s*19] = (t2 + t6);
+ im[s*19] = (t3 + t7);
+
+
+ /* 3. FFT4 stage */
+
+ /* Pre-additions */
+ t0 = (y16 + y20);
+ t2 = (y16 - y20);
+ t1 = (y17 + y21);
+ t3 = (y17 - y21);
+ t4 = (y18 + y22);
+ t7 = (y18 - y22);
+ t5 = (y23 + y19);
+ t6 = (y23 - y19);
+
+ /* Post-additions */
+ re[s* 8] = (t0 + t4);
+ im[s* 8] = (t1 + t5);
+ re[s*13] = (t2 - t6);
+ im[s*13] = (t3 - t7);
+ re[s*18] = (t0 - t4);
+ im[s*18] = (t1 - t5);
+ re[s* 3] = (t2 + t6);
+ im[s* 3] = (t3 + t7);
+
+ /* 4. FFT4 stage */
+
+ /* Pre-additions */
+ t0 = (y24 + y28);
+ t2 = (y24 - y28);
+ t1 = (y25 + y29);
+ t3 = (y25 - y29);
+ t4 = (y26 + y30);
+ t7 = (y26 - y30);
+ t5 = (y31 + y27);
+ t6 = (y31 - y27);
+
+ /* Post-additions */
+ re[s*12] = (t0 + t4);
+ im[s*12] = (t1 + t5);
+ re[s*17] = (t2 - t6);
+ im[s*17] = (t3 - t7);
+ re[s* 2] = (t0 - t4);
+ im[s* 2] = (t1 - t5);
+ re[s* 7] = (t2 + t6);
+ im[s* 7] = (t3 + t7);
+
+ /* 5. FFT4 stage */
+
+ /* Pre-additions */
+ t0 = (y32 + y36);
+ t2 = (y32 - y36);
+ t1 = (y33 + y37);
+ t3 = (y33 - y37);
+ t4 = (y34 + y38);
+ t7 = (y34 - y38);
+ t5 = (y39 + y35);
+ t6 = (y39 - y35);
+
+ /* Post-additions */
+ re[s*16] = (t0 + t4);
+ im[s*16] = (t1 + t5);
+ re[s* 1] = (t2 - t6);
+ im[s* 1] = (t3 - t7);
+ re[s* 6] = (t0 - t4);
+ im[s* 6] = (t1 - t5);
+ re[s*11] = (t2 + t6);
+ im[s*11] = (t3 + t7);
+
+ /* */
+ /* */
+ }
+
+ /*******************************************************************************
+ Functionname: fft30
+ *******************************************************************************
+
+ Description: 30-point FFT.
+
+ Arguments: in - pointer to data (interleaved real / imaginary parts)
+
+ Return: none
+
+ *******************************************************************************/
+
+ static void fft30(float * restrict in)
+ {
+ int i;
+ float temp[60];
+ float * temp_l = temp;
+ float * temp_lu = temp + 2*8;
+ float * temp_h = temp + 2*15;
+ float * temp_hu = temp + 2*15 + 2*8;
+ float *in_l = in + 2*0;
+ float *in_h = in + 2*15;
+ for(i=0; i<7; i++)
+ {
+ *temp_l++ = *in_l++;
+ *temp_l++ = *in_l++;
+ *temp_h++ = *in_h++;
+ *temp_h++ = *in_h++;
+ *temp_l++ = *in_h++;
+ *temp_l++ = *in_h++;
+ *temp_h++ = *in_l++;
+ *temp_h++ = *in_l++;
+ }
+ *temp_l++ = *in_l++;
+ *temp_l++ = *in_l++;
+ *temp_h++ = *in_h++;
+ *temp_h++ = *in_h++;
+ temp_l = temp;
+ temp_h = temp + 30;
+ fft15(temp_l);
+ fft15(temp_h);
+
+ in_l = in + 2*0;
+ in_h = in + 2*15;
+ for(i=0; i<7; i++)
+ {
+ *in_l++ = *temp_l + *temp_h;
+ *in_h++ = *temp_l++ - *temp_h++;
+ *in_l++ = *temp_l + *temp_h;
+ *in_h++ = *temp_l++ - *temp_h++;
+
+ *in_h++ = *temp_lu + *temp_hu;
+ *in_l++ = *temp_lu++ - *temp_hu++;
+ *in_h++ = *temp_lu + *temp_hu;
+ *in_l++ = *temp_lu++ - *temp_hu++;
+ }
+ *in_l++ = *temp_l + *temp_h;
+ *in_h++ = *temp_l++ - *temp_h++;
+ *in_l++ = *temp_l + *temp_h;
+ *in_h++ = *temp_l++ - *temp_h++;
+ }
+
+ /*-------------------------------------------------------------------*
+ * fft_cldfb()
+ *
+ * Interface functions FFT subroutines
+ *--------------------------------------------------------------------*/
+ void fft_cldfb (
+ float *data, /* i/o: input/output vector */
+ int size /* size of fft operation */
+ )
+ {
+
+ switch(size)
+ {
+ case 5:
+ fft5s(data,2);
+ break;
+ case 8:
+ fft8(data);
+ break;
+ case 10:
+ fft10(data);
+ break;
+ case 16:
+ fft16(data);
+ break;
+ case 20:
+ fft20(data);
+ break;
+ case 30:
+ fft30(data);
+ break;
+
+ default:
+ assert(0);
+ break;
+ }
+ }
diff --git a/lib_com/fft_rel.c b/lib_com/fft_rel.c
new file mode 100644
index 0000000000000000000000000000000000000000..0064a5eabe2f3f5dfc05a7ddcf11b92a7b29e64e
--- /dev/null
+++ b/lib_com/fft_rel.c
@@ -0,0 +1,267 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include "options.h"
+#include "wmc_auto.h"
+#include "prot.h"
+#include "rom_com.h"
+
+/*---------------------------------------------------------------------*
+ * Local constants
+ *---------------------------------------------------------------------*/
+
+#define N_MAX_FFT 1024
+#define N_MAX_DIV2 (N_MAX_FFT>>1)
+#define N_MAX_DIV4 (N_MAX_DIV2>>1)
+
+/*---------------------------------------------------------------------*
+ * fft_rel()
+ *
+ * Computes the split-radix FFT in place for the real-valued
+ * signal x of length n. The algorithm has been ported from
+ * the Fortran code of [1].
+ *
+ * The function needs sine and cosine tables t_sin and t_cos,
+ * and the constant N_MAX_FFT. The table entries are defined as
+ * sin(2*pi*i) and cos(2*pi*i) for i = 0, 1, ..., N_MAX_FFT-1. The
+ * implementation assumes that any entry will not be needed
+ * outside the tables. Therefore, N_MAX_FFT and n must be properly
+ * set. The function has been tested with the values n = 16,
+ * 32, 64, 128, 256, and N_MAX_FFT = 1280.
+ *
+ * References
+ * [1] H.V. Sorensen, D.L. Jones, M.T. Heideman, C.S. Burrus,
+ * "Real-valued fast Fourier transform algorithm," IEEE
+ * Trans. on Signal Processing, Vol.35, No.6, pp 849-863,
+ * 1987.
+ *
+ * OUTPUT
+ * x[0:n-1] Transform coeffients in the order re[0], re[1],
+ * ..., re[n/2], im[n/2-1], ..., im[1].
+ *---------------------------------------------------------------------*/
+
+void fft_rel(
+ float x[], /* i/o: input/output vector */
+ const short n, /* i : vector length */
+ const short m /* i : log2 of vector length */
+)
+{
+ short i, j, k, n1, n2, n4;
+ short step;
+ float xt, t1, t2;
+ float *x0, *x1, *x2;
+ float *xi2, *xi3, *xi4, *xi1;
+ const float *s, *c;
+ const short *idx;
+
+ /* !!!! NMAX = 256 is hardcoded here (similar optimizations should be done for NMAX > 256) !!! */
+
+ float *x2even, *x2odd;
+ float temp[512];
+
+ if ( n == 128 || n == 256 || n == 512 )
+ {
+ idx = fft256_read_indexes;
+
+ /* Combined Digit reverse counter & Length two butterflies */
+ if (n == 128)
+ {
+ x2 = temp;
+ for (i = 0; i < 64; i++)
+ {
+ j = *idx++;
+ k = *idx++;
+
+ *x2++ = x[j>>1] + x[k>>1];
+ *x2++ = x[j>>1] - x[k>>1];
+ }
+ }
+ else if (n == 256)
+ {
+ x2 = temp;
+ for (i = 0; i < 128; i++)
+ {
+ j = *idx++;
+ k = *idx++;
+
+ *x2++ = x[j] + x[k];
+ *x2++ = x[j] - x[k];
+ }
+ }
+ else if (n == 512)
+ {
+ x2even = temp;
+ x2odd = temp + 256;
+
+ for (i = 0; i < 128; i++)
+ {
+ j = 2 * *idx++;
+ k = 2 * *idx++;
+
+ *x2even++ = x[j] + x[k];
+ *x2even++ = x[j] - x[k];
+ *x2odd++ = x[++j] + x[++k];
+ *x2odd++ = x[j] - x[k];
+ }
+ }
+
+ /*-----------------------------------------------------------------*
+ * 1st Stage Loop has been Unrolled because n4 is '1' and that
+ * allows the elimination of the 'for_ (j = 1; j < n4; j++)' loop
+ * and the associated pointers initialization.
+ * Also, it allows to Put the Data from 'temp' back into 'x' due
+ * to the previous Combined Digit Reverse and Length two butterflies
+ *-----------------------------------------------------------------*/
+
+ /*for_ (k = 2; k < 3; k++)*/
+ {
+ x0 = temp;
+ x1 = x0 + 2;
+ x2 = x;
+
+ for (i = 0; i < n; i += 4)
+ {
+ *x2++ = *x0++ + *x1; /* x[i] = xt + x[i+n2]; */
+ *x2++ = *x0;
+ *x2++ = *--x0 - *x1++; /* x[i+n2] = xt - x[i+n2]; */
+ *x2++ = -*x1; /* x[i+n2+n4] = -x[i+n2+n4]; */
+
+ x0 += 4;
+ x1 += 3; /* x1 has already advanced */
+ }
+ }
+ }
+ else
+ {
+ /*-----------------------------------------------------------------*
+ * Digit reverse counter
+ *-----------------------------------------------------------------*/
+
+ j = 0;
+ x0 = &x[0];
+ for (i = 0; i < n-1; i++)
+ {
+ if (i < j)
+ {
+ xt = x[j];
+ x[j] = *x0;
+ *x0 = xt;
+ }
+ x0++;
+ k = n/2;
+ while (k <= j)
+ {
+ j -= k;
+ k = k>>1;
+ }
+ j += k;
+ }
+
+ /*-----------------------------------------------------------------*
+ * Length two butterflies
+ *-----------------------------------------------------------------*/
+
+ x0 = &x[0];
+ x1 = &x[1];
+ for (i = 0; i < n/2; i++)
+ {
+ *x1 = *x0 - *x1;
+ *x0 = *x0*2 - *x1;
+
+ x0++;
+ x0++;
+ x1++;
+ x1++;
+ }
+
+ /*-----------------------------------------------------------------*
+ * 1st Stage Loop has been Unrolled because n4 is '1' and that
+ * allows the elimination of the 'for_ (j = 1; j < n4; j++)' loop
+ * and the associated pointers initialization.
+ *-----------------------------------------------------------------*/
+
+ /* for_ (k = 2; k < 3; k++) */
+ {
+ x0 = x;
+ x1 = x0 + 2;
+
+ for (i = 0; i < n; i += 4)
+ {
+ *x1 = *x0 - *x1; /* x[i+n2] = xt - x[i+n2]; */
+ *x0 = *x0*2 - *x1++; /* x[i] = xt + x[i+n2]; */
+ *x1 = -*x1; /* x[i+n2+n4] = -x[i+n2+n4]; */
+
+ x0 += 4;
+ x1 += 3; /* x1 has already advanced */
+ }
+ }
+ }
+
+ /*-----------------------------------------------------------------*
+ * Other butterflies
+ *
+ * The implementation described in [1] has been changed by using
+ * table lookup for evaluating sine and cosine functions. The
+ * variable ind and its increment step are needed to access table
+ * entries. Note that this implementation assumes n4 to be so
+ * small that ind will never exceed the table. Thus the input
+ * argument n and the constant N_MAX_FFT must be set properly.
+ *-----------------------------------------------------------------*/
+
+ n4 = 1;
+ n2 = 2;
+ n1 = 4;
+
+ step = N_MAX_DIV4;
+
+ for (k = 3; k <= m; k++)
+ {
+ step >>= 1;
+ n4 <<= 1;
+ n2 <<= 1;
+ n1 <<= 1;
+
+ x0 = x;
+ x1 = x0 + n2;
+ x2 = x1 + n4;
+
+ for (i = 0; i < n; i += n1)
+ {
+ *x1 = *x0 - *x1; /* x[i+n2] = xt - x[i+n2]; */
+ *x0 = *x0*2 - *x1; /* x[i] = xt + x[i+n2]; */
+ *x2 = -*x2; /* x[i+n2+n4] = -x[i+n2+n4]; */
+
+ s = sincos_t_ext;
+ c = s + N_MAX_FFT/4; /* 1024/4 = 256, 256/4=64 */
+ xi1 = x0;
+ xi3 = xi1 + n2;
+ xi2 = xi3;
+ x0 += n1;
+ xi4 = x0;
+
+ for (j = 1; j < n4; j++)
+ {
+ xi3++;
+ xi1++;
+ xi4--;
+ xi2--;
+ c += step;
+ s+= step; /* autoincrement by ar0 */
+
+ t1 = *xi3**c + *xi4**s; /* t1 = *xi3**(pt_c+ind) + *xi4**(pt_s+ind); */
+ t2 = *xi3**s - *xi4**c; /* t2 = *xi3**(pt_s+ind) - *xi4**(pt_c+ind); */
+
+ *xi4 = *xi2 - t2;
+ *xi2 = *xi1 - t1;
+ *xi1 = *xi1*2 - *xi2;
+ *xi3 = -2*t2 - *xi4;
+ }
+
+ x1 += n1;
+ x2 += n1;
+ }
+ }
+
+ return;
+}
diff --git a/lib_com/fill_spectrum.c b/lib_com/fill_spectrum.c
new file mode 100644
index 0000000000000000000000000000000000000000..1229cee0d7fd0fb29cbafe2120be11bfafaaf6aa
--- /dev/null
+++ b/lib_com/fill_spectrum.c
@@ -0,0 +1,237 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include
+#include "wmc_auto.h"
+#include
+#include "options.h"
+#include "cnst.h"
+#include "rom_com.h"
+#include "prot.h"
+
+/*--------------------------------------------------------------------------*
+ * fill_spectrum()
+ *
+ * Apply spectral filling by
+ * - filling zero-bit bands below BWE region
+ * - applying BWE above transition frequency
+ *--------------------------------------------------------------------------*/
+
+void fill_spectrum(
+ float *coeff, /* i/o: normalized MLT spectrum / nf spectrum */
+ short *R, /* i : number of pulses per band */
+ const short is_transient, /* i : transient flag */
+ short norm[], /* i : quantization indices for norms */
+ const float *hq_generic_fenv, /* i : HQ GENERIC envelope */
+ const short hq_generic_offset, /* i : HQ GENERIC offset */
+ const short nf_idx, /* i : noise fill index */
+ const short length, /* i : Length of spectrum (32 or 48 kHz) */
+ const float env_stab, /* i : Envelope stability measure [0..1] */
+ short *no_att_hangover, /* i/o: Frame counter for attenuation hangover */
+ float *energy_lt, /* i/o: Long-term energy measure for transient detection */
+ short *bwe_seed, /* i/o: random seed for generating BWE input */
+ const short hq_generic_exc_clas, /* i : HQ generic hf excitation class */
+ const short core_sfm, /* i : index of the end band for core */
+ short HQ_mode, /* i : HQ mode */
+ float noise_level[], /* i : noise levels for harmonic modes */
+ long core_brate, /* i : target bit-rate */
+ float prev_noise_level[], /* i/o: noise factor in previous frame */
+ short *prev_R, /* i/o: bit allocation info. in previous frame */
+ float *prev_coeff_out, /* i/o: decoded spectrum in previous frame */
+ const short *peak_idx, /* i : HVQ peak indices */
+ const short Npeaks, /* i : Number of HVQ peaks */
+ const short *npulses, /* i : Number of assigned pulses per band */
+ short prev_is_transient, /* i : previous transient flag */
+ float *prev_normq, /* i : previous norms */
+ float *prev_env, /* i : previous noise envelopes */
+ short prev_bfi, /* i : previous bad frame indicator */
+ const short *sfmsize, /* i : Length of bands */
+ const short *sfm_start, /* i : Start of bands */
+ const short *sfm_end, /* i : End of bands */
+ short *prev_L_swb_norm, /* i/o: last normalize length for harmonic mode */
+ short prev_hq_mode, /* i : previous HQ mode */
+ const short num_sfm, /* i : Number of bands */
+ const short num_env_bands /* i : Number of envelope bands */
+)
+{
+ float CodeBook[FREQ_LENGTH];
+ short cb_size = 0;
+ short last_sfm;
+ float CodeBook_mod[FREQ_LENGTH];
+ float norm_adj[NB_SFM];
+ short high_sfm = 23;
+ short flag_32K_env_hangover;
+ short bin_th = 0;
+ short peak_pos[L_HARMONIC_EXC];
+ short bwe_peaks[L_FRAME48k];
+ float normq_v[NB_SFM];
+ float coeff_fine[L_FRAME48k];
+ float coeff_out[L_FRAME48k];
+
+ set_s( peak_pos, 0, L_HARMONIC_EXC );
+ set_s( bwe_peaks, 0, L_FRAME48k );
+ set_f( norm_adj, 1.0f, num_sfm );
+ set_f( coeff_out, 0.0f, L_FRAME48k );
+
+ if ( HQ_mode == HQ_TRANSIENT )
+ {
+ last_sfm = num_sfm-1;
+ }
+ else if (HQ_mode == HQ_GEN_SWB || HQ_mode == HQ_GEN_FB)
+ {
+ last_sfm = max(core_sfm,num_env_bands-1);
+ }
+ else
+ {
+ last_sfm = core_sfm;
+ }
+
+ if ( HQ_mode == HQ_HARMONIC )
+ {
+ high_sfm = (core_brate == HQ_24k40) ? HVQ_THRES_SFM_24k-1 : HVQ_THRES_SFM_32k-1;
+ if( last_sfm < high_sfm )
+ {
+ last_sfm = high_sfm;
+ }
+ }
+ else if ( HQ_mode == HQ_HVQ )
+ {
+ bin_th = sfm_end[last_sfm];
+ }
+
+ /* Transient analysis for envelope stability measure */
+ if( length == L_FRAME32k )
+ {
+ env_stab_transient_detect( is_transient, length, norm, no_att_hangover, energy_lt, HQ_mode, bin_th, coeff );
+ }
+
+ if ( length == L_FRAME16k || ((length == L_FRAME32k && HQ_mode != HQ_HARMONIC && HQ_mode != HQ_HVQ) && *no_att_hangover == 0) )
+ {
+ /* Norm adjustment function */
+ env_adj( npulses, length, last_sfm, norm_adj, env_stab, sfmsize );
+ }
+
+ flag_32K_env_hangover = ( length == L_FRAME32k && ( (env_stab < 0.5f && *no_att_hangover == 0) || HQ_mode == HQ_HVQ ) );
+
+ /*----------------------------------------------------------------*
+ * Build noise-fill codebook
+ *----------------------------------------------------------------*/
+
+ if ( HQ_mode != HQ_HVQ )
+ {
+ cb_size = build_nf_codebook( flag_32K_env_hangover, coeff, sfm_start, sfmsize, sfm_end, last_sfm, R, CodeBook, CodeBook_mod );
+ }
+
+ /*----------------------------------------------------------------*
+ * Prepare fine structure for Harmonic and HVQ
+ *----------------------------------------------------------------*/
+
+ if ( HQ_mode == HQ_HARMONIC )
+ {
+ harm_bwe_fine( R, last_sfm, high_sfm, num_sfm, norm, sfm_start, sfm_end, prev_L_swb_norm, coeff, coeff_out, coeff_fine );
+ }
+ else if ( HQ_mode == HQ_HVQ )
+ {
+ hvq_bwe_fine( last_sfm, num_sfm, sfm_end, peak_idx, Npeaks, peak_pos, prev_L_swb_norm, coeff, bwe_peaks, coeff_fine );
+ }
+
+ /*----------------------------------------------------------------*
+ * Apply noise-fill
+ *----------------------------------------------------------------*/
+
+ if( HQ_mode != HQ_HVQ && cb_size > 0 )
+ {
+ apply_noisefill_HQ( R, length, flag_32K_env_hangover, core_brate, last_sfm, CodeBook, CodeBook_mod, cb_size, sfm_start, sfm_end, sfmsize, coeff );
+ }
+
+ /*----------------------------------------------------------------*
+ * Normal mode BWE
+ *----------------------------------------------------------------*/
+
+ if ( HQ_mode == HQ_NORMAL )
+ {
+ hq_fold_bwe( last_sfm, sfm_end, num_sfm, coeff );
+ }
+
+ /*----------------------------------------------------------------*
+ * Apply noise-fill adjustment
+ *----------------------------------------------------------------*/
+
+ if( (length >= L_FRAME32k || core_brate > HQ_32k || core_brate < HQ_24k40) && HQ_mode != HQ_HVQ )
+ {
+ apply_nf_gain( nf_idx, last_sfm, R, sfm_start, sfm_end, coeff );
+ }
+
+ /*----------------------------------------------------------------*
+ * Prepare fine strucutre for HQ GENERIC
+ *----------------------------------------------------------------*/
+ if ( HQ_mode == HQ_GEN_SWB || HQ_mode == HQ_GEN_FB )
+ {
+ hq_generic_fine( coeff, last_sfm, sfm_start, sfm_end, bwe_seed, coeff_fine );
+ }
+
+ /*----------------------------------------------------------------*
+ * Apply envelope
+ *----------------------------------------------------------------*/
+
+ if ( HQ_mode != HQ_HARMONIC && HQ_mode != HQ_HVQ )
+ {
+ apply_envelope( coeff, norm, norm_adj, num_sfm, last_sfm, HQ_mode, length, sfm_start, sfm_end, normq_v, coeff_out, coeff_fine );
+ }
+
+ /*----------------------------------------------------------------*
+ * Harmonic BWE, HVQ BWE and HQ SWB BWE
+ *----------------------------------------------------------------*/
+
+ if( HQ_mode == HQ_HARMONIC )
+ {
+ harm_bwe( coeff_fine, coeff, num_sfm, sfm_start, sfm_end, last_sfm, high_sfm, R, prev_hq_mode, norm, noise_level, prev_noise_level, bwe_seed, coeff_out );
+ }
+ else if ( HQ_mode == HQ_HVQ )
+ {
+ hvq_bwe( coeff, coeff_fine, sfm_start, sfm_end, sfmsize, last_sfm,
+ prev_hq_mode, bwe_peaks, bin_th, num_sfm, core_brate, R, norm,
+ noise_level, prev_noise_level, bwe_seed, coeff_out );
+ }
+ else if ( HQ_mode == HQ_GEN_SWB || HQ_mode == HQ_GEN_FB )
+ {
+ hq_generic_bwe( HQ_mode, coeff_fine, hq_generic_fenv, coeff_out, hq_generic_offset, prev_L_swb_norm,
+ hq_generic_exc_clas, sfm_end, num_sfm, num_env_bands, R );
+ }
+
+ /*----------------------------------------------------------------*
+ * HQ WB BWE refinements
+ *----------------------------------------------------------------*/
+
+ if( length == L_FRAME16k && core_brate == HQ_32k )
+ {
+ hq_wb_nf_bwe( coeff, is_transient, prev_bfi, normq_v, num_sfm, sfm_start, sfm_end, sfmsize, last_sfm, R,
+ prev_is_transient, prev_normq, prev_env, bwe_seed, prev_coeff_out, prev_R, coeff_out );
+ }
+
+ /*----------------------------------------------------------------*
+ * Update memories
+ *----------------------------------------------------------------*/
+
+ if ( HQ_mode != HQ_HARMONIC && HQ_mode != HQ_HVQ )
+ {
+ prev_noise_level[0] = 0.1f;
+ prev_noise_level[1] = 0.1f;
+ }
+ if ( !(length == L_FRAME16k && core_brate == HQ_32k ) )
+ {
+ set_f( prev_env, 0, SFM_N_WB );
+ set_f( prev_normq, 0, SFM_N_WB );
+ }
+
+ if ( length == L_FRAME32k && core_brate <= HQ_32k )
+ {
+ *prev_R = R[SFM_N_WB-1];
+ mvr2r( coeff_out + L_FRAME16k - L_HQ_WB_BWE, prev_coeff_out, L_HQ_WB_BWE );
+ }
+
+ mvr2r( coeff_out, coeff, L_FRAME48k );
+
+ return;
+}
diff --git a/lib_com/findpulse.c b/lib_com/findpulse.c
new file mode 100644
index 0000000000000000000000000000000000000000..fc04b8b4479c612a28c380e95bd616dd0acf16ad
--- /dev/null
+++ b/lib_com/findpulse.c
@@ -0,0 +1,107 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include
+#include "wmc_auto.h"
+#include "options.h"
+#include "prot.h"
+#include "cnst.h"
+
+
+/*----------------------------------------------------------------------------------*
+ * findpulse()
+ *
+ * Find first pitch pulse in a frame
+ *----------------------------------------------------------------------------------*/
+
+short findpulse( /* o : pulse position */
+ const short L_frame, /* i : length of the frame */
+ const float res[], /* i : residual signal */
+ const short T0, /* i : integer pitch */
+ const short enc_dec, /* i : flag enc/dec, 0 - enc, 1 - dec */
+ short *sign /* i/o: sign of the maximum */
+)
+{
+ const float *ptr;
+ float val, maxval;
+ short i, maxi;
+ float resf[L_FRAME16k]; /* Low pass filtered residual */
+
+ if ( enc_dec == ENC )
+ {
+ /*-----------------------------------------------------------------*
+ * Very simple LP filter
+ *-----------------------------------------------------------------*/
+
+ resf[0] = 0.50f * res[0] + 0.25f * res[1];
+ for (i=1; imaxval)
+ {
+ maxval = val;
+ maxi = i;
+ if(*ptr >= 0)
+ {
+ *sign = 0;
+ }
+ else
+ {
+ *sign = 1;
+ }
+ }
+ ptr--;
+ }
+ }
+ else
+ {
+ /*-----------------------------------------------------------------*
+ * Find "biggest" pulse in the last pitch section according to the sign
+ *-----------------------------------------------------------------*/
+
+ ptr = res;
+ maxval = 0;
+ maxi = 0;
+
+ if( *sign == 0 )
+ {
+ for (i=1; i<=T0; i++)
+ {
+ val = *ptr++;
+ if ( val >= maxval )
+ {
+ maxval = val;
+ maxi = i;
+ }
+ }
+ }
+ else
+ {
+ for (i=1; i<=T0; i++)
+ {
+ val = *ptr++;
+ if (val<=maxval)
+ {
+ maxval = val;
+ maxi = i;
+ }
+ }
+ }
+ }
+
+ return(maxi);
+}
diff --git a/lib_com/fine_gain_bits.c b/lib_com/fine_gain_bits.c
new file mode 100644
index 0000000000000000000000000000000000000000..cc386852e1828a04aed92db7dacb33dfabeae3a0
--- /dev/null
+++ b/lib_com/fine_gain_bits.c
@@ -0,0 +1,101 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include "options.h"
+#include "wmc_auto.h"
+#include "rom_com.h"
+#include "prot.h"
+
+
+/*--------------------------------------------------------------------------
+ * subband_gain_bits()
+ *
+ * HQ core encoder
+ *--------------------------------------------------------------------------*/
+
+void subband_gain_bits(
+ const short *Rk, /* i : bit allocation per band (Q3)*/
+ const short N, /* i : number of bands */
+ short *bits, /* o : gain bits per band */
+ const short *sfmsize /* i : Size of bands */
+)
+{
+ short i,b,tot;
+ short bps;
+
+ tot = 0;
+
+ for ( i = 0; i < N; i++ )
+ {
+ bps = (short)(((int) Rk[i]*(int)fg_inv_tbl_fx[sfmsize[i]>>3])>>18) ;
+ if (((sfmsize[i]*(bps+1)) << 3) - Rk[i] == 0)
+ {
+ /* correct approx. division result, to obtain exact integer division output */
+ bps++;
+ }
+ bps = min(7, bps);
+
+
+
+ b = fine_gain_bits[bps];
+
+ bits[i] = b;
+ tot += b;
+ }
+
+ if ( tot == 0)
+ {
+ /* If no gain bits were assigned, use one bit anyway for potential PVQ overage */
+ bits[0] = 1;
+ }
+
+ return;
+}
+
+/*--------------------------------------------------------------------------*
+ * assign_gain_bits()
+ *
+ * Assign gain adjustment bits and update bit budget
+ *--------------------------------------------------------------------------*/
+
+short assign_gain_bits( /* o : Number of assigned gain bits */
+ const short core, /* i : HQ core */
+ const short BANDS, /* i : Number of bands */
+ const short *band_width, /* i : Sub band bandwidth */
+ short *Rk, /* i/o: Bit allocation/Adjusted bit alloc. (Q3)*/
+ short *gain_bits_array, /* o : Assigned gain bits */
+ short *Rcalc /* o : Bit budget for shape quantizer (Q3)*/
+)
+{
+ short subband_cnt;
+ short gain_bits_tot;
+ short i;
+
+ /* Allocate gain bits for every subband used, based on bit rate and bandwidth */
+ if( core == HQ_CORE )
+ {
+ subband_gain_bits(Rk, BANDS, gain_bits_array, band_width);
+ }
+ else
+ {
+ set_s( gain_bits_array, 0, BANDS );
+ }
+
+ /* Re-adjust bit budget for gain quantization */
+ subband_cnt = 0;
+ gain_bits_tot = 0;
+ *Rcalc = 0.0f;
+ for (i = 0; i < BANDS; i++)
+ {
+ if (Rk[i] > 0)
+ {
+ subband_cnt++;
+ Rk[i] -= gain_bits_array[i] * 8;
+ gain_bits_tot += gain_bits_array[i];
+ *Rcalc += Rk[i];
+ }
+ }
+
+ return gain_bits_tot;
+}
diff --git a/lib_com/frame_ener.c b/lib_com/frame_ener.c
new file mode 100644
index 0000000000000000000000000000000000000000..b16a8f36c9de4ae892ccfbf5b2a4266c2af9e9b6
--- /dev/null
+++ b/lib_com/frame_ener.c
@@ -0,0 +1,97 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include
+#include "wmc_auto.h"
+#include "options.h"
+#include "cnst.h"
+#include "prot.h"
+
+
+/*----------------------------------------------------------------------------------*
+* fer_energy()
+*
+* Estimation of pitch-synchronous (voiced sounds) or half-frame energy
+*----------------------------------------------------------------------------------*/
+
+void fer_energy(
+ const int L_frame, /* i : frame length */
+ const short clas, /* i : frame classification */
+ const float *synth, /* i : synthesized speech at Fs = 12k8 Hz */
+ const float pitch, /* i : pitch period */
+ float *enr, /* o : pitch-synchronous or half_frame energy */
+ const short offset /* i : speech pointer offset (0 or L_frame) */
+)
+{
+ short len;
+ const float *pt_synth;
+
+ if( clas == VOICED_CLAS || clas == ONSET || clas == SIN_ONSET ) /* Voiced or Onset current frame */
+ {
+ len = (short)( pitch + 0.5f ); /* pitch value */
+
+ pt_synth = synth;
+ if( offset != 0 )
+ {
+ pt_synth = synth + L_frame - len;
+ }
+
+ emaximum( pt_synth, len, enr ); /* pitch synchronous E */
+ }
+ else
+ {
+ pt_synth = synth;
+ if( offset != 0 )
+ {
+ pt_synth = synth + L_frame/2;
+ }
+
+ *enr = dotp( pt_synth, pt_synth, L_frame/2 );
+ *enr /= (float)(L_frame/2);
+
+ }
+ return;
+}
+
+
+/*------------------------------------------------------------------------*
+ * frame_energy()
+ *
+ * Compute pitch-synchronous energy at the frame end
+ *------------------------------------------------------------------------*/
+
+float frame_energy(
+ const short L_frame, /* i: length of the frame */
+ const float *pitch, /* i: pitch values for each subframe */
+ const float *speech, /* i: pointer to speech signal for E computation */
+ const float lp_speech, /* i: long-term active speech energy average */
+ float *frame_ener /* o: pitch-synchronous energy at frame end */
+)
+{
+ float enern;
+ const float *pt1;
+ short len;
+ float dotProd;
+
+ len = (short)( 0.5f * (pitch[2] + pitch[3]) + 0.5f );
+ if( len < L_SUBFR )
+ {
+ len *= 2;
+ }
+
+ pt1 = speech + L_frame - len;
+
+ dotProd = dotp( pt1, pt1, len );
+ if ( 0 == dotProd )
+ {
+ *frame_ener = MIN_LOG_VAL_60dB;
+ }
+ else
+ {
+ *frame_ener = 10.0f * (float) log10( dotProd / (float) len );
+ }
+ enern = *frame_ener - lp_speech;
+
+ return enern;
+}
diff --git a/lib_com/g192.c b/lib_com/g192.c
new file mode 100644
index 0000000000000000000000000000000000000000..daa4db49835fbf15a3506e4ecf961a72efec518a
--- /dev/null
+++ b/lib_com/g192.c
@@ -0,0 +1,255 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include
+#include
+#include
+#include
+#include "options.h"
+#include "g192.h"
+
+#define WMC_TOOL_SKIP
+
+#ifndef _WIN32
+#include
+#include
+#else
+#include
+typedef unsigned short uint16_t;
+typedef signed short int16_t;
+typedef unsigned int uint32_t;
+typedef signed int int32_t;
+typedef unsigned __int64 uint64_t;
+typedef signed __int64 int64_t;
+#endif
+
+#include "wmc_auto.h" /* Note that wmc_auto.h must be included after Winsock2.h because MAC() is defined in rpcerr.hand redefined within wmc_auto.h */
+
+
+#ifdef _MSC_VER
+#pragma warning( disable : 4996 )
+#endif
+
+#define G192_SYNC_GOOD_FRAME (unsigned short) 0x6B21
+#define G192_SYNC_BAD_FRAME (unsigned short) 0x6B20
+#define G192_BIT0 (unsigned short) 0x007F
+#define G192_BIT1 (unsigned short) 0x0081
+#define RTP_HEADER_PART1 (short)22 /* magic number by network simulator */
+
+#ifndef MAX_BITS_PER_FRAME
+#define MAX_BITS_PER_FRAME 2560
+#endif
+
+/*
+ * Structures
+ */
+
+/* main handle */
+struct __G192
+{
+ FILE * file;
+};
+
+/*
+ * Functions
+ */
+
+G192_ERROR
+G192_Reader_Open(G192_HANDLE* phG192, FILE * filename)
+{
+ /* create handle */
+ *phG192 = (G192_HANDLE) calloc(1, sizeof(struct __G192) );
+ if ( *phG192 == NULL )
+ {
+ return G192_MEMORY_ERROR;
+ }
+ memset(*phG192, 0, sizeof(struct __G192));
+
+ /* associate file stream */
+ (*phG192)->file = filename;
+ if( (*phG192)->file == NULL )
+ {
+ G192_Reader_Close(phG192);
+ return G192_FILE_NOT_FOUND;
+ }
+ return G192_NO_ERROR;
+}
+
+G192_ERROR
+G192_ReadVoipFrame_compact(G192_HANDLE const hG192,
+ unsigned char * const serial,
+ short * const num_bits,
+ unsigned short * const rtpSequenceNumber,
+ unsigned int * const rtpTimeStamp,
+ unsigned int * const rcvTime_ms)
+{
+ short short_serial [MAX_BITS_PER_FRAME];
+ G192_ERROR err;
+ short i;
+
+ err = G192_ReadVoipFrame_short(hG192, short_serial, num_bits, rtpSequenceNumber, rtpTimeStamp, rcvTime_ms);
+ if(err != G192_NO_ERROR)
+ return err;
+
+ for(i=0; i<*num_bits; i++)
+ {
+ unsigned char bit = (short_serial[i] == G192_BIT1) ? 1 : 0;
+ unsigned char bitinbyte = bit << (7- (i&0x7));
+ if(!(i&0x7))
+ serial[i>>3] = 0;
+ serial[i>>3] |= bitinbyte;
+ }
+ return G192_NO_ERROR;
+}
+
+G192_ERROR
+G192_ReadVoipFrame_short(G192_HANDLE const hG192,
+ short * const serial,
+ short * const num_bits,
+ unsigned short * const rtpSequenceNumber,
+ unsigned int * const rtpTimeStamp,
+ unsigned int * const rcvTime_ms)
+{
+ uint32_t rtpPacketSize;
+ uint16_t rtpPacketHeaderPart1;
+ uint32_t ssrc;
+ uint16_t rtpPayloadG192[2];
+ uint16_t rtpPayloadSize;
+
+ /* RTP packet size */
+ if(fread(&rtpPacketSize, sizeof(rtpPacketSize), 1, hG192->file) != 1)
+ {
+ if(feof( hG192->file) != 0)
+ {
+ return G192_EOF;
+ }
+ fprintf(stderr, "RTP Packet Size could't be read\n");
+
+ return G192_READ_ERROR;
+ }
+
+ if(rtpPacketSize <= 12)
+ {
+ fprintf(stderr, "RTP Packet size too small: %ud\n", rtpPacketSize);
+ return G192_INVALID_DATA;
+ }
+
+ /* RTP packet arrival time */
+ if(fread(rcvTime_ms, sizeof(*rcvTime_ms), 1, hG192->file) != 1)
+ {
+ if(feof( hG192->file) != 0)
+ {
+ return G192_EOF;
+ }
+ fprintf(stderr, "Reception Time in ms could't be read\n");
+
+ return G192_READ_ERROR;
+ }
+
+ /* RTP packet header (part without sequence number) */
+ if(fread(&rtpPacketHeaderPart1, sizeof(rtpPacketHeaderPart1), 1, hG192->file) != 1)
+ {
+ if(feof( hG192->file) != 0)
+ {
+ return G192_EOF;
+ }
+ fprintf(stderr, "RTP Header couldn't be read\n");
+
+ return G192_READ_ERROR;
+ }
+
+ if(rtpPacketHeaderPart1 != RTP_HEADER_PART1)
+ {
+ fprintf(stderr, "Unexpected RTP Packet header\n");
+ return G192_INVALID_DATA;
+ }
+
+ /* RTP sequence number */
+ if(fread(rtpSequenceNumber, sizeof(*rtpSequenceNumber), 1, hG192->file) != 1)
+ {
+ if(feof( hG192->file) != 0)
+ {
+ return G192_EOF;
+ }
+ fprintf(stderr, "RTP Sequence Number be read\n");
+
+ return G192_READ_ERROR;
+ }
+ *rtpSequenceNumber = ntohs(*rtpSequenceNumber);
+
+ /* RTP timestamp */
+ if(fread(rtpTimeStamp, sizeof(*rtpTimeStamp), 1, hG192->file) != 1)
+ {
+ if(feof( hG192->file) != 0)
+ {
+ return G192_EOF;
+ }
+ fprintf(stderr, "RTP Timestamp could't be read\n");
+
+ return G192_READ_ERROR;
+ }
+ *rtpTimeStamp = ntohl(*rtpTimeStamp);
+
+ /* RTP ssrc */
+ if(fread(&ssrc, sizeof(ssrc), 1, hG192->file) != 1)
+ {
+ if(feof( hG192->file) != 0)
+ {
+ return G192_EOF;
+ }
+ fprintf(stderr, "RTP SSRC could't be read\n");
+
+ return G192_READ_ERROR;
+ }
+
+ /* RTP payload size */
+ rtpPayloadSize = rtpPacketSize - 12;
+ if(rtpPayloadSize <= 2)
+ {
+ fprintf(stderr, "RTP payload size too small: %u\n", rtpPayloadSize);
+ return G192_INVALID_DATA;
+ }
+
+ /* RTP payload */
+ if(fread(rtpPayloadG192, sizeof(short), 2, hG192->file) != 2)
+ {
+ if(feof( hG192->file) != 0)
+ {
+ return G192_EOF;
+ }
+ fprintf(stderr, "Premature end of file, cannot read G.192 header\n");
+ return G192_READ_ERROR;
+ }
+ if(rtpPayloadG192[0] != G192_SYNC_GOOD_FRAME)
+ {
+ fprintf(stderr, "G192_SYNC_WORD missing from RTP payload!");
+ return G192_INVALID_DATA;
+ }
+ *num_bits = rtpPayloadG192[1];
+ if(*num_bits == 0u || *num_bits + 2u != rtpPayloadSize || *num_bits > MAX_BITS_PER_FRAME)
+ {
+ fprintf(stderr, "error in parsing RTP payload: rtpPayloadSize=%u nBits=%d",
+ rtpPayloadSize, *num_bits);
+ return G192_INVALID_DATA;
+ }
+ if( fread(serial, sizeof(short), *num_bits, hG192->file) != (unsigned short)*num_bits)
+ {
+ fprintf(stderr, "Premature end of file, cannot read G.192 payload\n");
+ return G192_READ_ERROR;
+ }
+
+ return G192_NO_ERROR;
+}
+
+G192_ERROR
+G192_Reader_Close(G192_HANDLE* phG192)
+{
+ if(phG192 == NULL || *phG192 == NULL)
+ return G192_NO_ERROR;
+
+ free( *phG192 );
+ *phG192 = NULL;
+ phG192 = NULL;
+ return G192_NO_ERROR;
+}
diff --git a/lib_com/g192.h b/lib_com/g192.h
new file mode 100644
index 0000000000000000000000000000000000000000..fc8cae6560d93cfc4a7d338f439cc9ea07c44160
--- /dev/null
+++ b/lib_com/g192.h
@@ -0,0 +1,66 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#ifndef G192_H
+#define G192_H
+
+#include
+
+/*
+ * ENUMS
+ */
+
+/* error enums */
+
+typedef enum _G192_ERROR
+{
+ G192_NO_ERROR = 0x0000,
+ G192_MEMORY_ERROR = 0x0001,
+ G192_WRONG_PARAMS = 0x0002,
+ G192_INIT_ERROR = 0x0003,
+ G192_WRITE_ERROR = 0x0004,
+ G192_READ_ERROR = 0x0005,
+ G192_FILE_NOT_FOUND = 0x0006,
+ G192_INVALID_DATA = 0x0007, /* error returned when read data is invalid */
+ G192_NOT_IMPLEMENTED = 0x0010,
+ G192_NOT_INITIALIZED = 0x0100,
+ G192_UNKNOWN_ERROR = 0x1000,
+ G192_EOF = 0xffff /* EOF during reading */
+} G192_ERROR;
+
+/*
+ * Structures
+ */
+
+/* main handle */
+struct __G192;
+typedef struct __G192 * G192_HANDLE;
+
+/*
+ * Functions
+ */
+
+G192_ERROR
+G192_Reader_Open(G192_HANDLE* phG192, FILE * filename);
+
+G192_ERROR
+G192_ReadVoipFrame_compact(G192_HANDLE const hG192,
+ unsigned char * const serial,
+ short * const num_bits,
+ unsigned short * const rtpSequenceNumber,
+ unsigned int * const rtpTimeStamp,
+ unsigned int * const rcvTime_ms);
+
+G192_ERROR
+G192_ReadVoipFrame_short(G192_HANDLE const hG192,
+ short * const serial,
+ short * const num_bits,
+ unsigned short * const rtpSequenceNumber,
+ unsigned int * const rtpTimeStamp,
+ unsigned int * const rcvTime_ms);
+
+G192_ERROR
+G192_Reader_Close(G192_HANDLE* phG192);
+
+#endif /* G192_H */
diff --git a/lib_com/get_gain.c b/lib_com/get_gain.c
new file mode 100644
index 0000000000000000000000000000000000000000..07f129362d82397ac3b3ae9e4336334adf481c31
--- /dev/null
+++ b/lib_com/get_gain.c
@@ -0,0 +1,38 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include "options.h"
+#include "wmc_auto.h"
+#include "prot.h"
+
+
+/*----------------------------------------------------------------------------------*
+* get_gain()
+*
+*
+*----------------------------------------------------------------------------------*/
+
+float get_gain( /* output: codebook gain (adaptive or fixed) */
+ float x[], /* input : target signal */
+ float y[], /* input : filtered codebook excitation */
+ int n, /* input : segment length */
+ float *en_y /* output: energy of y (sum of y[]^2, optional) */
+)
+{
+ float corr = 0.0f, ener = 1e-6f;
+ short i;
+
+ for (i = 0; i < n; i++)
+ {
+ corr += x[i]*y[i];
+ ener += y[i]*y[i];
+ }
+
+ if (en_y)
+ {
+ *en_y = ener;
+ }
+
+ return(corr/ener);
+}
diff --git a/lib_com/gs_bitallocation.c b/lib_com/gs_bitallocation.c
new file mode 100644
index 0000000000000000000000000000000000000000..d2e1051fad645d60db2293966d8240608c22ede8
--- /dev/null
+++ b/lib_com/gs_bitallocation.c
@@ -0,0 +1,452 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include
+#include "wmc_auto.h"
+#include "options.h"
+#include "cnst.h"
+#include "rom_com.h"
+#include "prot.h"
+
+
+/*-------------------------------------------------------------------*
+ * Local functions
+ *-------------------------------------------------------------------*/
+
+static float Find_bit_frac( const short nb_band, const short remaining_bits );
+
+/*-------------------------------------------------------------------*
+ * bands_and_bit_alloc()
+ *
+ * AC mode (GSC) bands and bits allocation
+ *-------------------------------------------------------------------*/
+
+void bands_and_bit_alloc(
+ const short cor_strong_limit, /* i : HF correlation */
+ const short noise_lev, /* i : dwn scaling factor */
+ const long core_brate, /* i : core bit rate */
+ const short Diff_len, /* i : Lenght of the difference signal (before pure spectral)*/
+ const short bits_used, /* i : Number of bit used before frequency Q */
+ short *bit, /* i/o: Number of bit allowed for frequency quantization */
+ float *Ener_per_bd_iQ, /* i/o: Quantized energy vector */
+ short *max_ener_band, /* o : Sorted order */
+ short *bits_per_bands_s,/* i/o: Number of bit allowed per allowed subband (Q3) */
+ short *nb_subbands, /* o : Number of subband allowed */
+ const float *exc_diff, /* i : Difference signal to quantize (encoder side only) */
+ float *concat_in, /* o : Concatened PVQ's input vector (encoder side only) */
+ short *pvq_len, /* o : Number of bin covered with the PVQ */
+ const short coder_type, /* i : coding type */
+ const short bwidth, /* i : input signal bandwidth */
+ const short GSC_noisy_speech /* i : GSC noisy speech flag */
+)
+{
+ short bandoffset, i, j, nb_bands_max, bit_new_bands, bit_tmp, st_band, nb_bands;
+ float bit_fracf, etmp;
+ float sum_bit;
+ float ener_vec[MBANDS_GN];
+ short nb_tot_bands;
+ short bit_index, bit_index_mem, imax;
+ short pos, band;
+ float SWB_bit_budget;
+ float bits_per_bands[MBANDS_GN];
+
+ /* initializations */
+ nb_tot_bands = 16;
+ set_f( bits_per_bands, 0.0f, MBANDS_GN );
+
+ /* To adapt current energy band to PVQ freq band for sorting*/
+ ener_vec[0] = Ener_per_bd_iQ[0] + Ener_per_bd_iQ[1];
+ mvr2r( Ener_per_bd_iQ + 1, ener_vec, 15 );
+ ener_vec[15] = ener_vec[14];
+
+ for(i = 0; i < MBANDS_GN; i++)
+ {
+ ener_vec[i] = (float)((short)(ener_vec[i]*4096.f+0.5f));
+ }
+
+ /*------------------------------------------------------------------------
+ * Determination of the number of bits available to the frequency domain
+ * Allocation of a maximum number of band to be encoded
+ *-----------------------------------------------------------------------*/
+
+ nb_bands_max = nb_tot_bands;
+ bit_new_bands = 5;
+
+ bit_index = BRATE2IDX(core_brate)*17;
+ bit_index_mem = bit_index;
+
+ if( (coder_type == AUDIO || coder_type == INACTIVE) && bwidth == NB )
+ {
+ if(core_brate >= ACELP_9k60)
+ {
+ *bit = (short)(core_brate*(1.0f/50) + 0.5f) - bits_used - 25;
+ }
+ else
+ {
+ *bit = (short)(core_brate*(1.0f/50) + 0.5f) - bits_used - 21;
+ }
+
+ nb_tot_bands = 10;
+ }
+ else
+ {
+ *bit = (short)(core_brate*(1.0f/50) + 0.5f) - bits_used - GSC_freq_bits[bit_index];
+ }
+
+ if( GSC_noisy_speech )
+ {
+ SWB_bit_budget = *bit;
+ nb_bands = 5;
+ st_band = nb_bands;
+
+ set_f( bits_per_bands, 0, MBANDS_GN );
+
+ bit_fracf = Find_bit_frac(nb_bands, SWB_bit_budget); /* Supplementary bits distributed only on first bands */
+
+ nb_tot_bands = nb_bands_max - 6;
+
+ if( nb_tot_bands > 16 )
+ {
+ nb_tot_bands = 16;
+ }
+
+ for(j = 0; j < 2; j++)
+ {
+ i = j;
+ max_ener_band[j] = i;
+ ener_vec[i] = 0;
+ }
+
+ for(; j < nb_bands; j++)
+ {
+ i = maximum(ener_vec, nb_tot_bands, &etmp);
+ max_ener_band[j] = i;
+ ener_vec[i] = 0;
+ }
+
+ set_f( bits_per_bands, bit_fracf, nb_bands );
+ }
+ else
+ {
+ bit_index++;
+ bit_tmp = *bit - GSC_freq_bits[bit_index];
+ bit_index++;
+ nb_bands_max += GSC_freq_bits[bit_index];
+ bit_index++;
+
+ *pvq_len = 112;
+ st_band = 7;
+
+ if( core_brate <= ACELP_9k60 )
+ {
+ *pvq_len = 80;
+ st_band = 5;
+ if( Diff_len == 0 )
+ {
+ nb_bands_max += 2;
+ bit_tmp -= 13;
+ }
+ }
+ else if( Diff_len == 0 )
+ {
+ nb_bands_max += 2;
+ bit_tmp -= 17;
+ }
+
+ nb_bands = *pvq_len/16;
+
+ /*------------------------------------------------------------------------
+ * Adjustement of the maximum number of bands in function of the
+ * dynamics of the spectrum (more or less speech like)
+ *-----------------------------------------------------------------------*/
+
+ if( coder_type == INACTIVE || noise_lev >= NOISE_LEVEL_SP3 )
+ {
+ /* Probably classification error -> concentrate bits on LF */
+ if( core_brate >= ACELP_8k00 )
+ {
+ nb_bands_max = nb_bands+1;
+ }
+ else
+ {
+ nb_bands_max = nb_bands;
+ }
+ }
+ else if( noise_lev >= NOISE_LEVEL_SP2 ||
+ (core_brate <= ACELP_13k20 && core_brate >= ACELP_9k60 && cor_strong_limit == 0) ) /* Very low dynamic, tend to speech, do not try to code HF at all */
+ {
+ nb_bands_max -= 2;
+ }
+ else if( noise_lev >= NOISE_LEVEL_SP1) /* Very low dynamic, tend to speech, code less HF */
+ {
+ nb_bands_max -= 1;
+ }
+
+ if( bwidth == NB && nb_bands_max > 10 )
+ {
+ nb_bands_max = 10;
+ }
+
+ /*------------------------------------------------------------------------
+ * Find extra number of band to code according to bit rate availables
+ *-----------------------------------------------------------------------*/
+
+ while ( bit_tmp >= bit_new_bands && nb_bands <= nb_bands_max - 1 )
+ {
+ bit_tmp -= bit_new_bands;
+ nb_bands++;
+ }
+
+ /*------------------------------------------------------------------------
+ * Fractional bits to distribute on the first x bands
+ *-----------------------------------------------------------------------*/
+
+ bit_fracf = Find_bit_frac(st_band, bit_tmp); /* Supplementary bits distributed only on first bands */
+
+ /*------------------------------------------------------------------------
+ * Complete the bit allocation per frequency band
+ *-----------------------------------------------------------------------*/
+
+ imax = 5;
+ if( core_brate > ACELP_9k60 )
+ {
+ imax = 7;
+ }
+
+ for(i = 0; i < imax; i++)
+ {
+ bits_per_bands[i] = GSC_freq_bits[bit_index] + bit_fracf;
+ bit_index++;
+ }
+
+ if( Diff_len == 0 )
+ {
+ bit_index = bit_index_mem+10;
+ for( i = 0; i < 7; i++ )
+ {
+ bits_per_bands[i] += GSC_freq_bits[bit_index];
+ bit_index++;
+ }
+ }
+
+ /*--------------------------------------------------------------------------
+ * Complete the bit allocation per frequency band for 16kHz high brate mode
+ *--------------------------------------------------------------------------*/
+
+ for( j = st_band; j < nb_bands; j++ )
+ {
+ bits_per_bands[j] = bit_new_bands;
+ }
+
+ /*--------------------------------------------------------------------------
+ * Compute a maximum band (band offset) for the search on maximal energy
+ * This is function of the spectral dynamic and the bitrate
+ *--------------------------------------------------------------------------*/
+
+ bandoffset = nb_tot_bands - (nb_bands + 2);
+
+ if( noise_lev <= NOISE_LEVEL_SP1a )
+ {
+ bandoffset--;
+ }
+ else if ( (core_brate <= ACELP_13k20 && (coder_type == INACTIVE || noise_lev >= NOISE_LEVEL_SP3)) ||
+ (core_brate <= ACELP_13k20 && core_brate >= ACELP_9k60 && cor_strong_limit == 0) )
+ {
+ bandoffset++;
+ }
+
+ if( bandoffset < 0 )
+ {
+ bandoffset = 0;
+ }
+
+ /*--------------------------------------------------------------------------
+ * Initiazed sorted vector
+ * For the first x bands to be included in th final sorted vector
+ * Sort the remaining bands in decrease energy order
+ *--------------------------------------------------------------------------*/
+
+ for(j = 0; j < nb_tot_bands; j++)
+ {
+ max_ener_band[j] = -10;
+ }
+
+ for(j = 0; j < st_band; j++)
+ {
+ max_ener_band[j] = j;
+ ener_vec[j] = -10;
+ }
+
+ pos = st_band;
+ for(; j < nb_bands; j++)
+ {
+ i = maximum(ener_vec, nb_tot_bands-bandoffset, &etmp);
+ if(i > pos)
+ {
+ pos = i;
+ }
+ max_ener_band[j] = i;
+ ener_vec[i] = -10;
+ }
+
+ /* re-allocate bits to the frames such that the highest band with allocated bits is higher than the threshold */
+ if( nb_tot_bands - bandoffset > nb_bands && ( pos > 7 && core_brate == ACELP_8k00 ) && bwidth == WB )
+ {
+ band = nb_tot_bands-bandoffset-nb_bands;
+ for( j=0; j 0 )
+ {
+ bits_per_bands[j] -= 1;
+
+ if ( j == st_band - 1 - i )
+ {
+ j = 0;
+ }
+ else
+ {
+ ++j;
+ }
+
+ if( j == 0 && i < st_band - 1)
+ {
+ i++;
+ }
+
+ bit_tmp -= 1;
+ }
+ }
+
+ /*--------------------------------------------------------------------------
+ * Bit sum verification for GSC inactive at very high rate
+ * The maximum number of bits per band of length 16 is 112
+ * Redistribute the overage bits if needed
+ *--------------------------------------------------------------------------*/
+
+ sum_bit = 0;
+ j = 0;
+ for( i = 0; i < nb_bands; i++ )
+ {
+ if( bits_per_bands[i] > 112 )
+ {
+ sum_bit += bits_per_bands[i] - 112;
+ bits_per_bands[i] = 112;
+ j = i+1;
+ }
+
+ /* safety check for overage bit reallocation */
+ else if( bits_per_bands[i] + sum_bit/3 > 112 )
+ {
+ j = i+1;
+ }
+ }
+
+ if( sum_bit != 0 )
+ {
+ sum_bit /= (nb_bands - j);
+ for( i = j; i < nb_bands; i++ )
+ {
+ bits_per_bands[i] += sum_bit;
+ }
+ }
+ }
+
+ /*--------------------------------------------------------------------------
+ * second step of bit sum verification, normally sum_bit == *bit
+ *--------------------------------------------------------------------------*/
+
+ sum_bit = 0.00f;
+ for( i = 0; i < nb_bands; i++ )
+ {
+ bits_per_bands[i] = (float)floor(bits_per_bands[i]);
+ sum_bit += bits_per_bands[i];
+ }
+
+ if( *bit > sum_bit )
+ {
+ i = nb_bands-1;
+ while(*bit > sum_bit)
+ {
+ bits_per_bands[i]++;
+ sum_bit++;
+ i--;
+ if(i==0)
+ {
+ i = nb_bands-1;
+ }
+ }
+ }
+
+ /*--------------------------------------------------------------------------
+ * Recompute the real number/length of frequency bands to encode
+ *--------------------------------------------------------------------------*/
+
+ *nb_subbands = nb_bands;
+ *pvq_len = *nb_subbands*16;
+
+ /*--------------------------------------------------------------------------
+ * Concatenate bands (encoder only)
+ *--------------------------------------------------------------------------*/
+
+ if( exc_diff != NULL )
+ {
+ for( j = 0; j < nb_bands; j++ )
+ {
+ mvr2r( exc_diff + max_ener_band[j]*16, concat_in+j*16, 16 );
+ }
+ }
+ for( j = 0; j < nb_bands; j++ )
+ {
+ bits_per_bands_s[j] = ((short)bits_per_bands[j]) << 3;
+ }
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------*
+ * Find_bit_frac()
+ *
+ * Computes the fraction of the remaining bit budget to allocate to the bands
+ *-------------------------------------------------------------------*/
+
+static float Find_bit_frac(
+ const short nb_band,
+ const short remaining_bits
+)
+{
+ float var_out;
+ short inv_bandQ15;
+ int L_num;
+
+ inv_bandQ15 = 6553;
+ if (nb_band == 7)
+ {
+ inv_bandQ15 = 4681;
+ }
+ L_num = inv_bandQ15*remaining_bits;
+ L_num *= 8;
+ var_out = L_num/262144.0f;
+
+ return (var_out);
+}
diff --git a/lib_com/gs_gains.c b/lib_com/gs_gains.c
new file mode 100644
index 0000000000000000000000000000000000000000..076ea847822ca0874fc22839516740ce43f18048
--- /dev/null
+++ b/lib_com/gs_gains.c
@@ -0,0 +1,572 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include
+#include "wmc_auto.h"
+#include "options.h"
+#include "cnst.h"
+#include "rom_com.h"
+#include "prot.h"
+
+
+/*-------------------------------------------------------------------*
+ * Local functions
+ *-------------------------------------------------------------------*/
+
+static short VDQ_vec( float *Qvec_out, const float *mean_dic, const float *dic,
+ const short index, const short vec_en );
+
+/*-------------------------------------------------------------------*
+ * Comp_and_apply_gain()
+ *
+ * Compute and apply the quantized per band gain
+ *-------------------------------------------------------------------*/
+
+void Comp_and_apply_gain(
+ float exc_diffQ[], /* i/o: Quantized excitation */
+ float Ener_per_bd_iQ[], /* o : Target ener per band */
+ float Ener_per_bd_yQ[], /* o : Ener per band for norm vector */
+ short Mbands_gn, /* i : number of bands */
+ const short ReUseGain /* i : Reuse the gain in Ener_per_bd_yQ */
+)
+{
+ short i, i_band;
+ short StartBin, NB_Qbins;
+ float y_gain;
+
+ /* Recreate excitation for local synthesis and decoder */
+ StartBin = 0;
+ NB_Qbins = 0;
+ for( i_band = 0; i_band < Mbands_gn; i_band++ )
+ {
+ StartBin += NB_Qbins;
+ NB_Qbins = mfreq_bindiv_loc[i_band];
+ if( ReUseGain == 1 )
+ {
+ y_gain = Ener_per_bd_yQ[i_band];
+ }
+ else
+ {
+ y_gain = (float)pow(10, (Ener_per_bd_iQ[i_band]-Ener_per_bd_yQ[i_band]));
+ Ener_per_bd_yQ[i_band] = y_gain;
+ }
+
+ for(i = StartBin ; i < NB_Qbins + StartBin ; i++)
+ {
+ exc_diffQ[i] *= y_gain;
+ }
+ }
+
+ return;
+}
+
+/*------------------------------------------------------------------*
+ * Ener_per_band_comp()
+ *
+ * Compute the energy per band in log domain for quantization purposes
+ * Loops are decomposed to accomodate the PVQ quantization
+ *------------------------------------------------------------------*/
+
+void Ener_per_band_comp(
+ const float exc_diff[], /* i : target signal */
+ float y_gain4[], /* o : Energy per band to quantize */
+ const short Mband, /* i : Max band */
+ const short Eflag /* i : flag of highest band */
+)
+{
+ float etmp;
+ const float *pt;
+ short i,j;
+
+ pt = exc_diff;
+ for(j = 0; j < 2; j++)
+ {
+ y_gain4[j] = 0;
+ etmp = 0.02f;
+
+ pt = exc_diff + j*8;
+ for(i = 0; i < 8; i++)
+ {
+ etmp += (*pt **pt);
+ pt++;
+ }
+
+ /* normalized to 16 bins to easy the quantization */
+ y_gain4[j] = (float)log10(sqrt(2*etmp));
+ }
+
+ for(j = 1; j < Mband-2; j++)
+ {
+ etmp = 0.01f;
+
+ pt = exc_diff + j*16;
+ for(i = 0; i < 16; i++)
+ {
+ etmp += (*pt **pt);
+ pt++;
+ }
+
+ y_gain4[j+1] = (float)log10(sqrt(etmp));
+ }
+
+ if( Eflag == 1 )
+ {
+ etmp = 0.01f;
+
+ pt = exc_diff + j*16;
+ for(i = 0; i < 32; i++)
+ {
+ etmp += (*pt **pt);
+ pt++;
+ }
+
+ y_gain4[j+1] = (float)log10(sqrt(etmp/2));
+ }
+
+ return;
+}
+
+/*-------------------------------------------------------------------*
+ * gsc_gainQ()
+ *
+ * Quantization of the energy per band
+ *-------------------------------------------------------------------*/
+
+float gsc_gainQ(
+ Encoder_State *st, /* i/o: encoder state structure */
+ const float y_gain4[], /* i : Energy per band */
+ float y_gainQ[], /* o : quantized energy per band */
+ const long core_brate, /* i : Core rate */
+ const short coder_type, /* i : coding type */
+ const short bwidth /* i : input signal bandwidth */
+)
+{
+ float y_gain_tmp[MBANDS_GN], y_gain_tmp2[MBANDS_GN];
+ short i, idx_g = 0;
+ float mean_4g[1], ftmp1;
+ float Gain_off = 0.0f;
+ short Mbands_gn = MBANDS_GN;
+ float y_gain_tmp3[MBANDS_GN];
+
+ mean_4g[0] = 0;
+
+ if( (coder_type == AUDIO || coder_type == INACTIVE) && bwidth == NB )
+ {
+ ftmp1 = mean(y_gain4, 10) - 0.6f;
+ for(i = 0; i < Mbands_gn; i++)
+ {
+ if(y_gain4[i] < ftmp1)
+ {
+ y_gain_tmp2[i] = ftmp1;
+ }
+ else
+ {
+ y_gain_tmp2[i] = y_gain4[i];
+ }
+ }
+
+ /* Quantized mean gain without clipping */
+ mean_4g[0] = mean(y_gain_tmp2, 10);
+ idx_g = (short)vquant(mean_4g, Gain_meanNB, mean_4g, Gain_mean_dicNB, 1, 64);
+ push_indice( st, IND_MEAN_GAIN2, idx_g, 6 );
+
+ for(i = 0; i < Mbands_gn; i++)
+ {
+ y_gain_tmp[i] = y_gain_tmp2[i] - mean_4g[0];
+ }
+
+ if( y_gain_tmp[9] < -0.3f )
+ {
+ y_gain_tmp[9] = -0.3f;
+ }
+
+ set_f(y_gain_tmp+10, 0.0f, MBANDS_GN-10);
+ idx_g = (short)vquant(y_gain_tmp, Mean_dic_NB, y_gain_tmp, Gain_dic1_NB, 3, 64);
+ push_indice( st, IND_Y_GAIN_TMP, idx_g, 6 );
+
+ if(core_brate < ACELP_9k60)
+ {
+ idx_g = (short)vquant(y_gain_tmp+3, Mean_dic_NB+3, y_gain_tmp+3, Gain_dic2_NB, 3, 32);
+ push_indice( st, IND_Y_GAIN_TMP, idx_g, 5 );
+
+ idx_g = (short)vquant(y_gain_tmp+6, Mean_dic_NB+6, y_gain_tmp+6, Gain_dic3_NB, 4, 16);
+ push_indice( st, IND_Y_GAIN_TMP, idx_g, 4 );
+ }
+ else
+ {
+ idx_g = (short)vquant(y_gain_tmp+3, Mean_dic_NB+3, y_gain_tmp+3, Gain_dic2_NBHR, 3, 64);
+ push_indice( st, IND_Y_GAIN_TMP, idx_g, 6 );
+
+ idx_g = (short)vquant(y_gain_tmp+6, Mean_dic_NB+6, y_gain_tmp+6, Gain_dic3_NBHR, 4, 128);
+ push_indice( st, IND_Y_GAIN_TMP, idx_g, 7 );
+ }
+
+ if( core_brate <= ACELP_9k60 && coder_type == INACTIVE )
+ {
+ /* Some energy is needed in high band for stat_noise_uv_enc() to be functional in inactive speech */
+ y_gain_tmp[10] = mean(y_gain_tmp+6, 3);
+ y_gain_tmp[11] = mean(y_gain_tmp+7, 3);
+ y_gain_tmp[12] = mean(y_gain_tmp+8, 3);
+ y_gain_tmp[13] = mean(y_gain_tmp+9, 3);
+ y_gain_tmp[14] = mean(y_gain_tmp+10, 3);
+ y_gain_tmp[15] = mean(y_gain_tmp+11, 3);
+ }
+ else
+ {
+ set_f( y_gain_tmp + 10, 0, MBANDS_GN - 10 );
+ }
+ }
+ else
+ {
+ ftmp1 = mean(y_gain4, 16);
+ for(i = 0; i < Mbands_gn; i++)
+ {
+ if(y_gain4[i] < ftmp1-0.6f)
+ {
+ y_gain_tmp2[i] = ftmp1-.6f;
+ }
+ else if(y_gain4[i] > ftmp1+0.6f)
+ {
+ y_gain_tmp2[i] = ftmp1+0.6f;
+ }
+ else
+ {
+ y_gain_tmp2[i] = y_gain4[i];
+ }
+ }
+
+ mean_4g[0] = mean(y_gain_tmp2, 16);
+ idx_g = (short)vquant(mean_4g, mean_m, mean_4g, mean_gain_dic, 1, 64);
+ push_indice( st, IND_MEAN_GAIN2, idx_g, 6 );
+
+ /* Subtraction of the average gain */
+ for(i = 0; i < Mbands_gn; i++)
+ {
+ y_gain_tmp[i] = y_gain_tmp2[i] - mean_4g[0];
+ }
+
+ if( core_brate < ACELP_9k60 )
+ {
+ /* prediction and quantization of the average gain */
+
+ /*--------------------------------------------------------------------------------------*
+ * Quantization of the first 8 bands
+ * Keep only 4 bands out of the last 8 bands
+ *--------------------------------------------------------------------------------------*/
+
+ mvr2r(y_gain_tmp, y_gain_tmp2, 8);
+
+ y_gain_tmp2[8] = y_gain_tmp[8];
+ y_gain_tmp2[9] = y_gain_tmp[10];
+ y_gain_tmp2[10] = y_gain_tmp[12];
+ y_gain_tmp2[11] = y_gain_tmp[14];
+
+ idx_g = 0;
+ idx_g = (short)vquant(y_gain_tmp2, YGain_mean_LR, y_gain_tmp2, YGain_dic1_LR, 3, 32);
+ push_indice( st, IND_Y_GAIN_TMP, idx_g, 5 );
+
+ idx_g = (short)vquant(y_gain_tmp2+3, YGain_mean_LR+3, y_gain_tmp2+3, YGain_dic2_LR, 4, 32);
+ push_indice( st, IND_Y_GAIN_TMP, idx_g, 5 );
+
+ /*----------------------------------------------------------------------*
+ * Vector quantization of the first 8 bands + quantization of the 4 bands out of the last 8
+ * Interpolation of the last 4 bands Q to create bands 8-16
+ *----------------------------------------------------------------------*/
+
+ idx_g = (short)vquant(y_gain_tmp2+7, YGain_mean_LR+7, y_gain_tmp2+7, YGain_dic3_LR, 5, 32);
+ push_indice( st, IND_Y_GAIN_TMP, idx_g, 5 );
+
+ set_f(y_gain_tmp2+12, 0, MBANDS_GN-12);
+
+ /* Update to quantized vector */
+ mvr2r(y_gain_tmp2, y_gain_tmp, 8);
+
+ mvr2r(y_gain_tmp2+8, y_gain_tmp3, 4);
+ set_f(y_gain_tmp+8, 0,8);
+ fft_rel(y_gain_tmp2+8, 4, 2);
+
+ mvr2r(y_gain_tmp2+8, y_gain_tmp+8, 3);
+ y_gain_tmp[15] = y_gain_tmp2[11];
+ ifft_rel(y_gain_tmp+8, 8, 3);
+
+ for(i = 8; i < 16; i++)
+ {
+ y_gain_tmp[i] *= 1.41f;
+ }
+
+ y_gain_tmp[8] = y_gain_tmp3[0];
+ y_gain_tmp[10]= y_gain_tmp3[1];
+ y_gain_tmp[12]= y_gain_tmp3[2];
+ y_gain_tmp[14]= y_gain_tmp3[3];
+ }
+ else
+ {
+ idx_g = (short)vquant(y_gain_tmp, YG_mean16, y_gain_tmp, YG_dicMR_1, 4, 64);
+ push_indice( st, IND_Y_GAIN_TMP, idx_g, 6 );
+
+ idx_g = (short)vquant(y_gain_tmp+4, YG_mean16+4, y_gain_tmp+4, YG_dicMR_2, 4, 32);
+ push_indice( st, IND_Y_GAIN_TMP, idx_g, 5 );
+
+ idx_g = (short)vquant(y_gain_tmp+8, YG_mean16+8, y_gain_tmp+8, YG_dicMR_3, 4, 32);
+ push_indice( st, IND_Y_GAIN_TMP, idx_g, 5 );
+
+ idx_g = (short)vquant(y_gain_tmp+12, YG_mean16+12, y_gain_tmp+12, YG_dicMR_4, 4, 16);
+ push_indice( st, IND_Y_GAIN_TMP, idx_g, 4 );
+ }
+ }
+
+ /* Gain adjustment to fit ACELP generic inactive coding gain at low rate */
+ if( coder_type == INACTIVE )
+ {
+ Gain_off = 0.0f;
+ {
+ if(core_brate <= ACELP_7k20 )
+ {
+ Gain_off = 8.f; /* 0 dB */
+ }
+ else if (core_brate <= ACELP_8k00 )
+ {
+ Gain_off = 6.6f; /* ~-3.3 dB */
+ }
+ else if (core_brate <= ACELP_9k60 )
+ {
+ Gain_off = 4.8f; /* ~-2.4 dB */
+ }
+ else if (core_brate <= ACELP_11k60 )
+ {
+ Gain_off = 3.5f; /* ~-2.4 dB */
+ }
+ else if (core_brate <= ACELP_13k20 )
+ {
+ Gain_off = 3.0f; /* ~-2.4 dB */
+ }
+ }
+
+ }
+
+ if( coder_type != INACTIVE )
+ {
+ for( i = 0; i < Mbands_gn; i++ )
+ {
+ y_gainQ[i] = y_gain_tmp[i] + mean_4g[0];
+ }
+ }
+ else
+ {
+ /*mimic ACELP decay of energy for low rates*/
+ for( i = 0; i < Mbands_gn; i++ )
+ {
+ y_gainQ[i] = y_gain_tmp[i]+mean_4g[0]-(i*(Gain_off/20.f)/((float) Mbands_gn));
+ }
+ }
+
+ return mean_4g[0];
+}
+
+/*-------------------------------------------------------------------*
+ * gsc_gaindec()
+ *
+ * Generic signal frequency band decoding and application
+ *-------------------------------------------------------------------*/
+
+float gsc_gaindec( /* o : average frequency gain */
+ Decoder_State *st, /* i/o: decoder state structure */
+ float y_gainQ[], /* o : quantized gain per band */
+ const long core_brate, /* i : core used */
+ float old_y_gain[], /* i/o: AR gain quantizer for low rate */
+ const short coder_type, /* i : coding type */
+ const short bwidth /* i : input signal bandwidth */
+)
+{
+ short idx_g, i;
+ float mean_4g;
+ float Gain_off = 0.0;
+ short Mbands_gn = MBANDS_GN;
+ float y_gain_tmp3[MBANDS_GN];
+
+ if( (coder_type == AUDIO || coder_type == INACTIVE) && bwidth == NB )
+ {
+ idx_g = (short) get_next_indice( st, 6 );
+ VDQ_vec(&mean_4g, Gain_meanNB, Gain_mean_dicNB, idx_g, 1 );
+
+ idx_g = (short) get_next_indice( st, 6 );
+ VDQ_vec(y_gainQ, Mean_dic_NB, Gain_dic1_NB, idx_g, 3 );
+
+ if(core_brate < ACELP_9k60)
+ {
+ idx_g = (short) get_next_indice( st, 5 );
+ VDQ_vec(y_gainQ+3, Mean_dic_NB+3, Gain_dic2_NB, idx_g, 3 );
+
+ idx_g = (short) get_next_indice( st, 4 );
+ VDQ_vec(y_gainQ+6, Mean_dic_NB+6, Gain_dic3_NB, idx_g, 4 );
+ }
+ else
+ {
+ idx_g = (short) get_next_indice( st, 6 );
+ VDQ_vec(y_gainQ+3, Mean_dic_NB+3, Gain_dic2_NBHR, idx_g, 3 );
+
+ idx_g = (short) get_next_indice( st, 7 );
+ VDQ_vec(y_gainQ+6, Mean_dic_NB+6, Gain_dic3_NBHR, idx_g, 4 );
+ }
+
+ if( core_brate <= ACELP_9k60 && coder_type == INACTIVE )
+ {
+ /* Some energy is needed in high band for stat_noise_uv_enc
+ to be functional in inactive speech */
+ y_gainQ[10] = mean(y_gainQ+6, 3);
+ y_gainQ[11] = mean(y_gainQ+7, 3);
+ y_gainQ[12] = mean(y_gainQ+8, 3);
+ y_gainQ[13] = mean(y_gainQ+9, 3);
+ y_gainQ[14] = mean(y_gainQ+10, 3);
+ y_gainQ[15] = mean(y_gainQ+11, 3);
+ }
+ else
+ {
+ set_f( y_gainQ + 10, 0, MBANDS_GN-10 );
+ }
+ }
+ else
+ {
+ idx_g = (short) get_next_indice( st, 6 );
+ VDQ_vec(&mean_4g, mean_m, mean_gain_dic, idx_g, 1 );
+
+ if( core_brate < ACELP_9k60 )
+ {
+ /*--------------------------------------------------------------------------------------*
+ * UQ of the first 8 bands and half of the last 8 bands
+ *--------------------------------------------------------------------------------------*/
+
+ idx_g = (short) get_next_indice( st, 5 );
+ VDQ_vec(y_gainQ, YGain_mean_LR, YGain_dic1_LR, idx_g, 3 );
+
+ idx_g = (short) get_next_indice( st, 5 );
+ VDQ_vec(y_gainQ+3, YGain_mean_LR+3, YGain_dic2_LR, idx_g, 4 );
+
+ /*----------------------------------------------------------------------*
+ * Interpolation of the last 4 Q bands to create bands 8-16
+ * And scaling
+ *----------------------------------------------------------------------*/
+
+ idx_g = (short) get_next_indice( st, 5 );
+ VDQ_vec(y_gainQ+7, YGain_mean_LR+7, YGain_dic3_LR, idx_g, 5 );
+
+ mvr2r(y_gainQ + 8, y_gain_tmp3, 4);
+ set_f(y_gainQ + 12, 0.0f, 4);
+
+ fft_rel(y_gainQ + 8, 4, 2);
+
+ y_gainQ[15] = y_gainQ[11];
+ y_gainQ[11] = 0.0f;
+
+ ifft_rel(y_gainQ + 8, 8, 3);
+
+ for(i = 8; i < 16; i++)
+ {
+ y_gainQ[i] *= 1.41f;
+ }
+
+ /*----------------------------------------------------------------------*
+ * Copy the true Q values in the specific bands
+ *----------------------------------------------------------------------*/
+
+ y_gainQ[8] = y_gain_tmp3[0];
+ y_gainQ[10]= y_gain_tmp3[1];
+ y_gainQ[12]= y_gain_tmp3[2];
+ y_gainQ[14]= y_gain_tmp3[3];
+ }
+ else
+ {
+ idx_g = (short) get_next_indice( st, 6 );
+ VDQ_vec(y_gainQ, YG_mean16, YG_dicMR_1, idx_g, 4 );
+
+ idx_g = (short) get_next_indice( st, 5 );
+ VDQ_vec(y_gainQ+4, YG_mean16+4, YG_dicMR_2, idx_g, 4 );
+
+ idx_g = (short) get_next_indice( st, 5 );
+ VDQ_vec(y_gainQ+8, YG_mean16+8, YG_dicMR_3, idx_g, 4 );
+
+ idx_g = (short) get_next_indice( st, 4 );
+ VDQ_vec(y_gainQ+12, YG_mean16+12, YG_dicMR_4, idx_g, 4);
+ }
+ }
+
+ /* Gain adjustment to fit ACELP generic inactive coding gain at low rate */
+ if( coder_type == INACTIVE )
+ {
+ Gain_off = 0.0f;
+ {
+ if(core_brate <= ACELP_7k20 )
+ {
+ Gain_off = 8.f; /* 0 dB */
+ }
+ else if (core_brate <= ACELP_8k00 )
+ {
+ Gain_off = 6.6f; /* ~-3.3 dB */
+ }
+ else if (core_brate <= ACELP_9k60 )
+ {
+ Gain_off = 4.8f; /* ~-2.4 dB */
+ }
+ else if (core_brate <= ACELP_11k60 )
+ {
+ Gain_off = 3.5f; /* ~-2.4 dB */
+ }
+ else if (core_brate <= ACELP_13k20 )
+ {
+ Gain_off = 3.0f; /* ~-2.4 dB */
+ }
+ }
+
+ }
+
+ if( coder_type != INACTIVE )
+ {
+ for( i = 0; i < Mbands_gn; i++ )
+ {
+ old_y_gain[i] = y_gainQ[i];
+ y_gainQ[i] += mean_4g;
+ }
+ }
+ else
+ {
+ /*mimic ACELP decay of energy for low rates*/
+ for( i = 0; i < Mbands_gn; i++ )
+ {
+ old_y_gain[i] = y_gainQ[i];
+ y_gainQ[i] += mean_4g-i*(Gain_off/20.f)/((float) Mbands_gn);
+ }
+ }
+
+ return mean_4g;
+}
+
+/*-------------------------------------------------------------------*
+ * VDQ_vec()
+ *
+ * Return the dequantized vector of index
+ *-------------------------------------------------------------------*/
+
+static short VDQ_vec(
+ float *Qvec_out, /* o: Quanitzed vector */
+ const float *mean_dic, /* i: average codebook */
+ const float *dic, /* i: codebook */
+ const short index, /* i: index of codebook*/
+ const short vec_en /* i: vector length */
+)
+{
+ short i, j;
+
+ j = index*vec_en;
+ for ( i = 0; i < vec_en; i++)
+ {
+ Qvec_out[i] = dic[j++];
+ }
+
+ for(i = 0; i < vec_en; i++)
+ {
+ Qvec_out[i] += mean_dic[i];
+ }
+
+ return index;
+}
diff --git a/lib_com/gs_inact_switching.c b/lib_com/gs_inact_switching.c
new file mode 100644
index 0000000000000000000000000000000000000000..001898eb9a8772891ad1ceba29f24f3d853ff5b1
--- /dev/null
+++ b/lib_com/gs_inact_switching.c
@@ -0,0 +1,108 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include
+#include "wmc_auto.h"
+#include "options.h"
+#include "cnst.h"
+#include "rom_com.h"
+#include "prot.h"
+
+/*-------------------------------------------------------------------*
+ * Local constants
+ *-------------------------------------------------------------------*/
+
+#define ALPHA0 0.5f
+#define BETA0 (1.0f-ALPHA0)
+
+/*-------------------------------------------------------------------*
+ * inact_switch_ematch()
+ *
+ * Apply energy matching when swithcing to INACTIVE frame coded by the GSC technology
+ *-------------------------------------------------------------------*/
+
+void inact_switch_ematch(
+ float exc2[], /* i/o: CELP/GSC excitation buffer */
+ float dct_exc_tmp[], /* i : GSC excitation in DCT domain */
+ float lt_ener_per_band[], /* i/o: Long term energy per band */
+ const short coder_type, /* i : Coding mode */
+ const short L_frame, /* i : Frame lenght */
+ const long core_brate, /* i : Core bit rate */
+ const short bfi /* i : frame lost indicator */
+ ,const short last_core, /* i : Last core used */
+ const short last_codec_mode /* i : Last codec mode */
+)
+{
+ float Ener_per_bd[MBANDS_GN];
+ float ftmp;
+ float *pt_exc;
+ short j, i;
+
+
+ /*--------------------------------------------------------------------------
+ * average energy per band
+ *--------------------------------------------------------------------------*/
+
+ if( coder_type == AUDIO && bfi == 0)
+ {
+ Ener_per_band_comp( dct_exc_tmp, Ener_per_bd, MBANDS_GN, 1 );
+
+ /* reset long-term energy per band */
+ for( i = 0; i < MBANDS_GN; i++ )
+ {
+ lt_ener_per_band[i] = Ener_per_bd[i];
+ }
+ }
+ else if( coder_type == VOICED || coder_type == GENERIC || coder_type == TRANSITION || last_core != ACELP_CORE || last_codec_mode != MODE1 )
+ {
+ /* Find spectrum and energy per band for GC and VC frames */
+ edct( exc2, dct_exc_tmp, L_frame );
+ Ener_per_band_comp( dct_exc_tmp, Ener_per_bd, MBANDS_GN, 1 );
+
+ /* reset long-term energy per band */
+ for(i = 0; i < MBANDS_GN; i++)
+ {
+ lt_ener_per_band[i] = Ener_per_bd[i];
+ }
+ }
+ else if( coder_type == INACTIVE && core_brate <= ACELP_24k40 )
+ {
+ /* Find spectrum and energy per band for inactive frames */
+ edct( exc2, dct_exc_tmp, L_frame );
+ Ener_per_band_comp( dct_exc_tmp, Ener_per_bd, MBANDS_GN, 1 );
+
+ /* More agressive smoothing in the first 50 frames */
+ pt_exc = dct_exc_tmp;
+ for( i = 0; i < MBANDS_GN; i++ )
+ {
+ /* Compute smoothing gain to apply with gain limitation */
+ lt_ener_per_band[i] = ALPHA0*lt_ener_per_band[i] + BETA0*Ener_per_bd[i];
+
+ ftmp = lt_ener_per_band[i] - Ener_per_bd[i];
+ ftmp = (float)pow(10, ftmp);
+
+ if( i < 2 )
+ {
+ for (j = 0; j < 8; j ++)
+ {
+ *pt_exc *= ftmp;
+ pt_exc++;
+ }
+ }
+ else
+ {
+ for (j = 0; j < 16; j ++)
+ {
+ *pt_exc *= ftmp;
+ pt_exc++;
+ }
+ }
+ }
+
+ /* Going back to time */
+ edct( dct_exc_tmp, exc2, L_frame );
+ }
+
+ return;
+}
diff --git a/lib_com/gs_noisefill.c b/lib_com/gs_noisefill.c
new file mode 100644
index 0000000000000000000000000000000000000000..6d113c17d940e18b119a25a42e1e3a0c8ff17614
--- /dev/null
+++ b/lib_com/gs_noisefill.c
@@ -0,0 +1,687 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include
+#include "wmc_auto.h"
+#include "options.h"
+#include "cnst.h"
+#include "rom_com.h"
+#include "prot.h"
+
+
+/*-------------------------------------------------------------------*
+ * gs_noisf()
+ *
+ * Noise fill-in function
+ *-------------------------------------------------------------------*/
+
+static void gs_noisf(
+ const short Start_BIN, /* i : First bin for noise fill */
+ const short NB_Qbins, /* i : Number of bin per band */
+ const float Noise_fac, /* i : Noise level */
+ const float *y_norm, /* i : Quantized pulses */
+ float *exc_diffQ, /* o : Quantized pulses with noise added */
+ short *seed_tcx, /* i : Random generator seed */
+ const short coder_type /* i : coder type */
+)
+{
+ float ftmp;
+ short i, k;
+ short NB_zer = NB_Qbins/2;
+
+ if( coder_type == INACTIVE )
+ {
+ NB_zer = 2;
+ }
+
+ /*----------------------------------------------*
+ * noise fill-in on unquantized subvector *
+ * injected only from 1066Hz to 6400Hz. *
+ *----------------------------------------------*/
+
+ for( k=Start_BIN; k ACELP_24k40 )
+ {
+ noise_offset = .2f;
+ }
+ else if( bitrate >= ACELP_22k60 )
+ {
+ noise_offset = .3f;
+ }
+ else if( bitrate >= ACELP_9k60 )
+ {
+ noise_offset = 0.35f;
+ }
+ else
+ {
+ noise_offset = .4f;
+ }
+
+ set_f( noisepb + i_band, noise_offset, Mbands_gn - i_band );
+
+ for( i = i_band; i < 5; i++ )
+ {
+ if( noisepb[i] > 0.2f )
+ {
+ noisepb[i] = 0.2f;
+ }
+ }
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------*
+ * EstimateNoiseLevel()
+ *
+ *
+ *-------------------------------------------------------------------*/
+
+static void EstimateNoiseLevel(
+ float *noisepb, /* o : Noise per band */
+ const long bitrate, /* i : Bitrate of the codec */
+ const short Diff_len, /* i : number of bin before cut-off frequency */
+ const short Mbands_gn, /* i : number of bands */
+ const short coder_type, /* i : coder type */
+ const short noise_lev, /* i : pulses dynamic */
+ const short pit_band_idx, /* i : bin position of the cut-off frequency */
+ short last_bin, /* i : the last bin of bit allocation */
+ short bwidth
+)
+{
+ short i_band;
+
+ i_band = 0;
+
+ if( Diff_len < L_FRAME )
+ {
+ EstimateNoiseLevel_inner(noisepb, bitrate, i_band, Mbands_gn);
+
+ if( coder_type != INACTIVE )
+ {
+ if( (bitrate == ACELP_8k00 && last_bin > 8) && bwidth != NB)
+ {
+ while(Mbands_gn > i_band )
+ {
+ noisepb[i_band] *= 2.0f;
+ i_band++;
+ }
+ }
+ else
+ {
+ while(pit_band_idx > i_band )
+ {
+ noisepb[i_band] /= 2.0f;
+ i_band++;
+ }
+ }
+ }
+ }
+
+ if ( (coder_type == INACTIVE || noise_lev >= NOISE_LEVEL_SP3) )
+ {
+ for( i_band = 9; i_band < Mbands_gn; i_band++ )
+ {
+ noisepb[i_band] *= 1.15f;
+ }
+ }
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------*
+ * Apply_NoiseFill()
+ *
+ *
+ *-------------------------------------------------------------------*/
+
+static void Apply_NoiseFill(
+ float *exc_diffQ, /* i/o: Noise per band */
+ short *seed_tcx, /* i : Seed for noise */
+ const float *noisepb, /* i : Noise per band */
+ const short Diff_len, /* i : number of bin before cut-off frequency */
+ const short Mbands_gn, /* i : number of bands */
+ const short coder_type, /* i : coder type */
+ const short *freq_nsbin_per_band /* i : bin per bands tables */
+)
+{
+ short StartBin, NB_Qbins, i_band;
+ StartBin = 0;
+ NB_Qbins = 0;
+
+ for( i_band = 0; i_band < Mbands_gn; i_band++ )
+ {
+ StartBin += NB_Qbins;
+ NB_Qbins = freq_nsbin_per_band[i_band];
+
+ if( Diff_len < L_FRAME )
+ {
+ gs_noisf( StartBin, NB_Qbins, noisepb[i_band], exc_diffQ, exc_diffQ, seed_tcx, coder_type );
+ }
+ }
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------*
+ * freq_dnw_scaling()
+ *
+ *
+ *-------------------------------------------------------------------*/
+
+void freq_dnw_scaling(
+ const short cor_strong_limit, /* i : HF correlation */
+ const short coder_type, /* i : coder type */
+ const short noise_lev, /* i : Noise level */
+ const long core_brate, /* i : Core bitrate */
+ float fy_norm[] /* i/o: Frequency quantized parameter */
+)
+{
+ float sc_dyn;
+ short start_sc, i;
+
+ sc_dyn = 1.0f;
+ start_sc = L_FRAME;
+
+ if( core_brate <= ACELP_8k00 && coder_type == INACTIVE )
+ {
+ sc_dyn *= .15f;
+ start_sc = 64;
+ }
+ else if( coder_type == INACTIVE )
+ {
+ sc_dyn *= .25f;
+ start_sc = 80;
+ }
+ else
+ {
+ sc_dyn = (float)(NOISE_LEVEL_SP3 - noise_lev)/10.0f + 0.4f;
+ start_sc = 112 + (NOISE_LEVEL_SP3 - noise_lev) * 16;
+
+ if( noise_lev == NOISE_LEVEL_SP0 )
+ {
+ start_sc = L_FRAME;
+ }
+ }
+
+ for(i = start_sc; i < L_FRAME; i++)
+ {
+ fy_norm[i] *= sc_dyn;
+ }
+
+ if( (core_brate < ACELP_13k20 && cor_strong_limit == 0) || core_brate < ACELP_9k60)
+ {
+ for(i = 160; i < L_FRAME; i++)
+ {
+ if( fy_norm[i] > 1.0f )
+ {
+ fy_norm[i] = 1.0f;
+ }
+
+ if( fy_norm[i] < -1.0f )
+ {
+ fy_norm[i] = -1.0f;
+ }
+ }
+ }
+ else if( core_brate < ACELP_22k60 )
+ {
+ for(i = 160; i < L_FRAME; i++)
+ {
+ if( fy_norm[i] > 1.5f )
+ {
+ fy_norm[i] = 1.5f;
+ }
+
+ if( fy_norm[i] < -1.5f )
+ {
+ fy_norm[i] = -1.5f;
+ }
+ }
+ }
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------*
+ * Decreas_freqPeak()
+ *
+ *
+ *-------------------------------------------------------------------*/
+
+static void Decreas_freqPeak(
+ float *lsf_new, /* i : ISFs at the end of the frame */
+ float *exc_diffQ, /* i/o: frequency coefficients of per band */
+ float thr_rat /* i : threshold of ratio between consecutive lsf_new_diff */
+)
+{
+ short i, j, k;
+ short last_bin = 0;
+ short pos = 0;
+ float *src;
+ float avrg, max;
+ float lsf_new_diff[M];
+ lsf_new_diff[0] = 0; /* prevent unitialized value */
+ for(j=1; j<(M-1); j++)
+ {
+ lsf_new_diff[j] = lsf_new[j] - lsf_new[j-1];
+ }
+
+ avrg = 0.0f;
+ /* This is to prevent a possible div by 0 in the '*(src) = (*src > 0) ?...'
+ loop. The value of 'max' is not important because it will be mutiplied
+ by 'avrg' and the result will be close to 0. The 'fabs(*src)/max'
+ div by 0 error will be avoided. */
+ max = 0.001f;
+ for(i=160; i max)
+ {
+ max = (float)fabs(exc_diffQ[i]);
+ pos = i;
+ }
+ avrg += (float)fabs(exc_diffQ[i]);
+ }
+ avrg /= 96;
+ last_bin = M-1; /* When the search is false, should equate the end of the vector, not the beginning */
+ for(i=0; i<(M-1); i++)
+ {
+ if(lsf_new[i] > 4000)
+ {
+ last_bin = i;
+ break;
+ }
+ }
+
+ for(i=last_bin; i<14; i++)
+ {
+ if( lsf_new_diff[i] < thr_rat*lsf_new_diff[i-1] )
+ {
+ src = &exc_diffQ[(i-1)*16];
+ for(j=0; j<2; j++)
+ {
+ for(k=0; k<16; k++)
+ {
+ if(fabs(*src) > 2.0f*avrg)
+ {
+ *(src) = (*src > 0) ? (float)(avrg*(2.0f-fabs(*src)/max)) : (float)(-avrg*(2.0f-fabs(*src)/max));
+ }
+ src++;
+ }
+ }
+ }
+ }
+
+ if(fabs(exc_diffQ[pos]) == max && max > 4.0f*avrg)
+ {
+ for(i=pos-1; i 8 || Diff_len != 0) && last_coder_type == AUDIO)
+ {
+ MAX_Bin = 10;
+ bwe_flag = 1;
+ }
+ else
+ {
+ MAX_Bin = 15;
+ }
+
+ last_bin_tmp = last_bin;
+ if(last_bin < MAX_Bin)
+ {
+ last_bin = MAX_Bin;
+ }
+ last_bin += 1;
+ }
+ else
+ {
+ last_bin = MBANDS_GN;
+ last_bin_tmp = last_bin;
+ }
+
+ if( bfi )
+ {
+ set_f( noisepb, 0.4f, MBANDS_GN );
+ }
+ else
+ {
+ EstimateNoiseLevel( noisepb, core_brate, Diff_len, last_bin, coder_type, noise_lev, pit_band_idx, last_bin_tmp, bwidth );
+ }
+
+ if( exc_wo_nf != NULL )
+ {
+ mvr2r( exc_diffQ, exc_wo_nf, L_FRAME );
+ }
+
+ if( GSC_noisy_speech && !bfi )
+ {
+ set_f( noisepb, 0.1f, MBANDS_GN );
+ }
+
+ Apply_NoiseFill( exc_diffQ, seed_tcx, noisepb, Diff_len, last_bin, coder_type, mfreq_bindiv );
+
+ /*--------------------------------------------------------------------------------------*
+ * Quantize average gain
+ * Substract Q averaged gain
+ * VQ of remaining gain per band
+ *--------------------------------------------------------------------------------------*/
+
+ if( core_brate == ACELP_8k00 && bwidth != NB )
+ {
+ Ener_per_band_comp( exc_diffQ, Ener_per_bd_yQ, last_bin+1, 0 );
+ }
+ else
+ {
+ Ener_per_band_comp( exc_diffQ, Ener_per_bd_yQ, MBANDS_GN, 1 );
+
+ if( nb_subfr < 4 )
+ {
+ for( i = L_FRAME-16; i < L_FRAME; i++ )
+ {
+ exc_diffQ[i] *= (0.067f * i - 15.0f);
+ }
+ }
+ }
+ /*--------------------------------------------------------------------------------------*
+ * Check potential energy excitation overshoot
+ *--------------------------------------------------------------------------------------*/
+ if( bfi )
+ {
+ if (GSC_noisy_speech == 0 && coder_type > UNVOICED) /* Here coder_type == last_coder_type because of the bfi */
+ {
+ for( i=0; i end)
+ {
+ *src-- = *dst--;
+ }
+
+ if( (bitallocation_exc[0] != 0 || bitallocation_exc[1] != 0) && core_brate == ACELP_8k00 )
+ {
+ exc_diffQ[160] = 0.0f;
+ }
+
+ envelop_modify(exc_diffQ, seed_tcx, last_bin, Ener_per_bd_iQ);
+
+ mvr2r( &exc_diffQ[last_bin*16], &exc_dct_in[last_bin*16], L_FRAME-last_bin*16 );
+ }
+
+ if( nb_subfr < 4 )
+ {
+ for( i = L_FRAME-16; i < L_FRAME; i++ )
+ {
+ exc_dct_in[i] *= (0.067f*i-15.f);
+ }
+ }
+
+ if( ener < 2*(*last_ener) && ener > 0.5f*(*last_ener) )
+ {
+ length_bin = 6;
+ if(last_coder_type != AUDIO)
+ {
+ set_s( last_bitallocation_band, 0, 6 );
+ mvr2r( &exc_dct_in[(4+length_bin)*16], &last_exc_dct_in[(4+length_bin)*16], length_bin*16 );
+ }
+
+ for(i=4; i<(4+length_bin); i++)
+ {
+ if( !(bitallocation_band[i] == 0 && last_bitallocation_band[i-4] == 0))
+ {
+ src = &exc_dct_in[(i+length_bin)*16];
+ dst = &last_exc_dct_in[(i+length_bin)*16];
+ for(j=0; j<16; j++)
+ {
+ if(fabs(*src) > 3.0f*fabs(*dst))
+ {
+ *src = (*src > 0) ? (float)(0.5f*(*src + fabs(*dst))) : (float)(0.5f*(*src - fabs(*dst)));
+ }
+ else if(fabs(*dst) > 3.0f*fabs(*src))
+ {
+ *src = (*src > 0) ? (float)(0.7f*(*src) + 0.3f*fabs(*dst)) : (float)(0.7f*(*src) - 0.3f*fabs(*dst));
+ }
+ src++;
+ dst++;
+ }
+ }
+ }
+ }
+
+ if( bwe_flag == 1 )
+ {
+ Decreas_freqPeak( lsf_new, exc_dct_in, 0.3f );
+ }
+ else
+ {
+ Decreas_freqPeak( lsf_new, exc_dct_in, 0.5f );
+ }
+ }
+
+ mvr2r( &exc_dct_in[64], &last_exc_dct_in[64], L_FRAME-64 );
+ mvs2s( &bitallocation_band[4], last_bitallocation_band, 6 );
+ *last_ener = ener;
+
+ return;
+}
diff --git a/lib_com/gs_preech.c b/lib_com/gs_preech.c
new file mode 100644
index 0000000000000000000000000000000000000000..39f1add36d0948218ba3f653d050794ccc2601df
--- /dev/null
+++ b/lib_com/gs_preech.c
@@ -0,0 +1,95 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include
+#include "wmc_auto.h"
+#include "options.h"
+#include "cnst.h"
+#include "rom_com.h"
+#include "prot.h"
+
+
+/*-------------------------------------------------------------------*
+ * Local constants
+ *-------------------------------------------------------------------*/
+
+#define ATT_LENGHT 64
+#define ATT_SEG_LEN (L_FRAME/ATT_LENGHT)
+#define INV_ATT_SEG_LEN (1.0f/ATT_SEG_LEN)
+#define INV_L_FRAME (1.0f/L_FRAME)
+
+
+/*-------------------------------------------------------------------*
+ * pre_echo_att()
+ *
+ * Attenuation of the pre-echo when encoder specifies an attack
+ *-------------------------------------------------------------------*/
+
+void pre_echo_att(
+ float *Last_frame_ener, /* i/o: Energy of the last frame */
+ float *exc, /* i/o: Excitation of the current frame */
+ const short attack_flag, /* i : flag signalling attack encoded by AC mode (GSC) */
+ const short last_coder_type /* i : Last coder type */
+)
+{
+ float etmp;
+ float etmp1;
+ float finc[ATT_LENGHT], ratio;
+ short attack_pos, i;
+
+ if ( attack_flag == 1 && last_coder_type == AUDIO)
+ {
+ /*-------------------------------------------------------------------------*
+ * Find where the onset (attack) occurs by computing the energy per section
+ * The inverse weighting aims to favor the first maxima in case of
+ * gradual onset
+ *-------------------------------------------------------------------------*/
+
+ for(i = 0; i < ATT_LENGHT; i++)
+ {
+ finc[i] = sum2_f( exc + i*ATT_SEG_LEN, ATT_SEG_LEN )*((float)(ATT_LENGHT-i)/(ATT_LENGHT));
+ }
+
+ etmp = -1;
+ attack_pos = maximum(finc, ATT_LENGHT, &etmp);
+
+ /* Scaled the maximum energy and allowed 6 dB increase*/
+ etmp *= INV_ATT_SEG_LEN;
+ etmp1 = etmp;
+ *Last_frame_ener *= 4.0f;
+
+ /* If the maximum normalized energy > last frame energy + 6dB */
+ if( etmp > *Last_frame_ener && attack_pos > 0 )
+ {
+ /* Find the average energy before the attack */
+ etmp = sum_f( finc, attack_pos ) + 0.01f;
+ etmp /= (attack_pos*ATT_SEG_LEN);
+
+ /* Find the correction factor and apply it before the attack */
+ ratio = (float)sqrt(*Last_frame_ener/etmp);
+
+
+ /* Pre-echo atttenuation should never increase the energy */
+ ratio = min(ratio, 1.0f);
+ for(i = 0; i < attack_pos*ATT_SEG_LEN; i++)
+ {
+ exc[i] *= ratio;
+ }
+ }
+ *Last_frame_ener = etmp1;
+ }
+ else
+ {
+ /*-------------------------------------------------------*
+ * In normal cases, just compute the energy of the frame
+ *-------------------------------------------------------*/
+
+ etmp = sum2_f( exc, L_FRAME ) + 0.01f;
+
+ etmp *= INV_L_FRAME;
+ *Last_frame_ener = etmp;
+ }
+
+ return;
+}
diff --git a/lib_com/guided_plc_util.c b/lib_com/guided_plc_util.c
new file mode 100644
index 0000000000000000000000000000000000000000..9fe04ee6e2c897d4e41155d3a3b5877842e1ad3b
--- /dev/null
+++ b/lib_com/guided_plc_util.c
@@ -0,0 +1,302 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include "prot.h"
+#include "wmc_auto.h"
+#include "rom_com.h"
+
+
+/*-------------------------------------------------------------------*
+ * Local function
+ *-------------------------------------------------------------------*/
+
+static void reorder_lsfs( float *lsf, float min_dist, const short n, int sr_core );
+
+
+/*-------------------------------------------------------------------*
+ * getLookAheadResSig()
+ *
+ *
+ *-------------------------------------------------------------------*/
+
+void getLookAheadResSig(
+ float *speechLookAhead,
+ const float *A,
+ float *res,
+ int L_frame,
+ int L_subfr,
+ int m,
+ int numSubFrame
+)
+{
+ const float *p_A;
+ short i_subfr;
+ short subfr_len[2] = { 0 };
+
+ subfr_len[0] = L_subfr;
+ subfr_len[1] = L_frame < L_FRAME16k ? (short)(0.75*L_subfr) : L_subfr;
+
+ p_A = A;
+ for (i_subfr=0; i_subfrlsf_adaptive_mean[i] = ( decState->lsfoldbfi1[i]+ decState->lsfoldbfi0[i]+lsf[i])/3;
+ decState->lsfoldbfi1[i] = decState->lsfoldbfi0[i];
+ decState->lsfoldbfi0[i] = lsf[i];
+ }
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------*
+ * getConcealedLP()
+ *
+ *
+ *-------------------------------------------------------------------*/
+
+void getConcealedLP(
+ HANDLE_PLC_ENC_EVS memDecState,
+ float *AqCon,
+ const float lsfBase[],
+ const float sr_core,
+ int last_good,
+ int L_frame
+)
+{
+ float *lsf = memDecState->lsf_con;
+ float lsp[(NB_DIV+1)*M];
+ short k;
+
+ dlpc_bfi( L_frame, &lsf[0], memDecState->lsfold, last_good,
+ 1 /* assumes packet loss */ , memDecState->mem_MA, memDecState->mem_AR, &(memDecState->stab_fac), memDecState->lsf_adaptive_mean,
+ 1, NULL, 0, NULL, NULL, lsfBase);
+
+ mvr2r( memDecState->lspold, lsp, M );
+
+ for ( k=0; k<1; k++ )
+ {
+ lsf2lsp(&lsf[k*M], &lsp[(k+1)*M], M, sr_core);
+ }
+
+ int_lsp( L_FRAME, &lsp[0], &lsp[M], AqCon, M, interpol_frac_12k8, 0 );
+
+ return;
+}
+
+/*-------------------------------------------------------------------*
+ * RecLpcSpecPowDiffuseLc()
+ *
+ *
+ *-------------------------------------------------------------------*/
+
+void RecLpcSpecPowDiffuseLc(
+ float *lspq,
+ float *lsp_old,
+ float *lsfq,
+ Decoder_State *st
+ , int reset_q
+)
+{
+ const float *means;
+ float lsf_old[M];
+ short i;
+
+
+ means = PlcGetlsfBase ( st->lpcQuantization, st->narrowBand, st->sr_core );
+
+ mvr2r( st->lsf_old, lsf_old, M );
+
+ modify_lsf( lsf_old, M, st->sr_core
+ , reset_q
+ );
+
+ lsf2lsp(lsf_old, lsp_old, M, st->sr_core);
+
+ if (reset_q)
+ {
+ for (i=0; imem_MA[i] + means[i];
+ }
+
+ v_sort( lsfq, 0, M - 1 );
+
+ reorder_lsfs( lsfq, LSF_GAP, M, st->sr_core);
+
+ lsf2lsp(lsfq, lspq, M, st->sr_core);
+ }
+ else
+ {
+ modify_lsf( lsfq, M, st->sr_core, reset_q );
+
+ lsf2lsp(lsfq, lspq, M, st->sr_core);
+ }
+
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------*
+ * modify_lsf()
+ *
+ *
+ *-------------------------------------------------------------------*/
+
+void modify_lsf(
+ float *lsf,
+ const short n,
+ const int sr_core
+ , int reset_q
+)
+{
+ short i, k;
+ float gap;
+ float th;
+
+ th = 1900;
+
+ if (reset_q==0)
+ {
+ th = 800;
+ }
+
+ if(sr_core == 16000)
+ {
+ th *= 1.25;
+ }
+
+
+ i = 1;
+
+ while(lsf[i] < th && i < n)
+ {
+ i++;
+ }
+ gap = lsf[i - 1] / i;
+
+ for(k = 0; k < i - 1; k++)
+ {
+ lsf[k] = gap * (k + 1);
+ }
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------*
+ * reorder_lsfs()
+ *
+ *
+ *-------------------------------------------------------------------*/
+
+static void reorder_lsfs(
+ float *lsf, /* i/o: vector of lsfs in the frequency domain (0..0.5)*/
+ float min_dist, /* i : minimum required distance */
+ const short n, /* i : LPC order */
+ int sr_core
+)
+{
+ short i;
+ float lsf_min;
+ float lsf_max;
+ float fac;
+ float th1, th2;
+
+ th1 = 1000.0f;
+ th2 = 1900.0f;
+
+
+ if(sr_core == 16000)
+ {
+ min_dist *= 1.25;
+ th1 *= 1.25;
+ th2 *= 1.25;
+ }
+
+ /*-----------------------------------------------------------------*
+ * Verify the LSF ordering and minimum GAP
+ *-----------------------------------------------------------------*/
+ fac = 3.0;
+
+ lsf_min = min_dist * fac;
+ for (i = 0; i < n; i++)
+ {
+
+ if (lsf[i] > th1)
+ {
+ fac = 2.0;
+ }
+ else
+ {
+ if (lsf[i] > 1900.0)
+ {
+ fac = 1.0;
+ }
+ }
+
+ if (lsf[i] < lsf_min)
+ {
+ lsf[i] = lsf_min;
+ }
+
+ lsf_min = lsf[i] + min_dist * fac;
+ }
+
+ /*------------------------------------------------------------------------------------------*
+ * Reverify the LSF ordering and minimum GAP in the reverse order (security)
+ *------------------------------------------------------------------------------------------*/
+
+ lsf_max = (float)(sr_core)/2.0f - min_dist * fac;
+
+ if( lsf[n-1] > lsf_max ) /* If danger of unstable filter in case of resonance in HF */
+ {
+ for (i = n-1; i >=0; i--) /* Reverify the minimum LSF gap in the reverse sens */
+ {
+
+ if (lsf[i] <= th2)
+ {
+ fac = 2.0;
+ }
+ else
+ {
+ if (lsf[i] <= th1)
+ {
+ fac = 3.0;
+ }
+ }
+
+ if (lsf[i] > lsf_max)
+ {
+ lsf[i] = lsf_max;
+ }
+
+ lsf_max = lsf[i] - min_dist * fac;
+ }
+ }
+
+ return;
+}
diff --git a/lib_com/hp50.c b/lib_com/hp50.c
new file mode 100644
index 0000000000000000000000000000000000000000..412ae766db3c13e100ad5d1478ef799022c598db
--- /dev/null
+++ b/lib_com/hp50.c
@@ -0,0 +1,106 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include
+#include "wmc_auto.h"
+#include "typedef.h"
+#include "options.h"
+#include "prot.h"
+
+
+#define WMC_TOOL_SKIP
+
+
+/*
+ * hp20
+ *
+ * Function:
+ * 2nd order high pass filter with nominal cut off frequency at 20 Hz.
+ *
+ * Returns:
+ * void
+ */
+
+void hp20(Float32 signal[], Word32 lg, Float32 mem[], Word32 fs)
+{
+ Word16 i;
+ Float32 x0, x1, x2, y0, y1, y2;
+ Float32 a1, a2, b1, b2;
+
+
+
+ y1 = mem[0];
+ y2 = mem[1];
+ x0 = mem[2];
+ x1 = mem[3];
+
+ if (fs == 8000)
+ {
+ /* hp filter 20Hz at 3dB for 8000KHz input sampling rate
+ [b,a] = butter(2, 20.0/4000.0, 'high');
+ b = [0.988954248067140 -1.977908496134280 0.988954248067140]
+ a =[1.000000000000000 -1.977786483776764 0.978030508491796]*/
+ a1 = 1.977786483776764f;
+ a2 = -0.978030508491796f;
+ b1 = -1.977908496134280f;
+ b2 = 0.988954248067140f;
+
+ }
+ else if (fs==16000)
+ {
+ /* hp filter 20Hz at 3dB for 16000KHz sampling rate
+ [b,a] = butter(2, 20.0/8000.0, 'high');
+ b =[ 0.994461788958195 -1.988923577916390 0.994461788958195]
+ a =[1.000000000000000 -1.988892905899653 0.988954249933127] */
+ a1 = 1.988892905899653f;
+ a2 = -0.988954249933127f;
+ b1 = -1.988923577916390f;
+ b2 = 0.994461788958195f;
+
+ }
+ else if (fs==32000)
+ {
+ /* hp filter 20Hz at 3dB for 32000KHz sampling rate
+ [b,a] = butter(2, 20.0/16000.0, 'high');
+ b =[0.997227049904470 -1.994454099808940 0.997227049904470]
+ a =[1.000000000000000 -1.994446410541927 0.994461789075954]*/
+ a1 = 1.994446410541927f;
+ a2 = -0.994461789075954f;
+ b1 = -1.994454099808940f;
+ b2 = 0.997227049904470f;
+
+
+ }
+ else
+ {
+ /* hp filter 20Hz at 3dB for 48000KHz sampling rate
+ [b,a] = butter(2, 20.0/24000.0, 'high');
+ b =[ 0.998150511190452 -1.996301022380904 0.998150511190452]
+ a =[1.000000000000000 -1.996297601769122 0.996304442992686]*/
+ a1 = 1.996297601769122f;
+ a2 = -0.996304442992686f;
+ b1 = -1.996301022380904f;
+ b2 = 0.998150511190452f;
+
+ }
+
+ for(i = 0; i < lg; i++)
+ {
+ x2 = x1;
+ x1 = x0;
+ x0 = signal[i];
+ y0 = (y1*a1) + (y2*a2) + (x0*b2) + (x1*b1) + (x2*b2);
+ signal[i] = y0;
+ y2 = y1;
+ y1 = y0;
+ }
+
+ mem[0] = ((y1 > 1e-10) | (y1 < -1e-10)) ? y1 : 0;
+ mem[1] = ((y2 > 1e-10) | (y2 < -1e-10)) ? y2 : 0;
+ mem[2] = ((x0 > 1e-10) | (x0 < -1e-10)) ? x0 : 0;
+ mem[3] = ((x1 > 1e-10) | (x1 < -1e-10)) ? x1 : 0;
+
+
+ return;
+}
diff --git a/lib_com/hq2_bit_alloc.c b/lib_com/hq2_bit_alloc.c
new file mode 100644
index 0000000000000000000000000000000000000000..0e2018853a76fe8dcecbce241ce6f393196cfedd
--- /dev/null
+++ b/lib_com/hq2_bit_alloc.c
@@ -0,0 +1,993 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include
+#include "wmc_auto.h"
+#include "options.h"
+#include "prot.h"
+#include "rom_com.h"
+#include "basop_util.h"
+#include "basop_mpy.h"
+#include "stl.h"
+
+#define WMC_TOOL_SKIP
+
+/*-------------------------------------------------------------------
+ * Local constants
+ *-------------------------------------------------------------------*/
+
+#define MIN_BITS_FIX 0
+#define HQ_16k40_BIT (HQ_16k40/50) /* 16400/50=328 , FOR FIX TMP */
+#define C1_QRk (1< 0 )
+ {
+ be_sum_fx = add(be_sum_fx, y_index_fx[k]);
+ }
+ }
+ QBavg = 0;
+ move16();
+
+ /*Ravg = (float) be_sum/be_cnt;*/
+ Ravg_fx = 0;
+ move16();
+ QRavg = 0;
+ move16();
+ IF( be_cnt_fx != 0x0 )
+ {
+ exp_normn = norm_s(be_sum_fx);
+ exp_normn = sub(exp_normn, 1);
+ exp_normd = norm_s(be_cnt_fx);
+ Ravg_fx = div_s(shl(be_sum_fx, exp_normn), shl(be_cnt_fx, exp_normd));
+
+ Ravg_fx = shr(Ravg_fx, 2); /* safe shift */
+ QRavg = add(sub(exp_normn, exp_normd), 15-2);
+ }
+
+ enr_diffcnt_fx = 0;
+ move16();
+ th_5_fx = shl(5, QRavg);
+ FOR (j = 0; j < be_cnt_fx; j++)
+ {
+ IF( sub(abs_s(sub(Ravg_fx, shl(y_index_fx[j], QRavg))), th_5_fx) > 0 )
+ {
+ enr_diffcnt_fx = add(enr_diffcnt_fx, 1);
+ }
+ }
+
+ IF( enr_diffcnt_fx > 0 )
+ {
+ scale_fact_fx = 11468;
+ move16(); /* 0.35f 11468.8(Q15) */
+ }
+ ELSE
+ {
+ scale_fact_fx = 19661;
+ move16(); /* 0.60f 19660.8(Q15) */
+ }
+
+ /* Bits allocation to individual SB's in a group based on Band Energies */
+ FOR (j = 0; j < be_cnt_fx; j++)
+ {
+ Rcnt_fx = add(i, 1);
+
+ /* Ravg = (float) be_sum/Rcnt; */
+ exp_normn = norm_s(be_sum_fx);
+ exp_normn = sub(exp_normn, 1);
+ exp_normd = norm_s(Rcnt_fx);
+ Ravg_fx = div_s(shl(be_sum_fx, exp_normn), shl(Rcnt_fx, exp_normd));
+ Ravg_fx = shr(Ravg_fx, 2); /* safe shift */
+ QRavg = add(sub(exp_normn, exp_normd), 15-2);
+
+ test();
+ if(be_sum_fx <= 0)
+ {
+ be_sum_fx = 1;
+ move16();
+ }
+
+ /* Bits_avg = (float) Bits/(be_sum+EPSILON); */
+ Bits_avg_fx = 0;
+ move16();
+ QBavg = 0;
+ move16();
+ IF ( Bits != 0 )
+ {
+ exp_normn = norm_s(Bits);
+ exp_normn = sub(exp_normn, 1);
+ exp_normd = norm_s(be_sum_fx);
+ Bits_avg_fx = div_s(shl(Bits, exp_normn), shl(be_sum_fx, exp_normd));
+ Bits_avg_fx = shr(Bits_avg_fx, 2); /* safe_shift */
+ QBavg = add(sub(exp_normn, exp_normd), 15-2);
+ }
+ FOR (k = 0; k <=i; k++)
+ {
+ IF(L_R_temp[k] > 0) /* Rtemp -> SWB_BWE_LR_QRk */
+ {
+ /* Allocate more bits to SB, if SB bandenergy is higher than average energy */
+ /* R_temp[k] = (float)( Bits_avg * y_index[k]+( scale_fact * (y_index[k] - Ravg))); */
+ L_temp1 = L_mult(Bits_avg_fx, y_index_fx[k]); /* QBavg+1 */
+ L_temp2 = L_mult(scale_fact_fx, sub(shl(y_index_fx[k], QRavg), Ravg_fx)); /* 15+QRavg+1 */
+ L_R_temp[k] = L_add(L_shr(L_temp1, sub(add(QBavg, 1), SWB_BWE_LR_QRk)), L_shr(L_temp2, sub(add(QRavg, 16), SWB_BWE_LR_QRk))); /* SWB_BWE_LR_QRk */
+ }
+ }
+ IF ( L_sub(L_R_temp[i], L_Bits_needed) < 0 )
+ {
+ L_R_temp[i] = 0x0L;
+ move32();
+
+ p2aflags_fx_ptr[index_fx[i]] = 0;
+ move16();
+
+ /* be_sum -= y_index[i]; */
+ be_sum_fx = sub(be_sum_fx, y_index_fx[i]);
+
+ i = sub(i, 1);
+ }
+ ELSE
+ {
+ BREAK;
+ }
+ }
+
+ /* Rearrange the bit allocation to align with original */
+ FOR ( k = 0 ; k < band_num_fx; k++ )
+ {
+ j = index_fx[k];
+ move16();
+ L_R_ptr[j] = L_R_temp[k];
+ move32();
+ }
+
+ return;
+}
+
+/*-------------------------------------------------------------------*
+ * hq2_bit_alloc_har()
+ *
+ * Bit allocation mechanism for HQ_HARMONIC mode
+ *-------------------------------------------------------------------*/
+
+void hq2_bit_alloc_har (
+ float *y, /* i : band energy of sub-vectors */
+ int B_fx, /* i : number of available bits */
+ short N_fx, /* i : number of sub-vectors */
+ Word32 *L_Rsubband,
+ short p2a_bands_fx,
+ long L_core_brate, /* i : core bit rate */
+ short p2a_flags_fx[],
+ short band_width_fx[]
+)
+{
+ Word16 i, j, k;
+
+ Word32 L_norm_sum; /* Qbe */
+ Word32 L_Ravg_sub[GRP_SB]; /* Qbe */
+ Word32 L_temp_band_energy[BANDS_MAX]; /* Qbe */
+
+ Word16 j_fx, k_fx, Bits_grp_fx[GRP_SB];
+
+ Word32 L_temp_band_energydiff[BANDS_MAX];
+ Word16 G1_BE_DIFF_POS_fx; /* Q0 */
+ Word32 L_G1_BE_DIFF_VAL; /* Qbe Word32 */
+ Word16 final_gr_fact_pos_fx, gmax_range_fx[2], temp_fx;
+ Word16 bits_fact_fx, bits_fact1_fx; /* Q? */
+ Word16 grp_rngmax_fx[2] = {0};
+ Word16 index_fx[NB_SWB_SUBBANDS_HAR], y_index_fx[NB_SWB_SUBBANDS_HAR], esthf_bits_fx, grp_bit_avg_fx, harmonic_band_fx;
+ Word32 L_norm_sum_avg;
+ Word32 L_norm_diff; /* Qbe */
+ Word16 bits_allocweigh_fx; /* Q15 */
+ Word16 grp_bound_fx[5];
+ Word32 L_grp_thr[GRP_SB]; /* not require Word32 precission */
+ Word16 lf_hf_ge_r_fx; /* Q15 */
+ Word32 L_avg_enhf_en_diff; /* Qbe */
+
+ Word16 B_norm_fx;
+
+ Word32 L_temp, L_temp2;
+ Word16 exp, frac;
+
+ Word32 L_THR1, L_THR2, L_THR3;
+
+ Word16 exp_norm;
+ Word16 norm_sum_fx;
+ Word16 Qns; /* Q value for norm_sum_fx */
+ Word16 Inv_norm_sum_fx; /* 1/norm_sum */
+ Word16 QIns; /* Q value for Inv_norm_sum_fx */
+
+ Word16 exp_normn, exp_normd;
+ Word16 div_fx;
+
+ Word16 Inv_p2a_bands_fx;
+ Word16 QIpb;
+
+ Word16 exp_shift;
+
+ Word32 L_y[BANDS_MAX];
+ for(i=0; i= 0x0L && sub(j_fx, grp_rngmax_fx[i]) < 0x0 )
+ {
+ test();
+ k_fx = add(k_fx, 1);
+ j_fx = add(j_fx, 1);
+ }
+
+ temp_fx = k_fx;
+ move16();
+ IF( sub(temp_fx, 1) > 0 )
+ {
+ FOR( temp_fx = 2; temp_fx <= k_fx ; )
+ {
+ IF( L_sub(L_temp_band_energy[gmax_range_fx[i]+temp_fx-1], L_temp_band_energy[gmax_range_fx[i]+temp_fx]) < 0 )
+ {
+ BREAK;
+ }
+ ELSE IF( L_sub(L_temp_band_energy[gmax_range_fx[i]+temp_fx-1], L_temp_band_energy[gmax_range_fx[i]+temp_fx]) >= 0 )
+ {
+ temp_fx = add(temp_fx, 1);
+ IF( sub(temp_fx, k_fx) > 0 )
+ {
+ temp_fx = sub(temp_fx, 1);
+ BREAK;
+ }
+ }
+ }
+
+ gmax_range_fx[i] = add(gmax_range_fx[i], temp_fx);
+ }
+ ELSE
+ {
+ gmax_range_fx[i] = add(gmax_range_fx[i], temp_fx);
+ }
+ }
+
+ grp_bound_fx[0] = 0;
+ move16();
+ FOR(i=1; i 0x0L )
+ {
+ L_Ravg_sub[i] = L_add(L_Ravg_sub[i], L_temp_band_energy[j]);
+ move32();
+ }
+ }
+ }
+
+ L_temp_band_energydiff[0] = L_temp_band_energy[0];
+ move32();
+ FOR ( j = 1; j < harmonic_band_fx; j++ )
+ {
+ L_temp_band_energydiff[j]= L_abs(L_sub(L_temp_band_energy[j], L_temp_band_energy[j-1]));
+ move32();
+ }
+
+ G1_BE_DIFF_POS_fx = 0;
+ move16();
+ L_G1_BE_DIFF_VAL = 0x0L;
+ move32();
+
+ FOR(j=1; j< harmonic_band_fx; j++)
+ {
+ IF( L_sub(L_temp_band_energydiff[j], L_G1_BE_DIFF_VAL) > 0 )
+ {
+ G1_BE_DIFF_POS_fx = j;
+ move16();
+ L_G1_BE_DIFF_VAL = L_temp_band_energydiff[j];
+ move32();
+ }
+ }
+
+ test();
+ test();
+ IF( sub(G1_BE_DIFF_POS_fx, gmax_range_fx[0] ) < 0 && G1_BE_DIFF_POS_fx > 0 )
+ {
+ final_gr_fact_pos_fx = 0;
+ move16();
+ }
+ ELSE IF ( sub(G1_BE_DIFF_POS_fx, gmax_range_fx[0]) >= 0 && sub(G1_BE_DIFF_POS_fx, gmax_range_fx[1] ) < 0 )
+ {
+ final_gr_fact_pos_fx = 1;
+ move16();
+ }
+ ELSE
+ {
+ final_gr_fact_pos_fx = 2;
+ move16();
+ }
+
+ test();
+ IF( final_gr_fact_pos_fx == 0 || sub(final_gr_fact_pos_fx, 1) == 0 )
+ {
+ IF( L_sub(L_core_brate, HQ_16k40 ) == 0 )
+ {
+ bits_fact_fx = BITS_FACT_1p10;
+ move16(); /* 1.10f; */ /* G1 */
+ bits_fact1_fx = BITS_FACT_0p92;
+ move16(); /* 0.92f; */ /* G3 */
+ }
+ ELSE
+ {
+ bits_fact_fx = BITS_FACT_1p05;
+ move16(); /* 1.05f; */ /* G1 */
+ bits_fact1_fx = BITS_FACT_0p97;
+ move16(); /* 0.97f; */ /* G3 */
+ }
+ }
+ ELSE
+ {
+ IF( L_sub(L_core_brate, HQ_16k40) == 0 )
+ {
+ bits_fact_fx = BITS_FACT_0p97;
+ move16(); /* 0.97f; */ /* G1 */
+ bits_fact1_fx = BITS_FACT_1p00;
+ move16(); /* 1.00f; */ /* G3 */
+ }
+ ELSE
+ {
+ bits_fact_fx = BITS_FACT_0p92;
+ move16(); /* 0.92f; */ /* G1 */
+ bits_fact1_fx = BITS_FACT_1p00;
+ move16(); /* 1.00f; */ /* G3 */
+ }
+ }
+
+ FOR ( i = 0; i < sub(N_fx, harmonic_band_fx); i++ )
+ {
+ y_index_fx[i] = extract_h(L_shl(L_temp_band_energy[harmonic_band_fx+i], sub(16, SWB_BWE_LR_Qbe)));
+ move16();
+ index_fx[i] = add(harmonic_band_fx, i);
+ move16();
+ }
+
+ reordvct(y_index_fx, sub(N_fx, harmonic_band_fx), index_fx);
+
+ /* Log2 */
+ L_temp = L_deposit_l(band_width_fx[index_fx[0]]);
+ exp = norm_l(L_temp);
+ frac = Log2_norm_lc(L_shl(L_temp, exp));
+ exp = sub(30, exp);
+ L_temp = L_Comp(exp, frac);
+ /* ceil */
+ if( L_and(0x0000ffff, L_temp) > 0 )
+ {
+ L_temp = L_add(L_temp, 0x00010000);
+ }
+ esthf_bits_fx = extract_h(L_temp);
+
+ L_grp_thr[0] = L_THR1;
+ move32();
+ L_grp_thr[1] = L_THR2;
+ move32();
+ L_grp_thr[2] = L_THR3;
+ move32();
+ L_grp_thr[3] = L_shl(L_deposit_l(esthf_bits_fx), SWB_BWE_LR_QRk);
+ move16();
+
+ L_norm_sum = 1;
+ move32();
+ FOR(i=0; i<3; i++)
+ {
+ L_norm_sum = L_add( L_norm_sum, L_Ravg_sub[i]);
+ move32();
+ }
+
+ /*reserve bits for HF coding */
+ L_temp = L_add(L_norm_sum, L_Ravg_sub[GRP_SB-1]);
+ exp_normn = norm_l(L_temp);
+ exp_normn = sub(exp_normn, 1);
+ exp_normd = norm_s(N_fx);
+
+ div_fx = div_l(L_shl(L_temp, exp_normn), shl(N_fx, exp_normd)); /* (Qbe+exp_normn)-(0+exp_normd)-1) */
+ L_norm_sum_avg = L_shr(L_deposit_h(div_fx), add(sub(exp_normn, exp_normd), 15)); /* -> Qbe */
+
+ exp_norm = norm_l(L_norm_sum);
+ norm_sum_fx = extract_h( L_shl(L_norm_sum, exp_norm) ); /* SWB_BWE_LR_Qbe+exp_norm-16 */
+ Qns = sub(add(SWB_BWE_LR_Qbe, exp_norm), 16);
+
+ Inv_norm_sum_fx = div_s( 0x4000 /* Q15 */ , norm_sum_fx );
+ QIns = sub(31, exp_norm); /* 14 - (14+exp_norm-16) + 15 */
+
+ grp_bit_avg_fx = div_s_ss(B_fx, GRP_SB); /* Q0 */
+
+ exp_normd = norm_s(p2a_bands_fx);
+ Inv_p2a_bands_fx = div_s(0x3fff, shl(p2a_bands_fx, exp_normd)); /* 14-exp_normd+15 */
+ QIpb = sub(29, exp_normd);
+
+ L_temp = L_shl(Mpy_32_16(L_Ravg_sub[GRP_SB-1], Inv_p2a_bands_fx), sub(SWB_BWE_LR_Qbe, sub(QIpb,1)));
+ L_norm_diff = L_sub(L_temp, L_norm_sum_avg); /* Qbe */
+
+ L_temp = Mpy_32_16(L_Ravg_sub[GRP_SB-1], sub(GRP_SB, 1)); /* Qbe+0+1 */
+ L_temp = Mpy_32_16(L_temp, Inv_norm_sum_fx); /* Qbe+1+QIpb+1 */
+ lf_hf_ge_r_fx = round_fx(L_shl(L_temp, sub(15+16, sub(add(SWB_BWE_LR_Qbe, QIns),30))));
+
+ exp_normn = norm_s(norm_sum_fx);
+ exp_normn = sub(exp_normn, 1);
+ exp_normd = norm_s(harmonic_band_fx);
+
+ div_fx = div_s(shl(norm_sum_fx, exp_normn), shl(harmonic_band_fx, exp_normd));
+ L_avg_enhf_en_diff = L_sub(L_temp_band_energy[index_fx[0]], L_shl(L_deposit_h(div_fx), sub(sub(SWB_BWE_LR_Qbe, (add(Qns,sub(exp_normn,exp_normd)))),31))); /* Qbe - (Qns+exp_normn-(exp_normd)+15) -16 */
+
+ IF( sub(lf_hf_ge_r_fx , 26214) > 0x0 && L_sub(L_avg_enhf_en_diff, (Word32)(8< 0x0L) /* 0.8=26214.4(Q15) 8.0f=131072(Qbe) */
+ {
+ bits_allocweigh_fx = 6554;
+ move16(); /* 0.2 6553.6(Q15) */
+ IF(L_norm_diff < 0x0L)
+ {
+ bits_allocweigh_fx = 13107;
+ move16(); /* 0.4 13107.2(Q15) */
+ }
+
+ /*allocate bits*/
+ /*Bits_grp[GRP_SB-1] = (short)min((grp_bit_avg/p2a_bands + bits_allocweigh*norm_diff),10);*/
+ L_temp = L_mult(grp_bit_avg_fx, Inv_p2a_bands_fx); /* Q0+QIpb+1 */
+ L_temp2 = Mpy_32_16(L_norm_diff, bits_allocweigh_fx); /* Qbe+Q15-15 */
+
+ L_temp = L_shr(L_temp, add(QIpb, 1));
+ L_temp = L_add(L_shl(L_temp,SWB_BWE_LR_Qbe), L_temp2);
+
+ Bits_grp_fx[GRP_SB-1] = extract_h(L_shl(L_temp, sub(16, SWB_BWE_LR_Qbe)));
+ Bits_grp_fx[GRP_SB-1] = s_min(Bits_grp_fx[GRP_SB-1], 10);
+
+ test();
+ if( sub(Bits_grp_fx[GRP_SB-1], esthf_bits_fx) < 0 )
+ {
+ Bits_grp_fx[GRP_SB-1] = 0;
+ move16();
+ }
+ B_fx = sub(B_fx, Bits_grp_fx[GRP_SB-1]);
+ }
+
+ exp_shift = sub(add(SWB_BWE_LR_Qbe, QIns), 47); /* (SWB_BWE_LR_Qbe+14+1+QIns-15-16) */
+ exp_norm = norm_s(B_fx);
+ B_norm_fx = shl(B_fx, exp_norm);
+ exp_shift = add(exp_shift, exp_norm);
+
+ IF( sub(final_gr_fact_pos_fx, 1) == 0 )
+ {
+ L_temp = Mpy_32_16(L_Ravg_sub[1], extract_h(L_mult(bits_fact_fx, B_norm_fx)));
+ L_temp = Mpy_32_16(L_temp, Inv_norm_sum_fx);
+ Bits_grp_fx[1] = extract_h(L_shr(L_temp, exp_shift));
+
+ L_temp = Mpy_32_16(L_Ravg_sub[2], extract_h(L_mult(bits_fact1_fx, B_norm_fx)));
+ L_temp = Mpy_32_16(L_temp, Inv_norm_sum_fx);
+ Bits_grp_fx[2] = extract_h(L_shr(L_temp, exp_shift));
+
+ Bits_grp_fx[0] = sub(sub(B_fx, Bits_grp_fx[1]), Bits_grp_fx[2]);
+ }
+ ELSE
+ {
+ L_temp = Mpy_32_16(L_Ravg_sub[0], extract_h(L_mult(bits_fact_fx, B_norm_fx)));
+ L_temp = Mpy_32_16(L_temp, Inv_norm_sum_fx);
+ Bits_grp_fx[0] = extract_h(L_shr(L_temp, exp_shift));
+
+ L_temp = Mpy_32_16(L_Ravg_sub[2], extract_h(L_mult(bits_fact1_fx, B_norm_fx)));
+ L_temp = Mpy_32_16(L_temp, Inv_norm_sum_fx);
+ Bits_grp_fx[2] = extract_h(L_shr(L_temp, exp_shift));
+
+ Bits_grp_fx[1] = sub(sub(B_fx, Bits_grp_fx[0]), Bits_grp_fx[2]);
+ }
+
+ IF( sub(Bits_grp_fx[2], THR2 ) < 0 )
+ {
+ Bits_grp_fx[1] = add(Bits_grp_fx[1], Bits_grp_fx[2]);
+ move16();
+ Bits_grp_fx[2] = 0;
+ move16();
+ }
+
+ FOR(i=0; i 0)
+ {
+ Bits2indvsb_fx( L_temp_band_energy, grp_bound_fx[i], grp_bound_fx[i+1] , Bits_grp_fx[i], L_grp_thr[i], L_Rsubband, p2a_flags_fx);
+ }
+ ELSE
+ {
+ set_val_Word32(L_Rsubband+grp_bound_fx[i], 0x0L, sub(grp_bound_fx[i+1], grp_bound_fx[i]));
+ IF( sub(i, GRP_SB-1) == 0 )
+ {
+ set_val_Word16(p2a_flags_fx+grp_bound_fx[i], 0, sub(grp_bound_fx[i+1], grp_bound_fx[i]));
+ }
+ }
+ }
+ return;
+}
+
+void hq2_bit_alloc (
+ const float band_energy[], /* i : band energy of each subband */
+ const short bands, /* i : total number of subbands in a frame */
+ Word32 L_Rk[], /* i/o: Bit allocation/Adjusted bit alloc. */
+ short *bit_budget_fx, /* i/o: bit bugdet */
+ short *p2a_flags, /* i : HF tonal indicator */
+ const Word16 weight_fx, /* i : weight (Q13) */
+ const short band_width[], /* i : Sub band bandwidth */
+ const short num_bits, /* i : available bits */
+ const short hqswb_clas, /* i : HQ2 class information */
+ const short bwidth, /* i : input bandwidth */
+ const short is_transient /* i : indicator HQ_TRANSIENT or not */
+)
+{
+ Word16 j, k;
+ Word16 tmp;
+ Word16 bit_budget_norm_fx;
+
+ Word32 L_Rcalc, L_Ravg, L_Rcalc1;
+
+ Word16 exp_normn, exp_normd;
+
+ Word16 Rcnt_fx;
+
+ Word16 div_fx;
+ Word16 Qdiv;
+
+ Word32 L_tmp;
+ Word16 tmp_fx;
+
+ Word32 L_maxxy;
+ Word16 maxdex_fx;
+ Word32 L_dummy;
+
+ Word16 bit_budget_temp_fx;
+
+ Word16 negflag;
+
+ Word32 L_THR1, L_THR2, L_THR3;
+
+ Word32 L_band_energy[BANDS_MAX];
+
+ for(k=0; k 0 )
+ {
+ L_Ravg = L_add(L_Ravg, L_shl(L_band_energy[k], sub(SWB_BWE_LR_QRk, SWB_BWE_LR_Qbe))); /* SWB_BWE_LR_QRk-SWB_BWE_LR_Qbe */
+ Rcnt_fx = add(Rcnt_fx, 1);
+ }
+ }
+ /* Ravg Qband_energy */
+
+ /*L_Ravg /= Rcnt; */
+ exp_normd = norm_l(L_Ravg);
+ exp_normd = sub(exp_normd, 1);
+ exp_normn = norm_s(Rcnt_fx);
+
+ tmp = shl(Rcnt_fx, exp_normn);
+ tmp = s_max(tmp,1);
+ IF ( L_Ravg > 0 )
+ {
+ div_fx = div_l(L_shl(L_Ravg, exp_normd), tmp); /* Qdiv = 14+exp_normd-(exp_normn)-1 */
+ }
+ ELSE
+ {
+ div_fx = div_l(L_shl(L_abs(L_Ravg), exp_normd), tmp); /* Qdiv = 14+exp_normd-(exp_normn)-1 */
+ div_fx = negate(div_fx);
+ }
+
+ /*Qdiv = QRk+exp_normd-(exp_normn)-1; */
+ Qdiv = sub(sub(add(SWB_BWE_LR_QRk, exp_normd), exp_normn), 1);
+
+ L_Ravg = L_shr(L_deposit_l(div_fx), sub(Qdiv, SWB_BWE_LR_QRk));
+
+ exp_normd = norm_s(*bit_budget_fx);
+ exp_normd = sub(exp_normd, 1);
+ bit_budget_norm_fx = shl(*bit_budget_fx, exp_normd);
+ div_fx = 0;
+ move16();
+
+ test();
+ IF( bit_budget_norm_fx > 0 && sub(bit_budget_norm_fx, tmp) < 0 )
+ {
+ div_fx = div_s(bit_budget_norm_fx, tmp);
+ }
+ Qdiv = add(sub(exp_normd, exp_normn), 15);
+
+ FOR (k = 0; k < bands; k++)
+ {
+ IF ( L_Rk[k] > 0)
+ {
+ /*Rk[k] = ((float) *bit_budget / Rcnt + weight * (band_energy[k] - Ravg)); */
+
+ L_tmp = Mpy_32_16(L_sub(L_shl(L_band_energy[k], sub(SWB_BWE_LR_QRk, SWB_BWE_LR_Qbe)), L_Ravg), weight_fx); /* SWB_BWE_LR_QRk + Q13 - 15 */
+ L_tmp = L_shl(L_tmp, 2); /* -> SWB_BWE_LR_QRk */
+
+ L_Rk[k] = L_add(L_shr(L_deposit_l(div_fx), sub(Qdiv, SWB_BWE_LR_QRk)) , L_tmp);
+ }
+ }
+
+ negflag = 0;
+ move16();
+ L_Rcalc = 0;
+ move32();
+ FOR (k = 0; k < bands; k++)
+ {
+ IF ( L_sub(L_Rk[k], MIN_BITS_FIX) < 0 )
+ {
+ L_Rk[k] = 0x0L;
+ move32();
+ negflag = 1;
+ move16();
+ }
+ L_Rcalc = L_add( L_Rcalc , L_Rk[k]); /*SWB_BWE_LR_QRk */
+ }
+
+ /* prune noiselike bands with low allocation */
+ IF ( sub(num_bits, HQ_16k40_BIT) <= 0 && negflag == 0)
+ {
+ L_maxxy = 0;
+ move32();
+ maxdex_fx = -1;
+ move16();
+ L_Rcalc = 0;
+ move32();
+
+ /* find worst under-allocation */
+ FOR (k = sub(bands, 1); k >= 0; k--)
+ {
+ /* dummy = ((float) min (band_width[k], max (12, band_width[k] / 4))) - Rk[k]; */
+ tmp_fx = s_min( band_width[k], s_max(12, shr( band_width[k], 2)));
+ L_dummy = L_sub(L_shl(L_deposit_l(tmp_fx), SWB_BWE_LR_QRk), L_Rk[k]) ; /*SWB_BWE_LR_QRk */
+ test();
+ test();
+ test();
+ IF ( p2a_flags[k] == 0 && L_sub(L_dummy, L_maxxy) > 0 && L_Rk[k] > 0 )
+ {
+ maxdex_fx = k;
+ move16();
+ L_maxxy = L_dummy;
+ move32();/*SWB_BWE_LR_QRk */
+ }
+ }
+
+ /* prune worst allocation and recalculate total allocation */
+ IF ( sub(maxdex_fx, -1) > 0)
+ {
+ L_Rk[maxdex_fx] = 0;
+ move32();
+ }
+ FOR (k = 0; k < bands; k++)
+ {
+ L_Rcalc = L_add(L_Rcalc, L_Rk[k]); /*SWB_BWE_LR_QRk */
+ }
+ }
+ test();
+ IF ( L_sub(L_Rcalc, L_Rcalc1) == 0 && sub(bwidth, SWB) == 0 )
+ {
+ /* Reallocate bits to individual subbands for HQ_NORMAL mode */
+ /* if bits allocated to subbands areless than predefined threshold */
+ IF( sub(hqswb_clas, HQ_NORMAL) == 0 && sub(num_bits, HQ_16k40_BIT) < 0 )
+ {
+ L_dummy = 0x0L;
+ move32();
+ FOR( k = 0; k < bands; k++ )
+ {
+ test();
+ test();
+ test();
+ test();
+ test();
+ IF( sub(k, 11) < 0 && L_sub(L_Rk[k], L_THR1) < 0 )
+ {
+ L_Rk[k] = 0x0L;
+ move32();
+ }
+ ELSE IF( sub(k, 11) >= 0 && sub(k, 16) < 0 && L_sub(L_Rk[k], L_THR2) < 0 )
+ {
+ L_Rk[k] = 0x0L;
+ move32();
+ }
+ ELSE IF( sub(k, 16) >= 0 && sub(k, bands ) < 0 && L_sub(L_Rk[k], L_THR3) < 0 )
+ {
+ L_Rk[k] = 0x0L;
+ move32();
+ }
+
+ L_dummy = L_add(L_dummy, L_Rk[k]);
+ }
+
+ IF( L_sub(L_dummy, L_Rcalc ) == 0 )
+ {
+ test();
+ IF( sub(hqswb_clas, HQ_NORMAL) == 0 && sub(num_bits, HQ_16k40_BIT) < 0)
+ {
+ bit_budget_temp_fx = *bit_budget_fx;
+ move16();
+ FOR( k=0; kBER_detect */
+ }
+ ELSE IF( sub(bit_budget_temp_fx, *bit_budget_fx ) == 0 )
+ {
+ BREAK;
+ }
+ }
+ ELSE
+ {
+ BREAK;
+ }
+ }
+ }
+ ELSE
+ {
+ BREAK;
+ }
+ }
+ ELSE IF ( L_sub(L_Rcalc, L_Rcalc1 ) == 0 && sub(bwidth, SWB) != 0)
+ {
+ BREAK;
+ }
+
+ L_Rcalc1 = L_Rcalc;
+ move32();
+
+ }
+ return;
+}
diff --git a/lib_com/hq2_core_com.c b/lib_com/hq2_core_com.c
new file mode 100644
index 0000000000000000000000000000000000000000..2b163f71d7f4ac94e816c68d726a85d7b177098b
--- /dev/null
+++ b/lib_com/hq2_core_com.c
@@ -0,0 +1,553 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include
+#include "wmc_auto.h"
+#include
+#include "options.h"
+#include "cnst.h"
+#include "rom_com.h"
+#include "prot.h"
+#include "basop_util.h"
+#include "basop_proto_func.h"
+
+/*--------------------------------------------------------------------------*
+ * mdct_spectrum_denorm()
+ *
+ *
+ *--------------------------------------------------------------------------*/
+
+void mdct_spectrum_denorm(
+ const int inp_vector[],
+ float y2[],
+ const short band_start[],
+ const short band_end[],
+ const short band_width[],
+ const float band_energy[],
+ const int npulses[],
+ const short bands,
+ const float ld_slope,
+ const float pd_thresh
+)
+{
+ short i, k;
+ float Eyy, gamma, pd, gain_tweak;
+
+ for (k = 0; k < bands; k++)
+ {
+ Eyy = 0;
+ for (i = band_start[k]; i <= band_end[k]; i++)
+ {
+ Eyy += (float) inp_vector[i] * inp_vector[i];
+ }
+
+ if (Eyy > 0.0f)
+ {
+ /* Set gamma to be pulse gain which results in perfect quantized subband energy */
+ gamma = (float) sqrt (pow (2.0f, band_energy[k]) / Eyy);
+
+ /* Adjust gamma based on pulse density (0 bit MSE gain estimator) */
+ pd = (float) npulses[k] / band_width[k];
+ if (pd < pd_thresh)
+ {
+ gain_tweak = (float) pow (2.0f, (ld_slope * log2_f (pd / pd_thresh)));
+ gamma *= gain_tweak;
+ }
+
+ for (i = band_start[k]; i <= band_end[k]; i++)
+ {
+ y2[i] = gamma * inp_vector[i];
+ }
+ }
+ }
+
+ return;
+}
+/*--------------------------------------------------------------------------*
+ * hq2_core_configure()
+ *
+ *
+ *--------------------------------------------------------------------------*/
+
+void hq2_core_configure(
+ const short frame_length, /* i : frame length */
+ const short num_bits, /* i : number of bits */
+ const short is_transient, /* i : transient flag */
+ short *bands,
+ short *length,
+ short band_width[],
+ short band_start[],
+ short band_end[],
+ Word32 *L_qint,
+ Word16 *eref_fx,
+ Word16 *bit_alloc_weight_fx,
+ short *gqlevs,
+ short *Ngq,
+ short *p2a_bands,
+ float *p2a_th,
+ float *pd_thresh,
+ float *ld_slope,
+ float *ni_coef,
+ float *ni_pd_th,
+ long bwe_br
+)
+{
+ const Xcore_Config *xcore_config;
+
+ short i, k;
+ short bands_sh;
+
+ if( frame_length == L_FRAME8k )
+ {
+ if( is_transient )
+ {
+ if (num_bits <= ACELP_7k20 / 50)
+ {
+ xcore_config = &xcore_config_8kHz_007200bps_short;
+ }
+ else if (num_bits <= ACELP_8k00 / 50)
+ {
+ xcore_config = &xcore_config_8kHz_008000bps_short;
+ }
+ else if (num_bits <= ACELP_13k20 / 50)
+ {
+ xcore_config = &xcore_config_8kHz_013200bps_short;
+ }
+ else
+ {
+ xcore_config = &xcore_config_8kHz_016400bps_short;
+ }
+ }
+ else
+ {
+ if (num_bits <= ACELP_7k20 / 50)
+ {
+ xcore_config = &xcore_config_8kHz_007200bps_long;
+ }
+ else if (num_bits <= ACELP_8k00 / 50)
+ {
+ xcore_config = &xcore_config_8kHz_008000bps_long;
+ }
+ else if (num_bits <= ACELP_13k20 / 50)
+ {
+ xcore_config = &xcore_config_8kHz_013200bps_long;
+ }
+ else
+ {
+ xcore_config = &xcore_config_8kHz_016400bps_long;
+ }
+ }
+ }
+ else if( frame_length == L_FRAME16k )
+ {
+ if( is_transient )
+ {
+ if (num_bits <= ACELP_13k20 / 50)
+ {
+ xcore_config = &xcore_config_16kHz_013200bps_short;
+ }
+ else
+ {
+ xcore_config = &xcore_config_16kHz_016400bps_short;
+ }
+ }
+ else
+ {
+ if (num_bits <= ACELP_13k20 / 50)
+ {
+ xcore_config = &xcore_config_16kHz_013200bps_long;
+ }
+ else
+ {
+ xcore_config = &xcore_config_16kHz_016400bps_long;
+ }
+ }
+ }
+ else /* (bwidth == SWB) */
+ {
+ if( is_transient )
+ {
+ if (bwe_br == ACELP_13k20)
+ {
+ xcore_config = &xcore_config_32kHz_013200bps_short;
+ }
+ else
+ {
+ xcore_config = &xcore_config_32kHz_016400bps_short;
+ }
+ }
+ else
+ {
+ if (bwe_br == ACELP_13k20)
+ {
+ xcore_config = &xcore_config_32kHz_013200bps_long;
+ }
+ else
+ {
+ xcore_config = &xcore_config_32kHz_016400bps_long;
+ }
+ }
+ }
+
+ *bands = xcore_config->bands;
+ *length = xcore_config->bw;
+ *L_qint = xcore_config->L_qint;
+ *eref_fx = xcore_config->eref_fx;
+ *bit_alloc_weight_fx = xcore_config->bit_alloc_weight_fx;
+ *gqlevs = xcore_config->gqlevs;
+ *Ngq = xcore_config->Ngq;
+
+ *p2a_bands = xcore_config->p2a_bands;
+ *p2a_th = xcore_config->p2a_th;
+
+ *pd_thresh = xcore_config->pd_thresh;
+ *ld_slope = xcore_config->ld_slope;
+ *ni_coef = xcore_config->ni_coef;
+ *ni_pd_th = xcore_config->ni_pd_th;
+
+ mvs2s (xcore_config->band_width, band_width, *bands);
+
+ /* Expand band_width[] table for short windows */
+ if( is_transient )
+ {
+ bands_sh = *bands;
+ *bands = NUM_TIME_SWITCHING_BLOCKS * bands_sh;
+ *length *= NUM_TIME_SWITCHING_BLOCKS;
+
+ for( i = 1; i <= 3; i++ )
+ {
+ for( k = 0; k < bands_sh; k++ )
+ {
+ band_width[i * bands_sh + k] = band_width[k];
+ }
+ }
+ }
+
+ /* Formulate band_start and band_end tables from band_width table */
+ band_start[0] = 0;
+ band_end[0] = band_width[0] - 1;
+ for( k = 1; k < *bands; k++ )
+ {
+ band_start[k] = band_start[k - 1] + band_width[k - 1];
+ band_end[k] = band_start[k] + band_width[k] - 1;
+ }
+
+
+ return;
+}
+
+/*--------------------------------------------------------------------------*
+ * reverse_transient_frame_energies()
+ *
+ *
+ *--------------------------------------------------------------------------*/
+
+void reverse_transient_frame_energies(
+ float band_energy[], /* o : band energies */
+ const short bands /* i : number of bands */
+)
+{
+ short k, k1, k2;
+ float be;
+
+ k1 = bands/4;
+ k2 = bands/2-1;
+ for( k = 0; k < bands/8; k++ )
+ {
+ be = band_energy[k1];
+ band_energy[k1] = band_energy[k2];
+ band_energy[k2] = be;
+ k1++, k2--;
+ }
+
+ k1 = 3*bands/4;
+ k2 = bands-1;
+ for( k = 0; k < bands/8; k++ )
+ {
+ be = band_energy[k1];
+ band_energy[k1] = band_energy[k2];
+ band_energy[k2] = be;
+ k1++, k2--;
+ }
+
+ return;
+}
+
+#define WMC_TOOL_SKIP
+void bit_allocation_second_fx(
+ Word32 *Rk,
+ Word32 *Rk_sort,
+ Word16 BANDS,
+ const Word16 *band_width,
+ Word16 *k_sort,
+ Word16 *k_num,
+ const Word16 *p2a_flags,
+ const Word16 p2a_bands,
+ const Word16 *last_bitalloc,
+ const Word16 input_frame
+)
+{
+ Word16 k, k2 = 0;
+ Word16 ever_bits[BANDS_MAX], ever_sort[BANDS_MAX];/*Q12 */
+ Word16 class_flag = 0;
+ Word16 rk_temp = 32767, ever_temp = 32767;/*Q12 */
+ Word16 exp;
+ Word16 tmp;
+ Word32 L_tmp;
+
+ for (k = 0; k < BANDS; k++)
+ {
+ if((( sub(k_sort[k],sub(BANDS,p2a_bands)) >= 0 )&&( sub(p2a_flags[k_sort[k]],1) == 0 )) ||
+ (( sub(k_sort[k],sub(BANDS,2)) >= 0 )&&( sub(last_bitalloc[sub(k_sort[k], sub(BANDS,2))], 1) == 0 )))
+ {
+ exp = norm_s(band_width[k_sort[k]]);
+ tmp = shl(band_width[k_sort[k]],exp);/*Q(exp) */
+ tmp = div_s(16384,tmp);/*Q(15+14-exp = 29-exp) */
+ L_tmp = Mult_32_16(Rk_sort[k],tmp);/* Q(16+29-exp-15 = 30-exp) */
+ tmp = sub(18,exp);
+ ever_bits[k] = extract_l(L_shr(L_tmp,tmp));/*Q12 */
+ if( sub(ever_bits[k],rk_temp) < 0 )
+ {
+ rk_temp = ever_bits[k];
+ k2 = k;
+ }
+ class_flag = 1;
+ }
+ }
+ if( class_flag ==0 || sub(input_frame,L_FRAME8k) == 0)
+ {
+ for(k = 0; k < BANDS; k++)
+ {
+ if( sub(k_sort[k],sub(BANDS,p2a_bands)) < 0 && Rk_sort[k] > 0 )
+ {
+ exp = norm_s(band_width[k_sort[k]]);
+ tmp = shl(band_width[k_sort[k]],exp);/*Q(exp) */
+ tmp = div_s(16384,tmp);/*Q(15+14-exp = 29-exp) */
+ L_tmp = Mult_32_16(Rk_sort[k],tmp);/* Q(16+29-exp-15 = 30-exp) */
+ tmp = sub(18,exp);
+ ever_sort[k] = extract_l(L_shr(L_tmp,tmp));/*Q12 */
+ IF(sub(ever_sort[k],ever_temp) < 0)
+ {
+ ever_temp = ever_sort[k];
+ k2 = k;
+ }
+ }
+ }
+ }
+
+ k_num[0] = k2;
+ if(sub(k_sort[k2],sub(BANDS,1)) == 0)
+ {
+ for (k = 0; k < BANDS; k++)
+ {
+ if(sub(k_sort[k],sub(k_sort[k2],1)) == 0)
+ {
+ k_num[1] = k;
+ }
+ }
+ }
+ else if(k_sort[k2] == 0)
+ {
+ for (k = 0; k < BANDS; k++)
+ {
+ if(sub(k_sort[k],add(k_sort[k2],1)) == 0)
+ {
+ k_num[1] = k;
+ }
+ }
+ }
+ else
+ {
+ if ( L_sub( Rk[sub(k_sort[k2],1)],Rk[add(k_sort[k2],1)] ) < 0 )
+ {
+ for (k = 0; k < BANDS; k++)
+ {
+ if(sub(k_sort[k],sub(k_sort[k2],1)) == 0)
+ {
+ k_num[1] = k;
+ }
+ }
+ }
+ else
+ {
+ for (k = 0; k < BANDS; k++)
+ {
+ if(sub(k_sort[k],add(k_sort[k2],1)) == 0)
+ {
+ k_num[1] = k;
+ }
+ }
+ }
+ }
+}
+#undef WMC_TOOL_SKIP
+
+/*--------------------------------------------------------------------------*
+ * spt_shorten_domain_pre()
+ *
+ * Compute shorten subband if previous frame has spectral peak.
+ *--------------------------------------------------------------------------*/
+
+void spt_shorten_domain_pre(
+ const short band_start[], /* i: Starting position of sub band */
+ const short band_end[], /* i: End position of sub band */
+ const short prev_SWB_peak_pos[], /* i: Spectral peak */
+ const short BANDS, /* i: total number of bands */
+ const long bwe_br, /* i: bitrate information */
+ short new_band_start[], /* o: Starting position of new shorten sub band */
+ short new_band_end[], /* o: End position of new shorten sub band */
+ short new_band_width[] /* o: new sub band bandwidth */
+)
+{
+ int j;
+ int k;
+ int kpos;
+
+ short new_band_width_half;
+ const short *p_bw_SPT_tbl; /* pointer of bw_SPT_tbl */
+
+ p_bw_SPT_tbl = bw_SPT_tbl[0];
+ if( bwe_br == HQ_16k40 )
+ {
+ p_bw_SPT_tbl = bw_SPT_tbl[1];
+ }
+
+ kpos = 0;
+ j = 0;
+ for(k=BANDS-SPT_SHORTEN_SBNUM; k band_end[k] )
+ {
+ new_band_end[j] = band_end[k];
+ new_band_start[j] = new_band_end[j] - (new_band_width[j] - 1);
+ }
+ }
+ else
+ {
+ new_band_width[j] = p_bw_SPT_tbl[j];
+
+ /*shorten the bandwidth for pulse resolution*/
+ new_band_width_half = new_band_width[j]/2;
+ new_band_start[j] = (band_start[k]+band_end[k])/2 - new_band_width_half;
+ new_band_end[j] = (band_start[k]+band_end[k])/2 + new_band_width_half;
+ }
+
+ kpos++;
+ j++;
+ }
+
+ return;
+}
+
+/*--------------------------------------------------------------------------*
+ * spt_shorten_domain_band_save()
+ *
+ * Store the original subband information
+ *--------------------------------------------------------------------------*/
+
+void spt_shorten_domain_band_save(
+ const short bands, /* i: total subband */
+ const short band_start[], /* i: starting position of subband */
+ const short band_end[], /* i: end position of subband */
+ const short band_width[], /* i: band width of subband */
+ short org_band_start[], /* o: starting position of subband */
+ short org_band_end[], /* o: end position of subband */
+ short org_band_width[] /* o: band width of subband */
+)
+{
+ int k;
+ int kpos;
+
+ kpos = 0;
+ for(k=bands-SPT_SHORTEN_SBNUM; k
+#include "wmc_auto.h"
+#include "options.h"
+#include "prot.h"
+
+/*--------------------------------------------------------------------------*
+ * hq2_noise_inject()
+ *
+ * HQ2 noise injection for WB signals
+ *--------------------------------------------------------------------------*/
+
+void hq2_noise_inject(
+ float y2hat[],
+ const short band_start[],
+ const short band_end[],
+ const short band_width[],
+ float Ep[],
+ float Rk[],
+ const int npulses[],
+ short ni_seed,
+ const short bands,
+ const short ni_start_band,
+ const short bw_low,
+ const short bw_high,
+ const float enerL,
+ const float enerH,
+ float last_ni_gain[],
+ float last_env[],
+ short *last_max_pos_pulse,
+ short *p2a_flags,
+ short p2a_bands,
+ const short hqswb_clas,
+ const short bwidth,
+ const long bwe_br
+)
+{
+ short i, j, k, ni_end_band, satur = 0, count[BANDS_MAX], max_pos_pulse, pos;
+ float ni_gain[BANDS_MAX], pd[BANDS_MAX], rand, peak[BANDS_MAX], fac, env[BANDS_MAX];
+ short sb = bands;
+
+ if( (hqswb_clas == HQ_HARMONIC || hqswb_clas == HQ_NORMAL) && (bwe_br == HQ_16k40 || bwe_br == HQ_13k20) && bwidth == SWB )
+ {
+ sb = (bwe_br == HQ_16k40) ? 19 : 17;
+ }
+
+ /* calculate the envelopes/ the decoded peak coeff./number of the decoded coeff./ the last subbands of the bit-allocated/saturation of bit-allocation */
+ ni_end_band = bands;
+ max_pos_pulse = bands;
+ for (k = ni_start_band; k < ni_end_band; k++)
+ {
+ pd[k] = (float) Rk[k] / band_width[k];
+ env[k] = (float)sqrt(Ep[k]/band_width[k]);
+
+ peak[k] = 0.0f;
+ count[k] = 0;
+ if(npulses[k] != 0)
+ {
+ for (i = band_start[k]; i <= band_end[k]; i++)
+ {
+ Ep[k] -= y2hat[i] * y2hat[i];
+ if( fabs(y2hat[i]) > peak[k])
+ {
+ peak[k] = (float)fabs(y2hat[i]);
+ }
+
+ if(y2hat[i] != 0)
+ {
+ count[k]++;
+ }
+ }
+
+ max_pos_pulse = k;
+ Ep[k] = Ep[k] > 0 ? (float)sqrt(Ep[k]/band_width[k]) : 0.0f;
+ }
+ else
+ {
+ Ep[k] = env[k];
+ }
+ }
+
+ for (k = ni_start_band; k < ni_end_band; k++)
+ {
+ /* calculate the noise gain */
+ satur = (pd[k] >= 0.8f) ? 1 : 0;
+ if (satur == 0 && Ep[k] > 0)
+ {
+ if(npulses[k] != 0)
+ {
+ if( bwidth == SWB )
+ {
+ if(hqswb_clas != HQ_TRANSIENT)
+ {
+ if(hqswb_clas == HQ_HARMONIC)
+ {
+ fac = (k <= sb) ? 6.0f*(1.5f - pd[k])*env[k]*Ep[k]/(peak[k]*peak[k]) : 1.5f*Ep[k]/peak[k];
+ }
+ else
+ {
+ fac = (k <= sb) ? 5.0f*(1.5f - pd[k])*Ep[k]/(peak[k]) : 4.0f*Ep[k]/peak[k];
+ }
+ }
+ else
+ {
+ fac = 1.1f;
+ }
+ }
+ else
+ {
+ fac = 20.0f*min(1.0f, (1.5f - pd[k]))*env[k]*Ep[k]/(peak[k]*peak[k]);
+ if(k > 1 && k < ni_end_band-1)
+ {
+ if(count[k+1] == 0 && env[k] > 0.5f*env[k+1] && env[k] < 2.0f*env[k-1])
+ {
+ fac = 1.5f*env[k+1]/env[k];
+ }
+ else if(count[k-1] == 0 && peak[k] > 2.0f*env[k])
+ {
+ fac = env[k-1]/env[k];
+ }
+ }
+
+ if(k >= ni_end_band - p2a_bands && bwidth == WB)
+ {
+ if(bw_low*enerH > bw_high*enerL && peak[k] < 2.0f*env[k])
+ {
+ fac *= (2.0f - Ep[k]/peak[k]);
+ }
+
+ if( p2a_flags[k] == 0 && fac > 0 )
+ {
+ fac *= min(1.25f*env[k]/(Ep[k]*fac), 1.5f);
+ }
+ }
+ }
+ }
+ else
+ {
+ fac = (hqswb_clas == HQ_HARMONIC && bwidth == SWB) ? 0.8f : 1.1f;
+ }
+
+ ni_gain[k] = fac * Ep[k];
+ }
+ else
+ {
+ ni_gain[k] = 0.0;
+ }
+
+ /* smooth the noise gain between the current frame and the previous frame */
+ pos = bwidth == SWB ? ni_end_band-1 : max(max_pos_pulse, *last_max_pos_pulse);
+
+ if(k <= pos)
+ {
+ if(k > 0 && k < ni_end_band-1)
+ {
+ if( (env[k] > 0.5f*last_env[k] && env[k] < 2.0f*last_env[k]) ||
+ (((env[k]+env[k-1]+env[k+1]) > 0.5f*(last_env[k]+last_env[k-1]+last_env[k+1])) &&
+ ((env[k]+env[k-1]+env[k+1]) < 2.0f*(last_env[k]+last_env[k-1]+last_env[k+1]))) )
+ {
+ if(ni_gain[k] > last_ni_gain[k])
+ {
+ ni_gain[k] = 0.2f*ni_gain[k] + 0.8f*last_ni_gain[k];
+ }
+ else
+ {
+ ni_gain[k] = 0.6f*ni_gain[k] + 0.4f*last_ni_gain[k];
+ }
+ }
+ }
+ else if (k == ni_end_band-1)
+ {
+ if( (env[k] > 0.5f*last_env[k] && env[k] < 2.0f*last_env[k]) ||
+ ((env[k]+env[k-1]) > 0.5f*(last_env[k]+last_env[k-1]) &&
+ (env[k]+env[k-1]) < 2.0f*(last_env[k]+last_env[k-1])) )
+ {
+ if(ni_gain[k] > last_ni_gain[k])
+ {
+ ni_gain[k] = 0.2f*ni_gain[k] + 0.8f*last_ni_gain[k];
+ }
+ else
+ {
+ ni_gain[k] = 0.6f*ni_gain[k] + 0.4f*last_ni_gain[k];
+ }
+ }
+ }
+ }
+
+ /* inject noise into the non-decoded coeffs */
+ if(k >= ni_end_band - p2a_bands && p2a_flags[k] == 0 && bwidth != SWB)
+ {
+ for (i = band_start[k]; i <= band_end[k]; i++)
+ {
+ if (y2hat[i] != 0)
+ {
+ y2hat[i] *= 0.8f;
+ }
+ }
+ }
+
+ if(k == max_pos_pulse && k < bands - p2a_bands && satur != 1 && bwidth != SWB)
+ {
+ j = 0;
+ if(ni_gain[k] < 0.01f)
+ {
+ fac = 0.0f;
+ }
+ else
+ {
+ fac = max(Ep[k]/ni_gain[k], 1.0f);
+ }
+ for (i = band_start[k]; i <= band_end[k]; i++)
+ {
+ if (y2hat[i] == 0)
+ {
+ rand = own_random (&ni_seed) / 32768.0f;
+ y2hat[i] += (fac - ((fac-1.0f)*j)/band_width[k])*ni_gain[k] * rand;
+ }
+
+ j++;
+ }
+ }
+ else
+ {
+ for (i = band_start[k]; i <= band_end[k]; i++)
+ {
+ if (y2hat[i] == 0)
+ {
+ rand = own_random (&ni_seed) / 32768.0f;
+ y2hat[i] += ni_gain[k] * rand;
+ }
+ }
+ }
+ }
+
+ mvr2r(env, last_env, ni_end_band);
+ mvr2r(ni_gain, last_ni_gain, ni_end_band);
+ *last_max_pos_pulse = max_pos_pulse;
+
+ return;
+}
diff --git a/lib_com/hq_bit_allocation.c b/lib_com/hq_bit_allocation.c
new file mode 100644
index 0000000000000000000000000000000000000000..1900286fb42291e27ede8b851d273ebabd5b2fe1
--- /dev/null
+++ b/lib_com/hq_bit_allocation.c
@@ -0,0 +1,190 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include
+#include "wmc_auto.h"
+#include "options.h"
+#include "cnst.h"
+#include "prot.h"
+#include "rom_com.h"
+
+
+/*--------------------------------------------------------------------------*
+ * hq_bit_allocation()
+ *
+ * Assign bits for HQ fine structure coding with PVQ
+ *--------------------------------------------------------------------------*/
+
+void hq_bit_allocation(
+ const long core_brate, /* i : Core bit-rate */
+ const short length, /* i : Frame length */
+ const short hqswb_clas, /* i : HQ class */
+ short *num_bits, /* i/o: Remaining bit budget */
+ const short *normqlg2, /* i : Quantized norms */
+ const short nb_sfm, /* i : Number sub bands to be encoded */
+ const short *sfmsize, /* i : Sub band bandwidths */
+ float *noise_level, /* o : HVQ noise level */
+ short *R, /* o : Bit allocation per sub band */
+ short *Rsubband, /* o : Fractional bit allocation (Q3) */
+ short *sum, /* o : Sum of allocated shape bits */
+ short *core_sfm, /* o : Last coded band in core */
+ const short num_env_bands /* i : Number sub bands to be encoded for HQ_SWB_BWE */
+)
+{
+ short sfm_limit = nb_sfm;
+ short i;
+ short idx[NB_SFM];
+ short wnorm[NB_SFM];
+ short avrg_wnorm;
+ short E_low;
+ short E_hb_mean;
+ short E_max;
+ short i_max;
+
+
+ set_s( R, 0, NB_SFM );
+ for( i = 0; i < nb_sfm; i++ )
+ {
+ idx[i] = i;
+ }
+ if( hqswb_clas != HQ_TRANSIENT && hqswb_clas != HQ_HVQ && !(length == L_FRAME16k && core_brate == HQ_32k))
+ {
+ /* 'nf_idx' 2-bits index written later */
+ *num_bits -= 2;
+ }
+
+ if ( hqswb_clas == HQ_GEN_SWB || hqswb_clas == HQ_GEN_FB )
+ {
+ if (core_brate == HQ_32k)
+ {
+ *num_bits -= HQ_GENERIC_SWB_NBITS2;
+ }
+ else
+ {
+ *num_bits -= HQ_GENERIC_SWB_NBITS;
+ }
+ if (length == L_FRAME48k)
+ {
+ *num_bits -= HQ_GENERIC_FB_NBITS;
+ }
+ }
+
+ if( (length == L_FRAME48k) && (hqswb_clas != HQ_HARMONIC) && (hqswb_clas != HQ_HVQ) )
+ {
+ map_quant_weight( normqlg2, wnorm, hqswb_clas == HQ_TRANSIENT );
+ }
+ else
+ {
+ mvs2s( normqlg2, wnorm, nb_sfm );
+ }
+
+
+ if( hqswb_clas == HQ_HARMONIC )
+ {
+ /* classification and limit bandwidth for bit allocation */
+ sfm_limit -= 2;
+ limit_band_noise_level_calc( wnorm, &sfm_limit, core_brate, noise_level );
+
+ /* Detect important band in high frequency region */
+ E_low = sum_s(wnorm, SFM_G1);
+ i_max = 0;
+ E_max = MIN16B;
+ E_hb_mean = 0;
+ for( i = SFM_G1; i < nb_sfm; i++)
+ {
+ E_hb_mean += wnorm[i];
+ if( wnorm[i] > E_max)
+ {
+ E_max = wnorm[i];
+ i_max = i;
+ }
+ }
+ E_hb_mean = E_hb_mean >> 4; /* Truncated division by SFM_G1 */
+ if ( E_max * 15 < E_low || E_max * 0.67 < E_hb_mean || i_max < sfm_limit )
+ {
+ i_max = 0;
+ }
+
+ set_s( wnorm + sfm_limit, -20, nb_sfm - sfm_limit );
+ if ( i_max > 0)
+ {
+ wnorm[i_max] = E_max;
+ }
+
+ }
+
+
+ if( hqswb_clas == HQ_HVQ )
+ {
+ *sum = 0;
+ }
+ else if ( hqswb_clas == HQ_GEN_SWB || (hqswb_clas == HQ_TRANSIENT && length == L_FRAME32k && core_brate <= HQ_32k) )
+ {
+ *sum = BitAllocF( wnorm, core_brate, *num_bits, nb_sfm, R, Rsubband, hqswb_clas, num_env_bands );
+ }
+ else if( length == L_FRAME16k && core_brate == HQ_32k )
+ {
+ if( hqswb_clas != HQ_TRANSIENT )
+ {
+ avrg_wnorm = wnorm[10];
+ for( i=11; i<18; i++ )
+ {
+ avrg_wnorm += wnorm[i];
+ }
+
+ avrg_wnorm /= 8;
+ for( i=0; i<4; i++ )
+ {
+ if( wnorm[i] < avrg_wnorm )
+ {
+ wnorm[i] = avrg_wnorm;
+ }
+ }
+
+ /* Estimate number of bits per band */
+ *sum = BitAllocWB( wnorm, *num_bits, nb_sfm, R, Rsubband );
+ }
+ else
+ {
+ reordvct(wnorm, nb_sfm, idx);
+ bitalloc( wnorm, idx, *num_bits, nb_sfm, QBIT_MAX2, R, sfmsize, hqswb_clas );
+ bitallocsum( R, nb_sfm, sum, Rsubband, *num_bits, length, sfmsize );
+ }
+ }
+ else
+ {
+ reordvct( wnorm, nb_sfm, idx );
+
+ /* enlarge the wnorm value so that more bits can be allocated to (sfm_limit/2 ~ sfm_limit) range */
+ if( hqswb_clas == HQ_HARMONIC )
+ {
+ for( i=sfm_limit/2; i
+#include "wmc_auto.h"
+#include
+#include "options.h"
+#include "cnst.h"
+#include "rom_com.h"
+#include "prot.h"
+
+
+/*--------------------------------------------------------------------------*
+ * hq_configure()
+ *
+ * Configuration routine for HQ mode
+ *--------------------------------------------------------------------------*/
+
+void hq_configure(
+ const short length, /* i : Frame length */
+ const short hqswb_clas, /* i : HQ SWB class */
+ const long core_brate, /* i : Codec bitrate */
+ short *num_sfm, /* o : Total number of subbands */
+ short *nb_sfm, /* o : Total number of coded bands */
+ short *start_norm, /* o : First norm to be SDE encoded */
+ short *num_env_bands, /* o : Number coded envelope bands */
+ short *numnrmibits, /* o : Number of bits in fall-back norm encoding */
+ short *hq_generic_offset, /* o : Freq offset for HQ GENERIC */
+ short const **sfmsize, /* o : Subband bandwidths */
+ short const **sfm_start, /* o : Subband start coefficients */
+ short const **sfm_end /* o : Subband end coefficients */
+)
+{
+ *start_norm = 0;
+
+ if( length == L_FRAME48k )
+ {
+ if ( hqswb_clas == HQ_GEN_FB )
+ {
+ *num_sfm = NB_SFM;
+ *sfmsize = band_len_HQ;
+ *sfm_start = band_start_HQ;
+ *sfm_end = band_end_HQ;
+
+ if( core_brate == HQ_32k )
+ {
+ *hq_generic_offset = HQ_GENERIC_FOFFSET_32K;
+ }
+ else if ( core_brate == HQ_16k40 || core_brate == HQ_24k40 )
+ {
+ *hq_generic_offset = HQ_GENERIC_FOFFSET_24K4;
+ }
+
+ /* setting start frequency of FD BWE */
+ if( core_brate == HQ_32k )
+ {
+ *num_env_bands = SFM_N_STA_10k;
+ }
+ else if( core_brate == HQ_16k40 || core_brate == HQ_24k40 )
+ {
+ *num_env_bands = SFM_N_STA_8k;
+ }
+
+ *nb_sfm = *num_sfm;
+ }
+ else
+ {
+ if(hqswb_clas == HQ_HARMONIC)
+ {
+ *num_sfm = SFM_N_HARM_FB;
+ *nb_sfm = SFM_N_HARM_FB;
+ *num_env_bands = SFM_N_HARM_FB;
+
+ *sfmsize = band_len_harm;
+ *sfm_start = band_start_harm;
+ *sfm_end = band_end_harm;
+ }
+ else if(hqswb_clas == HQ_HVQ)
+ {
+ if( core_brate == HQ_24k40 )
+ {
+ *num_sfm = SFM_N_HARM_FB;
+ *nb_sfm = HVQ_THRES_SFM_24k;
+ *num_env_bands = *num_sfm - *nb_sfm;
+
+ *sfmsize = band_len_harm;
+ *sfm_start = band_start_harm;
+ *sfm_end = band_end_harm;
+ *start_norm = HVQ_THRES_SFM_24k;
+ }
+ else
+ {
+ *num_sfm = SFM_N_HARM_FB;
+ *nb_sfm = HVQ_THRES_SFM_32k;
+ *num_env_bands = *num_sfm - *nb_sfm;
+
+ *sfmsize = band_len_harm;
+ *sfm_start = band_start_harm;
+ *start_norm = HVQ_THRES_SFM_32k;
+ *sfm_end = band_end_harm;
+ }
+ }
+ else
+ {
+ *num_sfm = NB_SFM;
+ *nb_sfm = *num_sfm;
+ *num_env_bands = NB_SFM;
+
+ *sfmsize = band_len_HQ;
+ *sfm_start = band_start_HQ;
+ *sfm_end = band_end_HQ;
+ }
+ }
+ }
+ else if( length == L_FRAME32k )
+ {
+ if( hqswb_clas == HQ_HARMONIC )
+ {
+ *num_sfm = SFM_N_HARM;
+ *nb_sfm = SFM_N_HARM;
+ *num_env_bands = SFM_N_HARM;
+
+ *sfmsize = band_len_harm;
+ *sfm_start = band_start_harm;
+ *sfm_end = band_end_harm;
+ }
+ else if ( hqswb_clas == HQ_HVQ )
+ {
+ if( core_brate == HQ_24k40 )
+ {
+ *num_sfm = SFM_N_HARM;
+ *nb_sfm = HVQ_THRES_SFM_24k;
+ *num_env_bands = *num_sfm - *nb_sfm;
+
+ *sfmsize = band_len_harm;
+ *sfm_start = band_start_harm;
+ *sfm_end = band_end_harm;
+ *start_norm = HVQ_THRES_SFM_24k;
+ }
+ else
+ {
+ *num_sfm = SFM_N_HARM;
+ *nb_sfm = HVQ_THRES_SFM_32k;
+ *num_env_bands = *num_sfm - *nb_sfm;
+
+ *sfmsize = band_len_harm;
+ *sfm_start = band_start_harm;
+ *start_norm = HVQ_THRES_SFM_32k;
+ *sfm_end = band_end_harm;
+ }
+ }
+ else if ( hqswb_clas == HQ_GEN_SWB )
+ {
+ *num_sfm = SFM_N_SWB;
+ *sfmsize = band_len_HQ;
+ *sfm_start = band_start_HQ;
+ *sfm_end = band_end_HQ;
+
+ if( core_brate == HQ_32k )
+ {
+ *hq_generic_offset = HQ_GENERIC_FOFFSET_32K;
+ }
+ else if ( core_brate == HQ_24k40 )
+ {
+ *hq_generic_offset = HQ_GENERIC_FOFFSET_24K4;
+ }
+
+ /* setting start frequency of FD BWE */
+ if( core_brate == HQ_32k )
+ {
+ *num_env_bands = SFM_N_STA_10k;
+ }
+ else if( core_brate == HQ_24k40 )
+ {
+ *num_env_bands = SFM_N_STA_8k;
+ }
+
+ *nb_sfm = *num_sfm;
+ }
+ else
+ {
+ /* HQ_NORMAL and HQ_TRANSIENT */
+ *num_sfm = SFM_N_SWB;
+ *nb_sfm = *num_sfm;
+ *num_env_bands = SFM_N_SWB;
+
+ *sfmsize = band_len_HQ;
+ *sfm_start = band_start_HQ;
+ *sfm_end = band_end_HQ;
+ }
+ }
+ else
+ {
+ *num_sfm = SFM_N_WB;
+ *nb_sfm = *num_sfm;
+ *num_env_bands = SFM_N_WB;
+
+ *sfmsize = band_len_wb;
+ *sfm_start = band_start_wb;
+ *sfm_end = band_end_wb;
+ }
+
+ *numnrmibits = (*num_env_bands - 1) * NORMI_BITS;
+
+ return;
+}
diff --git a/lib_com/hq_tools.c b/lib_com/hq_tools.c
new file mode 100644
index 0000000000000000000000000000000000000000..3cbef95726e9d5674a3a69755199a194d297686b
--- /dev/null
+++ b/lib_com/hq_tools.c
@@ -0,0 +1,1733 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include
+#include "wmc_auto.h"
+#include
+#include "options.h"
+#include "prot.h"
+#include "rom_com.h"
+
+/*--------------------------------------------------------------------------*
+ * Local functions
+ *--------------------------------------------------------------------------*/
+
+static void overlap_hq_bwe( const float *hq_swb_overlap_buf, float *coeff_out1, const short n_swb_overlap_offset, const short n_swb_overlap,
+ const short *R, const short num_env_bands, const short num_sfm, const short *sfm_end );
+
+/*--------------------------------------------------------------------------*
+ * hq_swb_harmonic_calc_norm_envelop()
+ *
+ * Calculate normalization envelop
+ *--------------------------------------------------------------------------*/
+
+void hq_swb_harmonic_calc_norm_envelop(
+ float *SWB_signal, /* i : input signal */
+ float *envelope, /* o : output envelope */
+ int L_swb_norm, /* i : length of normaliztion */
+ int SWB_flength /* i : length of input signal */
+)
+{
+ int lookback;
+ int env_index;
+ int n_freq;
+ int n_lag_now;
+ int n_lag;
+ int i;
+
+ lookback = L_swb_norm/2;
+ env_index = 0;
+ for (n_freq = 0; n_freq < lookback; n_freq++)
+ {
+ n_lag_now = lookback+n_freq;
+
+ /* Apply MA filter */
+ envelope[env_index] = EPSILON;
+ for (n_lag=0; n_lag 0.0f)
+ {
+ CodeBook_mod[cb_size] = 1.0f;
+ E_cb_vec++;
+ }
+ else if (coeff[j] < 0.0f)
+ {
+ CodeBook_mod[cb_size] = -1.0f;
+ E_cb_vec++;
+ }
+ else
+ {
+ CodeBook_mod[cb_size] = 0.0f;
+ }
+ cb_size++;
+ }
+
+ if (E_cb_vec < 2)
+ {
+ cb_size -= 8;
+ }
+ }
+ }
+ else
+ {
+ for (j = sfm_start[sfm]; j < sfm_end[sfm]; j++)
+ {
+ CodeBook[cb_size] = coeff[j];
+ cb_size++;
+ }
+ }
+ }
+ }
+
+ if (flag_32K_env_ho)
+ {
+ for (j = 0; j < cb_size; j++)
+ {
+ if (CodeBook_mod[j] != 0.0f)
+ {
+ /* Densify codebook */
+ CodeBook[j] = sign(CodeBook_mod[j])*(CodeBook_mod[j]*CodeBook_mod[j] + CodeBook_mod[cb_size-j-1]*CodeBook_mod[cb_size-j-1]);
+ }
+ else
+ {
+ CodeBook[j] = CodeBook_mod[cb_size-j-1];
+ }
+ }
+ }
+
+ return cb_size;
+}
+
+/*--------------------------------------------------------------------------*
+ * find_last_band()
+ *
+ * Find the last band which has bits allocated
+ *--------------------------------------------------------------------------*/
+
+short find_last_band( /* o : index of last band */
+ const short *bitalloc, /* i : bit allocation */
+ const short nb_sfm /* i : number of possibly coded bands */
+)
+{
+ short sfm, core_sfm;
+
+ core_sfm = nb_sfm-1;
+
+ for (sfm = nb_sfm-1; sfm >= 0; sfm--)
+ {
+ if ( bitalloc[sfm] != 0 )
+ {
+ core_sfm = sfm;
+ break;
+ }
+ }
+
+ return core_sfm;
+}
+
+/*--------------------------------------------------------------------------*
+ * apply_noisefill_HQ()
+ *
+ * Inject noise in non-coded bands
+ *--------------------------------------------------------------------------*/
+
+void apply_noisefill_HQ(
+ const short *R, /* i : bit allocation */
+ const short length, /* i : input frame length */
+ const short flag_32K_env_ho,/* i : envelope stability hangover flag*/
+ const long core_brate, /* i : core bit rate */
+ const short last_sfm, /* i : last coded subband */
+ const float *CodeBook, /* i : Noise-fill codebook */
+ const float *CodeBook_mod, /* i : Densified noise-fill codebook */
+ const short cb_size, /* i : Codebook length */
+ const short *sfm_start, /* i : Subband start coefficient */
+ const short *sfm_end, /* i : Subband end coefficient */
+ const short *sfmsize, /* i : Subband band width */
+ float *coeff /* i/o: coded/noisefilled spectrum */
+)
+{
+ short sfm;
+ short cb_pos;
+ float E_cb_vec;
+ float E_corr;
+ float cb_buff[64];
+ short i,j;
+
+ if( length >= L_FRAME32k || core_brate > HQ_32k || core_brate < HQ_24k40 )
+ {
+ /* Read from codebook */
+ cb_pos = 0;
+
+ for (sfm = 0; sfm <= last_sfm; sfm++)
+ {
+ if (R[sfm] == 0)
+ {
+ if (flag_32K_env_ho)
+ {
+ E_cb_vec = 0.0f;
+ if (sfm < 20)
+ {
+ for (i = 0; i < sfmsize[sfm]; i++)
+ {
+ cb_buff[i] = CodeBook_mod[cb_pos];
+ E_cb_vec += cb_buff[i]*cb_buff[i];
+ cb_pos++;
+ if(cb_pos >= cb_size)
+ {
+ cb_pos = 0;
+ }
+ }
+ }
+ else
+ {
+ for (i = 0; i < sfmsize[sfm]; i++)
+ {
+ cb_buff[i] = CodeBook[cb_pos];
+ E_cb_vec += cb_buff[i]*cb_buff[i];
+ cb_pos++;
+ if(cb_pos >= cb_size)
+ {
+ cb_pos = 0;
+ }
+ }
+ }
+
+ E_corr = E_cb_vec / ((float) sfmsize[sfm]);
+ E_corr = 1.0f / (float)sqrt(E_corr);
+
+ for (j = sfm_start[sfm]; j < sfm_end[sfm]; j++)
+ {
+ coeff[j] = cb_buff[j - sfm_start[sfm]] * E_corr;
+ }
+ }
+ else
+ {
+ for (j = sfm_start[sfm]; j < sfm_end[sfm]; j++)
+ {
+ coeff[j] = CodeBook[cb_pos];
+ cb_pos++;
+ cb_pos = (cb_pos>=cb_size) ? 0 : cb_pos;
+ }
+ }
+ }
+ }
+ }
+
+ return;
+}
+
+
+/*--------------------------------------------------------------------------*
+ * harm_bwe_fine()
+ *
+ * Prepare harmonic BWE fine structure
+ *--------------------------------------------------------------------------*/
+
+void harm_bwe_fine(
+ const short *R, /* i : bit allocation */
+ const short last_sfm, /* i : last coded subband */
+ const short high_sfm, /* i : higher transition band to BWE */
+ const short num_sfm, /* i : total number of bands */
+ const short *norm, /* i : quantization indices for norms */
+ const short *sfm_start, /* i : Subband start coefficient */
+ const short *sfm_end, /* i : Subband end coefficient */
+ short *prev_L_swb_norm, /* i/o: last normalize length */
+ float *coeff, /* i/o: coded/noisefilled normalized spectrum */
+ float *coeff_out, /* o : coded/noisefilled spectrum */
+ float *coeff_fine /* o : BWE fine structure */
+)
+{
+ short sfm;
+ short i;
+ float normq;
+ float SWB_signal[L_HARMONIC_EXC];
+ float envelope[L_HARMONIC_EXC];
+ float *src, *dst, *end;
+
+ short norm_width = 64;
+
+ /* shape the spectrum */
+ for (sfm = 0; sfm <= last_sfm; sfm++)
+ {
+ if( R[sfm] != 0 )
+ {
+ normq = dicn[norm[sfm]];
+ for (i = sfm_start[sfm]; i < sfm_end[sfm]; i++)
+ {
+ coeff_out[i] = coeff[i]*normq;
+ }
+ }
+ else
+ {
+ for (i = sfm_start[sfm]; i < sfm_end[sfm]; i++)
+ {
+ coeff_out[i] = 0.0f;
+ }
+ }
+ }
+
+ /* excitation replication */
+ mvr2r( coeff_out, SWB_signal, L_HARMONIC_EXC );
+ calc_normal_length( HQ_CORE, coeff_out, HQ_HARMONIC, -1, &norm_width, prev_L_swb_norm );
+ hq_swb_harmonic_calc_norm_envelop( SWB_signal, envelope, norm_width, L_HARMONIC_EXC );
+
+ /* Normalize with envelope */
+ for (i = 0; i < L_HARMONIC_EXC; i++)
+ {
+ SWB_signal[i] = SWB_signal[i] / envelope[i];
+ }
+
+ dst = coeff_fine + sfm_end[last_sfm];
+ end = coeff_fine + sfm_end[num_sfm-1];
+
+ if ( (sfm_end[last_sfm] - sfm_end[high_sfm]) <= L_HARMONIC_EXC - START_EXC )
+ {
+ src = SWB_signal + START_EXC + (sfm_end[last_sfm] - sfm_end[high_sfm]);
+ }
+ else
+ {
+ src = SWB_signal + L_HARMONIC_EXC - 1;
+ }
+
+ while (dst < end)
+ {
+ while (dst < end && src < &SWB_signal[L_HARMONIC_EXC])
+ {
+ *dst++ = *src++;
+ }
+ src --;
+
+ while (dst < end && src >= &SWB_signal[START_EXC])
+ {
+ *dst++ = *src--;
+ }
+ src++;
+ }
+
+ return;
+}
+
+/*--------------------------------------------------------------------------*
+ * hvq_bwe_fine()
+ *
+ * Prepare HVQ BWE fine structure
+ *--------------------------------------------------------------------------*/
+
+void hvq_bwe_fine(
+ const short last_sfm, /* i : last coded subband */
+ const short num_sfm, /* i : total number of bands */
+ const short *sfm_end, /* i : Subband end coefficient */
+ const short *peak_idx, /* i : Peak index */
+ const short Npeaks, /* i : Number of peaks */
+ short *peak_pos, /* i/o: Peak positions */
+ short *prev_L_swb_norm, /* i/o: last normalize length */
+ float *coeff, /* i/o: coded/noisefilled normalized spectrum */
+ short *bwe_peaks, /* o : Positions of peaks in BWE */
+ float *coeff_fine /* o : HVQ BWE fine structure */
+)
+{
+ short i, j;
+ float SWB_signal[L_HARMONIC_EXC];
+ float envelope[L_HARMONIC_EXC];
+ float *src, *dst, *end;
+ short *peak_dst, *peak_src;
+ short norm_width = 64;
+
+ /* excitation replication */
+ mvr2r( coeff, SWB_signal, L_HARMONIC_EXC );
+ calc_normal_length( HQ_CORE, coeff, HQ_HVQ, -1, &norm_width, prev_L_swb_norm );
+
+ hq_swb_harmonic_calc_norm_envelop( SWB_signal, envelope, norm_width, L_HARMONIC_EXC );
+
+ /* Normalize with envelope */
+ for (i = 0; i < L_HARMONIC_EXC; i++)
+ {
+ SWB_signal[i] = SWB_signal[i] / envelope[i];
+ }
+
+ dst = coeff_fine;
+ end = coeff_fine + sfm_end[num_sfm-1] - sfm_end[last_sfm];
+
+ src = SWB_signal + START_EXC;
+ peak_src = peak_pos + START_EXC;
+
+ for(i = 0; i < Npeaks; i++)
+ {
+ if ( peak_idx[i] < L_HARMONIC_EXC )
+ {
+ peak_pos[peak_idx[i]] = 1;
+ }
+ }
+
+ i = L_HARMONIC_EXC-1;
+ while( i-- > 0 )
+ {
+ if( peak_pos[i] == 1 )
+ {
+ break;
+ }
+ }
+
+ if( i < 180 )
+ {
+ i = 180;
+ }
+
+ for( j = L_HARMONIC_EXC-1; j > i+1; j-- )
+ {
+ SWB_signal[j] = 0.0f;
+ }
+
+ peak_dst = bwe_peaks + sfm_end[last_sfm];
+ while ( dst < end )
+ {
+ while ( dst < end && src < &SWB_signal[L_HARMONIC_EXC] )
+ {
+ *dst++ = *src++;
+ *peak_dst++ = *peak_src++;
+ }
+ peak_src--;
+ src --;
+
+ while (dst < end && src >= &SWB_signal[START_EXC])
+ {
+ *dst++ = *src--;
+ *peak_dst++ = *peak_src--;
+ }
+ peak_src++;
+ src++;
+ }
+
+ return;
+}
+
+/*--------------------------------------------------------------------------*
+ * hq_fold_bwe()
+ *
+ * HQ mode folding BWE
+ *--------------------------------------------------------------------------*/
+
+void hq_fold_bwe(
+ const short last_sfm, /* i : last coded subband */
+ const short *sfm_end, /* i : Subband end coefficient */
+ const short num_sfm, /* i : Number of subbands */
+ float *coeff /* i/o: coded/noisefilled normalized spectrum */
+)
+{
+ short low_coeff;
+ short first_coeff;
+ float *src, *dst, *end;
+
+ /* Find replication range for BWE */
+ low_coeff = sfm_end[last_sfm] >> 1;
+ src = coeff + sfm_end[last_sfm] - 1;
+
+ first_coeff = sfm_end[last_sfm];
+ dst = coeff + sfm_end[last_sfm];
+ end = coeff + sfm_end[num_sfm-1];
+
+ /* Generate BWE with spectral folding */
+ while (dst < end)
+ {
+ while (dst < end && src >= &coeff[low_coeff])
+ {
+ *dst++ = *src--;
+ }
+
+ src++;
+
+ while (dst < end && src < &coeff[first_coeff])
+ {
+ *dst++ = *src++;
+ }
+ }
+
+ return;
+}
+
+/*--------------------------------------------------------------------------*
+ * apply_nf_gain()
+ *
+ * Apply noise fill gain
+ *--------------------------------------------------------------------------*/
+
+void apply_nf_gain(
+ const short nf_idx, /* i : noise fill gain index */
+ const short last_sfm, /* i : last coded subband */
+ const short *R, /* i : bit allocation */
+ const short *sfm_start, /* i : Subband start coefficient */
+ const short *sfm_end, /* i : Subband end coefficient */
+ float *coeff /* i/o: coded/noisefilled normalized spectrum */
+)
+{
+ short sfm;
+ short j;
+ float nf_scale;
+
+ nf_scale = 1.0f / (1 << nf_idx);
+ for (sfm = 0; sfm <= last_sfm; sfm++)
+ {
+ if (R[sfm] == 0)
+ {
+ for (j = sfm_start[sfm]; j < sfm_end[sfm]; j++)
+ {
+ /* Scale NoiseFill */
+ coeff[j] = coeff[j] * nf_scale;
+ }
+ }
+ }
+
+ return;
+}
+
+/*--------------------------------------------------------------------------*
+ * hq_generic_fine()
+ *
+ * Prepare HQ SWB BWE fine structure
+ *--------------------------------------------------------------------------*/
+
+void hq_generic_fine(
+ float *coeff, /* i : coded/noisefilled normalized spectrum */
+ const short last_sfm, /* i : Last coded band */
+ const short *sfm_start, /* i : Subband start coefficient */
+ const short *sfm_end, /* i : Subband end coefficient */
+ short *bwe_seed, /* i/o: random seed for generating BWE input */
+ float *coeff_out1 /* o : HQ SWB BWE input */
+)
+{
+ short sfm;
+ short i;
+ float multi;
+
+ multi = 1.0f;
+ for (sfm = 0; sfm <= last_sfm; sfm++)
+ {
+ for (i = sfm_start[sfm]; i < sfm_end[sfm]; i++)
+ {
+ if (coeff[i]==0.f)
+ {
+ coeff_out1[i] = (float)multi*( own_random(bwe_seed)>0 ? 1.0f: -1.0f)*0.5f;
+ }
+ else
+ {
+ coeff_out1[i] = coeff[i];
+ }
+ }
+ }
+
+ return;
+}
+
+/*--------------------------------------------------------------------------*
+ * harm_bwe()
+ *
+ * HQ Harmonic BWE
+ *--------------------------------------------------------------------------*/
+
+void harm_bwe(
+ const float *coeff_fine, /* i : fine structure for BWE */
+ const float *coeff, /* i : coded/noisefilled normalized spectrum */
+ const short num_sfm, /* i : Number of subbands */
+ const short *sfm_start, /* i : Subband start coefficient */
+ const short *sfm_end, /* i : Subband end coefficient */
+ const short last_sfm, /* i : last coded subband */
+ const short high_sfm, /* i : higher transition band to BWE */
+ const short *R, /* i : bit allocation */
+ const short prev_hq_mode, /* i : previous hq mode */
+ short *norm, /* i/o: quantization indices for norms */
+ float *noise_level, /* i/o: noise levels for harmonic modes */
+ float *prev_noise_level, /* i/o: noise factor in previous frame */
+ short *bwe_seed, /* i/o: random seed for generating BWE input */
+ float *coeff_out /* o : coded/noisefilled spectrum */
+)
+{
+ short i, j;
+ short sfm;
+ float normq;
+ float norm_adj;
+ float E_L;
+
+ float alfa = 0.5f;
+ float alpha, beta;
+ short idx;
+ float fac;
+ float *src, *dst;
+
+ for (sfm = 0; sfm <= last_sfm; sfm++)
+ {
+ if (R[sfm] == 0)
+ {
+ normq = dicn[norm[sfm]];
+ for (i = sfm_start[sfm]; i < sfm_end[sfm]; i++)
+ {
+ coeff_out[i] = coeff[i]*normq;
+ }
+ }
+ }
+ noise_level[1] = noise_level[0];
+
+ /* shaping the BWE spectrum further by envelopes and noise factors */
+ noise_level[0] = 0.9f*prev_noise_level[0] + 0.1f*noise_level[0];
+ noise_level[1] = 0.9f*prev_noise_level[1] + 0.1f*noise_level[1];
+
+ if( prev_hq_mode == HQ_NORMAL || prev_hq_mode == HQ_GEN_SWB)
+ {
+ if( noise_level[0] < 0.25f )
+ {
+ noise_level[0] *= 4.0f;
+ }
+
+ if( noise_level[1] < 0.25f )
+ {
+ noise_level[1] *= 4.0f;
+ }
+ }
+
+ E_L = EPSILON;
+ for( i=last_sfm+1; i < num_sfm; i++ )
+ {
+ E_L = EPSILON;
+ for (j = sfm_start[i]; j < sfm_end[i]; j++)
+ {
+ E_L += coeff_fine[j] * coeff_fine[j];
+ }
+ E_L = (float)sqrt((sfm_end[i] - sfm_start[i])/E_L);
+
+ normq = dicn[norm[i]];
+ norm_adj = normq*E_L;
+ alfa = (i > 27) ? noise_level[1] : noise_level[0];
+ beta = (float)sqrt(1.0f - alfa);
+ alpha = (float)sqrt(alfa) * 0.5f;
+
+ for(sfm = sfm_start[i]; sfm < sfm_end[i]; sfm++)
+ {
+ coeff_out[sfm] = (beta*coeff_fine[sfm]*norm_adj + alpha*own_random(bwe_seed)/32768.0f*normq);
+ }
+ }
+
+ prev_noise_level[0] = noise_level[0];
+ prev_noise_level[1] = noise_level[1];
+ idx = 16;
+ src = &coeff_out[sfm_end[high_sfm] + L_HARMONIC_EXC - START_EXC];
+ dst = src-1;
+
+ for( i = 0; i < idx; i++ )
+ {
+ fac = i / (2.0f * idx);
+ *src++ *= 0.5f + fac;
+ *dst-- *= 0.5f + fac;
+ }
+ if( num_sfm ==33 )
+ {
+ set_f(&coeff_out[800], 0, 160);
+ }
+ return;
+}
+
+/*--------------------------------------------------------------------------*
+ * HVQ_bwe()
+ *
+ * HQ HVQ BWE
+ *--------------------------------------------------------------------------*/
+
+void hvq_bwe(
+ const float *coeff, /* i : coded/noisefilled spectrum */
+ const float *coeff_fine, /* i : BWE fine structure */
+ const short *sfm_start, /* i : Subband start coefficient */
+ const short *sfm_end, /* i : Subband end coefficient */
+ const short *sfm_len, /* i : Subband length */
+ const short last_sfm, /* i : last coded subband */
+ const short prev_hq_mode, /* i : previous hq mode */
+ const short *bwe_peaks, /* i : HVQ bwe peaks */
+ const short bin_th, /* i : HVQ transition bin */
+ const short num_sfm, /* i : Number of bands */
+ const long core_brate, /* i : Core bit-rate */
+ const short *R, /* i : Bit allocation */
+ short *norm, /* i/o: quantization indices for norms */
+ float *noise_level, /* i/o: noise levels for harmonic modes */
+ float *prev_noise_level, /* i/o: noise factor in previous frame */
+ short *bwe_seed, /* i/o: random seed for generating BWE input */
+ float *coeff_out /* o : coded/noisefilled spectrum */
+)
+{
+ short i, j;
+ short N;
+ float normq;
+ float E_L;
+
+ short bwe_noise_th = 0;
+ short peak_band, low, high, sel_norm;
+ short norm_ind;
+ float tmp_norm = 0;
+ short idx;
+ float fac;
+ float *src, *dst;
+ short istart, iend;
+ short offset = sfm_end[last_sfm];
+
+ mvr2r( coeff, coeff_out, L_FRAME48k );
+
+ bwe_noise_th = bin_th+(sfm_end[num_sfm-1] - bin_th)/HVQ_BWE_NOISE_BANDS;
+ logqnorm(&coeff_out[sfm_start[last_sfm]], &norm[last_sfm], 40, sfm_len[last_sfm], thren_HQ);
+
+ /* shaping the BWE spectrum further by envelopes and noise factors */
+ noise_level[0] = 0.9f*prev_noise_level[0] + 0.1f*noise_level[0];
+ noise_level[1] = 0.9f*prev_noise_level[1] + 0.1f*noise_level[1];
+
+ if( prev_hq_mode == HQ_NORMAL || prev_hq_mode == HQ_GEN_SWB)
+ {
+ if( noise_level[0] < 0.25f )
+ {
+ noise_level[0] *= 4.0f;
+ }
+
+ if( noise_level[1] < 0.25f )
+ {
+ noise_level[1] *= 4.0f;
+ }
+ }
+
+ norm_ind = last_sfm+1;
+ if (core_brate == HQ_24k40)
+ {
+ peak_band = 0;
+ E_L = EPSILON;
+ for (i = sfm_start[norm_ind]; i < sfm_end[norm_ind+1]; i++)
+ {
+ if (bwe_peaks[i])
+ {
+ peak_band = 1;
+ }
+ E_L += coeff_fine[i-offset] * coeff_fine[i-offset];
+ }
+ E_L = (float)sqrt((sfm_end[norm_ind+1] - sfm_start[norm_ind])/E_L);
+
+ normq = 0.1f*dicn[norm[norm_ind-1]] + 0.8f*dicn[norm[norm_ind]] + 0.1f*dicn[norm[norm_ind+1]];
+ tmp_norm = 0.1f*dicn[norm[norm_ind]] + 0.8f*dicn[norm[norm_ind+1]] + 0.1f*dicn[norm[norm_ind+2]];
+
+ istart = sfm_start[norm_ind];
+ iend = istart + sfm_len[norm_ind]/2;
+ for (i = istart; i < iend; i++)
+ {
+ coeff_out[i] = ((1.0f - noise_level[i/bwe_noise_th])*coeff_fine[i-offset]*E_L + noise_level[i/bwe_noise_th]*own_random(bwe_seed)/32768.0f)*normq;
+ }
+
+ j = 0;
+ N = sfm_len[norm_ind]/2+sfm_len[norm_ind+1]/2-1;
+ istart = iend;
+ iend = sfm_start[norm_ind+1] + sfm_len[norm_ind+1]/2;
+ for (i = istart; i < iend; i++)
+ {
+ coeff_out[i] = ((float)(N-j)/N*normq + (float)j/N*tmp_norm)*((1.0f - noise_level[i/bwe_noise_th])*coeff_fine[i-offset]*E_L + noise_level[i/bwe_noise_th]*own_random(bwe_seed)/32768.0f);
+ j++;
+ }
+
+ istart = iend;
+ iend = sfm_end[norm_ind+1];
+ for (i = istart; i < iend; i++)
+ {
+ coeff_out[i] = ((1.0f - noise_level[i/bwe_noise_th])*coeff_fine[i-offset]*E_L + noise_level[i/bwe_noise_th]*own_random(bwe_seed)/32768.0f)*tmp_norm;
+ }
+
+ norm_ind += 2;
+ }
+
+ for ( ; norm_ind < num_sfm; norm_ind++)
+ {
+ if ( R[norm_ind] == 0 )
+ {
+ peak_band = 0;
+ E_L = EPSILON;
+
+ for (i = sfm_start[norm_ind]; i < sfm_end[norm_ind]; i++)
+ {
+ if (bwe_peaks[i])
+ {
+ peak_band = 1;
+ break;
+ }
+ }
+
+ istart = sfm_start[norm_ind];
+ iend = sfm_end[norm_ind];
+
+ if ( peak_band == 1 && norm_ind > last_sfm+1 && norm_ind < num_sfm-1 )
+ {
+ istart -= sfm_len[norm_ind-1]/2;
+ iend += sfm_len[norm_ind+1]/2;
+ }
+
+ for (i = istart; i < iend; i++)
+ {
+ E_L += coeff_fine[i-offset] * coeff_fine[i-offset];
+ }
+ E_L = (float)sqrt((iend - istart)/E_L);
+
+ if ( peak_band )
+ {
+ if ( norm_ind+1 > num_sfm-1 )
+ {
+ normq = 0.15f*dicn[norm[norm_ind-1]] + 0.85f*dicn[norm[norm_ind]];
+ }
+ else
+ {
+ normq = 0.1f*dicn[norm[norm_ind-1]] + 0.8f*dicn[norm[norm_ind]] + 0.1f*dicn[norm[norm_ind+1]];
+ }
+ }
+ else
+ {
+ low = norm_ind;
+ high = min(norm_ind+1, num_sfm-1);
+ sel_norm = norm[norm_ind-1];
+ for (j = low; j <= high; j++)
+ {
+ if (norm[j] > sel_norm)
+ {
+ sel_norm = norm[j];
+ }
+ }
+ normq = dicn[sel_norm];
+ }
+
+ for (i = sfm_start[norm_ind]; i < sfm_end[norm_ind]; i++)
+ {
+ coeff_out[i] = ((1.0f - noise_level[i/bwe_noise_th])*coeff_fine[i-offset]*E_L + noise_level[i/bwe_noise_th]*own_random(bwe_seed)/32768.0f)*normq;
+ }
+ }
+ else /* R[norm_ind] > 0 */
+ {
+ for (i = sfm_start[norm_ind]; i < sfm_end[norm_ind]; i++)
+ {
+ coeff_out[i] = coeff[i]; /* Scaling already applied */
+ }
+ }
+
+ }
+
+ prev_noise_level[0] = noise_level[0];
+ prev_noise_level[1] = noise_level[1];
+ idx = 16;
+ src = &coeff_out[sfm_end[last_sfm] + L_HARMONIC_EXC - START_EXC];
+ dst = src-1;
+
+ for( i = 0; i < idx; i++ )
+ {
+ fac = i/(2.0f * idx);
+ *src++ *= 0.5f + fac;
+ *dst-- *= 0.5f + fac;
+ }
+
+ return;
+}
+/*-------------------------------------------------------------------*
+* hvq_concat_bands()
+*
+* Compute the band limits for concatenated bands for PVQ target signal in HVQ
+*--------------------------------------------------------------------------*/
+void hvq_concat_bands
+(
+ const short pvq_bands, /* i : Number of bands in concatenated PVQ target */
+ const short *sel_bnds, /* i : Array of selected high bands */
+ const short n_sel_bnds, /* i : Number of selected high bands */
+ short *hvq_band_start, /* i : Band start indices */
+ short *hvq_band_width, /* i : Band widths */
+ short *hvq_band_end /* i : Band end indices */
+)
+{
+ short k;
+ short s;
+
+ s = 0;
+
+ for (k = 0; k < pvq_bands; k++)
+ {
+
+ if( k >= pvq_bands - n_sel_bnds)
+ {
+ hvq_band_start[k] = hvq_band_end[k-1];
+ hvq_band_width[k] = band_len_harm[sel_bnds[s]];
+ hvq_band_end[k] = hvq_band_end[k-1] + band_len_harm[sel_bnds[s]];
+ s++;
+ }
+ else
+ {
+ hvq_band_start[k] = k * HVQ_PVQ_COEFS;
+ hvq_band_width[k] = HVQ_PVQ_COEFS;
+ hvq_band_end[k] = (k + 1) * HVQ_PVQ_COEFS;
+ }
+ }
+
+ return;
+}
+
+
+/*--------------------------------------------------------------------------*
+ * map_hq_generic_fenv_norm()
+ *
+ * mapping high frequency envelope to high band norm
+ *--------------------------------------------------------------------------*/
+void map_hq_generic_fenv_norm(
+ const short hqswb_clas,
+ const float *hq_generic_fenv,
+ short *ynrm,
+ short *normqlg2,
+ const short num_env_bands,
+ const short nb_sfm,
+ const short hq_generic_offset)
+{
+ float env_fl[17];
+ short i;
+
+ set_f( env_fl, 0, 17 );
+ if (hq_generic_offset == 144)
+ {
+ env_fl[0] = hq_generic_fenv[1];
+ env_fl[1] = hq_generic_fenv[2]*0.6640625f+hq_generic_fenv[3]*0.3359375f;
+ env_fl[2] = hq_generic_fenv[3]*0.6640625f+hq_generic_fenv[4]*0.3359375f;
+ env_fl[3] = hq_generic_fenv[4]*0.3359375f+hq_generic_fenv[5]*0.6640625f;
+ env_fl[4] = hq_generic_fenv[5]*0.3359375f+hq_generic_fenv[6]*0.6640625f;
+ env_fl[5] = hq_generic_fenv[7];
+ env_fl[6] = hq_generic_fenv[8]*0.75f+hq_generic_fenv[9]*0.25f;
+ env_fl[7] = hq_generic_fenv[9]*0.75f+hq_generic_fenv[10]*0.25f;
+ env_fl[8] = hq_generic_fenv[10]*0.25f+hq_generic_fenv[11]*0.75f;
+ }
+ else
+ {
+ env_fl[0] = hq_generic_fenv[0]*0.3359375f+hq_generic_fenv[1]*0.6640625f;
+ env_fl[1] = hq_generic_fenv[1]*0.3359375f+hq_generic_fenv[2]*0.6640625f;
+ env_fl[2] = hq_generic_fenv[3];
+ env_fl[3] = hq_generic_fenv[4]*0.6640625f+hq_generic_fenv[5]*0.3359375f;
+ env_fl[4] = hq_generic_fenv[5]*0.6640625f+hq_generic_fenv[6]*0.3359375f;
+ env_fl[5] = hq_generic_fenv[6]*0.3359375f+hq_generic_fenv[7]*0.6640625f;
+ env_fl[6] = hq_generic_fenv[7]*0.3359375f+hq_generic_fenv[8]*0.6640625f;
+ env_fl[7] = hq_generic_fenv[8]*0.3359375f+hq_generic_fenv[9]*0.6640625f;
+ env_fl[8] = hq_generic_fenv[9]*0.3359375f+hq_generic_fenv[10]*0.6640625f;
+ env_fl[9] = hq_generic_fenv[10]*0.25f+hq_generic_fenv[11]*0.75f;
+ env_fl[10] = hq_generic_fenv[12];
+ env_fl[11] = hq_generic_fenv[13];
+ }
+
+ if (hqswb_clas == HQ_GEN_FB)
+ {
+ if (hq_generic_offset == 144)
+ {
+ env_fl[9] = hq_generic_fenv[12];
+ env_fl[10] = hq_generic_fenv[12]*0.25f+hq_generic_fenv[13]*0.75f;
+ env_fl[11] = hq_generic_fenv[13]*0.5f+hq_generic_fenv[14]*0.5f;
+ env_fl[12] = hq_generic_fenv[14];
+ env_fl[13] = hq_generic_fenv[14];
+ }
+ else
+ {
+ env_fl[12] = hq_generic_fenv[14];
+ env_fl[13] = hq_generic_fenv[14]*0.25f+hq_generic_fenv[15]*0.75f;
+ env_fl[14] = hq_generic_fenv[15]*0.5f+hq_generic_fenv[16]*0.5f;
+ env_fl[15] = hq_generic_fenv[16];
+ env_fl[16] = hq_generic_fenv[16];
+ }
+ }
+
+ logqnorm_2( env_fl,40, num_env_bands, nb_sfm, ynrm+num_env_bands, normqlg2+num_env_bands, thren_HQ);
+
+ for(i=num_env_bands; i0)
+ {
+ i=nb_sfm-1;
+ while(b_add_bits_denv>0 && i>=0)
+ {
+ if (Rsubband[i]>24)
+ {
+ Rsubband[i] -= 8;
+ b_add_bits_denv--;
+ }
+ i--;
+ }
+ }
+
+ return;
+}
+
+short get_nor_delta_hf(
+ Decoder_State *st,
+ short *ynrm,
+ short *Rsubband,
+ const short num_env_bands,
+ const short nb_sfm,
+ const short core_sfm
+)
+{
+ short i;
+ short delta,bitsforDelta,add_bits_denv;
+
+ add_bits_denv = 0;
+ if (core_sfm >= num_env_bands)
+ {
+ bitsforDelta = (short)get_next_indice(st,2);
+ bitsforDelta += 2;
+ add_bits_denv += 2;
+
+ for(i=num_env_bands; i 39 )
+ {
+ ynrm[i] = 39;
+ st->BER_detect = 1;
+ }
+ add_bits_denv += bitsforDelta;
+ }
+ }
+
+ update_rsubband(nb_sfm, Rsubband,add_bits_denv);
+ }
+ return add_bits_denv;
+}
+
+short calc_nor_delta_hf(
+ Encoder_State *st,
+ const float *t_audio,
+ short *ynrm,
+ short *Rsubband,
+ const short num_env_bands,
+ const short nb_sfm,
+ const short *sfmsize,
+ const short *sfm_start,
+ const short core_sfm
+)
+{
+ short i;
+ short ynrm_t[44],normqlg2_t[44];
+ short delta,max_delta,min_delta,bitsforDelta,add_bits_denv;
+
+
+ short temp_num=0;
+
+ max_delta=-100;
+ calc_norm( t_audio, ynrm_t, normqlg2_t, 0, nb_sfm, sfmsize, sfm_start );
+ add_bits_denv = 0;
+ for(i=num_env_bands; i 0)
+ {
+ delta += 1;
+ }
+ else
+ {
+ delta = -delta;
+ }
+ if (delta>max_delta)
+ {
+ max_delta = delta;
+ }
+ }
+ }
+ if (core_sfm >= num_env_bands)
+ {
+ if (max_delta < 16)
+ {
+ bitsforDelta = 2;
+ while(max_delta>=2)
+ {
+ bitsforDelta++;
+ max_delta >>= 1;
+ }
+ }
+ else
+ {
+ bitsforDelta = 5;
+ }
+ max_delta = (1<<(bitsforDelta-1))-1;
+ min_delta = (max_delta+1)*(-1);
+
+ /* updating norm & storing delta norm */
+ add_bits_denv = 2;
+ push_indice( st, IND_DELTA_ENV_HQ, bitsforDelta-2 , 2 );
+ for(i=num_env_bands; i max_delta)
+ {
+ delta = max_delta;
+ }
+ else if (delta < min_delta)
+ {
+ delta = min_delta;
+ }
+ push_indice( st, IND_DELTA_ENV_HQ, delta - min_delta , bitsforDelta );
+ ynrm[i] += delta;
+ add_bits_denv += bitsforDelta;
+
+
+ temp_num++;
+ }
+ }
+
+ /* updating bit allocation */
+ update_rsubband(nb_sfm, Rsubband,add_bits_denv);
+
+ }
+
+ return add_bits_denv;
+}
+
+/*-------------------------------------------------------------------*
+* hq_generic_bwe()
+*
+* HQ GENERIC BWE
+*--------------------------------------------------------------------------*/
+void hq_generic_bwe(
+ const short HQ_mode, /* i : HQ mode */
+ float *coeff_out1, /* i/o: BWE input & temporary buffer */
+ const float *hq_generic_fenv, /* i : SWB frequency envelopes */
+ float *coeff_out, /* o : SWB signal in MDCT domain */
+ const short hq_generic_offset, /* i : frequency offset for representing hq generic*/
+ short *prev_L_swb_norm, /* i/o: last normalize length */
+ const short hq_generic_exc_clas, /* i : hq generic hf excitation class */
+ const short *sfm_end, /* i : End of bands */
+ const short num_sfm, /* i : Number of bands */
+ const short num_env_bands, /* i : Number of coded envelope bands */
+ const short *R /* i : Bit allocation */
+)
+{
+ short n_swb_overlap_offset, n_swb_overlap;
+ float hq_swb_overlap_buf[640];
+
+ n_swb_overlap_offset = swb_bwe_subband[0] + hq_generic_offset;
+
+ n_swb_overlap = sfm_end[num_env_bands-1] - n_swb_overlap_offset;
+ mvr2r( &coeff_out[n_swb_overlap_offset], hq_swb_overlap_buf, n_swb_overlap + sfm_end[num_sfm-1] - sfm_end[num_env_bands-1] );
+
+ hq_generic_hf_decoding( HQ_mode, coeff_out1, hq_generic_fenv, coeff_out, hq_generic_offset, prev_L_swb_norm, hq_generic_exc_clas, R );
+
+ overlap_hq_bwe( hq_swb_overlap_buf, coeff_out, n_swb_overlap_offset, n_swb_overlap, R, num_env_bands, num_sfm, sfm_end );
+
+ return;
+}
+
+
+/*--------------------------------------------------------------------------*
+ * hq_wb_nf_bwe()
+ *
+ * HQ WB noisefill and BWE
+ *--------------------------------------------------------------------------*/
+
+void hq_wb_nf_bwe(
+ const float *coeff, /* i : coded/noisefilled normalized spectrum */
+ const short is_transient, /* i : is transient flag */
+ const short prev_bfi, /* i : previous bad frame indicator */
+ const float *normq_v, /* i : norms */
+ const short num_sfm, /* i : Number of subbands */
+ const short *sfm_start, /* i : Subband start coefficient */
+ const short *sfm_end, /* i : Subband end coefficient */
+ const short *sfmsize, /* i : Subband band width */
+ const short last_sfm, /* i : last coded subband */
+ const short *R, /* i : bit allocation */
+ const short prev_is_transient, /* i : previous transient flag */
+ float *prev_normq, /* i/o: previous norms */
+ float *prev_env, /* i/o: previous noise envelopes */
+ short *bwe_seed, /* i/o: random seed for generating BWE input */
+ float *prev_coeff_out, /* i/o: decoded spectrum in previous frame */
+ short *prev_R, /* i/o: bit allocation info. in previous frame */
+ float *coeff_out /* o : coded/noisefilled spectrum */
+)
+{
+ short i;
+ short sfm;
+ short total_bit;
+ short num;
+
+ float bitalloc_var;
+ float sharp;
+ float mean;
+ float peak;
+ float fabs_coeff_out;
+ float harm_para;
+ float alfa = 0.5;
+ float env;
+ float step;
+ float min_coef;
+ float avrg_norm;
+ float prev_avrg_norm;
+
+ if( is_transient == 0 )
+ {
+ if( prev_bfi == 1 )
+ {
+ mvr2r(normq_v, prev_normq, SFM_N_WB);
+ }
+
+ /* the variance of bit allocation */
+ total_bit = 0;
+ bitalloc_var = 0.0f;
+ for (sfm = 8; sfm <= last_sfm; sfm++)
+ {
+ bitalloc_var += (float)abs(R[sfm] - R[sfm-1]);
+ total_bit += R[sfm];
+ }
+ bitalloc_var = (last_sfm > 8 && total_bit > 0) ? (bitalloc_var / total_bit) : 0;
+
+ /* calculate the peak-average ratio of saturable subbands */
+ num = 0;
+ sharp = EPSILON;
+ for(sfm = last_sfm; sfm >= 8; sfm--)
+ {
+ if(R[sfm] >= rat[sfm]*sfmsize[sfm])
+ {
+ peak = 0.0f;
+ mean = EPSILON;
+ for (i = sfm_start[sfm]; i < sfm_end[sfm]; i++)
+ {
+ fabs_coeff_out = (float)fabs(coeff_out[i]);
+ mean += fabs_coeff_out;
+ if(fabs_coeff_out > peak)
+ {
+ peak = fabs_coeff_out;
+ }
+ }
+ sharp += sfmsize[sfm]*peak/mean;
+ num ++;
+ }
+ }
+
+ sharp = (num != 0) ? 2.0f*num/sharp : 1.0f;
+ harm_para = sharp;
+ if( last_sfm == 0 )
+ {
+ step = 0;
+ }
+ else
+ {
+ step = 5.0f * sharp / last_sfm;
+ }
+ alfa = 2.5f;
+
+ /* fill noise for the insaturable subbands */
+ for( sfm = 0; sfm < num_sfm; sfm++ )
+ {
+ env = 0.0f;
+ if(R[sfm] != 0 && R[sfm] < 1.5f*sfmsize[sfm])
+ {
+ /* calculate the energy of the undecoded coefficients */
+ peak = 0.0f;
+ min_coef = FLT_MAX;
+ env = normq_v[sfm]*normq_v[sfm]*sfmsize[sfm];
+ for (i = sfm_start[sfm]; i < sfm_end[sfm]; i++)
+ {
+ fabs_coeff_out = (float)fabs(coeff_out[i]);
+ if(fabs_coeff_out < min_coef && coeff_out[i] != 0)
+ {
+ min_coef = fabs_coeff_out;
+ }
+ if(fabs_coeff_out > peak)
+ {
+ peak = fabs_coeff_out;
+ }
+ env -= coeff_out[i]*coeff_out[i];
+ }
+
+ if (env > 0 )
+ {
+ if(sfm == 0)
+ {
+ avrg_norm = normq_v[0] + normq_v[1] + normq_v[2];
+ prev_avrg_norm = prev_normq[0] + prev_normq[1] + prev_normq[2];
+ }
+ else if (sfm == 25)
+ {
+ avrg_norm = normq_v[23] + normq_v[24] + normq_v[25];
+ prev_avrg_norm = prev_normq[23] + prev_normq[24] + prev_normq[25];
+ }
+ else
+ {
+ avrg_norm = normq_v[sfm-1] + normq_v[sfm] + normq_v[sfm+1];
+ prev_avrg_norm = prev_normq[sfm-1] + prev_normq[sfm] + prev_normq[sfm+1];
+ }
+
+ if(bitalloc_var > 0.3f || 4.0f*normq_v[sfm] < peak)
+ {
+ /* calculate the noise magnitude of harmonic signal */
+ env = (float)(avrg_norm*harm_para *sqrt(env/sfmsize[sfm])/peak);
+ }
+ else
+ {
+ /* calculate the noise magnitude of normal signal */
+ env = sharp *(float)sqrt(env/sfmsize[sfm]);
+ if(alfa*normq_v[sfm] < peak)
+ {
+ env *= env/peak;
+ }
+ sharp += step;
+ }
+ if(env > 0.5f*min_coef)
+ {
+ env = 0.5f*min_coef;
+ }
+
+ if(prev_bfi == 1)
+ {
+ prev_env[sfm] = env;
+ }
+ /* smooth the noise magnitudes between inter-frame */
+ if(prev_avrg_norm > 0.5f*avrg_norm && prev_avrg_norm < 2.0f*avrg_norm && prev_is_transient == 0)
+ {
+ env = 0.5f*env + 0.5f*prev_env[sfm];
+ }
+
+ for (i = sfm_start[sfm]; i < sfm_end[sfm]; i++)
+ {
+ if (coeff[i] == 0)
+ {
+ coeff_out[i] = (float)( own_random(bwe_seed))/32768.0f;
+ coeff_out[i] *= env;
+ }
+ }
+ }
+ else
+ {
+ env = 0.0f;
+ }
+ }
+ else if(R[sfm] == 0)
+ {
+ /* fill random noise for 0 bit subbands */
+ for (i = sfm_start[sfm]; i < sfm_end[sfm]; i++)
+ {
+ if(coeff[i] == 0)
+ {
+ coeff_out[i] = (float)( own_random(bwe_seed))/32768.0f;
+ coeff_out[i] *= normq_v[sfm];
+ }
+ }
+
+ env = normq_v[sfm];
+ }
+ if(sfm == SFM_N_WB-1 && prev_is_transient == 0 && prev_normq[sfm] > 0.5f*normq_v[sfm] && prev_normq[sfm] < 2.0f*normq_v[sfm] && bitalloc_var <= 0.3f )
+ {
+ float *p_prev_coeff_out = prev_coeff_out;
+ for (i = sfm_start[sfm]+12; i < sfm_end[sfm]; i++)
+ {
+ if( fabs(coeff_out[i]) > 4.0f * fabs(*p_prev_coeff_out) ||
+ fabs(coeff_out[i]) < 0.25f * fabs(*p_prev_coeff_out) ||
+ (R[sfm] * (*prev_R) == 0 && R[sfm] + (*prev_R) != 0) )
+ {
+ coeff_out[i] = (coeff_out[i] > 0) ? (float)(0.5f*(fabs(coeff_out[i]) + fabs(*p_prev_coeff_out))) : (float)(-0.5f*(fabs(coeff_out[i]) + fabs(*p_prev_coeff_out)));
+ }
+ p_prev_coeff_out++;
+ }
+ }
+
+ prev_env[sfm] = env;
+ }
+ }
+ else
+ {
+ /* fill random noise for 0 bit subbands of transient frame */
+ for(sfm = 0; sfm < num_sfm; sfm++)
+ {
+ if( R[sfm] == 0 )
+ {
+ for (i = sfm_start[sfm]; i < sfm_end[sfm]; i++)
+ {
+ coeff_out[i] = (float)( own_random(bwe_seed))/32768.0f;
+ coeff_out[i] *= normq_v[sfm];
+ }
+ }
+ }
+
+ set_f( prev_env, 0, SFM_N_WB );
+ }
+
+ mvr2r(normq_v, prev_normq, SFM_N_WB);
+ mvr2r( coeff_out + L_FRAME16k - L_HQ_WB_BWE, prev_coeff_out, L_HQ_WB_BWE );
+ *prev_R = R[SFM_N_WB-1];
+
+ return;
+}
+
+
+/*--------------------------------------------------------------------------*
+ * enforce_zero_for_min_envelope()
+ *
+ * Detect minimum level of envelope and set corresponding bands to zero
+ *--------------------------------------------------------------------------*/
+
+void enforce_zero_for_min_envelope(
+ const short hqswb_clas, /* i : HQ coding mode */
+ const short *ynrm, /* i : Envelope indices */
+ float *coefsq, /* i/o: Quantized spectrum/zeroed spectrum */
+ short nb_sfm, /* i : Number of coded sub bands */
+ const short *sfm_start, /* i : Sub band start indices */
+ const short *sfm_end /* i : Sub band end indices */
+)
+{
+ short i, j;
+
+ /* prevent non-zero output for all-zero input */
+ if( hqswb_clas != HQ_HVQ )
+ {
+ if( ynrm[0] == 31 )
+ {
+ for( j = sfm_start[0]; j < sfm_end[0]; j++ )
+ {
+ coefsq[j] = 0.0f;
+ }
+ }
+
+ for( i = 1; i < nb_sfm; i++ )
+ {
+ if( ynrm[i] == 39 )
+ {
+ for( j = sfm_start[i]; j < sfm_end[i]; j++ )
+ {
+ coefsq[j] = 0.0f;
+ }
+ }
+ }
+ }
+
+ return;
+}
+
+
+/*--------------------------------------------------------------------------*
+ * overlap_hq_bwe()
+ *
+ * Overlapping at the boundary between HQ core and BWE
+ *--------------------------------------------------------------------------*/
+
+static void overlap_hq_bwe(
+ const float *hq_swb_overlap_buf, /* i : spectrum from HQ core */
+ float *coeff_out, /* i/o: spectrum from BWE, overlapped output */
+ const short n_swb_overlap_offset, /* i : starting offset of overlapping */
+ const short n_swb_overlap, /* i : length of overlapping */
+ const short *R, /* i : Bit allocation */
+ const short num_env_bands, /* i : Number of coded envelope bands */
+ const short num_sfm, /* i : Number of bands */
+ const short *sfm_end /* i : Band end indices */
+)
+{
+ short i;
+ float step;
+ float weighting;
+ short n_band;
+
+ if (R[num_env_bands-1] != 0)
+ {
+ mvr2r( hq_swb_overlap_buf, &coeff_out[n_swb_overlap_offset], n_swb_overlap );
+ }
+ else
+ {
+ /*weighting = 0.8f;*/
+ step = 1.0f / (float)n_swb_overlap;
+ weighting = 1.0f;
+ for (i = 0; i < n_swb_overlap; i++)
+ {
+ coeff_out[n_swb_overlap_offset+i] = hq_swb_overlap_buf[i] * weighting + coeff_out[n_swb_overlap_offset+i] * (1.0f - weighting);
+ weighting -= step;
+ }
+ }
+
+
+ for (n_band = num_env_bands; n_band < num_sfm; n_band++)
+ {
+ if (R[n_band] !=0 )
+ {
+ for(i=sfm_end[n_band-1]; i> 1;
+ accY = my >> 1;
+ align = *ex - ey;
+ if (align < 0)
+ {
+ if( align > -32) /* If align < -32, (accY >> (-align) = 0 */
+ {
+ accX = accX + (accY >> (-align));
+ }
+ }
+ else
+ {
+ if( align < 32) /* If align > 32, (accX >> align) = 0 */
+ {
+ accX = accY + (accX >> align);
+ }
+ else
+ {
+ accX = accY;
+ }
+ *ex = ey;
+ }
+
+#define WMC_TOOL_SKIP
+ expo = norm_l(accX); /* aligned to BASOP */
+#undef WMC_TOOL_SKIP
+ *mx = accX << expo;
+ *ex = *ex + expo - 1;
+
+ return;
+}
diff --git a/lib_com/hvq_pvq_bitalloc.c b/lib_com/hvq_pvq_bitalloc.c
new file mode 100644
index 0000000000000000000000000000000000000000..3f3b80a2a1509ac8a91a06ede13d3ecf1c7b91ab
--- /dev/null
+++ b/lib_com/hvq_pvq_bitalloc.c
@@ -0,0 +1,157 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include
+#include "wmc_auto.h"
+#include "options.h"
+#include "cnst.h"
+#include "prot.h"
+#include "rom_com.h"
+
+/*--------------------------------------------------------------------------*/
+/* Function hvq_pvq_bitalloc */
+/* ~~~~~~~~~~~~~~~~~~~~~~~~ */
+/* */
+/* Calculate the number of PVQ bands to code and allocate bits based on */
+/* the number of available bits. */
+/*--------------------------------------------------------------------------*/
+
+short hvq_pvq_bitalloc(
+ short num_bits, /* i/o: Number of available bits (including gain bits) */
+ const short brate, /* i : bitrate */
+ const short bwidth, /* i : Encoded bandwidth */
+ const short *ynrm, /* i : Envelope coefficients */
+ const int manE_peak, /* i : Peak energy mantissa */
+ const short expE_peak, /* i : Peak energy exponent */
+ short *Rk, /* o : bit allocation for concatenated vector */
+ short *R, /* i/o: Global bit allocation */
+ short *sel_bands, /* o : Selected bands for encoding */
+ short *n_sel_bands /* o : No. of selected bands for encoding */
+)
+{
+ short num_bands, k, band_max_bits;
+ short k_max;
+ short k_start;
+ float E_max;
+ int E_max5;
+ short expo;
+ short align;
+ int acc;
+ float tmp;
+ int env_mean;
+ short reciprocal;
+ short num_sfm;
+ short bit_cost;
+
+ if (bwidth == FB)
+ {
+ num_sfm = SFM_N_HARM_FB;
+ }
+ else
+ {
+ num_sfm = SFM_N_HARM;
+ }
+
+ if (brate == HQ_24k40)
+ {
+ band_max_bits = HVQ_BAND_MAX_BITS_24k;
+ k_start = HVQ_THRES_SFM_24k;
+ if (bwidth == FB)
+ {
+ reciprocal = 2731;
+ }
+ else
+ {
+ reciprocal = 3277;
+ }
+ }
+ else
+ {
+ band_max_bits = HVQ_BAND_MAX_BITS_32k;
+ k_start = HVQ_THRES_SFM_32k;
+ if (bwidth == FB)
+ {
+ reciprocal = 3641;
+ }
+ else
+ {
+ reciprocal = 4681;
+ }
+ }
+
+ num_bands = num_bits / band_max_bits;
+ num_bits = num_bits - num_bands*band_max_bits;
+
+ if (num_bits >= HVQ_NEW_BAND_BIT_THR)
+ {
+ num_bands++;
+ }
+ else
+ {
+ num_bits += band_max_bits;
+ }
+
+ /* safety check in case of bit errors */
+ if (num_bands < 1)
+ {
+ return 0;
+ }
+
+ *n_sel_bands = 0;
+ env_mean = 0;
+ E_max = 0;
+ k_max = k_start;
+ for ( k = k_start; k < num_sfm; k++ )
+ {
+ tmp = dicn[ynrm[k]];
+ env_mean += ynrm[k];
+ if( tmp > E_max )
+ {
+ E_max = tmp;
+ k_max = k;
+ }
+ }
+ env_mean = 2*((int)env_mean * (int)reciprocal);
+
+ if(band_len_harm[k_max] == 96)
+ {
+ bit_cost = 61;
+ }
+ else
+ {
+ QuantaPerDsDirac(band_len_harm[k_max], 1, hBitsN, &bit_cost);
+ }
+
+
+ expo = max(0, ynrm[k_max]-1) >> 1;
+ E_max5 = E_max5_tbl[ynrm[k_max]];
+ align = expo - expE_peak;
+ align = align + (19 - 14) - (31 - 2*12);
+ if (align < 0)
+ {
+ acc = E_max5 - (manE_peak >> -align);
+ }
+ else
+ {
+ acc = (E_max5 >> align) - manE_peak;
+ }
+ if ( acc > 0
+ && ((env_mean - (ynrm[k_max]<<16)) > 0x30000L)
+ && num_bands > 1
+ && (num_bits - HVQ_PVQ_GAIN_BITS)<<3 >= bit_cost )
+ {
+ sel_bands[*n_sel_bands] = k_max;
+ (*n_sel_bands)++;
+ R[k_max] = 1; /* Mark that the band has been encoded for fill_spectrum */
+ }
+
+ /* Allocate bits */
+ for (k = 0; k < num_bands-1; k++)
+ {
+ Rk[k] = band_max_bits-HVQ_PVQ_GAIN_BITS;
+ }
+ Rk[num_bands-1] = num_bits-HVQ_PVQ_GAIN_BITS;
+
+ return num_bands;
+}
diff --git a/lib_com/ifft_rel.c b/lib_com/ifft_rel.c
new file mode 100644
index 0000000000000000000000000000000000000000..a9357ea510dddd0c6c35c57db777093adb502e50
--- /dev/null
+++ b/lib_com/ifft_rel.c
@@ -0,0 +1,256 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include "options.h"
+#include "wmc_auto.h"
+#include "prot.h"
+#include "rom_com.h"
+
+
+/*-----------------------------------------------------------------*
+ * Local constants
+ *-----------------------------------------------------------------*/
+
+#define N_MAX_FFT 1024
+#define INV_SQR2 0.70710676908493f
+
+/*---------------------------------------------------------------------*
+ * ifft_rel()
+ *
+ * Calculate the inverse FFT of a real signal
+ *
+ * Based on the FORTRAN code from the article "Real-valued Fast Fourier Transform Algorithms"
+ * by Sorensen, ... in IEEE Trans. on ASSP, Vol. ASSP-35, No. June 6th 1987.
+ *
+ * Input: the io[] signal containing the spectrum in the following order :
+ *
+ * Re[0], Re[1], .. Re[n/2], Im[n/2-1], .. Im[1]
+ *---------------------------------------------------------------------*/
+
+void ifft_rel(
+ float io[], /* i/o: input/output vector */
+ const short n, /* i : vector length */
+ const short m /* i : log2 of vector length */
+)
+{
+ short i, j, k;
+ short step;
+ short n2, n4, n8, i0;
+ short is, id;
+ float *x,*xi0, *xi1, *xi2, *xi3, *xi4, *xup1, *xdn6, *xup3, *xdn8;
+ float xt;
+ float r1;
+ float t1, t2, t3, t4, t5;
+ float cc1, cc3, ss1, ss3;
+ const float *s, *s3, *c, *c3;
+ const short *idx;
+ float temp[512];
+ float n_inv;
+
+ n_inv = 1.0f/n;
+
+ /*-----------------------------------------------------------------*
+ * IFFT
+ *-----------------------------------------------------------------*/
+
+ x = &io[-1];
+ n2 = 2*n;
+ for (k=1; k> 1;
+ n4 = n2 >> 2;
+ n8 = n4 >> 1;
+ while (is < n-1)
+ {
+ xi1 = x + is + 1;
+ xi2 = xi1 + n4;
+ xi3 = xi2 + n4;
+ xi4 = xi3 + n4;
+
+ for (i=is; i>1)];
+ }
+ }
+ else if (n == 256)
+ {
+ for (i=0; i> 1;
+ while (k < j)
+ {
+ j = j - k;
+ k = k >> 1;
+ }
+ j = j + k;
+ }
+ }
+
+ /*-----------------------------------------------------------------*
+ * Normalization
+ *-----------------------------------------------------------------*/
+
+ for (i=1; i<=n; i++)
+ {
+ x[i] = xi0[i] * n_inv;
+ }
+
+ return;
+}
diff --git a/lib_com/igf_base.c b/lib_com/igf_base.c
new file mode 100644
index 0000000000000000000000000000000000000000..de22c9f760d0ad633de8eef763bf953d360f25f5
--- /dev/null
+++ b/lib_com/igf_base.c
@@ -0,0 +1,641 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include
+#include "wmc_auto.h"
+#include "options.h"
+#include "prot.h"
+#include "rom_com.h"
+
+/*---------------------------------------------------------------------*
+ * IGF_ApplyTransFac()
+ *
+ *
+ *---------------------------------------------------------------------*/
+
+static int IGF_ApplyTransFac( /**< out: | multiplication factor */
+ const int val, /**< in: Q15 | input value for multiplication, Q15 */
+ const float transFac /**< in: Q14 | multiplicator for variable val, Q14: 1.25f=0x5000, 1.0f=0x4000, 0.5f=0x2000 */
+)
+{
+ int ret = val;
+
+ if (transFac!=1.f)
+ {
+ ret = round_f(val*transFac);
+ ret +=(ret & 1);
+ }
+
+ return ret;
+}
+
+
+/*---------------------------------------------------------------------*
+ * IGF_MapBitRateToIndex()
+ *
+ * maps a given bitrate to the IGF_BITRATE index
+ *---------------------------------------------------------------------*/
+
+static short IGF_MapBitRateToIndex( /**< out: Q0 | return bit rate index */
+ int bitRate, /**< in: | bitrate */
+ int mode, /**< in: | bandwidth mode */
+ int rf_mode /**< in: | flag to signal the RF mode */
+)
+{
+ short bitRateIndex = IGF_BITRATE_UNKNOWN;
+
+ switch (mode)
+ {
+ case IGF_MODE_WB:
+ switch (bitRate)
+ {
+ case 13200:
+ if (rf_mode == 1)
+ {
+ bitRateIndex = IGF_BITRATE_RF_WB_13200;
+ }
+ break;
+ case 9600:
+ bitRateIndex = IGF_BITRATE_WB_9600;
+ break;
+ default:
+ assert(0);
+ }
+ break;
+ case IGF_MODE_SWB:
+ switch (bitRate)
+ {
+ case 9600:
+ bitRateIndex = IGF_BITRATE_SWB_9600;
+ break;
+ case 13200:
+ bitRateIndex = IGF_BITRATE_SWB_13200;
+ if (rf_mode == 1)
+ {
+ bitRateIndex = IGF_BITRATE_RF_SWB_13200;
+ }
+ break;
+ case 16400:
+ bitRateIndex = IGF_BITRATE_SWB_16400;
+ break;
+ case 24400:
+ bitRateIndex = IGF_BITRATE_SWB_24400;
+ break;
+ case 32000:
+ bitRateIndex = IGF_BITRATE_SWB_32000;
+ break;
+ case 48000:
+ bitRateIndex = IGF_BITRATE_SWB_48000;
+ break;
+ default:
+ assert(0);
+ }
+ break;
+ case IGF_MODE_FB:
+ switch (bitRate)
+ {
+ case 16400:
+ bitRateIndex = IGF_BITRATE_FB_16400;
+ break;
+ case 24400:
+ bitRateIndex = IGF_BITRATE_FB_24400;
+ break;
+ case 32000:
+ bitRateIndex = IGF_BITRATE_FB_32000;
+ break;
+ case 48000:
+ bitRateIndex = IGF_BITRATE_FB_48000;
+ break;
+ case 96000:
+ bitRateIndex = IGF_BITRATE_FB_96000;
+ break;
+ case 128000:
+ bitRateIndex = IGF_BITRATE_FB_128000;
+ break;
+ default:
+ assert(0);
+ }
+ break;
+ default:
+ assert(0);
+ }
+
+ return bitRateIndex;
+}
+
+
+/*---------------------------------------------------------------------*
+ * IGF_gridSetUp()
+ *
+ * IGF grid setup
+ *---------------------------------------------------------------------*/
+
+static void IGF_gridSetUp(
+ H_IGF_GRID hGrid, /**< out: | IGF grid handle */
+ short bitRateIndex, /**< in: | IGF bitrate index */
+ int sampleRate, /**< in: | sample rate */
+ int frameLength, /**< in: | frame length */
+ float transFac, /**< in: | transFac */
+ int igfMinFq /**< in: | IGF minimum frequency indicating lower start frequency for copy up */
+)
+{
+ int t;
+ int sfb;
+ int swb_offset_len;
+ int wrp_sfb;
+ const int *swb_offset;
+ float bandwidth;
+
+ /* inits */
+ swb_offset = NULL;
+ swb_offset_len = 0;
+
+ switch (bitRateIndex)
+ {
+ case IGF_BITRATE_WB_9600:
+ case IGF_BITRATE_RF_WB_13200:
+ case IGF_BITRATE_SWB_9600:
+ case IGF_BITRATE_RF_SWB_13200:
+ case IGF_BITRATE_SWB_13200:
+ case IGF_BITRATE_SWB_16400:
+ case IGF_BITRATE_SWB_24400:
+ case IGF_BITRATE_SWB_32000:
+ case IGF_BITRATE_SWB_48000:
+ swb_offset = &swb_offset_LB_new[bitRateIndex][1];
+ swb_offset_len = swb_offset_LB_new[bitRateIndex][0];
+ mvr2r(&igf_whitening_TH[(int)bitRateIndex][0][0], &hGrid->whiteningThreshold[0][0], IGF_MAX_TILES * 2);
+ break;
+ case IGF_BITRATE_FB_16400:
+ case IGF_BITRATE_FB_24400:
+ case IGF_BITRATE_FB_32000:
+ swb_offset = &swb_offset_LB_new[bitRateIndex][1];
+ swb_offset_len = swb_offset_LB_new[bitRateIndex][0];
+ mvr2r(&igf_whitening_TH[(int)bitRateIndex][0][0], &hGrid->whiteningThreshold[0][0], IGF_MAX_TILES * 2);
+ break;
+ case IGF_BITRATE_FB_48000:
+ case IGF_BITRATE_FB_96000:
+ case IGF_BITRATE_FB_128000:
+ swb_offset = &swb_offset_LB_new[bitRateIndex][1];
+ swb_offset_len = swb_offset_LB_new[bitRateIndex][0];
+ mvr2r(&igf_whitening_TH[(int)bitRateIndex][0][0], &hGrid->whiteningThreshold[0][0], IGF_MAX_TILES * 2);
+ break;
+ case IGF_BITRATE_UNKNOWN:
+ default:
+ assert(0);
+ }
+
+ for(sfb = 0; sfb < swb_offset_len; sfb++)
+ {
+ hGrid->swb_offset[sfb] = IGF_ApplyTransFac(swb_offset[sfb], transFac);
+ }
+
+ hGrid->infoIsRefined = 0;
+ frameLength = IGF_ApplyTransFac(frameLength, transFac);
+ bandwidth = (float)sampleRate / 2.0f / (float)frameLength;
+ hGrid->swb_offset_len = swb_offset_len;
+ hGrid->startSfb = 0;
+ hGrid->stopSfb = hGrid->swb_offset_len-1;
+ hGrid->startLine = hGrid->swb_offset[ hGrid->startSfb ];
+ hGrid->stopLine = hGrid->swb_offset[ hGrid->stopSfb ];
+ hGrid->startFrequency = round_f(bandwidth * hGrid->startLine);
+ hGrid->stopFrequency = round_f(bandwidth * hGrid->stopLine);
+ hGrid->minSrcSubband = round_f((igfMinFq * (frameLength)) / (sampleRate >> 1));
+ hGrid->minSrcSubband += hGrid->minSrcSubband % 2;
+ hGrid->minSrcFrequency = round_f(bandwidth * hGrid->minSrcSubband);
+ hGrid->infoGranuleLen = frameLength;
+ hGrid->infoTransFac = transFac;
+ hGrid->sfbWrap[0] = 0;
+ hGrid->tile[0] = hGrid->startLine;
+
+ switch (bitRateIndex)
+ {
+ /* SWB 13200 */
+ case IGF_BITRATE_WB_9600:
+ hGrid->nTiles = 2;
+ wrp_sfb = 2;
+
+ /*1st*/
+ hGrid->sfbWrap[0+1] = wrp_sfb;
+ hGrid->sbWrap[0] = hGrid->minSrcSubband;
+ hGrid->tile[0+1] = hGrid->swb_offset[wrp_sfb];
+
+ /*2nd*/
+ hGrid->sfbWrap[1+1] = hGrid->stopSfb;
+ hGrid->sbWrap[1] = hGrid->minSrcSubband;
+ hGrid->tile[1+1] = hGrid->swb_offset[hGrid->stopSfb];
+
+ break;
+ case IGF_BITRATE_RF_WB_13200:
+ hGrid->nTiles = 2;
+ wrp_sfb = 2;
+
+ /*1st*/
+ hGrid->sfbWrap[0+1] = wrp_sfb;
+ hGrid->sbWrap[0] = hGrid->minSrcSubband;
+ hGrid->tile[0+1] = hGrid->swb_offset[wrp_sfb];
+
+ /*2nd*/
+ hGrid->sfbWrap[1+1] = hGrid->stopSfb;
+ hGrid->sbWrap[1] = hGrid->minSrcSubband;
+ hGrid->tile[1+1] = hGrid->swb_offset[hGrid->stopSfb];
+
+ break;
+ case IGF_BITRATE_SWB_9600:
+ hGrid->nTiles = 3;
+ wrp_sfb = 1;
+
+ /*1st*/
+ hGrid->sfbWrap[0+1] = wrp_sfb;
+ hGrid->sbWrap[0] = hGrid->minSrcSubband;
+ hGrid->tile[0+1] = hGrid->swb_offset[wrp_sfb];
+
+ /*2nd*/
+ wrp_sfb = 2;
+ hGrid->sfbWrap[1+1] = wrp_sfb;
+ hGrid->sbWrap[1] = hGrid->minSrcSubband + IGF_ApplyTransFac(32, transFac);
+ hGrid->tile[1+1] = hGrid->swb_offset[wrp_sfb];
+
+ /*3rd*/
+ hGrid->sfbWrap[2+1] = hGrid->stopSfb;
+ hGrid->sbWrap[2] = hGrid->minSrcSubband + IGF_ApplyTransFac(46, transFac);
+ hGrid->tile[2+1] = hGrid->swb_offset[hGrid->stopSfb];
+
+ break;
+ case IGF_BITRATE_RF_SWB_13200:
+ hGrid->nTiles = 3;
+ wrp_sfb = 1;
+
+ /*1st*/
+ hGrid->sfbWrap[0+1] = wrp_sfb;
+ hGrid->sbWrap[0] = hGrid->minSrcSubband;
+ hGrid->tile[0+1] = hGrid->swb_offset[wrp_sfb];
+
+ /*2nd*/
+ wrp_sfb = 2;
+ hGrid->sfbWrap[1+1] = wrp_sfb;
+ hGrid->sbWrap[1] = hGrid->minSrcSubband + IGF_ApplyTransFac(32, transFac);
+ hGrid->tile[1+1] = hGrid->swb_offset[wrp_sfb];
+
+ /*3rd*/
+ hGrid->sfbWrap[2+1] = hGrid->stopSfb;
+ hGrid->sbWrap[2] = hGrid->minSrcSubband + IGF_ApplyTransFac(46, transFac);
+ hGrid->tile[2+1] = hGrid->swb_offset[hGrid->stopSfb];
+ break;
+ case IGF_BITRATE_SWB_13200:
+ hGrid->nTiles = 2;
+ wrp_sfb = 4;
+
+ /*1st*/
+ hGrid->sfbWrap[0+1] = wrp_sfb;
+ hGrid->sbWrap[0] = hGrid->minSrcSubband;
+ hGrid->tile[0+1] = hGrid->swb_offset[wrp_sfb];
+
+ /*2nd*/
+ hGrid->sfbWrap[1+1] = hGrid->stopSfb;
+ hGrid->sbWrap[1] = hGrid->minSrcSubband + IGF_ApplyTransFac(32, transFac);
+ hGrid->tile[1+1] = hGrid->swb_offset[hGrid->stopSfb];
+
+ break;
+ case IGF_BITRATE_SWB_16400:
+ hGrid->nTiles = 3;
+ wrp_sfb = 4;
+
+ /*1st*/
+ hGrid->sfbWrap[0+1] = wrp_sfb;
+ hGrid->sbWrap[0] = hGrid->minSrcSubband;
+ hGrid->tile[0+1] = hGrid->swb_offset[wrp_sfb];
+
+ /*2nd*/
+ hGrid->sfbWrap[1+1] = 6;
+ hGrid->sbWrap[1] = hGrid->minSrcSubband + IGF_ApplyTransFac(48, transFac);
+ hGrid->tile[1+1] = hGrid->swb_offset[6];
+
+ /*3nd*/
+ hGrid->sfbWrap[2+1] = hGrid->stopSfb;
+ hGrid->sbWrap[2] = hGrid->minSrcSubband + IGF_ApplyTransFac(64, transFac);
+ hGrid->tile[2+1] = hGrid->swb_offset[hGrid->stopSfb];
+
+ break;
+ case IGF_BITRATE_SWB_24400:
+ case IGF_BITRATE_SWB_32000:
+ hGrid->nTiles = 3;
+ wrp_sfb = 4;
+
+ /*1st*/
+ hGrid->sfbWrap[0+1] = wrp_sfb;
+ hGrid->sbWrap[0] = hGrid->minSrcSubband;
+ hGrid->tile[0+1] = hGrid->swb_offset[wrp_sfb];
+
+ /*2nd*/
+ hGrid->sfbWrap[1+1] = 7;
+ hGrid->sbWrap[1] = hGrid->minSrcSubband + IGF_ApplyTransFac(32, transFac);
+ hGrid->tile[1+1] = hGrid->swb_offset[7];
+
+ /*3nd*/
+ hGrid->sfbWrap[2+1] = hGrid->stopSfb;
+ hGrid->sbWrap[2] = hGrid->minSrcSubband + IGF_ApplyTransFac(64, transFac);
+ hGrid->tile[2+1] = hGrid->swb_offset[hGrid->stopSfb];
+ break;
+ case IGF_BITRATE_SWB_48000:
+ hGrid->nTiles = 1;
+ wrp_sfb = hGrid->stopSfb;
+
+ /*1st*/
+ hGrid->sfbWrap[0+1] = hGrid->stopSfb;
+ hGrid->sbWrap[0] = 2*hGrid->startLine - hGrid->stopLine;
+ hGrid->tile[0+1] = hGrid->swb_offset[hGrid->stopSfb];
+
+ break;
+ case IGF_BITRATE_FB_16400:
+ hGrid->nTiles = 3;
+ wrp_sfb = 4;
+
+ /*1st*/
+ hGrid->sfbWrap[0+1] = wrp_sfb;
+ hGrid->sbWrap[0] = hGrid->minSrcSubband;
+ hGrid->tile[0+1] = hGrid->swb_offset[wrp_sfb];
+ wrp_sfb = 7;
+
+ /*2nd*/
+ hGrid->sfbWrap[1+1] = wrp_sfb;
+ hGrid->sbWrap[1] = hGrid->minSrcSubband;
+ hGrid->tile[1+1] = hGrid->swb_offset[wrp_sfb];
+
+ /*3nd*/
+ hGrid->sfbWrap[2+1] = hGrid->stopSfb;
+ hGrid->sbWrap[2] = hGrid->minSrcSubband;
+ hGrid->tile[2+1] = hGrid->swb_offset[hGrid->stopSfb];
+
+ break;
+ case IGF_BITRATE_FB_24400:
+ case IGF_BITRATE_FB_32000:
+ hGrid->nTiles = 4;
+ wrp_sfb = 4;
+
+ /*1st*/
+ hGrid->sfbWrap[0+1] = wrp_sfb;
+ hGrid->sbWrap[0] = hGrid->minSrcSubband;
+ hGrid->tile[0+1] = hGrid->swb_offset[wrp_sfb];
+ wrp_sfb = 6;
+
+ /*2nd*/
+ hGrid->sfbWrap[1+1] = wrp_sfb;
+ hGrid->sbWrap[1] = hGrid->minSrcSubband + IGF_ApplyTransFac(32, transFac);
+ hGrid->tile[1+1] = hGrid->swb_offset[wrp_sfb];
+ wrp_sfb = 9;
+
+ /*3nd*/
+ hGrid->sfbWrap[2+1] = wrp_sfb;
+ hGrid->sbWrap[2] = hGrid->minSrcSubband;
+ hGrid->tile[2+1] = hGrid->swb_offset[wrp_sfb];
+
+ /*4nd*/
+ hGrid->sfbWrap[3+1] = hGrid->stopSfb;
+ hGrid->sbWrap[3] = hGrid->minSrcSubband + (hGrid->swb_offset[9] - hGrid->swb_offset[8]);
+ hGrid->tile[3+1] = hGrid->swb_offset[hGrid->stopSfb];
+ break;
+ case IGF_BITRATE_FB_48000:
+ case IGF_BITRATE_FB_96000:
+ case IGF_BITRATE_FB_128000:
+ hGrid->nTiles = 1;
+
+ /*1st*/
+ hGrid->sfbWrap[0+1] = hGrid->stopSfb;
+ hGrid->sbWrap[0] = 2*hGrid->startLine - hGrid->stopLine;
+ hGrid->tile[0+1] = hGrid->swb_offset[hGrid->stopSfb];
+
+ break;
+ default:
+ assert(0);
+ }/*switch*/
+
+
+ /* adapt level envelope: */
+ switch(bitRateIndex)
+ {
+ case IGF_BITRATE_RF_WB_13200:
+ case IGF_BITRATE_WB_9600:
+ hGrid->gFactor = 0.800f;
+ hGrid->fFactor = 0.70f;
+ hGrid->lFactor = 0.60f;
+ break;
+ case IGF_BITRATE_SWB_13200:
+ case IGF_BITRATE_FB_16400:
+ case IGF_BITRATE_SWB_16400:
+ hGrid->gFactor = 0.930f;
+ hGrid->fFactor = 0.20f;
+ hGrid->lFactor = 0.85f;
+ break;
+ case IGF_BITRATE_FB_24400:
+ case IGF_BITRATE_SWB_24400:
+ case IGF_BITRATE_FB_32000:
+ case IGF_BITRATE_SWB_32000:
+ hGrid->gFactor = 0.965f;
+ hGrid->fFactor = 0.20f;
+ hGrid->lFactor = 0.85f;
+ break;
+ case IGF_BITRATE_FB_48000:
+ case IGF_BITRATE_SWB_48000:
+ hGrid->gFactor = 1.000f;
+ hGrid->fFactor = 0.20f;
+ hGrid->lFactor = 1.000f;
+ break;
+ case IGF_BITRATE_SWB_9600:
+ case IGF_BITRATE_RF_SWB_13200:
+ default:
+ hGrid->gFactor = 1.000f;
+ hGrid->fFactor = 0.00f;
+ hGrid->lFactor = 1.000f;
+ }
+
+ for ( t = hGrid->nTiles+1; t < IGF_MAX_TILES; t++)
+ {
+ hGrid->tile[t] = 0;
+ hGrid->sbWrap[t - 1] = 0;
+ hGrid->sfbWrap[t] = 0;
+ }
+
+ return;
+}
+
+
+/*---------------------------------------------------------------------*
+ * IGFCommonFuncsWriteSerialBit()
+ *
+ * write bits to bitstream
+ *---------------------------------------------------------------------*/
+
+void IGFCommonFuncsWriteSerialBit(
+ void *st, /**< in: | encoder/decoder state structure */
+ int *pBitOffset, /**< out: | bit offset */
+ int bit /**< in: | value of bit */
+)
+{
+ if (st)
+ {
+ push_next_indice(st, bit, 1);
+ }
+ (*pBitOffset)++;
+
+ return;
+}
+
+
+/*---------------------------------------------------------------------*
+ * IGFCommonFuncsIGFConfiguration()
+ *
+ * changes the IGF configuration
+ *---------------------------------------------------------------------*/
+
+int IGFCommonFuncsIGFConfiguration( /**< out: | error value: 0 -> error, 1 -> ok */
+ int bitRate, /**< in: | bitrate in bs e.g. 9600 for 9.6kbs */
+ int mode, /**< in: | bandwidth mode */
+ H_IGF_INFO hIGFInfo, /**< out: | IGF info handle */
+ int rf_mode /**< in: flag to signal the RF mode */
+)
+{
+ H_IGF_GRID hGrid;
+ int retValue;
+ int sampleRate;
+ int frameLength;
+ int igfMinFq;
+ int maxHopsize;
+
+ retValue = 0; /* bitrate index is unknown -> error! */
+
+ /* interface call for reading in settings */
+ hIGFInfo->bitRateIndex = IGF_MapBitRateToIndex( bitRate, mode, rf_mode );
+
+ if (hIGFInfo->bitRateIndex != IGF_BITRATE_UNKNOWN)
+ {
+ retValue = 1; /* no error */
+
+ /* mapping to local values */
+ sampleRate = igfMode[(int)hIGFInfo->bitRateIndex].sampleRate;
+ frameLength = igfMode[(int)hIGFInfo->bitRateIndex].frameLength;
+ igfMinFq = igfMode[(int)hIGFInfo->bitRateIndex].igfMinFq;
+ maxHopsize = igfMode[(int)hIGFInfo->bitRateIndex].maxHopsize;
+
+ /* basic information */
+ hIGFInfo->sampleRate = sampleRate;
+ hIGFInfo->frameLength = frameLength;
+ hIGFInfo->maxHopsize = maxHopsize;
+ hIGFInfo->nfSeed = 0;
+
+ /* set up regular IGF grid for TCX 20 (transfac = 1.f) */
+ hGrid = &hIGFInfo->grid[IGF_GRID_LB_NORM];
+ IGF_gridSetUp(hGrid, hIGFInfo->bitRateIndex, sampleRate, frameLength, 1.00f, igfMinFq );
+
+ /* set up IGF grid for CELP->TCX 20 transitions (transfac = 1.25) */
+ hGrid = &hIGFInfo->grid[IGF_GRID_LB_TRAN];
+ IGF_gridSetUp( hGrid, hIGFInfo->bitRateIndex, sampleRate, frameLength, 1.25f, igfMinFq );
+
+ /* set up IGF grid for TCX 10 (transfac = 0.5) */
+ hGrid = &hIGFInfo->grid[IGF_GRID_LB_SHORT];
+ IGF_gridSetUp( hGrid, hIGFInfo->bitRateIndex, sampleRate, frameLength, 0.50f, igfMinFq );
+ }
+
+ return retValue;
+}
+
+
+/*---------------------------------------------------------------------*
+ * IGFCommonFuncsIGFGetCFTables()
+ *
+ * selects cumulative frequency tables and offsets for the IGF SCF arithmetic coder
+ *---------------------------------------------------------------------*/
+
+int IGFCommonFuncsIGFGetCFTables( /**< out: | error value: 0 -> error, 1 -> ok */
+ int bitRate, /**< in: | bitrate in bs e.g. 9600 for 9.6kbs */
+ int mode, /**< in: | bandwidth mode */
+ int rf_mode, /**< in: | flag to signal the RF mode */
+ const unsigned short **cf_se00, /**< out: | CF table for t == 0 and f == 0 */
+ const unsigned short **cf_se01, /**< out: | CF table for t == 0 and f == 1 */
+ short *cf_off_se01, /**< out: | offset for CF table above */
+ const unsigned short **cf_se02, /**< out: | CF tables for t == 0 and f >= 2 */
+ const short **cf_off_se02, /**< out: | offsets for CF tables above */
+ const unsigned short **cf_se10, /**< out: | CF table for t == 1 and f == 0 */
+ short *cf_off_se10, /**< out: | offset for CF table above */
+ const unsigned short **cf_se11, /**< out: | CF tables for t == 1 and f >= 1 */
+ const short **cf_off_se11 /**< out: | offsets for CF tables above */
+)
+{
+ int retValue;
+ short bitRateIndex;
+
+ retValue = 0; /* bitrate index is unknown -> error! */
+ bitRateIndex = IGF_MapBitRateToIndex( bitRate, mode, rf_mode );
+
+ if(bitRateIndex != IGF_BITRATE_UNKNOWN)
+ {
+ retValue = 1; /* no error */
+
+ switch(bitRateIndex)
+ {
+ case IGF_BITRATE_WB_9600:
+ case IGF_BITRATE_RF_WB_13200:
+ case IGF_BITRATE_SWB_9600:
+ case IGF_BITRATE_SWB_13200:
+ case IGF_BITRATE_RF_SWB_13200:
+ case IGF_BITRATE_SWB_16400:
+ case IGF_BITRATE_SWB_24400:
+ case IGF_BITRATE_SWB_32000:
+ case IGF_BITRATE_SWB_48000:
+ *cf_se00 = cf_se00_tab;
+ *cf_se01 = cf_se01_tab[bitRateIndex];
+ *cf_off_se01 = cf_off_se01_tab[bitRateIndex];
+ *cf_se02 = &cf_se02_tab[bitRateIndex][0][0];
+ *cf_off_se02 = &cf_off_se02_tab[bitRateIndex][0];
+ *cf_se10 = &cf_se10_tab[0];
+ *cf_off_se10 = cf_off_se10_tab;
+ *cf_se11 = &cf_se11_tab[0][0][0];
+ *cf_off_se11 = &cf_off_se11_tab[0][0];
+ break;
+ case IGF_BITRATE_FB_16400:
+ case IGF_BITRATE_FB_24400:
+ case IGF_BITRATE_FB_32000:
+ bitRateIndex = bitRateIndex-IGF_BITRATE_FB_16400+IGF_BITRATE_SWB_16400;
+ *cf_se00 = cf_se00_tab;
+ *cf_se01 = cf_se01_tab[bitRateIndex];
+ *cf_off_se01 = cf_off_se01_tab[bitRateIndex];
+ *cf_se02 = &cf_se02_tab[bitRateIndex][0][0];
+ *cf_off_se02 = &cf_off_se02_tab[bitRateIndex][0];
+ *cf_se10 = &cf_se10_tab[0];
+ *cf_off_se10 = cf_off_se10_tab;
+ *cf_se11 = &cf_se11_tab[0][0][0];
+ *cf_off_se11 = &cf_off_se11_tab[0][0];
+ break;
+ case IGF_BITRATE_FB_48000:
+ bitRateIndex = bitRateIndex-IGF_BITRATE_FB_48000+IGF_BITRATE_SWB_48000;
+ *cf_se00 = cf_se00_tab;
+ *cf_se01 = cf_se01_tab[bitRateIndex];
+ *cf_off_se01 = cf_off_se01_tab[bitRateIndex];
+ *cf_se02 = &cf_se02_tab[bitRateIndex][0][0];
+ *cf_off_se02 = &cf_off_se02_tab[bitRateIndex][0];
+ *cf_se10 = &cf_se10_tab[0];
+ *cf_off_se10 = cf_off_se10_tab;
+ *cf_se11 = &cf_se11_tab[0][0][0];
+ *cf_off_se11 = &cf_off_se11_tab[0][0];
+ break;
+ case IGF_BITRATE_FB_96000:
+ case IGF_BITRATE_FB_128000:
+ bitRateIndex = IGF_BITRATE_SWB_48000;
+ *cf_se00 = cf_se00_tab;
+ *cf_se01 = cf_se01_tab[bitRateIndex];
+ *cf_off_se01 = cf_off_se01_tab[bitRateIndex];
+ *cf_se02 = &cf_se02_tab[bitRateIndex][0][0];
+ *cf_off_se02 = &cf_off_se02_tab[bitRateIndex][0];
+ *cf_se10 = &cf_se10_tab[0];
+ *cf_off_se10 = cf_off_se10_tab;
+ *cf_se11 = &cf_se11_tab[0][0][0];
+ *cf_off_se11 = &cf_off_se11_tab[0][0];
+ break;
+ case IGF_BITRATE_UNKNOWN:
+ default:
+ assert(0);
+ }
+ }
+
+ return retValue;
+}
diff --git a/lib_com/index_pvq_opt.c b/lib_com/index_pvq_opt.c
new file mode 100644
index 0000000000000000000000000000000000000000..6bf79cfbea77945de7375c8dde40ea0fe6bd94b7
--- /dev/null
+++ b/lib_com/index_pvq_opt.c
@@ -0,0 +1,1163 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include
+#include
+#include
+#include "options.h"
+#include "cnst.h"
+#include "rom_com.h"
+#include "prot.h"
+#include "wmc_auto.h"
+
+
+/*-------------------------------------------------------------------*
+ * LOCAL DEFINITIONS
+ *-------------------------------------------------------------------*/
+
+#define N_OPT 5 /* complexity setting, direct functional calculation limit */
+#define TABLE_LIM_OPT 96 /* odd divisor table recursion limit setting, due to dim 6 */
+
+/* local typedefs for optimized pvq indexing, used only in this c-file to vectorize common function calls for c-code clarity */
+typedef void (*VEC2INDFUNCM) (const short* , short* , unsigned int*, unsigned int*);
+typedef unsigned int (*NFUNCM) (short);
+typedef unsigned int (*H_FUNCM) ( unsigned int );
+typedef void (*IND2VECFUNCM) ( short, short, unsigned int, short* ) ;
+typedef void (*NDIM_FUNCM) ( short, short, unsigned int, short* );
+
+typedef unsigned long long ui64; /* Basop Mpy32_32_uu simulation */
+
+/* local constants for indexing functions c-code clarity */
+#ifndef ONE_U
+
+#define ZERO 0
+#define ONE 1
+#define ONE_U 1u
+#define TWO 2
+#define SIGNBIT 0x80000000u
+
+#define MAXBIT 0x40000000L /* if Word32 */
+#define MINNEG 0xffffffffL
+
+#define UDIVBY3 2863311531U
+
+
+/*-------------------------------------------------------------------*
+ * local_norm_l_opt
+ *
+ * rewritten version of STL norm_l for "int" fixed point normalization
+ * in floating point c-code.
+ *-------------------------------------------------------------------*/
+static
+short local_norm_l_opt ( /* o : shifts needed for normalization */
+ int l32var /* i : signed 32bit input value */
+)
+{
+ short l32res;
+
+#define WMC_TOOL_SKIP
+ MAC(1);
+
+ if (l32var == (int)MINNEG )
+ {
+ return (32-ONE);
+ }
+ else
+ {
+ if (l32var == ZERO)
+ {
+ return ZERO;
+ }
+ else
+ {
+ if (l32var < ZERO)
+ {
+ l32var = ~l32var;
+ }
+
+ for (l32res = ZERO; l32var < (int)MAXBIT; l32res++)
+ {
+ l32var <<= ONE;
+ }
+ }
+ }
+#undef WMC_TOOL_SKIP
+
+ return (l32res);
+}
+
+
+
+/*-------------------------------------------------------------------*
+ * floor_sqrt_exact()
+ * returns x = floor(sqrt(input)); where (x*x) <= input
+ *-------------------------------------------------------------------*/
+unsigned int floor_sqrt_exact( /* o : floor(sqrt(input)) */
+ unsigned int input /* i : unsigned input [0.. UINT_MAX/4] */
+)
+{
+ double _tmp;
+ unsigned int x;
+ if (input == ZERO)
+ {
+ return ZERO;
+ }
+
+ _tmp = (double) input ;
+ x = (unsigned int)(sqrt( _tmp )); /* floor is a part of the cast */
+ return x;
+}
+
+/*-------------------------------------------------------------------*
+ * f_odd_exact_div_opt()
+ *
+ * find 1/(den1*2+1) * ( num1p*num2p - num3) ,
+ * if the result is known a priori to be exactly a 32bit unsigned integer
+ *-------------------------------------------------------------------*/
+static
+unsigned int f_odd_exact_div_opt( /* o : see Eq. */
+ unsigned int num1p, /* i : see Eq. */
+ unsigned int num2p, /* i : see Eq. */
+ unsigned int num3, /* i : see Eq. */
+ unsigned int den1 /* i : see Eq. */
+)
+{
+ unsigned int tmp;
+ tmp = exactdivodd[den1] * (num1p*num2p - num3);
+
+ return (tmp);
+}
+
+/*---------------------------------------------------------------------------*
+ * f_even_exact_div_opt()
+ *
+ * returns (num1p*num2p - num3 )/ den1
+ * if the result is known a priori to be exactly a 32bit unsigned integer
+ *--------------------------------------------------------------------------*/
+static
+unsigned int f_even_exact_div_opt( /* o : see Eq. */
+ unsigned int num1p, /* i : see Eq. */
+ unsigned int num2p, /* i : see Eq. range should be larger than num1p */
+ unsigned int num3, /* i : see Eq. */
+ int den1 /* i : see Eq. */
+)
+{
+ unsigned int tmp1, oddfactor, UL_tmp;
+ int den1_m1;
+ short even_sh;
+ unsigned int UL_tmp_h;
+ ui64 ULL_tmp;
+
+ den1_m1 = den1 - ONE; /* remove top bit */
+ even_sh = (31) - local_norm_l_opt((den1_m1)^den1); /* NB STL operation defined for signed positive 32 bit variable */
+ oddfactor = exactdivodd[den1_m1>>even_sh];
+ even_sh -= ONE;
+
+ ULL_tmp = (ui64)num1p*(ui64)num2p; /* use STL Mpy_32_32_uu functionality */
+ UL_tmp_h = (unsigned int)(ULL_tmp>>32); /* high output from basicop */
+ UL_tmp = (unsigned int) (ULL_tmp); /* low output from basicop */
+
+ if(num3 > UL_tmp)
+ {
+ UL_tmp_h = UL_tmp_h - ONE_U;
+ }
+ UL_tmp = (UL_tmp - num3); /* can and should underflow */
+ UL_tmp = (UL_tmp_h<<(32-even_sh))|(UL_tmp>>even_sh); /* bitwise OR */
+
+ /* use tabled modular multiplicative inverse for the odd part division */
+ tmp1 = UL_tmp*oddfactor;
+
+
+ return tmp1;
+}
+
+/*-------------------------------------------------------------------*
+ * a_three()
+ *-------------------------------------------------------------------*/
+static
+unsigned int a_three( /* o: offset for dim 3 */
+ unsigned int k_val /* i: nb unit pulses */
+) /* k_val may be higher than 16 bit signed */
+{
+ if( k_val )
+ {
+ return (ONE_U + k_val*((k_val - ONE_U) << ONE));
+ }
+ else
+ {
+ return ZERO;
+ }
+}
+
+/*-------------------------------------------------------------------*
+ * a_four()
+ *-------------------------------------------------------------------*/
+static
+unsigned int a_four( /* o: offset for dim 4 */
+ unsigned int k_val /* i: nb unit pulses */
+)
+{
+ if(k_val)
+ {
+ return UDIVBY3*((k_val<0,k=0) */
+ h_mem[1] = ONE_U; /* % A(*,k=1) */
+
+ if(dim_in==2)
+ {
+ for( k_val = TWO; k_val <= k_val_in; k_val++)
+ {
+ h_mem[k_val] = (unsigned int)((k_val<>1 ;
+ }
+ return;
+}
+
+
+/*-------------------------------------------------------------------*
+ * a_fwd()
+ *
+ * create offsets for A(n,k) from lower A(n-1,k)
+ *-------------------------------------------------------------------*/
+static
+void a_fwd(
+ unsigned int *a_in, /* i/o: offsets */
+ short n_items /* i : items, k's */
+)
+{
+ unsigned int a_1;
+ short i,i_prev;
+ unsigned int a_in0 ; /* i : start column value */
+
+ a_in0 = ONE_U;
+ i_prev=ZERO;
+ for(i=ONE; i <= n_items; i++) /*basic A fwd row recursion */
+ {
+ a_1 = a_in0 + a_in[i_prev] + a_in[i] ; /* a_in addressed in at least two locations */
+ a_in[i_prev] = a_in0;
+ a_in0 = a_1;
+ i_prev = i; /* no real need to count as it is a ptr update */
+ }
+ a_in[i_prev] = a_in0;
+
+ return;
+}
+
+/*-------------------------------------------------------------------*
+ * a_bwd()
+ *
+ * create offsets for A(n,k) from higher A(n+1,k)
+ *-------------------------------------------------------------------*/
+static
+void a_bwd(
+ unsigned int *a_in, /* i/o: offsets */
+ short n_items /* i: n_items */
+)
+{
+ unsigned int a_1;
+ unsigned int a_in0;
+ short i;
+ short i_prev;
+
+ a_in0 = ZERO;
+ i_prev = ZERO;
+ for(i=ONE; i<=n_items; i++) /*basic A reverse row recursion */
+ {
+ a_1 = a_in[i] - a_in0 - a_in[i_prev];
+ a_in[i_prev] = a_in0;
+ a_in0 = a_1;
+ i_prev = i;
+ }
+ a_in[i_prev] = a_in0;
+ return;
+}
+
+static
+unsigned int direct_row_A2U_rec_calc(short dim_in , short k_val_in, unsigned int a_km2, unsigned int a_km1)
+{
+
+ /* U(n,k) = (A(n,k-2)-1)/2 + ((2*n-1)*A(n,k-1) - A(n,k-2) )/2*(k-1) */
+ /* U(n,k) = floor(A(n,k-2)/2) + (n*A(n,k-1) - floor(A(n,k-1)/2) - floor(A(n,k-2)/2) +1 )/(k-1) */
+ /* U(n,k) = floor(A(n,k-2)/2) + (n*A(n,k-1) - (floor(A(n,k-1)/2) + floor(A(n,k-2)/2) +1) ) /(k-1) */
+
+ unsigned int divisor, km2_size, result;
+
+ divisor = (unsigned int)(k_val_in-ONE);
+ km2_size = (a_km1>>ONE) + (a_km2>>ONE) + ONE_U ;
+
+ if(divisor&ONE_U)
+ {
+ /* odd */
+ result = ( (a_km2>>ONE ) + f_odd_exact_div_opt((unsigned int)(dim_in), a_km1, km2_size , divisor>>ONE) );
+ }
+ else
+ {
+ /* even divisor */
+ result = ( (a_km2>>ONE) + f_even_exact_div_opt((unsigned int)dim_in,a_km1, km2_size, divisor ) );
+ }
+ return result;
+}
+
+static
+void a_u_fwd(
+ unsigned int *a_u_in,
+ short k_val_in,
+ short mem_size_m1
+)
+{
+ unsigned int u_kp1_prev;
+ unsigned int a_k_prev ;
+
+ /* mem_size_m1 = 1 + k_val_in */
+ u_kp1_prev = a_u_in[mem_size_m1]; /* previous n U (n,k+1) value*/
+ a_k_prev = a_u_in[k_val_in]; /* previous n A(n,k) value*/
+
+ a_fwd(&a_u_in[ONE], k_val_in); /* a_u_in[k==ZERO] = zero if n>0 */
+
+ /* low dynamic last offset entry mixed recursion */
+ /* used for size calculation */
+ /* U(n,k+1) = 1 + U(n-1,k+1) + U(n-1,k) + U(n,k) */
+ /* U(n,k+1) = 1 + U(n-1,k+1) + (A(n-1,k)-1)/2 + (A(n,k)-1)/2 */
+ /* Note, A(n,k) always odd for k>0 , subtracted one always shifted out */
+ /* assert(a_k_prev>0, a_k-curr>0) */
+
+ a_u_in[mem_size_m1] = ONE_U + u_kp1_prev + (a_k_prev>>ONE) + (a_u_in[k_val_in] >>ONE);
+
+ return;
+}
+
+/*-------------------------------------------------------------------*
+ * nm_h_prep_opt()
+ *
+ * find and return N_MPVQ(n,k) and also offsets A(n, 0 to k ) and U(n,k+1).
+ *-------------------------------------------------------------------*/
+static
+unsigned int nm_h_prep_opt( /* o: msize for dim */
+ short dim_in, /* i: dimension */
+ short k_val_in, /* i: nb unit pulses */
+ unsigned int *h /* o: A/U offsets array */
+)
+{
+ short mem_size_m1, k_val ;
+ short dim_tmp, d_start;
+ unsigned int h_saveA, h_saveB; /* registers for alternating A(n,k-1), A(n,k-2)*/
+ unsigned int numDsub1; /* k_val_curr, k_val_prev*/;
+
+ mem_size_m1 = k_val_in + ONE;
+
+ if( k_val_in > TABLE_LIM_OPT )
+ {
+ if( dim_in >= 3 )
+ {
+ d_start = 3;
+ }
+ else
+ {
+ d_start = 2;
+ }
+ initOffsets(d_start, h, k_val_in);
+
+ for(dim_tmp = d_start; dim_tmp < dim_in; dim_tmp++)
+ {
+ a_u_fwd(h, k_val_in, mem_size_m1);
+ }
+ }
+ else
+ {
+ h[ZERO] = ZERO;
+ h[ONE] = ONE_U;
+ numDsub1=(unsigned int) ((dim_in << ONE) - ONE);
+ h[TWO] = numDsub1;
+
+ /* interleaved odd even calls */
+ h_saveA = numDsub1 ;
+ h_saveB = ONE_U;
+ for (k_val = 3; k_val < (mem_size_m1); k_val++ )
+ {
+ /* A(n,k) = A(n,k-2) + ((2*n-1)*A(n,k-1)-A(n,k-2)) /(k-1) */
+ /* first odd k, even divisor */
+ h_saveB += f_even_exact_div_opt(numDsub1, h_saveA, h_saveB, k_val - ONE);
+ h[k_val] = h_saveB;
+
+ k_val++; /* next even k, odd divisor */
+ if( k_val >= (mem_size_m1))
+ {
+ break;
+ }
+ h_saveA += f_odd_exact_div_opt(numDsub1, h_saveB, h_saveA, (k_val - ONE)>>ONE);
+ h[k_val] = h_saveA;
+ }
+ /* always do the last (k+1) recursion based on U(n,k+1) = func( A(n-2,k+1), A(n-1,k+1) ) */
+ h[mem_size_m1] = direct_row_A2U_rec_calc(dim_in, mem_size_m1 , h[mem_size_m1-2], h[k_val_in]);
+ }
+
+ /* N_MPVQ(n,k) = 1 + U(n,k+1) + U(n,k) = 1 + U(n,k+1) + (A(n,k)-1)/2 ; */ /* A(n,k) always odd */
+ return ( ONE + h[mem_size_m1] + (h[k_val_in]>>ONE) );
+}
+
+
+/*
+ find_amp_split_offset_func_mem()
+ find first offset in range 0..k_val_in that is less than ind_in
+ using a tree search with direct function calls or memory iteration
+*/
+static
+short find_amp_split_offset_func_mem(
+ unsigned int ind_in,
+ short k_val_in,
+ H_FUNCM h_func_ptr, /* i: offset function pointer */
+ unsigned int *h_mem ,
+ short k_test, /* o: k_value */
+ unsigned int *tmp_offset /* o: offset found */
+)
+{
+ short not_ready, low,high ;
+
+ low = 0;
+ high = k_val_in;
+ /* split over A(n,k)= h_mem(k), or use direct function */
+ not_ready = ONE ;
+ while(not_ready)
+ {
+ k_test = (low+high)>>ONE; /*% split range in half */
+
+ if(h_mem)
+ {
+ *tmp_offset = h_mem[k_test]; /* memory search */
+ }
+ else
+ {
+ *tmp_offset = (*h_func_ptr)((unsigned int)k_test); /* function search. NB only line difference to the memory search*/
+ }
+
+ if(ind_in > *tmp_offset )
+ {
+ if(k_test < high)
+ {
+ low = 1 + k_test ;
+ }
+ else
+ {
+ not_ready=0;
+ }
+ }
+ else
+ {
+ if (*tmp_offset == ind_in )
+ {
+ not_ready=0;
+ }
+ else
+ {
+ high = k_test - 1;
+ }
+ }
+ }
+ return k_test;
+}
+
+
+/*
+ get_lead_sign()
+ update index and return leading sign
+*/
+static
+short get_lead_sign(unsigned int *ind)
+{
+ short leading_sign;
+
+ if( (*ind)&ONE_U) /* leading sign stored in LSB */
+ {
+ leading_sign = -1;
+ }
+ else
+ {
+ leading_sign = 1;
+ }
+ (*ind) = (*ind)>>ONE;
+
+ return leading_sign;
+}
+
+
+/*-------------------------------------------------------------------*
+ * mind2vec_one()
+ *-------------------------------------------------------------------*/
+static
+void mind2vec_one(
+ short k_val_in, /* i: nb unit pulses */
+ short leading_sign, /* i: leading sign */
+ unsigned int ind, /* i: index */
+ short *vec_out /* o: pulse train */
+)
+{
+ ind = 0; /* to avoid compiler warings */
+
+ vec_out[ind] = (leading_sign*k_val_in); /* NB input k_val_in can be zero */
+}
+
+/*-------------------------------------------------------------------*
+ * mind2vec_two()
+ *-------------------------------------------------------------------*/
+static
+void mind2vec_two(
+ short k_val_in, /* i: nb unit pulses */
+ short leading_sign, /* i: leading sign */
+ unsigned int ind_in, /* i: index */
+ short *vec_out /* o: pulse train */
+)
+{
+ unsigned int ind_tmp;
+ short val1;
+
+ if(k_val_in > 0) /* k_val_in check */
+ {
+ if (ind_in==0)
+ {
+ vec_out[0] = (leading_sign*k_val_in);
+ vec_out[1] = 0;
+ }
+ else if (ind_in == ( (unsigned int)(k_val_in<>ONE));
+ vec_out[0] = leading_sign*(k_val_in - val1) ;
+
+ if(ind_tmp&ONE_U)
+ {
+ vec_out[1] = -val1 ;
+ }
+ else
+ {
+ vec_out[1] = val1;
+ }
+ }
+ }
+}
+
+static
+short setval_update_sign(
+ short k_delta,
+ short k_max_local,
+ short *leading_sign,
+ unsigned int *ind_in,
+ short *vec_out
+)
+{
+ if(k_delta != 0 )
+ {
+ *vec_out = (*leading_sign)*k_delta;
+ *leading_sign = get_lead_sign(ind_in);
+ k_max_local = k_max_local-k_delta ;
+ }
+ return k_max_local;
+}
+
+/*-------------------------------------------------------------------*
+ * mind2vec_three()
+ *-------------------------------------------------------------------*/
+static
+void mind2vec_three(
+ short k_max_local, /* i: nb unit pulses */
+ short leading_sign, /* i: leading sign */
+ unsigned int ind_in, /* i: index */
+ short *vec_out /* o: pulse train */
+)
+{
+ short k_delta ;
+ unsigned int acc_val;
+
+ /*
+ use direct calculation of first amplitude
+ (to find amplitudes faster than using split or linear iteration)
+ */
+ if(ind_in==0)
+ {
+ vec_out[0] = leading_sign*k_max_local;
+ }
+ else
+ {
+ acc_val = ((ONE_U + floor_sqrt_exact((ind_in<>ONE ); /* in BASOP use approximation + search for exact sqrt )*/
+
+ k_delta = k_max_local - (short)acc_val;
+ ind_in -= a_three(acc_val); /* remove amplitude offset A(n,k_acc) */
+
+ k_max_local = setval_update_sign( k_delta, k_max_local, &leading_sign,&ind_in,vec_out);
+
+ mind2vec_two( k_max_local, leading_sign, ind_in ,&vec_out[1] );
+ }
+ return;
+}
+
+/*-------------------------------------------------------------------*
+ * mind2vec_direct ,
+ general function for direct decoding using direct functions
+ (no memory recursion)
+ *-------------------------------------------------------------------*/
+static
+void mind2vec_direct(
+ short k_max_local, /* i: nb unit pulses */
+ short leading_sign, /* i: leading sign */
+ unsigned int ind, /* i: index */
+ H_FUNCM h_func_ptr, /* i : offset function */
+ NDIM_FUNCM nd_func_ptr, /* i : next dimension function */
+ short *vec_out /* o: pulse train */
+)
+{
+ short k_delta, k_test=0;
+ unsigned int tmp_offset;
+
+ if(ind==0)
+ {
+ vec_out[0] = leading_sign*k_max_local;
+ }
+ else
+ {
+ k_test = find_amp_split_offset_func_mem(ind,k_max_local, h_func_ptr , NULL, k_test, &tmp_offset);
+
+ k_delta = k_max_local - k_test;
+ ind = ind - tmp_offset; /* % remove amplitude offset A(n,k_acc) */
+ k_max_local = setval_update_sign( k_delta, k_max_local, &leading_sign, &ind,vec_out);
+ (*nd_func_ptr)( k_max_local, leading_sign, ind , &vec_out[1] );
+ }
+ return;
+}
+
+/*-------------------------------------------------------------------*
+ * mind2vec_four()
+ *-------------------------------------------------------------------*/
+static
+void mind2vec_four(
+ short k_val_in, /* i: nb unit pulses */
+ short leading_sign, /* i: leading sign */
+ unsigned int ind_in, /* i: index */
+ short *vec_out /* o: pulse train */
+)
+{
+ mind2vec_direct(k_val_in,leading_sign, ind_in, a_four, mind2vec_three, vec_out);
+ return;
+}
+
+/*-------------------------------------------------------------------*
+ * mind2vec_five()
+ *-------------------------------------------------------------------*/
+static
+void mind2vec_five(
+ short k_val_in , /* i: nb unit pulses */
+ short leading_sign, /* i: leading sign */
+ unsigned int ind_in, /* i: index */
+ short *vec_out /* o: pulse train */
+)
+{
+ mind2vec_direct(k_val_in,leading_sign, ind_in, a_five, mind2vec_four, vec_out);
+ return;
+}
+
+
+/*-------------------------------------------------------------------*
+ * mind2vec()
+ *-------------------------------------------------------------------*/
+static
+void mind2vec(
+ short dim_in, /* i: dimension */
+ short k_max_local, /* i: nb unit pulses */
+ short leading_sign, /* i: leading sign */
+ unsigned int ind, /* i: index */
+ short *vec_out, /* o: pulse train */
+ unsigned int *h_in /* i: offset vector A=1+2U */
+)
+{
+ short pos;
+ short k_acc, k_delta;
+ unsigned int tmp_offset;
+
+ k_acc = k_max_local;
+
+ pos = ZERO;
+ while (pos < dim_in) /* first to last position decoding */
+ {
+ if(ind == 0)
+ {
+ vec_out[pos] = leading_sign*k_max_local;
+ break; /* "fast" recursion exit */
+ }
+ else
+ {
+ {
+ /* linear magnitude search */
+ k_acc = k_max_local;
+ tmp_offset = h_in[k_acc];
+ while(tmp_offset > ind)
+ {
+ k_acc = k_acc - 1;
+ tmp_offset = h_in[k_acc];
+ }
+ }
+ k_delta = k_max_local - k_acc; /* amplitude decoding */
+ }
+ ind = ind - tmp_offset; /* remove amplitude index offset A(n,k_acc) */
+
+ k_max_local = setval_update_sign( k_delta, k_max_local, &leading_sign, &ind, &vec_out[pos]);
+
+ /* move from A(n,kmax) to A(n-1, k_max_local), */
+ a_bwd( h_in,k_max_local + 1 ); /* [0..k_max_local], no need to calculate U(n,k_max_local+1) in index decoding */
+ pos = pos + 1;
+ }
+ return;
+}
+
+
+/*-------------------------------------------------------------------*
+ * vec2mind_one()
+ *-------------------------------------------------------------------*/
+static
+void vec2mind_one(
+ const short *vec_in, /* i : PVQ abs pulse train */
+ short *k_val_out_ptr , /* o : number of unit pulses */
+ unsigned int *next_sign_ind, /* i/o: next sign ind */
+ unsigned int *ind /* o : MPVQ index */
+)
+{
+ *k_val_out_ptr = -1; /* just to avoid compiler warnings */
+
+ *ind = ZERO;
+ /* *k_val_out_ptr = (short)abs(*vec_in); */ /* dim==1, function not called recursively */
+ *next_sign_ind = (unsigned int)(*vec_in < ZERO); /* single sign always pushed out of MPVQ */
+ return;
+}
+
+/*-------------------------------------------------------------------*
+* vec2mind_two()
+*-------------------------------------------------------------------*/
+static
+void vec2mind_two(
+ const short *vec_in, /* i : PVQ pulse train */
+ short *k_val_out_ptr, /* o : number of unit pulses */
+ unsigned int *next_sign_ind, /* i/o: next sign ind */
+ unsigned int *ind /* o: MPVQ index */
+)
+{
+ unsigned int lead_sign_ind;
+ short abs0,abs1,abs01;
+
+ abs0 = (short) abs(vec_in[0]);
+ abs1 = (short) abs(vec_in[1]);
+
+ abs01 = abs0+abs1;
+ *k_val_out_ptr = abs01;
+
+ if(abs01==0) /* zeroes can happen in a recursive encoding call */
+ {
+ *next_sign_ind = SIGNBIT;
+ *ind = ZERO;
+ }
+ else
+ {
+ *next_sign_ind=0;
+ if(abs1 == 0)
+ {
+ *ind = ZERO;
+ }
+ else if(abs0 == 0)
+ {
+ *ind = (unsigned int)(abs1< 0 )
+ {
+ *k_val_out_ptr += tmp_val;
+ }
+ else
+ {
+ *k_val_out_ptr -= tmp_val;
+ }
+ return ;
+}
+
+
+/*-------------------------------------------------------------------*
+ * vec2mind_three()
+ *-------------------------------------------------------------------*/
+static
+void vec2mind_three(
+ const short *vec_in, /* i : PVQ pulse train */
+ short *k_val_out_ptr, /* o : number of unit pulses */
+ unsigned int *next_sign_ind, /* i/o: next sign ind */
+ unsigned int *index /* o: MPVQ index */
+)
+{
+
+
+ vec2mind_gen345(vec_in,k_val_out_ptr, next_sign_ind, index, vec2mind_two, a_three);
+
+ return ;
+}
+
+/*-------------------------------------------------------------------*
+ * vec2mind_four()
+ *-------------------------------------------------------------------*/
+static
+void vec2mind_four(
+ const short *vec_in, /* i : PVQ pulse train */
+ short *k_val_out_ptr, /* o : number of unit pulses */
+ unsigned int *next_sign_ind, /* i/o: next sign ind */
+ unsigned int *index /* o: MPVQ index */
+)
+{
+
+ vec2mind_gen345(vec_in,k_val_out_ptr, next_sign_ind, index, vec2mind_three, a_four);
+
+ return ;
+}
+
+/*-------------------------------------------------------------------*
+ * vec2mind_five()
+ *-------------------------------------------------------------------*/
+static
+void vec2mind_five(
+ const short *vec_in, /* i : PVQ abs pulse train */
+ short *k_val_out_ptr, /* o : number of unit pulses */
+ unsigned int *next_sign_ind, /* i/o: next sign ind */
+ unsigned int *index /* o: MPVQ index */
+)
+{
+
+ vec2mind_gen345(vec_in,k_val_out_ptr, next_sign_ind, index, vec2mind_four, a_five);
+
+ return ;
+}
+
+
+
+/*-------------------------------------------------------------------*
+ * vec2mind()
+ *-------------------------------------------------------------------*/
+static
+void vec2mind(
+ short dim_in, /* i : dim */
+ short k_val_in, /* i : number of unit pulses */
+ const short *vec_in, /* i : PVQ pulse train */
+ unsigned int *next_sign_ind, /* o : pushed leading sign */
+ unsigned int *index , /* o : MPVQ index */
+ unsigned int *N_MPVQ_ptr, /* o : size(N_MPVQ(dim,K_val_in))*/
+ unsigned int *h_mem /* o : offsets */
+)
+{
+ short pos, mem_size_m1 ;
+ short k_val_acc ;
+ short tmp_val;
+
+
+ mem_size_m1 = k_val_in + ONE;
+
+ *next_sign_ind = SIGNBIT; /* % should always be 0 or 1 out, highest bit set signals no sign found yet*/
+
+
+ pos = dim_in - 2; /* % address 2nd last sample */
+ vec2mind_two(&vec_in[pos],&k_val_acc,next_sign_ind ,index);
+ initOffsets( 3, h_mem, k_val_in) ;
+
+
+ for (pos--; pos>=0; pos--)
+ {
+ /*
+ % Check if the leading sign 'bit' is to be added
+ */
+ tmp_val = vec_in[pos];
+ if( ((*next_sign_ind&SIGNBIT)==0 && (tmp_val != 0)) )
+ {
+ *index = (*index<0 */
+
+ k_val_acc += (short)abs(tmp_val);/*% now increase acc k value for next N */
+
+
+ if(pos)
+ {
+ a_u_fwd(h_mem, k_val_in ,mem_size_m1);
+ /*% update A(n,k=1:k_val_in) and U(n,k_val_in+1) , NB here (k_val_in + 2 elements always has to be updated */
+ }
+ }
+
+ /* size is needed for the subseqent arithmetic encoding/transmission of the index. */
+ /* use relation N_MPVQ(n,K) = 1 + (A(n, K)-1)/2 + U(n, 1 + K) */
+ /* = N_MPVQ(n,K) = 1 + (A(n, K)>>1) + U(n, 1 + K) , as A(n,K) is odd) */
+
+ *N_MPVQ_ptr = ONE_U + (h_mem[k_val_acc]>>ONE) + h_mem[ mem_size_m1 ] ; /* total size size */
+
+ return;
+}
+
+/*--------------------------------------------------------------------------*
+ * mpvq_encode_vec()
+ *
+ * returns struct with leading sign index, MPVQ-index , dim and N_MPVQ
+ *-------------------------------------------------------------------------*/
+
+PvqEntry mpvq_encode_vec( /* o : leading_sign_index, index, size, k_val */
+ const short *vec_in, /* i : signed pulse train */
+ short dim_in, /* i : dimension */
+ short k_val_local /* i : nb unit pulses */
+)
+{
+ PvqEntry result;
+ unsigned int h_mem[1+KMAX_NON_DIRECT+1]; /* allocate max offset memory for dim 6 */
+ /* OPT: actually only 1+k_val_in+1 needed ) */
+ unsigned int lead_sign_ind;
+
+ VEC2INDFUNCM vec2mind_f[1+N_OPT] = { (VEC2INDFUNCM)NULL, vec2mind_one, vec2mind_two, vec2mind_three, vec2mind_four, vec2mind_five };
+ /* VEC2INDFUNCM can be a static global */
+
+
+ result.k_val = k_val_local;
+ result.dim = dim_in;
+
+ /* NB, k_val_local may be changed in some sub encoding routines */
+ if( dim_in > N_OPT) /* use the generic dimension function */
+ {
+ vec2mind(dim_in, k_val_local, vec_in, &lead_sign_ind, &result.index, &result.size, h_mem);
+ }
+ else /* if (dim_in<=N_OPT) */
+ {
+ (vec2mind_f[dim_in])(vec_in, &k_val_local, &lead_sign_ind, &result.index);
+ result.size = direct_msize(dim_in, k_val_local); /* k_val_local not used for dim==1 */
+ }
+ result.lead_sign_ind=(short)lead_sign_ind;
+
+ return result;
+}
+
+/*-------------------------------------------------------------------*
+ * get_size_mpvq_calc_offset()
+ *
+ * unsigned int h_mem[1 + KMAX +1 ];
+ * example using fixed size of offset vector input help variable
+ *-------------------------------------------------------------------*/
+
+PvqEntry get_size_mpvq_calc_offset( /* o : size, dim, k_val */
+ short dim_in, /* i : dimension */
+ short k_val_in, /* i : nb unit pulses */
+ unsigned int* h_mem /* o : offsets */
+)
+{
+ PvqEntry entry;
+
+ entry.dim = dim_in;
+ entry.k_val = k_val_in;
+ entry.index = 0U; /* avoid gcc warning in struct passing */
+ entry.lead_sign_ind = 0; /* avoid gcc warning in struct passing */
+ if(dim_in > N_OPT ) /* non-direct solutions, use A+U relation */
+ {
+ entry.size = nm_h_prep_opt(entry.dim, entry.k_val, h_mem);
+ }
+ else
+ {
+ entry.size = direct_msize(dim_in, entry.k_val); /* ues equations, h_mem is not used */
+ }
+
+
+ return entry;
+}
+
+/*-------------------------------------------------------------------*
+ * mpvq_decode_vec()
+ *-------------------------------------------------------------------*/
+
+void mpvq_decode_vec( /* o : void */
+ const PvqEntry *entry, /* i : sign_ind, index, dim, k_val */
+ unsigned int *h_mem, /* i : A/U offsets */
+ short *vec_out /* o : pulse train */
+)
+{
+ short i, leading_sign;
+ IND2VECFUNCM mind2vec_f[N_OPT+1] = { (IND2VECFUNCM)NULL, mind2vec_one, mind2vec_two, mind2vec_three, mind2vec_four, mind2vec_five };
+ /*IND2VECFUNCM vector can be static global */
+
+
+ for(i=0; idim; i++)
+ {
+ vec_out[i]=ZERO; /* set all of short output vector to zero */
+ }
+
+ leading_sign = 1;
+ if(entry->lead_sign_ind)
+ {
+ leading_sign = -1;
+ }
+
+ if(entry->k_val != 0)
+ {
+ if(entry->dim > N_OPT ) /* N_OPT */
+ {
+ /* generic */
+ mind2vec(entry->dim, entry->k_val, leading_sign, entry->index, vec_out, h_mem);
+ }
+ else
+ {
+ /* specialized functions */
+ (mind2vec_f[entry->dim])(entry->k_val, leading_sign, entry->index, vec_out);
+ }
+ }
+ return;
+}
+
+#ifdef ONE_U
+#undef ZERO
+#undef ONE
+#undef ONE_U
+#undef TWO
+#undef MAXBIT
+#undef MINNEG
+#undef SIGNBIT
+#undef UDIVBY3
+#endif
+
+
+
+#endif
diff --git a/lib_com/int_lsp.c b/lib_com/int_lsp.c
new file mode 100644
index 0000000000000000000000000000000000000000..5146a7439ca62e136e17e9a4efa3335f1657a20f
--- /dev/null
+++ b/lib_com/int_lsp.c
@@ -0,0 +1,140 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include "options.h"
+#include "wmc_auto.h"
+#include "cnst.h"
+#include "prot.h"
+#include "rom_com.h"
+
+/*---------------------------------------------------------------------*
+ * int_lsp()
+ *
+ * Find the interpolated LSP parameters for all subframes
+ *---------------------------------------------------------------------*/
+
+void int_lsp(
+ const short L_frame, /* i : length of the frame */
+ const float lsp_old[], /* i : LSPs from past frame */
+ const float lsp_new[], /* i : LSPs from present frame */
+ float *Aq, /* o : LP coefficients in both subframes */
+ const short m, /* i : order of LP filter */
+ const float *int_coeffs, /* i : interpolation coefficients */
+ const short Opt_AMR_WB /* i : flag indicating AMR-WB IO mode */
+)
+{
+ float lsp[M], fnew, fold;
+ short i, k;
+ const float *pt_int_coeffs;
+
+ if( L_frame == L_FRAME )
+ {
+ pt_int_coeffs = int_coeffs;
+ }
+ else /* L_frame == L_FRAME16k */
+ {
+ pt_int_coeffs = interpol_frac_16k;
+ }
+
+ for( k=0; kcore_brate == SID_1k75 )
+ {
+ indice[0] = (short)get_next_indice( st, 6 );
+ indice[1] = (short)get_next_indice( st, 6 );
+ indice[2] = (short)get_next_indice( st, 6 );
+ indice[3] = (short)get_next_indice( st, 5 );
+ indice[4] = (short)get_next_indice( st, 5 );
+
+ disf_ns_28b( indice, isf_new );
+
+ reorder_isf( isf_new, ISF_GAP, M, INT_FS_12k8 );
+
+ isf2isp( isf_new, isp_new, M, INT_FS_12k8 );
+
+ /* return if SID frame (conversion to A(z) done in the calling function) */
+ return;
+ }
+
+ /*-----------------------------------------------------------------*
+ * ISF de-quantization of all other frames
+ *-----------------------------------------------------------------*/
+
+ if( st->core_brate == ACELP_6k60 )
+ {
+ indice[0] = (short)get_next_indice( st, 8 );
+ indice[1] = (short)get_next_indice( st, 8 );
+ indice[2] = (short)get_next_indice( st, 7 );
+ indice[3] = (short)get_next_indice( st, 7 );
+ indice[4] = (short)get_next_indice( st, 6 );
+
+ disf_2s_36b( indice, isf_new, st->mem_AR, st->mem_MA );
+ }
+ else
+ {
+ indice[0] = (short)get_next_indice( st, 8 );
+ indice[1] = (short)get_next_indice( st, 8 );
+ indice[2] = (short)get_next_indice( st, 6 );
+ indice[3] = (short)get_next_indice( st, 7 );
+ indice[4] = (short)get_next_indice( st, 7 );
+ indice[5] = (short)get_next_indice( st, 5 );
+ indice[6] = (short)get_next_indice( st, 5 );
+
+ disf_2s_46b( indice, isf_new, st->mem_AR, st->mem_MA);
+ }
+
+ reorder_isf( isf_new, ISF_GAP, M, INT_FS_12k8 );
+
+ /* convert quantized ISFs to ISPs */
+ isf2isp( isf_new, isp_new, M, INT_FS_12k8 );
+
+ /*-------------------------------------------------------------------------------------*
+ * FEC - update adaptive mean ISF vector
+ *-------------------------------------------------------------------------------------*/
+
+ for ( i=0; ilsf_adaptive_mean[i] = (st->lsfoldbfi1[i] + st->lsfoldbfi0[i] + isf_new[i]) / 3;
+ }
+
+ /*-------------------------------------------------------------------------------------*
+ * ISP interpolation
+ * A(z) calculation
+ *-------------------------------------------------------------------------------------*/
+
+ if( st->rate_switching_reset )
+ {
+ /*extrapolation instead of interpolation*/
+ mvr2r( isp_new, st->lsp_old, M );
+ mvr2r( isf_new, st->lsf_old, M );
+ }
+
+ /* ISP interpolation and A(z) calculation */
+ int_lsp( L_FRAME, st->lsp_old, isp_new, Aq, M, interpol_isp_amr_wb, 1 );
+
+ /*------------------------------------------------------------------*
+ * Check ISF stability : distance between old ISF and current ISF
+ *------------------------------------------------------------------*/
+
+ st->stab_fac = lsf_stab( isf_new, st->lsf_old, 1, st->L_frame );
+
+ return;
+}
+
+/*-------------------------------------------------------------------*
+ * disf_ns_28b()
+ *
+ * ISF de-quantizer for SID_1k75 frames (only for AMR-WB IO mode)
+ *-------------------------------------------------------------------*/
+
+void disf_ns_28b(
+ short *indice, /* i : quantized indices (use indice[0] = -1 in the decoder) */
+ float *isf_q /* o : ISF in the frequency domain (0..6400) */
+)
+{
+ short i;
+
+ for (i = 0; i < 2; i++)
+ {
+ isf_q[i] = dico1_ns_28b[indice[0]*2+i];
+ }
+
+ for (i = 0; i < 3; i++)
+ {
+ isf_q[i+2] = dico2_ns_28b[indice[1]*3+i];
+ isf_q[i+5] = dico3_ns_28b[indice[2]*3+i];
+ }
+
+ for (i = 0; i < 4; i++)
+ {
+ isf_q[i+8] = dico4_ns_28b[indice[3]*4+i];
+ isf_q[i+12] = dico5_ns_28b[indice[4]*4+i];
+ }
+
+ for (i=0; i
+#include "wmc_auto.h"
+#include "options.h"
+#include "prot.h"
+#include "cnst.h"
+#include "rom_com.h"
+
+/*-------------------------------------------------------------------*
+ * Local constants
+ *-------------------------------------------------------------------*/
+
+#define kLagWinThGain1 0.6f
+#define kLagWinThGain2 0.3f
+
+
+/*-------------------------------------------------------------*
+ * procedure lag_wind() *
+ * ~~~~~~~~~ *
+ * lag windowing of the autocorrelations *
+ *-------------------------------------------------------------*/
+
+void lag_wind(
+ float r[], /* i/o: autocorrelations */
+ const short m, /* i : order of LP filter */
+ const int sr, /* i : sampling rate */
+ const short strength /* i : LAGW_WEAK, LAGW_MEDIUM, or LAGW_STRONG */
+)
+{
+ short i;
+ const float *wnd;
+
+ assert(0 <= strength && strength <= NUM_LAGW_STRENGTHS);
+
+ switch (sr)
+ {
+ case 8000:
+ assert(m <= 16);
+ assert(strength == LAGW_STRONG);
+ wnd = lag_window_8k;
+ break;
+ case 12800:
+ assert(m <= 16);
+ wnd = lag_window_12k8[strength];
+ break;
+ case 16000:
+ assert(m <= 16);
+ wnd = lag_window_16k[strength];
+ break;
+ case 24000:
+ case 25600:
+ assert(m <= 16);
+ wnd = lag_window_25k6[strength];
+ break;
+ case 32000:
+ assert(m <= 16);
+ wnd = lag_window_32k[strength];
+ break;
+ case 48000:
+ assert(m <= 16);
+ assert(strength == LAGW_STRONG);
+ wnd = lag_window_48k;
+ break;
+ default:
+ assert(!"Lag window not implemented for this sampling rate");
+ return;
+ }
+
+ for( i=0; i<=m; ++i )
+ {
+ r[i] *= wnd[i];
+ }
+
+ return;
+}
+
+/*-------------------------------------------------------------*
+ * procedure adapt_lag_wind()
+ *
+ *
+ *-------------------------------------------------------------*/
+
+void adapt_lag_wind(
+ float r[], /* i/o: autocorrelations */
+ int m, /* i : order of LP filter */
+ const int Top, /* i : open loop pitch lags from curr. frame (or NULL if n/a) */
+ const float Tnc, /* i : open loop pitch gains from curr. frame (NULL if n/a) */
+ int sr /* i : sampling rate */
+)
+{
+ short strength;
+ short pitch_lag;
+ float pitch_gain;
+
+ pitch_lag = (short)Top;
+ pitch_gain = (float)Tnc;
+
+ if (pitch_lag < 80)
+ {
+ if (pitch_gain > kLagWinThGain1)
+ {
+ strength = LAGW_STRONG;
+ }
+ else
+ {
+ strength = LAGW_MEDIUM;
+ }
+ }
+ else if (pitch_lag < 160)
+ {
+ if (pitch_gain > kLagWinThGain2)
+ {
+ strength = LAGW_MEDIUM;
+ }
+ else
+ {
+ strength = LAGW_WEAK;
+ }
+ }
+ else
+ {
+ strength = LAGW_WEAK;
+ }
+
+ lag_wind( r, m, sr, strength );
+
+ return;
+}
diff --git a/lib_com/lerp.c b/lib_com/lerp.c
new file mode 100644
index 0000000000000000000000000000000000000000..2a57d5e8581948c881556d84303ec9279c8fd5db
--- /dev/null
+++ b/lib_com/lerp.c
@@ -0,0 +1,143 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include
+#include "wmc_auto.h"
+#include
+#include "prot.h"
+
+
+/*-------------------------------------------------------------*
+ * procedure lerp() *
+ * *
+ * *
+ *-------------------------------------------------------------*/
+
+static void lerp_proc(
+ float *f,
+ float *f_out,
+ int bufferNewSize,
+ int bufferOldSize
+);
+
+
+void lerp(
+ float *f,
+ float *f_out,
+ int bufferNewSize,
+ int bufferOldSize
+)
+{
+ float maxFac;
+
+ maxFac = 507.0/128.0;
+
+ if( (float)bufferNewSize / bufferOldSize > maxFac )
+ {
+ int tmpNewSize = bufferOldSize*2;
+ while(bufferNewSize > bufferOldSize)
+ {
+ if( (float)bufferNewSize / bufferOldSize <= maxFac )
+ {
+ tmpNewSize = bufferNewSize;
+ }
+
+ lerp_proc(f, f_out, tmpNewSize, bufferOldSize);
+
+ f = f_out;
+ bufferOldSize = tmpNewSize;
+ tmpNewSize *= 2;
+ }
+ }
+ else if( (float)bufferOldSize / bufferNewSize > maxFac )
+ {
+ int tmpNewSize = bufferOldSize/2;
+ while(bufferNewSize < bufferOldSize)
+ {
+ if( (float)bufferOldSize / bufferNewSize <= maxFac )
+ {
+ tmpNewSize = bufferNewSize;
+ }
+
+ lerp_proc(f, f_out, tmpNewSize, bufferOldSize);
+
+ f = f_out;
+ bufferOldSize = tmpNewSize;
+ tmpNewSize /= 2;
+ }
+ }
+ else
+ {
+ lerp_proc(f, f_out, bufferNewSize, bufferOldSize);
+ }
+}
+
+void lerp_proc(
+ float *f,
+ float *f_out,
+ int bufferNewSize,
+ int bufferOldSize
+)
+{
+ int i, idx;
+ float pos, shift, diff;
+ float buf[2*L_FRAME_MAX];
+
+
+ if( bufferNewSize == bufferOldSize )
+ {
+ mvr2r( f, buf, bufferNewSize );
+ mvr2r( buf, f_out, bufferNewSize );
+ return;
+ }
+
+ /* Using the basop code to avoid reading beyond end of input for bufferOldSize=320, bufferNewSize=640 */
+ shift = (float)(L_shl(L_deposit_l(div_s( bufferOldSize, shl(bufferNewSize, 4))), 4-15+16))/65536.0f;
+ pos = 0.5f * shift - 0.5f;
+
+ if (shift < 0.3f)
+ {
+ pos = pos - 0.13f;
+ }
+
+ /* first point of interpolation */
+ if( pos<0 )
+ {
+ buf[0]=f[0]+pos*(f[1]-f[0]);
+ }
+ else
+ {
+ idx=(int)pos;
+ diff = pos - idx;
+ buf[0] = f[idx] + diff * (f[idx+1]-f[idx]);
+ }
+
+ pos += shift;
+
+ for ( i=1; i bufferOldSize-1 )
+ {
+ idx=bufferOldSize-2;
+ }
+
+ diff = pos - idx;
+
+ buf[bufferNewSize-1] = f[idx]+diff*(f[idx+1]-f[idx]);
+
+ mvr2r( buf, f_out, bufferNewSize );
+
+ return;
+}
diff --git a/lib_com/limit_t0.c b/lib_com/limit_t0.c
new file mode 100644
index 0000000000000000000000000000000000000000..336ef58aba8cab32f1e46a4569d588829408c29d
--- /dev/null
+++ b/lib_com/limit_t0.c
@@ -0,0 +1,201 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include "options.h"
+#include "wmc_auto.h"
+#include "cnst.h"
+#include "prot.h"
+
+/*-------------------------------------------------*
+ * Local constants
+ *-------------------------------------------------*/
+
+#define LIMIT_PIT_REL_LOWER 2 /* delta interval to extend pitch coding in relative Q */
+#define LIMIT_PIT_REL_UPPER 0
+
+/*-------------------------------------------------*
+ * limit_T0()
+ *
+ * Close-loop pitch lag search limitation
+ *-------------------------------------------------*/
+
+void limit_T0(
+ const short L_frame, /* i : length of the frame */
+ const short delta, /* i : Half the close-loop searched interval */
+ const short pit_flag, /* i : selecting absolute(0) or delta(1) pitch quantization */
+ const short limit_flag, /* i : flag for Q limits (0=restrained, 1=extended) */
+ const short T0, /* i : rough pitch estimate around which the search is done */
+ const short T0_frac, /* i : pitch estimate fractional part */
+ short *T0_min, /* o : lower pitch limit */
+ short *T0_max /* o : higher pitch limit */
+)
+{
+ short delta2, T1;
+ short pit_min, pit_max;
+
+ if( limit_flag == 0 ) /* restrained Q limits */
+ {
+ /* set limits */
+ if( L_frame == L_FRAME )
+ {
+ pit_max = PIT_MAX;
+ pit_min = PIT_MIN;
+ }
+ else /* L_frame == L_FRAME16k */
+ {
+ pit_max = PIT16k_MAX;
+ pit_min = PIT16k_MIN;
+ }
+
+ delta2 = 2 * delta - 1;
+
+ T1 = T0;
+ if( T0_frac >= 2 )
+ {
+ T1++;
+ }
+ *T0_min = T1 - delta;
+
+ if( *T0_min < pit_min )
+ {
+ *T0_min = pit_min;
+ }
+ *T0_max = *T0_min + delta2;
+
+ if( *T0_max > pit_max )
+ {
+ *T0_max = pit_max;
+ *T0_min = *T0_max - delta2;
+ }
+ }
+ else /* extended Q limits */
+ {
+
+ /* set limits */
+ if( L_frame == L_FRAME )
+ {
+ pit_max = PIT_MAX;
+ pit_min = PIT_MIN_EXTEND;
+
+ if( limit_flag == 2 )
+ {
+ pit_min = PIT_MIN_DOUBLEEXTEND;
+ }
+ }
+ else /* L_frame == L_FRAME16k */
+ {
+ pit_max = PIT16k_MAX;
+ pit_min = PIT16k_MIN_EXTEND;
+ }
+
+ delta2 = 2 * delta - 1;
+
+ T1 = T0;
+ if( T0_frac >= 2 )
+ {
+ T1++;
+ }
+ *T0_min = T1 - delta;
+
+ if( pit_flag == 0 )
+ {
+ /* subframes with absolute search: keep Q range */
+ if( *T0_min < pit_min )
+ {
+ *T0_min = pit_min;
+ }
+ *T0_max = *T0_min + delta2;
+
+ if( *T0_max > pit_max )
+ {
+ *T0_max = pit_max;
+ *T0_min = *T0_max - delta2;
+ }
+ }
+ else
+ {
+ /* subframes with relative search: extend Q range */
+ if( *T0_min < pit_min - LIMIT_PIT_REL_LOWER )
+ {
+ *T0_min = pit_min - LIMIT_PIT_REL_LOWER;
+ }
+
+ if( *T0_min < L_INTERPOL )
+ {
+ *T0_min = L_INTERPOL ;
+ }
+ *T0_max = *T0_min + delta2;
+
+ if( *T0_max > pit_max + LIMIT_PIT_REL_UPPER )
+ {
+ *T0_max = pit_max + LIMIT_PIT_REL_UPPER;
+ *T0_min = *T0_max - delta2;
+ }
+ }
+ }
+
+ return;
+}
+
+#define WMC_TOOL_SKIP
+
+/*-------------------------------------------------*
+* Routine limit_T0_voiced()
+*
+* Close-loop pitch lag search limitation
+*-------------------------------------------------*/
+
+void limit_T0_voiced(
+ int nbits,
+ int res,
+ int T0, /* i : rough pitch estimate around which the search is done */
+ int T0_frac, /* i : pitch estimate fractional part */
+ int T0_res, /* i : pitch resolution */
+ int *T0_min, /* o : lower pitch limit */
+ int *T0_min_frac, /* o : lower pitch limit */
+ int *T0_max, /* o : higher pitch limit */
+ int *T0_max_frac, /* o : higher pitch limit */
+ int pit_min, /* i : Minimum pitch lag */
+ int pit_max /* i : Maximum pitch lag */
+)
+{
+ short T1, temp1, temp2;
+
+
+ /* Mid-point */
+ T1 = T0;
+ if( (T0_res > 1) && (T0_frac >= (T0_res>>1)) )
+ {
+ T1++;
+ }
+
+ /* Lower-bound */
+ temp1 = (T1*res) - (1<<(nbits-1));
+ temp2 = temp1 / res;
+ *T0_min = temp2;
+ *T0_min_frac = temp1 - temp2*res;
+ if ( *T0_min < pit_min)
+ {
+ *T0_min = pit_min;
+ *T0_min_frac = 0;
+ }
+
+ /* Higher-bound */
+ temp1 = (*T0_min*res) + *T0_min_frac + (1< pit_max)
+ {
+ *T0_max = pit_max;
+ *T0_max_frac = res - 1;
+ temp1 = (*T0_max*res) + *T0_max_frac - (1<
+#include "wmc_auto.h"
+#include "options.h"
+#include "cnst.h"
+#include "prot.h"
+#include "rom_com.h"
+#include "prot.h" /* Function prototypes */
+
+/*--------------------------------------------------------------------------
+ * logqnorm()
+ *
+ * Log quantization for norms of sub-vectors
+ *--------------------------------------------------------------------------*/
+
+void logqnorm(
+ const float *x, /* i : coefficient vector */
+ short *k, /* o : index */
+ const short L, /* i : codebook length */
+ const short N, /* i : sub-vector size */
+ const float *thren /* i : quantization thresholds */
+)
+{
+ short i, j, j1, j2;
+ float temp, power;
+
+
+ temp = 0.0;
+ for (i=0; i 0)
+ {
+ *k = L - 1;
+ }
+ else
+ {
+ power = (float)sqrt(temp);
+
+ j1 = 0;
+ j2 = L - 1;
+ while ((j2-j1)>1)
+ {
+ j = (j1 + j2) >> 1;
+ if ( power >= thren[j] )
+ {
+ j2 = j;
+ }
+ else
+ {
+ j1 = j;
+ }
+ }
+
+ *k = j2;
+ }
+
+ return;
+}
+
+
+/*--------------------------------------------------------------------------
+ * logqnorm_2()
+ *
+ *
+ *--------------------------------------------------------------------------*/
+
+void logqnorm_2(
+ const float *env_fl, /* o : index */
+ const short L, /* i : codebook length */
+ const short n_env_band, /* i : sub-vector size */
+ const short nb_sfm, /* i : sub-vector size */
+ short *ynrm,
+ short *normqlg2,
+ const float *thren /* i : quantization thresholds */
+)
+{
+ short i, j, j1, j2;
+ float temp, power;
+
+ for(i=n_env_band; i 0)
+ {
+ *ynrm = L - 1;
+ }
+ else
+ {
+ power = temp;
+ j1 = 0;
+ j2 = L - 1;
+ while ((j2-j1)>1)
+ {
+ j = (j1 + j2) >> 1;
+ if ( power >= thren[j] )
+ {
+ j2 = j;
+ }
+ else
+ {
+ j1 = j;
+ }
+ }
+ *ynrm = j2;
+ }
+ *normqlg2 = dicnlg2[*ynrm];
+ normqlg2++;
+ ynrm++;
+ }
+
+ return;
+}
+
+/*--------------------------------------------------------------------------
+ * calc_norm()
+ *
+ * Calculate the norms for the spectral envelope
+ *--------------------------------------------------------------------------*/
+
+void calc_norm(
+ const float *x, /* i : Input vector. */
+ short *norm, /* o : Quantization indices for norms */
+ short *normlg, /* o : Quantized norms in log2 */
+ const short start_band, /* i : Indice of band to start coding */
+ const short num_bands, /* i : Number of bands */
+ const short *band_len, /* i : Length of bands */
+ const short *band_start /* i : Start of bands */
+)
+{
+ short nrm;
+ short band;
+
+ set_s(norm, 0, start_band);
+
+ logqnorm(&x[band_start[start_band]], &nrm, 32, band_len[start_band], thren_HQ);
+ norm[start_band] = nrm;
+ normlg[start_band] = dicnlg2[nrm];
+
+ for (band = start_band + 1; band < start_band + num_bands; band++)
+ {
+ logqnorm( &x[band_start[band]], &nrm, 40, band_len[band], thren_HQ );
+ norm[band] = nrm;
+ normlg[band] = dicnlg2[nrm];
+ }
+
+ return;
+}
diff --git a/lib_com/longarith.c b/lib_com/longarith.c
new file mode 100644
index 0000000000000000000000000000000000000000..14e92de75288bd7147819b0f969f932bb0158223
--- /dev/null
+++ b/lib_com/longarith.c
@@ -0,0 +1,164 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include
+#include "wmc_auto.h"
+#include
+#include "prot.h"
+
+
+#define WMC_TOOL_SKIP
+
+
+/**
+ * \brief long addition: a[] = a[] + b[]
+ * Addition of unsigned vectors a[] and b[] without saturation.
+ * All words of b[] are added with carry to the corresponding words in a.
+ * An assertion failure occurs, if lenb exceeds lena or if overflow occurs.
+ *
+ * \param unsigned short a[]
+ * Input/Output: vector of the length lena
+ * \param unsigned short b[]
+ * Input: vector of the length lenb
+ * \param int lena
+ * Input: length of vector a[] in units of 'unsigned short'
+ * Note: lena must be greater/equal lenb
+ * \param int lenb
+ * Input: length of vector b[] in units of 'unsigned short'
+ *
+ * \return void
+ */
+
+void longadd(unsigned short a[], unsigned short b[], int lena, int lenb)
+{
+ int h;
+ long carry = 0;
+
+ assert(lena >= lenb);
+ for (h=0; h < lenb; h++)
+ {
+ carry += ((unsigned long)a[h]) + ((unsigned long)b[h]);
+ a[h] = (unsigned short) carry;
+ carry = carry >> 16;
+ }
+ for (; h < lena; h++)
+ {
+ carry = ((unsigned long)a[h]) + carry;
+ a[h] = (unsigned short) carry;
+ carry = carry >> 16;
+ }
+
+ assert(carry == 0); /* carry != 0 indicates addition overflow */
+ return;
+}
+
+/**
+ * \brief long shift right: d[] = a[] >> b
+ * Logical shift right of unsigned vectors a[] by b bit-positions.
+ * Vector d[] is filled with leading zeroes, where lend exceeds lena.
+ * It is allowed to overlay d[] with a[].
+ *
+ * \param unsigned short a[]
+ * Input: vector of the length lena
+ * \param int b
+ * Input: number of bit positions to shift right
+ * \param unsigned short d[]
+ * Output: vector of the length lend
+ * Note: vector d[] can be overlaid with vector a[], i.e. a[] = a[] >> b
+ * \param int lena
+ * Input: length of vector a[] in units of 'unsigned short'
+ * \param int lend
+ * Input: length of vector d[] in units of 'unsigned short'
+ *
+ * \return void
+ */
+
+void longshiftright(unsigned short a[], int b, unsigned short d[], int lena, int lend)
+{
+ int intb, fracb, fracb_u, k;
+
+
+ intb = b >> 4;
+
+ a += intb;
+ lena -= intb;
+
+ fracb = b & 0xF;
+ if (fracb)
+ {
+ fracb_u = 16-fracb;
+ for (k=0; k < lena-1; k++)
+ {
+ d[k] = ((a[k] >> fracb) | (a[k+1] << fracb_u)) & 0xFFFF;
+ }
+ d[k] = (a[k] >> fracb);
+ k++;
+ }
+ else
+ {
+ for (k=0; k < lena; k++)
+ {
+ d[k] = a[k];
+ }
+ }
+ /* fill remaining upper bits with zero */
+ for (; k < lend; k++)
+ {
+ d[k] = 0;
+ }
+ return;
+}
+
+/**
+ * \brief long shift left: d[] = a[] << b
+ * Logical shift left of unsigned vectors a[] by b bit-positions.
+ * It is allowed to overlay d[] with a[].
+ *
+ * \param unsigned short a[]
+ * Input: vector of the length len
+ * \param int b
+ * Input: number of bit positions to shift left
+ * \param unsigned short d[]
+ * Output: vector of the length len
+ * Note: vector d[] can be overlaid with vector a[], i.e. a[] = a[] << b
+ * \param int len
+ * Input: length of vector a[] and d[] in units of 'unsigned short'
+ *
+ * \return void
+ */
+
+void longshiftleft(unsigned short a[], int b, unsigned short d[], int len)
+{
+ int intb; /* integer part of b */
+ int fracb; /* shift left value for all upper words a[k] */
+ int fracb_l; /* shift right value for all lower words a[k-1] */
+ int k = len - 1;
+
+
+ intb = b >> 4;
+ fracb = b & 0xF;
+
+ if (fracb)
+ {
+ fracb_l = 16-fracb;
+ for (; k >intb; k--)
+ {
+ d[k] = (a[k-intb] << fracb) | (a[k-intb-1] >> fracb_l);
+ }
+ d[k] = (a[k-intb] << fracb);
+ k--;
+ }
+ else
+ {
+ for (; k >= intb; k--)
+ {
+ d[k] = a[k-intb];
+ }
+ }
+ for ( ; k >= 0; k--)
+ {
+ d[k] = 0;
+ }
+ return;
+}
diff --git a/lib_com/low_rate_band_att.c b/lib_com/low_rate_band_att.c
new file mode 100644
index 0000000000000000000000000000000000000000..62018f3d28d8768199706379652252fd0d23fb38
--- /dev/null
+++ b/lib_com/low_rate_band_att.c
@@ -0,0 +1,162 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include
+#include "wmc_auto.h"
+#include
+#include "options.h"
+#include "rom_com.h"
+#include "prot.h"
+
+
+/*--------------------------------------------------------------------------*
+ * fine_gain_pred()
+ *
+ * Fine gain prediction
+ *--------------------------------------------------------------------------*/
+
+void fine_gain_pred(
+ const short *sfm_start, /* i : Sub band start indices */
+ const short *sfm_end, /* i : Sub band end indices */
+ const short *sfm_size, /* i : Sub band bandwidths */
+ const short *i_sort, /* i : Energy sorting indices */
+ const short *K, /* i : Number of pulses per band */
+ const short *maxpulse, /* i : Maximum pulse per band */
+ const short *R, /* i : Bits per sub band (Q3) */
+ const short num_sfm, /* i : Number of sub bands */
+ float *xq, /* i/o: Quantized vector /quantized vector with finegain adj */
+ short *y, /* i/o: Quantized vector (int) */
+ float *fg_pred, /* o : Predicted fine gains */
+ const short core /* i : Core */
+)
+{
+ short i, band;
+ float gp;
+ float xx;
+ float accuracy;
+ short k, bw;
+ float att;
+
+ for( band = 0; band < num_sfm; band++)
+ {
+
+ k = K[i_sort[band]];
+ if(k > 0)
+ {
+ bw = sfm_size[i_sort[band]];
+ xx = 0;
+ for(i = sfm_start[i_sort[band]]; i < sfm_end[i_sort[band]]; i++)
+ {
+ xx += xq[i] * xq[i];
+ }
+
+ if ( xx > 0)
+ {
+ /* Normalize synthesis to RMS=1.0 */
+ gp = (float) sqrt(bw / xx);
+
+ if (core == HQ_CORE && R != NULL && R[i_sort[band]] <= 256)
+ {
+ accuracy = ((float)k/(float)bw)*maxpulse[i_sort[band]];
+ att = 1.0f - 0.05f / accuracy;
+ att = max( 0.840896f, att); /* Limit attenuation to norm quantizer error, 2^-0.25 */
+ gp *= att;
+ }
+
+ fg_pred[band] = gp;
+ }
+ else
+ {
+ fg_pred[band] = 0;
+ }
+ }
+ else
+ {
+ fg_pred[band] = 0;
+ for(i = sfm_start[i_sort[band]]; i < sfm_end[i_sort[band]]; i++)
+ {
+ y[i] = 0;
+ xq[i] = 0;
+ }
+ }
+ }
+ return;
+}
+
+/*--------------------------------------------------------------------------*
+ * get_max_pulses()
+ *
+ * Find the maximum pulse height (in unit pulses) in each band
+ *--------------------------------------------------------------------------*/
+
+void get_max_pulses(
+ const short *band_start, /* i : Sub band start indices */
+ const short *band_end, /* i : Sub band end indices */
+ const short *k_sort, /* i : Indices for sorting by energy */
+ const short *npulses, /* i : Pulses per sub band */
+ const short BANDS, /* i : Number of bands */
+ short *inp_vector, /* i/o: Encoded shape vectors (int)*/
+ short *maxpulse /* o : Maximum pulse height per band */
+)
+{
+ short i, k;
+ int npul;
+ int maxp;
+
+ for (k = 0; k < BANDS; k++)
+ {
+ npul = npulses[k_sort[k]];
+ maxp = 0;
+ if (npul > 0)
+ {
+ for (i = band_start[k_sort[k]]; i < band_end[k_sort[k]]; i++)
+ {
+ if (abs(inp_vector[i]) > maxp)
+ {
+ maxp = abs(inp_vector[i]);
+ }
+ }
+ }
+ maxpulse[k_sort[k]] = maxp;
+ }
+
+ return;
+}
+
+/*--------------------------------------------------------------------------*
+ * fine_gain_dec()
+ *
+ * Fine gain decoder. Decodes fine gain adjustments and applies correction to
+ * predicted fine gains
+ *--------------------------------------------------------------------------*/
+
+void fine_gain_dec
+(
+ Decoder_State *st, /* i/o: Decoder state struct */
+ const short *ord, /* i : Indices for energy order */
+ const short num_sfm, /* i : Number of bands */
+ const short *gain_bits, /* i : Gain adjustment bits per sub band */
+ float *fg_pred /* i/o: Predicted gains / Corrected gains */
+)
+{
+ short band;
+ short gbits;
+ short idx;
+ float gain_dbq;
+
+ for ( band = 0; band < num_sfm; band++)
+ {
+ gbits = gain_bits[ord[band]];
+ if ( fg_pred[band] != 0 && gbits > 0 )
+ {
+ idx = (short)get_next_indice( st, (short)gbits );
+ gain_dbq = finegain[gbits-1][idx];
+
+ /* Update prediced gain with quantized correction */
+ fg_pred[band] *= (float)pow(10, gain_dbq * 0.05f);
+ }
+ }
+
+ return;
+}
diff --git a/lib_com/lpc_tools.c b/lib_com/lpc_tools.c
new file mode 100644
index 0000000000000000000000000000000000000000..71c0ad5d63c99e5b63e6a9d4d5059944fbd44633
--- /dev/null
+++ b/lib_com/lpc_tools.c
@@ -0,0 +1,300 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include
+#include "wmc_auto.h"
+#include
+#include "options.h"
+#include "cnst.h"
+#include "prot.h"
+#include "rom_com.h"
+
+
+/*-----------------------------------------------------------------*
+ * Local constants
+ *-----------------------------------------------------------------*/
+
+#define MAX_LEN_LP 960
+#define SCALE1_LPC 2037.1832275390625f /* LSP to LSF conversion factor */
+
+
+/*---------------------------------------------------------------------*
+ * autocorr()
+ *
+ * Compute autocorrelations of input signal
+ *---------------------------------------------------------------------*/
+
+void autocorr(
+ const float *x, /* i : input signal */
+ float *r, /* o : autocorrelations vector */
+ const short m, /* i : order of LP filter */
+ const short len, /* i : window size */
+ const float *wind, /* i : window */
+ const short rev_flag, /* i : flag to reverse window */
+ const short sym_flag, /* i : symmetric window flag */
+ const short no_thr /* i : flag to avoid thresholding */
+)
+{
+ float t[MAX_LEN_LP];
+ float s;
+ short i, j;
+
+ /* Windowing of signal */
+ if (rev_flag == 1)
+ {
+ /* time reversed window */
+ for (i = 0; i < len; i++)
+ {
+ t[i] = x[i] * wind[len-i-1];
+ }
+ }
+ else if( sym_flag == 1 )
+ {
+ /* symmetric window of even length */
+ for( i=0; i 0.99945f)
+ {
+ flag=1;/* Test for unstable filter. If unstable keep old A(z) */
+ }
+
+ for ( j = 1; j <= i/2; j++ )
+ {
+ l = i-j;
+ at = a[j] + rc[i-1] * a[l];
+ a[l] += rc[i-1] * a[j];
+ a[j] = at;
+ }
+
+ a[i] = rc[i-1];
+
+ err += rc[i-1] * s;
+ if ( err <= 0.0f )
+ {
+ err = 0.01f;
+ }
+
+ if ( epsP != NULL)
+ {
+ epsP[i] = err;
+ }
+ }
+
+ return (flag);
+}
+
+
+/*---------------------------------------------------------------------*
+ * E_LPC_int_lpc_tcx()
+ *
+ *
+ *---------------------------------------------------------------------*/
+
+void E_LPC_int_lpc_tcx(
+ const float lsf_old[], /* input : LSFs from past frame */
+ const float lsf_new[], /* input : LSFs from present frame */
+ float a[] /* output: interpolated LP coefficients */
+)
+{
+ int i;
+ float lsf[M];
+
+ for (i = 0; i < M; i++)
+ {
+ lsf[i] = lsf_old[i]*0.125f + lsf_new[i]*0.875f;
+ }
+
+ lsp2a_stab(lsf, a, M);
+
+ return;
+}
+
+/*---------------------------------------------------------------------*
+ * lsp_reorder()
+ *
+ *
+ *---------------------------------------------------------------------*/
+
+static void lsp_reorder(
+ float *lsp, /* (I/O): lsp vector (acos() domain) */
+ float min_dist, /* (I): minimum required distance */
+ int lpcorder /* (I): LPC order */
+)
+{
+ short i;
+ float lsp_min, lsp_max;
+
+ /* Verify the LSF ordering and minimum GAP */
+ lsp_min = min_dist;
+
+ for (i=0; i lsp_max)
+ {
+ /* Reverify the minimum LSF gap in the reverse sense */
+ for (i = lpcorder-1; i>=0; --i)
+ {
+ if (lsp[i] > lsp_max)
+ {
+ lsp[i] = lsp_max;
+ }
+ lsp_max = lsp[i] - min_dist;
+ }
+ }
+
+ return;
+}
+
+
+/*---------------------------------------------------------------------*
+ * E_LPC_lsp_unweight()
+ *
+ * Approximate unweighting
+ *---------------------------------------------------------------------*/
+
+int E_LPC_lsp_unweight(
+ float lsp_w[], /* (I): weighted lsp */
+ float lsp_uw[], /* (O): unweighted lsp */
+ float lsf_uw[], /* (O): unweighted lsf */
+ float inv_gamma /* (I): inverse weighting factor */
+)
+{
+ float lsp_w_orig[M], lsp_w_diff[M], mean, step;
+ const lsp_unw_triplet *unw_coeffs = NULL;
+ short i;
+
+ /* Table selection */
+ if ((float)fabs(inv_gamma - 1.0f / 0.94f) < 0.0001f)
+ {
+ unw_coeffs = p16_gamma0_94to1;
+ }
+ else if ((float)fabs(inv_gamma - 1.0f / 0.92f) < 0.0001f)
+ {
+ unw_coeffs = p16_gamma0_92to1;
+ }
+ else
+ {
+ assert(0);
+ }
+
+ step = EVS_PI/(float)(M+1);
+ mean = step;
+
+ /* Apply acos() and get mean removed version */
+ for (i=0; i
+#include "wmc_auto.h"
+#include
+#include
+#include
+#include "cnst.h"
+#include "prot.h"
+#include "rom_com.h"
+
+/*---------------------------------------------------------------------*
+* routine: lsf_dec_bfi()
+*
+* Estimate the lsfs in case of FER
+* Bad frame, all active speech coders
+*---------------------------------------------------------------------*/
+
+void lsf_dec_bfi(
+ short codec_mode, /* i: : codec mode: MODE1 | MODE2 */
+ float *lsf, /* o : estimated LSF vector */
+ const float *lsfold, /* i : past quantized lsf */
+ float *lsf_adaptive_mean, /* i : lsf adaptive mean, updated when BFI==0 */
+ const float lsfBase[], /* i : base for differential lsf coding */
+ float *mem_MA, /* i/o: quantizer memory for MA model */
+ float *mem_AR, /* o : quantizer memory for AR model */
+ float stab_fac, /* i : lsf stability factor */
+ short last_coder_type, /* i : last coder type */
+ short L_frame, /* i : frame length */
+ const short last_good, /* i : last good received frame */
+ const short nbLostCmpt, /* i : counter of consecutive bad frames */
+ int plcBackgroundNoiseUpdated, /* i : background noise alreadyupdated? */
+ float *lsf_q_cng, /* o : quantized lsfs of background noise */
+ float *lsf_cng, /* i : long term target for fading to bg noise*/
+ float *old_lsf_q_cng, /* i : old quantized lsfs for background noise*/
+ short Last_GSC_pit_band_idx, /* i : AC mode (GSC) - Last pitch band index */
+ short Opt_AMR_WB, /* i : IO flag */
+ const short MODE1_bwidth /* i : coded bandwidth */
+)
+{
+ short i;
+ float alpha, tmp;
+ float lsf_mean[M];
+ const float* pt_meansForFading;
+ const float* pt_meansForMemUpdate;
+ float beta;
+
+ /* init vectors */
+ if (codec_mode == MODE1)
+ {
+ pt_meansForMemUpdate = &lsf_mean[0];
+
+ if( Opt_AMR_WB )
+ {
+ pt_meansForFading = mean_isf_amr_wb;
+ }
+ else
+ {
+ if( L_frame == L_FRAME )
+ {
+ if( MODE1_bwidth == NB )
+ {
+ pt_meansForFading = GENB_Ave;
+ }
+ else
+ {
+ pt_meansForFading = GEWB_Ave;
+ }
+ }
+ else
+ {
+ pt_meansForFading = GEWB2_Ave;
+ }
+ }
+ }
+ else
+ {
+ pt_meansForFading = pt_meansForMemUpdate = lsfBase;
+ if (lsf_cng != NULL && plcBackgroundNoiseUpdated)
+ {
+ pt_meansForFading = lsf_cng;
+ }
+ }
+
+ /*----------------------------------------------------------------------*
+ * Initialize the alpha factor
+ *----------------------------------------------------------------------*/
+
+ if( nbLostCmpt <= 3 )
+ {
+ if(last_coder_type == UNVOICED)
+ {
+ /* clearly unvoiced */
+ alpha = ALPHA_UU;
+ }
+ else if( last_coder_type == AUDIO || last_good == INACTIVE_CLAS )
+ {
+ if( Last_GSC_pit_band_idx > 0 && nbLostCmpt > 1 )
+ {
+ alpha = 0.8f;
+ }
+ else
+ {
+ alpha = 0.995f;
+ }
+ }
+ else if(last_good == UNVOICED_CLAS )
+ {
+ if( nbLostCmpt <= 1 )
+ {
+ /* if stable, do not flatten the spectrum in the 1st erased frame */
+ alpha = stab_fac * (1.0f - 2.0f*ALPHA_U) + 2.0f*ALPHA_U; /* [0.8, 1.0] */
+ }
+ else if( nbLostCmpt == 2 )
+ {
+ alpha = ALPHA_U*1.5f; /* 0.6 */
+ }
+ else
+ {
+ /* go rapidly to CNG spectrum */
+ alpha = ALPHA_U;
+ }
+ }
+ else if(last_good == UNVOICED_TRANSITION )
+ {
+ alpha = ALPHA_UT;
+ }
+ else if(last_good == VOICED_CLAS || last_good == ONSET )
+ {
+ /* clearly voiced - mild convergence to the CNG spectrum for the first 3 erased frames */
+ alpha = ALPHA_V;
+ }
+ else if(last_good == SIN_ONSET)
+ {
+ alpha = ALPHA_S;
+ }
+ else
+ {
+ alpha = ALPHA_VT;
+ }
+ }
+ else
+ {
+ alpha = 1.f/nbLostCmpt;
+ }
+
+ if( codec_mode == MODE1 )
+ {
+ beta = BETA_FEC;
+ }
+ else
+ {
+ if( plcBackgroundNoiseUpdated )
+ {
+ beta = 0.f;
+ }
+ else
+ {
+ beta = 0.25f;
+ }
+ }
+
+ for( i=0; i L_FRAME */
+ {
+ reorder_lsf( lsf, MODE1_LSF_GAP, M, L_frame * 50 );
+ if(lsf_q_cng!=NULL)
+ {
+ reorder_lsf(lsf_q_cng, MODE1_LSF_GAP, M, L_frame * 50);
+ }
+ }
+ }
+ /* update the AR memory to be used in the next frame */
+ mvr2r( lsf, mem_AR, M );
+
+ for(i=0; i
+#include "wmc_auto.h"
+#include
+#include
+#include "options.h"
+#include "cnst.h"
+#include "prot.h"
+#include "rom_com.h"
+#include "stl.h"
+#include "basop_proto_func.h"
+
+/*---------------------------------------------------------------------*
+ * midlsf_dec()
+ *
+ *
+ *---------------------------------------------------------------------*/
+
+void midlsf_dec(
+ float qlsf0[],
+ float qlsf1[],
+ short idx,
+ float qlsf[],
+ int N,
+ int coder_type,
+ short *mid_lsf_int,
+ short prev_bfi,
+ short safety_net
+)
+{
+ const float *ratio=NULL;
+ int j;
+ short bad_spacing = 0;
+ /* Select codebook */
+ if ( coder_type == UNVOICED )
+ {
+ ratio = tbl_mid_unv_wb_5b;
+ }
+ else
+ {
+ ratio = tbl_mid_gen_wb_5b;
+ }
+
+ for (j=0; j 0 && j < N && qlsf[j] < qlsf[j-1] + LSF_GAP_MID )
+ {
+ qlsf[j] = qlsf[j-1] + LSF_GAP_MID;
+ }
+
+ }
+ }
+ else
+ {
+ /* otherwise, use regular LSF spacing and ordering as in the encoder */
+ for (j=0; j 0 && j < N && qlsf[j] < qlsf[j-1] + LSF_GAP_MID )
+ {
+ qlsf[j] = qlsf[j-1] + LSF_GAP_MID;
+ }
+
+ }
+ }
+ if ( prev_bfi )
+ {
+ /* continue redoing mid-LSF interpolation with 0.4 in order not to propagate the error */
+ *mid_lsf_int = 1;
+ }
+ if ( safety_net )
+ {
+ /* safety-net encountered -> stop redoing mid-LSF interpolation with 0.4 */
+ *mid_lsf_int = 0;
+ }
+ }
+ else
+ {
+ /* use regular LSF spacing */
+ for (j=0; j 0 && j < N && qlsf[j] < qlsf[j-1] + LSF_GAP_MID )
+ {
+ qlsf[j] = qlsf[j-1] + LSF_GAP_MID;
+ }
+ }
+ }
+
+ return;
+}
+
+
+/*---------------------------------------------------------------------*
+ * lsf_ind_is_active()
+ *
+ *
+ *---------------------------------------------------------------------*/
+
+int lsf_ind_is_active(
+ const Word16 lsf_q_ind[],
+ const float means[],
+ int narrowband,
+ int cdk
+)
+{
+ Word16 lsf[2], min_distance;
+
+ lsf[0] = add(lsf_q_ind[0], LSFM(means[0]));
+ move16();
+ lsf[1] = add(lsf_q_ind[1], LSFM(means[1]));
+ move16();
+
+ min_distance = lsf[0];
+ min_distance = s_min(min_distance, sub(lsf[1], lsf[0]));
+
+ assert(narrowband == 0 || narrowband == 1);
+ assert(cdk == 0 || cdk == 1);
+
+ return sub(min_distance, min_distance_thr[narrowband][cdk]) < 0;
+}
diff --git a/lib_com/lsf_tools.c b/lib_com/lsf_tools.c
new file mode 100644
index 0000000000000000000000000000000000000000..2f8e2a59b15248ce3c9b7203141fb81dcfd25c4e
--- /dev/null
+++ b/lib_com/lsf_tools.c
@@ -0,0 +1,2343 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include
+#include "wmc_auto.h"
+#include "options.h"
+#include "cnst.h"
+#include "prot.h"
+#include "rom_com.h"
+#include "basop_proto_func.h"
+
+/*-------------------------------------------------------------------*
+ * Local functions
+ *-------------------------------------------------------------------*/
+
+static float chebps2(const float x, const float *f, const short n);
+static float LPC_chebyshev (float x, float f[], int n);
+static void get_isppol( const float *isp, float f[], const short n );
+
+/*---------------------------------------------------------------------*
+ * a2isp()
+ *
+ * Compute the ISPs from the LPC coefficients a[] using Chebyshev
+ * polynomials. The found ISPs are in the cosine domain with values
+ * in the range from 1 down to -1.
+ * The table grid[] contains the points (in the cosine domain) at
+ * which the polynomials are evaluated.
+ *
+ * The ISPs are the roots of the two polynomials F1(z) and F2(z)
+ * defined as
+ * F1(z) = [A(z) + z^-M A(z^-1)]
+ * and F2(z) = [A(z) - z^-M A(z^-1)]/ (1-z^-2)
+ *
+ * For an even order M=2N, F1(z) has M/2 conjugate roots on the unit circle
+ * and F2(z) has M/2-1 conjugate roots on the unit circle in addition to two
+ * roots at 0 and pi.
+ *
+ * For a 16th order LP analysis (M=16), F1(z) and F2(z) can be written as
+ *
+ * F1(z) = (1 + a[16]) * PRODUCT (1 - 2 cos(w_i) z^-1 + z^-2 )
+ * i=0,2,...,14
+ *
+ * F2(z) = (1 - a[16]) * PRODUCT (1 - 2 cos(w_i) z^-1 + z^-2 )
+ * i=1,3,...,13
+ *
+ * The ISPs are frequencies w_i, i=0...M-2 plus the last predictor
+ * coefficient a[M].
+ *---------------------------------------------------------------------*/
+
+void a2isp(
+ const float *a, /* i: LP filter coefficients */
+ float *isp, /* o: Immittance spectral pairs */
+ const float *old_isp /* i: ISP vector from past frame */
+)
+{
+ short j, i, nf, ip, order;
+ float xlow,ylow,xhigh,yhigh,xmid,ymid,xint;
+ float f1[NC+1], f2[NC];
+ float *coef;
+
+ /*-------------------------------------------------------------*
+ * find the sum and diff polynomials F1(z) and F2(z)
+ * F1(z) = [A(z) + z^M A(z^-1)]
+ * F2(z) = [A(z) - z^M A(z^-1)]/(1-z^-2)
+ *
+ * for (i=0; i 1.0f) || (a[M] < -1.0f) )
+ {
+ for( i=0; i 1; i--)
+ {
+ f2[i] -= f2[i-2];
+ }
+
+ /*-----------------------------------------------------------------*
+ * Scale F1(z) by (1+isp[m-1]) and F2(z) by (1-isp[m-1]) *
+ *-----------------------------------------------------------------*/
+
+ for (i = 0; i < nc; i++)
+ {
+ f1[i] *= (1.0f + isp[m-1]);
+ f2[i] *= (1.0f - isp[m-1]);
+ }
+
+ /*-----------------------------------------------------------------*
+ * A(z) = (F1(z)+F2(z))/2 *
+ * F1(z) is symmetric and F2(z) is asymmetric *
+ *-----------------------------------------------------------------*/
+
+ a[0] = 1.0f;
+ for (i=1, j=m-1; i= 4)
+ {
+ temp2 = LPC_chebyshev (temp, q + offset, order_by_2);
+ }
+ else
+ {
+ temp2 = temp + q[0 + offset];
+ }
+
+ if ((temp2 * prev[iswitch]) <= 0.0 || frequency >= 0.5)
+ {
+ if (STEPindex == STEPSNUM - 1)
+ {
+ if (fabs (temp2) < fabs (prev[iswitch]))
+ {
+ freq[lspnumber] = frequency;
+ }
+ else
+ {
+ freq[lspnumber] = frequency - STEP;
+ }
+ if ((prev[iswitch]) < 0.0)
+ {
+ prev[iswitch] = 9e9f;
+ }
+ else
+ {
+ prev[iswitch] = -9e9f;
+ }
+ root = 0;
+ frequency = LastFreq;
+ STEPindex = 0;
+ }
+ else
+ {
+ if (STEPindex == 0)
+ {
+ LastFreq = frequency;
+ }
+ frequency -= STEPS[++STEPindex]; /* Go back one grid step */
+ STEP = STEPS[STEPindex];
+ }
+ }
+ else
+ {
+ prev[iswitch] = temp2;
+ frequency += STEP;
+ }
+ } /* while(root) */
+
+ lspnumber++;
+ if (lspnumber > order - 1)
+ {
+ notlast = 0;
+ }
+ iswitch = 1 - iswitch;
+ } /* while (notlast) */
+
+ /* stability check */
+ space_min = 1;
+ for( i=1; i < order; i++ )
+ {
+ space_min = ((freq[i] - freq[i-1]) < space_min)?(freq[i] - freq[i-1]): space_min;
+ }
+
+ if( space_min <= 0 )
+ {
+ return 0;
+ }
+
+ return 1;
+}
+
+/*-------------------------------------------------------------------*
+ * lsp2a()
+ *
+ * Convert LSPs to predictor coefficients a[]
+ *-------------------------------------------------------------------*/
+
+void lsp2a (
+ float *pc_in, /* i/o: predictor coefficients */
+ float *freq, /* i/o: LSP coefficients */
+ const short order /* i : order of LP analysis */
+)
+{
+ float p[LPC_SHB_ORDER], q[LPC_SHB_ORDER];
+ float a[LPC_SHB_ORDER], a1[LPC_SHB_ORDER], a2[LPC_SHB_ORDER];
+ float b[LPC_SHB_ORDER], b1[LPC_SHB_ORDER], b2[LPC_SHB_ORDER];
+
+ float xx;
+ int i, k;
+ int lspflag;
+ float *pc;
+ int order_by_2;
+
+ lspflag = 1;
+ pc = &(pc_in[1]);
+
+ order_by_2 = order / 2;
+
+ /* check input for ill-conditioned cases */
+ if ((freq[0] <= 0.0) || (freq[order - 1] >= 0.5))
+ {
+ lspflag = 0;
+
+ if (freq[0] <= 0)
+ {
+ freq[0] = 0.022f;
+ }
+
+ if (freq[order - 1] >= 0.5)
+ {
+ freq[order - 1] = 0.499f;
+ }
+ }
+
+ if (!lspflag)
+ {
+ xx = (freq[order - 1] - freq[0]) * recip_order[order];
+ for (i = 1; i < order; i++)
+ {
+ freq[i] = freq[i - 1] + xx;
+ }
+ }
+
+ for (i = 0; i <= order_by_2; i++)
+ {
+ a[i] = 0.;
+ a1[i] = 0.;
+ a2[i] = 0.;
+ b[i] = 0.;
+ b1[i] = 0.;
+ b2[i] = 0.;
+ }
+
+ for (i = 0; i < order_by_2; i++)
+ {
+ p[i] = (float)cos (6.2832 * freq[2 * i]);
+ q[i] = (float)cos (6.2832 * freq[2 * i + 1]);
+ }
+
+ a[0] = 0.25f;
+ b[0] = 0.25f;
+
+ for (i = 0; i < order_by_2; i++)
+ {
+ a[i + 1] = a[i] - 2 * p[i] * a1[i] + a2[i];
+ b[i + 1] = b[i] - 2 * q[i] * b1[i] + b2[i];
+ a2[i] = a1[i];
+ a1[i] = a[i];
+ b2[i] = b1[i];
+ b1[i] = b[i];
+ }
+ a[0] = 0.25f;
+ b[0] = -0.25f;
+
+ for (i = 0; i < order_by_2; i++)
+ {
+ a[i + 1] = a[i] - 2 * p[i] * a1[i] + a2[i];
+ b[i + 1] = b[i] - 2 * q[i] * b1[i] + b2[i];
+ a2[i] = a1[i];
+ a1[i] = a[i];
+ b2[i] = b1[i];
+ b1[i] = b[i];
+ }
+
+ pc[0] = 2 * (a[order_by_2] + b[order_by_2]);
+
+ for (k = 2; k <= order; k++)
+ {
+ a[0] = 0.0f;
+ b[0] = 0.0f;
+
+ for (i = 0; i < order_by_2; i++)
+ {
+ a[i + 1] = a[i] - 2 * p[i] * a1[i] + a2[i];
+ b[i + 1] = b[i] - 2 * q[i] * b1[i] + b2[i];
+ a2[i] = a1[i];
+ a1[i] = a[i];
+ b2[i] = b1[i];
+ b1[i] = b[i];
+ }
+ pc[k - 1] = 2 * (a[order_by_2] + b[order_by_2]);
+ }
+
+ return;
+}
+
+/*-----------------------------------------------------------*
+ * get_lsppol()
+ *
+ * Find the polynomial F1(z) or F2(z) from the LSPs.
+ * This is performed by expanding the product polynomials:
+ *
+ * F1(z) = product ( 1 - 2 LSF_i z^-1 + z^-2 )
+ * i=0,2,4,..,n-2
+ * F2(z) = product ( 1 - 2 LSF_i z^-1 + z^-2 )
+ * i=1,3,5,..,n-1
+ *
+ * where LSP_i are the LSPs in the cosine domain.
+ *-----------------------------------------------------------*/
+
+static void get_lsppol(
+ const float lsp[], /* i : line spectral freq. (cosine domain) */
+ float f[], /* o : the coefficients of F1 or F2 */
+ const short n, /* i : no of coefficients (m/2) */
+ short flag /* i : 1 ---> F1(z) ; 2 ---> F2(z) */
+)
+{
+ float b;
+ const float *plsp;
+ int i,j;
+
+ plsp = lsp + flag - 1;
+
+ f[0] = 1.0f;
+ b = -2.0f * *plsp;
+ f[1] = b;
+
+ for (i = 2; i <= n; i++)
+ {
+ plsp += 2;
+ b = -2.0f * *plsp;
+ f[i] = b*f[i-1] + 2.0f*f[i-2];
+
+ for (j = i-1; j > 1; j--)
+ {
+ f[j] += b*f[j-1] + f[j-2];
+ }
+
+ f[1] += b;
+ }
+
+ return;
+}
+
+/*---------------------------------------------------------------------*
+ * a2lsp_stab()
+ *
+ * Compute the LSPs from the LPC coefficients a[] using Chebyshev
+ * polynomials. The found LSPs are in the cosine domain with values
+ * in the range from 1 down to -1.
+ * The table grid[] contains the points (in the cosine domain) at
+ * which the polynomials are evaluated.
+ *
+ * The ISPs are the roots of the two polynomials F1(z) and F2(z)
+ * defined as
+ * F1(z) = [A(z) + z^-M A(z^-1)]/ (1+z^-1)
+ * and F2(z) = [A(z) - z^-M A(z^-1)]/ (1-z^-1)
+ *---------------------------------------------------------------------*/
+
+void a2lsp_stab(
+ const float *a, /* i: LP filter coefficients */
+ float *lsp, /* o: LSP vector */
+ const float *old_lsp /* i: LSP vector from past frame */
+)
+{
+ short j, i, nf, ip;
+ float xlow, ylow, xhigh, yhigh, xmid, ymid, xint;
+ float *pf1, *pf2;
+ const float *pa1, *pa2;
+ float f1[NC+1], f2[NC+1];
+
+ /*-------------------------------------------------------------*
+ * find the sum and diff polynomials F1(z) and F2(z) *
+ * F1(z) = [A(z) + z^11 A(z^-1)]/(1+z^-1) *
+ * F2(z) = [A(z) - z^11 A(z^-1)]/(1-z^-1) *
+ *-------------------------------------------------------------*/
+
+ pf1 = f1; /* Equivalent code using indices */
+ pf2 = f2;
+ *pf1++ = 1.0f; /* f1[0] = 1.0; */
+ *pf2++ = 1.0f; /* f2[0] = 1.0; */
+ pa1 = a + 1;
+ pa2 = a + M;
+
+ for( i=0; i<=NC-1; i++ ) /* for (i=1, j=M; i<=NC; i++, j--) */
+ {
+ *pf1 = *pa1 + *pa2 - *(pf1-1); /* f1[i] = a[i]+a[j]-f1[i-1]; */
+ *pf2 = *pa1++ - *pa2-- + *(pf2-1);/* f2[i] = a[i]-a[j]+f2[i-1]; */
+ pf1++;
+ pf2++;
+ }
+
+ /*---------------------------------------------------------------------*
+ * Find the LSPs (roots of F1(z) and F2(z) ) using the *
+ * Chebyshev polynomial evaluation. *
+ * The roots of F1(z) and F2(z) are alternatively searched. *
+ * We start by finding the first root of F1(z) then we switch *
+ * to F2(z) then back to F1(z) and so on until all roots are found. *
+ * *
+ * - Evaluate Chebyshev pol. at grid points and check for sign change.*
+ * - If sign change track the root by subdividing the interval *
+ * 4 times and ckecking sign change. *
+ *---------------------------------------------------------------------*/
+
+ nf=0; /* number of found frequencies */
+ ip=0; /* flag to first polynomial */
+
+ pf1 = f1; /* start with F1(z) */
+
+ xlow = grid100[0];
+ ylow = chebps2( xlow, pf1, NC );
+
+ j = 0;
+ while( (nf < M) && (j < GRID100_POINTS) )
+ {
+ j++;
+ xhigh = xlow;
+ yhigh = ylow;
+ xlow = grid100[j];
+ ylow = chebps2( xlow, pf1, NC );
+
+ if( ylow*yhigh <= 0.0 ) /* if sign change new root exists */
+ {
+ j--;
+ /* divide the interval of sign change by NO_ITER */
+ for (i = 0; i < NO_ITER; i++)
+ {
+ xmid = 0.5f * ( xlow + xhigh );
+ ymid = chebps2( xmid, pf1, NC );
+ if( ylow*ymid <= 0.0 )
+ {
+ yhigh = ymid;
+ xhigh = xmid;
+ }
+ else
+ {
+ ylow = ymid;
+ xlow = xmid;
+ }
+ }
+
+ /* linear interpolation for evaluating the root */
+ ymid = (yhigh - ylow);
+ xint = xlow;
+ if ( ymid != 0 && ylow != 0) /* whenever ylow is 0, it doesn't make sense to compute the remaining part of the equation */
+ {
+ xint -= ylow * (xhigh - xlow) / (ymid);
+ }
+#ifdef DEBUG
+ else if (ymid == 0 && ylow != 0)
+ {
+ fprintf(stderr, "issue in a2lsp_stab\n");
+ }
+#endif
+ lsp[nf] = xint; /* new root */
+ nf++;
+ ip = 1 - ip; /* flag to other polynomial */
+ pf1 = ip ? f2 : f1; /* pointer to other polynomial */
+ xlow = xint;
+ ylow = chebps2( xlow, pf1, NC );
+ }
+ }
+
+ /* Check if M roots found */
+ /* if not use the LSPs from previous frame */
+ if( nf < M )
+ {
+
+ for( i=0; i 0; i--) */
+ {
+ *pf1-- += *pf1_1--; /* f1[i] += f1[i-1]; */
+ *pf2-- -= *pf2_1--; /* f2[i] -= f2[i-1]; */
+ }
+
+ /*-----------------------------------------------------*
+ * A(z) = (F1(z)+F2(z))/2 *
+ * F1(z) is symmetric and F2(z) is antisymmetric *
+ *-----------------------------------------------------*/
+
+ pa1 = a;
+ *pa1++ = 1.0; /* a[0] = 1.0; */
+ pa2 = a + m;
+ pf1 = f1 + 1;
+ pf2 = f2 + 1;
+ for (i = 0; i <= k; i++) /* for (i=1, j=M; i<=NC; i++, j--) */
+ {
+ *pa1++ = 0.5f*(*pf1 + *pf2); /* a[i] = 0.5*(f1[i] + f2[i]); */
+ *pa2-- = 0.5f*(*pf1++ - *pf2++);/* a[j] = 0.5*(f1[i] - f2[i]); */
+ }
+
+ return;
+}
+
+/*---------------------------------------------------------------------------
+ * reorder_lsf()
+ *
+ * To make sure that the LSFs are properly ordered and to keep a certain
+ * minimum distance between consecutive LSFs.
+ *--------------------------------------------------------------------------*/
+
+void reorder_lsf(
+ float *lsf, /* i/o: LSF vector */
+ const float min_dist, /* i : minimum required distance */
+ const short n, /* i : LPC order */
+ const float fs /* i : sampling frequency */
+)
+{
+ short i;
+ float lsf_min;
+ float lsf_max;
+
+ /*-----------------------------------------------------------------*
+ * Verify the LSF ordering and minimum GAP
+ *-----------------------------------------------------------------*/
+
+ lsf_min = min_dist;
+ for (i = 0; i < n; i++)
+ {
+ if (lsf[i] < lsf_min)
+ {
+ lsf[i] = lsf_min;
+ }
+ lsf_min = lsf[i] + min_dist;
+ }
+
+ /*------------------------------------------------------------------------------------------*
+ * Reverify the LSF ordering and minimum GAP in the reverse order (security)
+ *------------------------------------------------------------------------------------------*/
+
+ lsf_max = fs/2.0f - min_dist;
+
+ if( lsf[n-1] > lsf_max ) /* If danger of unstable filter in case of resonance in HF */
+ {
+ for (i = n-1; i >=0; i--) /* Reverify the minimum LSF gap in the reverse sens */
+ {
+ if (lsf[i] > lsf_max)
+ {
+ lsf[i] = lsf_max;
+ }
+
+ lsf_max = lsf[i] - min_dist;
+ }
+ }
+
+ return;
+}
+
+/*-------------------------------------------------------------------*
+ * space_lsfs()
+ *
+ *-------------------------------------------------------------------*/
+
+void space_lsfs (
+ float *lsfs, /* i/o: Line spectral frequencies */
+ const short order /* i : order of LP analysis */
+)
+{
+ float delta;
+ short i, flag = 1;
+
+ while (flag == 1)
+ {
+ flag = 0;
+ for (i = 0; i <= order; i++)
+ {
+ delta = (float)( i == 0 ? lsfs[0] : (i == order ? 0.5f - lsfs[i - 1] : (lsfs[i] - lsfs[i -1])));
+ if (delta < SPC)
+ {
+ flag = 1;
+ delta -= SPC_plus;
+ if (i == order)
+ {
+ lsfs[i - 1] += delta;
+ }
+ else
+ {
+ if (i == 0)
+ {
+ lsfs[i] -= delta;
+ }
+ else
+ {
+ delta *= 0.5f;
+ lsfs[i - 1] += delta;
+ lsfs[i] -= delta;
+ }
+ }
+ }
+ }
+ }
+
+ return;
+}
+
+/*-------------------------------------------------------------------*
+ * lsp_weights()
+ *
+ *-------------------------------------------------------------------*/
+
+void lsp_weights (
+ const float *lsps, /* i : Line spectral pairs */
+ float *weight, /* o : weights */
+ const short order /* i : order of LP analysis */
+)
+{
+ short i;
+ float delta1, delta2;
+
+ for (i = 0; i < order; i++)
+ {
+ delta1 = (float)((i == 0) ? lsps[i] : lsps[i] - lsps[i - 1]);
+ delta2 = (float)((i == order - 1) ? 0.5f - lsps[i] : lsps[i + 1] - lsps[i]);
+
+ weight[i] = 250 * root_a_over_b(ALPHA_SQ, delta1 * delta2);
+ }
+
+ if (order != LPC_SHB_ORDER_WB)
+ {
+ weight[3] *= 1.1f;
+ weight[4] *= 1.1f;
+ }
+
+ return;
+}
+
+
+/*-----------------------------------------------------------------------*
+ * isf2isp()
+ *
+ * Transformation of ISF to ISP
+ *
+ * ISP are immitance spectral pairs in cosine domain (-1 to 1).
+ * ISF are immitance spectral pairs in frequency domain (0 to fs/2).
+ *-----------------------------------------------------------------------*/
+
+void isf2isp(
+ const float isf[], /* i : isf[m] normalized (range: 0<=val<=fs/2) */
+ float isp[], /* o : isp[m] (range: -1<=val<1) */
+ const short m, /* i : LPC order */
+ const float fs /* i : sampling frequency */
+)
+{
+ short i;
+
+ for(i=0; i= 0; m--)
+ {
+ km = f[m];
+ if (km <= -1.0 || km >= 1.0)
+ {
+ for ( j = 0; j < lpcorder; j++ )
+ {
+ refl[j] = 0.f;
+ }
+
+ return;
+ }
+
+ refl[m] = -km;
+ denom = 1.0f / (1.0f - km * km);
+
+ for (j = 0; j < m / 2; j++)
+ {
+ n = m - 1 - j;
+ x = denom * f[j] + km * denom * f[n];
+ f[n] = denom * f[n] + km * denom * f[j];
+ f[j] = x;
+ }
+
+ if (m & 1)
+ {
+ f[j] = denom * f[j] + km * denom * f[j];
+ }
+ }
+
+ return;
+}
+
+
+/*----------------------------------------------------------------------------------*
+ * vq_dec_lvq()
+ *
+ * Multi-stage VQ decoder for LSF parameters, last stage LVQ
+ *----------------------------------------------------------------------------------*/
+
+short vq_dec_lvq (
+ short sf_flag, /* i : safety net flag */
+ float x[], /* o : Decoded vector */
+ short indices[], /* i : Indices */
+ short stages, /* i : Number of stages */
+ short N, /* i : Vector dimension */
+ short mode, /* (i): mode_lvq, or mode_lvq_p */
+ short no_bits, /* (i): no. bits for lattice */
+ unsigned int *p_offset_scale1,
+ unsigned int *p_offset_scale2,
+ unsigned int *p_offset_scale1_p,
+ unsigned int *p_offset_scale2_p,
+ short *p_no_scales,
+ short *p_no_scales_p
+)
+{
+ float x_lvq[16];
+ short i;
+ short ber_flag;
+ /* clear vector */
+ set_f(x, 0, N);
+
+ /*-----------------------------------------------*
+ * add contribution of each stage
+ *-----------------------------------------------*/
+
+ if (sf_flag == 1)
+ {
+ for(i=0; i -1)
+ {
+ if (nbits0>0) /* */
+ {
+ n_stages = 2;
+ levels0[0] = CBsizes[nbits0];
+ bits0[0] = nbits0;
+ bits0[1] = cumleft-nbits0;
+
+ if ( bits0[1] == 0 )
+ {
+ n_stages--;
+ }
+ else
+ {
+ levels0[1] = CBsizes[cumleft-nbits0];
+ }
+ }
+ else /* no bits for VQ stage */
+ {
+ n_stages = 0;
+ }
+
+ *stages0 = n_stages;
+ if(bits_lvq > 0)
+ {
+ bits0[n_stages] = bits_lvq;
+ levels0[n_stages] = bits_lvq; /* this is number of bits, not levels */
+ *stages0 = n_stages+1;
+ }
+ }
+ else
+ {
+ *stages0 = 0;
+ }
+
+ /*---------------------------------------------------*
+ * Calculate bit allocation for predictive quantizer
+ *---------------------------------------------------*/
+
+ if ( framemode_p > -1 )
+ {
+ cumleft = BitsVQ_p[framemode_p];
+ bits_lvq = nBits - cumleft;
+ nbits0 = CBbits_p[framemode_p];
+
+ if (nbits0 > -1)
+ {
+ if ( nbits0 > 0 )
+ {
+ if ( framemode_p == 7 )
+ {
+ /* for UNVOICED_WB only */
+ n_stages = 3;
+ for( i=0; i0)
+ {
+ levels1[1] = CBsizes[nbits0];
+ bits1[1] = nbits0;
+ n_stages = 2;
+ }
+
+ levels1[n_stages] = bits_lvq; /* this is number of bits, not levels */
+ bits1[n_stages] = bits_lvq;
+ *stages1 = n_stages+1;
+ }
+ }
+ else
+ {
+ *stages1 = 1;
+ bits1[0] = bits_lvq;
+ levels1[0] = bits_lvq;
+ }
+ }
+ else
+ {
+ fprintf(stderr, "lsf_allocate(): invalid number of bits in used predictive mode\n");
+ exit(-1);
+ }
+ }
+
+ return;
+}
+
+/*----------------------------------------------------------------------------------*
+ * find_pred_mode()
+ *
+ *
+ *----------------------------------------------------------------------------------*/
+
+short find_pred_mode(
+ const short coder_type,
+ const short bwidth,
+ const float int_fs,
+ short * p_mode_lvq,
+ short * p_mode_lvq_p,
+ short core_brate
+)
+{
+ short idx, predmode;
+
+ idx = bwidth;
+ if (idx>1)
+ {
+ idx = 1;
+ }
+ if ((int_fs == INT_FS_16k))
+ {
+ idx = 2;
+ }
+ else
+ {
+ if ((core_brate>=GENERIC_MA_LIMIT)&&(coder_type==GENERIC)
+ &&(idx==1)
+ )
+ {
+ idx = 3;
+ }
+ }
+
+ predmode = predmode_tab[idx][coder_type];
+
+ if (idx<=2)
+ {
+ *p_mode_lvq = NO_CODING_MODES*idx + coder_type;
+ if (predmode>0)
+ {
+ *p_mode_lvq_p = *p_mode_lvq;
+ }
+ else
+ {
+ *p_mode_lvq_p = -1;
+ }
+ }
+ else /* WB 12.8 with MA pred in GENERIC*/
+ {
+ *p_mode_lvq = NO_CODING_MODES + coder_type;
+ if (coder_type == GENERIC)
+ {
+ *p_mode_lvq_p = 18;
+ }
+ else
+ {
+ if (predmode>0)
+ {
+ *p_mode_lvq_p = *p_mode_lvq;
+ }
+ else
+ {
+ *p_mode_lvq_p = -1;
+ }
+ }
+ }
+
+
+ if (predmode==-1)
+ {
+ fprintf (stderr, "find_pred_mode(): incorrect coder_type specification: %d\n", coder_type);
+ exit(-1);
+ }
+
+ return predmode;
+}
+
+
+/*---------------------------------------------------------------------------
+ * reorder_isf()
+ *
+ * To make sure that the ISFs are properly ordered and to keep a certain
+ * minimum distance between consecutive ISFs.
+ *--------------------------------------------------------------------------*/
+
+void reorder_isf(
+ float *isf, /* i/o: ISF vector */
+ const float min_dist, /* i : minimum required distance */
+ const short n, /* i : LPC order */
+ const float fs /* i : sampling frequency */
+)
+{
+ short i;
+ float isf_min;
+ float isf_max;
+
+ /*-----------------------------------------------------------------*
+ * Verify the ISF ordering and minimum GAP
+ *-----------------------------------------------------------------*/
+
+ isf_min = min_dist;
+ for (i = 0; i < n-1; i++)
+ {
+ if (isf[i] < isf_min)
+ {
+ isf[i] = isf_min;
+ }
+
+ isf_min = isf[i] + min_dist;
+ }
+
+ /*------------------------------------------------------------------------------------------*
+ * Reverify the ISF ordering and minimum GAP in the reverse order (security)
+ *------------------------------------------------------------------------------------------*/
+
+ isf_max = fs/2.0f - min_dist;
+
+ if( isf[n-2] > isf_max ) /* If danger of unstable filter in case of resonance in HF */
+ {
+ for (i = n-2; i >=0; i--) /* Reverify the minimum ISF gap in the reverse sens */
+ {
+ if (isf[i] > isf_max)
+ {
+ isf[i] = isf_max;
+ }
+
+ isf_max = isf[i] - min_dist;
+ }
+ }
+
+ return;
+}
+
+/*----------------------------------------------------------------------------------*
+ * lsf_stab()
+ *
+ * Check LSF stability (distance between old LSFs and current LSFs)
+ *----------------------------------------------------------------------------------*/
+
+float lsf_stab( /* o : LP filter stability */
+ const float *lsf, /* i : LSF vector */
+ const float *lsfold, /* i : old LSF vector */
+ const short Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */
+ const short L_frame /* i : frame length */
+)
+{
+ short i, m;
+ float scale, stab_fac, tmp;
+
+ tmp = 0.0f;
+ if ( Opt_AMR_WB )
+ {
+ m = M-1;
+ }
+ else
+ {
+ m = M;
+ }
+
+ for (i=0; i 1.0f)
+ {
+ stab_fac = 1.0f;
+ }
+
+ if (stab_fac < 0.0f)
+ {
+ stab_fac = 0.0f;
+ }
+ return stab_fac;
+}
+
+
+/*---------------------------------------------------------------------
+ * get_isppol()
+ *
+ * Find the polynomial F1(z) or F2(z) from the ISPs.
+ * This is performed by expanding the product polynomials:
+ *
+ * F1(z) = PRODUCT ( 1 - 2 isp_i z^-1 + z^-2 )
+ * i=0,2,...,14
+ * F2(z) = PRODUCT ( 1 - 2 isp_i z^-1 + z^-2 )
+ * i=1,3,...,13
+ *
+ * where isp_i are the ISPs in the cosine domain.
+ *---------------------------------------------------------------------*/
+
+static void get_isppol(
+ const float *isp, /* i : Immitance spectral pairs (cosine domaine) */
+ float f[], /* o : the coefficients of F1 or F2 */
+ const short n /* i : nb. of coefficients (m/2) */
+)
+{
+ float b;
+ short i,j;
+
+ f[0] = 1.0f;
+ b = (float)(-2.0f * *isp);
+ f[1] = b;
+ for (i = 2; i <= n; i++)
+ {
+ isp += 2;
+ b = (float)(-2.0f * *isp);
+ f[i] = (float)(b * f[i-1] + 2.0f * f[i-2]);
+
+ for (j = i-1; j > 1; j--)
+ {
+ f[j] += b*f[j-1] + f[j-2];
+ }
+ f[1] += b;
+ }
+
+ return;
+}
+
+
+/*---------------------------------------------------------------------
+ * chebps2()
+ *
+ * Evaluates the Chebyshev polynomial series
+ *
+ * The polynomial order is
+ * n = m/2 (m is the prediction order)
+ * The polynomial is given by
+ * C(x) = f(0)T_n(x) + f(1)T_n-1(x) + ... +f(n-1)T_1(x) + f(n)/2
+ *---------------------------------------------------------------------*/
+
+static float chebps2( /* o: the value of the polynomial C(x) */
+ const float x, /* i: value of evaluation; x=cos(freq) */
+ const float *f, /* i: coefficients of sum or diff polyn. */
+ const short n /* i: order of polynomial */
+)
+{
+ float b1, b2, b0, x2;
+ short i;
+
+
+ x2 = (float)(2.0f * x);
+ b2 = f[0];
+
+ b1 = x2*b2 + f[1];
+
+ for (i=2; i A */
+ lsp2a_stab( lsp, a, m );
+
+ /* A --> ISP */
+ a2isp( a, isp, stable_isp );
+
+ /* Update to latest stable ISP */
+ mvr2r( isp, stable_isp, M );
+}
+
+/*-------------------------------------------------------------------*
+ * isp2lsp()
+ *
+ * Convert ISPs to LSPs via predictor coefficients A[]
+ *-------------------------------------------------------------------*/
+
+void isp2lsp(
+ const float *isp, /* i : LSP vector */
+ float *lsp, /* o : ISP filter coefficients */
+ float *stable_lsp, /* i/o: stable LSP filter coefficients */
+ const short m /* i : order of LP analysis */
+)
+{
+ float a[M+1];
+
+ /* ISP --> A */
+ isp2a( isp, a, m );
+
+ /* A --> LSP */
+ a2lsp_stab( a, lsp, stable_lsp );
+
+ /* Update to latest stable LSP */
+ mvr2r( lsp, stable_lsp, M );
+}
+
+
+/*-------------------------------------------------------------------*
+ * lsf2isf()
+ *
+ * Convert LSPs to ISPs
+ *-------------------------------------------------------------------*/
+
+void lsf2isf(
+ const float *lsf, /* i : LSF vector */
+ float *isf, /* o : ISF vector */
+ float *stable_isp, /* i/o: stable ISP filter coefficients */
+ const short m, /* i : order of LP analysis */
+ const float int_fs
+)
+{
+ float tmp_lsp[M];
+ float tmp_isp[M];
+
+ /* LSF --> LSP */
+ lsf2lsp( lsf, tmp_lsp, m, int_fs );
+
+ /* LSP --> ISP */
+ lsp2isp( tmp_lsp, tmp_isp, stable_isp, m );
+
+ /* ISP --> ISF */
+ isp2isf( tmp_isp, isf, m, int_fs );
+
+ return;
+}
+
+/*-------------------------------------------------------------------*
+ * isf2lsf()
+ *
+ * Convert ISFs to LSFs
+ *-------------------------------------------------------------------*/
+
+void isf2lsf(
+ const float *isf, /* i : ISF vector */
+ float *lsf, /* o : LSF vector */
+ float *stable_lsp, /* i/o: stable LSP filter coefficients */
+ const short m, /* i : order of LP analysis */
+ const float int_fs
+)
+{
+ float tmp_isp[M];
+ float tmp_lsp[M];
+
+ /* ISF --> ISP */
+ isf2isp( isf, tmp_isp, m, int_fs );
+
+ /* ISP --> LSP */
+ isp2lsp( tmp_isp, tmp_lsp, stable_lsp, m );
+
+ /* LSP --> LSF */
+ lsp2lsf( tmp_lsp, lsf, m, int_fs );
+
+ return;
+}
+
+/*-----------------------------------------------------------------------*
+ * lsp2lsf()
+ *
+ * Transformation of LSPs to LSFs
+ *
+ * LSP are line spectral pair in cosine domain (-1 to 1).
+ * LSF are line spectral frequencies (0 to fs/2).
+ *-----------------------------------------------------------------------*/
+
+void lsp2lsf(
+ const float lsp[], /* i : isp[m] (range: -1<=val<1) */
+ float lsf[], /* o : isf[m] normalized (range: 0<=val<=fs/2) */
+ const short m, /* i : LPC order */
+ const float fs /* i : sampling frequency */
+)
+{
+ short i;
+
+ /* convert LSPs to LSFs */
+ for( i=0; i> 4;
+ branch[1] = index[2] >> 4;
+
+ for(stage = 2; stage < N_STAGE_VQ-4; stage++)
+ {
+ branch[stage] = index[stage+1] >> 3;
+ }
+
+ branch[4] = fins & 0x1;
+ branch[5] = (fins >> 1) & 0x1;
+ branch[6] = (fins >> 2) & 0x1;
+ branch[7] = (fins >> 3) & 0x1;
+
+ /* Decode Codeword info */
+ for(stage = 0; stage < 2; stage++)
+ {
+ codeword[stage] = (index[stage+1] & 15) << 3;
+ }
+
+ for(stage = 2; stage < N_STAGE_VQ-4; stage++)
+ {
+ codeword[stage] = (index[stage+1] & 7) << 3;
+ }
+
+ for(stage = N_STAGE_VQ-4; stage < N_STAGE_VQ; stage++)
+ {
+ codeword[stage] = (index[stage+1] & 3) << 3;
+ }
+
+ state = (fins >> 2) << 2;
+
+ /* stage #1 */
+ iwd = NTRANS2[branch[0]+2][state] + codeword[0];
+ D[0][0] = TCVQ_CB_SUB1[0][iwd][0];
+ D[0][1] = TCVQ_CB_SUB1[0][iwd][1];
+ state = NTRANS2[branch[0]][state];
+
+ /* stage #2 */
+ pred[0] = IntraCoeff[0][0][0] * D[0][0] + IntraCoeff[0][0][1]*D[0][1];
+ pred[1] = IntraCoeff[0][1][0] * D[0][0] + IntraCoeff[0][1][1]*D[0][1];
+
+ iwd = NTRANS2[branch[1]+2][state] + codeword[1];
+ D[1][0] = TCVQ_CB_SUB1[1][iwd][0] + pred[0];
+ D[1][1] = TCVQ_CB_SUB1[1][iwd][1] + pred[1];
+ state = NTRANS2[branch[1]][state];
+
+ /* stage #3 - #4 */
+ for(stage = 2; stage < N_STAGE_VQ-4; stage++)
+ {
+ pred[0] = IntraCoeff[stage-1][0][0] * D[stage-1][0] + IntraCoeff[stage-1][0][1]*D[stage-1][1];
+ pred[1] = IntraCoeff[stage-1][1][0] * D[stage-1][0] + IntraCoeff[stage-1][1][1]*D[stage-1][1];
+
+ iwd = NTRANS2[branch[stage]+2][state] + codeword[stage];
+ D[stage][0] = TCVQ_CB_SUB2[stage-2][iwd][0] + pred[0];
+ D[stage][1] = TCVQ_CB_SUB2[stage-2][iwd][1] + pred[1];
+ state = NTRANS2[branch[stage]][state];
+ }
+
+ /* stage #5 - #8 */
+ for(stage = N_STAGE_VQ-4; stage < N_STAGE_VQ; stage++)
+ {
+ pred[0] = IntraCoeff[stage-1][0][0] * D[stage-1][0] + IntraCoeff[stage-1][0][1]*D[stage-1][1];
+ pred[1] = IntraCoeff[stage-1][1][0] * D[stage-1][0] + IntraCoeff[stage-1][1][1]*D[stage-1][1];
+
+ iwd = NTRANS2[branch[stage]+2][state] + codeword[stage];
+ D[stage][0] = TCVQ_CB_SUB3[stage-4][iwd][0] + pred[0];
+ D[stage][1] = TCVQ_CB_SUB3[stage-4][iwd][1] + pred[1];
+ state = NTRANS2[branch[stage]][state];
+ }
+
+ for(stage = 0; stage < N_STAGE_VQ; stage++)
+ {
+ for(i = 0; i < N_DIM; i++)
+ {
+ d_out[(N_DIM*stage) + i] = D[stage][i];
+ }
+ }
+ return;
+}
+
+/*---------------------------------------------------------------------------
+ * qlsf_ARSN_tcvq_Dec_16k()
+ *
+ * Predictive BC-TCQ encoder for LSF quantization
+ *--------------------------------------------------------------------------*/
+
+short qlsf_ARSN_tcvq_Dec_16k (
+ float *y, /* o : Quantized LSF vector */
+ short *indice, /* i : Indices */
+ const short nBits /* i : number of bits */
+)
+{
+ short i;
+ float error_svq_q[M];
+ short safety_net;
+
+ /* Select Mode */
+ safety_net = indice[0];
+
+
+ if(safety_net == 1)
+ {
+ tcvq_Dec(&indice[1], y, safety_net);
+
+ if(nBits>30)
+ {
+ for(i = 0; i < 8; i++)
+ {
+ error_svq_q[i] = AR_SVQ_CB1[indice[10]][i];
+ error_svq_q[i+8] = AR_SVQ_CB2[indice[11]][i];
+ }
+
+ for(i = 0; i < M; i++)
+ {
+ y[i] = y[i] + error_svq_q[i] * scale_ARSN[i];
+ }
+ }
+ }
+ else
+ {
+ tcvq_Dec(&indice[1], y, safety_net);
+
+ if(nBits>30)
+ {
+ for(i = 0; i < 8; i++)
+ {
+ error_svq_q[i] = AR_SVQ_CB1[indice[10]][i];
+ error_svq_q[i+8] = AR_SVQ_CB2[indice[11]][i];
+ }
+
+ for(i = 0; i < M; i++)
+ {
+ y[i] = y[i] + error_svq_q[i];
+ }
+ }
+ }
+
+ return safety_net;
+}
+
+
+/*-------------------------------------------------------------------*
+ * lsf_syn_mem_backup()
+ *
+ * back-up synthesis filter memory and LSF qunatizer memories (used in SC-VBR)
+ *-------------------------------------------------------------------*/
+
+void lsf_syn_mem_backup(
+ Encoder_State *st, /* i: state structure */
+ LPD_state* LPDmem, /* i: LPD state memory structure */
+ float *btilt_code, /* i: tilt code */
+ float *bgc_threshold, /* i: */
+ float *clip_var_bck, /* o: */
+ short *next_force_sf_bck, /* 0: */
+
+ float *lsp_new, /* i: LSP vector to quantize */
+ float *lsp_mid, /* i: mid-frame LSP vector */
+ float *clip_var, /* o: pitch clipping state var */
+ float *mem_AR, /* o: quantizer memory for AR model */
+ float *mem_MA, /* o: quantizer memory for AR model */
+ float *lsp_new_bck, /* o: LSP vector to quantize- backup */
+ float *lsp_mid_bck, /* o: mid-frame LSP vector - backup */
+ short *mCb1, /* o: counter for stationary frame after a transition frame */
+ float *Bin_E, /* o: FFT Bin energy 128 *2 sets */
+ float *Bin_E_old, /* o: FFT Bin energy 128 sets */
+ float *mem_syn_bck, /* o: synthesis filter memory */
+ float *mem_w0_bck, /* o: memory of the weighting filter */
+ float *streaklimit,
+ short *pstreaklen
+)
+{
+ short i;
+
+ *clip_var = st->clip_var[0];
+
+ for(i=0; imem_AR[i];
+ mem_MA[i] = st->mem_MA[i];
+ lsp_new_bck[i] = lsp_new[i];
+ lsp_mid_bck[i] = lsp_mid[i];
+ }
+
+ *mCb1 = st->mCb1;
+ *streaklimit = st->streaklimit;
+ *pstreaklen = st->pstreaklen;
+
+ for(i=0; iBin_E[i];
+ }
+
+ for(i=0; i<(L_FFT/2); i++)
+ {
+ Bin_E_old[i]=st->Bin_E_old[i];
+ }
+
+ /* back-up memories */
+ for(i=0; iLPDmem.mem_syn[i];
+ }
+
+ *mem_w0_bck = st->LPDmem.mem_w0;
+
+ *btilt_code = LPDmem->tilt_code;
+ *bgc_threshold = LPDmem->gc_threshold;
+ mvr2r( st->clip_var, clip_var_bck, 6 );
+ *next_force_sf_bck = st->next_force_safety_net;
+
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------*
+ * lsf_syn_mem_restore()
+ *
+ * restore synthesis filter memory and LSF quantizer memories
+ *-------------------------------------------------------------------*/
+
+void lsf_syn_mem_restore(
+ Encoder_State *st, /* o: state structure */
+ LPD_state* LPDmem, /* o: LPD_state vewctor */
+ float btilt_code, /* i: */
+ float gc_threshold, /* i: */
+ float *clip_var_bck, /* i: */
+ short next_force_sf_bck, /* i: */
+
+ float *lsp_new, /* o: LSP vector to quantize */
+ float *lsp_mid, /* o: mid-frame LSP vector */
+ float clip_var, /* i: pitch clipping state var */
+ float *mem_AR, /* i: quantizer memory for AR model */
+ float *mem_MA, /* i: quantizer memory for AR model */
+ float *lsp_new_bck, /* i: LSP vector to quantize- backup */
+ float *lsp_mid_bck, /* i: mid-frame LSP vector - backup */
+ short mCb1, /* i: counter for stationary frame after a transition frame */
+ float *Bin_E, /* i: FFT Bin energy 128 *2 sets */
+ float *Bin_E_old, /* i: FFT Bin energy 128 sets */
+ float *mem_syn_bck, /* i: synthesis filter memory */
+ float mem_w0_bck, /* i: memory of the weighting filter */
+ float streaklimit,
+ short pstreaklen
+)
+{
+ short i;
+
+ /* restore lsf memories */
+ st->clip_var[0] = clip_var;
+
+ for(i=0; imem_AR[i] = mem_AR[i];
+ st->mem_MA[i] = mem_MA[i];
+ lsp_new[i] = lsp_new_bck[i];
+ lsp_mid[i] = lsp_mid_bck[i];
+ }
+
+ st->mCb1 = mCb1;
+ st->streaklimit = streaklimit;
+ st->pstreaklen = pstreaklen;
+
+ for(i=0; iBin_E[i] = Bin_E[i];
+ }
+
+ for(i=0; i<(L_FFT/2); i++)
+ {
+ st->Bin_E_old[i]=Bin_E_old[i];
+ }
+
+ /* restoring memories */
+ st->LPDmem.mem_w0 = mem_w0_bck;
+
+ for(i=0; iLPDmem.mem_syn[i] = mem_syn_bck[i];
+ }
+
+ LPDmem->tilt_code = btilt_code;
+ LPDmem->gc_threshold = gc_threshold;
+ mvr2r( clip_var_bck, st->clip_var, 6 );
+ st->next_force_safety_net = next_force_sf_bck;
+
+
+ return;
+}
+
+/*--------------------------------------------------------------------------*
+ * lsf_update_memory()
+ *
+ *
+ *--------------------------------------------------------------------------*/
+
+void lsf_update_memory(
+ int narrowband, /* i : narrowband flag */
+ const float qlsf[], /* i : quantized lsf coefficients */
+ float old_mem_MA[], /* i : MA memory */
+ float mem_MA[] /* o : updated MA memory */
+)
+{
+ int i;
+
+ for (i=0; i= 0; specix++)
+ {
+ ;
+ }
+
+ lsf[lsfix++] = (specix-1 + spec_r[specix-1]/(spec_r[specix-1]-spec_r[specix]))*(12800/256);
+
+ /*check for the next zero crossing*/
+ for (; s * spec_i[specix] >= 0; specix++)
+ {
+ ;
+ }
+
+ lsf[lsfix++] = (specix-1 + spec_i[specix-1]/(spec_i[specix-1]-spec_i[specix]))*(12800/256);
+
+ spec_r[speclen] = s;
+ spec_i[speclen] = s;
+
+ s =-s;
+ }
+
+ if (lsfix < 16)
+ {
+ for(i=0; i<16; i++)
+ {
+ lsf[i] = old_lsf[i];
+ }
+ }
+
+ return;
+}
+
+/*--------------------------------------------------------------------------*
+ * a2isf()
+ *
+ *
+ *--------------------------------------------------------------------------*/
+
+#define SCALE1_HALF 1018.59161376953f
+
+typedef struct
+{
+ float re;
+ float im;
+} Pfloat;
+
+void a2isf(
+ float *a,
+ float *isf,
+ const float *old_isf,
+ short lpcOrder
+)
+{
+ float RealFFT[128];
+ float ImagFFT[128];
+ float RealOut[130];
+ float ImagOut[130];
+ float *ptrReal;
+ float *ptrImag;
+ int n, i, j;
+ const Pfloat *ptwiddle;
+ Pfloat *pwn17, pwn[128], *pwn15, tmpw15;
+ int N = 256;
+ float s[4];
+ float L_tmp, L_tmp1;
+ float lpc[19], fftTmpRe[16], fftTmpIm[16];
+ Pfloat twid[128];
+ float c;
+
+ set_zero(fftTmpRe, 16);
+ set_zero(fftTmpIm, 16);
+
+ /* half length FFT */
+ /*c = [sum(a) ((-1).^(1:length(a)))*a];*/
+
+ L_tmp = 0;
+ for(j=0; j<=lpcOrder; j++)
+ {
+ L_tmp += a[j];
+ }
+
+ L_tmp1 = 0;
+ for(j=0; jre) - (lpc[2*j+1] * ptwiddle->im);
+ fftTmpIm[j] = (lpc[2*j+1] * ptwiddle->re) + (lpc[2*j] * ptwiddle->im);
+ ptwiddle++;
+ }
+
+ fftTmpRe[j] = lpc[2*j]*ptwiddle->re;
+ fftTmpIm[j] = lpc[2*j]*ptwiddle->im;
+ ptwiddle++;
+ j++;
+ for(; j<16; j++)
+ {
+ fftTmpRe[j] = 0;
+ fftTmpIm[j] = 0;
+ ptwiddle++;
+ }
+
+ DoRTFTn(fftTmpRe, fftTmpIm, 16);
+
+ for(j=0; j<16; j++)
+ {
+ ptrReal[j*8] = fftTmpRe[j];
+ ptrImag[j*8] = fftTmpIm[j];
+ }
+
+ ptrReal++;
+ ptrImag++;
+
+ }
+
+ c = EVS_PI / ( 2.0f * (float)128 );
+
+ for ( i = 1 ; i < 128 ; i++ )
+ {
+ twid[i-1].im = (float)sin( c * ( 2.0f * (float)i ) );
+ twid[i-1].re = (float)cos( c * ( 2.0f * (float)i ) );
+ }
+ ptwiddle = twid;
+
+ /* pre-twiddle */
+ for ( i = 1 ; i < 128 ; i++ )
+ {
+ pwn[i-1].im = (float)sin( c * ( 18.0f * (float)i ) );
+ pwn[i-1].re = (float)cos( c * ( 18.0f * (float)i ) );
+ }
+
+ pwn17 = pwn;
+ pwn15 = &tmpw15;
+
+ /*Y(1) = real(X(1)) + imag(X(1));*/
+ RealOut[0] = (RealFFT[0] + ImagFFT[0]);
+ ImagOut[0] = 0;
+
+ /*Y(N/2+1) = 0.5*(X(1) + conj(X(1))).*exp(pi*i*128*(18)/N) - i*0.5*(X(1) - conj(X(1))).*exp(pi*i*128*(16)/N);*/
+ RealOut[128] = 0;
+ ImagOut[128] = (RealFFT[0] + RealFFT[0]) - (ImagFFT[0] + ImagFFT[0]);
+
+ /*Y(2:N/2) = (0.5*(X(2:N/2) + conj(X(N/2:-1:2))) - i*0.5*(X(2:N/2) - conj(X(N/2:-1:2))).*exp(-pi*i*r*(2)/N)).*exp(pi*i*r*(18)/N);*/
+ for(i=1; ire * pwn17->re) + (ptwiddle->im * pwn17->im);
+ tmpw15.im = (ptwiddle->re * pwn17->im) - (ptwiddle->im * pwn17->re);
+
+ /*RealOut[i] = mac_r(L_msu(L_msu(L_mult(ReAr, pwn17->re),ImAr, pwn17->im), ReBr, pwn15->v.im), ImBr, pwn15->re); move16();*/
+ RealOut[i] = (ReAr * pwn17->re) - (ImAr * pwn17->im) - ((ReBr * pwn15->im) + (ImBr * pwn15->re));
+ ImagOut[i] = (ReAr * pwn17->im) + (ImAr * pwn17->re) + (ReBr * pwn15->re) - (ImBr * pwn15->im);
+
+ ptwiddle++;
+ pwn17++;
+ }
+
+ spec2isf(RealOut, ImagOut, 128, isf, old_isf);
+
+ isf[lpcOrder - 1] = (Float32)(acos(a[lpcOrder]) * SCALE1_HALF);
+
+ return;
+}
diff --git a/lib_com/lsp_conv_poly.c b/lib_com/lsp_conv_poly.c
new file mode 100644
index 0000000000000000000000000000000000000000..629713223a1b6f433f5fa3d478c425b04000ffcb
--- /dev/null
+++ b/lib_com/lsp_conv_poly.c
@@ -0,0 +1,630 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include
+#include "wmc_auto.h"
+#include "options.h"
+#include "cnst.h"
+#include "rom_com.h"
+#include "prot.h"
+
+
+/*-------------------------------------------------------------------*
+ * Local constants
+ *-------------------------------------------------------------------*/
+
+/* The conversion modes. */
+#define DOWNCONV 0
+#define UPCONV 1
+/* The cap of the inverse power spectrum. */
+#define MAXPOWERSPECT 1e-5f
+#define N50 GRID50_POINTS
+#define N40 GRID40_POINTS
+
+
+/*-------------------------------------------------------------------*
+ * Local functions
+ *-------------------------------------------------------------------*/
+
+static void powerspect( const float x[], const short N, float R[], float S[], float G[], const short mode );
+
+static void spectautocorr( const float x[], const short N, const float G[], float r[] );
+
+static void zeros2poly( float x[], float R[], float S[] );
+
+static void polydecomp( float A[], float P[], float Q[] );
+
+static void cheb2poly( float P[] );
+
+
+/*---------------------------------------------------------------------*
+ * lsp_convert_poly()
+ *
+ * Converts the LP filter estimated at 16.0 kHz sampling rate down
+ * 12.8 kHz frequency scale or alternatively from 12.8 kHz up to
+ * 16.0 kHz. The former is called down conversation and latter up
+ * conversion. The resulting LP filter is characterized with its
+ * line spectrum pairs. The original Lp filter can be either in
+ * its immittance, used for the AMR-WB IO mode, or line spectrum
+ * pair representation.
+ *
+ * The conversion is based the autocorrelation computed from the
+ * power spectrum of the LP filter that is truncated or extrapolated
+ * to the desired frequency scale.
+ *---------------------------------------------------------------------*/
+
+short lsp_convert_poly(
+ float w[], /* i/o: LSP or ISP parameters */
+ const short L_frame, /* i : flag for up or down conversion */
+ const short Opt_AMRWB /* i : flag for the AMR-WB IO mode */
+)
+{
+ float epsP[M+1];
+ float G[GRID50_POINTS], r[M+1], A[M+1], A_old[M+1], R[NC+1], S[NC+1];
+ short i;
+ short flag;
+
+ /*---------------------------------------------------------------------*
+ * Because AMR-WB IO uses immittance spectrum frequency representation
+ * instead of line spectrum frequency representation, the input
+ * parameters do not give the zeros of the polynomials R(x) and S(x).
+ * Hence R(x) and S(x) are formed via the polynomial A(z) of the linear
+ * prediction filter.
+ *---------------------------------------------------------------------*/
+
+ if( Opt_AMRWB )
+ {
+ isp2a( w, A_old, M );
+ polydecomp( A_old, R, S );
+ }
+
+ /*---------------------------------------------------------------------*
+ * Form the polynomials R(x) and S(x) from their zeros that are the
+ * line spectrum pairs of A(z). The polynomial coefficients can be
+ * scaled for convenience, because scaling will not affect the
+ * resulting LP coefficients. Scaling by 128 gives the correct offset
+ * to the power spectrum for n = 16.
+ *---------------------------------------------------------------------*/
+
+ else
+ {
+ zeros2poly( w, R, S );
+ for (i = 0; i <= NC; i++)
+ {
+ R[i] *= 128.0f;
+ S[i] *= 128.0f;
+ }
+ lsp2a_stab( w, A_old, M );
+ }
+
+ /*---------------------------------------------------------------------*
+ * Conversion from 16.0 kHz down to 12.8 kHz. The power spectrum
+ * needs to be computed only up to 6.4 kHz, because the upper band
+ * is omitted.
+ *---------------------------------------------------------------------*/
+
+ if( L_frame == L_FRAME )
+ {
+ powerspect( grid50, N50, R, S, G, DOWNCONV );
+ spectautocorr( grid40, N40, G, r );
+ }
+
+ /*---------------------------------------------------------------------*
+ * Conversion from 12.8 kHz up to 16.0 kHz.
+ * Compute the power spectrum of the LP filter, extrapolate the
+ * power spectrum from 6.4 kHz to 8.0 kHz, and compute auto-
+ * correlation on this power spectrum.
+ *---------------------------------------------------------------------*/
+
+ else
+ {
+ powerspect( grid40, N40, R, S, G, UPCONV );
+ for (i = N40; i < N50; i++)
+ {
+ G[i] = G[N40-1];
+ }
+
+ spectautocorr( grid50, N50, G, r );
+ }
+
+ /*---------------------------------------------------------------------*
+ * Compute the linear prediction coefficients from the autocorrelation
+ * and convert to line spectrum pairs.
+ *---------------------------------------------------------------------*/
+
+ flag = lev_dur( A, r, M, epsP );
+ a2lsp_stab( A, w, stable_LSP );
+
+ return(flag);
+}
+
+
+/*---------------------------------------------------------------------*
+ * powerspect()
+ *
+ * Computes the power spectrum G(w) = 1/|A(w)|^2 at N points on
+ * the real axis x = cos w by utilizing the line spectrum frequency
+ * decomposition
+ *
+ * A(z) = (P(z) + Q(z))/2,
+ *
+ * where assuming A(z) of an even degree n,
+ *
+ * P(z) = [A(z) + z^(n+1) A(1/z)]/(1/z + 1),
+ * Q(z) = [A(z) - z^(n+1) A(1/z)]/(1/z - 1).
+ *
+ * The zeros of these polynomials give the line spectrum frequencies
+ * of A(z). It can be shown that for an even n,
+ *
+ * |A(x)|^2 = 2 (1 + x) R(x)^2 + 2 (1 - x) S(x)^2,
+ *
+ * where x = cos w, and R(x) and S(x) are the direct polynomials
+ * resulting from the Chebyshev series representation of P(z)
+ * and Q(z).
+ *
+ * This routine assumes the grid X = 1, x[0], x[1], .., x[m-1],
+ * -, ..., -x[1], -x[0], -1 such that x[i] = cos((i+1)*pi/N) for
+ * evaluating the power spectrum. Only m = (N-1)/2 - 1 grid points
+ * need to be stored, because cos(0) and cos(pi/2) are trivial,
+ * and the points above pi/2 are obtained readily using the symmetry
+ * of cosine.
+ *
+ * The power spectrum can be scaled as a*G[], where a is chosen
+ * for convenience. This is because the scaling has no impact on
+ * the LP coefficients to be determined based on the power spectrum.
+ *---------------------------------------------------------------------*/
+
+static void powerspect(
+ const float x[], /* i: Grid points x[0:N-1] */
+ const short N, /* i: Number of grid points */
+ float R[], /* i: Coefficients of R(x) in R[0:NC] */
+ float S[], /* i: Coefficients of S(x) in S[0:NC] */
+ float G[], /* o: Power spectrum G[0:N] */
+ const short mode /* i: Flag for up or down conversion */
+)
+{
+ float re, ro, se, so;
+ float s0, s1, r0, r1, x0, x1, x2;
+ Word16 i, j;
+ Word16 iuni, imid;
+
+ /* init buffer */
+ for(i=0; i cos(pi/2) = 0.
+ *---------------------------------------------------------------------*/
+
+ for (i = 1; i <= iuni; i++)
+ {
+ x0 = x[i-1];
+ r0 = R[0];
+ s0 = S[0];
+
+ for (j = 1; j <= NC; j++)
+ {
+ r0 = x0*r0 + R[j];
+ s0 = x0*s0 + S[j];
+ }
+ r0 = (1.0f + x0)*r0*r0;
+ s0 = (1.0f - x0)*s0*s0;
+
+ G[i] = 2.0f*(r0 + s0);
+ }
+
+ /*---------------------------------------------------------------------*
+ * Power spectrum at points other than x = -1, 0, and 1 and unique
+ * points is computed using the anti-symmetry of the grid relative
+ * to the midpoint x = 0 in order to reduce looping.
+ *---------------------------------------------------------------------*/
+
+ for ( ; i < imid; i++)
+ {
+ x0 = x[i-1];
+ x2 = x0*x0;
+
+ re = R[0];
+ se = S[0];
+ ro = R[1];
+ so = S[1];
+
+ for (j = 2; j < NC; j+=2)
+ {
+ re = x2*re + R[j];
+ ro = x2*ro + R[j+1];
+ se = x2*se + S[j];
+ so = x2*so + S[j+1];
+ }
+
+ re = x2*re + R[j];
+ ro *= x0;
+ se = x2*se + S[j];
+ so *= x0;
+
+ r0 = re + ro;
+ s0 = se + so;
+ r1 = re - ro;
+ s1 = se - so;
+
+ x1 = 1.0f + x0;
+ x2 = 1.0f - x0;
+
+ r0 = x1*r0*r0;
+ s0 = x2*s0*s0;
+ r1 = x2*r1*r1;
+ s1 = x1*s1*s1;
+
+ G[i] = 2.0f*(r0 + s0);
+ G[N-i-1] = 2.0f*(r1 + s1);
+ }
+
+ /*---------------------------------------------------------------------*
+ * Compute the power spectrum 1/|A(x)|^2 from |A(x)|^2 with logic
+ * to prevent division by small number and upper bound the spectrum.
+ * This upper bound is implicit in fixed point arithmetic, but is
+ * needed explicitly in floating point implementations to avoid numeric
+ * problems.
+ *---------------------------------------------------------------------*/
+
+ for(i=0; i 0; j--)
+ {
+ R[j] += xr*R[j-1];
+ S[j] += xs*S[j-1];
+ }
+ }
+
+ return;
+}
+
+/*---------------------------------------------------------------------*
+ * polydecomp()
+ *
+ * Computes the coefficients of the symmetric and antisymmetric
+ * polynomials P(z) and Q(z) that define the line spectrum pair
+ * decomposition of a given polynomial A(z) of order n. For even n,
+ *
+ * P(z) = [A(z) + z^(n+1) A(1/z)]/(1/z + 1),
+ * Q(z) = [A(z) - z^(n+1) A(1/z)]/(1/z - 1),
+ *
+ * These polynomials are then expressed in their direct form,
+ * respectively, R(x) and S(x), on the real axis x = cos w using
+ * explicit Chebyshev polynomials of the first kind.
+ *
+ * The coefficients of the polynomials R(x) and S(x) are returned
+ * in R[0:n/2] and S[0:n/2] for the given linear prediction
+ * coefficients A[0:n/2]. Note that R(x) and S(x) are formed in
+ * place such that P(z) is stored in the same array than R(x),
+ * and Q(z) is stored in the same array than S(x).
+ *
+ * The routines assumes n = 16.
+ *---------------------------------------------------------------------*/
+
+static void polydecomp(
+ float A[], /* i: linear prediction coefficients */
+ float R[], /* o: coefficients of R(x) */
+ float S[] /* o: coefficients of S(x) */
+)
+{
+ float *P = &R[0], *Q = &S[0];
+ Word16 i, j;
+
+ P[0] = A[0];
+ Q[0] = A[0];
+ for (i = 1, j = M; i <= NC; i++, j--)
+ {
+ P[i] = A[i] + A[j] - P[i-1];
+ Q[i] = A[i] - A[j] + Q[i-1];
+ }
+
+ cheb2poly(P);
+ cheb2poly(Q);
+
+ return;
+}
+
+/*---------------------------------------------------------------------*
+ * cheb2poly()
+ *
+ * Computes the coefficients of the explicit Chebyshev polynomial
+ * P(x) = P[0]*x^n + P[1]*x^(n-1) + ... + P[n] given the coefficients
+ * of the series
+ *
+ * C(x) = C[0]*T_n(x) + C[1]*T_n-1(x) + ... + C[n]*T_0(x),
+ *
+ * where T_n(x) is the nth Chebyshev polynomial of the first kind.
+ * This implementation assumes C[0] = 1. Only the value n = 8 is
+ * supported.
+ *
+ * The conversion from C(x) to P(x) is done in place such that the
+ * coefficients of C(x) are given in P[0:8] and those of P(x) are
+ * returned in the same array.
+ *---------------------------------------------------------------------*/
+
+static void cheb2poly(
+ float P[] /* i/o: The coefficients of C(x) and P(x) */
+)
+{
+ float c1, c2, c3, c4, c5, c6, c7, c8;
+
+ c1 = P[1];
+ c2 = P[2];
+ c3 = P[3];
+ c4 = P[4];
+ c5 = P[5];
+ c6 = P[6];
+ c7 = P[7];
+ c8 = P[8];
+
+ P[0] = 128.0f;
+ P[1] = 64.0f*c1;
+ P[2] = 32.0f*c2 - 256.0f;
+ P[3] = 16.0f*c3 - 112.0f*c1;
+ P[4] = 160.0f - 48.0f*c2 + 8.0f*c4;
+ P[5] = 56.0f*c1 - 20.0f*c3 + 4.0f*c5;
+ P[6] = 18.0f*c2 - 32.0f - 8.0f*c4 + 2.0f*c6;
+ P[7] = 5.0f*c3 - 7.0f*c1 - 3.0f*c5 + c7;
+ P[8] = 1.0f - c2 + c4 - c6 + 0.5f*c8;
+
+ return;
+}
diff --git a/lib_com/mime.h b/lib_com/mime.h
new file mode 100644
index 0000000000000000000000000000000000000000..3d0b659caf6a5c1e9b22456a2b4224d9e5e8b903
--- /dev/null
+++ b/lib_com/mime.h
@@ -0,0 +1,423 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+
+#define AMRWB_MAGIC_NUMBER "#!AMR-WB\n" /* defined in RFC4867 */
+#define EVS_MAGIC_NUMBER "#!EVS_MC1.0\n" /* defined in 26.445 */
+
+static const Word32 AMRWB_IOmode2rate[16] =
+{
+ 6600, /* AMRWB_IO_6600 */
+ 8850, /* AMRWB_IO_8850 */
+ 12650, /* AMRWB_IO_1265 */
+ 14250, /* AMRWB_IO_1425 */
+ 15850, /* AMRWB_IO_1585 */
+ 18250, /* AMRWB_IO_1825 */
+ 19850, /* AMRWB_IO_1985 */
+ 23050, /* AMRWB_IO_2305 */
+ 23850, /* AMRWB_IO_2385 */
+ 1750, /* AMRWB_IO_SID */
+ -1, /* AMRWB_IO_FUT1 */
+ -1, /* AMRWB_IO_FUT2 */
+ -1, /* AMRWB_IO_FUT3 */
+ -1, /* AMRWB_IO_FUT4 */
+ 0, /* SPEECH_BAD */
+ 0 /* NO_DATA */
+};
+
+static const Word32 PRIMARYmode2rate[16] =
+{
+ 2800, /* PRIMARY_2800 */
+ 7200, /* PRIMARY_7200 */
+ 8000, /* PRIMARY_8000 */
+ 9600, /* PRIMARY_9600 */
+ 13200, /* PRIMARY_13200 */
+ 16400, /* PRIMARY_16400 */
+ 24400, /* PRIMARY_24400 */
+ 32000, /* PRIMARY_32000 */
+ 48000, /* PRIMARY_48000 */
+ 64000, /* PRIMARY_64000 */
+ 96000, /* PRIMARY_96000 */
+ 128000, /* PRIMARY_128000 */
+ 2400, /* PRIMARY_SID */
+ -1, /* PRIMARY_FUT1 */
+ 0, /* SPEECH_LOST */
+ 0 /* NO_DATA */
+};
+
+/* sorting tables for all AMR-WB IO modes */
+
+static const Word16 sort_660[132] =
+{
+ 0, 5, 6, 7, 61, 84, 107, 130, 62, 85,
+ 8, 4, 37, 38, 39, 40, 58, 81, 104, 127,
+ 60, 83, 106, 129, 108, 131, 128, 41, 42, 80,
+ 126, 1, 3, 57, 103, 82, 105, 59, 2, 63,
+ 109, 110, 86, 19, 22, 23, 64, 87, 18, 20,
+ 21, 17, 13, 88, 43, 89, 65, 111, 14, 24,
+ 25, 26, 27, 28, 15, 16, 44, 90, 66, 112,
+ 9, 11, 10, 12, 67, 113, 29, 30, 31, 32,
+ 34, 33, 35, 36, 45, 51, 68, 74, 91, 97,
+ 114, 120, 46, 69, 92, 115, 52, 75, 98, 121,
+ 47, 70, 93, 116, 53, 76, 99, 122, 48, 71,
+ 94, 117, 54, 77, 100, 123, 49, 72, 95, 118,
+ 55, 78, 101, 124, 50, 73, 96, 119, 56, 79,
+ 102, 125
+};
+
+static const Word16 sort_885[177] =
+{
+ 0, 4, 6, 7, 5, 3, 47, 48, 49, 112,
+ 113, 114, 75, 106, 140, 171, 80, 111, 145, 176,
+ 77, 108, 142, 173, 78, 109, 143, 174, 79, 110,
+ 144, 175, 76, 107, 141, 172, 50, 115, 51, 2,
+ 1, 81, 116, 146, 19, 21, 12, 17, 18, 20,
+ 16, 25, 13, 10, 14, 24, 23, 22, 26, 8,
+ 15, 52, 117, 31, 82, 147, 9, 33, 11, 83,
+ 148, 53, 118, 28, 27, 84, 149, 34, 35, 29,
+ 46, 32, 30, 54, 119, 37, 36, 39, 38, 40,
+ 85, 150, 41, 42, 43, 44, 45, 55, 60, 65,
+ 70, 86, 91, 96, 101, 120, 125, 130, 135, 151,
+ 156, 161, 166, 56, 87, 121, 152, 61, 92, 126,
+ 157, 66, 97, 131, 162, 71, 102, 136, 167, 57,
+ 88, 122, 153, 62, 93, 127, 158, 67, 98, 132,
+ 163, 72, 103, 137, 168, 58, 89, 123, 154, 63,
+ 94, 128, 159, 68, 99, 133, 164, 73, 104, 138,
+ 169, 59, 90, 124, 155, 64, 95, 129, 160, 69,
+ 100, 134, 165, 74, 105, 139, 170
+};
+
+static const Word16 sort_1265[253] =
+{
+ 0, 4, 6, 93, 143, 196, 246, 7, 5, 3,
+ 47, 48, 49, 50, 51, 150, 151, 152, 153, 154,
+ 94, 144, 197, 247, 99, 149, 202, 252, 96, 146,
+ 199, 249, 97, 147, 200, 250, 100, 203, 98, 148,
+ 201, 251, 95, 145, 198, 248, 52, 2, 1, 101,
+ 204, 155, 19, 21, 12, 17, 18, 20, 16, 25,
+ 13, 10, 14, 24, 23, 22, 26, 8, 15, 53,
+ 156, 31, 102, 205, 9, 33, 11, 103, 206, 54,
+ 157, 28, 27, 104, 207, 34, 35, 29, 46, 32,
+ 30, 55, 158, 37, 36, 39, 38, 40, 105, 208,
+ 41, 42, 43, 44, 45, 56, 106, 159, 209, 57,
+ 66, 75, 84, 107, 116, 125, 134, 160, 169, 178,
+ 187, 210, 219, 228, 237, 58, 108, 161, 211, 62,
+ 112, 165, 215, 67, 117, 170, 220, 71, 121, 174,
+ 224, 76, 126, 179, 229, 80, 130, 183, 233, 85,
+ 135, 188, 238, 89, 139, 192, 242, 59, 109, 162,
+ 212, 63, 113, 166, 216, 68, 118, 171, 221, 72,
+ 122, 175, 225, 77, 127, 180, 230, 81, 131, 184,
+ 234, 86, 136, 189, 239, 90, 140, 193, 243, 60,
+ 110, 163, 213, 64, 114, 167, 217, 69, 119, 172,
+ 222, 73, 123, 176, 226, 78, 128, 181, 231, 82,
+ 132, 185, 235, 87, 137, 190, 240, 91, 141, 194,
+ 244, 61, 111, 164, 214, 65, 115, 168, 218, 70,
+ 120, 173, 223, 74, 124, 177, 227, 79, 129, 182,
+ 232, 83, 133, 186, 236, 88, 138, 191, 241, 92,
+ 142, 195, 245
+};
+
+static const Word16 sort_1425[285] =
+{
+ 0, 4, 6, 101, 159, 220, 278, 7, 5, 3,
+ 47, 48, 49, 50, 51, 166, 167, 168, 169, 170,
+ 102, 160, 221, 279, 107, 165, 226, 284, 104, 162,
+ 223, 281, 105, 163, 224, 282, 108, 227, 106, 164,
+ 225, 283, 103, 161, 222, 280, 52, 2, 1, 109,
+ 228, 171, 19, 21, 12, 17, 18, 20, 16, 25,
+ 13, 10, 14, 24, 23, 22, 26, 8, 15, 53,
+ 172, 31, 110, 229, 9, 33, 11, 111, 230, 54,
+ 173, 28, 27, 112, 231, 34, 35, 29, 46, 32,
+ 30, 55, 174, 37, 36, 39, 38, 40, 113, 232,
+ 41, 42, 43, 44, 45, 56, 114, 175, 233, 62,
+ 120, 181, 239, 75, 133, 194, 252, 57, 115, 176,
+ 234, 63, 121, 182, 240, 70, 128, 189, 247, 76,
+ 134, 195, 253, 83, 141, 202, 260, 92, 150, 211,
+ 269, 84, 142, 203, 261, 93, 151, 212, 270, 85,
+ 143, 204, 262, 94, 152, 213, 271, 86, 144, 205,
+ 263, 95, 153, 214, 272, 64, 122, 183, 241, 77,
+ 135, 196, 254, 65, 123, 184, 242, 78, 136, 197,
+ 255, 87, 145, 206, 264, 96, 154, 215, 273, 58,
+ 116, 177, 235, 66, 124, 185, 243, 71, 129, 190,
+ 248, 79, 137, 198, 256, 88, 146, 207, 265, 97,
+ 155, 216, 274, 59, 117, 178, 236, 67, 125, 186,
+ 244, 72, 130, 191, 249, 80, 138, 199, 257, 89,
+ 147, 208, 266, 98, 156, 217, 275, 60, 118, 179,
+ 237, 68, 126, 187, 245, 73, 131, 192, 250, 81,
+ 139, 200, 258, 90, 148, 209, 267, 99, 157, 218,
+ 276, 61, 119, 180, 238, 69, 127, 188, 246, 74,
+ 132, 193, 251, 82, 140, 201, 259, 91, 149, 210,
+ 268, 100, 158, 219, 277
+};
+
+static const Word16 sort_1585[317] =
+{
+ 0, 4, 6, 109, 175, 244, 310, 7, 5, 3,
+ 47, 48, 49, 50, 51, 182, 183, 184, 185, 186,
+ 110, 176, 245, 311, 115, 181, 250, 316, 112, 178,
+ 247, 313, 113, 179, 248, 314, 116, 251, 114, 180,
+ 249, 315, 111, 177, 246, 312, 52, 2, 1, 117,
+ 252, 187, 19, 21, 12, 17, 18, 20, 16, 25,
+ 13, 10, 14, 24, 23, 22, 26, 8, 15, 53,
+ 188, 31, 118, 253, 9, 33, 11, 119, 254, 54,
+ 189, 28, 27, 120, 255, 34, 35, 29, 46, 32,
+ 30, 55, 190, 37, 36, 39, 38, 40, 121, 256,
+ 41, 42, 43, 44, 45, 56, 122, 191, 257, 63,
+ 129, 198, 264, 76, 142, 211, 277, 89, 155, 224,
+ 290, 102, 168, 237, 303, 57, 123, 192, 258, 70,
+ 136, 205, 271, 83, 149, 218, 284, 96, 162, 231,
+ 297, 62, 128, 197, 263, 75, 141, 210, 276, 88,
+ 154, 223, 289, 101, 167, 236, 302, 58, 124, 193,
+ 259, 71, 137, 206, 272, 84, 150, 219, 285, 97,
+ 163, 232, 298, 59, 125, 194, 260, 64, 130, 199,
+ 265, 67, 133, 202, 268, 72, 138, 207, 273, 77,
+ 143, 212, 278, 80, 146, 215, 281, 85, 151, 220,
+ 286, 90, 156, 225, 291, 93, 159, 228, 294, 98,
+ 164, 233, 299, 103, 169, 238, 304, 106, 172, 241,
+ 307, 60, 126, 195, 261, 65, 131, 200, 266, 68,
+ 134, 203, 269, 73, 139, 208, 274, 78, 144, 213,
+ 279, 81, 147, 216, 282, 86, 152, 221, 287, 91,
+ 157, 226, 292, 94, 160, 229, 295, 99, 165, 234,
+ 300, 104, 170, 239, 305, 107, 173, 242, 308, 61,
+ 127, 196, 262, 66, 132, 201, 267, 69, 135, 204,
+ 270, 74, 140, 209, 275, 79, 145, 214, 280, 82,
+ 148, 217, 283, 87, 153, 222, 288, 92, 158, 227,
+ 293, 95, 161, 230, 296, 100, 166, 235, 301, 105,
+ 171, 240, 306, 108, 174, 243, 309
+};
+
+static const Word16 sort_1825[365] =
+{
+ 0, 4, 6, 121, 199, 280, 358, 7, 5, 3,
+ 47, 48, 49, 50, 51, 206, 207, 208, 209, 210,
+ 122, 200, 281, 359, 127, 205, 286, 364, 124, 202,
+ 283, 361, 125, 203, 284, 362, 128, 287, 126, 204,
+ 285, 363, 123, 201, 282, 360, 52, 2, 1, 129,
+ 288, 211, 19, 21, 12, 17, 18, 20, 16, 25,
+ 13, 10, 14, 24, 23, 22, 26, 8, 15, 53,
+ 212, 31, 130, 289, 9, 33, 11, 131, 290, 54,
+ 213, 28, 27, 132, 291, 34, 35, 29, 46, 32,
+ 30, 55, 214, 37, 36, 39, 38, 40, 133, 292,
+ 41, 42, 43, 44, 45, 56, 134, 215, 293, 198,
+ 299, 136, 120, 138, 60, 279, 58, 62, 357, 139,
+ 140, 295, 156, 57, 219, 297, 63, 217, 137, 170,
+ 300, 222, 64, 106, 61, 78, 294, 92, 142, 141,
+ 135, 221, 296, 301, 343, 59, 298, 184, 329, 315,
+ 220, 216, 265, 251, 218, 237, 352, 223, 157, 86,
+ 171, 87, 164, 351, 111, 302, 65, 178, 115, 323,
+ 72, 192, 101, 179, 93, 73, 193, 151, 337, 309,
+ 143, 274, 69, 324, 165, 150, 97, 338, 110, 310,
+ 330, 273, 68, 107, 175, 245, 114, 79, 113, 189,
+ 246, 259, 174, 71, 185, 96, 344, 100, 322, 83,
+ 334, 316, 333, 252, 161, 348, 147, 82, 269, 232,
+ 260, 308, 353, 347, 163, 231, 306, 320, 188, 270,
+ 146, 177, 266, 350, 256, 85, 149, 116, 191, 160,
+ 238, 258, 336, 305, 255, 88, 224, 99, 339, 230,
+ 228, 227, 272, 242, 241, 319, 233, 311, 102, 74,
+ 180, 275, 66, 194, 152, 325, 172, 247, 244, 261,
+ 117, 158, 166, 354, 75, 144, 108, 312, 94, 186,
+ 303, 80, 234, 89, 195, 112, 340, 181, 345, 317,
+ 326, 276, 239, 167, 118, 313, 70, 355, 327, 253,
+ 190, 176, 271, 104, 98, 153, 103, 90, 76, 267,
+ 277, 248, 225, 262, 182, 84, 154, 235, 335, 168,
+ 331, 196, 341, 249, 162, 307, 148, 349, 263, 321,
+ 257, 243, 229, 356, 159, 119, 67, 187, 173, 145,
+ 240, 77, 304, 332, 314, 342, 109, 254, 81, 278,
+ 105, 91, 346, 318, 183, 250, 197, 328, 95, 155,
+ 169, 268, 226, 236, 264
+};
+
+static const Word16 sort_1985[397] =
+{
+ 0, 4, 6, 129, 215, 304, 390, 7, 5, 3,
+ 47, 48, 49, 50, 51, 222, 223, 224, 225, 226,
+ 130, 216, 305, 391, 135, 221, 310, 396, 132, 218,
+ 307, 393, 133, 219, 308, 394, 136, 311, 134, 220,
+ 309, 395, 131, 217, 306, 392, 52, 2, 1, 137,
+ 312, 227, 19, 21, 12, 17, 18, 20, 16, 25,
+ 13, 10, 14, 24, 23, 22, 26, 8, 15, 53,
+ 228, 31, 138, 313, 9, 33, 11, 139, 314, 54,
+ 229, 28, 27, 140, 315, 34, 35, 29, 46, 32,
+ 30, 55, 230, 37, 36, 39, 38, 40, 141, 316,
+ 41, 42, 43, 44, 45, 56, 142, 231, 317, 63,
+ 73, 92, 340, 82, 324, 149, 353, 159, 334, 165,
+ 338, 178, 163, 254, 77, 168, 257, 153, 343, 57,
+ 248, 238, 79, 252, 166, 67, 80, 201, 101, 267,
+ 143, 164, 341, 255, 339, 187, 376, 318, 78, 328,
+ 362, 115, 232, 242, 253, 290, 276, 62, 58, 158,
+ 68, 93, 179, 319, 148, 169, 154, 72, 385, 329,
+ 333, 344, 102, 83, 144, 233, 323, 124, 243, 192,
+ 354, 237, 64, 247, 202, 209, 150, 116, 335, 268,
+ 239, 299, 188, 196, 298, 94, 195, 258, 123, 363,
+ 384, 109, 325, 371, 170, 370, 84, 110, 295, 180,
+ 74, 210, 191, 106, 291, 205, 367, 381, 377, 206,
+ 355, 122, 119, 120, 383, 160, 105, 108, 277, 380,
+ 294, 284, 285, 345, 208, 269, 249, 366, 386, 300,
+ 297, 259, 125, 369, 197, 97, 194, 286, 211, 281,
+ 280, 183, 372, 87, 155, 283, 59, 348, 327, 184,
+ 76, 111, 330, 203, 349, 69, 98, 152, 145, 189,
+ 66, 320, 337, 173, 358, 251, 198, 174, 263, 262,
+ 126, 241, 193, 88, 388, 117, 95, 387, 112, 359,
+ 287, 244, 103, 272, 301, 171, 162, 234, 273, 127,
+ 373, 181, 292, 85, 378, 302, 121, 107, 364, 346,
+ 356, 212, 278, 213, 65, 382, 288, 207, 113, 175,
+ 99, 296, 374, 368, 199, 260, 185, 336, 331, 161,
+ 270, 264, 250, 240, 75, 350, 151, 60, 89, 321,
+ 156, 274, 360, 326, 70, 282, 167, 146, 352, 81,
+ 91, 389, 266, 245, 177, 235, 190, 256, 204, 342,
+ 128, 118, 303, 104, 379, 182, 114, 375, 200, 96,
+ 293, 172, 214, 365, 279, 86, 289, 351, 347, 357,
+ 261, 186, 176, 271, 90, 100, 147, 322, 275, 361,
+ 71, 332, 61, 265, 157, 246, 236
+};
+
+static const Word16 sort_2305[461] =
+{
+ 0, 4, 6, 145, 247, 352, 454, 7, 5, 3,
+ 47, 48, 49, 50, 51, 254, 255, 256, 257, 258,
+ 146, 248, 353, 455, 151, 253, 358, 460, 148, 250,
+ 355, 457, 149, 251, 356, 458, 152, 359, 150, 252,
+ 357, 459, 147, 249, 354, 456, 52, 2, 1, 153,
+ 360, 259, 19, 21, 12, 17, 18, 20, 16, 25,
+ 13, 10, 14, 24, 23, 22, 26, 8, 15, 53,
+ 260, 31, 154, 361, 9, 33, 11, 155, 362, 54,
+ 261, 28, 27, 156, 363, 34, 35, 29, 46, 32,
+ 30, 55, 262, 37, 36, 39, 38, 40, 157, 364,
+ 41, 42, 43, 44, 45, 56, 158, 263, 365, 181,
+ 192, 170, 79, 57, 399, 90, 159, 297, 377, 366,
+ 275, 68, 183, 388, 286, 194, 299, 92 , 70, 182,
+ 401, 172, 59, 91, 58, 400, 368, 161, 81, 160,
+ 264, 171, 80, 389, 390, 378, 379, 193, 298, 69,
+ 266, 265, 367, 277, 288, 276, 287, 184, 60, 195,
+ 82, 93, 71, 369, 402, 173, 162, 444, 300, 391,
+ 98, 76, 278, 61, 267, 374, 135, 411, 167, 102,
+ 380, 200, 87, 178, 65, 94, 204, 124, 72, 342,
+ 189, 305, 381, 396, 433, 301, 226, 407, 289, 237,
+ 113, 215, 185, 128, 309, 403, 116, 320, 196, 331,
+ 370, 422, 174, 64, 392, 83, 425, 219, 134, 188,
+ 432, 112, 427, 139, 279, 163, 436, 208, 447, 218,
+ 236, 229, 97, 294, 385, 230, 166, 268, 177, 443,
+ 225, 426, 101, 272, 138, 127, 290, 117, 347, 199,
+ 414, 95, 140, 240, 410, 395, 209, 129, 283, 346,
+ 105, 241, 437, 86, 308, 448, 203, 345, 186, 107,
+ 220, 415, 334, 319, 106, 313, 118, 123, 73, 207,
+ 421, 214, 384, 373, 438, 62, 371, 341, 75, 449,
+ 168, 323, 164, 242, 416, 324, 304, 197, 335, 404,
+ 271, 63, 191, 325, 96, 169, 231, 280, 312, 187,
+ 406, 84, 201, 100, 67, 382, 175, 336, 202, 330,
+ 269, 393, 376, 383, 293, 307, 409, 179, 285, 314,
+ 302, 372, 398, 190, 180, 89, 99, 103, 232, 78,
+ 88, 77, 136, 387, 165, 198, 394, 125, 176, 428,
+ 74, 375, 238, 227, 66, 273, 282, 141, 306, 412,
+ 114, 85, 130, 348, 119, 291, 296, 386, 233, 397,
+ 303, 405, 284, 445, 423, 221, 210, 205, 450, 108,
+ 274, 434, 216, 343, 337, 142, 243, 321, 408, 451,
+ 310, 292, 120, 109, 281, 439, 270, 429, 332, 295,
+ 418, 211, 315, 222, 326, 131, 430, 244, 327, 349,
+ 417, 316, 143, 338, 440, 234, 110, 212, 452, 245,
+ 121, 419, 350, 223, 132, 441, 328, 413, 317, 339,
+ 126, 104, 137, 446, 344, 239, 435, 115, 333, 206,
+ 322, 217, 228, 424, 453, 311, 351, 111, 442, 224,
+ 213, 122, 431, 340, 235, 246, 133, 144, 420, 329,
+ 318
+};
+
+static const Word16 sort_2385[477] =
+{
+ 0, 4, 6, 145, 251, 360, 466, 7, 5, 3,
+ 47, 48, 49, 50, 51, 262, 263, 264, 265, 266,
+ 146, 252, 361, 467, 151, 257, 366, 472, 148, 254,
+ 363, 469, 149, 255, 364, 470, 156, 371, 150, 256,
+ 365, 471, 147, 253, 362, 468, 52, 2, 1, 157,
+ 372, 267, 19, 21, 12, 17, 18, 20, 16, 25,
+ 13, 10, 14, 24, 23, 22, 26, 8, 15, 53,
+ 268, 31, 152, 153, 154, 155, 258, 259, 260, 261,
+ 367, 368, 369, 370, 473, 474, 475, 476, 158, 373,
+ 9, 33, 11, 159, 374, 54, 269, 28, 27, 160,
+ 375, 34, 35, 29, 46, 32, 30, 55, 270, 37,
+ 36, 39, 38, 40, 161, 376, 41, 42, 43, 44,
+ 45, 56, 162, 271, 377, 185, 196, 174, 79, 57,
+ 411, 90, 163, 305, 389, 378, 283, 68, 187, 400,
+ 294, 198, 307, 92, 70, 186, 413, 176, 59, 91,
+ 58, 412, 380, 165, 81, 164, 272, 175, 80, 401,
+ 402, 390, 391, 197, 306, 69, 274, 273, 379, 285,
+ 296, 284, 295, 188, 60, 199, 82, 93, 71, 381,
+ 414, 177, 166, 456, 308, 403, 98, 76, 286, 61,
+ 275, 386, 135, 423, 171, 102, 392, 204, 87, 182,
+ 65, 94, 208, 124, 72, 350, 193, 313, 393, 408,
+ 445, 309, 230, 419, 297, 241, 113, 219, 189, 128,
+ 317, 415, 116, 328, 200, 339, 382, 434, 178, 64,
+ 404, 83, 437, 223, 134, 192, 444, 112, 439, 139,
+ 287, 167, 448, 212, 459, 222, 240, 233, 97, 302,
+ 397, 234, 170, 276, 181, 455, 229, 438, 101, 280,
+ 138, 127, 298, 117, 355, 203, 426, 95, 140, 244,
+ 422, 407, 213, 129, 291, 354, 105, 245, 449, 86,
+ 316, 460, 207, 353, 190, 107, 224, 427, 342, 327,
+ 106, 321, 118, 123, 73, 211, 433, 218, 396, 385,
+ 450, 62, 383, 349, 75, 461, 172, 331, 168, 246,
+ 428, 332, 312, 201, 343, 416, 279, 63, 195, 333,
+ 96, 173, 235, 288, 320, 191, 418, 84, 205, 100,
+ 67, 394, 179, 344, 206, 338, 277, 405, 388, 395,
+ 301, 315, 421, 183, 293, 322, 310, 384, 410, 194,
+ 184, 89, 99, 103, 236, 78, 88, 77, 136, 399,
+ 169, 202, 406, 125, 180, 440, 74, 387, 242, 231,
+ 66, 281, 290, 141, 314, 424, 114, 85, 130, 356,
+ 119, 299, 304, 398, 237, 409, 311, 417, 292, 457,
+ 435, 225, 214, 209, 462, 108, 282, 446, 220, 351,
+ 345, 142, 247, 329, 420, 463, 318, 300, 120, 109,
+ 289, 451, 278, 441, 340, 303, 430, 215, 323, 226,
+ 334, 131, 442, 248, 335, 357, 429, 324, 143, 346,
+ 452, 238, 110, 216, 464, 249, 121, 431, 358, 227,
+ 132, 453, 336, 425, 325, 347, 126, 104, 137, 458,
+ 352, 243, 447, 115, 341, 210, 330, 221, 232, 436,
+ 465, 319, 359, 111, 454, 228, 217, 122, 443, 348,
+ 239, 250, 133, 144, 432, 337, 326
+};
+
+static const Word16 sort_SID[35] =
+{
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34
+};
+
+/* pointer table for bit sorting tables */
+static const Word16 *const sort_ptr[16] = { sort_660, sort_885, sort_1265, sort_1425, sort_1585, sort_1825, sort_1985, sort_2305,
+ sort_2385, sort_SID, NULL, NULL, NULL, NULL, NULL, NULL
+ };
+
+/* 4 bit to 3 bit AMR-WB CMR remapping table */
+static const Word16 amrwb_3bit_cmr[16] =
+{
+ 0x00, /* AMRWB_660 */
+ 0x01, /* AMRWB_885 */
+ 0x02, /* AMRWB_1265 */
+ 0x05, /* AMRWB_1425 */
+ 0x03, /* AMRWB_1585 */
+ 0x06, /* AMRWB_1825 */
+ 0x06, /* AMRWB_1985 -> AMRWB_1825 */
+ 0x06, /* AMRWB_2305 -> AMRWB_1825 */
+ 0x04, /* AMRWB_2385 */
+ 0x07, /* invalid request -> none */
+ 0x07, /* invalid request -> none */
+ 0x07, /* invalid request -> none */
+ 0x07, /* invalid request -> none */
+ 0x07, /* invalid request -> none */
+ 0x07, /* invalid request -> none */
+ 0x07 /* invalid request -> none */
+};
+
+/* 3 bit to 4 bit AMR-WB CMR remapping table */
+static const Word16 amrwb_4bit_cmr[8] =
+{
+ 0x00, /* AMRWB_660 */
+ 0x01, /* AMRWB_885 */
+ 0x02, /* AMRWB_1265 */
+ 0x04, /* AMRWB_1585 */
+ 0x08, /* AMRWB_2385 */
+ 0x03, /* AMRWB_1425 */
+ 0x05, /* AMRWB_1825 */
+ 0x0f /* invalid */
+};
diff --git a/lib_com/modif_fs.c b/lib_com/modif_fs.c
new file mode 100644
index 0000000000000000000000000000000000000000..505adda57d6a4d83fa145645e85df50c3adc50d3
--- /dev/null
+++ b/lib_com/modif_fs.c
@@ -0,0 +1,858 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include
+#include "wmc_auto.h"
+#include "options.h"
+#include "cnst.h"
+#include "prot.h"
+#include "rom_com.h"
+
+
+/*-------------------------------------------------------------------*
+ * modify_Fs()
+ *
+ * Function for resampling of signals
+ *-------------------------------------------------------------------*/
+
+short modify_Fs( /* o : length of output */
+ const float sigIn[], /* i : signal to decimate */
+ short lg, /* i : length of input + 0 delay signaling */
+ const int fin, /* i : frequency of input */
+ float sigOut[], /* o : decimated signal */
+ const int fout, /* i : frequency of output */
+ float mem[] /* i/o: filter memory */
+ ,int nblp /* i : flag indicating if NB low-pass is applied */
+)
+{
+ short i;
+ short lg_out, fac_num, fac_den, filt_len, frac, mem_len;
+ float num_den;
+ short datastep, fracstep;
+ float *sigIn_ptr;
+ float signal_tab[3*L_FILT_MAX + L_FRAME48k], *signal, *signal_ana; /* 3* as 2* for memory and 1* for future prediction */
+ float A[M+1], r[M+1], epsP[M+1], val;
+ short mem_len_ana;
+ short plus_sample_in;
+ short j;
+ float mu_preemph;
+ float mem_preemph;
+ const Resampling_cfg *cfg_ptr;
+ short flag_low_order = 0;
+ short filt_len_tmp;
+
+ /*-------------------------------------------------------------------*
+ * IIR filters for resampling to/from 8 kHz
+ *-------------------------------------------------------------------*/
+
+ /*-------------------------------------------------------------------*
+ * Find the resampling configuration
+ *-------------------------------------------------------------------*/
+
+ if ( fin == fout )
+ {
+ /* just copy the signal and quit */
+ for (i = 0; i < lg; i++)
+ {
+ sigOut[i] = sigIn[i];
+ }
+
+ return lg;
+ }
+ else
+ {
+ /* find the resampling configuration in the lookup table */
+ for (cfg_ptr = &resampling_cfg_tbl[0]; (cfg_ptr->fin != 0) && !(cfg_ptr->fin == fin && cfg_ptr->fout == fout); cfg_ptr++)
+ {
+ }
+
+
+ /* find config with NB 4kHz low-pass */
+ if (nblp && (fin > 8000) && (fout == 12800))
+ {
+ flag_low_order = 1;
+ for (cfg_ptr++; (cfg_ptr->fin != 0) && !(cfg_ptr->fin == fin && cfg_ptr->fout == fout); cfg_ptr++)
+ {
+ }
+ }
+
+#define WMC_TOOL_SKIP
+ /* Retrieve and/or calculate the resampling parameters */
+ fac_num = cfg_ptr->fac_num;
+ fac_den = (short)((cfg_ptr->fin * fac_num) / cfg_ptr->fout);
+ lg_out = (lg * fac_num) / fac_den;
+ filt_len = cfg_ptr->filt_len;
+
+ mem_len = 2*filt_len;
+ plus_sample_in = 0; /* default, regular delay */
+ frac = 0;
+
+ if ( fin == 8000 && fout == 12800 )
+ {
+ plus_sample_in = 7;
+ frac = 4;
+ }
+
+ signal = signal_tab+2*L_FILT_MAX + L_FRAME48k - mem_len - lg;
+ signal_ana = signal;
+ mem_len_ana = mem_len;
+#undef WMC_TOOL_SKIP
+ }
+
+ /*-------------------------------------------------------------------*
+ * FIR filters for resampling to/from 12.8, 16, 32, 48 kHz
+ *-------------------------------------------------------------------*/
+
+ /* append filter memory */
+ for (i=0; i<2*filt_len; i++)
+ {
+ signal[i] = mem[i];
+ }
+
+ for (i=0; i 0 )
+ {
+
+ autocorr( signal_ana+mem_len_ana+lg-LEN_WIN_SSS, r, 1, LEN_WIN_SSS, wind_sss, 0, 0, 0 );
+
+ mu_preemph = r[1] / r[0];
+ mem_preemph = signal_ana[mem_len_ana+lg-LEN_WIN_SSS - 1];
+ preemph( signal_ana+mem_len_ana+lg-LEN_WIN_SSS, mu_preemph, LEN_WIN_SSS, &mem_preemph );
+
+ /* Autocorrelations */
+ autocorr( signal_ana+mem_len_ana+lg-LEN_WIN_SSS, r, M, LEN_WIN_SSS, wind_sss, 0, 0, 0 );
+
+ lag_wind( r, M, fin, LAGW_STRONG );
+
+ /* Levinson-Durbin */
+ lev_dur( A, r, M, epsP );
+
+ for (i=0; i> 1;
+ }
+
+ for(i=0; ifilter, frac, fac_num, filt_len_tmp );
+
+ frac = frac + fracstep;
+ if ( frac >= fac_num )
+ {
+ frac = frac - fac_num;
+ sigIn_ptr++;
+ }
+
+ sigIn_ptr += datastep;
+ }
+
+ /* rescaling */
+ if ( (fac_num > fac_den) == ((cfg_ptr->flags & RS_INV_FAC) != 0) )
+ {
+ num_den = (float)fac_num / fac_den;
+
+ for( i=0; i 0.25 ) */
+ k3d = fk1 - 1; /* to compurte index in cu with respect to the last sample with - sign (ex 1.25 -> -0.75 ) */
+
+ kk = 0;
+ for(i = 0; i < lg-ct2[cind][11];)
+ {
+ sigOut[j++] = sigIn[i];
+ for(k = 0; k < ct2[cind][10]; k++)
+ {
+ cc[kk][0] = sigIn[i+1]/3;
+ cc[kk][2] =(sigIn[i]+sigIn[i+2])/2-sigIn[i+1];
+ cc[kk][3] = (sigIn[i]+sigIn[i+3]-sigIn[i+1]-sigIn[i+2]-4*cc[kk][2]) / 6;
+ cc[kk][1] = sigIn[i+2]-sigIn[i+1]-cc[kk][3]-cc[kk][2];
+ i++;
+
+ i2 = kk-2;
+ i1 = kk-1;
+ if( i1 < 0 )
+ {
+ i1 += 4;
+ }
+
+ if( i2 < 0 )
+ {
+ i2 += 4;
+ }
+
+ for(k1 = ct2[cind][k]; k1 < fk1; k1 += ct2[cind][8])
+ {
+ k2 = k1 - k2d;
+ k3 = k3d - k1;
+ vv = (float)( cu[k1][2]*cc[i2][3] + cu[k1][1]*cc[i2][2] + cu[k1][0]*cc[i2][1] + cc[i2][0]);
+ vv += (float)( cu[k2][2]*cc[i1][3] + cu[k2][1]*cc[i1][2] + cu[k2][0]*cc[i1][1] + cc[i1][0]);
+ vv += (float)(-cu[k3][2]*cc[kk][3] + cu[k3][1]*cc[kk][2] - cu[k3][0]*cc[kk][1] + cc[kk][0]);
+ sigOut[j++] = vv;
+ }
+
+ kk++;
+ if( kk == 4 )
+ {
+ kk = 0;
+ }
+ }
+ }
+
+ sigOut[j++] = sigIn[i];
+
+ for(k = 0; k < ct2[cind][11]-3; k++)
+ {
+ cc[kk][0] = sigIn[i+1]/3;
+ cc[kk][2] =(sigIn[i]+sigIn[i+2])/2-sigIn[i+1];
+ cc[kk][3] = (sigIn[i]+sigIn[i+3]-sigIn[i+1]-sigIn[i+2]-4*cc[kk][2]) / 6;
+ cc[kk][1] = sigIn[i+2]-sigIn[i+1]-cc[kk][3]-cc[kk][2];
+ i++;
+
+ i2 = kk-2;
+ i1 = kk-1;
+ if( i1 < 0 )
+ {
+ i1 += 4;
+ }
+
+ if( i2 < 0 )
+ {
+ i2 += 4;
+ }
+
+ for(k1 = ct2[cind][k]; k1 < fk1; k1 += ct2[cind][8])
+ {
+ k2 = k1 - k2d;
+ k3 = k3d - k1;
+ vv = (float)( cu[k1][2]*cc[i2][3] + cu[k1][1]*cc[i2][2] + cu[k1][0]*cc[i2][1] + cc[i2][0]);
+ vv += (float)( cu[k2][2]*cc[i1][3] + cu[k2][1]*cc[i1][2] + cu[k2][0]*cc[i1][1] + cc[i1][0]);
+ vv += (float)(-cu[k3][2]*cc[kk][3] + cu[k3][1]*cc[kk][2] - cu[k3][0]*cc[kk][1] + cc[kk][0]);
+ sigOut[j++] = vv;
+ }
+
+ kk++;
+
+ if( kk == 4 )
+ {
+ kk = 0;
+ }
+ }
+
+ kk--;
+ if( kk == -1 )
+ {
+ kk = 3;
+ }
+
+ if( ct2[cind][10] == 1 )
+ {
+ sigOut[j++] = sigIn[i];
+ }
+
+ for(k1 = ct2[cind][k]; k1 < fk1; k1 += ct2[cind][8])
+ {
+ k2 = k1 - k2d;
+ vv = (float)( cu[k2][2]*cc[kk][3] + cu[k2][1]*cc[kk][2] + cu[k2][0]*cc[kk][1] + cc[kk][0]);
+ sigOut[j++] = vv*3;
+ }
+
+ if( ct2[cind][10] < 3 )
+ {
+ sigOut[j++] = sigIn[i+1];
+ }
+
+ for( k1 = ct2[cind][k+1]; k1 < fk1; k1 += ct2[cind][8] )
+ {
+ vv = (float)( cu[k1][2]*cc[kk][3] + cu[k1][1]*cc[kk][2] + cu[k1][0]*cc[kk][1] + cc[kk][0]);
+ sigOut[j++] = vv*3;
+ }
+
+ if( ct2[cind][10] == 1 )
+ {
+ sigOut[j++] = sigIn[i+2];
+ }
+ }
+
+ return lg_out;
+}
+
+/*-------------------------------------------------------------------*
+ * Interpolate_allpass_steep()
+ *
+ * Interpolation by a factor 2
+ *-------------------------------------------------------------------*/
+
+void Interpolate_allpass_steep(
+ const float *in, /* i : input array of size N */
+ float *state, /* i/o: memory */
+ const short N, /* i : number of input samples */
+ float *out /* o : output array of size 2*N */
+)
+{
+ short n, k;
+ float temp[ALLPASSSECTIONS_STEEP - 1];
+
+ /* upper allpass filter chain */
+ for (k = 0; k < N; k++)
+ {
+ temp[0] = state[0] + AP2_STEEP[0] * in[k];
+ state[0] = in[k] - AP2_STEEP[0] * temp[0];
+
+ /* for better performance, unroll this loop */
+ for (n = 1; n < ALLPASSSECTIONS_STEEP - 1; n++)
+ {
+ temp[n] = state[n] + AP2_STEEP[n] * temp[n - 1];
+ state[n] = temp[n - 1] - AP2_STEEP[n] * temp[n];
+ }
+
+ out[2 * k + 1] = state[ALLPASSSECTIONS_STEEP - 1] + AP2_STEEP[ALLPASSSECTIONS_STEEP - 1] * temp[ALLPASSSECTIONS_STEEP - 2];
+ state[ALLPASSSECTIONS_STEEP - 1] = temp[ALLPASSSECTIONS_STEEP - 2] - AP2_STEEP[ALLPASSSECTIONS_STEEP - 1] * out[2 * k + 1];
+ }
+
+ /* lower allpass filter chain */
+ for (k = 0; k < N; k++)
+ {
+ temp[0] = state[ALLPASSSECTIONS_STEEP] + AP1_STEEP[0] * in[k];
+ state[ALLPASSSECTIONS_STEEP] = in[k] - AP1_STEEP[0] * temp[0];
+
+ /* for better performance, unroll this loop */
+ for (n = 1; n < ALLPASSSECTIONS_STEEP - 1; n++)
+ {
+ temp[n] = state[ALLPASSSECTIONS_STEEP + n] + AP1_STEEP[n] * temp[n - 1];
+ state[ALLPASSSECTIONS_STEEP + n] = temp[n - 1] - AP1_STEEP[n] * temp[n];
+ }
+
+ out[2 * k] = state[2 * ALLPASSSECTIONS_STEEP - 1] + AP1_STEEP[ALLPASSSECTIONS_STEEP - 1] * temp[ALLPASSSECTIONS_STEEP - 2];
+ state[2 * ALLPASSSECTIONS_STEEP - 1] = temp[ALLPASSSECTIONS_STEEP - 2] - AP1_STEEP[ALLPASSSECTIONS_STEEP - 1] * out[2 * k];
+ }
+
+ return;
+}
+
+/*-------------------------------------------------------------------*
+ * Decimate_allpass_steep()
+ *
+ * Decimation by a factor 2
+ *-------------------------------------------------------------------*/
+
+void Decimate_allpass_steep (
+ const float *in, /* i : input array of size N */
+ float *state, /* i/o: memory */
+ const short N, /* i : number of input samples */
+ float *out /* o : output array of size N/2 */
+)
+{
+ short n, k;
+ float temp[ALLPASSSECTIONS_STEEP];
+
+ /* upper allpass filter chain */
+ for (k = 0; k < N / 2; k++)
+ {
+ temp[0] = state[0] + AP1_STEEP[0] * in[2 * k];
+ state[0] = in[2 * k] - AP1_STEEP[0] * temp[0];
+
+ /* for better performance, unroll this loop */
+ for (n = 1; n < ALLPASSSECTIONS_STEEP - 1; n++)
+ {
+ temp[n] = state[n] + AP1_STEEP[n] * temp[n - 1];
+ if( fabs(temp[n]) < 1e-12 )
+ {
+ temp[n] = sign(temp[n])*1e-12;
+ }
+ state[n] = temp[n - 1] - AP1_STEEP[n] * temp[n];
+ }
+
+ out[k] = state[ALLPASSSECTIONS_STEEP - 1] + AP1_STEEP[ALLPASSSECTIONS_STEEP - 1] * temp[ALLPASSSECTIONS_STEEP - 2];
+ state[ALLPASSSECTIONS_STEEP - 1] = temp[ALLPASSSECTIONS_STEEP - 2] - AP1_STEEP[ALLPASSSECTIONS_STEEP - 1] * out[k];
+ }
+
+ /* lower allpass filter chain */
+ temp[0] = state[ALLPASSSECTIONS_STEEP] + AP2_STEEP[0] * state[2 * ALLPASSSECTIONS_STEEP];
+ state[ALLPASSSECTIONS_STEEP] = state[2 * ALLPASSSECTIONS_STEEP] - AP2_STEEP[0] * temp[0];
+
+ /* for better performance, unroll this loop */
+ for (n = 1; n < ALLPASSSECTIONS_STEEP - 1; n++)
+ {
+ temp[n] = state[ALLPASSSECTIONS_STEEP + n] + AP2_STEEP[n] * temp[n - 1];
+ if( fabs(temp[n]) < 1e-12 )
+ {
+ temp[n] = sign(temp[n])*1e-12;
+ }
+ state[ALLPASSSECTIONS_STEEP + n] = temp[n - 1] - AP2_STEEP[n] * temp[n];
+ }
+
+ temp[ALLPASSSECTIONS_STEEP - 1] = state[2 * ALLPASSSECTIONS_STEEP - 1] + AP2_STEEP[ALLPASSSECTIONS_STEEP - 1] *
+ temp[ALLPASSSECTIONS_STEEP -2];
+
+ state[2 * ALLPASSSECTIONS_STEEP - 1] = temp[ALLPASSSECTIONS_STEEP - 2] - AP2_STEEP[ALLPASSSECTIONS_STEEP - 1] *
+ temp[ALLPASSSECTIONS_STEEP - 1];
+ out[0] = (float)((out[0] + temp[ALLPASSSECTIONS_STEEP - 1]) * 0.5);
+
+ for (k = 1; k < N / 2; k++)
+ {
+ temp[0] = state[ALLPASSSECTIONS_STEEP] + AP2_STEEP[0] * in[2 * k - 1];
+ state[ALLPASSSECTIONS_STEEP] = in[2 * k - 1] - AP2_STEEP[0] * temp[0];
+
+ /* for better performance, unroll this loop */
+ for (n = 1; n < ALLPASSSECTIONS_STEEP - 1; n++)
+ {
+ temp[n] = state[ALLPASSSECTIONS_STEEP + n] + AP2_STEEP[n] * temp[n - 1];
+ if( fabs(temp[n]) < 1e-12 )
+ {
+ temp[n] = sign(temp[n])*1e-12;
+ }
+ state[ALLPASSSECTIONS_STEEP + n] = temp[n - 1] - AP2_STEEP[n] * temp[n];
+ }
+
+ temp[ALLPASSSECTIONS_STEEP - 1] = state[2 * ALLPASSSECTIONS_STEEP - 1] + AP2_STEEP[ALLPASSSECTIONS_STEEP - 1] *
+ temp[ALLPASSSECTIONS_STEEP - 2];
+ state[2 * ALLPASSSECTIONS_STEEP - 1] = temp[ALLPASSSECTIONS_STEEP - 2] - AP2_STEEP[ALLPASSSECTIONS_STEEP - 1] *
+ temp[ALLPASSSECTIONS_STEEP - 1];
+ out[k] = (float)((out[k] + temp[ALLPASSSECTIONS_STEEP - 1]) * 0.5);
+ }
+
+ /* z^(-1) */
+ state[2 * ALLPASSSECTIONS_STEEP] = in[N - 1];
+
+ return;
+}
+
+/*-------------------------------------------------------------------*
+ * interpolate_3_over_2_allpass()
+ *
+ * Interpolate 3/2 using allpass iir polyphase filter. Delay 4 samples @48k
+ *-------------------------------------------------------------------*/
+
+void interpolate_3_over_2_allpass(
+ const float *input, /* i : input signal */
+ const short len, /* i : number of input samples */
+ float *out, /* o : output signal */
+ float *mem, /* i/o: memory */
+ const float *filt_coeff /* i : filter coefficients */
+)
+{
+ short i, loop_len;
+ float Vu[2], Vm[2], Vl[2]; /* Outputs of three cascaded allpass stages (upper, middle, and lower) */
+ float out1_buff[L_FRAME32k*3];
+ float * out1;
+ float mem_temp;
+
+ out1 = out1_buff;
+
+ for (i = 0; i < len; i++ )
+ {
+ /* Upper branch */
+ Vu[0] = mem[0] + filt_coeff[0] * ( input[i] - mem[1] );
+ Vu[1] = mem[1] + filt_coeff[1] * ( Vu[0] - mem[2] );
+ mem[3] = mem[2] + filt_coeff[2] * ( Vu[1] - mem[3] );
+
+ mem[1] = Vu[0];
+ mem[2] = Vu[1];
+ *out1++ = mem[3];
+
+ /* Middle branch */
+ Vm[0] = mem[0] + filt_coeff[3] * (input[i]-mem[4]);
+ Vm[1] = mem[4] + filt_coeff[4] * (Vm[0]-mem[5]);
+ mem[6] = mem[5] + filt_coeff[5] * (Vm[1]-mem[6]);
+
+ mem[4] = Vm[0];
+ mem[5] = Vm[1];
+ *out1++ = mem[6];
+
+ /* Lower branch */
+ Vl[0] = mem[0] + filt_coeff[6] * (input[i]-mem[7]);
+ Vl[1] = mem[7] + filt_coeff[7] * (Vl[0]-mem[8]);
+ mem[9] = mem[8] + filt_coeff[8] * (Vl[1]-mem[9]);
+
+ mem[0] = input[i];
+ mem[7] = Vl[0];
+ mem[8] = Vl[1];
+ *out1++ = mem[9];
+ }
+
+ loop_len = len*3/2;
+
+ /*decimate by 2 and LPF*/
+ for(i = 0; i < loop_len; i++)
+ {
+ mem_temp = out1_buff[2*i];
+ out[i] = (((0.0473147f)*(mem_temp+mem[10]))+((-0.151521f)*(mem[11]+mem[14])));
+ out[i] = (out[i]+((0.614152f)*(mem[12]+mem[13])));
+ mem[10] = mem[11];
+ mem[11] = mem[12];
+ mem[12] = mem[13];
+ mem[13] = mem[14];
+ mem[14] = mem_temp;
+ }
+ return;
+}
+
+/*-------------------------------------------------------------------*
+* decimate_2_over_3_allpass()
+*
+* Decimate 2/3 using allpass iir polyphase filter.
+*-------------------------------------------------------------------*/
+
+void decimate_2_over_3_allpass(
+ const float *input, /* i : input signal */
+ const short len, /* i : number of input samples */
+ float *out, /* o : output signal */
+ float *mem, /* i/o: memory */
+ const float *filt_coeff, /* i : filter coefficients */
+ const float *lp_num,
+ const float *lp_den,
+ float *lp_mem
+)
+{
+ short i, loop_len;
+ float Vu[2], Vm[2], Vl[2]; /* Outputs of three cascaded allpass stages (upper, middle, and lower) */
+ float * out1;
+ float *in;
+ float out1_buff[L_FRAME48k*2];
+ float tmp;
+
+ /* Combine the 2nd order iir lpf with the decimation by 2 to improve the efficiency*/
+ out1 = out1_buff;
+
+ *out1++ = lp_num[0] * ( input[0] + lp_mem[0] ) - lp_den[2] * lp_mem[2];
+ *out1++ = lp_num[1] * input[0] - lp_den[2] * lp_mem[1];
+
+ for (i=1; i < len; i++)
+ {
+ tmp = lp_num[0] * ( input[i] + input[i-1] ) - lp_den[2] * out1[-2];
+ *out1++ = tmp;
+ tmp = lp_num[1] * input[i] - lp_den[2] * out1[-2];
+ *out1++ = tmp;
+ }
+ lp_mem[0] = input[len-1];
+ lp_mem[1] = out1[-1];
+ lp_mem[2] = out1[-2];
+
+ /* do the all pass polyphase filter with pi/3 cutoff */
+ out1 = out;
+ in = out1_buff;
+ loop_len = (short) len*2/3;
+
+ for (i = 0; i < loop_len; i++ )
+ {
+ /* Lower branch */
+ Vl[0] = mem[8] + filt_coeff[6] * (*in - mem[9]);
+ Vl[1] = mem[9] + filt_coeff[7] * (Vl[0] - mem[10]);
+ mem[11] = mem[10] + filt_coeff[8] * (Vl[1] - mem[11]);
+
+ mem[8] = *in++;
+ mem[9] = Vl[0];
+ mem[10] = Vl[1];
+ *out1 = mem[11];
+
+ /* Middle branch */
+ Vm[0] = mem[4] + filt_coeff[3] * (*in - mem[5]);
+ Vm[1] = mem[5] + filt_coeff[4] * (Vm[0]-mem[6]);
+ mem[7] = mem[6] + filt_coeff[5] * (Vm[1]-mem[7]);
+
+ mem[4] = *in++;
+ mem[5] = Vm[0];
+ mem[6] = Vm[1];
+ *out1 += mem[7];
+
+ /* Upper branch */
+ Vu[0] = mem[0] + filt_coeff[0] * ( *in - mem[1] );
+ Vu[1] = mem[1] + filt_coeff[1] * ( Vu[0] - mem[2] );
+ mem[3] = mem[2] + filt_coeff[2] * ( Vu[1] - mem[3] );
+
+ mem[0] = *in++;
+ mem[1] = Vu[0];
+ mem[2] = Vu[1];
+ *out1++ += mem[3];
+ }
+
+ return;
+}
+
+/*-------------------------------------------------------------------*
+ * interpolate_3_over_1_allpass()
+ *
+ * Interpolate 3/1 using allpass iir polyphase filter. Delay 4 samples @48k
+ *-------------------------------------------------------------------*/
+
+void interpolate_3_over_1_allpass(
+ const float *input, /* i : input signal */
+ const short len, /* i : number of input samples */
+ float *out, /* o : output signal */
+ float *mem, /* i/o: memory */
+ const float *filt_coeff /* i : filter coefficients */
+)
+{
+ short i;
+ float Vu[2], Vm[2], Vl[2]; /* Outputs of three cascaded allpass stages (upper, middle, and lower) */
+ float * out1;
+ float mem_temp;
+ out1 = &out[0];
+
+ for (i = 0; i < len; i++ )
+ {
+ /* Upper branch */
+ Vu[0] = mem[0] + filt_coeff[0] * ( input[i] - mem[1] );
+ Vu[1] = mem[1] + filt_coeff[1] * ( Vu[0] - mem[2] );
+ mem[3] = mem[2] + filt_coeff[2] * ( Vu[1] - mem[3] );
+
+ mem[1] = Vu[0];
+ mem[2] = Vu[1];
+ *out1++ = mem[3];
+
+ /* Middle branch */
+ Vm[0] = mem[0] + filt_coeff[3] * (input[i]-mem[4]);
+ Vm[1] = mem[4] + filt_coeff[4] * (Vm[0]-mem[5]);
+ mem[6] = mem[5] + filt_coeff[5] * (Vm[1]-mem[6]);
+
+ mem[4] = Vm[0];
+ mem[5] = Vm[1];
+ *out1++ = mem[6];
+
+ /* Lower branch */
+ Vl[0] = mem[0] + filt_coeff[6] * (input[i]-mem[7]);
+ Vl[1] = mem[7] + filt_coeff[7] * (Vl[0]-mem[8]);
+ mem[9] = mem[8] + filt_coeff[8] * (Vl[1]-mem[9]);
+
+ mem[0] = input[i];
+ mem[7] = Vl[0];
+ mem[8] = Vl[1];
+ *out1++ = mem[9];
+ }
+
+ /*LPF*/
+ for(i = 0; i < len*3; i++)
+ {
+ mem_temp = out[i];
+ out[i] = (((0.572769f)*(mem[12]+mem[11]))-((0.074005f)*(mem_temp+mem[10])));
+ mem[10] = mem[11];
+ mem[11] = mem[12];
+ mem[12] = mem_temp;
+ }
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------*
+ * retro_interp4_5()
+ *
+ *
+ *-------------------------------------------------------------------*/
+
+void retro_interp4_5(
+ const float *syn,
+ float *pst_old_syn
+)
+{
+ float *pf5, *pf4;
+ short c;
+
+ /* resample st->pst_old_syn in a reverse way to preserve time-alignment */
+ pf4 = (float*) &pst_old_syn[58];
+ pf5 = (float*) pst_old_syn;
+ for (c=0; c<57; c++)
+ {
+ *pf5++ = pf4[0];
+ *pf5++ = 0.2f * pf4[0] + 0.8f * pf4[1];
+ *pf5++ = 0.4f * pf4[1] + 0.6f * pf4[2];
+ *pf5++ = 0.6f * pf4[2] + 0.4f * pf4[3];
+ *pf5++ = 0.8f * pf4[3] + 0.2f * pf4[4];
+ pf4+=4;
+ }
+ *pf5++ = pf4[0];
+ *pf5++ = 0.2f * pf4[0] + 0.8f * pf4[1];
+ *pf5++ = 0.4f * pf4[1] + 0.6f * pf4[2];
+ *pf5++ = 0.6f * pf4[2] + 0.4f * pf4[3];
+ *pf5++ = 0.8f * pf4[3] + 0.2f * syn[0];
+ /* all samples processed: NBPSF_PIT_MAX = 290 = (58*5) */
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------*
+ * retro_interp5_4()
+ *
+ *
+ *-------------------------------------------------------------------*/
+
+void retro_interp5_4( float *pst_old_syn )
+{
+ float *pf5, *pf4;
+ short c;
+
+ /* resample st->pst_old_syn in a reverse way to preserve time-alignment */
+ pf4 = (float*) &pst_old_syn[NBPSF_PIT_MAX-1];
+ pf5 = pf4;
+ for (c=0; c<58; c++)
+ {
+ *pf4-- = 0.75f * pf5[0] + 0.25f * pf5[-1];
+ *pf4-- = 0.50f * pf5[-1] + 0.50f * pf5[-2];
+ *pf4-- = 0.25f * pf5[-2] + 0.75f * pf5[-3];
+ *pf4-- = pf5[-4];
+ pf5-=5;
+ }
+ /* all samples processed: NBPSF_PIT_MAX = 290 = (58*5) */
+
+ return;
+}
diff --git a/lib_com/move.h b/lib_com/move.h
new file mode 100644
index 0000000000000000000000000000000000000000..09219dd1cbc34fe729e4f08887869c52afc58c09
--- /dev/null
+++ b/lib_com/move.h
@@ -0,0 +1,86 @@
+/******************************************************************************************************
+
+ (C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
+ Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
+ Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
+ Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
+ contributors to this repository. All Rights Reserved.
+
+ This software is protected by copyright law and by international treaties.
+ The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
+ Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
+ Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
+ Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
+ contributors to this repository retain full ownership rights in their respective contributions in
+ the software. This notice grants no license of any kind, including but not limited to patent
+ license, nor is any license granted by implication, estoppel or otherwise.
+
+ Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
+ contributions.
+
+ This software is provided "AS IS", without any express or implied warranties. The software is in the
+ development stage. It is intended exclusively for experts who have experience with such software and
+ solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
+ and fitness for a particular purpose are hereby disclaimed and excluded.
+
+ Any dispute, controversy or claim arising under or in relation to providing this software shall be
+ submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
+ accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
+ the United Nations Convention on Contracts on the International Sales of Goods.
+
+*******************************************************************************************************/
+
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#ifndef _MOVE_H
+#define _MOVE_H
+
+/* BASOP -> FLC brigde: data move counting */
+
+static __inline void move16( void )
+{
+#ifdef WMOPS
+ multiCounter[currCounter].move16++;
+#endif
+}
+
+static __inline void move32( void )
+{
+#ifdef WMOPS
+ multiCounter[currCounter].move32++;
+#endif
+}
+
+static __inline void test( void )
+{
+#ifdef WMOPS
+ multiCounter[currCounter].Test++;
+#endif
+}
+
+static __inline void logic16( void )
+{
+#ifdef WMOPS
+ multiCounter[currCounter].Logic16++;
+#endif
+}
+
+static __inline void logic32( void )
+{
+#ifdef WMOPS
+ multiCounter[currCounter].Logic32++;
+#endif
+}
+
+/*-------- legacy ----------*/
+#define data_move() move16()
+#define L_data_move() move32()
+#define data_move_external() move16()
+#define compare_zero() test()
+/*-------- end legacy ----------*/
+
+#define cast16 move16
+
+#endif /* _MOVE_H */
diff --git a/lib_com/mslvq_com.c b/lib_com/mslvq_com.c
new file mode 100644
index 0000000000000000000000000000000000000000..f381e64a8050bd9923e530048bb456c5bf4dcc99
--- /dev/null
+++ b/lib_com/mslvq_com.c
@@ -0,0 +1,734 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
+ ====================================================================================*/
+
+#include