diff --git a/Workspace_msvc/lib_com.vcxproj b/Workspace_msvc/lib_com.vcxproj
index 64dd04a58f7d5eb844993088eeb9ec3069ba36a0..ee98364c9ce986ca35c66ab6d2e4d442613e8c3d 100644
--- a/Workspace_msvc/lib_com.vcxproj
+++ b/Workspace_msvc/lib_com.vcxproj
@@ -139,6 +139,7 @@
+
@@ -298,6 +299,7 @@
+
diff --git a/Workspace_msvc/lib_com.vcxproj.filters b/Workspace_msvc/lib_com.vcxproj.filters
index 495917759336d37244a1eddfea119e1f417b0bf4..1f2cfe90a292b663dfdb147d1d67f1db990b8c49 100644
--- a/Workspace_msvc/lib_com.vcxproj.filters
+++ b/Workspace_msvc/lib_com.vcxproj.filters
@@ -73,9 +73,6 @@
common_all_c
-
- common_all_c
-
common_all_c
@@ -322,9 +319,6 @@
common_all_c
-
- common_all_c
-
common_all_c
@@ -518,8 +512,12 @@
common_all_c
-
-
+
+ common_all_c
+
+
+ common_all_c
+
common_all_c
@@ -581,6 +579,18 @@
common_all_c
+
+ common_all_c
+
+
+ common_all_c
+
+
+ common_all_c
+
+
+ common_all_c
+
diff --git a/Workspace_msvc/lib_enc.vcxproj b/Workspace_msvc/lib_enc.vcxproj
index e3deeb989ea3f425376861a0c831b1edaeac7c62..e033d4a0e14d262bea06a66626c4d5a48d6987a2 100644
--- a/Workspace_msvc/lib_enc.vcxproj
+++ b/Workspace_msvc/lib_enc.vcxproj
@@ -140,6 +140,9 @@
+
+
+
@@ -278,11 +281,13 @@
+
+
diff --git a/Workspace_msvc/lib_enc.vcxproj.filters b/Workspace_msvc/lib_enc.vcxproj.filters
index e74f441c4c7902d05da6850e2642eebf15c1208e..cba4641b38fb6d5b1ed8c58cc4f6d98687ec0daa 100644
--- a/Workspace_msvc/lib_enc.vcxproj.filters
+++ b/Workspace_msvc/lib_enc.vcxproj.filters
@@ -596,6 +596,21 @@
enc_ivas_c
+
+ enc_all_c
+
+
+ enc_evs_c
+
+
+ enc_evs_c
+
+
+ enc_evs_c
+
+
+ enc_all_c
+
diff --git a/lib_com/cnst.h b/lib_com/cnst.h
index 104c639b3e383478ae80f9704941a3c4950ee9d6..26238754a0f94dfa6cb8c39c208646f8a8e72275 100644
--- a/lib_com/cnst.h
+++ b/lib_com/cnst.h
@@ -201,6 +201,8 @@ enum{
#define SBA_AGC_FORCE_DISABLE 0
#define SBA_AGC_DEFAULT -1
+extern const Word16 Idx2Freq_Tbl[];
+
/*----------------------------------------------------------------------------------*
* Layers
*----------------------------------------------------------------------------------*/
@@ -2919,5 +2921,8 @@ extern const Word16 Idx2Freq_Tbl[];
#define L_PAST_MAX_12k8 144 /* maximum encoder past samples at 12k8Hz */
#define L_DIV 256 /* 20ms frame size (ACELP or short TCX frame) */
+
+//tbs_vase.c
+#define PRED_GAIN_E 8
/* clang-format on */
#endif /* CNST_H */
diff --git a/lib_com/codec_tcx_common.c b/lib_com/codec_tcx_common.c
index c919067a3cb5c2b98b6f21dc8ccdffe7b2e02d98..e04cebb9af451c54328d9368c6809d31f63d0ccc 100644
--- a/lib_com/codec_tcx_common.c
+++ b/lib_com/codec_tcx_common.c
@@ -1,206 +1,299 @@
-/******************************************************************************************************
-
- (C) 2022-2023 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
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
====================================================================================*/
#include
+#include
#include "options.h"
-#include
-#include "prot.h"
-#include "wmc_auto.h"
-
-/*-------------------------------------------------------------------*
- * tcxGetNoiseFillingTilt()
- *
- *
- *-------------------------------------------------------------------*/
-
-int16_t tcxGetNoiseFillingTilt(
- const float A[],
- const int16_t L_frame,
- const int16_t mode,
- float *noiseTiltFactor )
+#include "prot_fx2.h"
+#include "prot_fx1.h"
+#include "basop_util.h"
+#include "rom_basop_util.h"
+
+#define inv_int InvIntTable
+
+Word16 tcxGetNoiseFillingTilt(
+ const Word16 A[],
+ const Word16 lpcorder,
+ const Word16 L_frame,
+ const Word16 mode,
+ Word16 *noiseTiltFactor
+)
{
- int16_t firstLine;
-
- if ( mode )
- {
- firstLine = L_frame / 6;
- *noiseTiltFactor = 0.5625f;
- }
- else
- {
- firstLine = L_frame / 8;
- *noiseTiltFactor = get_gain_flt( A + 1, A, M, NULL );
- *noiseTiltFactor = min( 1.0f, ( *noiseTiltFactor ) + 0.09375f );
- }
-
- return firstLine;
+ Word16 firstLine;
+ Word32 tmp;
+ Word16 As[M + 1];
+
+
+ IF(mode != 0)
+ {
+ firstLine = idiv1616U(L_frame, 6);
+ *noiseTiltFactor = 18432/*0.5625f Q15*/;
+ move16();
+ }
+ ELSE
+ {
+ firstLine = shr(L_frame, 3);
+
+ Copy_Scale_sig(A, As, lpcorder + 1, sub(norm_s(A[0]),2));
+ tmp = get_gain(As + 1, As, lpcorder);
+ BASOP_SATURATE_WARNING_OFF_EVS;
+ *noiseTiltFactor = add(round_fx(L_shl(tmp, 15)), 3072/*0.09375f Q15*/);
+ move16();
+ BASOP_SATURATE_WARNING_ON_EVS;
+ }
+
+
+ return firstLine;
}
-/*-------------------------------------------------------------------*
- * tcxFormantEnhancement()
- *
- *
- *-------------------------------------------------------------------*/
void tcxFormantEnhancement(
- float xn_buf[],
- const float *gainlpc,
- float spectrum[],
- const int16_t L_frame )
+ Word16 xn_buf[],
+ const Word16 gainlpc[],
+ const Word16 gainlpc_e[],
+ Word32 spectrum[],
+ Word16 *spectrum_e,
+ const Word16 L_frame,
+ const Word16 L_frameTCX
+)
{
- int16_t k, 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 = hTcxCfg->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;
-}
+ Word16 i, j, k, l, n;
+ Word16 fac, fac0, fac1, fac_e, d, tmp;
+ Word16 xn_buf_e, xn_one, m, e;
+#ifdef BASOP_NOGLOB_DECLARE_LOCAL
+ Flag Overflow = 0;
+#endif
+
+ k = shr(L_frame, 6); /* FDNS_NPTS = 64 */
+ l = 0;
+ move16();
+
+ /* get exponent */
+ xn_buf_e = 0;
+ move16();
+ FOR(i = 0; i < FDNS_NPTS; i++)
+ {
+ xn_buf_e = s_max(xn_buf_e, gainlpc_e[i]);
+ }
+ xn_buf_e = shr(add(xn_buf_e, 1), 1); /* max exponent after sqrt */
+ xn_one = shr(0x4000, sub(xn_buf_e, 1)); /* 1.0 scaled to xn_buf_e */
+
+ /* Formant enhancement via square root of the LPC gains */
+ e = gainlpc_e[0];
+ move16();
+ m = Sqrt16(gainlpc[0], &e);
+ xn_buf[0] = shl(m, sub(e, xn_buf_e));
+ move16();
+
+ e = gainlpc_e[1];
+ move16();
+ m = Sqrt16(gainlpc[1], &e);
+ xn_buf[1] = shl(m, sub(e, xn_buf_e));
+ move16();
+
+ fac0 = s_min(xn_buf[0], xn_buf[1]);
+ fac_e = xn_buf_e;
+ move16();
+ fac0 = Inv16(fac0, &fac_e);
+
+ FOR(i = 1; i < FDNS_NPTS - 1; i++)
+ {
+ e = gainlpc_e[i + 1];
+ move16();
+ m = Sqrt16(gainlpc[i + 1], &e);
+ xn_buf[i + 1] = shl(m, sub(e, xn_buf_e));
+ move16();
+
+ test();
+ IF((LE_16(xn_buf[i - 1], xn_buf[i])) && (LE_16(xn_buf[i + 1], xn_buf[i])))
+ {
+ m = s_max(xn_buf[i - 1], xn_buf[i + 1]);
+ e = xn_buf_e;
+ move16();
+ m = Inv16(m, &e);
+
+ fac1 = m;
+ move16();
+ tmp = sub(e, fac_e);
+
+ if (tmp > 0) fac0 = shr(fac0, tmp);
+ if (tmp < 0) fac1 = shl(fac1, tmp);
+
+ if (tmp > 0)
+ {
+ fac_e = e;
+ move16();
+ }
+
+ d = sub(fac1, fac0);
+ n = sub(i, l);
+ assert(n <= 64);
+
+ xn_buf[l] = xn_one;
+ move16();
+ FOR(j = 1; j < n; j++)
+ {
+ fac = add(fac0, mult(d, extract_l(L_mult0(j, inv_int[n]))));
+ BASOP_SATURATE_WARNING_OFF_EVS;
+#ifdef BASOP_NOGLOB
+ xn_buf[l + j] = s_min(xn_one, shl_o(mult(xn_buf[l + j], fac), fac_e, &Overflow));
+#else
+ xn_buf[l + j] = s_min(xn_one, shl(mult(xn_buf[l + j], fac), fac_e));
+#endif
+ move16();
+ BASOP_SATURATE_WARNING_ON_EVS;
+ }
+
+ l = i;
+ move16();
+
+ fac0 = m;
+ move16();
+ fac_e = e;
+ move16();
+ }
+ }
+ /* i = FDNS_NPTS - 1; Completing changes to gains */
+ m = s_min(xn_buf[i - 1], xn_buf[i]);
+ e = xn_buf_e;
+ move16();
+ m = Inv16(m, &e);
+
+ fac1 = m;
+ move16();
+ tmp = sub(e, fac_e);
+
+ if (tmp > 0) fac0 = shr(fac0, tmp);
+ if (tmp < 0) fac1 = shl(fac1, tmp);
+
+ if (tmp > 0)
+ {
+ fac_e = e;
+ move16();
+ }
+
+ d = sub(fac1, fac0);
+ n = sub(i, l);
+ assert(n <= 64);
+
+ xn_buf[l] = xn_one;
+ move16();
+ FOR(j = 1; j < n; j++)
+ {
+ fac = add(fac0, mult(d, extract_l(L_mult0(j, inv_int[n]))));
+ BASOP_SATURATE_WARNING_OFF_EVS;
+ xn_buf[l + j] = s_min(xn_one, shl(mult(xn_buf[l + j], fac), fac_e));
+ move16();
+ BASOP_SATURATE_WARNING_ON_EVS;
+ }
+
+ xn_buf[i] = xn_one;
+ move16();
+
+ /* Application of changed gains onto decoded MDCT lines */
+ FOR(i = 0; i < L_frame; i += k)
+ {
+ FOR(l = 0; l < k; l++)
+ {
+ *spectrum = Mpy_32_16_1(*spectrum, *xn_buf);
+ move32();
+ spectrum++;
+ }
+ xn_buf++;
+ }
+
+ tmp = sub(L_frameTCX, L_frame);
+ FOR(i = 0; i < tmp; i++)
+ {
+ spectrum[i] = L_shr(spectrum[i], xn_buf_e);
+ move32();
+ }
+ *spectrum_e = add(*spectrum_e, xn_buf_e);
+ move16();
-/*-------------------------------------------------------------------*
- * tcxInvertWindowGrouping()
- *
- *
- *-------------------------------------------------------------------*/
+}
void tcxInvertWindowGrouping(
- TCX_CONFIG_HANDLE hTcxCfg,
- float xn_buf[],
- float spectrum[],
- const int16_t L_frame,
- const int16_t fUseTns,
- const int16_t last_core,
- const int16_t index,
- const int16_t frame_cnt,
- const int16_t bfi )
+ TCX_CONFIG_HANDLE hTcxCfg, /* i : configuration of TCX */
+ Word32 xn_buf[],
+ Word32 spectrum[],
+ const Word16 L_frame,
+ const Word8 fUseTns,
+ const Word16 last_core,
+ const Word16 index,
+ const Word16 frame_cnt,
+ const Word16 bfi
+)
{
- int16_t i, w, t_integer;
- int16_t L_win, L_spec;
-
- if ( frame_cnt && !bfi && last_core != ACELP_CORE )
- {
- /* fix sub-window overlap */
- hTcxCfg->tcx_last_overlap_mode = hTcxCfg->tcx_curr_overlap_mode;
- }
-
- if ( ( ( !bfi ) && ( ( hTcxCfg->tcx_last_overlap_mode != FULL_OVERLAP ) ||
- ( ( hTcxCfg->tcx_curr_overlap_mode == FULL_OVERLAP ) && ( frame_cnt == 0 ) && ( index == 0 ) ) ) ) ||
- ( ( bfi ) && ( ( hTcxCfg->tcx_last_overlap_mode != FULL_OVERLAP ) &&
- !( hTcxCfg->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 ( hTcxCfg->fIsTNSAllowed && !bfi && fUseTns )
- {
- L_win = L_frame >> 1;
- L_spec = hTcxCfg->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;
+ Word16 i, L_win, L_spec;
+ Word32 *p;
+
+
+ L_win = shr(L_frame, 1);
+ L_spec = hTcxCfg->tnsConfig[0][0].iFilterBorders[0];
+ move16();
+
+ test();
+ test();
+ if ((frame_cnt != 0) && (bfi == 0) && NE_16(last_core, ACELP_CORE)) /* fix sub-window overlap */
+ {
+ hTcxCfg->tcx_last_overlap_mode = hTcxCfg->tcx_curr_overlap_mode;
+ move16();
+ }
+ test(); test(); test(); test(); test(); test(); test();
+ IF(((bfi == 0) && ((hTcxCfg->tcx_last_overlap_mode != FULL_OVERLAP) ||
+ ((hTcxCfg->tcx_curr_overlap_mode == FULL_OVERLAP) && (frame_cnt == 0) && (index == 0))))
+ ||
+ ((bfi != 0) && ((hTcxCfg->tcx_last_overlap_mode != FULL_OVERLAP) &&
+ !(hTcxCfg->tcx_curr_overlap_mode == FULL_OVERLAP))))
+ {
+ /* ungroup sub-windows: deinterleave MDCT bins into separate windows */
+ p = xn_buf;
+ FOR(i = 1; i < L_win; i += 2)
+ {
+ *p++ = spectrum[i];
+ move32();
+ }
+
+ p = spectrum;
+ FOR(i = 0; i < L_frame; i += 2)
+ {
+ *p++ = spectrum[i];
+ move32();
+ }
+
+ p = spectrum + L_frame - 1;
+ FOR(i = sub(L_frame, 1); i > L_win; i -= 2)
+ {
+ *p-- = spectrum[i];
+ move32();
+ }
+ Copy32(xn_buf, spectrum + L_win, shr(L_win, 1));
+
+ test();
+ test();
+ IF((hTcxCfg->fIsTNSAllowed != 0) && (bfi == 0) && (fUseTns != 0))
+ {
+ /* rearrange LF sub-window lines prior to TNS synthesis filtering */
+ IF(LT_16(L_spec, L_frame))
+ {
+ Copy32(spectrum + 8, spectrum + 16, sub(shr(L_spec, 1), 8));
+ Copy32(spectrum + L_frame / 2, spectrum + 8, 8);
+ Copy32(spectrum + L_frame / 2 + 8, spectrum + L_spec / 2 + 8, sub(shr(L_spec, 1), 8));
+ }
+ ELSE
+ {
+ Copy32(spectrum + L_win, xn_buf, 8);
+ Copy32(spectrum + 8, spectrum + 16, sub(L_win, 8));
+ Copy32(xn_buf, spectrum + 8, 8);
+ }
+ }
+ }
+
}
+#ifdef IVAS_CODE_TCX_COM
/*-------------------------------------------------------------------*
* tcx5SpectrumInterleaving()
@@ -209,24 +302,24 @@ void tcxInvertWindowGrouping(
*-------------------------------------------------------------------*/
void tcx5SpectrumInterleaving(
- const int16_t tcx5Size,
- float *spectrum )
+ const int16_t tcx5Size,
+ float* spectrum)
{
- int16_t i;
- float interleaveBuf[N_TCX10_MAX];
+ int16_t i;
+ float interleaveBuf[N_TCX10_MAX];
- set_f( interleaveBuf, 0.0f, N_TCX10_MAX );
+ set_f(interleaveBuf, 0.0f, N_TCX10_MAX);
- /* group sub-windows: interleave bins according to their frequencies */
- for ( i = 0; i < tcx5Size; i++ )
- {
- interleaveBuf[2 * i] = spectrum[i];
- interleaveBuf[2 * i + 1] = spectrum[tcx5Size + i];
- }
+ /* group sub-windows: interleave bins according to their frequencies */
+ for (i = 0; i < tcx5Size; i++)
+ {
+ interleaveBuf[2 * i] = spectrum[i];
+ interleaveBuf[2 * i + 1] = spectrum[tcx5Size + i];
+ }
- mvr2r( interleaveBuf, spectrum, 2 * tcx5Size );
+ mvr2r(interleaveBuf, spectrum, 2 * tcx5Size);
- return;
+ return;
}
@@ -237,24 +330,24 @@ void tcx5SpectrumInterleaving(
*-------------------------------------------------------------------*/
void tcx5SpectrumDeinterleaving(
- const int16_t tcx5Size,
- float *spectrum )
+ const int16_t tcx5Size,
+ float* spectrum)
{
- int16_t i;
- float interleaveBuf[N_TCX10_MAX];
+ int16_t i;
+ float interleaveBuf[N_TCX10_MAX];
- set_f( interleaveBuf, 0.0f, N_TCX10_MAX );
+ set_f(interleaveBuf, 0.0f, N_TCX10_MAX);
- /* ungroup sub-windows: interleave bins according to their frequencies */
- for ( i = 0; i < tcx5Size; i++ )
- {
- interleaveBuf[i] = spectrum[2 * i];
- interleaveBuf[tcx5Size + i] = spectrum[2 * i + 1];
- }
+ /* ungroup sub-windows: interleave bins according to their frequencies */
+ for (i = 0; i < tcx5Size; i++)
+ {
+ interleaveBuf[i] = spectrum[2 * i];
+ interleaveBuf[tcx5Size + i] = spectrum[2 * i + 1];
+ }
- mvr2r( interleaveBuf, spectrum, 2 * tcx5Size );
+ mvr2r(interleaveBuf, spectrum, 2 * tcx5Size);
- return;
+ return;
}
@@ -265,26 +358,26 @@ void tcx5SpectrumDeinterleaving(
*-------------------------------------------------------------------*/
void tcx5TnsGrouping(
- const int16_t L_frame, /* i : frame length (TCX5) */
- const int16_t L_spec, /* i : coded spec length (TCX5, derived from filter borders*/
- float *spectrum )
+ const int16_t L_frame, /* i : frame length (TCX5) */
+ const int16_t L_spec, /* i : coded spec length (TCX5, derived from filter borders*/
+ float* spectrum)
{
- /* rearrange LF sub-window lines prior to TNS synthesis filtering */
- if ( L_spec < L_frame )
- {
- mvr2r( spectrum + 8, spectrum + 16, L_spec - 8 );
- mvr2r( spectrum + L_frame, spectrum + 8, 8 );
- mvr2r( spectrum + L_frame + 8, spectrum + L_spec + 8, L_spec - 8 );
- }
- else
- {
- float buff[8]; /* Buffer for the rearrangement of LF TCX5 */
- mvr2r( spectrum + L_spec, buff, 8 );
- mvr2r( spectrum + 8, spectrum + 16, L_spec - 8 );
- mvr2r( buff, spectrum + 8, 8 );
- }
-
- return;
+ /* rearrange LF sub-window lines prior to TNS synthesis filtering */
+ if (L_spec < L_frame)
+ {
+ mvr2r(spectrum + 8, spectrum + 16, L_spec - 8);
+ mvr2r(spectrum + L_frame, spectrum + 8, 8);
+ mvr2r(spectrum + L_frame + 8, spectrum + L_spec + 8, L_spec - 8);
+ }
+ else
+ {
+ float buff[8]; /* Buffer for the rearrangement of LF TCX5 */
+ mvr2r(spectrum + L_spec, buff, 8);
+ mvr2r(spectrum + 8, spectrum + 16, L_spec - 8);
+ mvr2r(buff, spectrum + 8, 8);
+ }
+
+ return;
}
@@ -295,38 +388,40 @@ void tcx5TnsGrouping(
*-------------------------------------------------------------------*/
void tcx5TnsUngrouping(
- const int16_t L_frame, /* i : frame length (TCX5) */
- const int16_t L_spec, /* i : coded spec length (TCX5, derived from filter borders*/
- float *spectrum,
- const int16_t enc_dec /* i : 0: encoder, else decoder */
+ const int16_t L_frame, /* i : frame length (TCX5) */
+ const int16_t L_spec, /* i : coded spec length (TCX5, derived from filter borders*/
+ float* spectrum,
+ const int16_t enc_dec /* i : 0: encoder, else decoder */
)
{
- /* undo rearrangement of LF sub-window lines prior to TNS analysis */
- if ( L_spec < L_frame )
- {
- mvr2r( spectrum + L_spec + 8, spectrum + L_frame + 8, L_spec - 8 );
- mvr2r( spectrum + 8, spectrum + L_frame, 8 );
- mvr2r( spectrum + 16, spectrum + 8, L_spec - 8 );
- set_zero( spectrum + L_spec, L_frame - L_spec );
- set_zero( spectrum + L_frame + L_spec, L_frame - L_spec );
- }
- else
- {
- float buff[8]; /* Buffer for the rearrangement of LF TCX5 */
-
- mvr2r( spectrum + 8, buff, 8 );
-
- if ( enc_dec == ENC )
- {
- mvr2r( spectrum + 16, spectrum + 8, L_frame - 8 );
- mvr2r( buff, spectrum + L_frame, 8 );
- }
- else
- {
- mvr2r( spectrum + 16, spectrum + 8, L_spec - 8 );
- mvr2r( buff, spectrum + L_spec, 8 );
- }
- }
-
- return;
+ /* undo rearrangement of LF sub-window lines prior to TNS analysis */
+ if (L_spec < L_frame)
+ {
+ mvr2r(spectrum + L_spec + 8, spectrum + L_frame + 8, L_spec - 8);
+ mvr2r(spectrum + 8, spectrum + L_frame, 8);
+ mvr2r(spectrum + 16, spectrum + 8, L_spec - 8);
+ set_zero(spectrum + L_spec, L_frame - L_spec);
+ set_zero(spectrum + L_frame + L_spec, L_frame - L_spec);
+ }
+ else
+ {
+ float buff[8]; /* Buffer for the rearrangement of LF TCX5 */
+
+ mvr2r(spectrum + 8, buff, 8);
+
+ if (enc_dec == ENC)
+ {
+ mvr2r(spectrum + 16, spectrum + 8, L_frame - 8);
+ mvr2r(buff, spectrum + L_frame, 8);
+ }
+ else
+ {
+ mvr2r(spectrum + 16, spectrum + 8, L_spec - 8);
+ mvr2r(buff, spectrum + L_spec, 8);
+ }
+ }
+
+ return;
}
+
+#endif
diff --git a/lib_com/codec_tcx_common_flt.c b/lib_com/codec_tcx_common_flt.c
new file mode 100644
index 0000000000000000000000000000000000000000..77bcaa9c9660262078717041e593ab6da72507e9
--- /dev/null
+++ b/lib_com/codec_tcx_common_flt.c
@@ -0,0 +1,332 @@
+/******************************************************************************************************
+
+ (C) 2022-2023 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 "options.h"
+#include
+#include "prot.h"
+#include "wmc_auto.h"
+
+/*-------------------------------------------------------------------*
+ * tcxGetNoiseFillingTilt()
+ *
+ *
+ *-------------------------------------------------------------------*/
+
+int16_t tcxGetNoiseFillingTilt_flt(
+ const float A[],
+ const int16_t L_frame,
+ const int16_t mode,
+ float *noiseTiltFactor )
+{
+ int16_t firstLine;
+
+ if ( mode )
+ {
+ firstLine = L_frame / 6;
+ *noiseTiltFactor = 0.5625f;
+ }
+ else
+ {
+ firstLine = L_frame / 8;
+ *noiseTiltFactor = get_gain_flt( A + 1, A, M, NULL );
+ *noiseTiltFactor = min( 1.0f, ( *noiseTiltFactor ) + 0.09375f );
+ }
+
+ return firstLine;
+}
+
+/*-------------------------------------------------------------------*
+ * tcxFormantEnhancement()
+ *
+ *
+ *-------------------------------------------------------------------*/
+
+void tcxFormantEnhancement_flt(
+ float xn_buf[],
+ const float *gainlpc,
+ float spectrum[],
+ const int16_t L_frame )
+{
+ int16_t k, 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 = hTcxCfg->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;
+}
+
+/*-------------------------------------------------------------------*
+ * tcxInvertWindowGrouping()
+ *
+ *
+ *-------------------------------------------------------------------*/
+
+void tcxInvertWindowGrouping_flt(
+ TCX_CONFIG_HANDLE hTcxCfg,
+ float xn_buf[],
+ float spectrum[],
+ const int16_t L_frame,
+ const int16_t fUseTns,
+ const int16_t last_core,
+ const int16_t index,
+ const int16_t frame_cnt,
+ const int16_t bfi )
+{
+ int16_t i, w, t_integer;
+ int16_t L_win, L_spec;
+
+ if ( frame_cnt && !bfi && last_core != ACELP_CORE )
+ {
+ /* fix sub-window overlap */
+ hTcxCfg->tcx_last_overlap_mode = hTcxCfg->tcx_curr_overlap_mode;
+ }
+
+ if ( ( ( !bfi ) && ( ( hTcxCfg->tcx_last_overlap_mode != FULL_OVERLAP ) ||
+ ( ( hTcxCfg->tcx_curr_overlap_mode == FULL_OVERLAP ) && ( frame_cnt == 0 ) && ( index == 0 ) ) ) ) ||
+ ( ( bfi ) && ( ( hTcxCfg->tcx_last_overlap_mode != FULL_OVERLAP ) &&
+ !( hTcxCfg->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 ( hTcxCfg->fIsTNSAllowed && !bfi && fUseTns )
+ {
+ L_win = L_frame >> 1;
+ L_spec = hTcxCfg->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;
+}
+
+
+/*-------------------------------------------------------------------*
+ * tcx5SpectrumInterleaving()
+ *
+ *
+ *-------------------------------------------------------------------*/
+
+void tcx5SpectrumInterleaving(
+ const int16_t tcx5Size,
+ float *spectrum )
+{
+ int16_t i;
+ float interleaveBuf[N_TCX10_MAX];
+
+ set_f( interleaveBuf, 0.0f, N_TCX10_MAX );
+
+ /* group sub-windows: interleave bins according to their frequencies */
+ for ( i = 0; i < tcx5Size; i++ )
+ {
+ interleaveBuf[2 * i] = spectrum[i];
+ interleaveBuf[2 * i + 1] = spectrum[tcx5Size + i];
+ }
+
+ mvr2r( interleaveBuf, spectrum, 2 * tcx5Size );
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------*
+ * tcx5SpectrumDeinterleaving()
+ *
+ *
+ *-------------------------------------------------------------------*/
+
+void tcx5SpectrumDeinterleaving(
+ const int16_t tcx5Size,
+ float *spectrum )
+{
+ int16_t i;
+ float interleaveBuf[N_TCX10_MAX];
+
+ set_f( interleaveBuf, 0.0f, N_TCX10_MAX );
+
+ /* ungroup sub-windows: interleave bins according to their frequencies */
+ for ( i = 0; i < tcx5Size; i++ )
+ {
+ interleaveBuf[i] = spectrum[2 * i];
+ interleaveBuf[tcx5Size + i] = spectrum[2 * i + 1];
+ }
+
+ mvr2r( interleaveBuf, spectrum, 2 * tcx5Size );
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------*
+ * tcx5TnsGrouping()
+ *
+ *
+ *-------------------------------------------------------------------*/
+
+void tcx5TnsGrouping(
+ const int16_t L_frame, /* i : frame length (TCX5) */
+ const int16_t L_spec, /* i : coded spec length (TCX5, derived from filter borders*/
+ float *spectrum )
+{
+ /* rearrange LF sub-window lines prior to TNS synthesis filtering */
+ if ( L_spec < L_frame )
+ {
+ mvr2r( spectrum + 8, spectrum + 16, L_spec - 8 );
+ mvr2r( spectrum + L_frame, spectrum + 8, 8 );
+ mvr2r( spectrum + L_frame + 8, spectrum + L_spec + 8, L_spec - 8 );
+ }
+ else
+ {
+ float buff[8]; /* Buffer for the rearrangement of LF TCX5 */
+ mvr2r( spectrum + L_spec, buff, 8 );
+ mvr2r( spectrum + 8, spectrum + 16, L_spec - 8 );
+ mvr2r( buff, spectrum + 8, 8 );
+ }
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------*
+ * tcx5TnsUngrouping()
+ *
+ *
+ *-------------------------------------------------------------------*/
+
+void tcx5TnsUngrouping(
+ const int16_t L_frame, /* i : frame length (TCX5) */
+ const int16_t L_spec, /* i : coded spec length (TCX5, derived from filter borders*/
+ float *spectrum,
+ const int16_t enc_dec /* i : 0: encoder, else decoder */
+)
+{
+ /* undo rearrangement of LF sub-window lines prior to TNS analysis */
+ if ( L_spec < L_frame )
+ {
+ mvr2r( spectrum + L_spec + 8, spectrum + L_frame + 8, L_spec - 8 );
+ mvr2r( spectrum + 8, spectrum + L_frame, 8 );
+ mvr2r( spectrum + 16, spectrum + 8, L_spec - 8 );
+ set_zero( spectrum + L_spec, L_frame - L_spec );
+ set_zero( spectrum + L_frame + L_spec, L_frame - L_spec );
+ }
+ else
+ {
+ float buff[8]; /* Buffer for the rearrangement of LF TCX5 */
+
+ mvr2r( spectrum + 8, buff, 8 );
+
+ if ( enc_dec == ENC )
+ {
+ mvr2r( spectrum + 16, spectrum + 8, L_frame - 8 );
+ mvr2r( buff, spectrum + L_frame, 8 );
+ }
+ else
+ {
+ mvr2r( spectrum + 16, spectrum + 8, L_spec - 8 );
+ mvr2r( buff, spectrum + L_spec, 8 );
+ }
+ }
+
+ return;
+}
diff --git a/lib_com/prot.h b/lib_com/prot.h
index 0f64e47609d850a1dbb272210abddc4930c4e37e..d0299041af758a2730250f279951e702a3d84bf1 100644
--- a/lib_com/prot.h
+++ b/lib_com/prot.h
@@ -8864,48 +8864,48 @@ void ReadFromBitstream(
int16_t **pStream,
int16_t *pnSize );
-void const *GetTnsFilterOrder( void const *p, const int16_t index, int16_t *pValue );
-void *SetTnsFilterOrder( void *p, const int16_t index, const int16_t value );
-void const *GetNumOfTnsFilters( void const *p, const int16_t index, int16_t *pValue );
-void *SetNumOfTnsFilters( void *p, const int16_t index, const int16_t value );
-void const *GetTnsEnabled( void const *p, const int16_t index, int16_t *pValue );
-void *SetTnsEnabled( void *p, const int16_t index, const int16_t value );
-void const *GetTnsEnabledSingleFilter( void const *p, const int16_t index, int16_t *pValue );
-void *SetTnsEnabledSingleFilter( void *p, const int16_t index, const int16_t value );
-void const *GetTnsFilterCoeff( void const *p, const int16_t index, int16_t *pValue );
-void *SetTnsFilterCoeff( void *p, const int16_t index, const int16_t value );
+//void const *GetTnsFilterOrder_flt( void const *p, const int16_t index, int16_t *pValue );
+//void *SetTnsFilterOrder_flt( void *p, const int16_t index, const int16_t value );
+void const *GetNumOfTnsFilters_flt (void const *p, const int16_t index, int16_t *pValue);
+void *SetNumOfTnsFilters_flt( void *p, const int16_t index, const int16_t value );
+//void const *GetTnsEnabled_flt( void const *p, const int16_t index, int16_t *pValue );
+//void *SetTnsEnabled_flt( void *p, const int16_t index, const int16_t value );
+//void const *GetTnsEnabledSingleFilter_flt( void const *p, const int16_t index, int16_t *pValue );
+//void *SetTnsEnabledSingleFilter_flt( void *p, const int16_t index, const int16_t value );
+//void const *GetTnsFilterCoeff_flt( void const *p, const int16_t index, int16_t *pValue );
+//void *SetTnsFilterCoeff_flt( void *p, const int16_t index, const int16_t value );
void const *GetTnsOnWhite( void const *p, const int16_t index, int16_t *pValue );
void *SetTnsOnWhite( void *p, const int16_t index, const int16_t value );
-int16_t GetSWBTCX10TnsFilterCoeffBits( const int16_t value, const int16_t index );
-int16_t EncodeSWBTCX10TnsFilterCoeff( const int16_t value, const int16_t index );
-int16_t DecodeSWBTCX10TnsFilterCoeff( Decoder_State *st, const int16_t index, int16_t *pValue );
-int16_t GetSWBTCX20TnsFilterCoeffBits( const int16_t value, const int16_t index );
-int16_t EncodeSWBTCX20TnsFilterCoeff( const int16_t value, const int16_t index );
-int16_t DecodeSWBTCX20TnsFilterCoeff( Decoder_State *st, const int16_t index, int16_t *pValue );
-
-int16_t GetWBTCX20TnsFilterCoeffBits( const int16_t value, const int16_t index );
-int16_t EncodeWBTCX20TnsFilterCoeff( const int16_t, const int16_t index );
-int16_t DecodeWBTCX20TnsFilterCoeff( Decoder_State *st, const int16_t index, int16_t *pValue );
-
-int16_t GetTnsFilterOrderBitsSWBTCX10( const int16_t value, const int16_t index );
-int16_t EncodeTnsFilterOrderSWBTCX10( const int16_t value, const int16_t index );
-int16_t DecodeTnsFilterOrderSWBTCX10( Decoder_State *st, const int16_t index, int16_t *pValue );
-int16_t GetTnsFilterOrderBitsSWBTCX20( const int16_t value, const int16_t index );
-int16_t EncodeTnsFilterOrderSWBTCX20( const int16_t value, const int16_t index );
-int16_t DecodeTnsFilterOrderSWBTCX20( Decoder_State *st, const int16_t index, int16_t *pValue );
-int16_t GetTnsFilterOrderBits( const int16_t value, const int16_t index );
-int16_t EncodeTnsFilterOrder( const int16_t value, const int16_t index );
-int16_t DecodeTnsFilterOrder( Decoder_State *st, const int16_t index, int16_t *pValue );
-
-void ResetTnsData(
+//int16_t GetSWBTCX10TnsFilterCoeffBits_flt( const int16_t value, const int16_t index );
+//int16_t EncodeSWBTCX10TnsFilterCoeff_flt( const int16_t value, const int16_t index );
+int16_t DecodeSWBTCX10TnsFilterCoeff_flt( Decoder_State *st, const int16_t index, int16_t *pValue );
+//int16_t GetSWBTCX20TnsFilterCoeffBits_flt( const int16_t value, const int16_t index );
+//int16_t EncodeSWBTCX20TnsFilterCoeff_flt( const int16_t value, const int16_t index );
+int16_t DecodeSWBTCX20TnsFilterCoeff_flt( Decoder_State *st, const int16_t index, int16_t *pValue );
+
+//int16_t GetWBTCX20TnsFilterCoeffBits_flt( const int16_t value, const int16_t index );
+//int16_t EncodeWBTCX20TnsFilterCoeff_flt( const int16_t, const int16_t index );
+int16_t DecodeWBTCX20TnsFilterCoeff_flt( Decoder_State *st, const int16_t index, int16_t *pValue );
+
+//int16_t GetTnsFilterOrderBitsSWBTCX10_flt( const int16_t value, const int16_t index );
+//int16_t EncodeTnsFilterOrderSWBTCX10_flt( const int16_t value, const int16_t index );
+int16_t DecodeTnsFilterOrderSWBTCX10_flt( Decoder_State *st, const int16_t index, int16_t *pValue );
+//int16_t GetTnsFilterOrderBitsSWBTCX20_flt( const int16_t value, const int16_t index );
+//int16_t EncodeTnsFilterOrderSWBTCX20_flt( const int16_t value, const int16_t index );
+int16_t DecodeTnsFilterOrderSWBTCX20_flt( Decoder_State *st, const int16_t index, int16_t *pValue );
+//int16_t GetTnsFilterOrderBits_flt( const int16_t value, const int16_t index );
+//int16_t EncodeTnsFilterOrder_flt( const int16_t value, const int16_t index );
+int16_t DecodeTnsFilterOrder_flt( Decoder_State *st, const int16_t index, int16_t *pValue );
+
+void ResetTnsData_flt(
STnsData *pTnsData );
-void ClearTnsFilterCoefficients(
+void ClearTnsFilterCoefficients_flt(
STnsFilter *pTnsFilter );
-void InitTnsConfiguration(
+void InitTnsConfiguration_flt(
const int16_t bwidth,
const int16_t frameLength,
STnsConfig *pTnsConfig,
@@ -8924,7 +8924,7 @@ int16_t DetectTnsFilt(
float *predictionGain /* o : TNS prediction gain */
);
-void ApplyTnsFilter(
+void ApplyTnsFilter_flt(
STnsConfig const *pTnsConfig,
STnsData const *pTnsData,
float spectrum[],
@@ -9322,19 +9322,19 @@ void decoder_LPD(
float *ptr_bwe_exc /* o : excitation for SWB TBE */
);
-int16_t tcxGetNoiseFillingTilt(
+int16_t tcxGetNoiseFillingTilt_flt(
const float A[],
const int16_t L_frame,
const int16_t mode,
float *noiseTiltFactor );
-void tcxFormantEnhancement(
+void tcxFormantEnhancement_flt(
float xn_buf[],
const float *gainlpc,
float spectrum[],
const int16_t L_frame );
-void tcxInvertWindowGrouping(
+void tcxInvertWindowGrouping_flt(
TCX_CONFIG_HANDLE hTcxCfg,
float xn_buf[],
float spectrum[],
diff --git a/lib_com/prot_fx2.h b/lib_com/prot_fx2.h
index 5e9a6c986796601868710b854f15a05f753bd63e..8e8fc01755941a4a8747575213d3bb221e39fad5 100644
--- a/lib_com/prot_fx2.h
+++ b/lib_com/prot_fx2.h
@@ -131,10 +131,44 @@ Word16 deindex_lvq_fx(
Word16 *p_no_scales
);
+void permute_fx(
+ Word16 *pTmp1, /* i/o: vector whose components are to be permuted */
+ const Word16 *perm /* i : permutation info (indexes that should be interchanged), max two perms */
+);
+
+void init_lvq_fx(
+ Word32 offset_scale1[][MAX_NO_SCALES + 1],
+ Word32 offset_scale2[][MAX_NO_SCALES + 1],
+ Word32 offset_scale1_p[][MAX_NO_SCALES + 1],
+ Word32 offset_scale2_p[][MAX_NO_SCALES + 1],
+ Word16 no_scales[][2],
+ Word16 no_scales_p[][2]
+);
+
+Word16 deindex_lvq_cng_fx(
+ Word16 *index, /* i : index to be decoded, as an array of 3 short */
+ Word16 *x_lvq, /* o : decoded codevector Q9*/
+ Word16 idx_cv, /* i : relative mode_lvq, wrt START_CNG */
+ Word16 no_bits, /* i : number of bits for lattice */
+ Word32 * p_offset_scale1,
+ Word32 * p_offset_scale2,
+ Word16 * p_no_scales
+);
+
/*========================================================================================================/
-swe_bwe_com_fx.c
+swb_bwe_com_fx.c
/========================================================================================================*/
+void calc_normal_length_fx(
+ const Word16 core, /* i : core */
+ const Word16 *sp, /* i : i signal */
+ const Word16 mode, /* i : i mode */
+ const Word16 extl, /* i : extension layer */
+ Word16 *L_swb_norm, /* o : normalize length */
+ Word16 *prev_L_swb_norm, /*i/o : last normalize length */
+ Word16 Q_syn
+);
+
void calc_normal_length_fx_32(
const Word16 core, /* i : core : Q0 */
const Word32 *sp, /* i : i signal : Q12 */
@@ -156,6 +190,118 @@ void hq_generic_decoding_fx(
const Word16 *R
);
+Word16 WB_BWE_gain_pred_fx(
+ Word16 *WB_fenv, /* o : WB frequency envelopes */
+ const Word16 *core_dec_freq, /* i : Frequency domain core decoded signal */
+ const Word16 coder_type, /* i : coding type */
+ Word16 prev_coder_type, /* i : coding type of last frame */
+ Word16 prev_WB_fenv, /* i : envelope for last frame */
+ Word16 *voice_factors, /* i : voicing factors Q15 */
+ const Word16 pitch_buf[], /* i : pitch buffer Q6 */
+ Word32 last_core_brate, /* i : previous frame core bitrate */
+ Word16 last_wb_bwe_ener, /* i : previous frame wb bwe signal energy */
+ Word16 Q_syn
+ , Word16 last_extl_fx,
+ Word16 tilt_wb_fx
+);
+
+Word32 calc_tilt_bwe_fx( /* o : Tilt in Q24 */
+ const Word16 *sp0, /* i : i signal */
+ const Word16 exp, /* i : Exp of inp signal */
+ const Word16 N /* i : signal length */
+);
+
+void calc_norm_envelop_fx(
+ const Word16 SWB_signal[], /* i : SWB spectrum Q_syn*/
+ Word32 *envelope, /* o : normalized envelope Q_syn*/
+ const Word16 L_swb_norm, /* i : length of envelope Q0 */
+ const Word16 SWB_flength, /* i : Length of i /output */
+ const Word16 st_offset /* i : offset */
+);
+
+void WB_BWE_decoding_fx(
+ const Word16 *core_dec_freq, /* i : Frequency domain core decoded signal */
+ Word16 *WB_fenv, /* i : WB frequency envelopes */
+ Word32 *WB_signal32, /* o : WB signal in MDCT domain */
+ const Word16 WB_flength, /* i : Length of i /output */
+ const Word16 mode, /* i : classification for WB signal */
+ const Word16 last_extl, /* i : extl. layer for last frame */
+ Word32 *prev_Energy, /* i/o: energy for last frame */
+ Word16 *prev_WB_fenv, /* i/o: envelope for last frame */
+ Word16 *prev_L_wb_norm, /* i/o: length for last frame wb norm */
+ const Word16 extl, /* i : extension layer */
+ const Word16 coder_type, /* i : coding type */
+ const Word32 total_brate, /* i : core layer bitrate */
+ Word16 *Seed, /* i/o: random generator seed */
+ Word16 *prev_flag, /* i/o: attenu flag of last frame */
+ Word16 prev_coder_type, /* i : coding type of last frame */
+ Word16 Q_syn,
+ Word16 *Q_syn_hb /*o : Q value of WB_signal_32 */
+);
+
+void SWB_BWE_decoding_fx(
+ const Word16 *core_dec_freq, /* i : Frequency domain core decoded signal */
+ Word16 *SWB_fenv, /* i/o: SWB frequency envelopes */
+ Word32 *SWB_signal, /* o : SWB signal in MDCT domain */
+ const Word16 SWB_flength, /* i : Length of i /output */
+ const Word16 mode, /* i : classification for SWB signal */
+ Word16 *frica_flag, /* o : fricative signal flag */
+ Word16 *prev_Energy, /* i/o: energy for last frame */
+ Word16 *prev_SWB_fenv, /* i/o: envelope for last frame */
+ Word16 *prev_L_swb_norm, /* i/o: length for last frame wb norm */
+ const Word16 tilt_nb, /* i : tilt of synthesis wb signal */
+ Word16 *Seed, /* i/o: random generator seed */
+ const Word16 st_offset, /* i : offset value due to different core */
+ Word16 *prev_weight, /* i/o: excitation weight value of last frame */
+ const Word16 extl, /* i : extension layer */
+ Word16 Q_syn
+ , const Word16 last_extl /* i : extension layer of last frame */
+);
+
+void time_envelop_shaping_fx(
+ Word16 werr[], /* i/o: SHB synthesis Q_synth*/
+ Word32 SWB_tenv[], /* i/o: frequency envelope Q15*/
+ const Word16 L, /* i : frame length */
+ Word16 *Q_synth
+);
+
+void time_reduce_pre_echo_fx(
+ const Word16 *synth, /* i : ACELP core synthesis Q_syn*/
+ Word16 *error, /* i/o: SHB BWE synthesis Q0*/
+ Word16 prev_td_energy, /* o : last td energy Q0*/
+ const Word16 L, /* i : subframe length */
+ Word16 Q_syn,
+ Word16 Q_synth
+);
+
+void calc_norm_envelop_fx_32(
+ const Word32 SWB_signal_fx[], /* i : SWB spectrum : Q12 */
+ Word32 *envelope_fx, /* o : normalized envelope : Q16 */
+ const Word16 L_swb_norm, /* i : length of envelope : Q0 */
+ const Word16 SWB_flength, /* i : Length of i /output : Q0 */
+ const Word16 st_offset /* i : offset : Q0 */
+);
+
+void hq_generic_decoding_fx(
+ const Word16 HQ_mode, /* i : HQ mode */
+ Word32 *coeff_out1_fx, /* i/o: BWE i & temporary buffer */
+ const Word16 *hq_generic_fenv_fx, /* i : SWB frequency envelopes */
+ Word32 *coeff_out_fx, /* o : SWB signal in MDCT domain */
+ const Word16 hq_generic_offset, /* i : frequency offset for representing hq generic*/
+ Word16 *prev_L_swb_norm, /* i/o: last normalize length */
+ const Word16 hq_generic_exc_clas, /* i : bwe excitation class */
+ const Word16 *R
+);
+
+void save_old_syn_fx(
+ const Word16 L_frame, /* i : frame length */
+ const Word16 syn[], /* i : ACELP synthesis */
+ Word16 old_syn[], /* o : old synthesis buffer */
+ Word16 old_syn_mem[], /* i/o: old synthesis buffer memory */
+ const Word16 preemph_fac, /* i : preemphasis factor */
+ Word16 *mem_deemph /* i/o: deemphasis filter memory */
+);
+
/*========================================================================================================/
lognorm_fx.c
/========================================================================================================*/
@@ -2607,4 +2753,282 @@ Word32 DTFS_getEngy_band_wb_fx(
Word16 hband
);
+//tns_base.c
+/** Init TNS configuration.
+ * Fills STnsConfig structure with sensible content.
+ * @param nSampleRate Sampling rate of the i .
+ * @param nFrameLength Frame length.
+ * @param pTnsConfig TNS configuration to be initialized.
+ * @return 0 on success, otherwise 1.
+ */
+void InitTnsConfiguration(
+ const Word16 bwidth,
+ const Word16 frameLength,
+ STnsConfig* pTnsConfig,
+ const Word16 igfStopFreq,
+ const Word32 total_brate,
+ const Word16 element_mode,
+ const Word16 is_mct
+);
+
+/** Modify spectrum using TNS filter.
+ * Modifies spectrum unsing TNS filter defined by pTnsData.
+ * If fIsAnalyses is true considers spectrum to be
+ * an i of encoder and returns residum.
+ * If fIsAnalyses is false considers spectrum to be
+ * a residum from decoder and returns output spectrum.
+ * @param pTnsConfig TNS configuration.
+ * @param pTnsData TNS data describing filters.
+ * @param spectrum Input/output spectrum.
+ * @param fIsAnalysis Defines if TNS filter is applied
+ * in encoder (TRUE) or in decoder (FALSE).
+ * @return 0 on success, otherwise 1.
+ */
+void ApplyTnsFilter(
+ STnsConfig const * pTnsConfig,
+ STnsData const * pTnsData,
+ Word32 spectrum[],
+ const Word8 fIsAnalysis
+);
+
+Word16 ITF_Detect_fx(Word32 const pSpectrum[],
+ const Word16 startLine,
+ const Word16 stopLine,
+ const Word16 maxOrder,
+ Word16* A,
+ Word16* Q_A,
+ Word16* predictionGain,
+ Word16* curr_order,
+ Word16 Q);
+
+void ITF_Apply_fx(Word32 spectrum[],
+ Word16 startLine, Word16 stopLine, const Word16* A,
+ Word16 Q_A,
+ Word16 curr_order);
+
+void const * GetTnsFilterCoeff(void const * p, const Word16 index, Word16 * pValue);
+
+void * SetTnsFilterCoeff(void * p, const Word16 index, const Word16 value);
+
+Word16 GetSWBTCX20TnsFilterCoeffBits(const Word16 value, const Word16 index);
+
+Word16 EncodeSWBTCX20TnsFilterCoeff(const Word16 value, const Word16 index);
+
+Word16 DecodeSWBTCX20TnsFilterCoeff(Decoder_State *st, const Word16 index, Word16 * pValue);
+
+Word16 GetSWBTCX10TnsFilterCoeffBits(const Word16 value, const Word16 index);
+
+Word16 EncodeSWBTCX10TnsFilterCoeff(const Word16 value, const Word16 index);
+
+Word16 DecodeSWBTCX10TnsFilterCoeff(Decoder_State *st, const Word16 index, Word16 * pValue);
+
+Word16 GetWBTCX20TnsFilterCoeffBits(const Word16 value, const Word16 index);
+
+Word16 EncodeWBTCX20TnsFilterCoeff(const Word16 value, const Word16 index);
+
+Word16 DecodeWBTCX20TnsFilterCoeff(Decoder_State *st, const Word16 index, Word16 * pValue);
+
+void const * GetTnsFilterOrder(void const * p, const Word16 index, Word16 * pValue);
+
+void * SetTnsFilterOrder(void * p, const Word16 index, const Word16 value);
+
+Word16 GetTnsFilterOrderBitsSWBTCX20(const Word16 value, const Word16 index);
+
+Word16 EncodeTnsFilterOrderSWBTCX20(const Word16 value, const Word16 index);
+
+Word16 DecodeTnsFilterOrderSWBTCX20(Decoder_State *st, const Word16 index, Word16 * pValue);
+
+Word16 GetTnsFilterOrderBitsSWBTCX10(const Word16 value, const Word16 index);
+
+Word16 EncodeTnsFilterOrderSWBTCX10(const Word16 value, const Word16 index);
+
+Word16 DecodeTnsFilterOrderSWBTCX10(Decoder_State *st, const Word16 index, Word16 * pValue);
+
+Word16 GetTnsFilterOrderBits(const Word16 value, const Word16 index);
+
+Word16 EncodeTnsFilterOrder(const Word16 value, const Word16 index);
+
+Word16 DecodeTnsFilterOrder(Decoder_State *st, const Word16 index, Word16 * pValue);
+
+void const * GetNumOfTnsFilters(void const * p, const Word16 index, Word16 * pValue);
+
+void * SetNumOfTnsFilters(void * p, const Word16 index, Word16 value);
+
+void const * GetTnsEnabled(void const * p, const Word16 index, Word16 * pValue);
+
+void * SetTnsEnabled(void * p, const Word16 index, const Word16 value);
+
+void const * GetTnsEnabledSingleFilter(void const * p, const Word16 index, Word16 * pValue);
+
+void * SetTnsEnabledSingleFilter(void * p, const Word16 index, const Word16 value);
+
+/*tns_base.h*/
+/** Reset TNS data.
+ * Resets TNS data to the initial state.
+ * @param pTnsData pointer to a TNS data to be reset.
+ */
+void ResetTnsData(STnsData * pTnsData);
+
+/** Clear TNS filter data.
+ * Resets TNS filter order and all coefficients to 0.
+ * @param pTnsFilter pointer to a TNS filter to be cleared.
+ */
+void ClearTnsFilterCoefficients(STnsFilter * pTnsFilter);
+
+/*========================================================================================================/
+gp_clips_fx.c
+/========================================================================================================*/
+
+void init_gp_clip_fx(
+ Word16 mem[] /* o : memory of gain of pitch clipping algorithm */
+);
+
+Word16 gp_clip_fx(
+ const Word16 element_mode, /* i : element mode */
+ const Word32 core_brate, /* i : core bitrate */
+ const Word16* voicing, /* i : normalized correlations (from OL pitch) */
+ const Word16 i_subfr, /* i : subframe index */
+ const Word16 coder_type, /* i : type of coder */
+ const Word16 xn[], /* i : target vector */
+ Word16 mem[], /* i/o: memory of gain of pitch clipping algorithm */
+ const Word16 Q_new /* i : scaling factor */
+);
+
+void gp_clip_test_isf_fx(
+ const Word16 element_mode, /* i : element mode */
+ const Word32 core_brate, /* i : core bitrate */
+ const Word16 isf[], /* i : isf values (in frequency domain) */
+ Word16 mem[], /* i/o: memory of gain of pitch clipping algorithm */
+ const Word16 Opt_AMR_WB /* i : flag indicating AMR-WB IO mode */
+);
+
+void gp_clip_test_gain_pit_fx(
+ const Word16 element_mode, /* i : element mode */
+ const Word32 core_brate, /* i : core bitrate */
+ const Word16 gain_pit, /* i : gain of quantized pitch Q14 */
+ Word16 mem[] /* i/o: memory of gain of pitch clipping algorithm 1Q14 */
+);
+
+Word16 Mode2_gp_clip(
+ const Word16 *voicing, /* i : normalized correlations (from OL pitch) */
+ const Word16 i_subfr, /* i : subframe index */
+ const Word16 coder_type, /* i : type of coder */
+ const Word16 xn[], /* i : target vector */
+ Word16 mem[], /* i/o: memory of gain of pitch clipping algorithm */
+ const Word16 L_subfr,
+ const Word16 Q_xn /* i : xn data format */
+);
+
+void gp_clip_test_lsf_fx(
+ const Word16 element_mode, /* i : element mode */
+ const Word16 lsf[], /* i : lsf values (in frequency domain) 14Q1*1.28 */
+ Word16 mem[], /* i/o: memory of gain of pitch clipping algorithm */
+ const Word16 m /* i : dimension of lsf */
+);
+
+/*========================================================================================================/
+nelp_enc_fx.c
+/========================================================================================================*/
+
+void quantize_uvg_fx(
+ Word16 *G,
+ Word16 *iG1,
+ Word16 *iG2,
+ Word16 *quantG,
+ Word16 bandwidth
+);
+
+void nelp_encoder_fx(
+ Encoder_State *st_fx, /* i/o: encoder state */
+ Word16 *in_fx, /* i : residual signal */
+ Word16 *exc_fx, /* o : NELP quantized excitation signal */
+ Word16 *qIn1
+ , Word16 reduce_gains
+);
+
+/*========================================================================================================/
+swb_bwe_enc_lr_fx.c
+/========================================================================================================*/
+
+void swb_bwe_enc_lr_fx(
+ Encoder_State *st_fx, /* i/o: encoder state structure */
+ const Word32 L_m_core[], /* i : lowband synthesis */
+ Word16 QsL,
+ const Word32 L_m_orig[], /* i/o: scaled orig signal (MDCT) */
+ Word32 L_m[], /* o : highband synthesis with lowband zeroed */
+ const Word32 L_total_brate, /* i : total bitrate for selecting subband pattern */
+ Word16 BANDS_fx, /* i : Total number of Subbands in a frame */
+ Word16 *band_start_fx, /* i : band start of each SB */
+ Word16 *band_end_fx, /* i : band end of each SB */
+ Word32 *L_band_energy, /* i : band_energy of each SB */
+ Word16 Qbe, /* i : Q value of band energy */
+ Word16 *p2a_flags_fx, /* i : HF tonal indicator */
+ const Word16 hqswb_clas_fx, /* i : HQ_NORMAL2 or HQ_HARMONIC mode */
+ Word16 lowlength_fx, /* i : lowband length */
+ Word16 highlength_fx, /* i : highband length */
+ Word16 *prev_frm_index_fx, /* i/o: previous frame lag index for harmonic mode */
+ const Word16 har_bands_fx, /* i : Number of LF harmonic bands */
+ Word16 *prev_frm_hfe2, /* i/o: */
+ Word16 *prev_stab_hfe2, /* i/o: */
+ const Word16 band_width_fx[], /* i : band_width information */
+ const Word32 L_y2_ni[], /* i : band_width information */
+ Word16 *ni_seed_fx /* i/o: random seed for search buffer NI */
+);
+
+/*========================================================================================================/
+isf_enc_amr_wb_fx.c
+/========================================================================================================*/
+
+void isf_enc_amr_wb_fx(
+ Encoder_State* st, /* i/o: state structure */
+ Word16* isf_new, /* i/o: quantized ISF vector */
+ Word16* isp_new, /* i/o: ISP vector to quantize/quantized */
+ Word16* Aq /* o : quantized A(z) for 4 subframes */
+);
+
+/*========================================================================================================/
+detect_transient_fx.c
+/========================================================================================================*/
+
+Word16 detect_transient_fx(
+ const Word16 *in_fx, /*Q_new */
+ const Word16 L,
+ Word16 Q_new,
+ Encoder_State *st_fx
+);
+
+/*========================================================================================================/
+codec_tcx_common.c
+/========================================================================================================*/
+
+Word16 tcxGetNoiseFillingTilt(
+ const Word16 A[],
+ const Word16 lpcorder,
+ const Word16 L_frame,
+ const Word16 mode,
+ Word16* noiseTiltFactor
+);
+
+void tcxFormantEnhancement(
+ Word16 xn_buf[],
+ const Word16 gainlpc[],
+ const Word16 gainlpc_e[],
+ Word32 spectrum[],
+ Word16* spectrum_e,
+ const Word16 L_frame,
+ const Word16 L_frameTCX
+);
+
+void tcxInvertWindowGrouping(
+ TCX_CONFIG_HANDLE hTcxCfg, /* i : configuration of TCX */
+ Word32 xn_buf[],
+ Word32 spectrum[],
+ const Word16 L_frame,
+ const Word8 fUseTns,
+ const Word16 last_core,
+ const Word16 index,
+ const Word16 frame_cnt,
+ const Word16 bfi
+);
+
#endif
\ No newline at end of file
diff --git a/lib_com/rom_basop_util.c b/lib_com/rom_basop_util.c
index b0c91f72367ce49dfb5e9919e4cf4f7513511b8f..e6b63e54a7f7c337b9a47d1f2c10d594516f4b11 100644
--- a/lib_com/rom_basop_util.c
+++ b/lib_com/rom_basop_util.c
@@ -813,4 +813,17 @@ const PWord16* getSineWindowTable(Word16 length)
assert(p != NULL);
return p;
-}
\ No newline at end of file
+}
+
+const Word16 InvIntTable[65] =
+{
+ 0x7FFF,
+ 0x7FFF, 0x4000, 0x2AAB, 0x2000, 0x199A, 0x1555, 0x1249, 0x1000,
+ 0x0E39, 0x0CCD, 0x0BA3, 0x0AAB, 0x09D9, 0x0925, 0x0889, 0x0800,
+ 0x0788, 0x071C, 0x06BD, 0x0666, 0x0618, 0x05D1, 0x0591, 0x0555,
+ 0x051F, 0x04EC, 0x04BE, 0x0492, 0x046A, 0x0444, 0x0421, 0x0400,
+ 0x03E1, 0x03C4, 0x03A8, 0x038E, 0x0376, 0x035E, 0x0348, 0x0333,
+ 0x031F, 0x030C, 0x02FA, 0x02E9, 0x02D8, 0x02C8, 0x02B9, 0x02AB,
+ 0x029D, 0x028F, 0x0283, 0x0276, 0x026A, 0x025F, 0x0254, 0x0249,
+ 0x023F, 0x0235, 0x022B, 0x0222, 0x0219, 0x0211, 0x0208, 0x0200
+};
\ No newline at end of file
diff --git a/lib_com/rom_basop_util.h b/lib_com/rom_basop_util.h
index 18c4bf70114336324879b7ae986a3594e8b89233..188af401324c4fedbb7a2ed8e5dba92874bcf3ba 100644
--- a/lib_com/rom_basop_util.h
+++ b/lib_com/rom_basop_util.h
@@ -51,4 +51,6 @@ extern const PWord16 SineTable320[161];
void BASOP_getTables(const PWord16 **ptwiddle, const PWord16 **sin_twiddle, Word16 *sin_step, Word16 length);
const PWord16* getSineWindowTable(Word16 length);
+extern const Word16 InvIntTable[65];
+
#endif
diff --git a/lib_com/rom_com.c b/lib_com/rom_com.c
index 75157e8f41d4e337a0bc91552bfa7c9d86521c3b..ff45696775643f7c588b2d0474aafc8a64bd299b 100644
--- a/lib_com/rom_com.c
+++ b/lib_com/rom_com.c
@@ -41,6 +41,7 @@
#include "prot.h"
#include "basop_util.h"
#include "wmc_auto.h"
+#include "prot_fx2.h"
/* clang-format off */
@@ -18683,6 +18684,8 @@ const float Mean_env_tr[5] = { 27.23f, 23.81f, 23.87f, 19.51f };
const float gain_table_SWB_BWE[NB_SWB_SUBBANDS] = {-0.4f, 0.1f, 0.6f, 1.1f};
+const Word16 gain_table_SWB_BWE_fx[NB_SWB_SUBBANDS] = { -6554/*-0.4f*/, 1638/*0.1f*/, 9830/*0.6f*/, 18022/*1.1f*/ }; /* Q14 */
+
const int16_t bits_lagIndices_modeNormal[NB_SWB_SUBBANDS] = {2, 2, 1, 1};
const int16_t subband_offsets_12KBPS[NB_SWB_SUBBANDS] = {SWB_SB_OFF0_12KBPS, SWB_SB_OFF1_12KBPS, SWB_SB_OFF2_12KBPS, SWB_SB_OFF3_12KBPS};
const int16_t subband_offsets_16KBPS[NB_SWB_SUBBANDS] = {SWB_SB_OFF0_16KBPS, SWB_SB_OFF1_16KBPS, SWB_SB_OFF2_16KBPS, SWB_SB_OFF3_16KBPS};
@@ -20225,6 +20228,8 @@ const int16_t lim_neg_inv_tbl_fx[MAX_SPLITS + 1 ] =
-5462, -4681, -4096, -3641, -3277
};
+const Word16 Idx2Freq_Tbl[] = { 6554/*12.8*512*/, 48 * 512, 13108/*25.6*512*/, 32 * 512, 16 * 512, 8 * 512 }; /* in Q9 */
+
const int16_t fg_inv_tbl_fx [HQ_MAX_BAND_LEN/8 + 1 ] =
{ /* i/8 , slice of inv_tbl_fx , Q15 */
0,
@@ -23308,6 +23313,10 @@ const float SmoothingWin_NB2[16] =
const float bp1_num_coef_wb[5] = {0.9329833984375,0,-1.865966796875,0,0.9329833984375};
const float bp1_den_coef_wb[5] = {1,0,-1.8614501953125,0,0.8704833984375};
+const Word16 bp1_num_coef_wb_fx[5] = { 15286, 0, -30572, 0, 15286, }; /* Q14 */
+const Word16 bp1_den_coef_wb_fx[5] = { 16384, 0, -30498, 0, 14262, }; /* Q14 */
+
+
const float shape1_num_coef[11] =
{
0.959381103515625f, -0.074554443359375f, -0.4161376953125f, 0.1317138671875f,
@@ -23315,6 +23324,13 @@ const float shape1_num_coef[11] =
-0.023681640625f, 0.03192138671875f, 0.012176513671875f
};
+const Word16 shape1_num_coef_fx[11] = /* Q15 */
+{
+ 31437, -2443, -13636, 4316,
+ -10188, 48, 2639, -3575,
+ -776, 1046, 399
+};
+
const float shape1_den_coef[11] =
{
1, 0.0897216796875f, -0.373443603515625f, 0.123046875f, -0.293243408203125f,
@@ -23322,6 +23338,12 @@ const float shape1_den_coef[11] =
0.026153564453125f, 0.007720947265625f
};
+const Word16 shape1_den_coef_fx[11] = { 32767, /* Q15 */
+ 2940, -12237, 4032, -9609,
+ -1998, 2335, -3900, -1595,
+ 857, 253
+};
+
const float shape2_num_coef[11] =
{
0.938720703125f, 0.000946044921875f, -0.295989990234375f, 0.2904052734375f,
@@ -23329,6 +23351,13 @@ const float shape2_num_coef[11] =
0.10003662109375f, -0.001922607421875f, 0.034027099609375f
};
+const Word16 shape2_num_coef_fx[11] = /* Q15 */
+{
+ 30760, 31, -9699, 9516,
+ -5878, -7249, -10468, 442,
+ 3278, -63, 1115
+};
+
const float shape2_den_coef[11] =
{
1, 0.488861083984375f, -0.02716064453125f, 0.390594482421875f, 0.07159423828125f,
@@ -23336,6 +23365,12 @@ const float shape2_den_coef[11] =
-0.0455322265625f, -0.00927734375f
};
+const Word16 shape2_den_coef_fx[11] = { 32767, /* Q15 */
+ 16019, -890, 12799, 2346,
+ -6985, -13192, -5795, -949,
+ -1492, -304
+};
+
const float shape3_num_coef[11] =
{
0.936431884765625f, -0.011688232421875f, -0.303253173828125f, -0.293121337890625f,
@@ -23343,6 +23378,13 @@ const float shape3_num_coef[11] =
0.098846435546875f, 0.0003662109375f, 0.0364990234375f
};
+const Word16 shape3_num_coef_fx[11] = /* Q15 */
+{
+ 30685, -383, -9937, -9605,
+ -5997, 7611, -10393, -355,
+ 3239, 12, 1196
+};
+
const float shape3_den_coef[11] =
{
1, -0.50347900390625f, -0.027801513671875f, -0.395111083984375f, 0.06976318359375f,
@@ -23350,6 +23392,14 @@ const float shape3_den_coef[11] =
0.0482177734375f, -0.008331298828125f
};
+const Word16 shape3_den_coef_fx[11] = { 32767, /* Q15 */
+ -16498, -911, -12947, 2286,
+ 7430, -13385, 6066, -1182,
+ 1580, -273
+};
+
+
+
const float txlpf1_num_coef[11] =
{
0.016845703125, 0.024169921875, 0.062744140625, 0.0831298828125, 0.1124267578125,
@@ -23357,6 +23407,13 @@ const float txlpf1_num_coef[11] =
0.016845703125
};
+const Word16 txlpf1_num_coef_fx[11] = /* Q13 */
+{
+ 138, 198, 514, 681, 921,
+ 964, 921, 681, 514, 198,
+ 138,
+};
+
const float txlpf1_den_coef[11] =
{
1, -2.3126220703125, 3.8590087890625, -3.8023681640625, 2.989990234375,
@@ -23364,6 +23421,13 @@ const float txlpf1_den_coef[11] =
0.00048828125
};
+const Word16 txlpf1_den_coef_fx[11] = /* Q13 */
+{
+ 8192,-18945, 31613,-31149, 24494,
+ -12753, 5528, -1436, 347, -25,
+ 4,
+};
+
const float txhpf1_num_coef[11] =
{
0.016845703125, -0.024169921875, 0.062744140625, -0.0831298828125, 0.1124267578125,
@@ -23371,25 +23435,52 @@ const float txhpf1_num_coef[11] =
0.016845703125
};
+const Word16 txhpf1_num_coef_fx[11] = /* Q13 */
+{
+ 138, -198, 514, -681, 921,
+ -964, 921, -681, 514, -198,
+ 138,
+};
+
const float txhpf1_den_coef[11] =
{
1, 2.3126220703125, 3.8590087890625, 3.8023681640625, 2.989990234375, 1.5567626953125,
0.6748046875, 0.17529296875, 0.0423583984375, 0.0030517578125, 0.00048828125
};
+
+const Word16 txhpf1_den_coef_fx[11] = /* Q13 */
+{
+ 8192, 18945, 31613, 31149, 24494,
+ 12753, 5528, 1436, 347, 25,
+ 4,
+};
+
/* NELP filter coefficients */
-const float bp1_num_coef_nb_fx_order7[8] =
+const float bp1_num_coef_nb_fx_order7_flt[8] =
{
0.180780569293627f, 0.821512462016641f, 1.901786162198923f, 2.798216464912205f,
2.798216464912205f, 1.901786162198923f, 0.821512462016641f, 0.180780569293627f
};
-const float bp1_den_coef_nb_fx_order7[8] =
+const Word16 bp1_num_coef_nb_fx_order7[8] =
+{
+ /* Q = BP1_COEF_NB_QF_ORDER7 = 13 */
+ 1481, 6730, 15579, 22923, 22923, 15579, 6730, 1481,
+
+};
+
+const float bp1_den_coef_nb_fx_order7_flt[8] =
{
1.0f, 1.972212566911875f, 2.906981567843655f, 2.667903533650106f,
1.784691945273023f, 0.807367818229743f, 0.232764318343094f, 0.032669566591295f
};
+const Word16 bp1_den_coef_nb_fx_order7[8] =
+{
+ /* Q = BP1_COEF_NB_QF_ORDER7 = 13 */
+ 8192, 16156, 23814, 21855, 14620, 6614, 1907, 268,
+};
/* order 8 LPF for nelp frames when non-native sampling freq inputs used with -max_band NB */
/* used to suppress frequencies above 4kHz present at the output of filters in pre_proc() */
@@ -26947,7 +27038,7 @@ const ParamsBitMap tnsSWBTCX20FilterCoeffBitMap =
{
1,
{
- { 0, GetSWBTCX20TnsFilterCoeffBits, TRUE, GetTnsFilterCoeff, SetTnsFilterCoeff, EncodeSWBTCX20TnsFilterCoeff, DecodeSWBTCX20TnsFilterCoeff, NULL } /* TNS filter coefficients */
+ { 0, GetSWBTCX20TnsFilterCoeffBits, TRUE, GetTnsFilterCoeff, SetTnsFilterCoeff, EncodeSWBTCX20TnsFilterCoeff, DecodeSWBTCX20TnsFilterCoeff_flt, NULL } /* TNS filter coefficients */
}
};
@@ -26955,7 +27046,7 @@ const ParamsBitMap tnsSWBTCX10FilterCoeffBitMap =
{
1,
{
- { 0, GetSWBTCX10TnsFilterCoeffBits, TRUE, GetTnsFilterCoeff, SetTnsFilterCoeff, EncodeSWBTCX10TnsFilterCoeff, DecodeSWBTCX10TnsFilterCoeff, NULL } /* TNS filter coefficients */
+ { 0, GetSWBTCX10TnsFilterCoeffBits, TRUE, GetTnsFilterCoeff, SetTnsFilterCoeff, EncodeSWBTCX10TnsFilterCoeff, DecodeSWBTCX10TnsFilterCoeff_flt, NULL } /* TNS filter coefficients */
}
};
@@ -26963,7 +27054,7 @@ const ParamsBitMap tnsSWBTCX20FilterBitMap =
{
1,
{
- { 0, GetTnsFilterOrderBitsSWBTCX20, FALSE, GetTnsFilterOrder, SetTnsFilterOrder, EncodeTnsFilterOrderSWBTCX20, DecodeTnsFilterOrderSWBTCX20, &tnsSWBTCX20FilterCoeffBitMap } /* TNS filter order */
+ { 0, GetTnsFilterOrderBitsSWBTCX20, FALSE, GetTnsFilterOrder, SetTnsFilterOrder, EncodeTnsFilterOrderSWBTCX20, DecodeTnsFilterOrderSWBTCX20_flt, &tnsSWBTCX20FilterCoeffBitMap } /* TNS filter order */
}
};
@@ -26971,7 +27062,7 @@ const ParamsBitMap tnsSWBTCX10FilterBitMap =
{
1,
{
- { 0, GetTnsFilterOrderBitsSWBTCX10, FALSE, GetTnsFilterOrder, SetTnsFilterOrder, EncodeTnsFilterOrderSWBTCX10, DecodeTnsFilterOrderSWBTCX10, &tnsSWBTCX10FilterCoeffBitMap } /* TNS filter order */
+ { 0, GetTnsFilterOrderBitsSWBTCX10, FALSE, GetTnsFilterOrder, SetTnsFilterOrder, EncodeTnsFilterOrderSWBTCX10, DecodeTnsFilterOrderSWBTCX10_flt, &tnsSWBTCX10FilterCoeffBitMap } /* TNS filter order */
}
};
@@ -26979,7 +27070,7 @@ const ParamsBitMap tnsSWBTCX20BitMap =
{
1,
{
- { 1, NULL, FALSE, GetNumOfTnsFilters, SetNumOfTnsFilters, NULL, NULL, &tnsSWBTCX20FilterBitMap } /* Number of TNS filters */
+ { 1, NULL, FALSE, GetNumOfTnsFilters_flt, SetNumOfTnsFilters_flt, NULL, NULL, &tnsSWBTCX20FilterBitMap } /* Number of TNS filters */
}
};
@@ -26996,7 +27087,7 @@ const ParamsBitMap tnsSWBTCX10BitMap =
{
1,
{
- { 1, NULL, FALSE, GetNumOfTnsFilters, SetNumOfTnsFilters, NULL, NULL, &tnsSWBTCX10FilterBitMap } /* Number of TNS filters */
+ { 1, NULL, FALSE, GetNumOfTnsFilters_flt, SetNumOfTnsFilters_flt, NULL, NULL, &tnsSWBTCX10FilterBitMap } /* Number of TNS filters */
}
};
@@ -27013,7 +27104,7 @@ const ParamsBitMap tnsWBTCX20FilterCoeffBitMap =
{
1,
{
- { 0, GetWBTCX20TnsFilterCoeffBits, TRUE, GetTnsFilterCoeff, SetTnsFilterCoeff, EncodeWBTCX20TnsFilterCoeff, DecodeWBTCX20TnsFilterCoeff, NULL } /* TNS filter coefficients */
+ { 0, GetWBTCX20TnsFilterCoeffBits, TRUE, GetTnsFilterCoeff, SetTnsFilterCoeff, EncodeWBTCX20TnsFilterCoeff, DecodeWBTCX20TnsFilterCoeff_flt, NULL } /* TNS filter coefficients */
}
};
@@ -27022,7 +27113,7 @@ const ParamsBitMap tnsWBTCX20FilterBitMap =
{
1,
{
- { 0, GetTnsFilterOrderBits, FALSE, GetTnsFilterOrder, SetTnsFilterOrder, EncodeTnsFilterOrder, DecodeTnsFilterOrder, &tnsWBTCX20FilterCoeffBitMap } /* TNS filter order */
+ { 0, GetTnsFilterOrderBits, FALSE, GetTnsFilterOrder, SetTnsFilterOrder, EncodeTnsFilterOrder, DecodeTnsFilterOrder_flt, &tnsWBTCX20FilterCoeffBitMap } /* TNS filter order */
}
};
@@ -27042,7 +27133,7 @@ const ParamsBitMap tnsOnWhiteSWBTCX20BitMap =
2,
{
{ 1, NULL, TRUE, GetTnsOnWhite, SetTnsOnWhite, NULL, NULL, NULL }, /* TNS Enabled/Disable */
- { 1, NULL, FALSE, GetNumOfTnsFilters, SetNumOfTnsFilters, NULL, NULL, &tnsSWBTCX20FilterBitMap }
+ { 1, NULL, FALSE, GetNumOfTnsFilters_flt, SetNumOfTnsFilters_flt, NULL, NULL, &tnsSWBTCX20FilterBitMap }
}
};
@@ -27059,7 +27150,7 @@ const ParamsBitMap tnsOnWhiteSWBTCX10BitMap =
2,
{
{ 1, NULL, TRUE, GetTnsOnWhite, SetTnsOnWhite, NULL, NULL, NULL }, /* TNS on whitened spectra */
- { 1, NULL, FALSE, GetNumOfTnsFilters, SetNumOfTnsFilters, NULL, NULL, &tnsSWBTCX10FilterBitMap }
+ { 1, NULL, FALSE, GetNumOfTnsFilters_flt, SetNumOfTnsFilters_flt, NULL, NULL, &tnsSWBTCX10FilterBitMap }
}
};
@@ -27076,7 +27167,7 @@ const ParamsBitMap tnsEnabledOnWhiteSWBTCX10BitMap =
/**
* 4 bit resolution TNS coefficients.
*/
-const float tnsCoeff4[16]=
+const float tnsCoeff4_flt[16]=
{
-0.99573418F, /* = sin(-8*(EVS_PI/2.0)/(8 + 0.5)) */
-0.96182564F, /* = sin(-7*(EVS_PI/2.0)/(8 + 0.5)) */
@@ -27096,6 +27187,26 @@ const float tnsCoeff4[16]=
0.99452190F /* = sin(7*(EVS_PI/2.0)/(8 - 0.5)) */
};
+const Word16 tnsCoeff4[16] =
+{
+ -32628/*-0.99573418F Q15*/, /* = sin(-8*(PI/2.0)/(8 + 0.5)) */
+ -31517/*-0.96182564F Q15*/, /* = sin(-7*(PI/2.0)/(8 + 0.5)) */
+ -29333/*-0.89516329F Q15*/,
+ -26149/*-0.79801723F Q15*/,
+ -22076/*-0.67369564F Q15*/,
+ -17250/*-0.52643216F Q15*/,
+ -11837/*-0.36124167F Q15*/,
+ -6021/*-0.18374952F Q15*/, /* = sin(-1*(PI/2.0)/(8 + 0.5)) */
+ 0/* 0.00000000F Q15*/, /* = sin(0*(PI/2.0)/(8 + 0.5)) */
+ 6813/* 0.20791169F Q15*/, /* = sin(1*(PI/2.0)/(8 - 0.5)) */
+ 13328/* 0.40673664F Q15*/,
+ 19261/* 0.58778525F Q15*/,
+ 24351/* 0.74314483F Q15*/,
+ 28378/* 0.86602540F Q15*/,
+ 31164/* 0.95105652F Q15*/, /* = sin(6*(PI/2.0)/(8 - 0.5)) */
+ 32588/* 0.99452190F Q15*/ /* = sin(7*(PI/2.0)/(8 - 0.5)) */
+};
+
/*----------------------------------------------------------------------------------*
* IGF settings for each bitrate
@@ -29766,5 +29877,8 @@ const Word16 cos_diff_table[512] =
};
+const Word32 bwMode2fs[4] = { 8000, 16000, 32000, 48000 };
+
+
/* clang-format on */
diff --git a/lib_com/rom_com.h b/lib_com/rom_com.h
index 08abfedda04a8108bf63ad31cac6b40727fb17fa..6f02594721c8d4258526fa073163ea2b3248849d 100644
--- a/lib_com/rom_com.h
+++ b/lib_com/rom_com.h
@@ -1047,7 +1047,10 @@ extern const Word16 env_stab_tp_fx[2][2];
/*----------------------------------------------------------------------------------*
* SWB BWE for LR MDCT core
*----------------------------------------------------------------------------------*/
+
extern const float gain_table_SWB_BWE[NB_SWB_SUBBANDS];
+extern const Word16 gain_table_SWB_BWE_fx[NB_SWB_SUBBANDS];
+
/* HQ_NORMAL mode */
extern const int16_t bits_lagIndices_modeNormal[NB_SWB_SUBBANDS];
extern const int16_t subband_offsets_12KBPS[NB_SWB_SUBBANDS];
@@ -1070,19 +1073,47 @@ extern const int16_t subband_search_offsets_16p4kbps_Har[NB_SWB_SUBBANDS_HAR_SEA
/* NELP filter coefficients */
extern const float bp1_num_coef_wb[5];
+extern const Word16 bp1_num_coef_wb_fx[5];
+
extern const float bp1_den_coef_wb[5];
+extern const Word16 bp1_den_coef_wb_fx[5];
+
extern const float shape1_num_coef[11];
+extern const Word16 shape1_num_coef_fx[11];
+
extern const float shape1_den_coef[11];
+extern const Word16 shape1_den_coef_fx[11];
+
extern const float shape2_num_coef[11];
+extern const Word16 shape2_num_coef_fx[11];
+
extern const float shape2_den_coef[11];
+extern const Word16 shape2_den_coef_fx[11];
+
extern const float shape3_num_coef[11];
+extern const Word16 shape3_num_coef_fx[11];
+
extern const float shape3_den_coef[11];
+extern const Word16 shape3_den_coef_fx[11];
+
extern const float txlpf1_num_coef[11];
+extern const Word16 txlpf1_num_coef_fx[11];
+
extern const float txlpf1_den_coef[11];
+extern const Word16 txlpf1_den_coef_fx[11];
+
extern const float txhpf1_num_coef[11];
+extern const Word16 txhpf1_num_coef_fx[11];
+
extern const float txhpf1_den_coef[11];
-extern const float bp1_num_coef_nb_fx_order7[8];
-extern const float bp1_den_coef_nb_fx_order7[8];
+extern const Word16 txhpf1_den_coef_fx[11];
+
+extern const float bp1_num_coef_nb_fx_order7_flt[8];
+extern const Word16 bp1_num_coef_nb_fx_order7[8];
+
+extern const float bp1_den_coef_nb_fx_order7_flt[8];
+extern const Word16 bp1_den_coef_nb_fx_order7[8];
+
extern const float num_nelp_lp[NELP_LP_ORDER + 1];
extern const float den_nelp_lp[NELP_LP_ORDER + 1];
@@ -1574,7 +1605,8 @@ extern const Coding codesTnsOrderTCX10[];
extern const Coding codesTnsOrder[];
extern const int16_t nTnsOrderCodes;
-extern const float tnsCoeff4[16];
+extern const float tnsCoeff4_flt[16];
+extern const Word16 tnsCoeff4[16];
/*----------------------------------------------------------------------------------*
* IGF settings for each bitrate
@@ -1680,5 +1712,5 @@ extern const short dsDiracsTab[65];
extern const Word16 pwf_fx[17];
extern const Word32 inverse_table[];
extern const Word16 cos_diff_table[512];
-
+extern const Word32 bwMode2fs[4];
#endif
diff --git a/lib_com/stat_com.h b/lib_com/stat_com.h
index 819d5837c79c54f8e2975de512a5254f578bb266..cd08c64baef3686f3b7cfb6a0902b70398b66a3e 100644
--- a/lib_com/stat_com.h
+++ b/lib_com/stat_com.h
@@ -490,7 +490,7 @@ typedef int16_t ( *TDecodeValue )( struct Decoder_State *st, int16_t index, int1
* @param x the current input value.
* @return the output of the filter.
*/
-typedef float ( *TLinearPredictionFilter )( const int16_t order, const float parCoeff[], float *state, float x );
+typedef float ( *TLinearPredictionFilter_flt )( const int16_t order, const float parCoeff[], float *state, float x );
/** Structure that defines mapping between a parameter and a bitstream. */
typedef struct ParamBitMap
diff --git a/lib_com/tcx_utils.c b/lib_com/tcx_utils.c
index eac1c1cb8280680b39ba91e46d31a1fbb7885400..a72b23bd9dd8dbc8906e5c8b6de59a62d08ec803 100644
--- a/lib_com/tcx_utils.c
+++ b/lib_com/tcx_utils.c
@@ -956,12 +956,12 @@ void InitTnsConfigs(
{
if ( total_brate > ACELP_32k )
{
- InitTnsConfiguration( bwidth, L_frame / 2, &tnsConfig[0][0], igfStopFreq, total_brate, element_mode, MCT_flag );
+ InitTnsConfiguration_flt( bwidth, L_frame / 2, &tnsConfig[0][0], igfStopFreq, total_brate, element_mode, MCT_flag );
}
- InitTnsConfiguration( bwidth, L_frame, &tnsConfig[1][0], igfStopFreq, total_brate, element_mode, MCT_flag );
+ InitTnsConfiguration_flt( bwidth, L_frame, &tnsConfig[1][0], igfStopFreq, total_brate, element_mode, MCT_flag );
- InitTnsConfiguration( bwidth, L_frame + L_frame / 4, &tnsConfig[1][1], igfStopFreq, total_brate, element_mode, MCT_flag );
+ InitTnsConfiguration_flt( bwidth, L_frame + L_frame / 4, &tnsConfig[1][1], igfStopFreq, total_brate, element_mode, MCT_flag );
return;
}
diff --git a/lib_com/tns_base.c b/lib_com/tns_base.c
index d38f032b693e087f8981bcbe3142571a915bcb9b..13aea5208b2ba0177ed8c361234077b7fab378e9 100644
--- a/lib_com/tns_base.c
+++ b/lib_com/tns_base.c
@@ -1,54 +1,24 @@
-/******************************************************************************************************
-
- (C) 2022-2023 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
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
====================================================================================*/
+
#include
#include
+#include
#include "options.h"
+#include "stat_com.h"
#include "cnst.h"
#include "rom_com.h"
-#include "prot.h"
-#include "stat_com.h"
-#include "wmc_auto.h"
-
+#include "prot_fx1.h"
+#include "prot_fx2.h"
+#include "basop_util.h"
/*----------------------------------------------------------------------------
* Local constants
*---------------------------------------------------------------------------*/
-#define HLM_MIN_NRG PCM16_TO_FLT_FAC
+#define HLM_MIN_NRG 32768.0f
#define MAX_SUBDIVISIONS 3
@@ -56,65 +26,121 @@
* Local prototypes
*---------------------------------------------------------------------------*/
+/** Linear prediction analysis/synthesis filter definition.
+ * @param order filter order.
+ * @param parCoeff filter (PARCOR) coefficients.
+ * @param state state of the filter. Must be at least of 'order' size.
+ * @param x the current input value.
+ * @return the output of the filter.
+ */
+typedef Word32 (* TLinearPredictionFilter)(Word16 order, Word16 const parCoeff[], Word32 * state, Word32 x);
-static void Index2Parcor( const int16_t index[], float parCoeff[], const int16_t order );
+/** Inverse quantization for reflection coefficients.
+ *
+ * @param index input quantized values.
+ * @param parCoeff output reflection coefficients.
+ * @param order number of coefficients/values.
+ */
+static void Index2Parcor(Word16 const index[], Word16 parCoeff[], Word16 order);
+
+/** Linear prediction analysis filter.
+ * See TLinearPredictionFilter for details.
+ */
+static Word32 FIRLattice(const Word16 order, const Word16 *parCoeff, Word32 *state, Word32 x);
-static float FIRLattice( const int16_t order, const float *parCoeff, float *state, float x );
+/** Linear prediction synthesis filter.
+ * See TLinearPredictionFilter for details.
+ */
+static Word32 IIRLattice(Word16 order, const Word16 *parCoeff, Word32 *state, Word32 x);
-static float IIRLattice( const int16_t order, const float *parCoeff, float *state, float x );
+/** TNS analysis/synthesis filter.
+ * @param spectrum input spectrum values.
+ * @param numOfLines number of lines in the spectrum.
+ * @param parCoeff filter (PARCOR) coefficients.
+ * @param order filter order.
+ * @param filter function that implements filtering.
+ By this function it is defined whether analysis or synthesis is performed.
+ * @param output filtered output spectrum values.
+ Inplace operation is supported, so it can be equal to spectrum.
+ */
+static void TnsFilter(const Word32 spectrum[], const Word16 numOfLines, const Word16 parCoeff[], const Word16 order, TLinearPredictionFilter filter, Word32 * state, Word32 output[]);
-static void TnsFilter( const float spectrum[], const int16_t numOfLines, const float parCoeff[], const int16_t order, TLinearPredictionFilter filter, float *state, float output[] );
+static void ITF_TnsFilter_fx( const Word32 spectrum[], const Word16 numOfLines, const Word16 A[], /* Q14 */ const Word16 Q_A, const Word16 order, Word32 output[]);
+static void ITF_GetFilterParameters_fx(Word32 rxx[], const Word16 maxOrder, Word16* A, /* Q14 */Word16* Q_A, Word16* predictionGain);
-/*-------------------------------------------------------------------*
- * InitTnsConfiguration()
- *
- *-------------------------------------------------------------------*/
+/********************************/
+/* Interface functions */
+/********************************/
+/** Init TNS configuration.
+ * Fills STnsConfig structure with sensible content.
+ * @param nSampleRate Sampling rate of the input.
+ * @param nFrameLength Frame length.
+ * @param pTnsConfig TNS configuration to be initialized.
+ * @return 0 on success, otherwise 1.
+ */
void InitTnsConfiguration(
- const int16_t bwidth,
- const int16_t frameLength,
- STnsConfig *pTnsConfig,
- const int16_t igfStopFreq,
- const int32_t total_brate,
+ const Word16 bwidth,
+ const Word16 frameLength,
+ STnsConfig * pTnsConfig,
+ const Word16 igfStopFreq,
+ const Word32 total_brate,
const int16_t element_mode,
- const int16_t MCT_flag )
+ const int16_t is_mct
+)
{
- int32_t nSampleRate;
- int16_t iFilter;
- int16_t *startLineFilter = &pTnsConfig->iFilterBorders[1];
-
- nSampleRate = inner_frame_tbl[bwidth] * FRAMES_PER_SEC;
+ Word16 iFilter = 0;
+ Word16 * startLineFilter;
+ Word32 L_tmp;
+ Word32 nSampleRate;
+ Word16 s1;
+ Word16 s2;
+#ifndef ADD_IVAS_TNS
+ (void)(element_mode);
+ (void)(is_mct);
+#endif
+ nSampleRate = bwMode2fs[bwidth];
+ move32();
+ startLineFilter = &pTnsConfig->iFilterBorders[1];
/* Sanity checks */
- assert( ( nSampleRate > 0 ) && ( frameLength > 0 ) && ( pTnsConfig != NULL ) );
- if ( ( nSampleRate <= 0 ) || ( frameLength <= 0 ) || ( pTnsConfig == NULL ) )
+ assert((nSampleRate > 0) && (frameLength > 0) && (pTnsConfig != NULL));
+ if ((nSampleRate <= 0) || (frameLength <= 0) || (pTnsConfig == NULL))
{
return /*TNS_FATAL_ERROR*/;
}
- /* WMOPS: All initializations are either for safety or static (tables) and thus not to be counted */
+
/* Initialize TNS filter flag and maximum order */
- pTnsConfig->maxOrder = TNS_MAX_FILTER_ORDER;
- if ( total_brate <= ACELP_32k )
- {
- pTnsConfig->nMaxFilters = sizeof( tnsParametersIGF32kHz_LowBR ) / sizeof( tnsParametersIGF32kHz_LowBR[0] );
+ move16();
+ pTnsConfig->maxOrder = TNS_MAX_FILTER_ORDER;
+ IF (LE_32(total_brate, ACELP_32k))
+ {
+ move16();
+ move16();
+ pTnsConfig->nMaxFilters = sizeof(tnsParametersIGF32kHz_LowBR)/sizeof(tnsParametersIGF32kHz_LowBR[0]);
pTnsConfig->pTnsParameters = tnsParametersIGF32kHz_LowBR;
}
- else
+ ELSE
{
- if ( nSampleRate > 32000 && nSampleRate == 100 * frameLength )
+ test();
+ IF (GT_32(nSampleRate,32000)&&EQ_32(nSampleRate,L_mult0(100,frameLength)))
{
- pTnsConfig->nMaxFilters = sizeof( tnsParameters48kHz_grouped ) / sizeof( tnsParameters48kHz_grouped[0] );
+ move16();
+ pTnsConfig->nMaxFilters = sizeof(tnsParameters48kHz_grouped)/sizeof(tnsParameters48kHz_grouped[0]);
+ move16();
pTnsConfig->pTnsParameters = tnsParameters48kHz_grouped;
}
- else if ( nSampleRate > 16000 )
+ ELSE
+ IF ( GT_32(nSampleRate,INT_FS_16k))
{
- if ( ( element_mode > IVAS_SCE ) && ( total_brate >= ( MCT_flag ? IVAS_32k : IVAS_48k ) ) )
+#ifdef ADD_IVAS_TNS
+ if ((element_mode > IVAS_SCE) && (total_brate >= (is_mct ? IVAS_32k : IVAS_48k)))
{
- pTnsConfig->nMaxFilters = sizeof( tnsParameters32kHz_Stereo ) / sizeof( tnsParameters32kHz_Stereo[0] );
- if ( nSampleRate == 100 * frameLength ) /* sub-frame length is <= 10 ms */
+ pTnsConfig->nMaxFilters = sizeof(tnsParameters32kHz_Stereo) / sizeof(tnsParameters32kHz_Stereo[0]);
+ if (nSampleRate == 100 * frameLength) /* sub-frame length is <= 10 ms */
{
pTnsConfig->pTnsParameters = tnsParameters32kHz_grouped;
}
@@ -124,398 +150,693 @@ void InitTnsConfiguration(
}
}
else
+#endif
{
- pTnsConfig->nMaxFilters = sizeof( tnsParameters32kHz ) / sizeof( tnsParameters32kHz[0] );
- if ( nSampleRate == 100 * frameLength ) /* sub-frame length is <= 10 ms */
+
+ move16();
+ pTnsConfig->nMaxFilters = sizeof(tnsParameters32kHz) / sizeof(tnsParameters32kHz[0]);
+
+ move16();
+ pTnsConfig->pTnsParameters = tnsParameters32kHz;
+
+ if (EQ_32(nSampleRate, L_mult0(100, frameLength))) /* sub-frame length is <= 10 ms */
{
+ move16();
pTnsConfig->pTnsParameters = tnsParameters32kHz_grouped;
}
- else
- {
- pTnsConfig->pTnsParameters = tnsParameters32kHz;
- }
}
}
- else
+ ELSE
{
- if ( nSampleRate == 100 * frameLength ) /* sub-frame length is <= 10 ms */
+ IF ( EQ_32(nSampleRate, L_mult0(100, frameLength))) /* sub-frame length is <= 10 ms */
{
- pTnsConfig->nMaxFilters = sizeof( tnsParameters16kHz_grouped ) / sizeof( tnsParameters16kHz_grouped[0] );
+ move16();
+ move16();
+ pTnsConfig->nMaxFilters = sizeof(tnsParameters16kHz_grouped)/sizeof(tnsParameters16kHz_grouped[0]);
pTnsConfig->pTnsParameters = tnsParameters16kHz_grouped;
}
- else
+ ELSE
{
- pTnsConfig->nMaxFilters = sizeof( tnsParameters16kHz ) / sizeof( tnsParameters16kHz[0] );
+ move16();
+ move16();
+ pTnsConfig->nMaxFilters = sizeof(tnsParameters16kHz)/sizeof(tnsParameters16kHz[0]);
pTnsConfig->pTnsParameters = tnsParameters16kHz;
}
}
}
- assert( pTnsConfig->nMaxFilters <= TNS_MAX_NUM_OF_FILTERS );
+ assert(pTnsConfig->nMaxFilters <= TNS_MAX_NUM_OF_FILTERS);
/* Set starting MDCT line for each filter based on the starting frequencies from the TNS table */
- for ( iFilter = 0; iFilter < pTnsConfig->nMaxFilters; iFilter++ )
+
+ FOR (iFilter = 0; iFilter < pTnsConfig->nMaxFilters; iFilter++)
{
- assert( pTnsConfig->pTnsParameters[iFilter].startLineFrequency < 0.5f * nSampleRate );
- startLineFilter[iFilter] = (int16_t) ( ( frameLength * 2 * pTnsConfig->pTnsParameters[iFilter].startLineFrequency ) / nSampleRate );
+ assert(pTnsConfig->pTnsParameters[iFilter].startLineFrequency < 0.5f*nSampleRate);
+ assert(nSampleRate <= 96000);
+ move16();
+ startLineFilter[iFilter] = divide3232(L_mult0(frameLength, pTnsConfig->pTnsParameters[iFilter].startLineFrequency), L_shl(nSampleRate,14));
}
- if ( igfStopFreq > 0 )
+
+ IF (igfStopFreq > 0)
{
- pTnsConfig->iFilterBorders[0] = (int16_t) ( ( frameLength * 2 * igfStopFreq ) / nSampleRate );
+ L_tmp = L_mult(frameLength, igfStopFreq);
+ s1 = sub(norm_l(L_tmp), 1);
+ s2 = norm_l(nSampleRate);
+
+ move16();
+ pTnsConfig->iFilterBorders[0] = shr( div_l( L_shl(L_tmp, s1), extract_h(L_shl(nSampleRate, s2)) ) , sub(WORD16_BITS-1, sub(s2, s1)));
+
}
- else
+ ELSE
{
+ move16();
pTnsConfig->iFilterBorders[0] = frameLength;
}
-
+#ifdef ADD_IVAS_TNS
pTnsConfig->allowTnsOnWhite = 0;
-
- return /*TNS_NO_ERROR*/;
+#endif
+ return; /*TNS_NO_ERROR;*/
}
-
/*-------------------------------------------------------------------*
* ApplyTnsFilter()
*
*-------------------------------------------------------------------*/
void ApplyTnsFilter(
- STnsConfig const *pTnsConfig,
- STnsData const *pTnsData,
- float spectrum[],
- const int16_t fIsAnalysis )
+ STnsConfig const * pTnsConfig,
+ STnsData const * pTnsData,
+ Word32 spectrum[],
+ const Word8 fIsAnalysis
+)
{
TLinearPredictionFilter filter;
- float state[TNS_MAX_FILTER_ORDER];
- int16_t iFilter;
- int16_t stopLine, startLine;
- const int16_t *pBorders;
+ Word32 state[TNS_MAX_FILTER_ORDER];
+ Word16 iFilter;
+ Word16 stopLine, startLine;
+ Word16 const * pBorders;
+
- filter = fIsAnalysis ? FIRLattice : IIRLattice;
- set_f( state, 0, TNS_MAX_FILTER_ORDER );
+ move16();
+ filter = IIRLattice;
+ if (fIsAnalysis)
+ {
+ move16();
+ filter = FIRLattice;
+ }
+ set32_fx(state, 0, TNS_MAX_FILTER_ORDER);
+ move16();
pBorders = pTnsConfig->iFilterBorders;
- for ( iFilter = pTnsConfig->nMaxFilters - 1; iFilter >= 0; iFilter-- )
+ FOR (iFilter = pTnsConfig->nMaxFilters-1; iFilter >= 0; iFilter--)
{
- float parCoeff[TNS_MAX_FILTER_ORDER];
- const STnsFilter *pFilter = &pTnsData->filter[iFilter];
+ Word16 parCoeff[TNS_MAX_FILTER_ORDER];
+ const STnsFilter * pFilter;
- set_f( parCoeff, 0, TNS_MAX_FILTER_ORDER );
+
+ move16();
+ move16();
+ move16();
+ pFilter = &pTnsData->filter[iFilter];
stopLine = pBorders[iFilter];
- startLine = pBorders[iFilter + 1];
+ startLine = pBorders[iFilter+1];
+
+ Index2Parcor(pFilter->coefIndex, parCoeff, pFilter->order);
+
+ TnsFilter(&spectrum[startLine], stopLine-startLine,
+ parCoeff, pFilter->order,
+ filter, state,
+ &spectrum[startLine]);
+
+ }
+
+ move16();
+
+ return /*result*/;
+}
+
+/*-------------------------------------------------------------------*
+ * ITF_Apply()
+ *
+ *-------------------------------------------------------------------*/
+
+void ITF_Apply_fx(
+ Word32 spectrum[],
+ Word16 startLine,
+ Word16 stopLine,
+ const Word16* A,
+ Word16 Q_A,
+ Word16 order
+)
+{
+
+ ITF_TnsFilter_fx(&spectrum[startLine],(Word16)(stopLine-startLine), A, Q_A, (Word16)order, &spectrum[startLine]);
+
+ return /*TNS_NO_ERROR*/;
+}
+/*-------------------------------------------------------------------*
+* ITF_Detect()
+*
+*
+*-------------------------------------------------------------------*/
+
+Word16 ITF_Detect_fx(
+ const Word32 pSpectrum[],
+ const Word16 startLine,
+ const Word16 stopLine,
+ const Word16 maxOrder,
+ Word16* A,
+ Word16* Q_A,
+ Word16* predictionGain,
+ Word16* curr_order,
+ Word16 Q
+)
+{
+
+ Word16 spectrumLength;
+ Word16 const nSubdivisions = MAX_SUBDIVISIONS;
+ Word16 iSubdivisions;
+ Word16 iStartLine;
+ Word16 iEndLine;
+ Word16 facs[MAX_SUBDIVISIONS];
+ Word16 facs_e[MAX_SUBDIVISIONS]; /* exponents of facs[][] */
+ Word16 shifts[MAX_SUBDIVISIONS];
+ Word16 tmp, headroom, shift;
+ Word32 rxx[ITF_MAX_FILTER_ORDER+1];
+ Word16 lag;
+ Word32 L_tmp, tmp32;
+ Word16 tmpbuf[325];
+ Word16 n, i;
+#ifdef BASOP_NOGLOB_DECLARE_LOCAL
+ Flag Overflow = 0;
+#endif
+
+ move16();
+ move16();
+ move16();
+
+ if (maxOrder <= 0)
+ {
+ return 0;
+ }
+
+ /* Calculate norms for each spectrum part */
+ FOR (iSubdivisions = 0; iSubdivisions < nSubdivisions; iSubdivisions++)
+ {
+ assert((nSubdivisions == 1) || (nSubdivisions == 3));
+
+ tmp = sub(stopLine, startLine);
+ iStartLine = imult1616(tmp, iSubdivisions);
+ iEndLine = add(iStartLine, tmp);
+
+ if (EQ_16(nSubdivisions, 3))iStartLine=mult(iStartLine,0x2AAB);
+ iStartLine = add(iStartLine, startLine);
+
+ if (EQ_16(nSubdivisions, 3))iEndLine=mult(iEndLine,0x2AAB);
+ iEndLine = add(iEndLine, startLine);
+ headroom = getScaleFactor32(pSpectrum+iStartLine-IGF_START_MN, sub(iEndLine, iStartLine));
+ /* Calculate norm of spectrum band */
+ L_tmp = Norm32Norm(pSpectrum+iStartLine-IGF_START_MN, headroom, sub(iEndLine, iStartLine), &shift);
+
+ /* Check threshold HLM_MIN_NRG */
+ BASOP_SATURATE_WARNING_OFF_EVS;
+#ifdef BASOP_NOGLOB
+ tmp32 = L_sub(L_shl_o(L_tmp, sub(shift, 24-Q), &Overflow), 4194304l/*HLM_MIN_NRG Q7*/);
+#else /* BASOP_NOGLOB */
+ tmp32 = L_sub(L_shl(L_tmp, sub(shift, 24-Q)), 4194304l/*HLM_MIN_NRG Q7*/);
+#endif
+ BASOP_SATURATE_WARNING_ON_EVS;
+
+ /* get pre-shift for autocorrelation */
+ tmp = sub(shift, norm_l(L_tmp)); /* exponent for normalized L_tmp */
+ tmp = shr(sub(1, tmp), 1); /* pre-shift to apply before autocorrelation */
+ shifts[iSubdivisions] = s_min(tmp, headroom);
+ move16();
+
+ /* calc normalization factor */
+ facs[iSubdivisions] = 0;
+ move16();
+ facs_e[iSubdivisions] = 0;
+ move16();
+
+ if (tmp32 > 0)
+ {
+ facs[iSubdivisions] = 0x7FFF;
+ move16(); /* normalization not needed for one subdivision */
+ }
+
+ test();
+ IF ((tmp32 > 0) && (GT_16(nSubdivisions, 1)))
+ {
+ move16();
+ facs_e[iSubdivisions] = shl(sub(tmp, shifts[iSubdivisions]), 1);
+
+ tmp = sub(1, shl(tmp, 1)); /* exponent of autocorrelation */
+ L_tmp = L_shl(L_tmp, sub(shift, tmp)); /* shift L_tmp to that exponent */
- Index2Parcor( pFilter->coefIndex, parCoeff, pFilter->order );
+ /* calc factor (with 2 bits headroom for sum of 3 subdivisions) */
+ facs[iSubdivisions] = div_s(0x2000, round_fx(L_tmp)); /* L_tmp is >= 0x2000000 */ move16();
+ }
- TnsFilter( &spectrum[startLine], stopLine - startLine, parCoeff, pFilter->order, filter, state, &spectrum[startLine] );
}
- return /*( pTnsData->nFilters < 0 ) ? TNS_FATAL_ERROR : TNS_NO_ERROR*/;
+ /* Calculate normalized autocorrelation for spectrum subdivision and get filter parameters based on it */
+ set32_fx(rxx, 0, ITF_MAX_FILTER_ORDER+1);
+
+ spectrumLength = sub(stopLine, startLine);
+
+ FOR (iSubdivisions = 0; iSubdivisions < nSubdivisions; iSubdivisions++)
+ {
+ IF ( facs[iSubdivisions] == 0 )
+ {
+ BREAK;
+ }
+
+
+ assert((nSubdivisions == 1) || (nSubdivisions == 3));
+
+ iStartLine = imult1616(spectrumLength, iSubdivisions);
+ iEndLine = add(iStartLine, spectrumLength);
+
+ if (EQ_16(nSubdivisions, 3))iStartLine=mult(iStartLine,0x2AAB);
+ iStartLine = add(iStartLine, startLine);
+
+ if (EQ_16(nSubdivisions, 3))iEndLine=mult(iEndLine,0x2AAB);
+ iEndLine = add(iEndLine, startLine);
+
+
+ move16();
+ shift = shifts[iSubdivisions];
+
+ n = sub(iEndLine, iStartLine);
+ assert(n < (Word16)(sizeof(tmpbuf)/sizeof(Word16)));
+ FOR (i = 0; i < n; i++)
+ {
+ tmpbuf[i] = round_fx(L_shl(pSpectrum[iStartLine+i-IGF_START_MN], shift));
+ }
+
+ FOR (lag = 0; lag <= maxOrder; lag++)
+ {
+ n = sub(sub(iEndLine,lag), iStartLine);
+
+ {
+ Word64 tmp64 = 0;
+ FOR (i = 0; i < n; i++)
+ {
+ tmp64 = W_mac0_16_16(tmp64, tmpbuf[i], tmpbuf[i+lag]);
+ }
+ L_tmp = W_sat_l(tmp64);
+ }
+
+ L_tmp = Mpy_32_16_1(L_tmp, facs[iSubdivisions]);
+ L_tmp = L_shl(L_tmp, facs_e[iSubdivisions]);
+
+ rxx[lag] = L_add(rxx[lag], L_tmp);
+ move32();
+ }
+
+ }
+
+ IF ( EQ_16(iSubdivisions,nSubdivisions)) /* meaning there is no subdivision with low energy */
+ {
+ /* Limit the maximum order to spectrum length/4 */
+ ITF_GetFilterParameters_fx(rxx, s_min (maxOrder, shr(spectrumLength,2)), A, Q_A, predictionGain);
+
+ *curr_order = maxOrder;
+ }
+
+ return 1;
}
-/*********************************************************************************************/
-/* Definitions of functions used in the mapping between TNS parameters and a bitstream. */
-/*********************************************************************************************/
+/* Helper functions for Hufmann table coding */
-/* Helper functions for hufmann table coding */
/** Get number of bits from a Huffman table.
- * The table must be sorted by values.
- */
-static int16_t GetBitsFromTable( int16_t value, const Coding codes[], const int16_t nSize )
+ * The table must be sorted by values.
+ */
+static Word16 GetBitsFromTable(const Word16 value, const Coding codes[], const Word16 nSize)
{
- (void) nSize;
- assert( ( value >= 0 ) && ( value < nSize ) && ( nSize >= 0 ) && ( nSize <= 256 ) );
- return codes[value].nBits;
+ (void)nSize;
+ assert((value >= 0) && (value < nSize) && (nSize >= 0) && (nSize <= 256));
+
+ move16();
+ cast16();
+ return (Word16)codes[value].nBits;
}
/** Get the code for a value from a Huffman table.
- * The table must be sorted by values.
- */
-static int16_t EncodeUsingTable( int16_t value, const Coding codes[], const int16_t nSize )
+ * The table must be sorted by values.
+ */
+static Word16 EncodeUsingTable(const Word16 value, const Coding codes[], const Word16 nSize)
{
- (void) nSize;
- assert( ( value >= 0 ) && ( value < nSize ) && ( nSize >= 0 ) && ( nSize <= 256 ) );
+ (void)nSize;
+ assert((value >= 0) && (value < nSize) && (nSize >= 0) && (nSize <= 256));
+
+ move16();
return codes[value].code;
}
+
/** Decode a value from a bitstream using a Huffman table. */
-static int16_t DecodeUsingTable( Decoder_State *st, int16_t *pValue, const Coding codes[], const int16_t nSize )
+static Word16 DecodeUsingTable(Decoder_State *st, Word16 * pValue, const Coding codes[], const Word16 nSize)
{
- uint16_t code = 0;
- uint8_t nBits = 0;
- int16_t valueIndex = nSize;
+ Word16 code = 0;
+ Word16 nBits = 0;
+ Word16 valueIndex;
+
+ assert((nSize >= 0) && (nSize <= 256));
- assert( ( nSize >= 0 ) && ( nSize <= 256 ) );
- /* Variable initialization. All are required! */
- while ( valueIndex == nSize )
+
+ move16();
+ valueIndex = nSize;
+
+
+ WHILE (valueIndex == nSize)
{
- code = ( code << 1 ) + get_next_indice( st, 1 );
- ++nBits;
- if ( nBits > nSize || nBits > 16 )
+ code = add(shl(code,1), get_next_indice_fx(st, 1));
+ nBits = add(nBits,1);
+ if (nBits > nSize || nBits > 16)
{
st->BER_detect = 1;
*pValue = 0;
+
return -1;
}
- for ( valueIndex = 0; valueIndex < nSize; valueIndex++ )
+
+ FOR (valueIndex = 0; valueIndex < nSize; valueIndex++)
{
- if ( codes[valueIndex].nBits == nBits )
+
+ IF ( s_and((Word16)EQ_16(codes[valueIndex].nBits,nBits),(Word16)EQ_16(codes[valueIndex].code,code)))
{
- if ( codes[valueIndex].code == code )
- {
- break;
- }
+ BREAK;
}
}
- /* Loop condition */
- }
- if ( valueIndex < nSize )
+ }
+ if (valueIndex < nSize)
{
- *pValue = codes[valueIndex].value;
+ *pValue = (Word16)codes[valueIndex].value;
}
else
{
st->BER_detect = 1;
*pValue = 0;
+
return -1;
}
return nBits;
}
+
/* TNS filter coefficients */
-void const *GetTnsFilterCoeff( void const *p, const int16_t index, int16_t *pValue )
+void const * GetTnsFilterCoeff(void const * p, const Word16 index, Word16 * pValue)
{
- *pValue = ( (int16_t const *) p )[index] + INDEX_SHIFT;
+ *pValue = ((Word16 const *)p)[index] + INDEX_SHIFT;
return NULL;
}
-void *SetTnsFilterCoeff( void *p, const int16_t index, const int16_t value )
+void * SetTnsFilterCoeff(void * p, const Word16 index, const Word16 value)
{
- ( (int16_t *) p )[index] = value - INDEX_SHIFT;
+ ((Word16 *)p)[index] = sub(value, INDEX_SHIFT);
return NULL;
}
-int16_t GetSWBTCX20TnsFilterCoeffBits( const int16_t value, const int16_t index )
+
+Word16 GetSWBTCX20TnsFilterCoeffBits(const Word16 value, const Word16 index)
{
- assert( ( index >= 0 ) && ( index < nTnsCoeffTables ) );
- return GetBitsFromTable( value, codesTnsCoeffSWBTCX20[index], nTnsCoeffCodes );
+ assert((index >= 0) && (index < nTnsCoeffTables));
+
+ return GetBitsFromTable(value, codesTnsCoeffSWBTCX20[index], nTnsCoeffCodes);
}
-int16_t EncodeSWBTCX20TnsFilterCoeff( const int16_t value, const int16_t index )
+Word16 EncodeSWBTCX20TnsFilterCoeff(const Word16 value, const Word16 index)
{
- assert( ( index >= 0 ) && ( index < nTnsCoeffTables ) );
- return EncodeUsingTable( value, codesTnsCoeffSWBTCX20[index], nTnsCoeffCodes );
+ assert((index >= 0) && (index < nTnsCoeffTables));
+
+ return EncodeUsingTable(value, codesTnsCoeffSWBTCX20[index], nTnsCoeffCodes);
}
-int16_t DecodeSWBTCX20TnsFilterCoeff( Decoder_State *st, const int16_t index, int16_t *pValue )
+Word16 DecodeSWBTCX20TnsFilterCoeff(Decoder_State *st, const Word16 index, Word16 * pValue)
{
- assert( ( index >= 0 ) && ( index < nTnsCoeffTables ) );
- return DecodeUsingTable( st, pValue, codesTnsCoeffSWBTCX20[index], nTnsCoeffCodes );
+ assert((index >= 0) && (index < nTnsCoeffTables));
+
+ return DecodeUsingTable(st, pValue, codesTnsCoeffSWBTCX20[index], nTnsCoeffCodes);
}
-int16_t GetSWBTCX10TnsFilterCoeffBits( const int16_t value, const int16_t index )
+Word16 GetSWBTCX10TnsFilterCoeffBits(const Word16 value, const Word16 index)
{
- assert( ( index >= 0 ) && ( index < nTnsCoeffTables ) );
- return GetBitsFromTable( value, codesTnsCoeffSWBTCX10[index], nTnsCoeffCodes );
+ assert((index >= 0) && (index < nTnsCoeffTables));
+
+ return GetBitsFromTable(value, codesTnsCoeffSWBTCX10[index], nTnsCoeffCodes);
}
-int16_t EncodeSWBTCX10TnsFilterCoeff( const int16_t value, const int16_t index )
+Word16 EncodeSWBTCX10TnsFilterCoeff(const Word16 value, const Word16 index)
{
- assert( ( index >= 0 ) && ( index < nTnsCoeffTables ) );
- return EncodeUsingTable( value, codesTnsCoeffSWBTCX10[index], nTnsCoeffCodes );
+ assert((index >= 0) && (index < nTnsCoeffTables));
+
+ return EncodeUsingTable(value, codesTnsCoeffSWBTCX10[index], nTnsCoeffCodes);
}
-int16_t DecodeSWBTCX10TnsFilterCoeff( Decoder_State *st, const int16_t index, int16_t *pValue )
+Word16 DecodeSWBTCX10TnsFilterCoeff(Decoder_State *st, const Word16 index, Word16 * pValue)
{
- assert( ( index >= 0 ) && ( index < nTnsCoeffTables ) );
- return DecodeUsingTable( st, pValue, codesTnsCoeffSWBTCX10[index], nTnsCoeffCodes );
+ assert((index >= 0) && (index < nTnsCoeffTables));
+
+ return DecodeUsingTable(st, pValue, codesTnsCoeffSWBTCX10[index], nTnsCoeffCodes);
}
-int16_t GetWBTCX20TnsFilterCoeffBits( const int16_t value, const int16_t index )
+Word16 GetWBTCX20TnsFilterCoeffBits(const Word16 value, const Word16 index)
{
- assert( ( index >= 0 ) && ( index < nTnsCoeffTables ) );
- return GetBitsFromTable( value, codesTnsCoeffWBTCX20[index], nTnsCoeffCodes );
+ assert((index >= 0) && (index < nTnsCoeffTables));
+
+ return GetBitsFromTable(value, codesTnsCoeffWBTCX20[index], nTnsCoeffCodes);
}
-int16_t EncodeWBTCX20TnsFilterCoeff( const int16_t value, const int16_t index )
+Word16 EncodeWBTCX20TnsFilterCoeff(const Word16 value, const Word16 index)
{
- assert( ( index >= 0 ) && ( index < nTnsCoeffTables ) );
- return EncodeUsingTable( value, codesTnsCoeffWBTCX20[index], nTnsCoeffCodes );
+ assert((index >= 0) && (index < nTnsCoeffTables));
+
+ return EncodeUsingTable(value, codesTnsCoeffWBTCX20[index], nTnsCoeffCodes);
}
-int16_t DecodeWBTCX20TnsFilterCoeff( Decoder_State *st, const int16_t index, int16_t *pValue )
+Word16 DecodeWBTCX20TnsFilterCoeff(Decoder_State *st, const Word16 index, Word16 * pValue)
{
- assert( ( index >= 0 ) && ( index < nTnsCoeffTables ) );
- return DecodeUsingTable( st, pValue, codesTnsCoeffWBTCX20[index], nTnsCoeffCodes );
+ assert((index >= 0) && (index < nTnsCoeffTables));
+
+ return DecodeUsingTable(st, pValue, codesTnsCoeffWBTCX20[index], nTnsCoeffCodes);
}
+
/* TNS filter order */
-void const *GetTnsFilterOrder( void const *p, const int16_t index, int16_t *pValue )
+void const * GetTnsFilterOrder(void const * p, const Word16 index, Word16 * pValue)
{
- *pValue = ( (STnsFilter const *) p )[index].order;
- return ( (STnsFilter const *) p )[index].coefIndex;
+ move16();
+ *pValue = ((STnsFilter const *)p)[index].order;
+
+ move16();
+ return ((STnsFilter const *)p)[index].coefIndex;
}
-void *SetTnsFilterOrder( void *p, const int16_t index, const int16_t value )
+void * SetTnsFilterOrder(void * p, const Word16 index, const Word16 value)
{
- ( (STnsFilter *) p )[index].order = value;
- return ( (STnsFilter *) p )[index].coefIndex;
+ move16();
+ ((STnsFilter *)p)[index].order = value;
+
+ move16();
+ return ((STnsFilter *)p)[index].coefIndex;
}
-int16_t GetTnsFilterOrderBitsSWBTCX20( const int16_t value, const int16_t index )
+Word16 GetTnsFilterOrderBitsSWBTCX20(const Word16 value, const Word16 index)
{
- (void) index;
- return GetBitsFromTable( value - 1, codesTnsOrderTCX20, nTnsOrderCodes );
+ (void)index;
+
+ return GetBitsFromTable(value-1, codesTnsOrderTCX20, nTnsOrderCodes);
}
-int16_t EncodeTnsFilterOrderSWBTCX20( const int16_t value, const int16_t index )
+Word16 EncodeTnsFilterOrderSWBTCX20(const Word16 value, const Word16 index)
{
- (void) index;
- return EncodeUsingTable( value - 1, codesTnsOrderTCX20, nTnsOrderCodes );
+ (void)index;
+
+ return EncodeUsingTable(value-1, codesTnsOrderTCX20, nTnsOrderCodes);
}
-int16_t DecodeTnsFilterOrderSWBTCX20( Decoder_State *st, const int16_t index, int16_t *pValue )
+Word16 DecodeTnsFilterOrderSWBTCX20(Decoder_State *st, const Word16 index, Word16 * pValue)
{
- (void) index;
- return DecodeUsingTable( st, pValue, codesTnsOrderTCX20, nTnsOrderCodes );
+ (void)index;
+
+ return DecodeUsingTable(st, pValue, codesTnsOrderTCX20, nTnsOrderCodes);
}
-int16_t GetTnsFilterOrderBitsSWBTCX10( const int16_t value, const int16_t index )
+Word16 GetTnsFilterOrderBitsSWBTCX10(const Word16 value, const Word16 index)
{
- (void) index;
- return GetBitsFromTable( value - 1, codesTnsOrderTCX10, nTnsOrderCodes );
+ (void)index;
+
+ return GetBitsFromTable(value-1, codesTnsOrderTCX10, nTnsOrderCodes);
}
-int16_t EncodeTnsFilterOrderSWBTCX10( const int16_t value, const int16_t index )
+Word16 EncodeTnsFilterOrderSWBTCX10(const Word16 value, const Word16 index)
{
- (void) index;
- return EncodeUsingTable( value - 1, codesTnsOrderTCX10, nTnsOrderCodes );
+ (void)index;
+
+ return EncodeUsingTable(value-1, codesTnsOrderTCX10, nTnsOrderCodes);
}
-int16_t DecodeTnsFilterOrderSWBTCX10( Decoder_State *st, const int16_t index, int16_t *pValue )
+Word16 DecodeTnsFilterOrderSWBTCX10(Decoder_State *st, const Word16 index, Word16 * pValue)
{
- (void) index;
- return DecodeUsingTable( st, pValue, codesTnsOrderTCX10, nTnsOrderCodes );
+ (void)index;
+
+ return DecodeUsingTable(st, pValue, codesTnsOrderTCX10, nTnsOrderCodes);
}
-int16_t GetTnsFilterOrderBits( const int16_t value, const int16_t index )
+Word16 GetTnsFilterOrderBits(const Word16 value, const Word16 index)
{
- (void) index;
- return GetBitsFromTable( value - 1, codesTnsOrder, nTnsOrderCodes );
+ (void)index;
+
+ return GetBitsFromTable(value-1, codesTnsOrder, nTnsOrderCodes);
}
-int16_t EncodeTnsFilterOrder( const int16_t value, const int16_t index )
+Word16 EncodeTnsFilterOrder(const Word16 value, const Word16 index)
{
- (void) index;
- return EncodeUsingTable( value - 1, codesTnsOrder, nTnsOrderCodes );
+ (void)index;
+
+ return EncodeUsingTable(value-1, codesTnsOrder, nTnsOrderCodes);
}
-int16_t DecodeTnsFilterOrder( Decoder_State *st, const int16_t index, int16_t *pValue )
+Word16 DecodeTnsFilterOrder(Decoder_State *st, const Word16 index, Word16 * pValue)
{
- (void) index;
- return DecodeUsingTable( st, pValue, codesTnsOrder, nTnsOrderCodes );
+ (void)index;
+
+ return DecodeUsingTable(st, pValue, codesTnsOrder, nTnsOrderCodes);
}
/* Number of TNS filters */
-void const *GetNumOfTnsFilters( void const *p, const int16_t index, int16_t *pValue )
+void const * GetNumOfTnsFilters(void const * p, const Word16 index, Word16 * pValue)
{
- *pValue = (int16_t) abs( ( (STnsData const *) p )[index].nFilters );
- return ( (STnsData const *) p )[index].filter;
+ *pValue = ((STnsData const *)p)[index].nFilters;
+
+ return ((STnsData const *)p)[index].filter;
}
-void *SetNumOfTnsFilters( void *p, const int16_t index, const int16_t value )
+void * SetNumOfTnsFilters(void * p, const Word16 index, Word16 value)
{
- ( (STnsData *) p )[index].nFilters = (int16_t) abs( value );
- return ( (STnsData *) p )[index].filter;
+ ((STnsData *)p)[index].nFilters = value;
+
+ return ((STnsData *)p)[index].filter;
}
/* TNS enabled/disabled flag */
-void const *GetTnsEnabled( void const *p, const int16_t index, int16_t *pValue )
+void const * GetTnsEnabled(void const * p, const Word16 index, Word16 * pValue)
{
- *pValue = ( (STnsData const *) p )[index].nFilters != 0 ? 1 : 0;
+ move16();
+ *pValue = 0;
+ if (((STnsData const *)p)[index].nFilters != 0)
+ {
+ move16();
+ *pValue = 1;
+ }
return NULL;
}
-void *SetTnsEnabled( void *p, const int16_t index, const int16_t value )
+void * SetTnsEnabled(void * p, const Word16 index, const Word16 value)
{
- (void) p, (void) index, (void) value;
+ (void)p,(void)index,(void)value;
return NULL;
}
-
+#ifdef ADD_IVAS_TNS
/* TNS on whitened spectra flag */
-void const *GetTnsOnWhite( void const *p, const int16_t index, int16_t *pValue )
+void const* GetTnsOnWhite(void const* p, const int16_t index, int16_t* pValue)
{
- *pValue = ( (STnsData const *) p )[index].tnsOnWhitenedSpectra > 0 ? 1 : 0;
+ *pValue = ((STnsData const*)p)[index].tnsOnWhitenedSpectra > 0 ? 1 : 0;
return NULL;
}
-void *SetTnsOnWhite( void *p, const int16_t index, const int16_t value )
+void* SetTnsOnWhite(void* p, const int16_t index, const int16_t value)
{
- ( (STnsData *) p )[index].tnsOnWhitenedSpectra = value;
+ ((STnsData*)p)[index].tnsOnWhitenedSpectra = value;
return NULL;
}
-void const *GetTnsEnabledSingleFilter( void const *p, const int16_t index, int16_t *pValue )
+void const* GetTnsEnabledSingleFilter(void const* p, const int16_t index, int16_t* pValue)
{
- *pValue = ( (STnsData const *) p )[index].nFilters != 0 ? 1 : 0;
- return ( (STnsData const *) p )[index].filter;
+ *pValue = ((STnsData const*)p)[index].nFilters != 0 ? 1 : 0;
+ return ((STnsData const*)p)[index].filter;
}
+#endif
-void *SetTnsEnabledSingleFilter( void *p, const int16_t index, const int16_t value )
+void const * GetTnsEnabledSingleFilter(void const * p, const Word16 index, Word16 * pValue)
{
- ( (STnsData *) p )[index].nFilters = value;
- return ( (STnsData *) p )[index].filter;
+ move16();
+ *pValue = 0;
+ if (((STnsData const *)p)[index].nFilters > 0)
+ {
+ move16();
+ *pValue = 1;
+ }
+ return ((STnsData const *)p)[index].filter;
}
+void * SetTnsEnabledSingleFilter(void * p, const Word16 index, const Word16 value)
+{
+ ((STnsData *)p)[index].nFilters = value;
+ return ((STnsData *)p)[index].filter;
+}
/*-------------------------------------------------------------------*
* ResetTnsData()
*
*-------------------------------------------------------------------*/
-void ResetTnsData(
- STnsData *pTnsData )
+void ResetTnsData(STnsData * pTnsData)
{
- uint16_t iFilter;
+ Word16 iFilter;
+
pTnsData->nFilters = 0;
+#ifdef ADD_IVAS_TNS
pTnsData->tnsOnWhitenedSpectra = 0;
-
- for ( iFilter = 0; iFilter < sizeof( pTnsData->filter ) / sizeof( pTnsData->filter[0] ); iFilter++ )
+#endif
+ FOR (iFilter = 0; iFilter < (Word16) (sizeof(pTnsData->filter)/sizeof(pTnsData->filter[0])); iFilter++)
{
- STnsFilter *const pTnsFilter = &pTnsData->filter[iFilter];
+ STnsFilter * const pTnsFilter = &pTnsData->filter[iFilter];
pTnsFilter->spectrumLength = 0;
- pTnsFilter->predictionGain_flt = 1.0f;
- pTnsFilter->avgSqrCoef_flt = 0;
+ pTnsFilter->predictionGain = 128/*1.0f Q7*/;
+ pTnsFilter->avgSqrCoef = 0;
+#ifdef ADD_IVAS_TNS
pTnsFilter->filterType = TNS_FILTER_OFF;
- ClearTnsFilterCoefficients( pTnsFilter );
+#endif
+ ClearTnsFilterCoefficients(pTnsFilter);
}
- return;
}
-
-
/*-------------------------------------------------------------------*
* ClearTnsFilterCoefficients()
*
*-------------------------------------------------------------------*/
void ClearTnsFilterCoefficients(
- STnsFilter *pTnsFilter )
+ STnsFilter * pTnsFilter
+)
{
+ move16();
pTnsFilter->order = 0;
- set_s( pTnsFilter->coefIndex, 0, TNS_MAX_FILTER_ORDER );
-
- return;
+ assert(TNS_MAX_FILTER_ORDER == 8);
+ move16();move16();move16();move16();
+ move16();move16();move16();move16();
+ pTnsFilter->coefIndex[0] = 0;
+ pTnsFilter->coefIndex[1] = 0;
+ pTnsFilter->coefIndex[2] = 0;
+ pTnsFilter->coefIndex[3] = 0;
+ pTnsFilter->coefIndex[4] = 0;
+ pTnsFilter->coefIndex[5] = 0;
+ pTnsFilter->coefIndex[6] = 0;
+ pTnsFilter->coefIndex[7] = 0;
}
/** Inverse quantization for reflection coefficients.
@@ -524,71 +845,74 @@ void ClearTnsFilterCoefficients(
* @param parCoeff output reflection coefficients.
* @param order number of coefficients/values.
*/
-static void Index2Parcor(
- const int16_t index[],
- float parCoeff[],
- const int16_t order )
+static void Index2Parcor(const Word16 index[], Word16 parCoeff[], Word16 order)
{
- const float *values = tnsCoeff4;
- int16_t i;
+ const Word16 * values;
+ Word16 i;
+
+ move16();
+ values = tnsCoeff4;
- for ( i = 0; i < order; i++ )
+ FOR (i = 0; i < order; i++)
{
- parCoeff[i] = values[index[i] + INDEX_SHIFT];
+ move16();
+ parCoeff[i] = values[add(index[i], INDEX_SHIFT)];
}
-
return;
}
+
/* Linear prediction analysis filter. */
-static float FIRLattice(
- const int16_t order,
- const float *parCoeff,
- float *state,
- float x )
+static Word32 FIRLattice(
+ const Word16 order,
+ const Word16 *parCoeff /*Q15*/,
+ Word32 *state,
+ Word32 x /* Q0 */
+)
{
- int16_t i;
- float tmpSave;
+ Word16 i;
+ Word32 tmpSave, tmp;
+
tmpSave = x;
- for ( i = 0; i < order - 1; i++ )
+ move32();
+ FOR (i = 0; i < order-1; i++)
{
- const float tmp = parCoeff[i] * x + state[i];
- /* Variable initialization */
- x += parCoeff[i] * state[i];
+ tmp = L_add(state[i], Mpy_32_16_1(x, parCoeff[i]));
+ x = L_add(x, Mpy_32_16_1(state[i], parCoeff[i])); /* exponent: 31+0 */
state[i] = tmpSave;
+ move32();
tmpSave = tmp;
+ move32();
}
/* last stage: only need half operations */
- x += parCoeff[order - 1] * state[order - 1];
- state[order - 1] = tmpSave;
+ x = L_add(x, Mpy_32_16_1(state[order-1], parCoeff[order-1]));
+ state[order-1] = tmpSave;
+ move32();
return x;
}
-/* Linear prediction synthesis filter. */
-static float IIRLattice(
- const int16_t order,
- const float *parCoeff,
- float *state,
- float x )
+static Word32 IIRLattice(Word16 order, const Word16 *parCoeff, Word32 *state, Word32 x)
{
- int16_t i;
+ Word16 i;
+
/* first stage: no need to calculate state[order-1] */
- x -= parCoeff[order - 1] * state[order - 1];
- for ( i = order - 2; i >= 0; i-- )
+ x = L_sub(x, Mpy_32_16_1(state[order-1], parCoeff[order-1]));
+
+ FOR (i = order-2; i >= 0; i--)
{
- x -= parCoeff[i] * state[i];
- state[i + 1] = parCoeff[i] * x + state[i];
+ x = L_sub(x, Mpy_32_16_1(state[i], parCoeff[i]));
+ state[i+1] = L_add(state[i], Mpy_32_16_1(x, parCoeff[i]));
+ move32();
}
+ move32();
state[0] = x;
-
return x;
}
-
/** TNS analysis/synthesis filter.
* @param spectrum input spectrum values.
* @param numOfLines number of lines in the spectrum.
@@ -600,250 +924,154 @@ static float IIRLattice(
Inplace operation is supported, so it can be equal to spectrum.
*/
static void TnsFilter(
- const float spectrum[],
- const int16_t numOfLines,
- const float parCoeff[],
- const int16_t order,
- TLinearPredictionFilter filter,
- float *state,
- float output[] )
+ const Word32 spectrum[],
+ const Word16 numOfLines,
+ const Word16 parCoeff[],
+ const Word16 order,
+ TLinearPredictionFilter filter,
+ Word32 * state,
+ Word32 output[]
+)
{
- int16_t j;
+ Word16 j;
+
- assert( ( order >= 0 ) && ( order <= TNS_MAX_FILTER_ORDER ) );
- assert( ( numOfLines > 0 ) || ( ( numOfLines == 0 ) && ( order == 0 ) ) );
+ assert((order >= 0) && (order <= TNS_MAX_FILTER_ORDER));
+ assert((numOfLines > 0) || ((numOfLines == 0) && (order == 0)));
- if ( order == 0 )
+ IF (order == 0)
{
- if ( ( spectrum != output ) && ( numOfLines > 0 ) )
+
+ test();
+ IF ( s_and((spectrum != output), numOfLines > 0) )
{
- mvr2r( spectrum, output, numOfLines );
+ Copy32(spectrum, output, numOfLines);
}
}
- else
+ ELSE
{
- for ( j = 0; j < numOfLines; j++ )
{
- output[j] = filter( order, parCoeff, state, spectrum[j] );
+
+ FOR (j = 0; j < numOfLines; j++)
+ {
+ move32();
+ output[j] = filter(order, parCoeff, state, spectrum[j]);
+ }
}
}
-
return;
}
-
-static void ITF_TnsFilter(
- const float spectrum[],
- const int16_t numOfLines,
- const float A[],
- const int16_t order,
- float output[] )
+static void ITF_TnsFilter_fx(
+ const Word32 spectrum[],
+ const Word16 numOfLines,
+ const Word16 A[], /* ifdef FIX_ITF_OVERFLOW Q_A else Q14 */
+ const Word16 Q_A,
+ const Word16 order,
+ Word32 output[]
+)
{
- int16_t i, j;
- float *p, buf[ITF_MAX_FILTER_ORDER + N_MAX];
-
- assert( ( order >= 0 ) && ( order <= ITF_MAX_FILTER_ORDER ) );
- assert( ( numOfLines > 0 ) || ( ( numOfLines == 0 ) && ( order == 0 ) ) );
-
- if ( order == 0 )
+ Word16 i, j;
+ Word32 buf[ITF_MAX_FILTER_ORDER + N_MAX];
+ Word32* p;
+ Word16 shift;
+ assert((order >= 0) && (order <= ITF_MAX_FILTER_ORDER));
+ assert((numOfLines > 0) || ((numOfLines == 0) && (order == 0)));
+
+ IF (order == 0)
{
- if ( ( spectrum != output ) && ( numOfLines > 0 ) )
+
+ test();
+ IF ( s_and((spectrum != output), numOfLines > 0) )
{
- mvr2r( spectrum, output, numOfLines );
+ Copy32(spectrum, output, numOfLines);
}
}
- else
+ ELSE
{
- p = buf + ITF_MAX_FILTER_ORDER;
+ shift = sub(15, Q_A);
- set_f( buf, 0, ITF_MAX_FILTER_ORDER );
- mvr2r( spectrum, p, numOfLines );
-
- for ( j = 0; j < numOfLines; j++, p++ )
+ p = buf + ITF_MAX_FILTER_ORDER;
+ set32_fx(buf, 0, ITF_MAX_FILTER_ORDER);
+ Copy32(spectrum, p, numOfLines);
+ FOR (j = 0; j < numOfLines; j++)
{
- output[j] = p[0];
- for ( i = 1; i < order; i++ )
+ Word32 L_tmp;
+
+ L_tmp = L_add(p[0], 0);
+ FOR (i = 1; i < order; i++)
{
- output[j] += A[i] * p[-i];
+ L_tmp = L_add(L_tmp, L_shl(Mpy_32_16_1(p[-i], A[i]), shift));
}
+ output[j] = L_tmp;
+ move32();
+ ++p;
}
}
-
return;
}
+static void ITF_GetFilterParameters_fx(
+ Word32 rxx[],
+ const Word16 maxOrder,
+ Word16* A, /* ifdef FIX_ITF_OVERFLOW Q_A else Q14 */
+ Word16* Q_A,
+ Word16* predictionGain
+)
+{
+ Word16 i, j, i_2, tmp;
+ Word16 parCoeff[ITF_MAX_FILTER_ORDER];
+ Word32 epsP[ITF_MAX_FILTER_ORDER+1], L_tmp;
-/*********************************************************************************************/
-/* Definitions of functions used in the mapping between TNS parameters and a bitstream. */
-/*********************************************************************************************/
-
-/* Helper functions for hufmann table coding */
-
-/********************************/
-/* Private functions */
-/********************************/
+ /* compute filter in ParCor form with LeRoux-Gueguen algorithm */
+ L_tmp = E_LPC_schur(rxx, parCoeff, epsP, maxOrder);
+ BASOP_SATURATE_WARNING_OFF_EVS /* Allow saturation, this value is compared against a threshold. */
+ *predictionGain = divide3232(L_shr(epsP[0], PRED_GAIN_E), L_tmp);
+ BASOP_SATURATE_WARNING_ON_EVS
-/** Autocorrelation to parcor coefficients.
- * Conversion of autocorrelation to parcor/reflection coefficients.
- * @param input Autocorrelation function/coefficients.
- * @param parCoeff output filter (PARCOR) coefficients.
- * @param order filter order.
- * @return prediction gain.
- */
-static float ITF_AutoToLPcoef(
- const float input[],
- float a[],
- const int16_t order )
-{
- int16_t i, j;
- float tmp, tmp2;
- float workBuffer[2 * ITF_MAX_FILTER_ORDER];
- float parCoeff[ITF_MAX_FILTER_ORDER];
- float *const pWorkBuffer = &workBuffer[order]; /* temp pointer */
-
- for ( i = 0; i < order; i++ )
{
- workBuffer[i] = input[i];
- pWorkBuffer[i] = input[i + 1];
- }
+ Word32 A32[ITF_MAX_FILTER_ORDER];
+ Word16 tmp1_l, tmp1_h, tmp2_l, tmp2_h;
- for ( i = 0; i < order; i++ )
- {
- if ( workBuffer[0] < 1.0f / 65536.0f )
- {
- tmp = 0;
- }
- else
+ /* Convert ParCor / reflection coefficients to LPC */
+ A32[0] = 134217728l/*1.0 Q27*/;
+ move16(); /* Q11+16 */
+ A32[1] = L_shr(L_deposit_h(parCoeff[0]), 4); /* Q11+16 */
+
+ FOR (i=1; i Q14 */
+ FOR (i=0; i HLM_MIN_NRG ); iSubdivisions++ )
- {
- fac = 1.0f / norms[iSubdivisions];
- iStartLine = startLine + spectrumLength * iSubdivisions / nSubdivisions;
- iEndLine = startLine + spectrumLength * ( iSubdivisions + 1 ) / nSubdivisions;
- pWindow = tnsAcfWindow;
-
- /* For additional loop condition */
- /* Variable initialization */
- for ( lag = 1; lag <= maxOrder; lag++ )
- {
- rxx[lag] += fac * ( *pWindow ) * dotp( pSpectrum + iStartLine - IGF_START_MN, pSpectrum + iStartLine - IGF_START_MN + lag, iEndLine - iStartLine - lag );
- pWindow++;
- }
- }
-
- *predictionGain = 0;
- if ( iSubdivisions == nSubdivisions ) /* meaning there is no subdivision with low energy */
- {
- rxx[0] = (float) nSubdivisions;
-
- /* Limit the maximum order to spectrum length/4 */
- *predictionGain = ITF_AutoToLPcoef( rxx, A, min( maxOrder, spectrumLength / 4 ) );
-
- *curr_order = maxOrder;
- }
-
- return 1;
-}
diff --git a/lib_com/tns_base_flt.c b/lib_com/tns_base_flt.c
new file mode 100644
index 0000000000000000000000000000000000000000..c0cffa830ec5316ded1d0f221476ae2f3f9d99da
--- /dev/null
+++ b/lib_com/tns_base_flt.c
@@ -0,0 +1,849 @@
+/******************************************************************************************************
+
+ (C) 2022-2023 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 "cnst.h"
+#include "rom_com.h"
+#include "prot.h"
+#include "stat_com.h"
+#include "wmc_auto.h"
+
+
+/*----------------------------------------------------------------------------
+ * Local constants
+ *---------------------------------------------------------------------------*/
+
+#define HLM_MIN_NRG PCM16_TO_FLT_FAC
+#define MAX_SUBDIVISIONS 3
+
+
+/*----------------------------------------------------------------------------
+ * Local prototypes
+ *---------------------------------------------------------------------------*/
+
+
+static void Index2Parcor( const int16_t index[], float parCoeff[], const int16_t order );
+
+static float FIRLattice( const int16_t order, const float *parCoeff, float *state, float x );
+
+static float IIRLattice( const int16_t order, const float *parCoeff, float *state, float x );
+
+static void TnsFilter( const float spectrum[], const int16_t numOfLines, const float parCoeff[], const int16_t order, TLinearPredictionFilter_flt filter, float *state, float output[] );
+
+
+/*-------------------------------------------------------------------*
+ * InitTnsConfiguration()
+ *
+ *-------------------------------------------------------------------*/
+
+void InitTnsConfiguration_flt(
+ const int16_t bwidth,
+ const int16_t frameLength,
+ STnsConfig *pTnsConfig,
+ const int16_t igfStopFreq,
+ const int32_t total_brate,
+ const int16_t element_mode,
+ const int16_t MCT_flag )
+{
+ int32_t nSampleRate;
+ int16_t iFilter;
+ int16_t *startLineFilter = &pTnsConfig->iFilterBorders[1];
+
+ nSampleRate = inner_frame_tbl[bwidth] * FRAMES_PER_SEC;
+
+ /* Sanity checks */
+ assert( ( nSampleRate > 0 ) && ( frameLength > 0 ) && ( pTnsConfig != NULL ) );
+ if ( ( nSampleRate <= 0 ) || ( frameLength <= 0 ) || ( pTnsConfig == NULL ) )
+ {
+ return /*TNS_FATAL_ERROR*/;
+ }
+
+ /* WMOPS: All initializations are either for safety or static (tables) and thus not to be counted */
+ /* Initialize TNS filter flag and maximum order */
+ pTnsConfig->maxOrder = TNS_MAX_FILTER_ORDER;
+ if ( total_brate <= ACELP_32k )
+ {
+ pTnsConfig->nMaxFilters = sizeof( tnsParametersIGF32kHz_LowBR ) / sizeof( tnsParametersIGF32kHz_LowBR[0] );
+
+ pTnsConfig->pTnsParameters = tnsParametersIGF32kHz_LowBR;
+ }
+ else
+ {
+ if ( nSampleRate > 32000 && nSampleRate == 100 * frameLength )
+ {
+ pTnsConfig->nMaxFilters = sizeof( tnsParameters48kHz_grouped ) / sizeof( tnsParameters48kHz_grouped[0] );
+ pTnsConfig->pTnsParameters = tnsParameters48kHz_grouped;
+ }
+ else if ( nSampleRate > 16000 )
+ {
+ if ( ( element_mode > IVAS_SCE ) && ( total_brate >= ( MCT_flag ? IVAS_32k : IVAS_48k ) ) )
+ {
+ pTnsConfig->nMaxFilters = sizeof( tnsParameters32kHz_Stereo ) / sizeof( tnsParameters32kHz_Stereo[0] );
+ if ( nSampleRate == 100 * frameLength ) /* sub-frame length is <= 10 ms */
+ {
+ pTnsConfig->pTnsParameters = tnsParameters32kHz_grouped;
+ }
+ else
+ {
+ pTnsConfig->pTnsParameters = tnsParameters32kHz_Stereo;
+ }
+ }
+ else
+ {
+ pTnsConfig->nMaxFilters = sizeof( tnsParameters32kHz ) / sizeof( tnsParameters32kHz[0] );
+ if ( nSampleRate == 100 * frameLength ) /* sub-frame length is <= 10 ms */
+ {
+ pTnsConfig->pTnsParameters = tnsParameters32kHz_grouped;
+ }
+ else
+ {
+ pTnsConfig->pTnsParameters = tnsParameters32kHz;
+ }
+ }
+ }
+ else
+ {
+ if ( nSampleRate == 100 * frameLength ) /* sub-frame length is <= 10 ms */
+ {
+ pTnsConfig->nMaxFilters = sizeof( tnsParameters16kHz_grouped ) / sizeof( tnsParameters16kHz_grouped[0] );
+ pTnsConfig->pTnsParameters = tnsParameters16kHz_grouped;
+ }
+ else
+ {
+ pTnsConfig->nMaxFilters = sizeof( tnsParameters16kHz ) / sizeof( tnsParameters16kHz[0] );
+ pTnsConfig->pTnsParameters = tnsParameters16kHz;
+ }
+ }
+ }
+
+ assert( pTnsConfig->nMaxFilters <= TNS_MAX_NUM_OF_FILTERS );
+
+ /* Set starting MDCT line for each filter based on the starting frequencies from the TNS table */
+ for ( iFilter = 0; iFilter < pTnsConfig->nMaxFilters; iFilter++ )
+ {
+ assert( pTnsConfig->pTnsParameters[iFilter].startLineFrequency < 0.5f * nSampleRate );
+ startLineFilter[iFilter] = (int16_t) ( ( frameLength * 2 * pTnsConfig->pTnsParameters[iFilter].startLineFrequency ) / nSampleRate );
+ }
+ if ( igfStopFreq > 0 )
+ {
+ pTnsConfig->iFilterBorders[0] = (int16_t) ( ( frameLength * 2 * igfStopFreq ) / nSampleRate );
+ }
+ else
+ {
+ pTnsConfig->iFilterBorders[0] = frameLength;
+ }
+
+ pTnsConfig->allowTnsOnWhite = 0;
+
+ return /*TNS_NO_ERROR*/;
+}
+
+
+/*-------------------------------------------------------------------*
+ * ApplyTnsFilter()
+ *
+ *-------------------------------------------------------------------*/
+
+void ApplyTnsFilter_flt(
+ STnsConfig const *pTnsConfig,
+ STnsData const *pTnsData,
+ float spectrum[],
+ const int16_t fIsAnalysis )
+{
+ TLinearPredictionFilter_flt filter;
+ float state[TNS_MAX_FILTER_ORDER];
+ int16_t iFilter;
+ int16_t stopLine, startLine;
+ const int16_t *pBorders;
+
+ filter = fIsAnalysis ? FIRLattice : IIRLattice;
+ set_f( state, 0, TNS_MAX_FILTER_ORDER );
+ pBorders = pTnsConfig->iFilterBorders;
+
+ for ( iFilter = pTnsConfig->nMaxFilters - 1; iFilter >= 0; iFilter-- )
+ {
+ float parCoeff[TNS_MAX_FILTER_ORDER];
+ const STnsFilter *pFilter = &pTnsData->filter[iFilter];
+
+ set_f( parCoeff, 0, TNS_MAX_FILTER_ORDER );
+ stopLine = pBorders[iFilter];
+ startLine = pBorders[iFilter + 1];
+
+ Index2Parcor( pFilter->coefIndex, parCoeff, pFilter->order );
+
+ TnsFilter( &spectrum[startLine], stopLine - startLine, parCoeff, pFilter->order, filter, state, &spectrum[startLine] );
+ }
+
+ return /*( pTnsData->nFilters < 0 ) ? TNS_FATAL_ERROR : TNS_NO_ERROR*/;
+}
+
+
+/*********************************************************************************************/
+/* Definitions of functions used in the mapping between TNS parameters and a bitstream. */
+/*********************************************************************************************/
+
+/* Helper functions for hufmann table coding */
+
+/** Get number of bits from a Huffman table.
+ * The table must be sorted by values.
+ */
+static int16_t GetBitsFromTable( int16_t value, const Coding codes[], const int16_t nSize )
+{
+ (void) nSize;
+ assert( ( value >= 0 ) && ( value < nSize ) && ( nSize >= 0 ) && ( nSize <= 256 ) );
+ return codes[value].nBits;
+}
+
+/** Get the code for a value from a Huffman table.
+ * The table must be sorted by values.
+ */
+static int16_t EncodeUsingTable( int16_t value, const Coding codes[], const int16_t nSize )
+{
+ (void) nSize;
+ assert( ( value >= 0 ) && ( value < nSize ) && ( nSize >= 0 ) && ( nSize <= 256 ) );
+ return codes[value].code;
+}
+
+/** Decode a value from a bitstream using a Huffman table. */
+static int16_t DecodeUsingTable( Decoder_State *st, int16_t *pValue, const Coding codes[], const int16_t nSize )
+{
+ uint16_t code = 0;
+ uint8_t nBits = 0;
+ int16_t valueIndex = nSize;
+
+ assert( ( nSize >= 0 ) && ( nSize <= 256 ) );
+ /* Variable initialization. All are required! */
+ while ( valueIndex == nSize )
+ {
+ code = ( code << 1 ) + get_next_indice( st, 1 );
+ ++nBits;
+ if ( nBits > nSize || nBits > 16 )
+ {
+ st->BER_detect = 1;
+ *pValue = 0;
+ return -1;
+ }
+ for ( valueIndex = 0; valueIndex < nSize; valueIndex++ )
+ {
+ if ( codes[valueIndex].nBits == nBits )
+ {
+ if ( codes[valueIndex].code == code )
+ {
+ break;
+ }
+ }
+ }
+ /* Loop condition */
+ }
+
+ if ( valueIndex < nSize )
+ {
+ *pValue = codes[valueIndex].value;
+ }
+ else
+ {
+ st->BER_detect = 1;
+ *pValue = 0;
+ return -1;
+ }
+
+ return nBits;
+}
+
+/* TNS filter coefficients */
+
+//void const *GetTnsFilterCoeff_flt( void const *p, const int16_t index, int16_t *pValue )
+//{
+// *pValue = ( (int16_t const *) p )[index] + INDEX_SHIFT;
+// return NULL;
+//}
+
+//void *SetTnsFilterCoeff_flt( void *p, const int16_t index, const int16_t value )
+//{
+// ( (int16_t *) p )[index] = value - INDEX_SHIFT;
+// return NULL;
+//}
+
+//int16_t GetSWBTCX20TnsFilterCoeffBits_flt( const int16_t value, const int16_t index )
+//{
+// assert( ( index >= 0 ) && ( index < nTnsCoeffTables ) );
+// return GetBitsFromTable( value, codesTnsCoeffSWBTCX20[index], nTnsCoeffCodes );
+//}
+
+//int16_t EncodeSWBTCX20TnsFilterCoeff_flt( const int16_t value, const int16_t index )
+//{
+// assert( ( index >= 0 ) && ( index < nTnsCoeffTables ) );
+// return EncodeUsingTable( value, codesTnsCoeffSWBTCX20[index], nTnsCoeffCodes );
+//}
+
+int16_t DecodeSWBTCX20TnsFilterCoeff_flt( Decoder_State *st, const int16_t index, int16_t *pValue )
+{
+ assert( ( index >= 0 ) && ( index < nTnsCoeffTables ) );
+ return DecodeUsingTable( st, pValue, codesTnsCoeffSWBTCX20[index], nTnsCoeffCodes );
+}
+
+//int16_t GetSWBTCX10TnsFilterCoeffBits_flt( const int16_t value, const int16_t index )
+//{
+// assert( ( index >= 0 ) && ( index < nTnsCoeffTables ) );
+// return GetBitsFromTable( value, codesTnsCoeffSWBTCX10[index], nTnsCoeffCodes );
+//}
+
+//int16_t EncodeSWBTCX10TnsFilterCoeff_flt( const int16_t value, const int16_t index )
+//{
+// assert( ( index >= 0 ) && ( index < nTnsCoeffTables ) );
+// return EncodeUsingTable( value, codesTnsCoeffSWBTCX10[index], nTnsCoeffCodes );
+//}
+
+int16_t DecodeSWBTCX10TnsFilterCoeff_flt( Decoder_State *st, const int16_t index, int16_t *pValue )
+{
+ assert( ( index >= 0 ) && ( index < nTnsCoeffTables ) );
+ return DecodeUsingTable( st, pValue, codesTnsCoeffSWBTCX10[index], nTnsCoeffCodes );
+}
+
+//int16_t GetWBTCX20TnsFilterCoeffBits_flt( const int16_t value, const int16_t index )
+//{
+// assert( ( index >= 0 ) && ( index < nTnsCoeffTables ) );
+// return GetBitsFromTable( value, codesTnsCoeffWBTCX20[index], nTnsCoeffCodes );
+//}
+
+//int16_t EncodeWBTCX20TnsFilterCoeff_flt( const int16_t value, const int16_t index )
+//{
+// assert( ( index >= 0 ) && ( index < nTnsCoeffTables ) );
+// return EncodeUsingTable( value, codesTnsCoeffWBTCX20[index], nTnsCoeffCodes );
+//}
+
+int16_t DecodeWBTCX20TnsFilterCoeff_flt( Decoder_State *st, const int16_t index, int16_t *pValue )
+{
+ assert( ( index >= 0 ) && ( index < nTnsCoeffTables ) );
+ return DecodeUsingTable( st, pValue, codesTnsCoeffWBTCX20[index], nTnsCoeffCodes );
+}
+
+
+/* TNS filter order */
+
+//void const *GetTnsFilterOrder_flt( void const *p, const int16_t index, int16_t *pValue )
+//{
+// *pValue = ( (STnsFilter const *) p )[index].order;
+// return ( (STnsFilter const *) p )[index].coefIndex;
+//}
+
+//void *SetTnsFilterOrder_flt( void *p, const int16_t index, const int16_t value )
+//{
+// ( (STnsFilter *) p )[index].order = value;
+// return ( (STnsFilter *) p )[index].coefIndex;
+//}
+
+//int16_t GetTnsFilterOrderBitsSWBTCX20_flt( const int16_t value, const int16_t index )
+//{
+// (void) index;
+// return GetBitsFromTable( value - 1, codesTnsOrderTCX20, nTnsOrderCodes );
+//}
+
+//int16_t EncodeTnsFilterOrderSWBTCX20_flt( const int16_t value, const int16_t index )
+//{
+// (void) index;
+// return EncodeUsingTable( value - 1, codesTnsOrderTCX20, nTnsOrderCodes );
+//}
+
+int16_t DecodeTnsFilterOrderSWBTCX20_flt( Decoder_State *st, const int16_t index, int16_t *pValue )
+{
+ (void) index;
+ return DecodeUsingTable( st, pValue, codesTnsOrderTCX20, nTnsOrderCodes );
+}
+
+int16_t GetTnsFilterOrderBitsSWBTCX10_flt( const int16_t value, const int16_t index )
+{
+ (void) index;
+ return GetBitsFromTable( value - 1, codesTnsOrderTCX10, nTnsOrderCodes );
+}
+
+int16_t EncodeTnsFilterOrderSWBTCX10_flt( const int16_t value, const int16_t index )
+{
+ (void) index;
+ return EncodeUsingTable( value - 1, codesTnsOrderTCX10, nTnsOrderCodes );
+}
+
+int16_t DecodeTnsFilterOrderSWBTCX10_flt( Decoder_State *st, const int16_t index, int16_t *pValue )
+{
+ (void) index;
+ return DecodeUsingTable( st, pValue, codesTnsOrderTCX10, nTnsOrderCodes );
+}
+
+//int16_t GetTnsFilterOrderBits_flt( const int16_t value, const int16_t index )
+//{
+// (void) index;
+// return GetBitsFromTable( value - 1, codesTnsOrder, nTnsOrderCodes );
+//}
+
+//int16_t EncodeTnsFilterOrder_flt( const int16_t value, const int16_t index )
+//{
+// (void) index;
+// return EncodeUsingTable( value - 1, codesTnsOrder, nTnsOrderCodes );
+//}
+
+int16_t DecodeTnsFilterOrder_flt( Decoder_State *st, const int16_t index, int16_t *pValue )
+{
+ (void) index;
+ return DecodeUsingTable( st, pValue, codesTnsOrder, nTnsOrderCodes );
+}
+
+/* Number of TNS filters */
+
+void const *GetNumOfTnsFilters_flt( void const *p, const int16_t index, int16_t *pValue )
+{
+ *pValue = (int16_t) abs( ( (STnsData const *) p )[index].nFilters );
+ return ( (STnsData const *) p )[index].filter;
+}
+
+void *SetNumOfTnsFilters_flt( void *p, const int16_t index, const int16_t value )
+{
+ ( (STnsData *) p )[index].nFilters = (int16_t) abs( value );
+ return ( (STnsData *) p )[index].filter;
+}
+
+/* TNS enabled/disabled flag */
+
+//void const *GetTnsEnabled_flt( void const *p, const int16_t index, int16_t *pValue )
+//{
+// *pValue = ( (STnsData const *) p )[index].nFilters != 0 ? 1 : 0;
+// return NULL;
+//}
+
+//void *SetTnsEnabled_flt( void *p, const int16_t index, const int16_t value )
+//{
+// (void) p, (void) index, (void) value;
+// return NULL;
+//}
+
+/* TNS on whitened spectra flag */
+
+void const *GetTnsOnWhite( void const *p, const int16_t index, int16_t *pValue )
+{
+ *pValue = ( (STnsData const *) p )[index].tnsOnWhitenedSpectra > 0 ? 1 : 0;
+ return NULL;
+}
+
+void *SetTnsOnWhite( void *p, const int16_t index, const int16_t value )
+{
+ ( (STnsData *) p )[index].tnsOnWhitenedSpectra = value;
+ return NULL;
+}
+
+//void const *GetTnsEnabledSingleFilter_flt( void const *p, const int16_t index, int16_t *pValue )
+//{
+// *pValue = ( (STnsData const *) p )[index].nFilters != 0 ? 1 : 0;
+// return ( (STnsData const *) p )[index].filter;
+//}
+
+//void *SetTnsEnabledSingleFilter_flt( void *p, const int16_t index, const int16_t value )
+//{
+// ( (STnsData *) p )[index].nFilters = value;
+// return ( (STnsData *) p )[index].filter;
+//}
+
+
+/*-------------------------------------------------------------------*
+ * ResetTnsData()
+ *
+ *-------------------------------------------------------------------*/
+
+void ResetTnsData_flt(
+ STnsData *pTnsData )
+{
+ uint16_t iFilter;
+
+ pTnsData->nFilters = 0;
+ pTnsData->tnsOnWhitenedSpectra = 0;
+
+ for ( iFilter = 0; iFilter < sizeof( pTnsData->filter ) / sizeof( pTnsData->filter[0] ); iFilter++ )
+ {
+ STnsFilter *const pTnsFilter = &pTnsData->filter[iFilter];
+ pTnsFilter->spectrumLength = 0;
+ pTnsFilter->predictionGain_flt = 1.0f;
+ pTnsFilter->avgSqrCoef_flt = 0;
+ pTnsFilter->filterType = TNS_FILTER_OFF;
+ ClearTnsFilterCoefficients_flt( pTnsFilter );
+ }
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------*
+ * ClearTnsFilterCoefficients_flt()
+ *
+ *-------------------------------------------------------------------*/
+
+void ClearTnsFilterCoefficients_flt(
+ STnsFilter *pTnsFilter )
+{
+ pTnsFilter->order = 0;
+ set_s( pTnsFilter->coefIndex, 0, TNS_MAX_FILTER_ORDER );
+
+ return;
+}
+
+/** Inverse quantization for reflection coefficients.
+ *
+ * @param index input quantized values.
+ * @param parCoeff output reflection coefficients.
+ * @param order number of coefficients/values.
+ */
+static void Index2Parcor(
+ const int16_t index[],
+ float parCoeff[],
+ const int16_t order )
+{
+ const float *values = tnsCoeff4_flt;
+ int16_t i;
+
+ for ( i = 0; i < order; i++ )
+ {
+ parCoeff[i] = values[index[i] + INDEX_SHIFT];
+ }
+
+ return;
+}
+
+/* Linear prediction analysis filter. */
+static float FIRLattice(
+ const int16_t order,
+ const float *parCoeff,
+ float *state,
+ float x )
+{
+ int16_t i;
+ float tmpSave;
+
+ tmpSave = x;
+ for ( i = 0; i < order - 1; i++ )
+ {
+ const float tmp = parCoeff[i] * x + state[i];
+ /* Variable initialization */
+ x += parCoeff[i] * state[i];
+ state[i] = tmpSave;
+ tmpSave = tmp;
+ }
+
+ /* last stage: only need half operations */
+ x += parCoeff[order - 1] * state[order - 1];
+ state[order - 1] = tmpSave;
+
+ return x;
+}
+
+/* Linear prediction synthesis filter. */
+static float IIRLattice(
+ const int16_t order,
+ const float *parCoeff,
+ float *state,
+ float x )
+{
+ int16_t i;
+
+ /* first stage: no need to calculate state[order-1] */
+ x -= parCoeff[order - 1] * state[order - 1];
+ for ( i = order - 2; i >= 0; i-- )
+ {
+ x -= parCoeff[i] * state[i];
+ state[i + 1] = parCoeff[i] * x + state[i];
+ }
+
+ state[0] = x;
+
+ return x;
+}
+
+/** TNS analysis/synthesis filter.
+ * @param spectrum input spectrum values.
+ * @param numOfLines number of lines in the spectrum.
+ * @param parCoeff filter (PARCOR) coefficients.
+ * @param order filter order.
+ * @param filter function that implements filtering.
+ By this function it is defined whether analysis or synthesis is performed.
+ * @param output filtered output spectrum values.
+ Inplace operation is supported, so it can be equal to spectrum.
+ */
+static void TnsFilter(
+ const float spectrum[],
+ const int16_t numOfLines,
+ const float parCoeff[],
+ const int16_t order,
+ TLinearPredictionFilter_flt filter,
+ float *state,
+ float output[] )
+{
+ int16_t j;
+
+ assert( ( order >= 0 ) && ( order <= TNS_MAX_FILTER_ORDER ) );
+ assert( ( numOfLines > 0 ) || ( ( numOfLines == 0 ) && ( order == 0 ) ) );
+
+ if ( order == 0 )
+ {
+ if ( ( spectrum != output ) && ( numOfLines > 0 ) )
+ {
+ mvr2r( spectrum, output, numOfLines );
+ }
+ }
+ else
+ {
+ for ( j = 0; j < numOfLines; j++ )
+ {
+ output[j] = filter( order, parCoeff, state, spectrum[j] );
+ }
+ }
+
+ return;
+}
+
+
+static void ITF_TnsFilter(
+ const float spectrum[],
+ const int16_t numOfLines,
+ const float A[],
+ const int16_t order,
+ float output[] )
+{
+ int16_t i, j;
+ float *p, buf[ITF_MAX_FILTER_ORDER + N_MAX];
+
+ assert( ( order >= 0 ) && ( order <= ITF_MAX_FILTER_ORDER ) );
+ assert( ( numOfLines > 0 ) || ( ( numOfLines == 0 ) && ( order == 0 ) ) );
+
+ if ( order == 0 )
+ {
+ if ( ( spectrum != output ) && ( numOfLines > 0 ) )
+ {
+ mvr2r( spectrum, output, numOfLines );
+ }
+ }
+ else
+ {
+ p = buf + ITF_MAX_FILTER_ORDER;
+
+ set_f( buf, 0, ITF_MAX_FILTER_ORDER );
+ mvr2r( spectrum, p, numOfLines );
+
+ for ( j = 0; j < numOfLines; j++, p++ )
+ {
+ output[j] = p[0];
+ for ( i = 1; i < order; i++ )
+ {
+ output[j] += A[i] * p[-i];
+ }
+ }
+ }
+
+ return;
+}
+
+
+/*********************************************************************************************/
+/* Definitions of functions used in the mapping between TNS parameters and a bitstream. */
+/*********************************************************************************************/
+
+/* Helper functions for hufmann table coding */
+
+/********************************/
+/* Private functions */
+/********************************/
+
+/** Autocorrelation to parcor coefficients.
+ * Conversion of autocorrelation to parcor/reflection coefficients.
+ * @param input Autocorrelation function/coefficients.
+ * @param parCoeff output filter (PARCOR) coefficients.
+ * @param order filter order.
+ * @return prediction gain.
+ */
+static float ITF_AutoToLPcoef(
+ const float input[],
+ float a[],
+ const int16_t order )
+{
+ int16_t i, j;
+ float tmp, tmp2;
+ float workBuffer[2 * ITF_MAX_FILTER_ORDER];
+ float parCoeff[ITF_MAX_FILTER_ORDER];
+ float *const pWorkBuffer = &workBuffer[order]; /* temp pointer */
+
+ for ( i = 0; i < order; i++ )
+ {
+ workBuffer[i] = input[i];
+ pWorkBuffer[i] = input[i + 1];
+ }
+
+ for ( i = 0; i < order; i++ )
+ {
+ if ( workBuffer[0] < 1.0f / 65536.0f )
+ {
+ tmp = 0;
+ }
+ else
+ {
+ tmp = -pWorkBuffer[i] / workBuffer[0];
+ }
+
+ /* compensate for calculation inaccuracies limit reflection coefs to ]-1,1[ */
+ tmp = min( 0.999f, max( -0.999f, tmp ) );
+
+ parCoeff[i] = tmp;
+ for ( j = i; j < order; j++ )
+ {
+ tmp2 = pWorkBuffer[j] + tmp * workBuffer[j - i];
+ workBuffer[j - i] += tmp * pWorkBuffer[j];
+ pWorkBuffer[j] = tmp2;
+ }
+ }
+
+ /* Convert ParCor / reflection coefficients to LPC */
+ a[0] = 1.0f;
+ a[1] = parCoeff[0];
+
+ for ( i = 1; i < order; i++ )
+ {
+ for ( j = 0; j < i / 2; j++ )
+ {
+ tmp = a[j + 1];
+ a[j + 1] += parCoeff[i] * a[i - 1 - j + 1];
+ a[i - 1 - j + 1] += parCoeff[i] * tmp;
+ }
+ if ( i & 1 )
+ {
+ a[j + 1] += parCoeff[i] * a[j + 1];
+ }
+
+ a[i + 1] = parCoeff[i];
+ }
+
+ return ( ( input[0] + 1e-30f ) / ( workBuffer[0] + 1e-30f ) );
+}
+
+
+/*-------------------------------------------------------------------*
+ * ITF_Apply()
+ *
+ *-------------------------------------------------------------------*/
+
+void ITF_Apply(
+ float spectrum[],
+ const int16_t startLine,
+ const int16_t stopLine,
+ const float *A,
+ const int16_t order )
+{
+ ITF_TnsFilter( &spectrum[startLine], stopLine - startLine, A, order, &spectrum[startLine] );
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------*
+ * ITF_Detect()
+ *
+ *
+ *-------------------------------------------------------------------*/
+
+int16_t ITF_Detect(
+ const float pSpectrum[],
+ const int16_t startLine,
+ const int16_t stopLine,
+ const int16_t maxOrder,
+ float *A,
+ float *predictionGain,
+ int16_t *curr_order )
+{
+ float norms[MAX_SUBDIVISIONS];
+ int16_t nSubdivisions;
+ int16_t iStartLine, iEndLine, spectrumLength;
+ float rxx[ITF_MAX_FILTER_ORDER + 1];
+ float fac;
+ const float *pWindow;
+ int16_t iSubdivisions, lag;
+
+ nSubdivisions = MAX_SUBDIVISIONS;
+ set_f( norms, 0.f, MAX_SUBDIVISIONS );
+ set_f( rxx, 0.f, ITF_MAX_FILTER_ORDER + 1 ); /* This initialization is required */
+
+ if ( maxOrder <= 0 )
+ {
+ return 0;
+ }
+
+ /* Calculate norms for each spectrum part */
+ for ( iSubdivisions = 0; iSubdivisions < nSubdivisions; iSubdivisions++ )
+ {
+ iStartLine = startLine + ( stopLine - startLine ) * iSubdivisions / nSubdivisions;
+ iEndLine = startLine + ( stopLine - startLine ) * ( iSubdivisions + 1 ) / nSubdivisions;
+
+ /* Variable initialization */
+ norms[iSubdivisions] = sum2_f( pSpectrum + iStartLine - IGF_START_MN, iEndLine - iStartLine );
+ }
+
+ /* Calculate normalized autocorrelation for spectrum subdivision and get TNS filter parameters based on it */
+ spectrumLength = stopLine - startLine;
+
+ /* Variable initialization */
+ for ( iSubdivisions = 0; ( iSubdivisions < nSubdivisions ) && ( norms[iSubdivisions] > HLM_MIN_NRG ); iSubdivisions++ )
+ {
+ fac = 1.0f / norms[iSubdivisions];
+ iStartLine = startLine + spectrumLength * iSubdivisions / nSubdivisions;
+ iEndLine = startLine + spectrumLength * ( iSubdivisions + 1 ) / nSubdivisions;
+ pWindow = tnsAcfWindow;
+
+ /* For additional loop condition */
+ /* Variable initialization */
+ for ( lag = 1; lag <= maxOrder; lag++ )
+ {
+ rxx[lag] += fac * ( *pWindow ) * dotp( pSpectrum + iStartLine - IGF_START_MN, pSpectrum + iStartLine - IGF_START_MN + lag, iEndLine - iStartLine - lag );
+ pWindow++;
+ }
+ }
+
+ *predictionGain = 0;
+ if ( iSubdivisions == nSubdivisions ) /* meaning there is no subdivision with low energy */
+ {
+ rxx[0] = (float) nSubdivisions;
+
+ /* Limit the maximum order to spectrum length/4 */
+ *predictionGain = ITF_AutoToLPcoef( rxx, A, min( maxOrder, spectrumLength / 4 ) );
+
+ *curr_order = maxOrder;
+ }
+
+ return 1;
+}
diff --git a/lib_dec/dec_tcx.c b/lib_dec/dec_tcx.c
index 320519d491a23baa2813e593d9a2896146afb2e9..1920b6f3cd66f82bd3f03a690d6adf03788e00e0 100644
--- a/lib_dec/dec_tcx.c
+++ b/lib_dec/dec_tcx.c
@@ -1043,7 +1043,7 @@ void decoder_tcx_invQ(
{
assert( !"Not adapted to warped scale" );
}
- tcxFormantEnhancement( xn_buf, gainlpc2, x, L_frame );
+ tcxFormantEnhancement_flt( xn_buf, gainlpc2, x, L_frame );
}
}
@@ -1126,7 +1126,7 @@ void decoder_tcx_noisefilling(
if ( !bfi && ( fac_ns > 0.0f ) )
{
- firstLine = tcxGetNoiseFillingTilt( A, L_frame, ( total_brate >= ACELP_13k20 && !st->rf_flag ), &noiseTiltFactor );
+ firstLine = tcxGetNoiseFillingTilt_flt( A, L_frame, ( total_brate >= ACELP_13k20 && !st->rf_flag ), &noiseTiltFactor );
if ( st->tcxonly )
{
@@ -1298,7 +1298,7 @@ void decoder_tcx_noisefilling(
}
noiseTiltFactor = 1.0f;
- tcxGetNoiseFillingTilt( A, L_frame, ( total_brate >= ACELP_13k20 && !st->rf_flag ), &noiseTiltFactor );
+ tcxGetNoiseFillingTilt_flt( A, L_frame, ( total_brate >= ACELP_13k20 && !st->rf_flag ), &noiseTiltFactor );
if ( st->element_mode == IVAS_CPE_MDCT && !MCT_flag )
{
@@ -1528,7 +1528,7 @@ void decoder_tcx_tns(
tcx5TnsGrouping( L >> 1, hTcxCfg->tnsConfig[0][0].iFilterBorders[0] >> 1, x );
}
- ApplyTnsFilter( hTcxCfg->pCurrentTnsConfig, tnsData, x, 0 );
+ ApplyTnsFilter_flt( hTcxCfg->pCurrentTnsConfig, tnsData, x, 0 );
if ( ( L_frame == st->L_frame >> 1 ) && st->tcxonly && isTCX5 )
{
diff --git a/lib_dec/nelp_dec.c b/lib_dec/nelp_dec.c
index 77b3703d10d53fc757e57afbbd77497cf871c101..5ca7cf2547b7b6dca602451009fe939caaa0304c 100644
--- a/lib_dec/nelp_dec.c
+++ b/lib_dec/nelp_dec.c
@@ -155,7 +155,7 @@ void nelp_decoder(
if ( coder_type == UNVOICED && st->bwidth == NB )
{
- polezero_filter( ptr, ptr_tmp, L_FRAME, bp1_num_coef_nb_fx_order7, bp1_den_coef_nb_fx_order7, 7, hSC_VBR->bp1_filt_mem_nb_dec );
+ polezero_filter( ptr, ptr_tmp, L_FRAME, bp1_num_coef_nb_fx_order7_flt, bp1_den_coef_nb_fx_order7_flt, 7, hSC_VBR->bp1_filt_mem_nb_dec );
mvr2r( ptr_tmp, ptr, L_FRAME );
}
diff --git a/lib_dec/tns_base_dec.c b/lib_dec/tns_base_dec.c
index 444c465042ed8232f18414ca6b69a8355b0a9b8c..baa4c0dbecbead80f4a2e1a25b23dfb1349d3f5b 100644
--- a/lib_dec/tns_base_dec.c
+++ b/lib_dec/tns_base_dec.c
@@ -107,7 +107,7 @@ int16_t DecodeTnsData(
int16_t *pnSize,
STnsData *pTnsData )
{
- ResetTnsData( pTnsData );
+ ResetTnsData_flt( pTnsData );
if ( pTnsConfig->nMaxFilters > 1 )
{
diff --git a/lib_enc/SNR_calc_fx.c b/lib_enc/SNR_calc_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..360cc589b81359cc43abf9ad669c814ff2220cc7
--- /dev/null
+++ b/lib_enc/SNR_calc_fx.c
@@ -0,0 +1,543 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+
+#include
+#include "options.h"
+#include "options.h"
+#include "basop_util.h"
+#include "vad_basop.h"
+#include "prot_fx2.h"
+#include "rom_enc.h"
+
+
+ /*-------------------------------------------------------------------*
+ * calc_lf_snr()
+ *
+ *
+ *-------------------------------------------------------------------*/
+
+void calc_lf_snr(
+ Word32 *lf_snr_smooth, /* o : smoothed lf_snr*/
+ Word32 *lf_snr, /* o : long time frequency domain
+ SNR calculated by l_speech_snr and l_silence_snr*/
+ const Word32 l_speech_snr, /* i : sum of active frames snr */
+ const Word32 l_speech_snr_count, /* i : amount of the active frame */
+ const Word32 l_silence_snr, /* i : sum of the nonactive frames snr*/
+ const Word32 l_silence_snr_count,/* i : amount of the nonactive frame */
+ const Word16 fg_energy_count, /* i : amount of the foreground energy frame */
+ const Word16 bg_energy_count, /* i : amount of the background energy frame */
+ const Word16 bw_index /* i : band width index*/
+)
+{
+
+ Word32 l_snr, div1, div2, tmp;
+ Word16 q_divout, q_divout1;
+
+
+ div1 = VAD_L_div(l_speech_snr, l_speech_snr_count, 16, 0, &q_divout);
+ div2 = VAD_L_div(l_silence_snr, l_silence_snr_count, 16, 0, &q_divout1);
+ l_snr = VAD_L_ADD(div1, q_divout, L_negate(div2), q_divout1, &q_divout);
+
+ *lf_snr_smooth = MUL_F(*lf_snr_smooth, 29490/* 0.9 Q15 */);
+ move32();
+ tmp = MUL_F(l_snr, 26214);
+ *lf_snr_smooth = VAD_L_ADD(*lf_snr_smooth, 25, tmp, add(3, q_divout), &q_divout1);
+ move32();
+ *lf_snr_smooth = L_shr(*lf_snr_smooth, sub(q_divout1, 25));
+ move32();
+ l_snr = L_shr(l_snr, sub(q_divout, 25));
+
+ test();
+ if ((LT_16(bg_energy_count, 56)) || (LT_16(fg_energy_count, 56)))
+ {
+ l_snr = 161061275/* 4.8 Q25 */;
+ move32();
+ }
+
+ l_snr = MUL_F(l_snr, 3932/* 0.12 Q15 */);
+ l_snr = L_sub(l_snr, 12079595/* 0.36 Q25 */);
+
+ l_snr = L_max(0, l_snr);
+ l_snr = L_min(l_snr, MAX_LF_SNR_TAB[bw_index]);
+
+ *lf_snr = l_snr;
+ move32();
+ return;
+}
+/*-------------------------------------------------------------------*
+ * calc_lt_snr()
+ *
+ *
+ *-------------------------------------------------------------------*/
+void calc_lt_snr(
+ VAD_CLDFB_HANDLE hVAD_CLDFB, /* i/o: CLDFB VAD state */
+ Word32 *lt_snr_org_fp, /* o : original long time SNR*/
+ Word32 *lt_snr_fp, /* o : long time SNR calculated by fg_energy and bg_energy*/
+ Word32 fg_energy, /* i : foreground energy sum */
+ Word16 fg_energy_count, /* i : amount of the foreground energy frame */
+ Word32 bg_energy, /* i : background energy sum */
+ Word16 bg_energy_count, /* i : amount of the background energy frame */
+ Word16 bw_index, /* i : band width index*/
+ Word16 lt_noise_sp_center0 /* i : long time noise spectral center by 0*/
+)
+{
+ Word16 tmp_lt_noise_sp_center;
+ Word16 q_div1, q_div2, q_divout, q_divout1;
+ Word32 lt_snr_org;
+ Word32 lt_snr, div1, div2, tmp;
+
+
+ tmp_lt_noise_sp_center = sub(lt_noise_sp_center0, 1432/* 1.4 Q10 */);
+ if (GT_16(tmp_lt_noise_sp_center, 818/* 0.8 Q10 */))
+ {
+ tmp_lt_noise_sp_center = 818/* 0.8 Q10 */;
+ move16();
+ }
+
+ if (tmp_lt_noise_sp_center < 0)
+ {
+ tmp_lt_noise_sp_center = 0;
+ move16();
+ }
+
+ div1 = MUL_F(fg_energy, bg_energy_count);
+ div1 = VAD_L_ADD(div1, hVAD_CLDFB->fg_energy_scale, 1, 126, &q_div1);
+ div2 = MUL_F(bg_energy, fg_energy_count);
+ div2 = VAD_L_ADD(div2, hVAD_CLDFB->bg_energy_scale, 1, 126, &q_div2);
+ if (div2 == 0)
+ {
+ div2 = 1;
+ move32(); /* div2==0 , may occur for >30000 frames all zero input */
+ if (div1 != 0)
+ {
+ hVAD_CLDFB->bg_energy_scale = add(hVAD_CLDFB->fg_energy_scale, 50);
+ }
+ }
+ div2 = VAD_L_div(div1, div2, q_div1, q_div2, &q_divout);
+ lt_snr_org = VAD_Log2(div2, q_divout);
+ lt_snr_org = MUL_F(lt_snr_org, 9864);
+ lt_snr = lt_snr_org; move32();
+ *lt_snr_org_fp = lt_snr;
+ move32();
+
+ test();
+ IF(LT_16(bg_energy_count, 56) || LT_16(fg_energy_count, 56))
+ {
+ lt_snr = 70464302/* 2.1 Q25 */;
+ move32();
+ }
+
+ IF(EQ_16(bw_index, CLDFBVAD_NB_ID))
+ {
+ lt_snr = L_sub(L_shr(lt_snr, 1), 25165823/* 0.75 Q25 */);
+ }
+ ELSE IF(EQ_16(bw_index, CLDFBVAD_WB_ID))
+ {
+ lt_snr = L_sub(L_shr(lt_snr, 1), 25165823/* 0.75 Q25 */);
+ }
+ ELSE
+ {
+ lt_snr = MUL_F(lt_snr, 15073/* 0.46 Q15 */);
+ lt_snr = L_sub(lt_snr, 23152557/* 0.69 Q25 */);
+ }
+
+ tmp = MUL_F(lt_snr, 13107/* 0.4 Q15 */);
+
+ tmp = L_add(L_shr(tmp, 1), -26214);
+
+ tmp = MUL_F(tmp, 13107/* 0.4 Q15 */);
+ tmp = MUL_F(tmp, tmp_lt_noise_sp_center);
+ lt_snr = VAD_L_ADD(lt_snr, 25, tmp, 19, &q_divout1);
+ lt_snr = L_shr(lt_snr, sub(q_divout1, 25));
+
+ lt_snr = L_max(0, lt_snr);
+
+ if (GT_32(lt_snr, 67108862/* 2.0 Q25 */))
+ {
+ lt_snr = 67108862/* 2.0 Q25 */;
+ move32();
+ }
+
+ *lt_snr_fp = lt_snr;
+ move32();
+ return;
+}
+
+/*-------------------------------------------------------------------*
+ * calc_snr_flux()
+ *
+ *
+ *-------------------------------------------------------------------*/
+void calc_snr_flux(
+ Word32 tsnr, /* i : time-domain SNR*/
+ Word32 *pre_snr, /* i/o: time-domain SNR storage*/
+ Word32 *snr_flux_fp /* o : average tsnr*/
+)
+{
+ Word32 i;
+ Word32 tmp, snr_flux;
+ Word16 s16MaxCoefNorm;
+ /*save a new time-domain SNR to pre_snr[0]*/
+
+
+ test();
+ IF((LT_32(L_shr(tsnr, 1), 43620759/* 2.6f/2.0f Q25 */)) && tsnr > 0)
+ {
+ pre_snr[0] = tsnr;
+ move32();
+ }
+ ELSE IF(tsnr <= 0)
+ {
+ pre_snr[0] = 0;
+ move32();
+ }
+ ELSE
+ {
+ pre_snr[0] = 87241517/* 2.6 Q25 */;
+ move32();
+ }
+
+ /*calculate snr_flux*/
+ snr_flux = 0;
+ move32();
+ s16MaxCoefNorm = sub(ffr_getSfWord32(pre_snr, 32), 5);
+ FOR(i = 0; i < 32; i++)
+ {
+ tmp = L_shl(pre_snr[i], s16MaxCoefNorm);
+ snr_flux = L_add(snr_flux, tmp);
+ }
+ snr_flux = L_shr(snr_flux, add(s16MaxCoefNorm, 5));
+ *snr_flux_fp = snr_flux;
+ move32();
+
+ /*update the tsnr storage pre_snr*/
+ FOR(i = PRE_SNR_NUM - 1; i > 0; i--)
+ {
+ pre_snr[i] = pre_snr[i - 1];
+ move32();
+ }
+ return;
+
+}
+
+
+/*-------------------------------------------------------------------*
+ * SNR_calc()
+ *
+ *
+ *-------------------------------------------------------------------*/
+void snr_calc(
+ VAD_CLDFB_HANDLE hVAD_CLDFB, /* i/o: CLDFB VAD state */
+ const Word16 sacle_sbpower, /* i : the Scaling of sbpower*/
+ Word32 *snr, /* o : frequency domain SNR */
+ Word32* tsnr, /* o : time domain SNR */
+ const Word32 frame_energy, /* i : current frame energy */
+ const Word32 bwidth /* i : audio band width*/
+)
+{
+ Word32 i;
+ Word32 tmpframe_eg, tmpsb_eg, constff, div1, div2;
+ Word32 snr_tmp, tmp;
+
+ Word32 SNR_sb_num;
+ Word32 *sb_bg_energy;
+ Word32 *frame_sb_energy;
+ Word32 t_bg_energy;
+ Word16 tmp_addQ1, tmp_addQ2, minscale, minscale1, minscale2, s16MaxCoefNorm, q_divout;
+ Word32 tmpspec_amp;
+ Word32 const CONSTfix = 1759218560;
+ Word32 snr_tmpidx[12] = { 0 };
+
+
+ SNR_sb_num = SNR_SUB_BAND_NUM[bwidth - CLDFBVAD_NB_ID];
+ move16();
+ sb_bg_energy = hVAD_CLDFB->sb_bg_energy;
+ frame_sb_energy = hVAD_CLDFB->frame_sb_energy;
+ t_bg_energy = hVAD_CLDFB->t_bg_energy;
+ move32();
+
+ snr_tmp = 0;
+ move32();
+ FOR(i = 0; i < SNR_sb_num; i++)
+ {
+ div1 = VAD_L_ADD(frame_sb_energy[i], hVAD_CLDFB->frame_sb_energy_scale, CONSTfix, 44, &tmp_addQ1);
+ div2 = VAD_L_ADD(sb_bg_energy[i], hVAD_CLDFB->sb_bg_energy_scale, CONSTfix, 44, &tmp_addQ2);
+ tmp = VAD_L_div(div1, div2, tmp_addQ1, tmp_addQ2, &q_divout);
+ tmp = VAD_Log2(tmp, q_divout);
+
+ if (GT_32(tmp, -3355443/* -0.10 Q25 */))
+ {
+ snr_tmpidx[i] = tmp;
+ move32();
+ }
+ }
+
+ s16MaxCoefNorm = sub(ffr_getSfWord32(snr_tmpidx, (Word16)SNR_sb_num), 4);
+ FOR(i = 0; i < SNR_sb_num; i++)
+ {
+ tmpspec_amp = L_shl(snr_tmpidx[i], s16MaxCoefNorm);
+ snr_tmp = L_add(snr_tmp, tmpspec_amp);
+ }
+ snr_tmp = L_max(0, snr_tmp);
+ snr_tmp = MUL_F(snr_tmp, BAND_MUL[bwidth - CLDFBVAD_NB_ID]);
+ *snr = L_shr(snr_tmp, s16MaxCoefNorm);
+ move32();
+
+ IF(bwidth == CLDFBVAD_SWB_ID)
+ {
+ IF(t_bg_energy)
+ {
+ minscale = norm_l(t_bg_energy);
+ minscale2 = sub(s_min(add(minscale, hVAD_CLDFB->scale_t_bg_energy), 31), 1);
+ tmpsb_eg = L_shr(t_bg_energy, sub(hVAD_CLDFB->scale_t_bg_energy, minscale2));
+ constff = L_shr(1, sub(31, minscale2));
+ }
+ ELSE
+ {
+ tmpsb_eg = 0; move32();
+ constff = 1; move32();
+ minscale2 = 31;
+ move16();
+ }
+ div2 = L_add(tmpsb_eg, constff);
+ tmp = VAD_L_div(frame_energy, div2, sacle_sbpower, minscale2, &q_divout);
+ IF(tmp)
+ {
+ minscale = norm_l(tmp);
+ minscale2 = sub(s_min(add(minscale, q_divout), 31), 1);
+ tmpsb_eg = L_shr(tmp, limitScale32(sub(q_divout, minscale2)));
+ constff = L_shr(1, sub(31, minscale2));
+ tmp = L_add(tmpsb_eg, constff);
+ }
+ ELSE
+ {
+ tmp = 1; move32();
+ minscale2 = 31;
+ move16();
+ }
+ *tsnr = VAD_Log2(tmp, minscale2);
+ move32();
+ *tsnr = L_add(*tsnr, MUL_F(*tsnr, 6226)); /* *tsnr *= 1.2; */
+ move32();
+ }
+ ELSE
+ {
+ IF(frame_energy)
+ {
+ minscale = norm_l(frame_energy);
+ minscale1 = sub(s_min(add(minscale,sacle_sbpower),44),1);
+ tmpframe_eg = L_shr(frame_energy,sub(sacle_sbpower,minscale1));
+ constff = L_shr(CONSTfix,sub(44,minscale1));
+ }
+ ELSE
+ {
+ tmpframe_eg = 0; move32();
+ constff = CONSTfix; move32();
+ minscale1 = 44;
+ move16();
+ }
+ div1 = L_add(tmpframe_eg, constff);
+ IF(t_bg_energy)
+ {
+ minscale = norm_l(t_bg_energy);
+ minscale2 = sub(s_min(add(minscale,hVAD_CLDFB->scale_t_bg_energy),44),1);
+ tmpsb_eg = L_shr(t_bg_energy,sub(hVAD_CLDFB->scale_t_bg_energy,minscale2));
+ constff = L_shr(CONSTfix,sub(44,minscale2));
+ }
+ ELSE
+ {
+ tmpsb_eg = 0; move32();
+ constff = CONSTfix; move32();
+ minscale2 = 44;
+ move16();
+ }
+ div2 = L_add(tmpsb_eg, constff);
+ tmp = VAD_L_div(div1, div2, minscale1, minscale2, &q_divout);
+ *tsnr = VAD_Log2(tmp,q_divout);
+ move32();
+ }
+ return;
+}
+
+Word32 construct_snr_thresh(
+ Word16 sp_center[], /* i : spectral center*/
+ Word32 snr_flux, /* i : snr flux*/
+ Word32 lt_snr, /* i : long time time domain snr*/
+ Word32 l_snr, /* i : long time frequency domain snr*/
+ Word32 continuous_speech_num, /* i : amount of continuous speech frames*/
+ Word16 continuous_noise_num, /* i : amount of continuous noise frames*/
+ Word32 fg_energy_est_start, /* i : whether if estimated energy*/
+ Word16 bw_index /* i : band width index*/
+)
+{
+
+ Word32 bw_snr, tmp_snr, snr_delta, test_l_snr, tmp, div1, div2;
+
+
+
+
+ snr_delta = COMVAD_INIT_SNR_DELTA[bw_index];
+ move32();
+ bw_snr = lt_snr;
+ move32();
+
+
+
+ test_l_snr = lt_snr; move32();
+ IF(EQ_16(bw_index, CLDFBVAD_SWB_ID))
+ {
+
+ IF(GT_16(sp_center[3], 2864/* 2.80 Q10 */))
+ {
+ snr_delta = snr_delta;
+ move32();
+ }
+ ELSE IF(GT_16(sp_center[2], 2660/* 2.6 Q10 */))
+ {
+ snr_delta = L_add(snr_delta, 1006633/* 0.03 Q25 */);
+ }
+ ELSE IF(GT_16(sp_center[2], 1637/* 1.6 Q10 */))
+ {
+ snr_delta = L_add(snr_delta, 1677722/* 0.05 Q25 */);
+ }
+ ELSE IF(GT_16(sp_center[3], 1432/* 1.4 Q10 */))
+ {
+ snr_delta = L_add(snr_delta, 3355443/* 0.10 Q25 */);
+ }
+ ELSE
+ {
+ snr_delta = L_add(snr_delta , 13421773/* 0.40 Q25 */);
+ }
+
+ tmp = MUL_F(l_snr, 3277/* 0.1 Q15 */);
+ tmp = L_add(tmp, 20132659/* 0.6 Q25 */);
+
+ test();
+ test();
+ IF(GT_32(continuous_speech_num, 8) && EQ_32(fg_energy_est_start, 1))
+ {
+ snr_delta = L_sub(snr_delta, 6710886/* 0.2 Q25 */);
+ }
+ ELSE IF(GT_16(continuous_noise_num, 12) && (GT_32(snr_flux, tmp)))
+ {
+ snr_delta = L_add(snr_delta, 3355443/* 0.10 Q25 */);
+ }
+ ELSE IF(GT_16(continuous_noise_num, 24))
+ {
+ snr_delta = L_add(snr_delta, 6710886/* 0.2 Q25 */);
+ }
+ ELSE IF((GT_16(continuous_noise_num, 4)))
+ {
+ snr_delta = L_add(snr_delta, 3355443/* 0.10 Q25 */);
+ }
+ }
+ ELSE IF(EQ_16(bw_index, CLDFBVAD_WB_ID))
+ {
+
+ IF(GT_16(sp_center[3], 2864/* 2.80 Q10 */))
+ {
+ snr_delta = snr_delta;
+ move32();
+ }
+ ELSE IF(GT_16(sp_center[2], 2660/* 2.6 Q10 */))
+ {
+ snr_delta = L_add(snr_delta, 1006633/* 0.03 Q25 */);
+ }
+ ELSE IF(GT_16(sp_center[2], 1637/* 1.6 Q10 */))
+ {
+ snr_delta = L_add(snr_delta, 1677722/* 0.05 Q25 */);
+ }
+ ELSE IF(GT_16(sp_center[3], 1432/* 1.4 Q10 */))
+ {
+ snr_delta = L_add(snr_delta, 3355443/* 0.10 Q25 */);
+ }
+ ELSE
+ {
+ snr_delta = L_add(snr_delta, 10066330/* 0.30 Q25 */);
+ }
+
+ tmp = MUL_F(bw_snr, 3277/* 0.1 Q15 */);
+ tmp = L_add(tmp, 20132659/* 0.6 Q25 */);
+
+ test();
+ test();
+ IF(GT_32(continuous_speech_num, 8) && EQ_32(fg_energy_est_start, 1))
+ {
+ snr_delta = L_sub(snr_delta, 3355443/* 0.10 Q25 */);
+ }
+ ELSE IF(GT_16(continuous_noise_num, 12) && (GT_32(snr_flux, tmp)))
+ {
+ snr_delta = L_add(snr_delta, 3355443/* 0.10 Q25 */);
+ }
+ ELSE IF(GT_16(continuous_noise_num, 24))
+ {
+ snr_delta = L_add(snr_delta, 6710886/* 0.20 Q25 */);
+ }
+ ELSE IF((GT_16(continuous_noise_num, 4)))
+ {
+ snr_delta = L_add(snr_delta, 3355443/* 0.10 Q25 */);
+ }
+ }
+ ELSE IF(EQ_16(bw_index, CLDFBVAD_NB_ID))
+ {
+
+ IF(GT_16(sp_center[3], 3069/* 3.0 Q10 */))
+ {
+ snr_delta = snr_delta;
+ move32();
+ }
+ ELSE IF(GT_16(sp_center[2], 2660/* 2.6 Q10 */))
+ {
+ snr_delta = L_add(snr_delta, 671089/* 0.02 Q25 */);
+ }
+ ELSE IF(GT_16(sp_center[2], 1637/* 1.6 Q10 */))
+ {
+ snr_delta = L_add(snr_delta, 1342177/* 0.04 Q25 */);
+ }
+ ELSE IF(GT_16(sp_center[2], 1494/* 1.46 Q10 */))
+ {
+ snr_delta = L_add(snr_delta, 3355443/* 0.10 Q25 */);
+ }
+ ELSE
+ {
+ snr_delta = L_add(snr_delta , 6039798/* 0.18 Q25 */);
+ }
+
+ tmp = MUL_F(l_snr, 3277/* 0.1 Q15 */);
+ div1 = L_add(tmp, 6710886/* 0.2 Q25 */);
+ div2 = L_add(tmp, 20132659/* 0.6 Q25 */);
+
+ test();
+ test();
+ test();
+ test();
+ test();
+ IF(GT_32(continuous_speech_num, 80) && EQ_32(fg_energy_est_start, 1) && (GT_16(sp_center[0], 1432/* 1.4 Q10 */)))
+ {
+ snr_delta = L_sub(snr_delta, 10737418/* 0.32 Q25 */);
+ }
+ ELSE IF(GT_32(continuous_speech_num, 8) && EQ_32(fg_energy_est_start, 1) && (GT_32(snr_flux, div1)))
+ {
+ snr_delta = L_sub(snr_delta, 3355443/* 0.10 Q25 */);
+ }
+ ELSE IF(GT_16(continuous_noise_num, 12) && (GT_32(snr_flux, div2)))
+ {
+ snr_delta = L_add(snr_delta, 3355443/* 0.10 Q25 */);
+ }
+ ELSE IF(GT_16(continuous_noise_num, 24))
+ {
+ snr_delta = L_add(snr_delta, 6710886/* 0.2 Q25 */);
+ }
+ }
+ ELSE
+ {
+ snr_delta = 33554431/* 1.0 Q25 */;
+ move32();
+ }
+ tmp_snr = L_add(snr_delta, test_l_snr);
+
+
+ return tmp_snr;
+}
+
diff --git a/lib_enc/cod_tcx.c b/lib_enc/cod_tcx.c
index ffb45d9e922b262502449f891654a5adb95be532..d8fd90f9fa16600f5c20cf22febdaa7c08113767 100644
--- a/lib_enc/cod_tcx.c
+++ b/lib_enc/cod_tcx.c
@@ -165,7 +165,7 @@ void TNSAnalysisStereo(
}
/* WMOPS: All initializations are either for safety or static (tables) and thus not to be counted */
- ResetTnsData( &hTcxEnc->tnsData[k] );
+ ResetTnsData_flt( &hTcxEnc->tnsData[k] );
if ( st->hTcxCfg->pCurrentTnsConfig->maxOrder <= 0 )
{
break;
@@ -356,8 +356,8 @@ void TNSAnalysisStereo(
sts[1]->hTcxEnc->fUseTns[k] = 0;
for ( iFilter = sts[0]->hTcxCfg->pCurrentTnsConfig->nMaxFilters - 1; iFilter >= 0; iFilter-- )
{
- ClearTnsFilterCoefficients( sts[0]->hTcxEnc->tnsData[k].filter + iFilter );
- ClearTnsFilterCoefficients( sts[1]->hTcxEnc->tnsData[k].filter + iFilter );
+ ClearTnsFilterCoefficients_flt( sts[0]->hTcxEnc->tnsData[k].filter + iFilter );
+ ClearTnsFilterCoefficients_flt( sts[1]->hTcxEnc->tnsData[k].filter + iFilter );
}
}
maxPredictionGain = max( maxPredictionGain, maxPredGain );
@@ -438,7 +438,7 @@ void TNSAnalysisStereo(
sts[ch]->hTcxEnc->tnsData[k].nFilters = 0;
for ( iFilter = sts[ch]->hTcxCfg->pCurrentTnsConfig->nMaxFilters - 1; iFilter >= 0; iFilter-- )
{
- ClearTnsFilterCoefficients( sts[ch]->hTcxEnc->tnsData[k].filter + iFilter );
+ ClearTnsFilterCoefficients_flt( sts[ch]->hTcxEnc->tnsData[k].filter + iFilter );
sts[ch]->hTcxEnc->tnsData[k].filter[iFilter].filterType = TNS_FILTER_OFF;
}
}
@@ -471,11 +471,11 @@ void TNSAnalysisStereo(
switch ( pFilter->filterType )
{
case TNS_FILTER_OFF:
- ClearTnsFilterCoefficients( sts[ch]->hTcxEnc->tnsData[k].filter + iFilter );
+ ClearTnsFilterCoefficients_flt( sts[ch]->hTcxEnc->tnsData[k].filter + iFilter );
break;
case TNS_FILTER_ON_ZERO:
/* Since TNS filter of order 0 is not allowed we have to signal in the stream filter of order 1 with the 0th coefficient equal to 0 */
- ClearTnsFilterCoefficients( pFilter );
+ ClearTnsFilterCoefficients_flt( pFilter );
pFilter->order = 1;
break;
}
@@ -539,7 +539,7 @@ void TNSAnalysisStereo(
{
st->hTcxCfg->pCurrentTnsConfig = &st->hTcxCfg->tnsConfig[st->hTcxEnc->transform_type[k] == TCX_20][( k == 0 ) && ( st->last_core == ACELP_CORE )];
- ApplyTnsFilter( st->hTcxCfg->pCurrentTnsConfig, &st->hTcxEnc->tnsData[k], spectrum, 1 );
+ ApplyTnsFilter_flt( st->hTcxCfg->pCurrentTnsConfig, &st->hTcxEnc->tnsData[k], spectrum, 1 );
}
if ( st->hTcxEnc->transform_type[k] == TCX_5 )
@@ -621,7 +621,7 @@ void TNSAnalysis(
/* If TNS should be used then get the residual after applying it inplace in the spectrum */
if ( *pfUseTns )
{
- ApplyTnsFilter( hTcxCfg->pCurrentTnsConfig, pTnsData, spectrum, 1 );
+ ApplyTnsFilter_flt( hTcxCfg->pCurrentTnsConfig, pTnsData, spectrum, 1 );
}
if ( transform_type == TCX_5 )
@@ -700,7 +700,7 @@ void ShapeSpectrum(
}
}
- tcxGetNoiseFillingTilt( A, L_frame, ( total_brate >= ACELP_13k20 && !st->rf_mode ), &st->hTcxEnc->noiseTiltFactor_flt);
+ tcxGetNoiseFillingTilt_flt( A, L_frame, ( total_brate >= ACELP_13k20 && !st->rf_mode ), &st->hTcxEnc->noiseTiltFactor_flt);
/* Calculate Spectrum Flatness Measure for the TCX Concealment */
if ( st->enablePlcWaveadjust )
@@ -1657,7 +1657,7 @@ void InternalTCXDecoder(
/* Replication of ACELP formant enhancement for low rates */
if ( st->total_brate < ACELP_13k20 || st->rf_mode )
{
- tcxFormantEnhancement( lf_deemph_fact, gainlpc, spectrum, L_frame );
+ tcxFormantEnhancement_flt( lf_deemph_fact, gainlpc, spectrum, L_frame );
}
/*-----------------------------------------------------------*
@@ -1666,7 +1666,7 @@ void InternalTCXDecoder(
if ( fac_ns > 0.0f )
{
- iStart = tcxGetNoiseFillingTilt( A, L_frame, ( st->total_brate >= ACELP_13k20 && !st->rf_mode ), &hTcxEnc->noiseTiltFactor_flt);
+ iStart = tcxGetNoiseFillingTilt_flt( A, L_frame, ( st->total_brate >= ACELP_13k20 && !st->rf_mode ), &hTcxEnc->noiseTiltFactor_flt);
noiseTransWidth = GetTransWidth( st->tcxonly, ( L_frame == st->L_frame >> 1 ), hTcxEnc->tcxltp_gain_flt, ( st->hTcxCfg->ctx_hm && st->last_core != ACELP_CORE && hm_active ) );
assert( st->element_mode != IVAS_CPE_MDCT );
@@ -1724,7 +1724,7 @@ void InternalTCXDecoder(
L = L_spec;
}
- tcxInvertWindowGrouping( st->hTcxCfg, xn_buf, spectrum, L, hTcxEnc->fUseTns[frame_cnt], st->last_core, tcx_last_overlap_mode, frame_cnt, 0 );
+ tcxInvertWindowGrouping_flt( st->hTcxCfg, xn_buf, spectrum, L, hTcxEnc->fUseTns[frame_cnt], st->last_core, tcx_last_overlap_mode, frame_cnt, 0 );
}
/*-----------------------------------------------------------*
@@ -1738,7 +1738,7 @@ void InternalTCXDecoder(
/* Apply TNS to get the reconstructed signal */
if ( hTcxEnc->fUseTns[frame_cnt] != 0 )
{
- ApplyTnsFilter( st->hTcxCfg->pCurrentTnsConfig, &hTcxEnc->tnsData[frame_cnt], spectrum, 0 );
+ ApplyTnsFilter_flt( st->hTcxCfg->pCurrentTnsConfig, &hTcxEnc->tnsData[frame_cnt], spectrum, 0 );
if ( ( L_frame == st->L_frame >> 1 ) && ( st->tcxonly ) )
{
diff --git a/lib_enc/detect_transient_fx.c b/lib_enc/detect_transient_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..bab7a501fb9d9b8f86a6548e3be46496382ccd61
--- /dev/null
+++ b/lib_enc/detect_transient_fx.c
@@ -0,0 +1,434 @@
+/******************************************************************************************************
+
+ (C) 2022-2023 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.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+#include
+#include "options.h" /* Compilation switches */
+#include "cnst.h" /* Common constants */
+#include "rom_com_fx.h" /* Static table prototypes */
+#include "prot_fx2.h" /* Function prototypes */
+
+ /*--------------------------------------------------------------------------*/
+ /* Function hp_filter */
+ /* ~~~~~~~~~~~~~~~~~~~~ */
+ /* */
+ /* High pass filter */
+ /*--------------------------------------------------------------------------*/
+ /* float x (i) in Q_new input to filter */
+ /* float y (o) in Q_new +2 output of filter */
+ /* float *oldy (i/o) previous output of filter */
+ /* float *oldx (i/o) in Q_memx previous input of filter */
+ /* short L (i) in Q_memx +2 length (32 or 48 kHz) */
+ /*--------------------------------------------------------------------------*/
+
+static void hp_filter_fx(
+ const Word16 *x, /*Q_new */
+ Word16 *y, /*Q_new */
+ Word16 *oldy, /*Q_new */
+ Word16 *oldx, /*Q_new */
+ const Word16 L
+)
+{
+ Word16 i;
+ Word32 L_tmp;
+#ifdef BASOP_NOGLOB_DECLARE_LOCAL
+ Flag Overflow = 0;
+#endif
+
+
+ /*y[0] = 0.4931f * *oldy + 0.7466f*(x[0] - *oldx); */
+#ifdef BASOP_NOGLOB
+ L_tmp = L_mult(sub_o(x[0], *oldx, &Overflow), 24465);/*Q_new+16 */
+#else /* BASOP_NOGLOB */
+ L_tmp = L_mult(sub(x[0], *oldx), 24465);/*Q_new+16 */
+#endif /* BASOP_NOGLOB */
+ L_tmp = L_mac(L_tmp, *oldy, 16158);/*Q_new+16 */
+ y[0] = round_fx(L_tmp);/*Q_new */
+
+ FOR(i = 1; i < L; i++)
+ {
+ /*y[i] = 0.4931f*y[i-1] + 0.7466f*(x[i] - x[i-1]); */
+#ifdef BASOP_NOGLOB
+ L_tmp = L_mult(sub_o(x[i], x[i - 1], &Overflow), 24465);/*Q_new+16 */
+ L_tmp = L_mac_o(L_tmp, y[i - 1], 16158, &Overflow);/*Q_new+16 */
+ y[i] = round_fx_o(L_tmp, &Overflow); /*Q_new */
+#else /* BASOP_NOGLOB */
+ L_tmp = L_mult(sub(x[i], x[i - 1]), 24465);/*Q_new+16 */
+ L_tmp = L_mac(L_tmp, y[i - 1], 16158);/*Q_new+16 */
+ y[i] = round_fx(L_tmp); /*Q_new */
+#endif /* BASOP_NOGLOB */
+ }
+
+ *oldx = x[L - 1];
+ move16();/*Q_new */
+ *oldy = y[L - 1];
+ move16();/*Q_new */
+
+}
+/*--------------------------------------------------------------------------*/
+/* Function detect_transient */
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+/* */
+/* Detect if the signal is a transient */
+/*--------------------------------------------------------------------------*/
+/* float in[] (i) input signal Q_new */
+/* Encoder_State *st (i/o) state of coder */
+/* short L (i) length (32 or 48 kHz) */
+/*--------------------------------------------------------------------------*/
+/* short return (o) result of transient check */
+/*--------------------------------------------------------------------------*/
+
+Word16 detect_transient_fx(
+ const Word16 *in_fx, /*Q_new */
+ const Word16 L,
+ Word16 Q_new,
+ Encoder_State *st_fx
+)
+{
+ Word32 Energy, L_tmp;
+ Word32 EnergyLT;
+ Word16 i, blk;
+ Word16 IsTransient;
+ Word16 out_filt_fx[L_FRAME48k];
+ Word16 position = 0;
+ Word16 thr;
+ Word32 L_tmp2;
+ Word16 shift;
+ Word32 Energy_fx, E_in_fx = 0, E_out_fx = 0, Energy_in_fx[5] = { 0,0,0,0,0 }; /* Energy_fx can be replaced by Energy */
+ Word32 E_low_fx, E_high_fx;
+ Word16 temp16, Thres_fx = 0;
+ Word16 exp;
+#ifdef BASOP_NOGLOB_DECLARE_LOCAL
+ Flag Overflow = 0;
+#endif
+
+ shift = 0;
+ move16();
+
+ IsTransient = 0;
+ move16();
+ IF(NE_16(st_fx->last_extl, st_fx->extl))
+ {
+ st_fx->TransientHangOver = 0;
+ move16();
+ st_fx->old_hpfilt_in_fx = 0;
+ move16();
+ st_fx->old_hpfilt_out_fx = 0;
+ move16();
+ }
+
+ /* High pass filter */
+ hp_filter_fx(in_fx, out_filt_fx, &(st_fx->old_hpfilt_in_fx), &(st_fx->old_hpfilt_out_fx), L);
+
+ /* Long term energy */
+ test();
+ test();
+ test();
+ IF(NE_16(st_fx->last_extl, st_fx->extl) || (EQ_16(st_fx->last_extl, st_fx->extl) && NE_16(st_fx->last_core, st_fx->core)) || EQ_16(st_fx->last_codec_mode, MODE2))
+ {
+ /*EnergyLT = EPSILON_FX; */
+ EnergyLT = L_deposit_l(0);
+ FOR(i = 0; i < L / 4; i++)
+ {
+ /*EnergyLT += out_filt[i] * out_filt[i]; */
+#ifdef BASOP_NOGLOB
+ EnergyLT = L_mac0_o(EnergyLT, out_filt_fx[i], out_filt_fx[i], &Overflow); /*2Q_new */
+#else
+ EnergyLT = L_mac0(EnergyLT, out_filt_fx[i], out_filt_fx[i]); /*2Q_new */
+#endif
+ }
+ }
+ ELSE
+ {
+ EnergyLT = L_add(st_fx->EnergyLT_fx, 0); /*2Q_new */
+ }
+ IF(EQ_16(L, L_FRAME8k))
+ {
+ Energy_in_fx[0] = st_fx->Energy_Old_fx;
+ move32();
+ /* Compute block energy */
+ FOR(blk = 0; blk < 4; blk++)
+ {
+ Energy_fx = L_deposit_l(0);
+ Energy_in_fx[blk + 1] = L_deposit_l(0);
+ FOR(i = 0; i < L / 4; i++)
+ {
+ temp16 = extract_l(L_shr(out_filt_fx[i + blk * (L / 4)], 12));
+#ifdef BASOP_NOGLOB
+ Energy_fx = L_add_o(Energy_fx, L_mult0(temp16, temp16), &Overflow);
+#else
+ Energy_fx = L_add(Energy_fx, L_mult0(temp16, temp16));
+#endif
+ temp16 = shr(in_fx[i + blk * (L / 4)], Q_new);
+#ifdef BASOP_NOGLOB
+ Energy_in_fx[blk + 1] = L_add_o(Energy_in_fx[blk + 1], L_mult0(temp16, temp16), &Overflow);
+#else
+ Energy_in_fx[blk + 1] = L_add(Energy_in_fx[blk + 1], L_mult0(temp16, temp16));
+#endif
+ move32();
+ }
+
+#ifdef BASOP_NOGLOB
+ E_in_fx = L_add_o(E_in_fx, Energy_in_fx[blk + 1], &Overflow);
+ E_out_fx = L_add_o(E_out_fx, Energy_fx, &Overflow);
+#else
+ E_in_fx = L_add(E_in_fx, Energy_in_fx[blk + 1]);
+ E_out_fx = L_add(E_out_fx, Energy_fx);
+#endif
+
+ Thres_fx = 2185;/*1 /15 */
+ move16();
+ IF(GT_32(Mult_32_16(Energy_fx, 5461), EnergyLT))
+ {
+ IsTransient = 1;
+ move16();
+ position = blk;
+ move16();
+ }
+
+ EnergyLT = L_add(Mult_32_16(EnergyLT, 24576), Mult_32_16(Energy_fx, 8192));
+ }
+ }
+ ELSE
+ {
+ /* Compute block energy */
+ FOR(blk = 0; blk < 4; blk++)
+ {
+ L_tmp = L_deposit_l(0);
+ FOR(i = 0; i < L / 8; i++)
+ {
+ /*Energy += out_filt_fx[i + blk*(L/4)] * out_filt_fx[i + blk*(L/4)]; */
+#ifdef BASOP_NOGLOB
+ L_tmp = L_mac0_o(L_tmp, out_filt_fx[i + blk * (L / 4)], out_filt_fx[i + blk * (L / 4)], &Overflow); /*2Q_new */
+#else
+ L_tmp = L_mac0(L_tmp, out_filt_fx[i + blk * (L / 4)], out_filt_fx[i + blk * (L / 4)]); /*2Q_new */
+#endif
+ }
+ L_tmp2 = L_deposit_l(0);
+ FOR(; i < L / 4; i++)
+ {
+ /*Energy += out_filt_fx[i + blk*(L/4)] * out_filt_fx[i + blk*(L/4)]; */
+#ifdef BASOP_NOGLOB
+ L_tmp2 = L_mac0_o(L_tmp2, out_filt_fx[i + blk * (L / 4)], out_filt_fx[i + blk * (L / 4)], &Overflow); /*2Q_new */
+#else
+ L_tmp2 = L_mac0(L_tmp2, out_filt_fx[i + blk * (L / 4)], out_filt_fx[i + blk * (L / 4)]); /*2Q_new */
+#endif
+ }
+ Overflow = 0;
+ move16();
+#ifdef BASOP_NOGLOB /* Critical Overflow */
+ Energy = L_add_o(L_tmp, L_tmp2, &Overflow);
+#else
+ Energy = L_add(L_tmp, L_tmp2);
+#endif
+ shift = 0;
+ if (Overflow != 0)
+ {
+ shift = 1;
+ move16();
+ }
+ Overflow = 0;
+ move16();
+
+#ifdef BASOP_NOGLOB /* shift is >= 0, not overflow possible for shr */
+ Energy = L_add_o(L_shr(L_tmp, shift), L_shr(L_tmp2, shift), &Overflow);
+#else
+ Energy = L_add(L_shr(L_tmp, shift), L_shr(L_tmp2, shift));
+#endif
+ test();
+ IF(EQ_16(st_fx->extl,SWB_BWE) || EQ_16(st_fx->extl,FB_BWE))
+ {
+ /*Calculate shift to get to Q0*/
+ test();
+ test();
+ IF((GT_32(Mult_32_16(Energy, shl(2427, shift)), EnergyLT)) || (GT_32(Mult_32_16(Energy,shl(3277,shift)),EnergyLT)
+ && EQ_16(st_fx->core,ACELP_CORE) && EQ_16(st_fx->coder_type,INACTIVE)))
+ {
+ IsTransient = 1;
+ move16();
+ position = blk;
+ move16();
+ }
+ }
+ ELSE
+ {
+ test();
+ IF(LE_32(st_fx->total_brate,HQ_16k40) && EQ_16(st_fx->bwidth,SWB))
+ {
+ thr = 2427;
+ move16();
+ }
+ ELSE
+ {
+ thr = 5461;
+ move16();
+ }
+ thr = shl(thr, shift);
+ /*if(Energy > L_shr(Mult_32_16(EnergyLT,22624),shift_cnt)) //getting in Q0 32*16 = Q_inp1+Q_inp2+1-16 */
+ IF(GT_32(Mult_32_16(Energy, thr),EnergyLT))
+ /*if(Energy > 6.0f * EnergyLT) */
+ {
+ IsTransient = 1;
+ move16();
+ position = blk;
+ move16();
+ }
+ }
+ /*EnergyLT = 0.75f*EnergyLT + 0.25f*Energy; */
+ /*0.75f*EnergyLT in Q0 //0.25f*Energy in Q0 */
+ #ifdef BASOP_NOGLOB
+ EnergyLT = L_add_o(Mult_32_16(EnergyLT,24576),Mult_32_16(Energy, shl(8192, shift)), &Overflow); /*2Q_new */
+ #else /* BASOP_NOGLOB */
+ EnergyLT = L_add(Mult_32_16(EnergyLT,24576),Mult_32_16(Energy, shl(8192, shift))); /*2Q_new */
+ #endif
+ }
+ }
+ st_fx->EnergyLT_fx = EnergyLT;
+ move32();
+
+ test();
+ test();
+ test();
+ test();
+ test();
+ if ((NE_16(st_fx->last_extl, SWB_BWE) && NE_16(st_fx->last_extl, SWB_TBE) && EQ_16(st_fx->extl, SWB_BWE)) ||
+ (NE_16(st_fx->last_extl, FB_BWE) && NE_16(st_fx->last_extl, FB_TBE) && EQ_16(st_fx->extl, FB_BWE)))
+ {
+ IsTransient = 0;
+ move16();
+ }
+
+ test();
+ IF(IsTransient && L == L_FRAME8k)
+ {
+ blk = 0;
+ move16();
+ E_low_fx = L_deposit_l(0);
+ FOR(i = 0; i < position + 1; i++)
+ {
+ /*blk++; */
+ blk = add(blk, 1);
+ E_low_fx = L_add(E_low_fx, Energy_in_fx[i]);
+ }
+
+ exp = norm_s(blk);
+ temp16 = div_s(16384, shl(blk, exp));/* 15 + 14 - exp; */
+ exp = 15 + 14 - exp;
+ temp16 = shl(temp16, sub(15, exp));
+ E_low_fx = Mult_32_16(E_low_fx, temp16);
+
+ blk = 0;
+ move16();
+ E_high_fx = L_deposit_l(0);
+ FOR(i = position + 1; i < 5; i++)
+ {
+ /*blk++; */
+ blk = add(blk, 1);
+ E_high_fx = L_add(E_high_fx, Energy_in_fx[i]);
+ }
+
+ exp = norm_s(blk);
+ temp16 = div_s(16384, shl(blk, exp));/* 15 + 14 - exp; */
+ exp = 15 + 14 - exp;
+ temp16 = shl(temp16, 15 - exp);
+ E_high_fx = Mult_32_16(E_high_fx, temp16);
+
+ test();
+ test();
+ IF(LT_32(L_shr(E_high_fx, 1), E_low_fx) && GT_32(E_high_fx, Mult_32_16(E_low_fx, 22938)) && GT_32(Mult_32_16(E_in_fx, Thres_fx), E_out_fx))
+ {
+ IsTransient = 0;
+ move16();
+ }
+ }
+ IF(EQ_32(st_fx->core_brate, ACELP_24k40))
+ {
+ test();
+ IF(NE_16(st_fx->last_core, HQ_CORE) || NE_32(st_fx->last_core_brate, ACELP_24k40))
+ {
+ st_fx->TransientHangOver = 0;
+ move16();
+ IsTransient = 0;
+ move16();
+ }
+ ELSE
+ {
+ IF(IsTransient)
+ {
+ IF(EQ_16(position,3))
+ {
+ /* Set Hangover */
+ st_fx->TransientHangOver = 1;
+ move16();
+ }
+ }
+ ELSE
+ {
+ IF(st_fx->TransientHangOver)
+ {
+ st_fx->TransientHangOver = 0;
+ move16();
+ IsTransient = 1;
+ move16();
+ }
+ }
+ }
+ }
+ ELSE
+ {
+ IF(IsTransient)
+ {
+ st_fx->TransientHangOver = 1;
+ move16();
+ }
+ ELSE
+ {
+ IF(st_fx->TransientHangOver)
+ {
+ st_fx->TransientHangOver = 0;
+ move16();
+ IsTransient = 1;
+ move16();
+ }
+ }
+ }
+
+ IF(EQ_16(L, L_FRAME8k))
+ {
+ st_fx->Energy_Old_fx = Energy_in_fx[4];
+ move32();
+ }
+
+ return IsTransient;
+}
diff --git a/lib_enc/enc_ppp_fx.c b/lib_enc/enc_ppp_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..00f7991d757ac927b9283e5ba3ad281bdc9face1
--- /dev/null
+++ b/lib_enc/enc_ppp_fx.c
@@ -0,0 +1,235 @@
+///*====================================================================================
+// EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+// ====================================================================================*/
+//#include
+//#include "options.h" /* Compilation switches */
+//#include "cnst.h" /* Common constants */
+//#include "prot_fx2.h" /* Function prototypes */
+//
+// /*Temporary location to be move in prot* when merge is done */
+//void E_LPC_f_lsp_a_conversion(const Word16 *lsp, Word16 *a, const Word16 m);
+//
+///*=======================================================================================*/
+///* FUNCTION : encod_ppp_fx() */
+///*---------------------------------------------------------------------------------------*/
+///* PURPOSE : */
+///*---------------------------------------------------------------------------------------*/
+///* INPUT ARGUMENTS : */
+///* _ (Word16) speech_fx[], i : input speech Q_new */
+///* _ (Word16) Aq_fx[], i : 12k8 Lp coefficient Q12 */
+///* _ (Word16) A_fx[], i : unquantized A(z) filter with bandwidth expansion Q12*/
+///* _ (Word16) coder_type_fx, i : coding type */
+///* _ (Word16) T_op_fx[], i : open loop pitch */
+///* _ (Word16) voicing_fx[], i : voicing Q15 */
+///* _ (Word16) *res_fx, i : residual signal Q_new */
+///* _ (Word16) Q_new i : Q factor for res */
+///* _ (Word16) vadsnr_fx i : SNR for current frame Q7 */
+///*---------------------------------------------------------------------------------------*/
+///* OUTPUT ARGUMENTS : */
+///* _ (Word16) *exc2_fx, o : current enhanced excitation Q0 */
+///* _ (Word16) *pitch_buf_fx, o : floating pitch values for each subframe Q6 */
+///* _ (Word16) *synth_fx, o : core synthesis Q-1 */
+///* _ Encoder_State_fx *st_fx: */
+///* _ lastLgainE_fx - Q11 */
+///* _ lastHgainE_fx - Q11 */
+///* _ lasterbE_fx - Q13 */
+///*---------------------------------------------------------------------------------------*/
+///* INPUT/OUTPUT ARGUMENTS : */
+///* _ Encoder_State_fx *st_fx: */
+///* _ st_fx->dtfs_enc_xxxx */
+///* _ a nd b in st_fx->dtfs_enc_Q */
+///* rest all in Q0 */
+///* - bump_up_fx - Q0 */
+///* _ (Word16) *exc_fx, o : current enhanced excitation Q0 */
+///*---------------------------------------------------------------------------------------*/
+///* RETURN ARGUMENTS : */
+///* _ None. */
+///*---------------------------------------------------------------------------------------*/
+///* CALLED FROM : TX */
+///*=======================================================================================*/
+//ivas_error encod_ppp_fx(
+// Encoder_State* st_fx, /* i/o: state structure */
+// const Word16 speech_fx[], /* i : input speech Q_new*/
+// const Word16 Aw_fx[], /* i : weighted A(z) unquantized for subframes */
+// const Word16 Aq_fx[], /* i : 12k8 Lp coefficient */
+// Word16 *res_fx, /* i : residual signal Q_new*/
+// Word16 *synth_fx, /* o : core synthesis Q-1*/
+// Word16 *exc_fx, /* i/o: current non-enhanced excitation Q_new*/
+// Word16 *exc2_fx, /* o : current enhanced excitation Q0*/
+// Word16 *pitch_buf_fx, /* o : floating pitch values for each subframe Q6*/
+// Word16 *voice_factors, /* o : voicing factors */
+// Word16 *bwe_exc, /* o : excitation for SWB TBE */
+// Word16 Q_new,
+// Word16 shift
+//)
+//{
+// Word16 xn_fx[L_SUBFR]; /* Target vector for pitch search */
+// Word16 h1_fx[L_SUBFR + (M + 1)]; /* Impulse response vector */
+// Word16 i_subfr; /* tmp variables */
+// const Word16 *p_Aw_fx, *p_Aq_fx; /* pointer to LP filter coeff. vector*/
+//
+// Word16 k;
+// Word16 p_Aq_old_fx[M + 1], excQ_ppp_fx[L_FRAME], p_Aq_curr_fx[M], pitch_fx[NB_SUBFR];
+// Word16 LPC_de_old_fx[M + 1], LPC_de_curr_fx[M + 1];
+// Word16 shift_wsp = add(Q_new, shift);
+// Word16 rate_ctrl_fx;
+// Word16 saved_Q_new = Q_new;
+// LPD_state_HANDLE hLPDmem = st_fx->hLPDmem;
+// SC_VBR_ENC_HANDLE hSC_VBR = st_fx->hSC_VBR;
+// BSTR_ENC_HANDLE hBstr = st_fx->hBstr;
+// ivas_error error;
+//
+// error = IVAS_ERR_OK;
+// move16();
+// rate_ctrl_fx = hSC_VBR->rate_control;
+// move16();
+//
+// /*------------------------------------------------------------------*
+// * ACELP subframe loop
+// *------------------------------------------------------------------*/
+// p_Aw_fx = Aw_fx;
+// p_Aq_fx = Aq_fx;
+// FOR(i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)
+// {
+// /*----------------------------------------------------------------*
+// * Bandwidth expansion of A(z) filter coefficients
+// * Find the the excitation search target "xn" and innovation
+// * target in residual domain "cn"
+// * Compute impulse response, h1[], of weighted synthesis filter
+// *----------------------------------------------------------------*/
+//
+// Copy(&res_fx[i_subfr], &exc_fx[i_subfr], L_SUBFR);
+//
+// find_targets_fx(speech_fx, hLPDmem->mem_syn, i_subfr, &hLPDmem->mem_w0, p_Aq_fx,
+// res_fx, L_SUBFR, p_Aw_fx, TILT_FAC_FX, xn_fx, NULL, h1_fx);
+//
+// /* scale xn[] and h1[] to avoid overflow in dot_product12() */
+// Scale_sig(xn_fx, L_SUBFR, shift); /* scaling of xn[] to limit dynamic at 12 bits */
+//
+// /* call voiced encoder at this point */
+// IF(i_subfr == 0) /* generate the L_FRAME exc */
+// {
+// FOR(k = 0; k < M; k++)
+// {
+// p_Aq_curr_fx[k] = p_Aq_fx[k + (3 * (M + 1)) + 1];
+// move16();
+// }
+//
+// E_LPC_f_lsp_a_conversion(st_fx->lsp_old_fx, p_Aq_old_fx, M);
+// deemph_lpc_fx(p_Aq_curr_fx, p_Aq_old_fx, LPC_de_curr_fx, LPC_de_old_fx, 1);
+// /* both outputs LPC_de_curr_fx and LPC_de_old_fx are in Q12 */
+//
+//
+// /* last frame-end lpc and curr frame-end lpc */
+// IF((error = ppp_voiced_encoder_fx(hBstr, hSC_VBR, st_fx->bwidth, st_fx->last_coder_type_raw, st_fx->old_pitch_buf_fx, res_fx,
+// excQ_ppp_fx, st_fx->pitch_fx[1], LPC_de_old_fx, LPC_de_curr_fx, exc_fx, pitch_fx, Q_new)) != IVAS_ERR_OK)
+// {
+// return error;
+// }
+//
+// Scale_sig(exc_fx, L_FRAME, (saved_Q_new - Q_new));
+// if (EQ_16(hSC_VBR->bump_up, 1))
+// {
+// i_subfr = L_FRAME;
+// move16();
+// }
+// }
+//
+// IF(NE_16(hSC_VBR->bump_up, 1))
+// {
+// /*-----------------------------------------------------------------*
+// * Gain clipping test to avoid unstable synthesis on frame erasure
+// * or in case of floating point encoder & fixed p. decoder
+// *-----------------------------------------------------------------*/
+// gp_clip_fx(st_fx->element_mode, st_fx->core_brate, st_fx->voicing_fx, i_subfr, st_fx->coder_type, xn_fx, st_fx->clip_var_fx, sub(shift_wsp, 1));
+//
+//
+// /* run the above to maintain gain clipping memories */
+// gp_clip_test_gain_pit_fx(st_fx->element_mode, st_fx->core_brate, hSC_VBR->prev_ppp_gain_pit_fx, st_fx->clip_var_fx);
+//
+//
+// /*-----------------------------------------------------------------*
+// * Synthesize speech to update mem_syn[].
+// * Update A(z) filters
+// *-----------------------------------------------------------------*/
+//
+// Syn_filt_s(1, p_Aq_fx, M, &excQ_ppp_fx[i_subfr], &synth_fx[i_subfr], L_SUBFR, hLPDmem->mem_syn, 1);
+//
+//
+// p_Aw_fx += (M + 1);
+// p_Aq_fx += (M + 1);
+// }
+//
+// } /* end of subframe loop */
+//
+// IF(hSC_VBR->bump_up)
+// {
+// /* PPP failed, bump up */
+// hSC_VBR->ppp_mode = 0;
+// move16();
+// st_fx->core_brate = ACELP_7k20;
+// move16();
+// hSC_VBR->pppcountE = 0;
+// move16();
+//
+// IF(hSC_VBR->set_ppp_generic)
+// {
+// st_fx->coder_type = GENERIC;
+// move16();
+// }
+// ELSE
+// {
+// st_fx->coder_type = VOICED;
+// move16();
+// }
+//
+// /* We write signalling indices again only in case of bump_up */
+// /* delete previous indices */
+//#ifndef IVAS_CODE_BITSTREAM
+// reset_indices_enc_fx(hBstr);
+//#else
+// reset_indices_enc_fx(hBstr, hBstr->nb_ind_tot);
+//#endif
+//
+// /* signalling matrix (writing of signalling bits) */
+// signalling_enc_fx(st_fx);
+// }
+// ELSE
+// {
+// Copy(excQ_ppp_fx, exc_fx, L_FRAME);
+//
+// /*-----------------------------------------------------------------*
+// * Updates: last value of new target is stored in mem_w0
+// *-----------------------------------------------------------------*/
+//
+// hLPDmem->mem_w0 = sub(shr(xn_fx[L_SUBFR - 1],shift), shr(exc_fx[L_FRAME - 1],1)); /*Q_new-1 */
+//
+// Copy(exc_fx, exc2_fx, L_FRAME);
+//
+// hLPDmem->dm_fx.prev_state = 2;
+// move16();/*Q0 dispMem index 0 */
+// hLPDmem->dm_fx.prev_gain_pit[0] = hSC_VBR->prev_ppp_gain_pit_fx;
+// move16();/*Q14 dispMem index 2 */
+//
+// FOR(k = 1; k < 5; k++)
+// {
+// hLPDmem->dm_fx.prev_gain_pit[k] = hLPDmem->dm_fx.prev_gain_pit[k - 1];
+// move16();
+// }
+//
+// hLPDmem->tilt_code = hSC_VBR->prev_tilt_code_fx;
+// move16();
+// Copy(pitch_fx, pitch_buf_fx, NB_SUBFR);
+// pitch_buf_fx[NB_SUBFR16k - 1] = pitch_fx[NB_SUBFR - 1];
+//
+// interp_code_5over2_fx(exc2_fx, bwe_exc, L_FRAME);
+// set16_fx(voice_factors, 0, NB_SUBFR16k);
+// }
+//
+// hSC_VBR->rate_control = rate_ctrl_fx;
+// move16();
+//
+// set16_fx(hSC_VBR->nelp_lp_fit_mem, 0, NELP_LP_ORDER * 2);
+//
+// return error;
+//}
diff --git a/lib_enc/gp_clip_fx.c b/lib_enc/gp_clip_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..66108aad3924f3a9207082cf185f1266c0a936a8
--- /dev/null
+++ b/lib_enc/gp_clip_fx.c
@@ -0,0 +1,459 @@
+/******************************************************************************************************
+
+ (C) 2022-2023 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.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+
+#include
+#include "options.h" /* Compilation switches */
+#include "cnst.h" /* Common constants */
+#include "prot_fx2.h" /* Function prototypes */
+#include "basop_util.h"
+
+ /*-------------------------------------------------------------------*
+ * Local constants
+ *-------------------------------------------------------------------*/
+
+#define DIST_ISF_MAX_IO 384 /* 150 Hz (6400Hz=16384) */
+#define DIST_ISF_MAX 307 /* 120 Hz (6400Hz=16384) */
+#define DIST_ISF_THRES 154 /* 60 (6400Hz=16384) */
+#define GAIN_PIT_THRES 14746 /* 0.9 in Q14 */
+#define GAIN_PIT_MIN 9830 /* 0.6 in Q14 */
+
+#define ALPHA1 32113 /* 0.98f */
+#define ALPHA4 32440 /* 0.99f */
+#define WINDOW_SIZE 50
+#define THRESH_TYPE 13926 /* 0.85f in Q14 */
+#define THRESH_VOICING 14090 /* 0.86f in Q14 */
+
+#define GPCLIP_E (6+2)
+
+#define ALPHA1_M1 21474836l/*1.0f-0.98 Q30*/
+#define ALPHA4_M1 10737408l/*1.0f-0.99f Q30*/
+
+ /*-------------------------------------------------------------------*
+ * init_gp_clip
+ *
+ * Pitch Gain clipping initializations
+ *-------------------------------------------------------------------*/
+void init_gp_clip_fx(
+ Word16 mem[] /* o : memory of gain of pitch clipping algorithm */
+)
+{
+ mem[0] = DIST_ISF_MAX;
+ move16(); /* Q0 */
+ mem[1] = GAIN_PIT_MIN;
+ move16(); /* 1Q14 */
+ mem[2] = 0;
+ move16(); /* 8Q7 */ /* old energy of target (dB) */
+ mem[3] = 0;
+ move16(); /* Q0 */
+ mem[4] = 0;
+ move16(); /* Q14 */
+ mem[5] = 13107;/*0.8*/ move16(); /* Q14 */
+
+ return;
+}
+
+/*-------------------------------------------------------------------*
+ * Function gp_clip
+ *
+ * The gain needs to be limited (gain pitch < 1.0) when one of the
+ * following cases occurs:
+ * - a resonance on LPC filter (lp_disp < 60 Hz) AND a good pitch
+ * prediction (lp_gp > 0.9)
+ * - target energy drops by 6 dB AND a good pitch prediction (lp_gp>1.0)
+ *-------------------------------------------------------------------*/
+
+Word16 gp_clip_fx(
+ const Word16 element_mode, /* i : element mode */
+ const Word32 core_brate, /* i : core bitrate */
+ const Word16 *voicing, /* i : normalized correlations (from OL pitch) */
+ const Word16 i_subfr, /* i : subframe index */
+ const Word16 coder_type, /* i : type of coder */
+ const Word16 xn[], /* i : target vector */
+ Word16 mem[], /* i/o: memory of gain of pitch clipping algorithm */
+ const Word16 Q_new /* i : scaling factor */
+)
+{
+ Word16 clip;
+ Word16 i, wener;
+ Word16 e_ener, f_ener;
+ Word32 ener;
+ Word32 L_tmp;
+ Word16 thres;
+#ifdef BASOP_NOGLOB_DECLARE_LOCAL
+ Flag Overflow = 0;
+#endif
+
+ clip = 0;
+ move16();
+ test();
+ test();
+ IF(EQ_32(core_brate, ACELP_6k60) || EQ_32(core_brate, ACELP_8k85) || GT_16(element_mode, EVS_MONO))
+ {
+ thres = add(14746, mult(1638, extract_l(L_mult(mem[0], (Word16)(16384 / DIST_ISF_MAX_IO))))); /* clipping is activated when filtered pitch gain > threshold (0.94 to 1 in Q14) */
+ test();
+ if (GT_16(mem[1], thres))
+ {
+ clip = 1;
+ move16();
+ }
+ }
+ ELSE
+ {
+ test();
+ if (LT_16(mem[0], DIST_ISF_THRES) && GT_16(mem[1],GAIN_PIT_THRES))
+ {
+ clip = 1;
+ move16();
+ }
+ }
+
+#ifdef BASOP_NOGLOB
+ ener = L_mac_o(1L, xn[0], xn[0], &Overflow);
+#else
+ ener = L_mac(1L, xn[0], xn[0]);
+#endif
+ FOR(i = 1; i < L_SUBFR; i++)
+ {
+#ifdef BASOP_NOGLOB
+ ener = L_mac_o(ener, xn[i], xn[i], &Overflow);
+#else /* BASOP_NOGLOB */
+ ener = L_mac(ener, xn[i], xn[i]);
+#endif
+ }
+
+ /* ener = 10.0f*(float)log10(ener) */
+ e_ener = norm_l(ener);
+ f_ener = Log2_norm_lc(L_shl(ener, e_ener));
+ e_ener = sub(30, e_ener);
+ e_ener = sub(e_ener, Q_new);
+ ener = Mpy_32_16(e_ener, f_ener, LG10);
+ wener = round_fx(L_shl(ener, 10));
+
+ test();
+ if (LT_16(wener, sub(mem[2], 1536)) && GT_16(mem[1], 16384))
+ {
+ clip = 1;
+ move16();
+ }
+
+ mem[2] = wener;
+ move16();
+
+ L_tmp = L_mult(ALPHA1, mem[4]);
+
+ test();
+ test();
+ if (EQ_16(coder_type, GENERIC) || EQ_16(coder_type, TRANSITION) || EQ_16(coder_type, INACTIVE))
+ {
+ /* mem[4] = (1-ALPHA1) + ALPHA1 * mem[4], if branch taken */
+ /* mem[4] = ALPHA1 * mem[4], otherwise */
+ L_tmp = L_add(L_tmp, 32768L * (32768 - ALPHA1));
+ }
+ mem[4] = round_fx(L_tmp);
+
+ L_tmp = L_mult(ALPHA4, mem[5]);
+ if (i_subfr == 0)
+ {
+ /* mem[5] = (1-ALPHA4) * voicing[0] + ALPHA4 * mem[5] */
+ mem[5] = mac_r(L_tmp, (32768 - ALPHA4) / 2, voicing[0]);
+ move16(); /* /2 to put voicing from Q15 to Q14 */
+ }
+
+ if (EQ_16(i_subfr, 2 * L_SUBFR))
+ {
+ /* mem[5] = (1-ALPHA4) * voicing[1] + ALPHA4 * mem[5] */
+ mem[5] = mac_r(L_tmp, (32768 - ALPHA4) / 2, voicing[1]);
+ move16(); /* /2 to put voicing from Q15 to Q14 */
+ }
+
+ IF(GT_16(mem[3], WINDOW_SIZE))
+ {
+ test();
+ if (GT_16(mem[4], THRESH_TYPE) && GT_16(mem[5], THRESH_VOICING))
+ {
+ clip = 1;
+ move16();
+ }
+ }
+ ELSE
+ {
+ mem[3] = add(mem[3], 1);
+ move16();
+ }
+
+ return (clip);
+}
+
+/*-------------------------------------------------------------------*
+ * gp_clip_test_lsf()
+ *
+ * check the minimum distance of LSFs for pitch gain clipping flag
+ *-------------------------------------------------------------------*/
+
+void gp_clip_test_isf_fx(
+ const Word16 element_mode, /* i : element mode */
+ const Word32 core_brate, /* i : core bitrate */
+ const Word16 isf[], /* i : isf values (in frequency domain) */
+ Word16 mem[], /* i/o: memory of gain of pitch clipping algorithm */
+ const Word16 Opt_AMR_WB /* i : flag indicating AMR-WB IO mode */
+)
+{
+ Word16 i, dist, dist_min, m;
+
+ dist_min = sub(isf[1], isf[0]);
+
+ m = M;
+ move16();
+ if (EQ_16(Opt_AMR_WB, 1))
+ {
+ m = M - 1;
+ move16();
+ }
+
+ move16(); /* ptr init*/
+ FOR(i = 2; i < m; i++)
+ {
+ dist = sub(isf[i], isf[i - 1]);
+ dist_min = s_min(dist, dist_min);
+ }
+
+ dist = extract_h(L_mac(L_mult(26214, mem[0]), 6554, dist_min));
+
+ test();
+ test();
+ IF(EQ_32(core_brate, ACELP_6k60) || EQ_32(core_brate, ACELP_8k85) || GT_16(element_mode, EVS_MONO))
+ {
+ dist = s_min(dist, DIST_ISF_MAX_IO);
+ }
+ ELSE
+ {
+ dist = s_min(dist, DIST_ISF_MAX);
+ }
+ mem[0] = dist;
+ move16();
+
+ return;
+}
+
+/*-------------------------------------------------------------------*
+ * gp_clip_test_gain_pit()
+ *
+ * low-pass filtering of the pitch gain for pitch gain clipping flag
+ *-------------------------------------------------------------------*/
+
+void gp_clip_test_gain_pit_fx(
+ const Word16 element_mode, /* i : element mode */
+ const Word32 core_brate, /* i : core bitrate */
+ const Word16 gain_pit, /* i : gain of quantized pitch Q14 */
+ Word16 mem[] /* i/o: memory of gain of pitch clipping algorithm 1Q14 */
+)
+{
+ Word16 gain;
+ Word32 L_tmp;
+
+ test();
+ test();
+ IF(EQ_32(core_brate, ACELP_6k60) || EQ_32(core_brate, ACELP_8k85) || GT_16(element_mode, EVS_MONO))
+ {
+ L_tmp = L_mult(32113, mem[1]); /* long term LTP gain average (>250ms) */
+ L_tmp = L_mac(L_tmp, 655, gain_pit);
+ }
+ ELSE
+ {
+ L_tmp = L_mult(29491, mem[1]);
+ L_tmp = L_mac(L_tmp, 3277, gain_pit);
+ }
+ gain = extract_h(L_tmp);
+ gain = s_max(gain, GAIN_PIT_MIN);
+ mem[1] = gain;
+ move16();
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------*
+ * Function gp_clip
+ *
+ * The gain needs to be limited (gain pitch < 1.0) when one of the
+ * following cases occurs:
+ * - a resonance on LPC filter (lp_disp < 60 Hz) AND a good pitch
+ * prediction (lp_gp > 0.9)
+ * - target energy drops by 6 dB AND a good pitch prediction (lp_gp>1.0)
+ *-------------------------------------------------------------------*/
+Word16 Mode2_gp_clip(
+ const Word16 voicing[3], /* i : normalized correlations from OL pitch Q15 */
+ const Word16 i_subfr, /* i : subframe index */
+ const Word16 coder_type, /* i : type of coder */
+ const Word16 xn[], /* i : target vector Q_xn */
+ Word16 mem[], /* i/o: memory of gain of pitch clipping algorithm */
+ /* mem[0]: Q0 */
+ /* mem[1]: 1Q14 */
+ /* mem[2]: 8Q7 */
+ /* mem[3]: Q0 (integer) */
+ /* mem[4]: Q14 */
+ /* mem[5]: Q14 */
+ const Word16 L_subfr,
+ const Word16 Q_xn /* i : scaling factor of vector xn[] */
+)
+{
+ Word16 clip, tmp, exp_xn;
+ Word16 i;
+ Word32 wener, Ltmp;
+#ifdef BASOP_NOGLOB_DECLARE_LOCAL
+ Flag Overflow = 0;
+#endif
+ move16();
+ clip = 0;
+
+ test();
+ if ((LT_16(mem[0], DIST_ISF_THRES)) && (GT_16(mem[1], GAIN_PIT_THRES)))
+ {
+ move16();
+ clip = 1;
+ }
+
+ /*ener_exp = exp_xn * 2 + 1*/
+ exp_xn = add(shl(sub(15, Q_xn), 1), 1);
+ wener = L_shr(21474836l/*0.01f Q31*/, s_min(31, exp_xn));
+ wener = L_max(1, wener);
+
+ FOR(i = 0; i < L_subfr; i++)
+ {
+#ifdef BASOP_NOGLOB
+ wener = L_mac0_o(wener, xn[i], xn[i], &Overflow);
+#else
+ wener = L_mac0(wener, xn[i], xn[i]);
+#endif
+ }
+
+ /*wener = 10.0f*(float)log10(wener);*/
+ wener = BASOP_Util_Log2(wener);
+ wener = L_add(wener, L_shl(exp_xn, 31 - LD_DATA_SCALE));
+ wener = Mpy_32_16_1(wener, LG10); /* wener in 8Q7 */
+#if (GPCLIP_E != 6+2)
+ wener = shl(wener, GPCLIP_E - (6 + 2));
+#endif
+ tmp = round_fx(wener);
+ /* exponent of wener = 6+2 */
+
+ test();
+ if (LT_16(tmp, sub(mem[2], 768/*6.0f Q7*/)) &&
+ GT_16(mem[1], 16384/*1.0f Q14*/))
+ {
+ move16();
+ clip = 1;
+ }
+
+ move16();
+ mem[2] = tmp; /* wener in 8Q7 format */
+ Ltmp = Mpy_32_16_1(ALPHA1, mem[4]); /* mem[4] in Q14 format, Ltmp in Q14 */
+
+ if (s_or((Word16)EQ_16(coder_type, GENERIC), (Word16)EQ_16(coder_type, TRANSITION)))
+ {
+ Ltmp = L_add(Ltmp, ALPHA1_M1);
+ }
+ mem[4] = round_fx(Ltmp);
+
+ Ltmp = Mpy_32_16_1(ALPHA4, mem[5]); /* mem[5] in Q14 format, Ltmp in Q14 */
+ IF(i_subfr == 0)
+ {
+ move16(); /* voicing: Q15 */
+ mem[5] = round_fx(L_add(Mpy_32_16_1(ALPHA4_M1, voicing[0]), Ltmp));
+ }
+ ELSE IF(EQ_16(i_subfr, shl(L_subfr, 1)))
+ {
+ move16();
+ mem[5] = round_fx(L_add(Mpy_32_16_1(ALPHA4_M1, voicing[1]), Ltmp));
+ }
+
+ IF(GT_16(mem[3], WINDOW_SIZE))
+ {
+ test();
+ if ((GT_16(mem[4], THRESH_TYPE)) && (GT_16(mem[5], THRESH_VOICING)))
+ {
+ move16();
+ clip = 1;
+ }
+ }
+ ELSE
+ {
+ move16();
+ mem[3] = add(mem[3], 1);
+ }
+
+
+ return (clip);
+}
+
+/*-------------------------------------------------------------------*
+* gp_clip_test_lsf:
+*
+* check the minimum distance of LSFs for pitch gain clipping flag
+*-------------------------------------------------------------------*/
+void gp_clip_test_lsf_fx(
+ const Word16 element_mode, /* i : element mode */
+ const Word16 lsf[], /* i : lsf values (in frequency domain) 14Q1*1.28 */
+ Word16 mem[], /* i/o: memory of gain of pitch clipping algorithm */
+ const Word16 m /* i : dimension of lsf */
+)
+{
+ Word16 i;
+ Word16 dist, dist_min, dist_max;
+
+ dist_max = DIST_ISF_MAX;
+ move16();
+ if (GT_16(element_mode, EVS_MONO))
+ {
+ dist_max = DIST_ISF_MAX_IO;
+ move16();
+ }
+ dist_min = sub(lsf[1], lsf[0]);
+
+ FOR(i = 2; i < m - 1; i++)
+ {
+ dist = sub(lsf[i], lsf[i - 1]);
+ dist_min = s_min(dist, dist_min);
+ }
+ /*dist = 0.8f*mem[0] + 0.2f*dist_min;*/
+ dist = s_min(dist_max, mac_r(L_mult(26214/*0.8f Q15*/, mem[0]), 6554/*0.2f Q15*/, dist_min));
+
+ mem[0] = dist;
+ move16();
+
+
+ return;
+}
diff --git a/lib_enc/isf_enc_amr_wb_fx.c b/lib_enc/isf_enc_amr_wb_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..de6a422f3da6ec5b8467fc31016e8dc82ee5aad0
--- /dev/null
+++ b/lib_enc/isf_enc_amr_wb_fx.c
@@ -0,0 +1,571 @@
+/******************************************************************************************************
+
+ (C) 2022-2023 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.
+
+*******************************************************************************************************/
+
+#include
+#include "options.h" /* Compilation switches */
+#include "cnst.h" /* Common constants */
+#include "rom_com.h" /* Static table prototypes */
+#include "prot_fx2.h" /* Function prototypes */
+
+
+ /*-----------------------------------------------------------------*
+ * Local constants
+ *-----------------------------------------------------------------*/
+
+#define DICO1_NS_19b 16 /* codebook dimensions for SID ISF quantizers */
+#define DICO2_NS_19b 16
+#define DICO3_NS_19b 16
+#define DICO4_NS_19b 8
+#define DICO5_NS_19b 16
+
+#define DICO1_NS_28b 64
+#define DICO2_NS_28b 64
+#define DICO3_NS_28b 64
+#define DICO4_NS_28b 32
+#define DICO5_NS_28b 32
+
+#define N_SURV_MAX 4 /* maximum number of survivors */
+
+ /*---------------------------------------------------------------------*
+ * Local function prototypes
+ *---------------------------------------------------------------------*/
+
+static void qisf_ns_28b_fx(BSTR_ENC_HANDLE hBstr, Word16 *isf);
+static void qisf_2s_46b_fx(BSTR_ENC_HANDLE hBstr, Word16 *isf, Word16 nb_surv, Word16 *mem_AR, Word16 *mem_MA);
+static void qisf_2s_36b_fx(BSTR_ENC_HANDLE hBstr, Word16 *isf, Word16 nb_surv, Word16 *mem_AR, Word16 *mem_MA);
+static void VQ_stage1_fx(const Word16 *x, const Word16 *dico, const Word16 dim, const Word16 dico_size, Word16 *index, const Word16 surv);
+static Word16 sub_VQ_fx(Word16 *x, const Word16 *dico, const Word16 dim, const Word16 dico_size, Word32 *distance);
+
+/*-------------------------------------------------------------------*
+ * isf_enc_amr_wb()
+ *
+ * Quantization of ISF parameters in AMR-WB IO mode
+ *-------------------------------------------------------------------*/
+
+void isf_enc_amr_wb_fx(
+ Encoder_State *st, /* i/o: state structure */
+ Word16 *isf_new, /* i/o: quantized ISF vector */
+ Word16 *isp_new, /* i/o: ISP vector to quantize/quantized */
+ Word16 *Aq /* o : quantized A(z) for 4 subframes */
+)
+{
+ BSTR_ENC_HANDLE hBstr = st->hBstr;
+
+ /*---------------------------------*
+ * ISF quantization of SID frames
+ *---------------------------------*/
+
+ IF(EQ_32(st->core_brate, SID_1k75))
+ {
+ qisf_ns_28b_fx(hBstr, isf_new);
+
+ reorder_isf_fx(isf_new, ISF_GAP_FX, M, Fs_2);
+
+ E_LPC_isf_isp_conversion(isf_new, isp_new, M);
+
+ /* return if SID frame (conversion to A(z) done in the calling function) */
+ return;
+ }
+
+ /* check resonance for pitch clipping algorithm */
+ gp_clip_test_isf_fx(st->element_mode, st->core_brate, isf_new, st->clip_var_fx, 1);
+
+ /*---------------------------------------*
+ * ISF quantization of all other frames
+ *---------------------------------------*/
+
+ IF(EQ_32(st->core_brate, ACELP_6k60))
+ {
+ qisf_2s_36b_fx(hBstr, isf_new, 4, st->mem_AR_fx, st->mem_MA_fx);
+ }
+ ELSE IF(GE_32(st->core_brate, ACELP_8k85))
+ {
+ qisf_2s_46b_fx(hBstr, isf_new, 4, st->mem_AR_fx, st->mem_MA_fx);
+ }
+
+ reorder_isf_fx(isf_new, ISF_GAP_FX, M, Fs_2);
+ /* convert quantized ISFs back to ISPs */
+ E_LPC_isf_isp_conversion(isf_new, isp_new, M);
+
+ /*-------------------------------------------------------------------------------------*
+ * ISP interpolation
+ * A(z) calculation
+ *-------------------------------------------------------------------------------------*/
+
+ if (st->rate_switching_reset)
+ {
+ Copy(isf_new, st->lsf_old_fx, M);
+ Copy(isp_new, st->lsp_old_fx, M);
+ }
+
+ int_lsp_fx(L_FRAME, st->lsp_old_fx, isp_new, Aq, M, interpol_isp_amr_wb_fx, 1);
+
+ /*------------------------------------------------------------------*
+ * Calculate ISF stability (distance between old ISF and current ISF)
+ *------------------------------------------------------------------*/
+ IF(NE_32(st->last_core_brate, SID_1k75))
+ {
+ st->stab_fac_fx = lsf_stab_fx(isf_new, st->lsf_old_fx, 1, L_FRAME);
+ }
+
+ return;
+}
+
+/*-------------------------------------------------------------------*
+* qisf_ns_28b()
+*
+* ISF quantizer for SID frames (only in AMR-WB IO mode)
+*-------------------------------------------------------------------*/
+
+static void qisf_ns_28b_fx(
+ BSTR_ENC_HANDLE hBstr, /* i/o: encoder state structure */
+ Word16 *isf /* i/o: unquantized/quantized ISF vector */
+)
+{
+ Word16 i, indice[5];
+ Word32 tmp;
+
+ FOR(i = 0; i < M; i++)
+ {
+ /*isf[i] -= mean_isf_noise_amr_wb[i];*/
+ isf[i] = sub(isf[i], mean_isf_noise_amr_wb_fx[i]);
+ move16();
+ }
+
+ indice[0] = sub_VQ_fx(&isf[0], dico1_ns_28b_fx, 2, DICO1_NS_28b, &tmp);
+ move16();
+ indice[1] = sub_VQ_fx(&isf[2], dico2_ns_28b_fx, 3, DICO2_NS_28b, &tmp);
+ move16();
+ indice[2] = sub_VQ_fx(&isf[5], dico3_ns_28b_fx, 3, DICO3_NS_28b, &tmp);
+ move16();
+ indice[3] = sub_VQ_fx(&isf[8], dico4_ns_28b_fx, 4, DICO4_NS_28b, &tmp);
+ move16();
+ indice[4] = add(sub_VQ_fx(&isf[12], dico5_ns_28b_fx + 4, 4, DICO5_NS_28b - 1, &tmp), 1); /* First vector has a problem -> do not allow */
+
+ /* write indices to array */
+ push_indice_fx(hBstr, IND_ISF_0_0, indice[0], 6);
+ push_indice_fx(hBstr, IND_ISF_0_1, indice[1], 6);
+ push_indice_fx(hBstr, IND_ISF_0_2, indice[2], 6);
+ push_indice_fx(hBstr, IND_ISF_0_3, indice[3], 5);
+ push_indice_fx(hBstr, IND_ISF_0_4, indice[4], 5);
+
+ /* decoding the ISFs */
+ disf_ns_28b_fx(indice, isf);
+
+ return;
+}
+
+
+/*---------------------------------------------------------------------*
+ * qisf_2s_36b()
+ *
+ * ISF quantizer for AMR-WB 6k60 frames
+ *
+ * The ISF vector is quantized using two-stage MA-prediction VQ with split-by-2
+ * in 1st stage and split-by-3 in the second stage.
+ *---------------------------------------------------------------------*/
+
+static void qisf_2s_36b_fx(
+ BSTR_ENC_HANDLE hBstr, /* i/o: encoder state structure */
+ Word16 *isf, /* i/o: unquantized/quantized ISF vector */
+ Word16 nb_surv, /* i : number of survivors (1, 2, 3 or 4) */
+ Word16 *mem_AR, /* o : quantizer memory for AR model */
+ Word16 *mem_MA /* i/o: quantizer memory for MA model */
+)
+{
+ Word16 i, k, indice[5], tmp_ind[2];
+ Word16 surv1[N_SURV_MAX], tmp16; /* indices of survivors from 1st stage */
+ Word32 temp, min_err, distance;
+ Word16 isf2[M];
+
+ /*------------------------------------------------------------------------*
+ * Subtract mean
+ *------------------------------------------------------------------------*/
+
+ FOR(i = 0; i < M; i++)
+ {
+ /*isf[i] -= mean_isf_amr_wb[i] + MU_MA * mem_MA[i];*/
+ tmp16 = sub(isf[i], mean_isf_amr_wb_fx[i]);
+ isf[i] = sub(tmp16, mult(MU_MA_FX, mem_MA[i]));
+ move16();
+
+ }
+
+ /*------------------------------------------------------------------------*
+ * Quantize ISFs 0 - 8
+ *------------------------------------------------------------------------*/
+
+ VQ_stage1_fx(&isf[0], dico1_isf_fx, 9, SIZE_BK1, surv1, nb_surv);
+
+ distance = MAX_32;
+ move32();
+ nb_surv = s_min(nb_surv, N_SURV_MAX);
+
+ FOR(k = 0; k < nb_surv; k++)
+ {
+ tmp16 = i_mult2(surv1[k], 9);
+ FOR(i = 0; i < 9; i++)
+ {
+ /*isf2[i] = isf[i] - dico1_isf[i+surv1[k]*9];*/
+ isf2[i] = sub(isf[i], dico1_isf_fx[i + tmp16]);
+ move16();
+ }
+
+ tmp_ind[0] = sub_VQ_fx(&isf2[0], dico21_isf_36b_fx, 5, SIZE_BK21_36b, &min_err);
+ temp = L_add(min_err, 0);
+
+ tmp_ind[1] = sub_VQ_fx(&isf2[5], dico22_isf_36b_fx, 4, SIZE_BK22_36b, &min_err);
+ temp = L_add(temp, min_err);
+
+ IF(LT_32(temp, distance))
+ {
+ distance = L_add(temp, 0);
+ indice[0] = surv1[k];
+ move16();
+ FOR(i = 0; i < 2; i++)
+ {
+ indice[i + 2] = tmp_ind[i];
+ move16();
+ }
+ }
+ }
+
+ /*------------------------------------------------------------------------*
+ * Quantize ISFs 9 - 15
+ *------------------------------------------------------------------------*/
+
+ VQ_stage1_fx(&isf[9], dico2_isf_fx, 7, SIZE_BK2, surv1, nb_surv);
+
+ distance = MAX_32;
+ move32();
+ FOR(k = 0; k < nb_surv; k++)
+ {
+ tmp16 = i_mult2(surv1[k], 7);
+ FOR(i = 0; i < 7; i++)
+ {
+ /*isf2[9+i] = isf[9+i] - dico2_isf[i+surv1[k]*7];*/
+ isf2[i + 9] = sub(isf[9 + i], dico2_isf_fx[i + tmp16]);
+ move16();
+ }
+
+ tmp_ind[0] = sub_VQ_fx(&isf2[9], dico23_isf_36b_fx, 3, SIZE_BK23_36b, &min_err);
+ move16();
+ temp = L_add(min_err, 0);
+ IF(LT_32(temp, distance))
+ {
+ distance = L_add(temp, 0);
+ indice[1] = surv1[k];
+ move16();
+ indice[4] = tmp_ind[0];
+ move16();
+ }
+ }
+
+ /*------------------------------------------------------------------------*
+ * decoding the ISFs
+ *------------------------------------------------------------------------*/
+
+ disf_2s_36b_fx(indice, isf, mem_AR, mem_MA, 0);
+
+ /*------------------------------------------------------------------------*
+ * write indices to array
+ *------------------------------------------------------------------------*/
+
+ indice[0] = Indirect_dico1[indice[0]];
+ move16(); /* Make interoperable with G722.2 */
+
+ push_indice_fx(hBstr, IND_ISF_0_0, indice[0], 8);
+ push_indice_fx(hBstr, IND_ISF_0_1, indice[1], 8);
+ push_indice_fx(hBstr, IND_ISF_1_0, indice[2], 7);
+ push_indice_fx(hBstr, IND_ISF_1_1, indice[3], 7);
+ push_indice_fx(hBstr, IND_ISF_1_2, indice[4], 6);
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------*
+ * qisf_2s_46b()
+ *
+ * ISF quantizer for all other AMR-WB frames
+ *
+ * The ISF vector is quantized using two-stage VQ with split-by-2
+ * in 1st stage and split-by-5 in the second stage.
+ *-------------------------------------------------------------------*/
+
+static void qisf_2s_46b_fx(
+ BSTR_ENC_HANDLE hBstr, /* i/o: encoder state structure */
+ Word16 *isf, /* i/o: unquantized/quantized ISF vector */
+ Word16 nb_surv, /* i : number of survivors (1, 2, 3 or 4) */
+ Word16 *mem_AR, /* o : quantizer memory for AR model */
+ Word16 *mem_MA /* i/o: quantizer memory for MA model */
+)
+{
+ Word16 i, k, indice[7], tmp_ind[5];
+ Word16 surv1[N_SURV_MAX]; /* indices of survivors from 1st stage */
+ Word32 temp, min_err, distance;
+ Word16 tmp16, isf2[M];
+
+
+ /*------------------------------------------------------------------------*
+ * Subtract mean
+ *------------------------------------------------------------------------*/
+
+ FOR(i = 0; i < M; i++)
+ {
+ /*isf[i] -= mean_isf_amr_wb[i] + MU_MA * mem_MA[i];*/
+ tmp16 = sub(isf[i], mean_isf_amr_wb_fx[i]);
+ isf[i] = sub(tmp16, mult(MU_MA_FX, mem_MA[i]));
+ move16();
+ }
+
+ /*------------------------------------------------------------------------*
+ * Quantize ISFs 0 - 8
+ *------------------------------------------------------------------------*/
+
+ VQ_stage1_fx(&isf[0], dico1_isf_fx, 9, SIZE_BK1, surv1, nb_surv);
+
+ distance = MAX_32;
+ move32();
+ nb_surv = s_min(nb_surv, N_SURV_MAX);
+
+ FOR(k = 0; k < nb_surv; k++)
+ {
+ tmp16 = i_mult2(surv1[k], 9);
+ FOR(i = 0; i < 9; i++)
+ {
+ /*isf2[i] = isf[i] - dico1_isf[i+surv1[k]*9];*/
+ isf2[i] = sub(isf[i], dico1_isf_fx[i + tmp16]);
+ move16();
+ }
+
+ tmp_ind[0] = sub_VQ_fx(&isf2[0], dico21_isf_46b_fx, 3, SIZE_BK21, &min_err);
+ temp = L_add(min_err, 0);
+ tmp_ind[1] = sub_VQ_fx(&isf2[3], dico22_isf_46b_fx, 3, SIZE_BK22, &min_err);
+ temp = L_add(temp, min_err);
+ tmp_ind[2] = sub_VQ_fx(&isf2[6], dico23_isf_46b_fx, 3, SIZE_BK23, &min_err);
+ temp = L_add(temp, min_err);
+ IF(LT_32(temp, distance))
+ {
+ distance = L_add(temp, 0);
+ indice[0] = surv1[k];
+ move16();
+ FOR(i = 0; i < 3; i++)
+ {
+ indice[i + 2] = tmp_ind[i];
+ move16();
+ }
+ }
+ }
+
+ /*------------------------------------------------------------------------*
+ * Quantize ISFs 9 - 15
+ *------------------------------------------------------------------------*/
+
+ VQ_stage1_fx(&isf[9], dico2_isf_fx, 7, SIZE_BK2, surv1, nb_surv);
+
+ distance = MAX_32;
+ move32();
+ FOR(k = 0; k < nb_surv; k++)
+ {
+ tmp16 = i_mult2(surv1[k], 7);
+ FOR(i = 0; i < 7; i++)
+ {
+ /*isf2[9+i] = isf[9+i] - dico2_isf[i+surv1[k]*7];*/
+ isf2[i + 9] = sub(isf[9 + i], dico2_isf_fx[i + tmp16]);
+ move16();
+ }
+ tmp_ind[0] = sub_VQ_fx(&isf2[9], dico24_isf_46b_fx, 3, SIZE_BK24, &min_err);
+ move16();
+ temp = L_add(min_err, 0);
+
+ tmp_ind[1] = sub_VQ_fx(&isf2[12], dico25_isf_46b_fx, 4, SIZE_BK25, &min_err);
+ move16();
+ temp = L_add(temp, min_err);
+
+ IF(LT_32(temp, distance))
+ {
+ distance = L_add(temp, 0);
+ indice[1] = surv1[k];
+ move16();
+ FOR(i = 0; i < 2; i++)
+ {
+ indice[i + 5] = tmp_ind[i];
+ move16();
+ }
+ }
+ }
+
+ /*------------------------------------------------------------------------*
+ * decoding the ISFs
+ *------------------------------------------------------------------------*/
+
+ disf_2s_46b_fx(indice, isf, mem_AR, mem_MA, 0);
+
+ /*------------------------------------------------------------------------*
+ * write indices to array
+ *------------------------------------------------------------------------*/
+ indice[0] = Indirect_dico1[indice[0]];
+ move16(); /* Make interoperable with G722.2 */
+
+ push_indice_fx(hBstr, IND_ISF_0_0, indice[0], 8);
+ push_indice_fx(hBstr, IND_ISF_0_1, indice[1], 8);
+ push_indice_fx(hBstr, IND_ISF_1_0, indice[2], 6);
+ push_indice_fx(hBstr, IND_ISF_1_1, indice[3], 7);
+ push_indice_fx(hBstr, IND_ISF_1_2, indice[4], 7);
+ push_indice_fx(hBstr, IND_ISF_1_3, indice[5], 5);
+ push_indice_fx(hBstr, IND_ISF_1_4, indice[6], 5);
+
+ return;
+}
+
+/*-------------------------------------------------------------------*
+ * VQ_stage1()
+ *
+ * 1st stage of ISF quantization
+ *-------------------------------------------------------------------*/
+
+static void VQ_stage1_fx(
+ const Word16 *x, /* i : ISF vector */
+ const Word16 *dico, /* i : ISF codebook */
+ const Word16 dim, /* i : codebook dimension */
+ const Word16 dico_size, /* i : codebook size */
+ Word16 *index, /* o : indices of best vector candidates */
+ const Word16 surv /* i : nb of surviving best candidates */
+)
+{
+ Word32 dist_min[N_SURV_MAX];
+ Word32 dist;
+ const Word16 *p_dico;
+ Word16 i, j, k, l, temp;
+
+
+ FOR(i = 0; i < surv; i++)
+ {
+ dist_min[i] = MAX_32;
+ move32();
+ index[i] = i;
+ move16();
+ }
+
+ p_dico = dico;
+
+ FOR(i = 0; i < dico_size; i++)
+ {
+ dist = L_deposit_l(0);
+ FOR(j = 0; j < dim; j++)
+ {
+ /*temp = x[j] - *p_dico++;*/
+ temp = sub(x[j], *p_dico++);
+ /*dist += temp * temp;*/
+ dist = L_mac(dist, temp, temp);
+ }
+
+ FOR(k = 0; k < surv; k++)
+ {
+ IF(LT_32(dist, dist_min[k]))
+ {
+ FOR(l = sub(surv, 1); l > k; l--)
+ {
+ dist_min[l] = dist_min[l - 1];
+ move32();
+ index[l] = index[l - 1];
+ move16();
+ }
+ dist_min[k] = dist;
+ move32();
+ index[k] = i;
+ move16();
+ BREAK;
+ }
+ }
+ }
+ return;
+}
+
+/*-------------------------------------------------------------------*
+ * sub_VQ_fx()
+ *
+ * Quantization of a subvector in Split-VQ of ISFs
+ *-------------------------------------------------------------------*/
+
+static Word16 sub_VQ_fx( /* o : selected codebook vector index */
+ Word16 *x, /* i/o: ISF vector */
+ const Word16 *dico, /* i : ISF codebook */
+ const Word16 dim, /* i : codebook dimension */
+ const Word16 dico_size, /* i : codebook size */
+ Word32 *distance /* o : quantization error (min. distance) */
+)
+{
+ Word32 dist_min, dist;
+ const Word16 *p_dico;
+ Word16 i, j, index, temp;
+
+
+ dist_min = MAX_32;
+ move32();
+ p_dico = dico;
+ move16();
+
+ index = 0;
+ move16();
+ FOR(i = 0; i < dico_size; i++)
+ {
+ dist = L_deposit_l(0);
+ FOR(j = 0; j < dim; j++)
+ {
+ /*temp = x[j] - *p_dico++;*/
+ temp = sub(x[j], *p_dico++);
+ /*dist += temp * temp;*/
+ dist = L_mac(dist, temp, temp);
+ }
+
+ IF(LT_32(dist, dist_min))
+ {
+ dist_min = L_add(dist, 0);
+ index = i;
+ move16();
+ }
+ }
+
+ *distance = dist_min;
+ move32();
+
+ /* Reading the selected vector */
+ p_dico = &dico[i_mult2(index, dim)];
+ FOR(j = 0; j < dim; j++)
+ {
+ x[j] = *p_dico++;
+ move16();
+ }
+ return index;
+}
diff --git a/lib_enc/nelp_enc.c b/lib_enc/nelp_enc.c
index 1c065a51733de510a854ff14f2fd90cdd5dd5854..9f72248ff8ffe345de2a76d904c526c7635dfb23 100644
--- a/lib_enc/nelp_enc.c
+++ b/lib_enc/nelp_enc.c
@@ -317,7 +317,7 @@ void nelp_encoder(
}
else if ( st->bwidth == NB )
{
- polezero_filter( ptr, ptr_tmp, L_FRAME, bp1_num_coef_nb_fx_order7, bp1_den_coef_nb_fx_order7, 7, hSC_VBR->bp1_filt_mem_nb );
+ polezero_filter( ptr, ptr_tmp, L_FRAME, bp1_num_coef_nb_fx_order7_flt, bp1_den_coef_nb_fx_order7_flt, 7, hSC_VBR->bp1_filt_mem_nb );
mvr2r( ptr_tmp, ptr, L_FRAME );
}
diff --git a/lib_enc/nelp_enc_fx.c b/lib_enc/nelp_enc_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..c5042c48abf1f488477fa503ca8784010bdcc596
--- /dev/null
+++ b/lib_enc/nelp_enc_fx.c
@@ -0,0 +1,1028 @@
+/******************************************************************************************************
+
+ (C) 2022-2023 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.
+
+*******************************************************************************************************/
+
+#include
+#include "control.h"
+#include "options.h" /* Compilation switches */
+#include "cnst.h" /* Common constants */
+#include "prot_fx2.h" /* Function prototypes */
+#include "prot_fx1.h"
+#include "rom_com.h"
+
+/*===================================================================*/
+/* FUNCTION : quantize_uvg_fx() */
+/*-------------------------------------------------------------------*/
+/* PURPOSE : This function returns the quantized gain vector */
+/* and corresponding table indices, given the
+input unquantized gain vector */
+/*-------------------------------------------------------------------*/
+/* INPUT ARGUMENTS : */
+/* _ (Word16*) G : Un-quantized gain vector (Q0) */
+/*-------------------------------------------------------------------*/
+/* OUTPUT ARGUMENTS : */
+/* _ (Word16) iG1 : UVG1CB_fx table index (Q0) */
+/* _ (Word16*) iG2 : UVG2CB_fx table indices (Q0) */
+/* _ (Word16*) quantG : Output quantized gain vector */
+/*-------------------------------------------------------------------*/
+/* INPUT/OUTPUT ARGUMENTS : */
+/* _ None. */
+/*-------------------------------------------------------------------*/
+/* RETURN ARGUMENTS : */
+/* _ None. */
+/*===================================================================*/
+
+void quantize_uvg_fx(Word16 *G, Word16 *iG1, Word16 *iG2, Word16 *quantG, Word16 bwidth_fx)
+{
+ Word16 G1[2], G2[10], L16, L16_1;
+ Word16 i, j, k, ind, temp;
+ Word32 mmse;
+ Word16 exp, tmp, frac;
+ Word32 Lacc, Lexp[2], L_tmp;
+ const Word16(*UVG1CB_fx)[2] = NULL;
+ const Word16(*UVG2CB1_fx)[5] = NULL;
+ const Word16(*UVG2CB2_fx)[5] = NULL;
+ test();
+ IF(EQ_16(bwidth_fx, NB))
+ {
+ UVG1CB_fx = UVG1CB_NB_FX;
+ move16();/*Q13 */
+ UVG2CB1_fx = UVG2CB1_NB_FX;
+ move16();/*Q12 */
+ UVG2CB2_fx = UVG2CB2_NB_FX;
+ move16();/*Q12 */
+ }
+ ELSE IF(EQ_16(bwidth_fx, WB) || EQ_16(bwidth_fx, SWB))
+ {
+ UVG1CB_fx = UVG1CB_WB_FX;
+ move16();/*Q13 */
+ UVG2CB1_fx = UVG2CB1_WB_FX;
+ move16();/*Q12 */
+ UVG2CB2_fx = UVG2CB2_WB_FX;
+ move16();/*Q12 */
+ }
+
+
+ FOR(i = 0; i < 2; i++)
+ {
+ Lacc = L_deposit_l(0);
+ FOR(j = 0; j < 5; j++)
+ {
+ ind = add(shr(extract_l(L_mult(i, 5)), 1), j);
+ Lacc = L_mac0(Lacc, G[ind], G[ind]); /*Q0 */
+ }
+
+ IF(Lacc == 0)
+ {
+ Lacc = L_deposit_l(1); /* to avoid log10(0) */
+ }
+
+ /*G1[i] = (float) log10(sqrt(G1[i]/5)); */
+ L_tmp = Mult_32_16(Lacc, 13108);
+ IF(L_tmp)
+ {
+ exp = norm_l(L_tmp);
+ frac = Log2_norm_lc(L_shl(L_tmp, exp));
+ exp = (30 - exp - 1);
+ move16();/*(+1)=/2 in log */
+ L_tmp = Mpy_32_16(exp, frac, 4932); /*Q16 ; 0.5*log10(2) in Q15 */
+ G1[i] = round_fx(L_shl(L_tmp, 13)); /*Q13 */
+ }
+ ELSE
+ {
+ G1[i] = 0;
+ move16();
+ }
+
+ }
+
+
+ mmse = L_add(MAX_32, 0);
+ *iG1 = 0;
+ move16();
+ FOR(i = 0; i < UVG1_CBSIZE; i++)
+ {
+ L16 = shr(sub(G1[0], UVG1CB_fx[i][0]), 1); /* Q12 */
+ L16_1 = shr(sub(G1[1], UVG1CB_fx[i][1]), 1); /* Q12 */
+ Lacc = 0;
+ Lacc = L_mac0(Lacc, L16, L16); /*Q24 */
+ Lacc = L_mac0(Lacc, L16_1, L16_1);/*Q24 */
+
+ IF(LT_32(Lacc, mmse))
+ {
+ *iG1 = i;
+ move16();
+ mmse = Lacc;
+ }
+
+ }
+
+ L_tmp = L_mult0(UVG1CB_fx[*iG1][0], 27213);/*Q26 */
+ L_tmp = L_shr(L_tmp, 10); /* From Q26 to Q16 */
+ frac = L_Extract_lc(L_tmp, &exp); /* Extract exponent of L_tmp */
+ L_tmp = Pow2(30, frac);
+ exp = exp - 30; /*move16(); */
+ Lexp[0] = L_shl(L_tmp, exp + 15);
+
+
+ L_tmp = L_mult0(UVG1CB_fx[*iG1][1], 27213);/*Q26 */
+ L_tmp = L_shr(L_tmp, 10); /* From Q26 to Q16 */
+ frac = L_Extract_lc(L_tmp, &exp); /* Extract exponent of L_tmp */
+ L_tmp = Pow2(30, frac);
+ exp = exp - 30; /*move16(); */
+ Lexp[1] = L_shl(L_tmp, exp + 15);
+
+
+ FOR(i = 0; i < 2; i++)
+ {
+ FOR(j = 0; j < 5; j++)
+ {
+ exp = norm_l(Lexp[i]);
+ tmp = extract_h(L_shl(Lexp[i], exp));
+ exp = sub(sub(30, exp), 15);
+ tmp = div_s(16384, tmp); /*Q(15+exp) */
+ L_tmp = L_shr(L_mult0(G[i * 5 + j], tmp), exp + 3); /*Q12 */
+ G2[i * 5 + j] = extract_l(L_tmp); /*Q12 */
+ }
+ }
+
+
+ FOR(i = 0; i < 2; i++)
+ {
+ mmse = MAX_32;
+ iG2[i] = 0;
+ FOR(j = 0; j < UVG2_CBSIZE; j++)
+ {
+ Lacc = L_deposit_l(0);
+ FOR(k = 0; k < 5; k++)
+ {
+ IF(i == 0)
+ {
+ /*mse += SQR(G2[i*5+k]-UVG2CB1[j][k]); */
+ ind = add(shr(extract_l(L_mult(i, 5)), 1), k);
+ temp = sub(G2[ind], UVG2CB1_fx[j][k]);
+ Lacc = L_mac0(Lacc, temp, temp); /*Q24 */
+ }
+ ELSE IF(i == 1)
+ {
+ /*mse += SQR(G2[i*5+k]-UVG2CB2[j][k]); */
+ ind = add(shr(extract_l(L_mult(i, 5)), 1), k);
+ temp = sub(G2[ind], UVG2CB2_fx[j][k]);
+ Lacc = L_mac0(Lacc, temp, temp); /*Q24 */
+ }
+ }
+
+ IF(LT_32(Lacc, mmse))
+ {
+ mmse = Lacc;
+ iG2[i] = j;
+ move16();
+ }
+ }
+ }
+
+ dequantize_uvg_fx(*iG1, iG2, quantG, bwidth_fx, 0);
+
+}
+
+/*===================================================================*/
+/* FUNCTION : normalize_arr() */
+/*-------------------------------------------------------------------*/
+/* PURPOSE : Normalize array */
+/* */
+/*-------------------------------------------------------------------*/
+/* GLOBAL INPUT ARGUMENTS : */
+/* _ (Word16*) qf */
+/* _ (Word16*) size */
+/* _ (Word16*) hdr */
+/*-------------------------------------------------------------------*/
+/* OUTPUT ARGUMENTS : */
+/* _ (Word16*) arr : Normalized array */
+/*-------------------------------------------------------------------*/
+
+/* _ None */
+/*-------------------------------------------------------------------*/
+/* RETURN ARGUMENTS : */
+/* _ None */
+/*===================================================================*/
+static void normalize_arr(Word16 *arr, Word16 *qf, Word16 size, Word16 hdr)
+{
+ Word16 i;
+ Word16 max_s = 0;
+
+ FOR(i = 0; i < size; i++)
+ {
+ max_s = s_max(max_s, abs_s(arr[i]));
+ }
+
+ *qf = norm_s((Word16)max_s);
+ test();
+ IF((*qf == 0) && (((Word16)max_s) == 0))
+ {
+ *qf = 15;
+ move16();
+ }
+
+ *qf = *qf - hdr;
+
+ FOR(i = 0; i < size; i++)
+ {
+ arr[i] = shl(arr[i], *qf);
+ move16(); /* saturation can occur here */
+ }
+
+ return;
+}
+
+
+/*===================================================================*/
+/* FUNCTION : nelp_encoder_fx() */
+/*-------------------------------------------------------------------*/
+/* PURPOSE : NELP encoder */
+/* */
+/*-------------------------------------------------------------------*/
+/* GLOBAL INPUT ARGUMENTS : */
+/* _ (Struct) st : encoder state */
+/* _ (Word16[]) in_fx : residual signal (qIn) */
+/*-------------------------------------------------------------------*/
+/* OUTPUT ARGUMENTS : */
+/* _ (Word16[]) exc_fx : NELP quantized excitation signal (qIn) */
+/* _ (Word16) qIn1 : input/output qformat */
+/*-------------------------------------------------------------------*/
+
+/* _ (Word16[]) shape1_filt_mem_fx : filter memory (Q0) */
+/* _ (Word16[]) shape2_filt_mem_fx : filter memory (Q0) */
+/* _ (Word16[]) shape3_filt_mem_fx : filter memory (Q0) */
+/* _ (Word16[]) bp1_filt_mem_wb_fx : filter memory (Q0) */
+/* _ (Word16[]) txlpf1_filt1_mem_fx : filter memory (Q0) */
+/* _ (Word16[]) txlpf1_filt1_mem_fx : filter memory (Q0) */
+/* _ (Word16[]) txhpf1_filt2_mem_fx : filter memory (Q-1) */
+/* _ (Word16[]) txlpf1_filt2_mem_fx : filter memory (Q0) */
+/* _ (Word16) nelp_gain_mem_fx : gain memory (Q0) */
+/* _ (Word16) nelp_enc_seed : */
+/*-------------------------------------------------------------------*/
+/* RETURN ARGUMENTS : */
+/* _ None */
+/*===================================================================*/
+
+void nelp_encoder_fx(
+ Encoder_State *st_fx,/* i/o: encoder state */
+ Word16 *in_fx, /* i : residual signal */
+ Word16 *exc_fx, /* o : NELP quantized excitation signal */
+ Word16 *qIn1,
+ Word16 reduce_gains
+)
+{
+ Word16 i, j;
+ Word16 *ptr_fx = exc_fx;
+ Word16 lag = 25; /* to cover 25*9 + 31 */
+ Word16 sqrt_inv_lag = 6554; /* sqrt(1/lag) in Q15 */
+ Word16 sqrt_inv_lframe_lag = 5885; /* sqrt(1/(L_FRAME-lag*9)) */
+ Word16 Gains_fx[10], gain_fac_fx;
+ Word16 iG1_fx, iG2_fx[2];
+ Word16 fid;
+ Word16 fdbck_fx;
+ Word32 var_dB_fx;
+ Word32 E1_fx = 0, EL1_fx = 0, EH1_fx = 0, E2_fx = 0, E3_fx = 0, EL2_fx = 0, EH2_fx = 0;
+ Word32 RL_fx = 0, RH_fx = 0;
+ Word16 R_fx = 0;
+ Word16 filtRes_fx[L_FRAME];
+ Word16 ptr_tmp_fx[L_FRAME];
+
+ Word16 qE1 = 0, qE2 = 0, qE3 = 0, qEL1 = 0, qEL2 = 0, qEH1 = 0, qEH2 = 0;
+ Word16 qIn = 0, qGain = 0, qf = 0, qf1 = 0, qNelpGain = 0;
+ Word16 exp1, exp2, tmp1, tmp2;
+ Word16 f_Noise, etmp, e_Noise;
+ Word16 max1 = 0;
+ Word32 l_nelp_gain_mem;
+ Word32 Ltemp = 0, Ltemp1 = 0, L_tmp = 0, L_const_1;
+ Word16 BP1_ORDER;
+ Word16 rf_flag;
+#ifdef BASOP_NOGLOB_DECLARE_LOCAL
+ Flag Overflow = 0;
+#endif
+ SC_VBR_ENC_HANDLE hSC_VBR = st_fx->hSC_VBR;
+ BSTR_ENC_HANDLE hBstr = st_fx->hBstr;
+ RF_ENC_HANDLE hRF = st_fx->hRF;
+
+ rf_flag = st_fx->rf_mode;
+
+ if (EQ_16(hSC_VBR->last_nelp_mode, 1) && NE_16(st_fx->bwidth, st_fx->last_bwidth))
+ {
+ hSC_VBR->last_nelp_mode = 0;
+ }
+
+ qIn = *qIn1;
+ move16();
+ test();
+ IF(EQ_16(st_fx->bwidth, NB))
+ {
+ IF(hSC_VBR->last_nelp_mode != 1)
+ {
+ BP1_ORDER = 7;
+ move16();
+ set32_fx(hSC_VBR->bp1_filt_mem_nb_fx, 0, BP1_ORDER * 2);
+ hSC_VBR->qprevGain_fx = 0;
+ move16();
+ }
+ }
+ ELSE IF(EQ_16(st_fx->bwidth, WB) || EQ_16(st_fx->bwidth, SWB))
+ {
+ IF(hSC_VBR->last_nelp_mode != 1)
+ {
+ BP1_ORDER = 4;
+ move16();
+ set16_fx(hSC_VBR->bp1_filt_mem_wb_fx, 0, BP1_ORDER * 2);
+ }
+ }
+
+ IF(hSC_VBR->last_nelp_mode != 1)
+ {
+ test();
+ IF(st_fx->bwidth == WB || EQ_16(st_fx->bwidth, SWB))
+ {
+ set16_fx(hSC_VBR->shape1_filt_mem_fx, 0, 10);
+ set16_fx(hSC_VBR->shape2_filt_mem_fx, 0, 10);
+ set16_fx(hSC_VBR->shape3_filt_mem_fx, 0, 10);
+ set16_fx(hSC_VBR->txlpf1_filt1_mem_fx, 0, 10);
+ set16_fx(hSC_VBR->txlpf1_filt2_mem_fx, 0, 10);
+ set16_fx(hSC_VBR->txhpf1_filt1_mem_fx, 0, 10);
+ set16_fx(hSC_VBR->txhpf1_filt2_mem_fx, 0, 10);
+ hSC_VBR->qprevIn_fx = 0;
+ move16();
+ hSC_VBR->qprevGain_fx = 0;
+ move16();
+ }
+ }
+
+ /* Start Unvoiced/NELP Processing */
+ test();
+ IF(EQ_16(st_fx->bwidth, WB) || EQ_16(st_fx->bwidth, SWB))
+ {
+ qE1 = qIn;
+ move16();
+ E1_fx = L_deposit_l(0);
+ FOR(i = 0; i < L_FRAME; i++)
+ {
+#ifdef BASOP_NOGLOB
+ E1_fx = L_mac0_o(E1_fx, in_fx[i], in_fx[i], &Overflow); /*Q(qE1+qE1) */
+#else
+ E1_fx = L_mac0(E1_fx, in_fx[i], in_fx[i]); /*Q(qE1+qE1) */
+#endif
+ }
+
+ qE1 = shl(qE1, 1);;
+
+ qf = qIn;
+ move16();
+ Scale_sig(hSC_VBR->txlpf1_filt1_mem_fx, 10, (qf - hSC_VBR->qprevIn_fx));
+ pz_filter_sp_fx(txlpf1_num_coef_fx, txlpf1_den_coef_fx, in_fx, filtRes_fx, hSC_VBR->txlpf1_filt1_mem_fx, 10, 10, L_FRAME, 3);/*1 = (16-qformat of shape1 cofficient) */
+
+ qEL1 = qf;
+ move16();
+ EL1_fx = L_deposit_l(0);
+ FOR(i = 0; i < L_FRAME; i++)
+ {
+#ifdef BASOP_NOGLOB
+ EL1_fx = L_mac0_o(EL1_fx, filtRes_fx[i], filtRes_fx[i], &Overflow); /*Q(2*qIn) */
+#else
+ EL1_fx = L_mac0(EL1_fx, filtRes_fx[i], filtRes_fx[i]); /*Q(2*qIn) */
+#endif
+ }
+ qEL1 = shl(qEL1, 1);
+
+ qf = qIn;
+ move16();
+ Scale_sig(hSC_VBR->txhpf1_filt1_mem_fx, 10, qf - hSC_VBR->qprevIn_fx);
+ pz_filter_sp_fx(txhpf1_num_coef_fx, txhpf1_den_coef_fx, in_fx, filtRes_fx, hSC_VBR->txhpf1_filt1_mem_fx, 10, 10, L_FRAME, 3);/*1 = (16-qformat of shape1 cofficient) */
+ hSC_VBR->qprevIn_fx = qf;
+ move16();
+
+ qEH1 = qf;
+ move16();
+ EH1_fx = L_deposit_l(0);
+ FOR(i = 0; i < L_FRAME; i++)
+ {
+#ifdef BASOP_NOGLOB
+ EH1_fx = L_mac0_o(EH1_fx, filtRes_fx[i], filtRes_fx[i], &Overflow); /*Q(2*qEH1) */
+#else
+ EH1_fx = L_mac0(EH1_fx, filtRes_fx[i], filtRes_fx[i]); /*Q(2*qEH1) */
+#endif
+ }
+ qEH1 = 2 * qEH1;
+ move16();
+
+ }
+
+ qGain = qIn;
+ move16();
+ qGain = 2 * qGain;
+ move16();
+
+ FOR(i = 0; i < 9; i++)
+ {
+ Ltemp = L_deposit_l(0);
+ FOR(j = (Word16)(i*lag); j < (Word16)((i + 1)*lag); j++)
+ {
+#ifdef BASOP_NOGLOB
+ Ltemp = L_mac0_o(Ltemp, in_fx[j], in_fx[j], &Overflow); /*Q(2*qGain) */
+#else
+ Ltemp = L_mac0(Ltemp, in_fx[j], in_fx[j]); /*Q(2*qGain) */
+#endif
+ }
+
+ /*Gains[i] = (float) sqrt(Gains[i]/lag); */
+ IF(Ltemp != 0)
+ {
+ exp1 = norm_l(Ltemp);
+ tmp1 = extract_h(L_shl(Ltemp, exp1));/*2*qGain+exp1-16 */
+ exp1 = sub(exp1, 30 - qGain); /* */
+
+ tmp1 = div_s(16384, tmp1);/*14-2*qGain-exp1+16 */
+ L_tmp = L_deposit_h(tmp1);
+ L_tmp = Isqrt_lc(L_tmp, &exp1);
+ L_tmp = Mult_32_16(L_tmp, sqrt_inv_lag);
+ Ltemp = L_shl(L_tmp, sub(exp1, 12));/*Q3 */
+ }
+
+ Gains_fx[i] = round_fx(Ltemp);
+ }
+
+
+ Ltemp = L_deposit_l(0);
+ FOR(j = (Word16)(i*lag); j < L_FRAME; j++)
+ {
+#ifdef BASOP_NOGLOB
+ Ltemp = L_mac0_o(Ltemp, in_fx[j], in_fx[j], &Overflow); /*Q(2*qGain) */
+#else
+ Ltemp = L_mac0(Ltemp, in_fx[j], in_fx[j]); /*Q(2*qGain) */
+#endif
+ }
+
+ /*Gains[i] = (float) sqrt(Gains[i]/(L_FRAME-(lag*i))); */
+ IF(Ltemp != 0)
+ {
+ exp1 = norm_l(Ltemp);
+ tmp1 = extract_h(L_shl(Ltemp, exp1));
+ exp1 = sub(exp1, 30 - qGain); /* */
+
+ tmp1 = div_s(16384, tmp1);
+ L_tmp = L_deposit_h(tmp1);
+ L_tmp = Isqrt_lc(L_tmp, &exp1);
+ L_tmp = Mult_32_16(L_tmp, sqrt_inv_lframe_lag);
+ Ltemp = L_shl(L_tmp, sub(exp1, 12));
+ }
+
+ Gains_fx[i] = round_fx(Ltemp);
+
+ IF(EQ_16(reduce_gains, 1))
+ {
+ FOR(i = 0; i < 10; i++)
+ {
+ Gains_fx[i] = mult(Gains_fx[i], 19661);
+ }
+ }
+
+
+ qGain = 3;
+ move16();
+ IF(hSC_VBR->last_nelp_mode != 1) /* if prev frame was not NELP then init mem*/
+ {
+ hSC_VBR->nelp_gain_mem_fx = Gains_fx[0];
+ move16();
+ qNelpGain = qGain;
+ move16();
+ }
+
+ /* tmp = (float) (20.0 * (log10 (Gains[0]) - log10 (st->nelp_gain_mem) ) ); */
+ /* var_dB = tmp * tmp; */
+ L_tmp = L_deposit_l(Gains_fx[0]);
+ L_tmp = L_max(L_tmp, 1);
+ exp2 = norm_l(L_tmp);
+ L_tmp = L_shl(L_tmp, exp2);/*15+qEL1-qEL2-exp1+exp2 */
+ exp2 = 30 - exp2 - qGain;
+ move16();
+ tmp1 = Log2_norm_lc(L_tmp);
+ Ltemp = Mpy_32_16(exp2, tmp1, 9864); /*log(2) in Q13 format = Q0 format */
+ /*tmp1 = round_fx(L_shl(Ltemp,12)); Q12 */
+
+ L_tmp = L_deposit_l(hSC_VBR->nelp_gain_mem_fx); /*Q0 */
+ L_tmp = L_max(L_tmp, 1);
+ exp2 = norm_l(L_tmp);
+ L_tmp = L_shl(L_tmp, exp2);/*15+qEL1-qEL2-exp1+exp2 */
+ exp2 = 30 - exp2 - qNelpGain;
+ move16();
+ tmp2 = Log2_norm_lc(L_tmp);
+ Ltemp1 = Mpy_32_16(exp2, tmp2, 9864); /*log(2) in Q13 format = Q0 format */
+ Ltemp1 = L_sub(Ltemp, Ltemp1);/*Q16 */
+ Ltemp = Mult_32_16(Ltemp1, 20480);/*Q11 (20 in Q10) */
+ L_tmp = L_shl(Ltemp, 12);/*Q23 */
+ var_dB_fx = Mult_32_32(L_tmp, L_tmp);/*Q15 */
+
+ FOR(i = 1; i < 10; i++)
+ {
+ L_tmp = L_deposit_l(Gains_fx[i]);
+ L_tmp = L_max(L_tmp, 1);
+ exp2 = norm_l(L_tmp);
+ L_tmp = L_shl(L_tmp, exp2);/*15+qEL1-qEL2-exp1+exp2 */
+ exp2 = 30 - exp2 - qGain;
+ move16();
+ tmp1 = Log2_norm_lc(L_tmp);
+ Ltemp = Mpy_32_16(exp2, tmp1, 9864); /*log(2) in Q13 format = Q0 format */
+
+ L_tmp = L_deposit_l(Gains_fx[i - 1]); /*Q0 */
+ L_tmp = L_max(L_tmp, 1);
+ exp2 = norm_l(L_tmp);
+ L_tmp = L_shl(L_tmp, exp2);/*15+qEL1-qEL2-exp1+exp2 */
+ exp2 = 30 - exp2 - qGain;
+ move16();
+ tmp2 = Log2_norm_lc(L_tmp);
+ Ltemp1 = Mpy_32_16(exp2, tmp2, 9864); /*log(2) in Q13 format = Q0 format */
+ Ltemp1 = L_sub(Ltemp, Ltemp1);/*Q16 */
+ Ltemp = Mult_32_16(Ltemp1, 20480);/*Q11 (20 in Q10) */
+ L_tmp = L_shl(Ltemp, 12);/*Q23 */
+ L_tmp = Mult_32_32(L_tmp, L_tmp);/*Q15 */
+ var_dB_fx = L_add(L_tmp, var_dB_fx);/*Q15 */
+ }
+
+ IF(hSC_VBR->last_nelp_mode != 1)
+ {
+ /*var_dB *= 0.111f; */
+ var_dB_fx = Mult_32_16(var_dB_fx, 3637); /*0.111 in Q15 */
+ }
+ ELSE
+ {
+ /*var_dB *= 0.1f; */
+ var_dB_fx = Mult_32_16(var_dB_fx, 3277); /*0.1 in Q15 */
+ }
+
+ max1 = 0;
+ move16();
+ FOR(i = 0; i < 10; i++)
+ {
+ max1 = s_max(max1, abs_s(Gains_fx[i]));
+ }
+
+ qf = norm_s((Word16)max1);
+ test();
+ IF((qf == 0) && (((Word16)max1) == 0))
+ {
+ qf = 15;
+ move16();
+ }
+ qf = sub(qf, 1);
+ qGain = add(qGain, qf);
+
+ Scale_sig(Gains_fx, 10, qf);
+
+ L_tmp = L_sub(var_dB_fx, 655360); /* 20 in Q15 */
+ Ltemp = L_shr_r(L_tmp, 2);/*Q15 */
+ {
+ /*exp = pow(2, x*log2(e)) */
+ L_tmp = Mult_32_16(Ltemp, 23637); /*15 + 14 -15 ->Q14 */
+ L_tmp = L_shl(L_tmp, 2); /*Q16 */
+ f_Noise = L_Extract_lc(L_tmp, &e_Noise); /*Q16 */
+ etmp = extract_l(Pow2(14, f_Noise)); /* Put 14 as exponent */
+ e_Noise = sub(e_Noise, 14); /* Retreive exponent of etmp */
+
+
+ IF(e_Noise > 0)
+ {
+ L_tmp = L_shl(etmp, e_Noise); /* Result in Q30 */
+ L_tmp = L_add(1, L_tmp);
+
+ exp1 = norm_l(L_tmp);
+ tmp1 = extract_h(L_shl(L_tmp, exp1));/*exp1-16 */
+ tmp1 = div_s(16384, tmp1);/*14-(exp1-16)-> 30+15-exp1 */
+ fdbck_fx = mult(26870, tmp1);/*45-exp1+15-15=>45-exp1 */
+ fdbck_fx = shr_r(fdbck_fx, 14);
+ exp1 = sub(31, exp1);
+ }
+ ELSE
+ {
+ L_tmp = L_shl(etmp,add(e_Noise, 14)); /* Result in Q30 */
+ L_tmp = L_add(16384, L_tmp);
+
+ exp1 = norm_l(L_tmp);
+ tmp1 = extract_h(L_shl(L_tmp, exp1));/*14+exp1-16 */
+ tmp1 = div_s(16384, tmp1);/*14-(14+exp1-16)-> 16+15-exp1 */
+ fdbck_fx = mult(26870, tmp1);/*31-exp1+15-15=>31-exp1 */
+ exp1 = sub(31,exp1);
+ }
+ }
+
+ IF(exp1 == 31)
+ {
+ L_const_1 = 0x7fffffff;
+ move32();
+ }
+ ELSE
+ {
+ L_const_1 = L_shl(1, exp1);
+ }
+
+ l_nelp_gain_mem = L_deposit_l(hSC_VBR->nelp_gain_mem_fx);
+ IF(NE_16(qNelpGain, qGain))
+ {
+ l_nelp_gain_mem = L_shl(l_nelp_gain_mem, sub(qGain, qNelpGain));
+ }
+
+ FOR(i = 0; i < 10; i++)
+ {
+ /*Gains[i] = (float)((1.0f - fdbck) * Gains[i] + fdbck * st->nelp_gain_mem); */
+ L_tmp = L_sub(L_const_1, L_deposit_l(fdbck_fx));/*31-exp1 */
+ L_tmp = Mult_32_16(L_tmp, Gains_fx[i]);/*exp1+qGain-15=>exp1-15+qGain */
+ Ltemp1 = Mult_32_16(l_nelp_gain_mem, fdbck_fx);/*exp1+qGain-15 */
+ L_tmp = L_add(L_tmp, Ltemp1);
+ L_tmp = L_shr_r(L_tmp, (exp1 - 15));
+ Gains_fx[i] = round_fx(L_shl(L_tmp, 16));
+ move16();
+ l_nelp_gain_mem = L_tmp;
+ }
+
+ hSC_VBR->nelp_gain_mem_fx = round_fx(L_shl(l_nelp_gain_mem, 16));
+
+ Scale_sig(&hSC_VBR->nelp_gain_mem_fx, 1, -qGain);
+ Scale_sig(Gains_fx, 10, -qGain);
+ qGain = 0;
+ move16();
+
+ quantize_uvg_fx(Gains_fx, &iG1_fx, iG2_fx, Gains_fx, st_fx->bwidth);
+
+ IF(EQ_16(rf_flag, 1))
+ {
+ hRF->rf_indx_nelp_iG1[0] = iG1_fx;
+ hRF->rf_indx_nelp_iG2[0][0] = iG2_fx[0];
+ hRF->rf_indx_nelp_iG2[0][1] = iG2_fx[1];
+ }
+ ELSE
+ {
+ push_indice_fx(hBstr, IND_IG1, iG1_fx, 5);
+ push_indice_fx(hBstr, IND_IG2A, iG2_fx[0], 6);
+ push_indice_fx(hBstr, IND_IG2B, iG2_fx[1], 6);
+ }
+
+ test();
+ IF(EQ_16(st_fx->bwidth, WB) || EQ_16(st_fx->bwidth, SWB))
+ {
+ gain_fac_fx = 19005;
+ move16();/* 1.16f in Q14 */
+ }
+ ELSE
+ {
+ gain_fac_fx = 22446;
+ move16(); /* 1.37f in Q14 */
+ }
+
+ /* Normalize Gains_fx[10] with headroom 4 */
+ /* This fills up qGain with some new value */
+ normalize_arr(Gains_fx, &qGain, 10, 4);
+
+ generate_nelp_excitation_fx(&(hSC_VBR->nelp_enc_seed), Gains_fx, ptr_fx, gain_fac_fx);
+ test();
+ IF(EQ_16(st_fx->bwidth, WB) || EQ_16(st_fx->bwidth, SWB))
+ {
+ BP1_ORDER = 4;
+ Scale_sig(hSC_VBR->bp1_filt_mem_wb_fx, BP1_ORDER * 2, qGain - hSC_VBR->qprevGain_fx);/*qf-qAdj */
+ pz_filter_sp_fx(bp1_num_coef_wb_fx, bp1_den_coef_wb_fx, ptr_fx, ptr_tmp_fx, hSC_VBR->bp1_filt_mem_wb_fx, BP1_ORDER, BP1_ORDER, L_FRAME, 2);
+ Copy(ptr_tmp_fx, ptr_fx, L_FRAME);
+ }
+ ELSE IF(EQ_16(st_fx->bwidth, NB))
+ {
+ BP1_ORDER = 7;
+ move16();
+ Scale_sig32(hSC_VBR->bp1_filt_mem_nb_fx, BP1_ORDER * 2, (qGain - hSC_VBR->qprevGain_fx));
+ pz_filter_dp_fx(bp1_num_coef_nb_fx_order7, bp1_den_coef_nb_fx_order7, ptr_fx, ptr_tmp_fx, hSC_VBR->bp1_filt_mem_nb_fx, BP1_ORDER, BP1_ORDER, L_FRAME, (sub(16, BP1_COEF_NB_QF_ORDER7)));
+ Copy(ptr_tmp_fx, ptr_fx, L_FRAME);
+
+ Scale_sig(ptr_fx, L_FRAME, -1); /* bring exc to qgain-1 */
+ *qIn1 = qGain - 1; /* use this temp only in the parent */
+ }
+
+ E3_fx = L_deposit_l(0);
+ FOR(i = 0; i < L_FRAME; i++)
+ {
+ E3_fx = L_mac(E3_fx, ptr_fx[i], ptr_fx[i]); /*Q1 */
+ }
+ qE3 = 2 * qGain + 1;
+ move16();
+ test();
+ IF(st_fx->bwidth == WB || EQ_16(st_fx->bwidth, SWB))
+ {
+ Scale_sig(hSC_VBR->shape1_filt_mem_fx, 10, (qGain - hSC_VBR->qprevGain_fx));
+ pz_filter_sp_fx(shape1_num_coef_fx, shape1_den_coef_fx, ptr_fx, ptr_tmp_fx, hSC_VBR->shape1_filt_mem_fx, 10, 10, L_FRAME, 1);/*1 = (16-qformat of shape1 cofficient) */
+ Copy(ptr_tmp_fx, ptr_fx, L_FRAME);
+
+ qf = qGain;
+ move16();
+ E2_fx = L_deposit_l(0);
+ FOR(i = 0; i < L_FRAME; i++)
+ {
+ Ltemp = L_mult0(ptr_fx[i], ptr_fx[i]); /*Q(2*qE2+1) */
+ Ltemp = L_shr_r(Ltemp, 4);
+ E2_fx = L_add(E2_fx, Ltemp);
+ }
+ qE2 = 2 * qf - 4;
+ move16();
+
+ test();
+ IF(E1_fx == 0)
+ {
+ R_fx = 0;
+ move16();
+ }
+ ELSE IF((E2_fx == 0) && (E1_fx != 0))
+ {
+ exp1 = norm_l(E1_fx);
+ tmp1 = extract_h(L_shl(E1_fx, exp1));/*qE1+exp1-16 */
+ tmp1 = div_s(16384, tmp1);/*14-(qE1+exp1-16)-> 30-qE1-exp1 */
+ exp1 = sub(exp1, 30 - qE1);
+
+ L_tmp = L_deposit_h(tmp1);
+ L_tmp = Isqrt_lc(L_tmp, &exp1);
+ Ltemp = L_shl(L_tmp, sub(exp1, 12));
+ R_fx = round_fx(Ltemp);
+ }
+ ELSE
+ {
+ exp1 = norm_l(E1_fx);
+ tmp1 = extract_h(L_shl(E1_fx, exp1));/*qE1+exp1-16 */
+ tmp1 = div_s(16384, tmp1);/*14-(qE1+exp1-16)-> 30-qE1-exp1 */
+ L_tmp = Mult_32_16(E2_fx, tmp1);/*qE2+30-qE1-exp1-15=>15+qE2-qE1-exp1 */
+
+ exp2 = norm_l(L_tmp);
+ L_tmp = L_shl(L_tmp, exp2);/*15+qE2-qE1-exp1+exp2 */
+ exp2 = 30 - (15 + qE2 - qE1 - exp1 + exp2);
+ move16();
+ L_tmp = Isqrt_lc(L_tmp, &exp2);/*Q(31+exp2) */
+ R_fx = round_fx(L_tmp);
+ exp1 = 31 - exp2 - 16 - 7;
+ move16();
+ }
+
+ FOR(i = 0; i < L_FRAME; i++)
+ {
+ Ltemp = L_mult0(R_fx, ptr_fx[i]);
+ Ltemp = L_shr_r(Ltemp, exp1);
+ filtRes_fx[i] = round_fx(L_shl(Ltemp, 16));
+ }
+
+ qf1 = qGain;
+ move16();
+ Scale_sig(hSC_VBR->txlpf1_filt2_mem_fx, 10, (qf1 - hSC_VBR->qprevGain_fx));
+
+ pz_filter_sp_fx(txlpf1_num_coef_fx, txlpf1_den_coef_fx, filtRes_fx, ptr_tmp_fx, hSC_VBR->txlpf1_filt2_mem_fx, 10, 10, L_FRAME, 3);/*1 = (16-qformat of shape1 cofficient) */
+ Copy(ptr_tmp_fx, filtRes_fx, L_FRAME);
+
+ qEL2 = qf1;
+ move16();
+ EL2_fx = L_deposit_l(0);
+ FOR(i = 0; i < L_FRAME; i++)
+ {
+ EL2_fx = L_mac0(EL2_fx, filtRes_fx[i], filtRes_fx[i]); /*Q(2*qEL2) */
+ }
+ qEL2 = 2 * qEL2;
+ move16();
+
+ FOR(i = 0; i < L_FRAME; i++)
+ {
+ Ltemp = L_mult0(R_fx, ptr_fx[i]);
+ Ltemp = L_shr_r(Ltemp, exp1);
+ filtRes_fx[i] = round_fx(L_shl(Ltemp, 16));
+ }
+
+ qf = qGain;
+ move16();
+ Scale_sig(hSC_VBR->txhpf1_filt2_mem_fx, 10, (qf - hSC_VBR->qprevGain_fx));
+ pz_filter_sp_fx(txhpf1_num_coef_fx, txhpf1_den_coef_fx, filtRes_fx, ptr_tmp_fx, hSC_VBR->txhpf1_filt2_mem_fx, 10, 10, L_FRAME, 3);/*1 = (16-qformat of shape1 cofficient) */
+
+ Copy(ptr_tmp_fx, filtRes_fx, L_FRAME);
+
+ qEH2 = qf;
+ move16();
+ EH2_fx = L_deposit_l(0);
+ FOR(i = 0; i < L_FRAME; i++)
+ {
+ EH2_fx = L_mac0(EH2_fx, filtRes_fx[i], filtRes_fx[i]); /*Q(2*qEH2) */
+ }
+ qEH2 = 2 * qEH2;
+ move16();
+ IF(EL2_fx == 0)
+ {
+ exp2 = norm_l(EL1_fx);
+ L_tmp = L_shl(EL1_fx, exp2);
+ exp2 = 30 - exp2 - qEL1;
+ move16();
+ tmp1 = Log2_norm_lc(L_tmp);
+ Ltemp = Mpy_32_16(exp2, tmp1, 9864); /*10*log(2) in Q15 format = Q0 format */
+ tmp1 = round_fx(L_shl(Ltemp, 12));/* Q12 */
+ RL_fx = L_mult0(tmp1, 10);
+ }
+ ELSE
+ {
+ exp1 = norm_l(EL2_fx);
+ tmp1 = extract_h(L_shl(EL2_fx, exp1));/*qEL2+exp1-16 */
+ tmp1 = div_s(16384, tmp1);/*14-(qEL2+exp1-16)-> 30-qEL2-exp1 */
+ L_tmp = Mult_32_16(EL1_fx, tmp1);/*qEL1+30-qEL2-exp1-15=>15+qE1-qEL2-exp1 */
+
+ exp2 = norm_l(L_tmp);
+ L_tmp = L_shl(L_tmp, exp2);/*15+qEL1-qEL2-exp1+exp2 */
+ exp2 = 30 - (30 + qEL1 - qEL2 - exp1 + exp2);
+ move16();
+ tmp1 = Log2_norm_lc(L_tmp);
+ Ltemp = Mpy_32_16(exp2, tmp1,9864); /*10*log(2) in Q15 format = Q0 format */
+ tmp1 = round_fx(L_shl(Ltemp,12));/* Q12 */
+ RL_fx = L_mult0(tmp1, 10);
+ }
+
+ IF(EH2_fx == 0)
+ {
+ exp2 = norm_l(EH2_fx);
+ L_tmp = L_shl(EH2_fx, exp2);
+ exp2 = 30 - exp2 - qEH2;
+ move16();
+ tmp1 = Log2_norm_lc(L_tmp);
+ Ltemp = Mpy_32_16(exp2, tmp1, 9864); /*10*log(2) in Q13 format = Q0 format */
+ tmp1 = round_fx(L_shl(Ltemp, 12));/* Q12 */
+ RH_fx = L_mult0(tmp1, 10);
+ }
+ ELSE
+ {
+ exp1 = norm_l(EH2_fx);
+ tmp1 = extract_h(L_shl(EH2_fx, exp1));/*qEH2+exp1-16 */
+ tmp1 = div_s(16384, tmp1);/*14-(qEH2+exp1-16)-> 30-qEH2-exp1 */
+ L_tmp = Mult_32_16(EH1_fx, tmp1);/*15+qEH1-qEH2-exp1 */
+
+ exp2 = norm_l(L_tmp);
+ L_tmp = L_shl(L_tmp, exp2);/*15+qEH1-qEH2-exp1+exp2 */
+ exp2 = 30 - (30 + qEH1 - qEH2 - exp1 + exp2);
+ move16();
+ tmp1 = Log2_norm_lc(L_tmp);
+ Ltemp = Mpy_32_16(exp2, tmp1,9864); /*10*log(2) in Q13 format = Q0 format */
+ tmp1 = round_fx(L_shl(Ltemp,12));/* Q12 */
+ RH_fx = L_mult0(tmp1, 10);
+ }
+
+ fid = 0;
+ move16();
+ IF(LT_32(RL_fx, -12288)) /* -3 in Q12 */
+ {
+ fid = 1;
+ move16();
+ }
+ ELSE IF(LT_32(RH_fx, -12288)) /* -3 in Q12 */
+ {
+ fid = 2;
+ move16();
+ }
+
+ IF(rf_flag == 0)
+ {
+
+ SWITCH(fid)
+ {
+ case 1:
+ /* Update other filter memory */
+ Scale_sig(hSC_VBR->shape3_filt_mem_fx, 10, (qGain - hSC_VBR->qprevGain_fx));
+ pz_filter_sp_fx(shape3_num_coef_fx, shape3_den_coef_fx, ptr_fx, filtRes_fx, hSC_VBR->shape3_filt_mem_fx, 10, 10, L_FRAME, 1);/*1 = (16-qformat of shape1 cofficient) */
+
+ /* filter the residual to desired shape */
+ Scale_sig(hSC_VBR->shape2_filt_mem_fx, 10, (qGain - hSC_VBR->qprevGain_fx));
+ pz_filter_sp_fx(shape2_num_coef_fx, shape2_den_coef_fx, ptr_fx, ptr_tmp_fx, hSC_VBR->shape2_filt_mem_fx, 10, 10, L_FRAME, 1);/*1 = (16-qformat of shape1 cofficient) */
+ Copy(ptr_tmp_fx, ptr_fx, L_FRAME);
+
+ BREAK;
+ case 2:
+ /* Update other filter memory */
+ Scale_sig(hSC_VBR->shape2_filt_mem_fx, 10, (qGain - hSC_VBR->qprevGain_fx));
+ pz_filter_sp_fx(shape2_num_coef_fx, shape2_den_coef_fx, ptr_fx, filtRes_fx, hSC_VBR->shape2_filt_mem_fx, 10, 10, L_FRAME, 1);/*1 = (16-qformat of shape1 cofficient) */
+
+ /* filter the residual to desired shape */
+ Scale_sig(hSC_VBR->shape3_filt_mem_fx, 10, (qGain - hSC_VBR->qprevGain_fx));
+ pz_filter_sp_fx(shape3_num_coef_fx, shape3_den_coef_fx, ptr_fx, ptr_tmp_fx, hSC_VBR->shape3_filt_mem_fx, 10, 10, L_FRAME, 1);/*1 = (16-qformat of shape1 cofficient) */
+
+ Copy(ptr_tmp_fx, ptr_fx, L_FRAME);
+
+ BREAK;
+ default:
+ Scale_sig(hSC_VBR->shape2_filt_mem_fx, 10, (qGain - hSC_VBR->qprevGain_fx));
+ pz_filter_sp_fx(shape2_num_coef_fx, shape2_den_coef_fx, ptr_fx, filtRes_fx, hSC_VBR->shape2_filt_mem_fx, 10, 10, L_FRAME, 1);/*1 = (16-qformat of shape1 cofficient) */
+
+ Scale_sig(hSC_VBR->shape3_filt_mem_fx, 10, (qGain - hSC_VBR->qprevGain_fx));
+ pz_filter_sp_fx(shape3_num_coef_fx, shape3_den_coef_fx, ptr_fx, filtRes_fx, hSC_VBR->shape3_filt_mem_fx, 10, 10, L_FRAME, 1);/*1 = (16-qformat of shape1 cofficient) */
+
+ BREAK;
+ }
+
+ qE2 = qGain;
+ move16();
+
+ E2_fx = L_deposit_l(0);
+ FOR(i = 0; i < L_FRAME; i++)
+ {
+ Ltemp = L_mult0(ptr_fx[i], ptr_fx[i]); /*Q(2*qE2+1) */
+ Ltemp = L_shr_r(Ltemp, 4);
+ E2_fx = L_add(E2_fx, Ltemp);
+ }
+ qE2 = (2 * qE2) - 4;
+ move16();
+ test();
+ IF(E3_fx == 0)
+ {
+ R_fx = 0;
+ move16();
+ }
+ ELSE IF((E2_fx == 0) && (E3_fx != 0))
+ {
+ exp1 = norm_l(E3_fx);
+ tmp1 = extract_h(L_shl(E3_fx, exp1));/*qE3+exp1-16 */
+ tmp1 = div_s(16384, tmp1);/*14-(qE3+exp1-16)-> 30-qE3-exp1 */
+ exp1 = sub(exp1, 30 - qE3);
+
+ L_tmp = L_deposit_h(tmp1);
+ L_tmp = Isqrt_lc(L_tmp, &exp1);
+ Ltemp = L_shl(L_tmp, sub(exp1, 12));
+ R_fx = round_fx(Ltemp);
+ }
+ ELSE
+ {
+ exp1 = norm_l(E3_fx);
+ tmp1 = extract_h(L_shl(E3_fx, exp1));/*qE3+exp1-16 */
+ tmp1 = div_s(16384, tmp1);/*14-(qE3+exp1-16)-> 30-qE3-exp1 */
+ L_tmp = Mult_32_16(E2_fx, tmp1);/*qE2+30-qE3-exp1-15=>15+qE2-qE3-exp1 */
+
+ exp2 = norm_l(L_tmp);
+ L_tmp = L_shl(L_tmp, exp2);/*15+qE2-qE3-exp1+exp2 */
+ exp2 = 30 - (15 + qE2 - qE3 - exp1 + exp2);
+ move16();
+ L_tmp = Isqrt_lc(L_tmp, &exp2);/*Q(31+exp2) */
+ R_fx = round_fx(L_tmp);
+ exp1 = 31 - exp2 - 16 - 7;
+ move16();
+ }
+
+ FOR(i = 0; i < L_FRAME; i++)
+ {
+ L_tmp = L_mult0(R_fx, ptr_fx[i]);
+ L_tmp = L_shr_r(L_tmp, exp1 + 1);
+ ptr_fx[i] = round_fx(L_shl(L_tmp, 16));
+ }
+ *qIn1 = qGain - 1;
+ move16();
+ }
+
+ IF(EQ_16(rf_flag, 1))
+ {
+ hRF->rf_indx_nelp_fid[0] = fid;
+ move16();
+ }
+ ELSE
+ {
+ push_indice_fx(hBstr, IND_NELP_FID, fid, 2);
+ }
+ }
+
+ hSC_VBR->qprevGain_fx = qGain;
+ move16();
+
+ IF(rf_flag == 0)
+ {
+ FOR(i = 0; i < L_FRAME; i++)
+ {
+ exc_fx[i] = ptr_fx[i];
+ move16();
+ }
+ }
+
+ return;
+}
+
+
diff --git a/lib_enc/stat_enc.h b/lib_enc/stat_enc.h
index 4ce027a19a4e09fdf8078a82565ad5266ae2850a..97411839cf8c0dbe49b7465e9f47e0576d685081 100644
--- a/lib_enc/stat_enc.h
+++ b/lib_enc/stat_enc.h
@@ -977,6 +977,9 @@ typedef struct sc_vbr_enc_structure
int16_t last_nelp_mode;
int16_t nelp_mode;
+ Word16 qprevIn_fx;
+ Word16 qprevGain_fx;
+
/* PPP variables */
int16_t pppcountE;
int16_t bump_up;
diff --git a/lib_enc/swb_bwe_enc_lr_fx.c b/lib_enc/swb_bwe_enc_lr_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..4088bb500a405d932d5e2b0a1faf5ed4afa37e79
--- /dev/null
+++ b/lib_enc/swb_bwe_enc_lr_fx.c
@@ -0,0 +1,1128 @@
+/******************************************************************************************************
+
+ (C) 2022-2023 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.
+
+*******************************************************************************************************/
+
+#include
+#include "options.h"
+#include "prot_fx2.h"
+#include "rom_com.h"
+#include "enh32.h"
+
+ /*--------------------------------------------------------------------------*
+ * GetSubbandCorrIndex2_har()
+ *
+ * Finds the index of best correlation between highband (*inBuf) and lowband (*predBuf) for current subband of length (fLen)
+ *--------------------------------------------------------------------------*/
+static
+Word16 GetSubbandCorrIndex2_har_fx( /* o : best correlation index */
+ const Word32 *L_inBuf, /* i : target buffer (i.e., highband signal) : spectra */
+ const Word16 fLen, /* i : window length */
+ const Word16 *predBuf_fx, /* i : prediction buffer (i.e., lowband) : sspectra */
+ const Word16 predBufLen, /* i : sspectra buffer size */
+ const Word16 maxLag_fx, /* i : search length */
+ const GainItem_fx *G_item_fx, /* i : */
+ const Word16 nZero_fx, /* i : number of nonzero components used in */
+ Word16 *prev_frame_bstindx_fx /* i : previous frame best Indices */
+)
+{
+ Word16 i, j;
+ Word16 bestIdx_fx;
+ Word32 L_lagCorr_sq;
+ Word32 L_lagEnergy;
+
+ Word32 L_energy;
+ Word32 L_corr;
+ Word32 L_corr_sq;
+
+ Word16 corr_sq_hi_fx;
+ Word32 L_corr_sq_tmp;
+ Word32 L_lagCorr_sq_tmp;
+ Word16 corr_sq_fx;
+ Word16 lagCorr_sq_fx;
+ Word32 L_energy_tmp;
+ Word32 L_lagEnergy_tmp;
+ Word16 energy_fx;
+ Word16 lagEnergy_fx;
+
+ Word16 N1_fx, N2_fx;
+ Word16 exp_safe_e;
+
+ Word16 exp_corr;
+ Word16 exp_energy;
+
+ Word32 L_buf;
+
+ Word16 ibuf_fx[L_FRAME32k];
+ Word16 pbuf_fx[L_FRAME32k];
+ Word16 *ptr_pbuf;
+ Word16 exp_shift;
+
+ Word16 exp_norm;
+
+ Word32 L_tmp;
+
+#ifdef BASOP_NOGLOB_DECLARE_LOCAL
+ Flag Overflow = 0;
+#endif
+
+ exp_safe_e = 4;
+
+ L_tmp = L_deposit_l(0);
+ FOR(i = 0; i < fLen; i++)
+ {
+ L_tmp = L_or(L_tmp, L_abs(L_inBuf[i]));
+ }
+ exp_norm = norm_l(L_tmp);
+ exp_shift = sub(exp_norm, exp_safe_e);
+
+ FOR(i = 0; i < fLen; i++)
+ {
+ ibuf_fx[i] = extract_h(L_shl(L_inBuf[i], exp_shift)); /* Qi+exp_shift-16 */
+ }
+
+ FOR(i = 0; i < predBufLen; i++)
+ {
+ pbuf_fx[i] = shr(predBuf_fx[i], exp_safe_e);
+ move16(); /* Qss-exp_safe_e */
+ }
+
+ bestIdx_fx = 0;
+ move16();
+ L_lagCorr_sq = L_deposit_l(0);
+ L_lagEnergy = 0x7FFFFFFF;
+ move32();
+
+ N1_fx = s_max(0x0, sub(*prev_frame_bstindx_fx, shr(maxLag_fx, 1)));
+ IF(*prev_frame_bstindx_fx < 0)
+ {
+ N2_fx = sub(maxLag_fx, 1);
+ }
+ ELSE
+ {
+ N2_fx = s_min(sub(maxLag_fx, 1), add(*prev_frame_bstindx_fx, shr(maxLag_fx,1)));
+ }
+ predBuf_fx += N1_fx;
+ ptr_pbuf = pbuf_fx + N1_fx;
+
+
+ Overflow = 0;
+ move16();
+
+ /* find the best lag */
+ FOR(i = N1_fx; i <= N2_fx; i++)
+ {
+ L_corr = L_deposit_l(0);
+
+ /* get the energy, remove the old and update with the new energy index */
+
+ L_energy = L_deposit_l(0);
+ FOR(j = 0; j < fLen; j++)
+ {
+ /*energy += *predBuf * *predBuf; */
+#ifdef BASOP_NOGLOB /* Critical Overflow , as well as those below*/
+ L_energy = L_mac_o(L_energy, *ptr_pbuf, *ptr_pbuf, &Overflow); /* Q*2-1; */
+#else
+ L_energy = L_mac(L_energy, *ptr_pbuf, *ptr_pbuf); /* Q*2-1; */
+#endif
+ ptr_pbuf++;
+ }
+
+ ptr_pbuf -= fLen;
+
+ /* get cross-correlation */
+ IF(L_energy != 0x0L)
+ {
+ L_corr = L_deposit_l(0);
+ FOR(j = 0; j < nZero_fx; j++)
+ {
+ /*corr += inBuf[G_item[j].gainIndex]* predBuf[G_item[j].gainIndex]; */
+#ifdef BASOP_NOGLOB /* Critical Overflow */
+ L_corr = L_mac_o(L_corr, ibuf_fx[G_item_fx[j].gainIndex_fx], ptr_pbuf[G_item_fx[j].gainIndex_fx], &Overflow); /* Q*2-1 */
+#else
+ L_corr = L_mac(L_corr, ibuf_fx[G_item_fx[j].gainIndex_fx], ptr_pbuf[G_item_fx[j].gainIndex_fx]); /* Q*2-1 */
+#endif
+ }
+
+ /*corr_sq = corr*corr; */
+ exp_norm = norm_l(L_corr);
+ exp_norm = sub(exp_norm, 1); /* added for Overflow 0x8000 * 0x8000 -> Overflow */
+ L_corr_sq = L_shl(L_corr, exp_norm);
+ corr_sq_hi_fx = extract_h(L_corr_sq);
+
+#ifdef BASOP_NOGLOB /* Critical Overflow */
+ L_corr_sq = L_mult_o(corr_sq_hi_fx, corr_sq_hi_fx, &Overflow); /* (((Qhi:Qsh+exp_norm_hi-16)+Qss+1)+exp_norm-16)*2+1 */
+ L_corr_sq = L_shr_o(L_corr_sq, s_min(shl(exp_norm, 1), 31), &Overflow); /* (QCorr-16)*2+1 */
+#else
+ L_corr_sq = L_mult(corr_sq_hi_fx, corr_sq_hi_fx); /* (((Qhi:Qsh+exp_norm_hi-16)+Qss+1)+exp_norm-16)*2+1 */
+ L_corr_sq = L_shr(L_corr_sq, s_min(shl(exp_norm, 1), 31)); /* (QCorr-16)*2+1 */
+#endif
+ IF(Overflow != 0)
+ {
+ L_corr_sq = 0x0L;
+ move16();
+ Overflow = 0;
+ move16();
+ }
+
+ /* normalize for L_lagCorr_sq and L_corr_sq */
+ L_buf = L_or(L_lagCorr_sq, L_corr_sq);
+ exp_corr = norm_l(L_buf);
+ L_corr_sq_tmp = L_shl(L_corr_sq, exp_corr);
+ L_lagCorr_sq_tmp = L_shl(L_lagCorr_sq, exp_corr);
+ corr_sq_fx = extract_h(L_corr_sq_tmp);
+ lagCorr_sq_fx = extract_h(L_lagCorr_sq_tmp);
+
+ /* normalize for L_lagEnergy and L_energy */
+ L_buf = L_or(L_lagEnergy, L_energy);
+ exp_energy = norm_l(L_buf);
+ L_energy_tmp = L_shl(L_energy, exp_energy);
+ L_lagEnergy_tmp = L_shl(L_lagEnergy, exp_energy);
+ energy_fx = extract_h(L_energy_tmp);
+ lagEnergy_fx = extract_h(L_lagEnergy_tmp);
+
+ /*if( (double)lagCorr_sq*(double)energy < (double)corr_sq*(double)lagEnergy ) */
+ IF(L_msu(L_mult(lagCorr_sq_fx, energy_fx), corr_sq_fx, lagEnergy_fx) < 0)
+ {
+ bestIdx_fx = i;
+ move16();
+ L_lagCorr_sq = L_add(L_corr_sq, 0);
+ L_lagEnergy = L_add(L_energy, 0);
+ }
+
+ }
+ predBuf_fx++;
+ ptr_pbuf++;
+ }
+
+ test();
+ IF(L_lagCorr_sq == 0x0 && *prev_frame_bstindx_fx < 0)
+ {
+ bestIdx_fx = 0x0;
+ move16();
+ }
+ ELSE
+ {
+ if (L_lagCorr_sq == 0x0)
+ {
+ bestIdx_fx = *prev_frame_bstindx_fx;
+ move16();
+ }
+ }
+
+ *prev_frame_bstindx_fx = bestIdx_fx;
+ move16();
+
+ return bestIdx_fx;
+}
+
+/*--------------------------------------------------------------------------*
+ * getswbindices_har()
+ *
+ * Finds the pulse index of best correlation between highband (*yos) and lowband (*y2) for two groups of length sbLen
+ *--------------------------------------------------------------------------*/
+
+static void getswbindices_har_fx(
+ const Word32 *L_yos, /* i : original input spectrum */
+ Word16 exp_refBuf, /* i : */
+ Word16 *y2_fx, /* i : decoded spectrum */
+ const Word16 nBands_search_fx, /* i : number of bands */
+ Word16 *lagIndices_fx, /* o : pulse index */
+ Word16 *prev_frame_bstindx_fx, /* i/o: prev frame index */
+ const Word16 swb_lowband_fx, /* i : length of the LF spectrum */
+ const Word16 *subband_offsets_fx, /* i : */
+ const Word16 *sbWidth_fx, /* i : */
+ const Word16 *subband_search_offset_fx /* i : */
+)
+{
+ Word16 i, j, k, sb, tmp;
+ Word16 *ptr_predBuf;
+ GainItem_fx Nbiggest_fx[(NB_SWB_SUBBANDS_HAR_SEARCH_SB)*N_NBIGGEST_PULSEARCH];
+ Word16 n_nbiggestsearch_fx[NB_SWB_SUBBANDS_HAR];
+
+ Word16 search_offset_fx[NB_SWB_SUBBANDS_HAR_SEARCH_SB];
+ Word16 nlags_fx[NB_SWB_SUBBANDS_HAR_SEARCH_SB];
+
+ Word16 low_freqsgnl_fx[L_FRAME32k]; /* Qy2 (sspectra) */
+
+ ptr_predBuf = y2_fx;
+
+ /* Get the number of HF groups for performing Similarity search */
+ FOR(sb = 0; sb < nBands_search_fx; sb++)
+ {
+ /*nlags[sb] = (short)pow(2, bits_lagIndices_mode0_Har[sb]); */
+ nlags_fx[sb] = shl(1, bits_lagIndices_mode0_Har[sb]);
+ }
+
+ j = 0;
+ move16();
+ FOR(sb = 0; sb < nBands_search_fx; sb++)
+ {
+ /* Find NBiggest samples in HF Groups */
+ FindNBiggest2_simple_fx_har(L_yos + add(swb_lowband_fx, subband_offsets_fx[sb]), exp_refBuf, Nbiggest_fx + j,
+ sbWidth_fx[sb], &n_nbiggestsearch_fx[sb], N_NBIGGEST_PULSEARCH);
+
+ search_offset_fx[sb] = subband_search_offset_fx[sb];
+ j = add(j, N_NBIGGEST_PULSEARCH);
+ }
+
+ /* Similarity Search for the HF spectrum */
+ FOR(sb = 0; sb < nBands_search_fx; sb++)
+ {
+ IF(sb == 0)
+ {
+ /* copy SSmoothed LF Spectrum */
+ ptr_predBuf = y2_fx + sub(search_offset_fx[sb], shr(nlags_fx[sb], 1));
+ tmp = add(sbWidth_fx[sb], nlags_fx[sb]);
+ FOR(i = 0; i < tmp; i++)
+ {
+ low_freqsgnl_fx[i] = *ptr_predBuf++;
+ move16();
+ }
+ }
+ ELSE
+ {
+ /* copy SSmoothed LF Spectrum */
+ k = 0;
+ move16();
+ tmp = sub(search_offset_fx[sb], add(sbWidth_fx[sb], shr(nlags_fx[sb], 1)));
+ FOR(j = add(search_offset_fx[sb], shr(nlags_fx[sb], 1)); j > tmp; j--)
+ {
+ low_freqsgnl_fx[k] = y2_fx[j];
+ k = add(k, 1);
+ }
+ }
+ /* correlation b/w HF spectrum Group1 of length sbLen and decoded LF spectrum */
+ lagIndices_fx[sb] = (Word16)GetSubbandCorrIndex2_har_fx(L_yos + add(swb_lowband_fx, subband_offsets_fx[sb]),
+ sbWidth_fx[sb],
+ low_freqsgnl_fx,
+ add(sbWidth_fx[sb], nlags_fx[sb]),
+ nlags_fx[sb], Nbiggest_fx + (sb*N_NBIGGEST_PULSEARCH),
+ n_nbiggestsearch_fx[sb], &prev_frame_bstindx_fx[sb]
+ );
+ }
+
+ return;
+}
+/*--------------------------------------------------------------------------*
+ * GetSubbandCorrIndex2_pulsestep_fx()
+ *
+ *--------------------------------------------------------------------------*/
+
+static Word16 GetSubbandCorrIndex2_pulsestep_fx(
+ const Word32 *L_inBuf, /* i: original input vector (highband) */
+ const Word16 *predBuf_fx, /* i: spectrum smoothing vector */
+ const Word16 *predBufMa_fx, /* i: moving averaged spectrum smoothing vector Q=Qss */
+ const Word16 fLen, /* i: subband length of highband */
+ const Word16 maxLag, /* i: number of search pulse number */
+ const GainItem_fx *gi_fx, /* i: lag gain structure */
+ const Word16 nZero, /* i: */
+ const Word16 ssearch_buflim, /* i: length of search buffer */
+ const Word16 *predBuf_ni_fx /* i: spectrum including noise smoothing vector */
+)
+{
+ Word16 i, j;
+ Word16 absPos_fx;
+ Word16 bestIdx_fx;
+ Word32 L_lagCorr_sq;
+ Word32 L_lagEnergy;
+
+ const Word16 *ptr_predBuf;
+ const Word16 *ptr_predBuf_ni;
+
+ Word32 L_energy;
+ Word32 L_corr;
+ Word16 corr_fx;
+
+ Word32 L_corr_sq;
+
+
+ Word16 hiBuf_fx[L_FRAME32k];
+ Word16 exp_norm_hi;
+
+ Word16 exp_norm;
+ Word32 L_corr_sq_tmp;
+ Word32 L_lagCorr_sq_tmp;
+ Word16 corr_sq_fx;
+ Word16 lagCorr_sq_fx;
+ Word32 L_energy_tmp;
+ Word32 L_lagEnergy_tmp;
+ Word16 energy_fx;
+ Word16 lagEnergy_fx;
+
+ Word16 ib_flag_fx;
+
+ Word32 L_buf;
+ Word32 L_buf2;
+ Word32 L_temp;
+
+ Word16 ssBuf_fx[L_FRAME32k];
+ Word16 ssBuf_ni_fx[L_FRAME32k];
+ Word16 *ptr_ssBuf_ni_fx;
+ Word16 exp_norm_ss;
+
+ set16_fx(hiBuf_fx, 0x0, L_FRAME32k);
+ set16_fx(ssBuf_fx, 0x0, L_FRAME32k);
+
+ ib_flag_fx = 0;
+ move16();
+
+ absPos_fx = 0;
+ move16();
+ bestIdx_fx = -1;
+ move16();
+ L_lagCorr_sq = L_deposit_l(0);
+ L_lagEnergy = 0x7FFFFFFFL;
+ move32();
+
+ ptr_predBuf = predBuf_fx;
+ ptr_predBuf_ni = predBuf_ni_fx;
+
+ /* This part must be computed on parent function. */
+ exp_norm_ss = 2;
+ move16();
+
+ j = add(ssearch_buflim, fLen);
+ FOR(i = 0; i < j; i++)
+ {
+ ssBuf_fx[i] = shr(predBuf_fx[i], exp_norm_ss);
+ move16(); /* Qss+exp_norm_ss */
+ ssBuf_ni_fx[i] = shr(predBuf_ni_fx[i], exp_norm_ss);
+ move16(); /* Qss+exp_norm_ss */
+ }
+
+ L_temp = L_deposit_l(0);
+ FOR(i = 0; i < fLen; i++)
+ {
+ L_temp = L_or(L_temp, L_abs(L_inBuf[i]));
+ }
+ exp_norm_hi = norm_l(L_temp);
+ exp_norm_hi = sub(exp_norm_hi, 3); /* max 109 < 2^7 , sspectrum is sparse, it is't need 4 */
+
+ FOR(i = 0; i < fLen; i++)
+ {
+ hiBuf_fx[i] = extract_h(L_shl(L_inBuf[i], exp_norm_hi));
+ move16(); /* Qsh+exp_norm_hi-16 */
+ }
+
+ /* Get the initial energy for zero lag */
+ WHILE(*ptr_predBuf == 0 && LT_16(absPos_fx, ssearch_buflim))
+ {
+ ptr_predBuf++;
+ ptr_predBuf_ni++;
+ absPos_fx = add(absPos_fx, 1);
+ }
+
+ IF(EQ_16(absPos_fx, ssearch_buflim))
+ {
+ ptr_predBuf--;
+ ptr_predBuf_ni--;
+ absPos_fx = sub(absPos_fx, 1);
+ }
+
+ ptr_ssBuf_ni_fx = ssBuf_ni_fx + absPos_fx;
+ L_energy = L_deposit_l(0);
+ FOR(i = 0; i < fLen; i++)
+ {
+ L_energy = L_mac(L_energy, *ptr_ssBuf_ni_fx, *ptr_ssBuf_ni_fx); /* (Qss-exp_norm_ss)*2+1 */
+ ptr_ssBuf_ni_fx++;
+ ptr_predBuf_ni++;
+ }
+
+ ptr_ssBuf_ni_fx -= fLen;
+ ptr_predBuf_ni -= fLen;
+
+ L_lagEnergy = L_add(L_energy, 0);
+
+ /* Find the best lag */
+ FOR(i = 0; i < maxLag; i++)
+ {
+ L_corr = L_deposit_l(0);
+
+ /* Get the energy, remove the old and update with the new energy index */
+ L_energy = L_deposit_l(0);
+ FOR(j = 0; j < fLen; j++)
+ {
+ L_energy = L_mac(L_energy, *ptr_ssBuf_ni_fx, *ptr_ssBuf_ni_fx);
+ ptr_ssBuf_ni_fx++;
+ ptr_predBuf_ni++;
+ }
+ ptr_ssBuf_ni_fx -= fLen;
+ ptr_predBuf_ni -= fLen;
+
+ /* Get cross-correlation */
+ IF(L_energy != 0x0L)
+ {
+ L_corr = L_deposit_l(0);
+ FOR(j = 0; j < nZero; j++)
+ {
+ /*corr += inBuf[G_item[j].gainIndex]* predBufMa[G_item[j].gainIndex]; */
+ L_corr = L_mac(L_corr, hiBuf_fx[gi_fx[j].gainIndex_fx], predBufMa_fx[gi_fx[j].gainIndex_fx]); /* Qsh+Qss+1 */
+ }
+
+ /*corr_sq = corr*corr; */
+ exp_norm = norm_l(L_corr);
+ exp_norm = sub(exp_norm, 1); /* added for Overflow 0x8000 * 0x8000 -> Overflow */
+ L_corr_sq = L_shl(L_corr, exp_norm);
+ corr_fx = extract_h(L_corr_sq);
+ L_corr_sq = L_mult(corr_fx, corr_fx); /* (((Qhi:Qsh+exp_norm_hi-16)+Qss+1)+exp_norm-16)*2+1 */
+ L_corr_sq = L_shr(L_corr_sq, s_min(shl(exp_norm, 1), 31)); /* (QCorr-16)*2+1 */
+
+ /*if( (lagCorr_sq == 0.0f && corr_sq == 0.0f) || (double)lagCorr_sq*(double)energy < (double)corr_sq*(double)lagEnergy ) */
+ /*{ */
+ /* bestIdx = i; */
+ /* bestAbsPos = absPos; */
+ /* lagCorr_sq = corr_sq; */
+ /* lagCorr = corr; */
+ /* lagEnergy = energy; */
+ /*} */
+ /* normalize for L_lagCorr_sq and L_corr_sq */
+ L_buf = L_or(L_lagCorr_sq, L_corr_sq);
+ exp_norm = norm_l(L_buf); /* overflow allowed */
+ L_corr_sq_tmp = L_shl(L_corr_sq, exp_norm);
+ L_lagCorr_sq_tmp = L_shl(L_lagCorr_sq, exp_norm);
+ corr_sq_fx = extract_h(L_corr_sq_tmp);
+ lagCorr_sq_fx = extract_h(L_lagCorr_sq_tmp);
+
+ /* normalize for L_lagEnergy and L_energy */
+ L_buf = L_or(L_lagEnergy, L_energy);
+ exp_norm = norm_l(L_buf); /* overflow allowed */
+ L_energy_tmp = L_shl(L_energy, exp_norm);
+ L_lagEnergy_tmp = L_shl(L_lagEnergy, exp_norm);
+ energy_fx = extract_h(L_energy_tmp);
+ lagEnergy_fx = extract_h(L_lagEnergy_tmp);
+
+ L_buf = L_or(L_lagCorr_sq, L_corr_sq);
+ L_buf2 = L_msu(L_mult(lagCorr_sq_fx, energy_fx), corr_sq_fx, lagEnergy_fx);
+ test();
+ IF(L_buf == 0 || L_buf2 < 0)
+ {
+ bestIdx_fx = i;
+ move16();
+ L_lagCorr_sq = L_add(L_corr_sq, 0);
+ L_lagEnergy = L_add(L_energy, 0);
+ }
+ }
+ ptr_predBuf++;
+ ptr_ssBuf_ni_fx++;
+ ptr_predBuf_ni++;
+ absPos_fx++;
+
+ WHILE(*ptr_predBuf == 0 && LT_16(absPos_fx, ssearch_buflim))
+ {
+ ptr_predBuf++;
+ ptr_ssBuf_ni_fx++;
+ ptr_predBuf_ni++;
+ absPos_fx = add(absPos_fx, 1);
+ }
+
+ IF(GE_16(absPos_fx, ssearch_buflim))
+ {
+ if (EQ_16(bestIdx_fx, -1))
+ {
+ ib_flag_fx = 1;
+ move16();
+ }
+
+ BREAK;
+ }
+ }
+
+ IF(EQ_16(ib_flag_fx, 1))
+ {
+ bestIdx_fx = 0;
+ move16();
+ }
+
+ return bestIdx_fx;
+}
+/*--------------------------------------------------------------------------*
+ * GetSWBIndices_fx()
+ *
+ *--------------------------------------------------------------------------*/
+static void GetSWBIndices_fx(
+ const Word16 *predBuf_fx, /* i : low-frequency band */
+ /*const Word16 Qss,*/ /* i : Q value of predBuf_fx */
+ const Word32 *L_targetBuf, /* i : SWB MDCT coeff. */
+ const Word16 Qsh, /* i : Q value of L_targetBuf */
+ const Word16 nBands_search, /* i : number of search subbands */
+ const Word16 *sbWidth, /* i : subband lengths */
+ Word16 *lagIndices, /* o : selected lags for subband coding */
+ const Word16 predBufLen, /* i : low-frequency band length */
+ GainItem_fx *gi_fx, /* o : most representative region */
+ const Word16 *subband_offsets, /* o : N biggest components */
+ Word16 *predBuf_ni_fx /* i : low-frequency band filled noise */
+)
+{
+ Word16 j;
+ Word16 sb, tmp;
+ Word16 sbLen;
+ Word16 n_nbiggestsearch_fx[NB_SWB_SUBBANDS];
+ Word16 ssearch_buflim_fx;
+ Word16 search_offset_fx[NB_SWB_SUBBANDS];
+ Word16 nlags_fx[NB_SWB_SUBBANDS];
+
+ Word16 exp_refBuf;
+ Word16 sspectra_ma_fx[L_FRAME32k];
+
+
+ Word32 L_temp;
+
+
+ /* Initializations */
+ exp_refBuf = Qsh;
+
+ j = 0;
+ move16();
+ FOR(sb = 0; sb < nBands_search; sb++)
+ {
+ FindNBiggest2_simple_fx_har(L_targetBuf + subband_offsets[sb], exp_refBuf, gi_fx + j, sbWidth[sb], &n_nbiggestsearch_fx[sb], N_NBIGGEST_PULSEARCH);
+
+ j = add(j, N_NBIGGEST_PULSEARCH);
+ move16();
+ }
+
+ /* Selection of most representative subband (full search) */
+ FOR(sb = 0; sb < nBands_search; sb++)
+ {
+ nlags_fx[sb] = shl(1, bits_lagIndices_modeNormal[sb]);
+ move16();
+ }
+
+ FOR(sb = 0; sb < nBands_search; sb++)
+ {
+ search_offset_fx[sb] = subband_search_offsets[sb];
+ move16();
+ }
+
+ sspectra_ma_fx[0] = add(shr(predBuf_ni_fx[0], 1), shr(predBuf_ni_fx[1], 1));
+ tmp = sub(predBufLen, 1);
+ FOR(sb = 1; sb < tmp; sb++)
+ {
+ /*sspectra_ma[sb] = (predBuf[sb-1] + predBuf[sb] + predBuf[sb+1])/3.0f; */
+ L_temp = L_mult(predBuf_ni_fx[sb], 10922); /* 10922 = 0.33333 (Q15) */
+ L_temp = L_add(L_temp, L_mult(predBuf_ni_fx[sb - 1], 10922));
+ L_temp = L_add(L_temp, L_mult(predBuf_ni_fx[sb + 1], 10922)); /* Qss+15+1 */
+ sspectra_ma_fx[sb] = round_fx(L_temp);
+ }
+ sspectra_ma_fx[sb] = add(shr(predBuf_ni_fx[sb - 1], 1), shr(predBuf_ni_fx[sb], 1));
+
+ /* Partial search for rest of subbands except the last which is fixed */
+ FOR(sb = 0; sb < nBands_search; sb++)
+ {
+ sbLen = sbWidth[sb];
+ ssearch_buflim_fx = sub(predBufLen, add(sbLen, search_offset_fx[sb]));
+ lagIndices[sb] = GetSubbandCorrIndex2_pulsestep_fx(
+ L_targetBuf + subband_offsets[sb],
+ predBuf_fx + search_offset_fx[sb],
+ sspectra_ma_fx + search_offset_fx[sb],
+ sbLen, nlags_fx[sb], gi_fx + (sb*N_NBIGGEST_PULSEARCH),
+ n_nbiggestsearch_fx[sb],
+ ssearch_buflim_fx, predBuf_ni_fx + search_offset_fx[sb]);
+ }
+
+}
+/*--------------------------------------------------------------------------*
+ * gethar_noisegn_fx()
+ *
+ *--------------------------------------------------------------------------*/
+
+static void gethar_noisegn_fx(
+ BSTR_ENC_HANDLE hBstr, /* i/o: bitstream handle */
+ const Word32 L_spectra[], /* i : Qs input MDCT */
+ const Word16 QsL, /* i : Q0 Q value for L_spectra, L_xSynth_har */
+ const Word16 noise_flr_fx[], /* i : Qss noise floor */
+ const Word16 Qss, /* i : Q0 Q value for noise_flr_fx, sspectra */
+ Word32 L_xSynth_har[], /* o : Qs output SWB MDCT */
+ const Word16 sbWidth[], /* i : Q0 band width for SWB */
+ const Word16 lagIndices[], /* i : Q0 lag Indices */
+ const Word16 bands, /* i : Q0 all band number */
+ const Word16 har_bands, /* i : Q0 harmonic band number */
+ const Word16 fLenLow, /* i : Q0 low frequency band width */
+ const Word16 fLenHigh, /* i : Q0 SWB band width */
+ const Word16 subband_offsets[], /* i : Q0 offset */
+ const Word16 subband_search_offset[], /* i : Q0 offset */
+ const Word16 band_start[], /* i : Q0 band start array */
+ const Word16 band_end[], /* i : Q0 band end array */
+ const Word16 band_width[], /* i : Q0 band width */
+ Word32 L_band_energy[], /* i : Qbe band energy (Log scale) */
+ const Word16 Qbe, /* i : Q0 Q value for L_band_energy */
+ Word32 L_be_tonal[], /* o : QbeL tonal energy */
+ Word16 *QbeL, /* o : Q0 Q value for L_be_tonal */
+ const Word16 *sspectra_fx, /* i : Qss smoothed spectrum */
+ const Word16 har_freq_est2, /* i : Q0 for harmonic structure */
+ const Word16 pos_max_hfe2, /* i/o : Q0 for harmonic structure */
+ Word16 *pul_res_fx, /* o : Q0 */
+ GainItem_fx pk_sf_fx[] /* o : */
+)
+{
+ Word16 i;
+
+ Word32 L_xSynth_har_sft[L_FRAME32k];
+ Word32 L_hfspec_sft[L_FRAME32k];
+
+ Word32 L_hfspec[L_FRAME32k];
+
+ GainItem_fx get_pk_fx[N_NBIGGEST_SEARCH_LRG_B];
+ Word16 n_nbiggestsearch_fx, imin_fx, gqlevs_fx;
+
+ Word32 L_g1, L_g2;
+ Word16 exp_safe;
+ Word32 L_temp;
+
+ Word16 exp_normn, exp_normd;
+ Word16 temp_fx;
+ Word16 div_fx;
+
+ Word16 exp_norm_g1, exp_norm_g2;
+ Word16 sqrt_fx, Qsqrt;
+ Word16 g_fx;
+ Word16 exp, frac;
+
+ Word16 dmin_fx, d_fx;
+
+ Word16 temp_lo, temp_hi;
+ Word16 Qg;
+#ifdef BASOP_NOGLOB_DECLARE_LOCAL
+ Flag Overflow = 0;
+#endif
+ /*Generate HF noise*/
+ genhf_noise_fx(noise_flr_fx, Qss, L_xSynth_har, QsL, sspectra_fx, bands, har_bands, har_freq_est2, pos_max_hfe2, pul_res_fx, pk_sf_fx, fLenLow,
+ fLenHigh, sbWidth, lagIndices, subband_offsets, subband_search_offset);
+
+ Copy32(&L_spectra[fLenLow], L_hfspec, fLenHigh);
+ FindNBiggest2_simple_fx_har(L_hfspec, QsL, get_pk_fx, fLenHigh, &n_nbiggestsearch_fx, N_NBIGGEST_SEARCH_LRG_B);
+ FOR(i = 0; i < n_nbiggestsearch_fx; i++)
+ {
+ L_hfspec[get_pk_fx[i].gainIndex_fx] = 0x0;
+ move16();
+ }
+
+ L_temp = 0x0;
+ FOR(i = 0; i < fLenHigh; i++)
+ {
+ L_temp = L_or(L_temp, L_abs(L_hfspec[i]));
+ }
+ exp_norm_g1 = norm_l(L_temp);
+ FOR(i = 0; i < fLenHigh; i++)
+ {
+ L_hfspec_sft[i] = L_shl(L_hfspec[i], exp_norm_g1);
+ }
+
+ L_temp = 0x0;
+ FOR(i = 0; i < fLenHigh; i++)
+ {
+ L_temp = L_or(L_temp, L_abs(L_xSynth_har[i]));
+ }
+ exp_norm_g2 = norm_l(L_temp);
+ FOR(i = 0; i < fLenHigh; i++)
+ {
+ L_xSynth_har_sft[i] = L_shl(L_xSynth_har[i], exp_norm_g2);
+ }
+
+ exp_safe = 4;
+ move16();
+ L_g1 = L_deposit_l(0);
+ L_g2 = L_deposit_l(0);
+ FOR(i = 0; i < fLenHigh; i++)
+ {
+ temp_fx = round_fx(L_shr(L_hfspec_sft[i], exp_safe));
+ L_g1 = L_mac(L_g1, temp_fx, temp_fx); /* 4: safe shift */
+ temp_fx = round_fx(L_shr(L_xSynth_har_sft[i], exp_safe));
+ L_g2 = L_mac(L_g2, temp_fx, temp_fx); /* 4: safe shift */
+ }
+
+ /*g = (float) log10(sqrt(g1/g2));*/
+ /* Div Part */
+ exp_normn = norm_l(L_g1);
+ exp_normn = sub(exp_normn, 1);
+ exp_normd = norm_l(L_g2);
+ temp_fx = extract_h(L_shl(L_g2, exp_normd));
+ exp_normd = sub(exp_normd, 16);
+
+ imin_fx = 0;
+ move16();
+ test();
+ IF(L_g1 != 0 && temp_fx != 0x0)
+ {
+ div_fx = div_l(L_shl(L_g1, exp_normn), temp_fx);
+ /* SQRT Part */
+ sqrt_32n_16_fx(L_deposit_h(div_fx), add(add(sub(exp_normn, exp_normd), shl(sub(exp_norm_g1, exp_norm_g2), 1)), 15), &sqrt_fx, &Qsqrt); /* (exp_normn-exp_normd+(exp_norm_g1-exp_norm_g2)*2 -1)+16 */
+
+ /* Log10 Part */
+ g_fx = 0x0;
+ move16();
+ IF(sqrt_fx > 0x0)
+ {
+ L_temp = L_deposit_l(sqrt_fx);
+
+ exp = norm_l(L_temp);
+ frac = Log2_norm_lc(L_shl(L_temp, exp));
+ exp = sub(30, exp);
+ exp = sub(exp, Qsqrt);
+ L_temp = L_Comp(exp, frac);
+
+ L_temp = Mpy_32_16_1(L_temp, 19728); /* log(2)/log(10)=.30102999566398119521 = 19728.3(Q16) Q(0+16+1)=Q17 */
+#ifdef BASOP_NOGLOB
+ L_temp = L_shl_o(L_temp, 13, &Overflow); /* Q17+13=30 30-16=14 */
+ g_fx = round_fx_o(L_temp, &Overflow);
+#else
+ L_temp = L_shl(L_temp, 13); /* Q17+13=30 30-16=14 */
+ g_fx = round_fx(L_temp);
+#endif
+ }
+
+ gqlevs_fx = 4;
+ move16();
+ dmin_fx = 32767;
+ move16();
+ imin_fx = 0;
+ move16();
+
+ FOR(i = 0; i < gqlevs_fx; i++)
+ {
+ d_fx = abs_s(g_fx - gain_table_SWB_BWE_fx[i]);
+ IF(LT_16(d_fx, dmin_fx))
+ {
+ dmin_fx = d_fx;
+ move16();
+ imin_fx = i;
+ move16();
+ }
+ }
+ }
+
+ push_indice_fx(hBstr, IND_NOISEG, imin_fx, 2);
+
+ /*g=(float) pow (10.0f,gain_table[imin]);*/
+ L_temp = L_mult(gain_table_SWB_BWE_fx[imin_fx], 27213); /* Q14+Q13+1=Q28 log(10)/log(2)=3.3219 27213.23(Q13) */
+ L_temp = L_shr(L_temp, 12); /* Q28-Q12 -> Q16 */
+ temp_lo = L_Extract_lc(L_temp, &temp_hi);
+ Qg = sub(14, temp_hi);
+ g_fx = extract_l(Pow2(14, temp_lo));
+ g_fx = shl(g_fx, sub(11, Qg));
+
+ ton_ene_est_fx(
+ L_xSynth_har, QsL, L_be_tonal, QbeL, L_band_energy, Qbe,
+ band_start, band_end, band_width, fLenLow, fLenHigh, bands, har_bands, g_fx,
+ pk_sf_fx, Qss, pul_res_fx
+ );
+
+ return;
+}
+/*--------------------------------------------------------------------------*
+ * EncodeSWBSubbands()
+ *
+ * Main routine for generic SWB coding. High-frequency subband
+ * replicated based on the lowband signal. A search is perform
+ * find lowband indices denoting the selected lowband subband.
+ *--------------------------------------------------------------------------*/
+static void EncodeSWBSubbands_fx(
+ Encoder_State *st_fx, /* i/o: encoder state structure */
+ Word32 *L_spectra, /* i/o: MDCT domain spectrum */
+ Word16 QsL, /* i : Q value for L_spectra */
+ const Word16 fLenLow_fx, /* i : lowband length */
+ const Word16 fLenHigh_fx, /* i : highband length */
+ const Word16 nBands_fx, /* i : number of subbands */
+ const Word16 nBands_search_fx, /* i : number of subbands to be searched for BWE */
+ const Word16 *sbWidth_fx, /* i : subband lengths */
+ const Word16 *subband_offsets_fx, /* i : Subband offset for BWE */
+ Word16 *lagIndices_fx, /* o : lowband index for each subband */
+ const Word16 BANDS_fx, /* i : noise estimate from WB part */
+ const Word16 *band_start_fx, /* i : Number subbands/Frame */
+ const Word16 *band_end_fx, /* i : Band Start of each SB */
+ Word32 *L_band_energy, /* i : Band end of each SB, :Qbe */
+ Word16 Qbe, /* i : Q value of band energy */
+ const Word16 *p2a_flags_fx, /* i : BAnd energy of each SB */
+ const Word16 hqswb_clas_fx, /* i : lowband synthesis */
+ Word16 *prev_frm_index_fx, /* i : clas information */
+ const Word16 har_bands_fx, /* i/o: Index of the previous Frame */
+ const Word16 *subband_search_offset_fx, /* i : Number of harmonic LF bands */
+ Word16 *prev_frm_hfe2_fx, /* i/o: */
+ Word16 *prev_stab_hfe2_fx, /* i/o: */
+ const Word16 band_width_fx[], /* i : band width */
+ const Word32 L_spectra_ni[], /* i : Qs noise injected spectra */
+ Word16 *ni_seed_fx /* i/o: random seed */
+)
+{
+ Word16 i, k;
+ Word16 sspectra_fx[L_FRAME32k];
+ Word16 sspectra_ni_fx[L_FRAME32k];
+ Word16 sspectra_diff_fx[L_FRAME32k];
+ Word16 Qss; /* Q value of Smoothed Spectrum low-subband */
+ Word32 L_be_tonal[SWB_HAR_RAN1]; /* Q */
+ Word16 ss_min_fx; /* Qss */
+ Word32 L_th_g[NB_SWB_SUBBANDS];
+ Word16 QbeL;
+ GainItem_fx pk_sf_fx[(NB_SWB_SUBBANDS) * 8];
+ Word16 pul_res_fx[NB_SWB_SUBBANDS];
+
+ GainItem_fx Nbiggest_fx[NB_SWB_SUBBANDS*N_NBIGGEST_PULSEARCH];
+
+ Word32 L_xSynth_har[L_FRAME32k]; /* Qs */
+
+ Word16 lagGains_fx[NB_SWB_SUBBANDS];
+ Word16 QlagGains[NB_SWB_SUBBANDS];
+ Word16 har_freq_est1, har_freq_est2;
+ Word16 flag_dis;
+ Word16 pos_max_hfe2;
+ HQ_ENC_HANDLE hHQ_core = st_fx->hHQ_core;
+
+ har_freq_est1 = 0;
+ move16();
+ har_freq_est2 = 0;
+ move16();
+ flag_dis = 1;
+ move16();
+ pos_max_hfe2 = 0;
+ move16();
+
+ set16_fx(sspectra_fx, 0, fLenLow_fx);
+ set16_fx(sspectra_ni_fx, 0, fLenLow_fx);
+ set32_fx(L_xSynth_har, 0, L_FRAME32k);
+ set16_fx(pul_res_fx, 0, NB_SWB_SUBBANDS);
+
+
+ IF(EQ_16(hqswb_clas_fx, HQ_HARMONIC))
+ {
+ pos_max_hfe2 = har_est_fx(L_spectra, fLenLow_fx, &har_freq_est1, &har_freq_est2, &flag_dis, prev_frm_hfe2_fx, subband_search_offset_fx, sbWidth_fx, prev_stab_hfe2_fx);
+ noise_extr_corcod_fx(L_spectra, L_spectra_ni, sspectra_fx, sspectra_diff_fx, sspectra_ni_fx, fLenLow_fx, hHQ_core->prev_hqswb_clas, &hHQ_core->prev_ni_ratio_fx, &Qss);
+ /* Find best indices for each group */
+ getswbindices_har_fx(
+ L_spectra,
+ QsL, sspectra_ni_fx,
+ nBands_search_fx, lagIndices_fx, prev_frm_index_fx, fLenLow_fx, subband_offsets_fx, sbWidth_fx, subband_search_offset_fx);
+
+ /* Write the indices into the bitstream */
+ FOR(k = 0; k < nBands_search_fx; k++)
+ {
+ push_indice_fx(st_fx->hBstr, IND_LAGINDICES, lagIndices_fx[k], bits_lagIndices_mode0_Har[k]);
+ }
+
+ IF(flag_dis == 0)
+ {
+ test();
+ if (NE_16(har_freq_est2, SWB_HAR_RAN1) || NE_16(har_freq_est2, *prev_frm_hfe2_fx))
+ {
+ har_freq_est2 = add(har_freq_est2, lagIndices_fx[0]);
+ move16();
+ }
+ }
+
+ gethar_noisegn_fx(st_fx->hBstr, L_spectra, QsL, sspectra_diff_fx, Qss, L_xSynth_har,
+ sbWidth_fx, lagIndices_fx, BANDS_fx, har_bands_fx, fLenLow_fx, fLenHigh_fx,
+ subband_offsets_fx, subband_search_offset_fx, band_start_fx, band_end_fx, band_width_fx,
+ L_band_energy, Qbe, L_be_tonal, &QbeL, sspectra_fx,
+ har_freq_est2, pos_max_hfe2, pul_res_fx, pk_sf_fx);
+
+
+ Gettonl_scalfact_fx(L_xSynth_har, QsL, L_spectra_ni, fLenLow_fx, fLenHigh_fx, har_bands_fx, BANDS_fx, L_band_energy, Qbe, band_start_fx, band_end_fx,
+ p2a_flags_fx, L_be_tonal, QbeL, pk_sf_fx, Qss, pul_res_fx);
+
+ IF(flag_dis == 0)
+ {
+ *prev_frm_hfe2_fx = 0;
+ move16();
+ }
+ ELSE
+ {
+ *prev_frm_hfe2_fx = har_freq_est2;
+ move16();
+ }
+
+ FOR(k = BANDS_fx - NB_SWB_SUBBANDS; k < BANDS_fx; k++)
+ {
+ FOR(i = band_start_fx[k]; i <= band_end_fx[k]; i++)
+ {
+ L_spectra[i] = L_xSynth_har[i - fLenLow_fx];
+ move32(); /* QsL */
+ }
+ }
+ }
+ ELSE
+ {
+ ss_min_fx = spectrumsmooth_noiseton_fx(L_spectra, /*QsL,*/ L_spectra_ni, sspectra_fx, sspectra_diff_fx, sspectra_ni_fx, &Qss, fLenLow_fx, ni_seed_fx);
+
+ /* Get lag indices */
+ GetSWBIndices_fx(sspectra_fx, /*Qss,*/ L_spectra + fLenLow_fx, QsL, nBands_fx, sbWidth_fx, lagIndices_fx, fLenLow_fx,
+ Nbiggest_fx, subband_offsets_fx, sspectra_fx);
+
+ /* Bitstream operations */
+ FOR(k = 0; k < nBands_fx; k++)
+ {
+ IF(EQ_16(p2a_flags_fx[BANDS_fx - NB_SWB_SUBBANDS + k], 1))
+ {
+ lagIndices_fx[k] = 0;
+ move16();
+ lagGains_fx[k] = 0;
+ move16();
+ QlagGains[k] = 15;
+ move16();
+ }
+ ELSE
+ {
+ push_indice_fx(st_fx->hBstr, IND_LAGINDICES, lagIndices_fx[k], bits_lagIndices_modeNormal[k]);
+ }
+ }
+
+ convert_lagIndices_pls2smp_fx(lagIndices_fx, nBands_fx, lagIndices_fx, sspectra_fx, sbWidth_fx, fLenLow_fx);
+
+ GetlagGains_fx(sspectra_ni_fx, Qss, &L_band_energy[BANDS_fx - NB_SWB_SUBBANDS], Qbe, nBands_fx, sbWidth_fx, lagIndices_fx, fLenLow_fx, lagGains_fx, QlagGains);
+ FOR(k = 0; k < NB_SWB_SUBBANDS; k++)
+ {
+ lagGains_fx[k] = mult_r(lagGains_fx[k], 29491); /* lagGains[k]*0.9f; */
+ }
+
+ FOR(k = 0; k < NB_SWB_SUBBANDS; k++)
+ {
+ L_th_g[k] = L_deposit_l(0);
+ IF(p2a_flags_fx[BANDS_fx - NB_SWB_SUBBANDS + k] == 0)
+ {
+ L_th_g[k] = L_shl(L_mult(lagGains_fx[k], ss_min_fx), sub(QsL, add(add(QlagGains[k], Qss), 1))); /* QlagGain+Qss -> QsL */
+ }
+ }
+
+ GetSynthesizedSpecThinOut_fx(sspectra_ni_fx, Qss, L_xSynth_har, QsL, nBands_fx, sbWidth_fx, lagIndices_fx, lagGains_fx, QlagGains, fLenLow_fx);
+
+ /*Level adjustment for the missing bands*/
+ noiseinj_hf_fx(L_xSynth_har, QsL, L_th_g, L_band_energy, Qbe, hHQ_core->prev_En_sb_fx, p2a_flags_fx, BANDS_fx, band_start_fx, band_end_fx, fLenLow_fx, fLenHigh_fx);
+
+
+ FOR(k = BANDS_fx - NB_SWB_SUBBANDS; k < BANDS_fx; k++)
+ {
+ IF(p2a_flags_fx[k] == 0)
+ {
+ FOR(i = band_start_fx[k]; i <= band_end_fx[k]; i++)
+ {
+ L_spectra[i] = L_xSynth_har[i - fLenLow_fx];
+ move32(); /* Qob */
+ }
+ }
+ ELSE
+ {
+ FOR(i = band_start_fx[k]; i <= band_end_fx[k]; i++)
+ {
+ L_spectra[i] = L_spectra_ni[i];
+ move32();
+ }
+ }
+ }
+ }
+
+ return;
+}
+/*--------------------------------------------------------------------------*
+ * swb_bwe_enc_lr()
+ *
+ * Main encoding routine of SWB BWE for the LR MDCT core
+ *--------------------------------------------------------------------------*/
+void swb_bwe_enc_lr_fx(
+ Encoder_State *st_fx, /* i/o: encoder state structure */
+ const Word32 L_m_core[], /* i : lowband synthesis */
+ Word16 QsL, /* i : Q value */
+ const Word32 L_m_orig[], /* i/o: scaled orig signal (MDCT) */
+ Word32 L_m[], /* o : highband synthesis with lowband zeroed */
+ const Word32 L_total_brate, /* i : total bitrate for selecting subband pattern */
+ Word16 BANDS_fx, /* i : Total number of Subbands in a frame */
+ Word16 *band_start_fx, /* i : band start of each SB */
+ Word16 *band_end_fx, /* i : band end of each SB */
+ Word32 *L_band_energy, /* i : band_energy of each SB */
+ Word16 Qbe, /* i : Q value of band energy */
+ Word16 *p2a_flags_fx, /* i : HF tonal indicator */
+ const Word16 hqswb_clas_fx, /* i : HQ_NORMAL2 or HQ_HARMONIC mode */
+ Word16 lowlength_fx, /* i : lowband length */
+ Word16 highlength_fx, /* i : highband length */
+ Word16 *prev_frm_index_fx, /* i/o: previous frame lag index for harmonic mode */
+ const Word16 har_bands_fx, /* i : Number of LF harmonic bands */
+ Word16 *prev_frm_hfe2, /* i/o: */
+ Word16 *prev_stab_hfe2, /* i/o: */
+ const Word16 band_width_fx[],/* i : band_width information */
+ const Word32 L_y2_ni[], /* i : band_width information */
+ Word16 *ni_seed_fx /* i/o: random seed for search buffer NI */
+)
+{
+ Word16 k;
+ Word16 nBands_fx;
+ Word16 nBands_search_fx;
+ Word16 wBands_fx[NB_SWB_SUBBANDS];
+ Word16 lagIndices_fx[NB_SWB_SUBBANDS];
+ Word16 swb_lowband_fx, swb_highband_fx, allband_fx;
+
+ const Word16 *subband_offsets_fx;
+ const Word16 *subband_search_offset_fx;
+
+ Word32 *p_L_m;
+
+ subband_search_offset_fx = subband_search_offsets_13p2kbps_Har;
+ subband_offsets_fx = subband_offsets_sub5_13p2kbps_Har;
+
+ hf_parinitiz_fx(L_total_brate, hqswb_clas_fx, lowlength_fx, highlength_fx, wBands_fx, &subband_search_offset_fx, &subband_offsets_fx, &nBands_fx, &nBands_search_fx, &swb_lowband_fx, &swb_highband_fx);
+ allband_fx = add(swb_lowband_fx, swb_highband_fx);
+ move16();
+
+ /* Prepare m[], low part from WB core, high part from 32k input */
+ Copy32(L_m_core, L_m, swb_lowband_fx);
+ Copy32(&L_m_orig[swb_lowband_fx], &L_m[swb_lowband_fx], swb_highband_fx);
+
+ EncodeSWBSubbands_fx(
+ st_fx,
+ L_m, QsL,
+ swb_lowband_fx, swb_highband_fx, nBands_fx, nBands_search_fx, wBands_fx, subband_offsets_fx,
+ lagIndices_fx,
+ BANDS_fx, band_start_fx, band_end_fx,
+ L_band_energy, Qbe,
+ p2a_flags_fx,
+ hqswb_clas_fx, prev_frm_index_fx, har_bands_fx, subband_search_offset_fx,
+ prev_frm_hfe2, prev_stab_hfe2,
+ band_width_fx, L_y2_ni, ni_seed_fx
+ );
+
+ p_L_m = &L_m[sub(allband_fx, 1)];
+ *p_L_m = Mult_32_16(*p_L_m, 2028);
+ move32();
+ p_L_m--; /* 0.0625 = 2028 (Q15) */
+ *p_L_m = Mult_32_16(*p_L_m, 4096);
+ move32();
+ p_L_m--; /* 0.125 = 4096 (Q15) */
+ *p_L_m = Mult_32_16(*p_L_m, 8192);
+ move32();
+ p_L_m--; /* 0.25 = 8192 (Q15) */
+ *p_L_m = Mult_32_16(*p_L_m, 16384);
+ move32();
+ p_L_m--; /* 0.5 = 16384 (Q15) */
+
+ /* set low frequencies to zero */
+ FOR(k = 0; k < swb_lowband_fx; k++)
+ {
+ L_m[k] = L_deposit_l(0);
+ }
+
+ return;
+}
diff --git a/lib_enc/tns_base_enc.c b/lib_enc/tns_base_enc.c
index 37a0b10a223cd6cb2699fbad454e357b0946afaa..aaa3df2c4df0b24f0a6bc0ab773f562fd560d47e 100644
--- a/lib_enc/tns_base_enc.c
+++ b/lib_enc/tns_base_enc.c
@@ -79,7 +79,7 @@ int16_t DetectTnsFilt(
float *predictionGain /* o : TNS prediction gain */
)
{
- ResetTnsData( pTnsData );
+ ResetTnsData_flt( pTnsData );
if ( pTnsConfig->maxOrder <= 0 )
{
@@ -261,7 +261,7 @@ static void GetFilterParameters(
{
int16_t i;
float parCoeff[TNS_MAX_FILTER_ORDER];
- const float *values = tnsCoeff4;
+ const float *values = tnsCoeff4_flt;
int16_t *indexes = pTnsFilter->coefIndex;
/* Variable initialization */
@@ -308,7 +308,7 @@ static void Parcor2Index(
)
{
const int16_t nValues = 1 << TNS_COEF_RES;
- const float *values = tnsCoeff4;
+ const float *values = tnsCoeff4_flt;
int16_t i;
int16_t iIndex;
float x;
@@ -464,20 +464,20 @@ static void TnsDecision(
}
else
{
- ClearTnsFilterCoefficients( pFilter );
+ ClearTnsFilterCoefficients_flt( pFilter );
}
}
}
else if ( pTnsData->nFilters > 0 ) /* If a previous filter is turned on */
{
/* Since TNS filter of order 0 is not allowed we haved to signal in the stream filter of order 1 with the 0th coefficient equal to 0 */
- ClearTnsFilterCoefficients( pFilter );
+ ClearTnsFilterCoefficients_flt( pFilter );
pFilter->order = 1;
++pTnsData->nFilters;
}
else
{
- ClearTnsFilterCoefficients( pFilter );
+ ClearTnsFilterCoefficients_flt( pFilter );
}
}