From a49644a9ddecec6eb089fdaa4a9011452f612614 Mon Sep 17 00:00:00 2001 From: Fabian Bauer Date: Thu, 28 Aug 2025 14:50:42 +0200 Subject: [PATCH 01/32] added temporary macro and draft solution --- lib_com/options.h | 1 + lib_com/tools_fx.c | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/lib_com/options.h b/lib_com/options.h index 53d58f113..17927b239 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -77,6 +77,7 @@ #define FIX_1942_ASSERTION_LOWSHELF /* FhG: Modified the target_gains_db_fx calculation in compute_t60_coeffs_fx() */ #define FIX_1944_CRASH_FOR_STEREO /* FhG: improve TonalMDCTConceal_InsertNoise calculation precision */ #define FIX_1970_SBA_CRASH /* Dlb: Fix for issue 1970, SBA crash */ +#define FIX_maximum_exp_fx /*issue needed*/ #define FIX_1946_CRASH_JBM_PROCESSING /* FhG: Increased guard bits of DFT_fx */ /* #################### Start BASOP porting switches ############################ */ diff --git a/lib_com/tools_fx.c b/lib_com/tools_fx.c index f175f14b6..bbfbf1e36 100644 --- a/lib_com/tools_fx.c +++ b/lib_com/tools_fx.c @@ -1224,13 +1224,24 @@ Word16 maximum_exp_fx( /* o : index of the maximum value Word16 tmp, exp; ind = 0; move16(); +#ifndef FIX_maximum_exp_fx tmp = vec_fx[0]; move16(); exp = exp_vec[0]; move16(); +#endif FOR( j = 1; j < lvec_fx; j++ ) { +#ifdef FIX_maximum_exp_fx + exp = sub(norm_s( vec_fx[j] ), 1); + tmp = shl( vec_fx[j], exp ); + if( LT_16( vec_fx[ind], shr_sat( tmp, sub( exp_vec[ind], sub(exp_vec[j], exp) ) ) ) ) + { + ind = j; + move16(); + } +#else IF( LT_16( tmp, shr_sat( vec_fx[j], sub( exp, exp_vec[j] ) ) ) ) { ind = j; @@ -1240,6 +1251,7 @@ Word16 maximum_exp_fx( /* o : index of the maximum value exp = exp_vec[j]; move16(); } +#endif } return ind; -- GitLab From 01d6efd2c2cb603d6cdb8977de1d3929f7fbb0a1 Mon Sep 17 00:00:00 2001 From: Fabian Bauer Date: Thu, 28 Aug 2025 14:57:54 +0200 Subject: [PATCH 02/32] rename macro --- lib_com/options.h | 2 +- lib_com/tools_fx.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib_com/options.h b/lib_com/options.h index 17927b239..3af9ebd9e 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -77,7 +77,7 @@ #define FIX_1942_ASSERTION_LOWSHELF /* FhG: Modified the target_gains_db_fx calculation in compute_t60_coeffs_fx() */ #define FIX_1944_CRASH_FOR_STEREO /* FhG: improve TonalMDCTConceal_InsertNoise calculation precision */ #define FIX_1970_SBA_CRASH /* Dlb: Fix for issue 1970, SBA crash */ -#define FIX_maximum_exp_fx /*issue needed*/ +#define FIX_1981_MAXIMUM_EXP_FX /* FhG: Fix bug in function to find maximum value in vector */ #define FIX_1946_CRASH_JBM_PROCESSING /* FhG: Increased guard bits of DFT_fx */ /* #################### Start BASOP porting switches ############################ */ diff --git a/lib_com/tools_fx.c b/lib_com/tools_fx.c index bbfbf1e36..8eec2dddb 100644 --- a/lib_com/tools_fx.c +++ b/lib_com/tools_fx.c @@ -1224,7 +1224,7 @@ Word16 maximum_exp_fx( /* o : index of the maximum value Word16 tmp, exp; ind = 0; move16(); -#ifndef FIX_maximum_exp_fx +#ifndef FIX_1981_MAXIMUM_EXP_FX tmp = vec_fx[0]; move16(); exp = exp_vec[0]; @@ -1233,7 +1233,7 @@ Word16 maximum_exp_fx( /* o : index of the maximum value FOR( j = 1; j < lvec_fx; j++ ) { -#ifdef FIX_maximum_exp_fx +#ifdef FIX_1981_MAXIMUM_EXP_FX exp = sub(norm_s( vec_fx[j] ), 1); tmp = shl( vec_fx[j], exp ); if( LT_16( vec_fx[ind], shr_sat( tmp, sub( exp_vec[ind], sub(exp_vec[j], exp) ) ) ) ) -- GitLab From 236ae528df2c2d8b1df0f87c06a833df04154278 Mon Sep 17 00:00:00 2001 From: Fabian Bauer Date: Thu, 28 Aug 2025 15:08:51 +0200 Subject: [PATCH 03/32] make it even faster --- lib_com/options.h | 2 +- lib_com/tools_fx.c | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/lib_com/options.h b/lib_com/options.h index 3af9ebd9e..95d342158 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -77,7 +77,7 @@ #define FIX_1942_ASSERTION_LOWSHELF /* FhG: Modified the target_gains_db_fx calculation in compute_t60_coeffs_fx() */ #define FIX_1944_CRASH_FOR_STEREO /* FhG: improve TonalMDCTConceal_InsertNoise calculation precision */ #define FIX_1970_SBA_CRASH /* Dlb: Fix for issue 1970, SBA crash */ -#define FIX_1981_MAXIMUM_EXP_FX /* FhG: Fix bug in function to find maximum value in vector */ +//#define FIX_1981_MAXIMUM_EXP_FX /* FhG: Fix bug in function to find maximum value in vector */ #define FIX_1946_CRASH_JBM_PROCESSING /* FhG: Increased guard bits of DFT_fx */ /* #################### Start BASOP porting switches ############################ */ diff --git a/lib_com/tools_fx.c b/lib_com/tools_fx.c index 8eec2dddb..6bfa9ca23 100644 --- a/lib_com/tools_fx.c +++ b/lib_com/tools_fx.c @@ -1221,22 +1221,23 @@ Word16 maximum_exp_fx( /* o : index of the maximum value ) { Word16 j, ind; +#ifndef FIX_1981_MAXIMUM_EXP_FX Word16 tmp, exp; ind = 0; move16(); -#ifndef FIX_1981_MAXIMUM_EXP_FX tmp = vec_fx[0]; move16(); exp = exp_vec[0]; move16(); +#else + ind = 0; + move16(); #endif FOR( j = 1; j < lvec_fx; j++ ) { #ifdef FIX_1981_MAXIMUM_EXP_FX - exp = sub(norm_s( vec_fx[j] ), 1); - tmp = shl( vec_fx[j], exp ); - if( LT_16( vec_fx[ind], shr_sat( tmp, sub( exp_vec[ind], sub(exp_vec[j], exp) ) ) ) ) + if( LE_16( vec_fx[ind], shr_sat( vec_fx[j], sub( exp_vec[ind], exp_vec[j] ) ) ) ) { ind = j; move16(); -- GitLab From e1bc28157a3ef599bc486051087153df0fc6714a Mon Sep 17 00:00:00 2001 From: Fabian Bauer Date: Thu, 28 Aug 2025 15:09:20 +0200 Subject: [PATCH 04/32] insert assert to find critical bitstreams --- lib_com/tools_fx.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib_com/tools_fx.c b/lib_com/tools_fx.c index 6bfa9ca23..953d8ec1b 100644 --- a/lib_com/tools_fx.c +++ b/lib_com/tools_fx.c @@ -1243,6 +1243,9 @@ Word16 maximum_exp_fx( /* o : index of the maximum value move16(); } #else + // insert assert to find critical bitstreams + assert( tmp != 0x7FFFFFFF ); + IF( LT_16( tmp, shr_sat( vec_fx[j], sub( exp, exp_vec[j] ) ) ) ) { ind = j; -- GitLab From 6d4c24b2912c48c379df332e834afd09e1f280fb Mon Sep 17 00:00:00 2001 From: Fabian Bauer Date: Thu, 28 Aug 2025 15:15:19 +0200 Subject: [PATCH 05/32] clang patch --- lib_com/tools_fx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib_com/tools_fx.c b/lib_com/tools_fx.c index 953d8ec1b..7222f2ed7 100644 --- a/lib_com/tools_fx.c +++ b/lib_com/tools_fx.c @@ -1237,7 +1237,7 @@ Word16 maximum_exp_fx( /* o : index of the maximum value FOR( j = 1; j < lvec_fx; j++ ) { #ifdef FIX_1981_MAXIMUM_EXP_FX - if( LE_16( vec_fx[ind], shr_sat( vec_fx[j], sub( exp_vec[ind], exp_vec[j] ) ) ) ) + if ( LE_16( vec_fx[ind], shr_sat( vec_fx[j], sub( exp_vec[ind], exp_vec[j] ) ) ) ) { ind = j; move16(); -- GitLab From 3fe52332792f2bc33887333c8a2754e6058dc6d8 Mon Sep 17 00:00:00 2001 From: Fabian Bauer Date: Thu, 28 Aug 2025 15:40:44 +0200 Subject: [PATCH 06/32] fix warning --- lib_com/tools_fx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib_com/tools_fx.c b/lib_com/tools_fx.c index 7222f2ed7..ab20dd44d 100644 --- a/lib_com/tools_fx.c +++ b/lib_com/tools_fx.c @@ -1244,7 +1244,7 @@ Word16 maximum_exp_fx( /* o : index of the maximum value } #else // insert assert to find critical bitstreams - assert( tmp != 0x7FFFFFFF ); + assert( tmp != (Word16)0x7FFF ); IF( LT_16( tmp, shr_sat( vec_fx[j], sub( exp, exp_vec[j] ) ) ) ) { -- GitLab From e7cfff8df3b95bd95c7331083b86db18280d4734 Mon Sep 17 00:00:00 2001 From: Fabian Bauer Date: Thu, 28 Aug 2025 15:46:52 +0200 Subject: [PATCH 07/32] clang patch --- lib_com/tools_fx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib_com/tools_fx.c b/lib_com/tools_fx.c index ab20dd44d..45a737506 100644 --- a/lib_com/tools_fx.c +++ b/lib_com/tools_fx.c @@ -1244,7 +1244,7 @@ Word16 maximum_exp_fx( /* o : index of the maximum value } #else // insert assert to find critical bitstreams - assert( tmp != (Word16)0x7FFF ); + assert( tmp != (Word16) 0x7FFF ); IF( LT_16( tmp, shr_sat( vec_fx[j], sub( exp, exp_vec[j] ) ) ) ) { -- GitLab From b4147e2da566eea8b04937261922c85772787704 Mon Sep 17 00:00:00 2001 From: Fabian Bauer Date: Tue, 2 Sep 2025 09:52:43 +0200 Subject: [PATCH 08/32] more specific assert --- lib_com/tools_fx.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/lib_com/tools_fx.c b/lib_com/tools_fx.c index 45a737506..ac22df9da 100644 --- a/lib_com/tools_fx.c +++ b/lib_com/tools_fx.c @@ -1244,7 +1244,16 @@ Word16 maximum_exp_fx( /* o : index of the maximum value } #else // insert assert to find critical bitstreams - assert( tmp != (Word16) 0x7FFF ); + { + Word16 tmp16, tmp16_1; + Word32 tmp32, tmp32_1; + tmp16 = tmp; + tmp32 = L_deposit_l( tmp ); + tmp16_1 = shr_sat( vec_fx[j], sub( exp, exp_vec[j] ) ); + tmp32_1 = L_shr_sat( L_deposit_l(vec_fx[j]), sub( exp, exp_vec[j] ) ); + + assert( LT_16( tmp16, tmp16_1 ) == LT_32( tmp32, tmp32_1 ) ); + } IF( LT_16( tmp, shr_sat( vec_fx[j], sub( exp, exp_vec[j] ) ) ) ) { -- GitLab From 7dd58feef28094467090e569be964cf6c9ea7ebf Mon Sep 17 00:00:00 2001 From: Fabian Bauer Date: Tue, 2 Sep 2025 10:19:44 +0200 Subject: [PATCH 09/32] clang patch --- lib_com/tools_fx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib_com/tools_fx.c b/lib_com/tools_fx.c index ac22df9da..ac23a58ce 100644 --- a/lib_com/tools_fx.c +++ b/lib_com/tools_fx.c @@ -1250,7 +1250,7 @@ Word16 maximum_exp_fx( /* o : index of the maximum value tmp16 = tmp; tmp32 = L_deposit_l( tmp ); tmp16_1 = shr_sat( vec_fx[j], sub( exp, exp_vec[j] ) ); - tmp32_1 = L_shr_sat( L_deposit_l(vec_fx[j]), sub( exp, exp_vec[j] ) ); + tmp32_1 = L_shr_sat( L_deposit_l( vec_fx[j] ), sub( exp, exp_vec[j] ) ); assert( LT_16( tmp16, tmp16_1 ) == LT_32( tmp32, tmp32_1 ) ); } -- GitLab From 470a1b45b5dd69e9a7efed2a9545f7342179f3d5 Mon Sep 17 00:00:00 2001 From: Fabian Bauer Date: Tue, 2 Sep 2025 15:50:01 +0200 Subject: [PATCH 10/32] activate macro --- lib_com/options.h | 2 +- lib_com/tools_fx.c | 40 ++++++++++++++++++++++++++++++++++++---- 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/lib_com/options.h b/lib_com/options.h index 42376280b..908053bb2 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -78,7 +78,7 @@ #define FIX_1944_CRASH_FOR_STEREO /* FhG: improve TonalMDCTConceal_InsertNoise calculation precision */ #define FIX_1970_SBA_CRASH /* Dlb: Fix for issue 1970, SBA crash */ #define FIX_1978_SAT_MISSING_IN_GAIN_ENC /* VA: Fix add saturation missing that lead to a crash in P800-10 */ -//#define FIX_1981_MAXIMUM_EXP_FX /* FhG: Fix bug in function to find maximum value in vector */ +#define FIX_1981_MAXIMUM_EXP_FX /* FhG: Fix bug in function to find maximum value in vector */ #define FIX_1979_SAT_MISSING_IN_LSF_ENC /* VA: Proposal to fix 1979, saturation in lsf_enc, NOkia to review */ #define FIX_1946_CRASH_JBM_PROCESSING /* FhG: Increased guard bits of DFT_fx */ diff --git a/lib_com/tools_fx.c b/lib_com/tools_fx.c index ac23a58ce..00979865a 100644 --- a/lib_com/tools_fx.c +++ b/lib_com/tools_fx.c @@ -1230,21 +1230,44 @@ Word16 maximum_exp_fx( /* o : index of the maximum value exp = exp_vec[0]; move16(); #else + Word16 tmp, exp, scale; ind = 0; move16(); #endif +#if 0 + + float vec_float[1024]; + for ( int ii = 0; ii < lvec_fx; ii++ ) + vec_float[ii] = vec_fx[ii] * pow( 2, exp_vec[ii] - 31 ); + +#endif + + +#ifdef FIX_1981_MAXIMUM_EXP_FX + scale = sub( norm_s( vec_fx[ind] ), 1 ); + FOR( j = 1; j < lvec_fx; j++ ) { -#ifdef FIX_1981_MAXIMUM_EXP_FX - if ( LE_16( vec_fx[ind], shr_sat( vec_fx[j], sub( exp_vec[ind], exp_vec[j] ) ) ) ) + + IF( LT_16( tmp, shr_sat( vec_fx[j], sub( exp, exp_vec[j] ) ) ) ) { ind = j; move16(); + + scale = sub( norm_s( vec_fx[ind] ), 1 ); + tmp = shl(vec_fx[j], scale); + exp = sub( exp_vec[j], scale ); } + } #else + FOR( j = 1; j < lvec_fx; j++ ) + { +#if 0 // insert assert to find critical bitstreams { + static int calls = 0; + calls++; Word16 tmp16, tmp16_1; Word32 tmp32, tmp32_1; tmp16 = tmp; @@ -1252,8 +1275,14 @@ Word16 maximum_exp_fx( /* o : index of the maximum value tmp16_1 = shr_sat( vec_fx[j], sub( exp, exp_vec[j] ) ); tmp32_1 = L_shr_sat( L_deposit_l( vec_fx[j] ), sub( exp, exp_vec[j] ) ); - assert( LT_16( tmp16, tmp16_1 ) == LT_32( tmp32, tmp32_1 ) ); + if ( ( LT_16( tmp16, tmp16_1 ) != LT_32( tmp32, tmp32_1 ) ) ) + { + tmp16 = LT_16( tmp16, tmp16_1 ); + tmp32 = LT_32( tmp32, tmp32_1 ); + assert( tmp16 == tmp32 ); + } } +#endif IF( LT_16( tmp, shr_sat( vec_fx[j], sub( exp, exp_vec[j] ) ) ) ) { @@ -1264,8 +1293,11 @@ Word16 maximum_exp_fx( /* o : index of the maximum value exp = exp_vec[j]; move16(); } -#endif } +#endif +#if 0 /*value out*/ + printf( "\n val= %15.15f", vec_fx[ind] * pow(2,exp_vec[ind] - 15) ); +#endif return ind; } -- GitLab From cda13bd6e191c35d7767078c03b621e92933528a Mon Sep 17 00:00:00 2001 From: Fabian Bauer Date: Tue, 2 Sep 2025 16:00:37 +0200 Subject: [PATCH 11/32] clang patch --- lib_com/tools_fx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib_com/tools_fx.c b/lib_com/tools_fx.c index 00979865a..87dd3b886 100644 --- a/lib_com/tools_fx.c +++ b/lib_com/tools_fx.c @@ -1256,7 +1256,7 @@ Word16 maximum_exp_fx( /* o : index of the maximum value move16(); scale = sub( norm_s( vec_fx[ind] ), 1 ); - tmp = shl(vec_fx[j], scale); + tmp = shl( vec_fx[j], scale ); exp = sub( exp_vec[j], scale ); } } -- GitLab From 7b4c1f4c3c3cf9896cb78065bc1cae5be58c0a18 Mon Sep 17 00:00:00 2001 From: Fabian Bauer Date: Wed, 3 Sep 2025 09:32:37 +0200 Subject: [PATCH 12/32] new fix --- .../tools_fx.c | 5026 +++++++++++++++++ .../ba9e794e4af04046f8293c8af70d4da/options.h | 102 + .../pitch_ol_fx.c | 2475 ++++++++ lib_com/options.h | 2 + lib_com/tools_fx.c | 13 +- lib_enc/pitch_ol_fx.c | 13 + 6 files changed, 7626 insertions(+), 5 deletions(-) create mode 100644 Workspace_msvc/enc_temp_folder/75f9146d81645fb7408b2c8c144cfa7/tools_fx.c create mode 100644 Workspace_msvc/enc_temp_folder/ba9e794e4af04046f8293c8af70d4da/options.h create mode 100644 Workspace_msvc/enc_temp_folder/d76ccfdc3b9fa9da476bcd2a44fe879/pitch_ol_fx.c diff --git a/Workspace_msvc/enc_temp_folder/75f9146d81645fb7408b2c8c144cfa7/tools_fx.c b/Workspace_msvc/enc_temp_folder/75f9146d81645fb7408b2c8c144cfa7/tools_fx.c new file mode 100644 index 000000000..15e2631e2 --- /dev/null +++ b/Workspace_msvc/enc_temp_folder/75f9146d81645fb7408b2c8c144cfa7/tools_fx.c @@ -0,0 +1,5026 @@ +/****************************************************************************************************** + + (C) 2022-2025 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 +#include +#include "options.h" +#include "stl.h" +#include +#include "cnst.h" +#include "prot_fx.h" +#include "basop_util.h" +#include "basop32.h" +#include "wmc_auto.h" +#include "prot_fx_enc.h" +#include "ivas_prot_fx.h" + +#define INV_BANDS10 3277 /* 1/10 in Q15 */ +#define INV_BANDS9 3641 /* 1/9 in Q15 */ +#define INV_BANDS3 10923 /* 1/9 in Q15 */ +const Word16 b_hp400_fx[3] = { 3660, -7320, 3660 }; /* Q12 (/4) */ +const Word16 a_hp400_fx[3] = { 16384, 29280, -14160 }; +const Word16 a_hp400_ivas_fx[3] = { 4096, 7320, -3540 }; /*Q12*/ + +#define WMC_TOOL_SKIP + +// conversion functions: +Word32 float_to_fix( float number, Word32 Q ) +{ + assert( Q >= 0 ); + if ( number == 1.0f && Q == Q31 ) + { + return ONE_IN_Q31; + } + if ( isnan( number ) ) + { + number = 0; + } + assert( fabs( number ) < pow( 2, 31 - Q ) ); + Word32 ret = (Word32) ( number * ( (UWord32) 1 << Q ) ); + return ret; +} + +float fix_to_float( Word32 number, Word32 Q ) +{ + assert( Q >= 0 ); + float ret = (float) number / ( (UWord32) 1 << Q ); + return ret; +} + +Word16 float_to_fix16( float number, Word16 Q ) +{ + assert( Q >= 0 ); + IF( isnan( number ) ) + return 0; + if ( number == 1.0f && Q == Q15 ) + return MAX16B; + if ( number == -1.0f && Q == Q15 ) + return MIN16B; + assert( fabs( number ) < pow( 2, 15 - Q ) ); + Word16 ret = (Word16) ( number * ( (UWord16) 1 << Q ) ); + return ret; +} + +Word16 float_to_fix16_thrld( float number, Word16 Q ) +{ + assert( Q >= 0 ); + if ( number == 1.0f && Q == Q15 ) + return MAX16B; + float limit = (float) pow( 2, 15 - Q ); + /*Add threshold*/ + if ( number > MAX16B_FLT ) + { + number = MAX16B_FLT; + } + else if ( number < MIN16B_FLT ) + { + number = MIN16B_FLT; + } + assert( number <= limit && number >= -limit ); + Word16 ret = (Word16) ( number * ( (UWord16) 1 << Q ) ); + return ret; +} + +float fix16_to_float( Word16 number, Word16 Q ) +{ + assert( Q >= 0 ); + float ret = (float) number / ( (UWord16) 1 << Q ); + return ret; +} + +// Float to 32-bit Mantissa and Exponent +void f2me( float n, Word32 *mantissa, Word16 *expo ) +{ + Word32 e; + float mf = (float) frexp( n, &e ); + *expo = (Word16) e; + *mantissa = float_to_fix( mf, Q31 ); +} + +// 32-bit Mantissa and Exponent to Float +float me2f( Word32 m, Word16 expo ) +{ + float mf = fix_to_float( m, Q31 ); + return (float) ldexp( mf, expo ); +} + +// Float buffer to 32-bit mantissa buffer and common exponent. +void f2me_buf( const float *x, Word32 *m, Word16 *e, const Word32 n ) +{ + Word16 max_e = -32, tmp_e; + Word32 i; + + for ( i = 0; i < n; i++ ) + { + f2me( x[i], &m[i], &tmp_e ); + max_e = ( max_e > tmp_e ) ? max_e : tmp_e; + } + + for ( i = 0; i < n; i++ ) + { + f2me( x[i], &m[i], &tmp_e ); + m[i] = L_shr( m[i], max_e - tmp_e ); + } + + *e = max_e; +} + +// 32-bit Mantissa buffer and exponent into float buffer. +void me2f_buf( const Word32 *m, const Word16 e, float *out, const Word32 n ) +{ + for ( int i = 0; i < n; i++ ) + { + out[i] = me2f( m[i], e ); + } +} + +// Float to 16-bit Mantissa and Exponent +void f2me_16( float n, Word16 *mantissa, Word16 *expo ) +{ + Word32 e; + float mf = (float) frexp( n, &e ); + *expo = (Word16) e; + *mantissa = float_to_fix16( mf, 15 ); +} + +// 16-bit Mantissa and Exponent to Float +float me2f_16( Word16 m, Word16 expo ) +{ + float mf = fix16_to_float( m, 15 ); + return (float) ldexp( mf, expo ); +} + +// Float buffer to 16-bit mantissa buffer and common exponent. +void f2me_buf_16( const float *x, Word16 *m, Word16 *e, const Word32 n ) +{ + Word16 max_e = -16, tmp_e; + Word32 i; + + for ( i = 0; i < n; i++ ) + { + f2me_16( x[i], &m[i], &tmp_e ); + max_e = ( max_e > tmp_e ) ? max_e : tmp_e; + } + + for ( i = 0; i < n; i++ ) + { + f2me_16( x[i], &m[i], &tmp_e ); + m[i] = shr( m[i], max_e - tmp_e ); + } + + *e = max_e; +} + +// 16-bit Mantissa buffer and exponent into float buffer. +void me2f_buf_16( const Word16 *m, const Word16 e, float *out, const Word32 n ) +{ + for ( int i = 0; i < n; i++ ) + { + out[i] = me2f_16( m[i], e ); + } +} +void f2fix( float *var_flt, Word32 *var_fix, Word32 expo ) +{ + *var_fix = (Word32) ( *var_flt * pow( 2, 31 - expo ) ); +} + +void fix2f( Word32 *var_fix, float *var_flt, Word32 expo ) +{ + float mf = fix_to_float( *var_fix, 31 ); + *var_flt = (float) ldexp( mf, expo ); +} + +void f2fix_16( float *var_flt, Word16 *var_fix, Word32 expo ) +{ + *var_fix = (Word16) ( *var_flt * pow( 2, 15 - expo ) ); +} + +void fix2f_16( Word16 *var_fix, float *var_flt, Word32 expo ) +{ + float mf = fix16_to_float( *var_fix, 15 ); + *var_flt = (float) ldexp( mf, expo ); +} + +#undef WMC_TOOL_SKIP + +/*-------------------------------------------------------------------* + * usdequant_fx() + * + * Uniform scalar de-quantizer routine + * + * Applies de-quantization based on scale and round operations. + *-------------------------------------------------------------------*/ +Word16 usdequant_fx( /* Qx*/ + const Word16 idx, /* i: quantizer index Q0*/ + const Word16 qlow, /* i: lowest codebook entry (index 0) Qx*/ + const Word16 delta /* i: quantization step Qx-1*/ +) +{ + Word16 g; + Word32 L_tmp; + + /*g = idx * delta + qlow;*/ + L_tmp = L_deposit_l( qlow ); /*Qx */ + L_tmp = L_mac( L_tmp, idx, delta ); /*Qx */ + g = round_fx_sat( L_shl_sat( L_tmp, 16 ) ); /*Qx */ + return ( g ); +} + +Word32 usdequant32_fx( /* Qx*/ + const Word16 idx, /* i: quantizer index Q0*/ + const Word32 qlow, /* i: lowest codebook entry (index 0) Qx*/ + const Word32 delta /* i: quantization step Qx-1*/ +) +{ + Word32 g; + Word64 L_tmp; + + /*g = idx * delta + qlow;*/ + L_tmp = W_deposit32_l( qlow ); /*Qx */ + L_tmp = W_mac_32_16( L_tmp, delta, idx ); + IF( GE_64( L_tmp, MAX_32 ) ) + { + g = MAX_32; + move32(); + } + ELSE + { + g = W_extract_l( L_tmp ); /*Qx */ + } + return ( g ); +} + +/*-------------------------------------------------------------------* + * usquant() + * + * Uniform scalar quantizer according to MMSE criterion + * (nearest neighbour in Euclidean space) + * + * Applies quantization based on scale and round operations. + * Index of the winning codeword and the winning codeword itself are returned. + *-------------------------------------------------------------------*/ +Word16 usquant_fx( /* o: index of the winning codeword */ + const Word16 x, /* i: scalar value to quantize Qx*/ + Word16 *xq, /* o: quantized value Qx*/ + const Word16 qlow, /* i: lowest codebook entry (index 0) Qx*/ + const Word16 delta, /* i: quantization step Qx-1*/ + const Word16 cbsize /* i: codebook size */ +) +{ + Word16 idx; + Word16 tmp, exp; + Word32 L_tmp; +#ifndef ISSUE_1836_replace_overflow_libcom +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move32(); +#endif +#endif + + /* idx = (short)( (x - qlow)/delta + 0.5f); */ + exp = norm_s( delta ); + tmp = div_s( shl( 1, sub( 14, exp ) ), delta ); /*Q(29-exp-(Qx-1))->Q(30-exp-Qx) */ +#ifdef ISSUE_1836_replace_overflow_libcom + L_tmp = L_mult( sub_sat( x, qlow ), tmp ); /*Q(31-exp) */ + idx = extract_l( L_shr_r( L_add( L_tmp, shl_sat( 1, sub( 30, exp ) ) ), sub( 31, exp ) ) ); /*Q0 */ +#else + L_tmp = L_mult( sub_o( x, qlow, &Overflow ), tmp ); /*Q(31-exp) */ + idx = extract_l( L_shr_r( L_add( L_tmp, shl_o( 1, sub( 30, exp ), &Overflow ) ), sub( 31, exp ) ) ); /*Q0 */ +#endif + + idx = s_min( idx, sub( cbsize, 1 ) ); + idx = s_max( idx, 0 ); + + /* *xq = idx*delta + qlow; */ + L_tmp = L_deposit_l( qlow ); /*Qx */ + L_tmp = L_mac( L_tmp, idx, delta ); /*Qx */ +#ifdef ISSUE_1836_replace_overflow_libcom + *xq = round_fx_sat( L_shl_sat( L_tmp, 16 ) ); /*Qx */ +#else + *xq = round_fx_o( L_shl_o( L_tmp, 16, &Overflow ), &Overflow ); /*Qx */ +#endif + return idx; +} +/*-------------------------------------------------------------------* + * Dot_product: + * + * Compute scalar product of using accumulator. + * Performs no normalization, as opposed to Dot_product12() + *-------------------------------------------------------------------*/ +Word32 Dot_product( /* o : Sum */ + const Word16 x[], /* i : 12bits: x vector */ + const Word16 y[], /* i : 12bits: y vector */ + const Word16 lg /* i : vector length */ +) +{ + Word16 i; + Word32 L_sum; + Word64 L64_sum; + + L64_sum = 1; + move64(); + FOR( i = 0; i < lg; i++ ) + { + L64_sum = W_mac_16_16( L64_sum, x[i], y[i] ); + } + L_sum = W_sat_l( L64_sum ); + return L_sum; +} +/*---------------------------------------------------------------------* + * dotp_fx() + * + * Dot product of vector x[] and vector y[] + *---------------------------------------------------------------------*/ + +Word32 dotp_fx( /* o : dot product of x[] and y[] */ + const Word16 x[], /* i : vector x[] */ + const Word16 y[], /* i : vector y[] */ + const Word16 n, /* i : vector length */ + Word16 *exp /* (o) : exponent of result (0..+30) */ +) +{ + Word16 sft; + Word32 L_sum; + + assert( *exp == 0 ); + + L_sum = L_add( L_shr( Dot_product( x, y, n ), 1 ), 1 ); + + /* Normalize acc in Q31 */ + + sft = norm_l( L_sum ); + L_sum = L_shl( L_sum, sft ); + + *exp = sub( 30, sft ); + move16(); /* exponent = 0..30 */ + + return L_sum; +} + +Word32 sum2_fx( /* o : sum of all squared vector elements Q(2x+1)*/ + const Word16 *vec, /* i : input vector Qx*/ + const Word16 lvec /* i : length of input vector */ +) +{ + Word16 i; + Word32 L_tmp; +#ifndef ISSUE_1836_replace_overflow_libcom +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move32(); +#endif +#endif + L_tmp = L_deposit_l( 0 ); + FOR( i = 0; i < lvec; i++ ) + { +#ifdef ISSUE_1836_replace_overflow_libcom + L_tmp = L_mac_sat( L_tmp, vec[i], vec[i] ); /*Q(2x+1) */ +#else + L_tmp = L_mac_o( L_tmp, vec[i], vec[i], &Overflow ); /*Q(2x+1) */ +#endif + } + + return L_tmp; +} + +Word64 sum2_fx_no_sat( /* o : sum of all squared vector elements Q(2*Qx)*/ + const Word16 *vec, /* i : input vector Qx*/ + const Word16 lvec /* i : length of input vector */ +) +{ + Word16 i; + Word64 sum; + + sum = 0; + move64(); + FOR( i = 0; i < lvec; i++ ) + { + sum = W_mac0_16_16( sum, vec[i], vec[i] ); // 2*Qx + } + + return sum; +} + +Word32 sum_32_fx( + const Word32 *vec, /* i : input vector */ + const Word16 lvec, /* i : length of input vector */ + Word16 *e ) +{ + Word16 i, shift; + Word64 tmp = 0; + move64(); + Word32 ans; + + FOR( i = 0; i < lvec; i++ ) + { + tmp = W_add( tmp, vec[i] ); // e + } + shift = W_norm( tmp ); + tmp = W_shl( tmp, shift ); // shift + (31 - e) + ans = W_extract_h( tmp ); // shift + (31 - e) - 32 + *e = add( sub( *e, shift ), 32 ); + move16(); + + return ans; +} + +Word32 sum2_fx_mod( /* o : sum of all squared vector elements Q(2x+1 -5)*/ + const Word16 *vec, /* i : input vector Qx*/ + const Word16 lvec /* i : length of input vector */ +) +{ + Word16 i; + Word32 L_tmp; +#ifndef ISSUE_1836_replace_overflow_libcom +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move32(); +#endif +#endif + + L_tmp = L_deposit_l( 0 ); + FOR( i = 0; i < lvec; i++ ) + { +#ifdef ISSUE_1836_replace_overflow_libcom + L_tmp = L_add_sat( L_tmp, L_shr( L_mult_sat( vec[i], vec[i] ), 9 ) ); +#else + L_tmp = L_add_o( L_tmp, L_shr( L_mult_o( vec[i], vec[i], &Overflow ), 9 ), &Overflow ); +#endif + } + + return L_tmp; +} +/*-------------------------------------------------------------------* + * Copy: + * + * Copy vector x[] to y[] + * + *-------------------------------------------------------------------*/ +void Copy( + const Word16 x[], /* i : input vector */ + Word16 y[], /* o : output vector */ + const Word16 L /* i : vector length */ +) +{ + Word16 i; + + IF( y < x ) + { + FOR( i = 0; i < L; i++ ) + { + y[i] = x[i]; + move16(); + } + + /* Location of x and y may differ depending on platform/memory allocation. Since IF and ELSE has different complexity count, the early return is used instead of ELSE to ensure the same complexity number regardless of x and y memory addresses. */ + return; + } + + FOR( i = L - 1; i >= 0; i-- ) + { + y[i] = x[i]; + move16(); + } + + return; +} +/*-------------------------------------------------------------------* + * Copy64: + * + * Copy vector x[] to y[] (64 bits) + *-------------------------------------------------------------------*/ +void Copy64( + const Word64 x[], /* i : input vector */ + Word64 y[], /* o : output vector */ + const Word16 L /* i : vector length */ +) +{ + Word16 i; + IF( y < x ) + { + FOR( i = 0; i < L; i++ ) + { + y[i] = x[i]; + move64(); + } + + /* Location of x and y may differ depending on platform/memory allocation. Since IF and ELSE has different complexity count, the early return is used instead of ELSE to ensure the same complexity number regardless of x and y memory addresses. */ + return; + } + + FOR( i = L - 1; i >= 0; i-- ) + { + y[i] = x[i]; + move64(); + } + + return; +} + +void set64_fx( + Word64 y[], /* i/o: Vector to set */ + const Word64 a, /* i : Value to set the vector to */ + const Word16 N /* i : Lenght of the vector */ +) +{ + Word16 i; + FOR( i = 0; i < N; i++ ) + { + y[i] = a; + move64(); + } + + return; +} + +void Copy_pword( + const PWord16 x[], /* i : input vector */ + PWord16 y[], /* o : output vector */ + const Word16 L /* i : vector length */ +) +{ + Word16 i; + + IF( y < x ) + { + FOR( i = 0; i < L; i++ ) + { + y[i].v.im = x[i].v.im; + y[i].v.re = x[i].v.re; + move16(); + move16(); + } + + /* Location of x and y may differ depending on platform/memory allocation. Since IF and ELSE has different complexity count, the early return is used instead of ELSE to ensure the same complexity number regardless of x and y memory addresses. */ + return; + } + + FOR( i = L - 1; i >= 0; i-- ) + { + y[i].v.im = x[i].v.im; + y[i].v.re = x[i].v.re; + move16(); + move16(); + } + + return; +} +/*-------------------------------------------------------------------* + * Copy32: + * + * Copy vector x[] to y[] (32 bits) + *-------------------------------------------------------------------*/ +void Copy32( + const Word32 x[], /* i : input vector */ + Word32 y[], /* o : output vector */ + const Word16 L /* i : vector length */ +) +{ + Word16 i; + IF( y < x ) + { + FOR( i = 0; i < L; i++ ) + { + y[i] = x[i]; + move32(); + } + + return; + } + + FOR( i = L - 1; i >= 0; i-- ) + { + y[i] = x[i]; + move32(); + } +} + +void set8_fx( + Word8 y[], /* i/o: Vector to set */ + const Word8 a, /* i : Value to set the vector to */ + const Word16 N /* i : Lenght of the vector */ +) +{ + Word16 i; + + FOR( i = 0; i < N; i++ ) + { + y[i] = a; + move16(); + } + + return; +} + +/*-------------------------------------------------------------------* + * set16_fx() + * set32_fx() + * + * Set the vector elements to a value + *-------------------------------------------------------------------*/ +void set16_fx( + Word16 y[], /* i/o: Vector to set */ + const Word16 a, /* i : Value to set the vector to */ + const Word16 N /* i : Lenght of the vector */ +) +{ + Word16 i; + + FOR( i = 0; i < N; i++ ) + { + y[i] = a; + move16(); + } + + return; +} + +void set32_fx( + Word32 y[], /* i/o: Vector to set */ + const Word32 a, /* i : Value to set the vector to */ + const Word16 N /* i : Lenght of the vector */ +) +{ + Word16 i; + + FOR( i = 0; i < N; i++ ) + { + y[i] = a; + move32(); + } + + return; +} +/*-------------------------------------------------------------------* + * Copy_Scale_sig + * + * Up/down scale a 16 bits vector x and move it into y + *-------------------------------------------------------------------*/ +void Copy_Scale_sig( + const Word16 x[], /* i : signal to scale input Qx */ + Word16 y[], /* o : scaled signal output Qx */ + const Word16 lg, /* i : size of x[] Q0 */ + const Word16 exp0 /* i : exponent: x = round(x << exp) Qx ?exp */ +) +{ + Word16 i; + Word16 tmp; +#ifndef ISSUE_1836_replace_overflow_libcom +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move32(); +#endif +#endif + IF( exp0 == 0 ) + { + FOR( i = 0; i < lg; i++ ) + { + y[i] = x[i]; + move16(); + } + return; + } + IF( exp0 < 0 ) + { + tmp = shl( -32768, exp0 ); /* we use negative to correctly represent 1.0 */ + FOR( i = 0; i < lg; i++ ) + { + y[i] = msu_r( 0, x[i], tmp ); + move16(); + } + return; + } + FOR( i = 0; i < lg; i++ ) + { +#ifdef ISSUE_1836_replace_overflow_libcom + y[i] = shl_sat( x[i], exp0 ); +#else + y[i] = shl_o( x[i], exp0, &Overflow ); +#endif + move16(); /* saturation can occur here */ + } +} +/*-------------------------------------------------------------------* + * Copy_Scale_sig + * + * Up/down scale a 16 bits vector x and move it into y + *-------------------------------------------------------------------*/ +void Copy_Scale_sig_16_32_DEPREC( + const Word16 x[], /* i : signal to scale input Qx */ + Word32 y[], /* o : scaled signal output Qx */ + const Word16 lg, /* i : size of x[] Q0 */ + const Word16 exp0 /* i : exponent: x = round(x << exp) Qx ?exp */ +) +{ + Word16 i; + Word16 tmp; +#ifndef ISSUE_1836_replace_overflow_libcom +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move32(); +#endif +#endif + + + IF( exp0 == 0 ) + { + FOR( i = 0; i < lg; i++ ) + { + y[i] = L_deposit_l( x[i] ); + move32(); + } + return; + } + IF( exp0 < 0 ) + { + /*Should not happen */ + FOR( i = 0; i < lg; i++ ) + { +#ifdef ISSUE_1836_replace_overflow_libcom + y[i] = L_deposit_l( shl_sat( x[i], exp0 ) ); +#else + y[i] = L_deposit_l( shl_o( x[i], exp0, &Overflow ) ); +#endif + move32(); + } + return; + } +#ifdef DEBUGGING + if ( exp0 >= 16 ) + { + printf( "Issue in Copy_Scale_sig_16_32_DEPREC\n" ); + } +#else + assert( exp0 < 16 ); +#endif +#ifdef ISSUE_1836_replace_overflow_libcom + tmp = shl_sat( 1, exp0 ); +#else + tmp = shl_o( 1, exp0, &Overflow ); +#endif + FOR( i = 0; i < lg; i++ ) + { + y[i] = L_mult0( x[i], tmp ); + move32(); /* saturation can occur here */ + } +} + +void Copy_Scale_sig_16_32_no_sat( + const Word16 x[], /* i : signal to scale input Qx */ + Word32 y[], /* o : scaled signal output Qx */ + const Word16 lg, /* i : size of x[] Q0 */ + const Word16 exp0 /* i : exponent: x = round(x << exp) Qx ?exp */ +) +{ + Word16 i; + Word32 L_tmp; +#ifndef ISSUE_1836_replace_overflow_libcom +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move32(); +#endif +#endif + + + IF( exp0 == 0 ) + { + FOR( i = 0; i < lg; i++ ) + { + y[i] = L_deposit_l( x[i] ); + move32(); + } + return; + } + IF( exp0 < 0 ) + { + /*Should not happen */ + FOR( i = 0; i < lg; i++ ) + { +#ifdef ISSUE_1836_replace_overflow_libcom + y[i] = L_deposit_l( shl_sat( x[i], exp0 ) ); +#else + y[i] = L_deposit_l( shl_o( x[i], exp0, &Overflow ) ); +#endif + move32(); + } + return; + } +#ifdef ISSUE_1836_replace_overflow_libcom + L_tmp = L_shl_sat( 1, exp0 - 1 ); +#else + L_tmp = L_shl_o( 1, exp0 - 1, &Overflow ); +#endif + + IF( L_tmp >= 0x7FFF ) + { + FOR( i = 0; i < lg; i++ ) + { + // y[i] = L_mult0(x[i], L_tmp); + y[i] = W_extract_l( W_mult_32_16( L_tmp, x[i] ) ); + move32(); /* Overflow can occur here */ + } + return; + } + // ELSE + { + Word16 tmp = extract_l( L_tmp ); + FOR( i = 0; i < lg; i++ ) + { + y[i] = L_mult( x[i], tmp ); + move32(); + } + } +} + +void Copy_Scale_sig_32_16( + const Word32 x[], /* i : signal to scale input Qx */ + Word16 y[], /* o : scaled signal output Qx */ + const Word16 lg, /* i : size of x[] Q0 */ + const Word16 exp0 /* i : exponent: x = round(x << exp) Qx ?exp */ +) +{ + Word16 i; + Word16 tmp; +#ifndef ISSUE_1836_replace_overflow_libcom +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move32(); +#endif +#endif + + tmp = add( 16, exp0 ); + IF( tmp != 0 ) + { + FOR( i = 0; i < lg; i++ ) + { +#ifdef ISSUE_1836_replace_overflow_libcom + y[i] = round_fx_sat( L_shl_sat( x[i], tmp ) ); +#else + y[i] = round_fx_o( L_shl_o( x[i], tmp, &Overflow ), &Overflow ); +#endif + move16(); + } + } + ELSE + { + FOR( i = 0; i < lg; i++ ) + { +#ifdef ISSUE_1836_replace_overflow_libcom + y[i] = round_fx_sat( x[i] ); +#else + y[i] = round_fx_o( x[i], &Overflow ); +#endif + move16(); + } + } +} + +/*-------------------------------------------------------------------* + * Scale_sig32 + * + * Up/down scale a 32 bits vector + *-------------------------------------------------------------------*/ +void Scale_sig32( + Word32 x[], /* i/o: signal to scale Qx */ + const Word16 lg, /* i : size of x[] Q0 */ + const Word16 exp0 /* i : exponent: x = round(x << exp) Qx ?exp */ +) +{ + Word16 i; +#ifndef ISSUE_1836_replace_overflow_libcom +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move32(); +#endif +#endif + IF( 0 == exp0 ) + { + return; + } + + FOR( i = 0; i < lg; i++ ) + { +#ifdef ISSUE_1836_replace_overflow_libcom + x[i] = L_shl_sat( x[i], exp0 ); +#else + x[i] = L_shl_o( x[i], exp0, &Overflow ); +#endif + move32(); /* saturation can occur here */ + } +} + +/*------------------------------------------------------------------* + * function Random_Fill + * + * Signed 16 bits random generator. + * (Avoids Store of Seed to Memory for 'n' Random Values and + * Combines Scaling Operation.) + *------------------------------------------------------------------*/ +void Random_Fill( + Word16 *seed, /* i/o: random seed */ + Word16 n, /* i : number of values */ + Word16 *y, /* o : output values */ + Word16 scaling /* i : scaling of values */ +) +{ + Word16 i; + Word16 local_seed; + + local_seed = *seed; + move16(); + FOR( i = 0; i < n; i++ ) + { + local_seed = extract_l( L_mac0( 13849L, local_seed, 31821 ) ); + *y++ = shr( local_seed, scaling ); + move16(); + } + *seed = local_seed; + move16(); +} +/*-------------------------------------------------------------------* + * Scale_sig + * Up/down scale a 16 bits vector + *-------------------------------------------------------------------*/ +void Scale_sig( + Word16 x[], /* i/o: signal to scale Qx */ + const Word16 lg, /* i : size of x[] Q0 */ + const Word16 exp0 /* i : exponent: x = round(x << exp) Qx ?exp */ +) +{ + Word16 i; + Word16 tmp; + + IF( exp0 > 0 ) + { + FOR( i = 0; i < lg; i++ ) + { + x[i] = shl_sat( x[i], exp0 ); + move16(); /* saturation can occur here */ + } + return; + } + IF( exp0 < 0 ) + { + tmp = shl_sat( -32768, exp0 ); /* we use negative to correctly represent 1.0 */ + FOR( i = 0; i < lg; i++ ) + { + x[i] = msu_r_sat( 0, x[i], tmp ); + move16(); /* msu instead of mac because factor is negative */ + } + return; + } +} + +/*-------------------------------------------------------------------* + * scale_sig + * Up/down scale a 16 bits vector + *-------------------------------------------------------------------*/ +void scale_sig( + Word16 x[], /* i/o: signal to scale Qx */ + const Word16 lg, /* i : size of x[] Q0 */ + const Word16 exp0 /* i : exponent: x = round(x << exp) Qx exp */ +) +{ + Word16 i; + + IF( exp0 != 0 ) + { + FOR( i = 0; i < lg; i++ ) + { + x[i] = shl( x[i], exp0 ); + move16(); + } + } +} + +/*---------------------------------------------------------------------* + * mean_fx() + * + *---------------------------------------------------------------------*/ +Word16 mean_fx( /* o : mean of vector */ + const Word16 *vec_fx, /* i : input vector */ + const Word16 lvec_fx /* i : length of input vector */ +) +{ + Word16 tmp; + // PMT("TBV : this function could be written differently to minimize the risk of saturation"); + tmp = sum16_fx( vec_fx, lvec_fx ); + tmp = mult_r( tmp, div_s( 1, lvec_fx ) ); + + return tmp; +} + +Word16 mean_no_sat_fx( /* o : mean of vector Qx */ + const Word16 *vec_fx, /* i : input vector Qx */ + const Word16 lvec_fx /* i : length of input vector */ +) +{ + Word16 i; + Word32 L_tmp = 0; + move32(); + FOR( i = 0; i < lvec_fx; ++i ) + { + L_tmp = L_add( L_tmp, vec_fx[i] ); + } + L_tmp = Mpy_32_16_1( L_tmp, div_s( 1, lvec_fx ) ); /* Qx */ + + return extract_l( L_tmp ); +} +Word32 mean_no_sat_Word32_fx( /* o : mean of vector Qx */ + const Word32 *vec_fx, /* i : input vector Qx */ + const Word16 lvec_fx, /* i : length of input vector */ + const Word16 gb ) +{ + Word16 i; + Word32 L_tmp = 0; + move32(); + FOR( i = 0; i < lvec_fx; ++i ) + { + L_tmp = L_add( L_tmp, L_shr( vec_fx[i], gb ) ); + } + L_tmp = Mpy_32_16_1( L_tmp, div_s( 1, lvec_fx ) ); /* Qx-gb */ + + return L_tmp; +} +/*-------------------------------------------------------------------* + * Vr_add + * + * Add two Word16 vectors together integer by integer + *-------------------------------------------------------------------*/ +void Vr_add( + const Word16 *in1, /* i : Input vector 1 */ + const Word16 *in2, /* i : Input vector 2 */ + Word16 *out, /* o : Output vector that contains vector 1 + vector 2 */ + Word16 Len /* i : Vector lenght */ +) +{ + Word16 i; + + FOR( i = 0; i < Len; i++ ) + { + out[i] = add_sat( in1[i], in2[i] ); + move16(); + } +} + +void sort_fx( + Word16 *r, /* i/o: Vector to be sorted in place */ + Word16 lo, /* i : Low limit of sorting range */ + Word16 up /* I : High limit of sorting range */ +) +{ + Word16 i, j, i1; + Word16 tempr; + + FOR( i = sub( up, 1 ); i >= lo; i-- ) + { + i1 = add( i, 1 ); + tempr = r[i]; + move16(); + move16(); /*supplementary move for the j-1 PTR initialization*/ + FOR( j = i1; j <= up; j++ ) + { + IF( LE_16( tempr, r[j] ) ) + { + BREAK; + } + + r[j - 1] = r[j]; + move16(); + } + r[j - 1] = tempr; + move16(); + } +} + +void sort_32_fx( + Word32 *r, /* i/o: Vector to be sorted in place */ + const Word16 lo, /* i : Low limit of sorting range */ + const Word16 up /* I : High limit of sorting range */ +) +{ + Word16 i, j; + Word32 tempr; + FOR( i = sub( up, 1 ); i >= lo; i-- ) + { + tempr = r[i]; + move32(); + FOR( j = add( i, 1 ); j <= up; j++ ) + { + IF( LE_32( tempr, r[j] ) ) + { + BREAK; + } + r[j - 1] = r[j]; + move32(); + } + + r[j - 1] = tempr; + move32(); + } + + return; +} + +Word16 minimum_fx( /* o : index of the minimum value in the input vector */ + const Word16 *vec_fx, /* i : input vector */ + const Word16 lvec_fx, /* i : length of input vector */ + Word16 *min_fx /* o : minimum value in the input vector */ +) +{ + Word16 j, ind; + Word16 tmp; + ind = 0; + move16(); + tmp = vec_fx[0]; + move16(); + + FOR( j = 1; j < lvec_fx; j++ ) + { + if ( LT_16( vec_fx[j], tmp ) ) + { + ind = j; + move16(); + /*tmp = vec_fx[j]; move16(); */ + } + tmp = s_min( tmp, vec_fx[j] ); + } + + *min_fx = tmp; + move16(); + + return ind; +} + +Word16 maximum_fx( /* o : index of the maximum value in the input vector */ + const Word16 *vec_fx, /* i : input vector */ + const Word16 lvec_fx, /* i : length of input vector */ + Word16 *max_fx /* o : maximum value in the input vector */ +) +{ + Word16 j, ind; + Word16 tmp; + ind = 0; + move16(); + tmp = vec_fx[0]; + move16(); + + FOR( j = 1; j < lvec_fx; j++ ) + { + if ( GT_16( vec_fx[j], tmp ) ) + { + ind = j; + move16(); + } + tmp = s_max( tmp, vec_fx[j] ); + } + *max_fx = tmp; + move16(); + + return ind; +} + +Word16 maximum_exp_fx( /* o : index of the maximum value in the input vector */ + const Word16 *vec_fx, /* i : input vector */ + const Word16 *exp_vec, /* i : exponents of input vector */ + const Word16 lvec_fx /* i : length of input vector */ +) +{ + Word16 j, ind; +#ifndef FIX_1981_MAXIMUM_EXP_FX + Word16 tmp, exp; + ind = 0; + move16(); + tmp = vec_fx[0]; + move16(); + exp = exp_vec[0]; + move16(); +#else + Word16 tmp, exp, scale; + ind = 0; + move16(); +#endif + +#if 0 + + float vec_float[1024]; + for ( int ii = 0; ii < lvec_fx; ii++ ) + vec_float[ii] = vec_fx[ii] * pow( 2, exp_vec[ii] - 31 ); + +#endif + + +#ifdef FIX_1981_MAXIMUM_EXP_FX + scale = sub( norm_s( vec_fx[ind] ), 1 ); + + FOR( j = 1; j < lvec_fx; j++ ) + { + + IF( LT_16( tmp, shr_sat( vec_fx[j], sub( exp, exp_vec[j] ) ) ) ) + { + ind = j; + move16(); + + scale = sub( norm_s( vec_fx[ind] ), 1 ); + tmp = shl( vec_fx[j], scale ); + exp = sub( exp_vec[j], scale ); + } + } +#else + FOR( j = 1; j < lvec_fx; j++ ) + { +#if 0 + // insert assert to find critical bitstreams + { + static int calls = 0; + calls++; + Word16 tmp16, tmp16_1; + Word32 tmp32, tmp32_1; + tmp16 = tmp; + tmp32 = L_deposit_l( tmp ); + + tmp16_1 = shr_sat( vec_fx[j] , sub( exp, exp_vec[j] ) ); + tmp32_1 = L_shr_sat( L_deposit_l( vec_fx[j] ), sub( exp, exp_vec[j] ) ); + + if ( ( LT_16( tmp16, tmp16_1 ) != LT_32( tmp32, tmp32_1 ) ) ) + { + tmp16 = LT_16( tmp16, tmp16_1 ); + tmp32 = LT_32( tmp32, tmp32_1 ); + assert( tmp16 == tmp32 ); + } + } +#endif + + IF( LT_16( tmp, shr_sat( vec_fx[j], sub( exp, exp_vec[j] ) ) ) ) + { + ind = j; + move16(); + tmp = vec_fx[j]; + move16(); + exp = exp_vec[j]; + move16(); + } + } +#endif +#if 1 /*value out*/ + printf( "\n val= %15.15f", (float)vec_fx[ind] * pow(2,exp_vec[ind] - 15) ); +#endif + + return ind; +} + +/*---------------------------------------------------------------------* + * maximum_abs_16_fx() + * + * Find index and value of the absolute maximum in a vector + *---------------------------------------------------------------------*/ + +Word16 maximum_abs_16_fx( /* o : index of the maximum abs value in the input vector */ + const Word16 *vec, /* i : input vector */ + const Word16 lvec, /* i : length of input vector */ + Word16 *max_val /* o : maximum value in the input vector */ +) +{ + Word16 j, ind; + Word16 tmp; + ind = 0; + move16(); + tmp = abs_s( vec[0] ); + + FOR( j = 1; j < lvec; j++ ) + { + if ( GT_16( abs_s( vec[j] ), tmp ) ) + { + ind = j; + move16(); + } + tmp = s_max( tmp, abs_s( vec[j] ) ); + } + *max_val = tmp; + move16(); + + return ind; +} + +/*---------------------------------------------------------------------* + * minimum_abs32_fx() + * + * Find index and value of the absolute minimum in a vector + *---------------------------------------------------------------------*/ +Word16 minimum_abs32_fx( /* o : index of the minimum value in the input vector */ + const Word32 *vec_fx, /* i : input vector */ + const Word16 lvec_fx, /* i : length of input vector */ + Word32 *min_fx /* o : minimum value in the input vector */ +) +{ + Word16 j, ind; + Word32 tmp; + ind = 0; + move16(); + tmp = vec_fx[0]; + move16(); + + FOR( j = 1; j < lvec_fx; j++ ) + { + IF( LT_32( L_abs( vec_fx[j] ), tmp ) ) + { + ind = j; + move16(); + /*tmp = vec_fx[j]; move16(); */ + } + tmp = L_min( tmp, L_abs( vec_fx[j] ) ); + } + + *min_fx = tmp; + move16(); + + return ind; +} + +/*---------------------------------------------------------------------* + * minimum_32_fx() + * + * Find index and value of the minimum in a vector + *---------------------------------------------------------------------*/ + +Word16 minimum_32_fx( /* o : index of the minimum value in the input vector */ + const Word32 *vec_fx, /* i : input vector */ + const Word16 lvec_fx, /* i : length of input vector */ + Word32 *min_fx /* o : minimum value in the input vector */ +) +{ + Word16 j, ind; + Word32 tmp; + ind = 0; + move16(); + tmp = vec_fx[0]; + move16(); + + FOR( j = 1; j < lvec_fx; j++ ) + { + if ( LT_32( vec_fx[j], tmp ) ) + { + ind = j; + move16(); + /*tmp = vec_fx[j]; move32(); */ + } + tmp = L_min( tmp, vec_fx[j] ); + } + if ( min_fx != NULL ) + { + *min_fx = tmp; + } + move32(); + + return ind; +} + +/*---------------------------------------------------------------------* + * maximum_32_fx() + * + * Find index and value of the maximum in a vector + *---------------------------------------------------------------------*/ + +Word16 maximum_32_fx( /* o : index of the maximum value in the input vector */ + const Word32 *vec, /* i : input vector */ + const Word16 lvec, /* i : length of input vector */ + Word32 *max_val /* o : maximum value in the input vector */ +) +{ + Word16 j, ind; + Word32 tmp; + ind = 0; + move16(); + tmp = vec[0]; + move16(); + + FOR( j = 1; j < lvec; j++ ) + { + IF( GT_32( vec[j], tmp ) ) + { + ind = j; + move16(); + } + tmp = L_max( tmp, vec[j] ); + } + if ( max_val != NULL ) + { + *max_val = tmp; + } + move32(); + + return ind; +} + +Word16 maximum_abs_32_fx( /* o : index of the maximum abs value in the input vector */ + const Word32 *vec, /* i : input vector */ + const Word16 lvec, /* i : length of input vector */ + Word32 *max_val /* o : maximum value in the input vector */ +) +{ + Word16 j, ind; + Word32 tmp; + ind = 0; + move16(); + tmp = L_abs( vec[0] ); + + FOR( j = 1; j < lvec; j++ ) + { + if ( GT_32( L_abs( vec[j] ), tmp ) ) + { + ind = j; + move16(); + } + tmp = L_max( tmp, L_abs( vec[j] ) ); + } + *max_val = tmp; + move32(); + + return ind; +} + + +/*---------------------------------------------------------------- + *Function: + *Finds number of shifts to normalize a 16-bit array variable. + *Return value + *Number of shifts + *----------------------------------------------------------------*/ +Word16 Exp16Array( + const Word16 n, /* (i): Array size */ + const Word16 *sx /* (i): Data array */ +) +{ + Word16 k; + Word16 exp; + Word16 sMax; + Word16 sAbs; + + sMax = abs_s( sx[0] ); + move16(); + + FOR( k = 1; k < n; k++ ) + { + sAbs = abs_s( sx[k] ); + sMax = s_max( sMax, sAbs ); + } + + exp = norm_s( sMax ); + return exp; +} + +Word16 Exp32Array( + const Word16 n, /* (i): Array size */ + const Word32 *sx /* (i): Data array */ +) +{ + Word16 k; + Word16 exp; + Word32 L_Max; + Word32 L_Abs; + + L_Max = L_abs( sx[0] ); + FOR( k = 1; k < n; k++ ) + { + L_Abs = L_abs( sx[k] ); + L_Max = L_max( L_Max, L_Abs ); + } + exp = norm_l( L_Max ); + + if ( L_Max == 0 ) + { + exp = 31; + move16(); + } + return exp; +} + +Word32 sum16_32_fx( /* o : sum of all vector elements Qx*/ + const Word16 *vec, /* i : input vector Qx*/ + const Word16 lvec /* i : length of input vector */ +) +{ + Word16 i; + Word32 tmp, L_var; + tmp = 0; + move16(); + FOR( i = 0; i < lvec; i++ ) + { + L_var = L_deposit_l( vec[i] ); + tmp = L_add( tmp, L_var ); /*Qx */ + } + + return tmp; +} + +Word32 sum32_sat( /* o : sum of all vector elements Qx*/ + const Word32 *vec, /* i : input vector Qx*/ + const Word16 lvec /* i : length of input vector */ +) +{ + Word16 i; + Word32 tmp; + tmp = 0; + move16(); + FOR( i = 0; i < lvec; i++ ) + { + tmp = L_add_sat( tmp, vec[i] ); /*Qx */ + } + + return tmp; +} + +Word32 var_fx_32( /* o: variance of vector Qx+16*/ + const Word16 *x, /* i: input vector Qx*/ + const Word16 Qx, + const Word16 len /* i: length of inputvector */ +) +{ + Word16 m; + Word32 v; + Word16 i; + Word16 tmp, exp, inv_len; + Word32 L_tmp; + + + L_tmp = L_add( x[0], 0 ); + FOR( i = 1; i < len; i++ ) + { + L_tmp = L_add( L_tmp, x[i] ); /*Qx */ + } + exp = norm_s( len ); + inv_len = div_s( shl( 1, sub( 14, exp ) ), len ); /*Q(29-exp) */ + L_tmp = Mult_32_16( L_tmp, inv_len ); /*Q(14-exp+Qx) */ + m = round_fx( L_shl( L_tmp, add( exp, 2 ) ) ); /*Qx */ + + v = L_deposit_l( 0 ); + FOR( i = 0; i < len; i++ ) + { + tmp = sub( x[i], m ); /*Qx */ + v = L_mac0_sat( v, tmp, tmp ); /*(Qx+Qx) */ + } + L_tmp = Mult_32_16( v, inv_len ); /*Q(14-exp+Qx+Qx) */ + v = L_shl( L_tmp, add( exp, sub( 2, Qx ) ) ); /*Qx+16 */ + + return v; +} + +Word32 var_fx_32in_32out( /* o: variance of vector Qx*/ + const Word32 *x, /* i: input vector Qx*/ + Word16 *Qx, /*i/o:Q for input/output */ + const Word16 len, /* i: length of inputvector */ + const Word16 gb ) +{ + Word16 i; + Word16 shift; + Word32 L_tmp1, L_tmp; + Word64 W_temp; + + L_tmp = mean_no_sat_Word32_fx( x, len, gb ); /*Qx-gb */ + W_temp = 0; + FOR( i = 0; i < len; i++ ) + { + L_tmp1 = L_sub( L_shr( x[i], gb ), L_tmp ); /*Qx-gb */ + W_temp = W_add( W_temp, W_mult0_32_32( L_tmp1, L_tmp1 ) ); /*Qx-gb +Qx-gb*/ + } + shift = W_norm( W_temp ); + L_tmp = Mult_32_16( W_extract_h( W_shl( W_temp, shift ) ), div_s( 1, len ) ); /*Q2*(Qx-gb)+shift -32 */ + + *Qx = sub( add( shl( sub( *Qx, gb ), 1 ), shift ), 32 ); + move16(); + return L_tmp; +} +/*-------------------------------------------------------------------* + * conv() + * + * Convolution between vectors x[] and h[] written to y[] + * All vectors are of length L. Only the first L samples of the + * convolution are considered. + *-------------------------------------------------------------------*/ + +Flag conv_fx( + const Word16 x[], /* i : input vector Q_new*/ + const Word16 h[], /* i : impulse response (or second input vector) Q(15)*/ + Word16 y[], /* o : output vetor (result of convolution) 12 bits*/ + const Word16 L /* i : vector size */ +) +{ + + Word16 i, n; + Word32 L_sum; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move32(); +#endif + y[0] = mult_r( x[0], h[0] ); + move16(); + FOR( n = 1; n < L; n++ ) + { + L_sum = L_mult( x[0], h[n] ); + FOR( i = 1; i < n; i++ ) + { + L_sum = L_mac_o( L_sum, x[i], h[n - i], &Overflow ); + } + y[n] = mac_ro( L_sum, x[i], h[0], &Overflow ); + move16(); + } + return Overflow; +} + +/*-------------------------------------------------------------------* + * conv_fx_32() + * + * Convolution between vectors x[] and h[] written to y[] + * All vectors are of length L. Only the first L samples of the + * convolution are considered. + *-------------------------------------------------------------------*/ +Flag conv_fx_32( + const Word16 x[], /* i : input vector Q_new*/ + const Word16 h[], /* i : impulse response (or second input vector) Q(15)*/ + Word32 y[], /* o : output vetor (result of convolution) 12 bits*/ + const Word16 L /* i : vector size */ +) +{ + + Word16 i, n; + Word32 L_sum; + Flag Overflow = 0; + y[0] = L_mult( x[0], h[0] ); + move32(); + FOR( n = 1; n < L; n++ ) + { + L_sum = L_mult( x[0], h[n] ); + FOR( i = 1; i < n; i++ ) + { + L_sum = L_mac_o( L_sum, x[i], h[n - i], &Overflow ); + } + y[n] = L_mac_o( L_sum, x[i], h[0], &Overflow ); + move32(); + } + return Overflow; +} +Word16 var_fx( /* o: variance of vector Qx*/ + const Word16 *x, /* i: input vector Qx*/ + const Word16 Qx, + const Word16 len /* i: length of inputvector */ +) +{ + Word16 m; + Word32 v; + Word16 v_16; + Word16 i; + Word16 tmp, exp, inv_len; + Word32 L_tmp; + + L_tmp = x[0]; + move32(); + FOR( i = 1; i < len; i++ ) + { + L_tmp = L_add( L_tmp, x[i] ); /*Qx */ + } + exp = norm_s( len ); + inv_len = div_s( shl( 1, sub( 14, exp ) ), len ); /*Q(29-exp) */ + L_tmp = Mult_32_16( L_tmp, inv_len ); /*Q(14-exp+Qx) */ + m = round_fx( L_shl( L_tmp, add( exp, 2 ) ) ); /*Qx */ + + v = L_deposit_l( 0 ); + FOR( i = 0; i < len; i++ ) + { + tmp = sub_sat( x[i], m ); /*Qx */ + v = L_mac0_sat( v, tmp, tmp ); /*(Qx+Qx) */ + } + L_tmp = Mult_32_16( v, inv_len ); /*Q(14-exp+Qx+Qx) */ + v_16 = round_fx_sat( L_shl_sat( L_tmp, add( exp, sub( 2, Qx ) ) ) ); /*Qx */ + + return v_16; +} + +/*---------------------------------------------------------------------* + * std_fx() + * + * Calculate the standard deviation of a vector + *---------------------------------------------------------------------*/ + +Word16 std_fx( /* o: standard deviation */ + const Word16 x[], /* i: input vector */ + const Word16 len /* i: length of the input vector */ +) +{ + Word16 i; + Word32 L_tmp; + Word16 exp1, exp2, tmp; + Word32 stdev; + + stdev = 0; + move16(); + FOR( i = 0; i < len; i++ ) + { + L_tmp = L_mult( x[i], x[i] ); /*29 */ + stdev = L_add( stdev, L_shr( L_tmp, 3 ) ); /*26 */ + } + + IF( stdev != 0 ) + { + exp1 = norm_l( stdev ); + tmp = div_s( 16384, extract_h( L_shl( stdev, exp1 ) ) ); /*15 + 14 - (26 + exp1 - 16) */ + L_tmp = L_mult( tmp, len ); /*15 + 14 - (26 + exp1 - 16) + 1 */ + exp2 = norm_l( L_tmp ); + exp1 = add( sub( exp1, exp2 ), 11 ); + stdev = Isqrt_lc( L_shl( L_tmp, exp2 ), &exp1 ); /*31-exp1 */ + stdev = L_shl( stdev, sub( exp1, 1 ) ); /*30 */ + } + + + return extract_h( stdev ); +} + +Word32 dot_product_mat_fx( /* o : the dot product x'*A*x */ + const Word16 *x, /* i : vector x Q15 */ + const Word32 *A, /* i : matrix A Q0*/ + const Word16 m /* i : vector & matrix size */ + +) +{ + Word16 i, j; + Word64 tmp_sum_64; + Word32 suma, tmp_sum; + const Word32 *pt_A; + const Word16 *pt_x; + + pt_A = A; + suma = L_deposit_l( 0 ); + + FOR( i = 0; i < m; i++ ) + { + tmp_sum_64 = 0; + move64(); + pt_x = x; + FOR( j = 0; j < m; j++ ) + { + tmp_sum_64 = W_mac_32_16( tmp_sum_64, *pt_A, *pt_x ); /*Q0 */ + pt_A++; + pt_x++; + } + tmp_sum = W_sat_m( tmp_sum_64 ); + suma = Madd_32_16( suma, tmp_sum, x[i] ); /*Q0 */ + } + return suma; +} +/*-------------------------------------------------------------------* + * Vr_subt + * + * Subtract two Word16 vectors integer by integer + *-------------------------------------------------------------------*/ +void Vr_subt( + const Word16 x1[], /* i : Input vector 1 */ + const Word16 x2[], /* i : Input vector 2 */ + Word16 y[], /* o : Output vector that contains vector 1 - vector 2 */ + Word16 N /* i : Vector lenght */ +) +{ + Word16 i; + + FOR( i = 0; i < N; i++ ) + { + y[i] = sub_sat( x1[i], x2[i] ); + move16(); + } +} +/*-------------------------------------------------------------------* + * vquant() + * + * Vector quantizer according to MMSE criterion (nearest neighbour in Euclidean space) + * + * Searches a given codebook to find the nearest neighbour in Euclidean space. + * Index of the winning codevector and the winning vector itself are returned. + *-------------------------------------------------------------------*/ +Word16 vquant_ivas_fx( /* o: index of the winning codevector */ + Word32 x[], /* i: vector to quantize Q25 */ + const Word32 x_mean[], /* i: vector mean to subtract (0 if none) Q25 */ + Word32 xq[], /* o: quantized vector Q25 */ + const Word32 cb[], /* i: codebook Q25 */ + const Word16 dim, /* i: dimension of codebook vectors */ + const Word16 cbsize /* i: codebook size */ +) +{ + Word16 c, d, idx, j; + Word32 L_dist, L_tmp, L_mindist; + + idx = 0; + move16(); + L_mindist = MAX_32; + move32(); + IF( x_mean != 0 ) + { + FOR( d = 0; d < dim; d++ ) + { + /*x[d] -= x_mean[d]; */ + x[d] = L_sub( x[d], x_mean[d] ); + move32(); /*Qx */ + } + } + j = 0; + move16(); + FOR( c = 0; c < cbsize; c++ ) + { + L_dist = 0; + move32(); + + FOR( d = 0; d < dim; d++ ) + { + /*tmp = x[d] - cb[j++];*/ + L_tmp = L_sub( x[d], cb[j++] ); // Q25 + L_dist = L_add( L_dist, Mpy_32_32( L_tmp, L_tmp ) ); // (Q25, Q25) -> Q19 + } + if ( LT_32( L_dist, L_mindist ) ) // Q19 + { + idx = c; + move16(); + } + L_mindist = L_min( L_mindist, L_dist ); // Q19 + } + IF( xq == 0 ) + { + return idx; + } + + /*j = idx*dim;*/ + j = i_mult2( idx, dim ); + FOR( d = 0; d < dim; d++ ) + { + xq[d] = cb[j++]; // Q25 + move32(); + } + IF( x_mean != 0 ) + { + FOR( d = 0; d < dim; d++ ) + { + /*xq[d] += x_mean[d]; */ + xq[d] = L_add( xq[d], x_mean[d] ); // Q25 + move32(); + } + } + + return idx; +} + +Word16 vquant_fx( /* o: index of the winning codevector */ + Word16 x[], /* i: vector to quantize Q13 */ + const Word16 x_mean[], /* i: vector mean to subtract (0 if none) Q13 */ + Word16 xq[], /* o: quantized vector Q13 */ + const Word16 cb[], /* i: codebook Q13 */ + const Word16 dim, /* i: dimension of codebook vectors */ + const Word16 cbsize /* i: codebook size */ +) +{ + Word16 tmp; + Word16 c, d, idx, j; + Word32 L_dist, /*L_tmp,*/ L_mindist; + + idx = 0; + move16(); + L_mindist = MAX_32; + move32(); + IF( x_mean != 0 ) + { + FOR( d = 0; d < dim; d++ ) + { + /*x[d] -= x_mean[d]; */ + x[d] = sub( x[d], x_mean[d] ); + move16(); /*Qx */ + } + } + j = 0; + move16(); + FOR( c = 0; c < cbsize; c++ ) + { + L_dist = 0; + move32(); + + FOR( d = 0; d < dim; d++ ) + { + /*tmp = x[d] - cb[j++];*/ + tmp = sub( x[d], cb[j++] ); /*Qx */ + L_dist = L_mac0( L_dist, tmp, tmp ); + } + if ( LT_32( L_dist, L_mindist ) ) + { + idx = c; + move16(); + } + L_mindist = L_min( L_mindist, L_dist ); + } + IF( xq == 0 ) + { + return idx; + } + + /*j = idx*dim;*/ + j = i_mult2( idx, dim ); + FOR( d = 0; d < dim; d++ ) + { + xq[d] = cb[j++]; + move16(); + } + IF( x_mean != 0 ) + { + FOR( d = 0; d < dim; d++ ) + { + /*xq[d] += x_mean[d]; */ + xq[d] = add( xq[d], x_mean[d] ); + move16(); + } + } + + return idx; +} + +/*-------------------------------------------------------------------* + * w_vquant_fx() + * + * Vector quantizer according to MMSE criterion (nearest neighbour in Euclidean space) + * + * Searches a given codebook to find the nearest neighbour in Euclidean space. + * Weights are put on the error for each vector element. + * Index of the winning codevector and the winning vector itself are returned. + *-------------------------------------------------------------------*/ +Word16 w_vquant_fx( + Word16 x[], /* i: vector to quantize in Q10 */ + Word16 Qx, + const Word16 weights[], /* i: error weights in Q0 */ + Word16 xq[], /* o: quantized vector in Q15 */ + const Word16 cb[], /* i: codebook in Q15 */ + const Word16 cbsize, /* i: codebook size */ + const Word16 rev_vect /* i: reverse codebook vectors */ +) +{ + Word16 tmp; + Word16 c, idx, j; + Word32 dist, minDist; +#ifndef ISSUE_1836_replace_overflow_libcom +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move32(); +#endif +#endif + + + idx = 0; + move16(); + minDist = 0x7fffffffL; + move32(); + Qx = sub( 15, Qx ); + + j = 0; + move16(); + IF( rev_vect ) + { + FOR( c = 0; c < cbsize; c++ ) + { + dist = L_deposit_l( 0 ); + +#ifdef ISSUE_1836_replace_overflow_libcom + tmp = sub_sat( x[3], shr( cb[j++], Qx ) ); + if ( weights[3] != 0 ) + { + dist = L_mac0_sat( dist, tmp, tmp ); + } + tmp = sub_sat( x[2], shr( cb[j++], Qx ) ); + if ( weights[2] != 0 ) + { + dist = L_mac0_sat( dist, tmp, tmp ); + } + tmp = sub_sat( x[1], shr( cb[j++], Qx ) ); + if ( weights[1] != 0 ) + { + dist = L_mac0_sat( dist, tmp, tmp ); + } + tmp = sub_sat( x[0], shr( cb[j++], Qx ) ); + if ( weights[0] != 0 ) + { + dist = L_mac0_sat( dist, tmp, tmp ); + } +#else + tmp = sub_o( x[3], shr( cb[j++], Qx ), &Overflow ); + if ( weights[3] != 0 ) + { + dist = L_mac0_o( dist, tmp, tmp, &Overflow ); + } + tmp = sub_o( x[2], shr( cb[j++], Qx ), &Overflow ); + if ( weights[2] != 0 ) + { + dist = L_mac0_o( dist, tmp, tmp, &Overflow ); + } + tmp = sub_o( x[1], shr( cb[j++], Qx ), &Overflow ); + if ( weights[1] != 0 ) + { + dist = L_mac0_o( dist, tmp, tmp, &Overflow ); + } + tmp = sub_o( x[0], shr( cb[j++], Qx ), &Overflow ); + if ( weights[0] != 0 ) + { + dist = L_mac0_o( dist, tmp, tmp, &Overflow ); + } +#endif + if ( LT_32( dist, minDist ) ) + { + idx = c; + move16(); + } + minDist = L_min( minDist, dist ); + } + + IF( xq == 0 ) + { + return idx; + } + + j = shl( idx, 2 ); + xq[3] = cb[j++]; + move16(); /* in Q15 */ + xq[2] = cb[j++]; + move16(); /* in Q15 */ + xq[1] = cb[j++]; + move16(); /* in Q15 */ + xq[0] = cb[j++]; + move16(); /* in Q15 */ + } + ELSE + { + FOR( c = 0; c < cbsize; c++ ) + { + dist = L_deposit_l( 0 ); + +#ifdef ISSUE_1836_replace_overflow_libcom + tmp = sub_sat( x[0], shr( cb[j++], Qx ) ); + if ( weights[0] != 0 ) + { + dist = L_mac0_sat( dist, tmp, tmp ); + } + tmp = sub_sat( x[1], shr( cb[j++], Qx ) ); + if ( weights[1] != 0 ) + { + dist = L_mac0_sat( dist, tmp, tmp ); + } + tmp = sub_sat( x[2], shr( cb[j++], Qx ) ); + if ( weights[2] != 0 ) + { + dist = L_mac0_sat( dist, tmp, tmp ); + } + tmp = sub_sat( x[3], shr( cb[j++], Qx ) ); + if ( weights[3] != 0 ) + { + dist = L_mac0_sat( dist, tmp, tmp ); + } +#else + tmp = sub_o( x[0], shr( cb[j++], Qx ), &Overflow ); + if ( weights[0] != 0 ) + { + dist = L_mac0_o( dist, tmp, tmp, &Overflow ); + } + tmp = sub_o( x[1], shr( cb[j++], Qx ), &Overflow ); + if ( weights[1] != 0 ) + { + dist = L_mac0_o( dist, tmp, tmp, &Overflow ); + } + tmp = sub_o( x[2], shr( cb[j++], Qx ), &Overflow ); + if ( weights[2] != 0 ) + { + dist = L_mac0_o( dist, tmp, tmp, &Overflow ); + } + tmp = sub_o( x[3], shr( cb[j++], Qx ), &Overflow ); + if ( weights[3] != 0 ) + { + dist = L_mac0_o( dist, tmp, tmp, &Overflow ); + } +#endif + if ( LT_32( dist, minDist ) ) + { + idx = c; + move16(); + } + minDist = L_min( minDist, dist ); + } + + IF( xq == 0 ) + { + return idx; + } + + j = shl( idx, 2 ); + xq[0] = cb[j++]; + move16(); /* in Q15 */ + xq[1] = cb[j++]; + move16(); /* in Q15 */ + xq[2] = cb[j++]; + move16(); /* in Q15 */ + xq[3] = cb[j++]; + move16(); /* in Q15 */ + } + + return idx; +} +/*-------------------------------------------------------------------* + * Emaximum: + * + * Find index of a maximum energy in a vector + *-------------------------------------------------------------------*/ +Word16 emaximum_fx( /* o : return index with max energy value in vector Q0 */ + const Word16 Qvec, /* i : Q of input vector Q0 */ + const Word16 *vec, /* i : input vector Qx */ + const Word16 lvec, /* i : length of input vector Q0 */ + Word32 *ener_max /* o : maximum energy value Q0 */ +) +{ + Word16 j, ind; + Word32 L_tmp, L_tmp1; + Word32 emax; + + emax = L_mult0( vec[0], vec[0] ); + ind = 0; + move16(); + + FOR( j = 1; j < lvec; j++ ) + { + L_tmp = L_mult0( vec[j], vec[j] ); + L_tmp1 = L_sub( L_tmp, emax ); + if ( L_tmp1 > 0 ) + { + ind = j; + move16(); + } + emax = L_max( emax, L_tmp ); + } + + *ener_max = L_shr_sat( emax, add( Qvec, Qvec ) ); + move32(); + + return ind; +} + +Word16 emaximum_32fx( /* o : return index with max energy value in vector Q0 */ + const Word16 Qvec, /* i : Q of input vector Q0 */ + const Word32 *vec, /* i : input vector Qx */ + const Word16 lvec, /* i : length of input vector Q0 */ + Word32 *ener_max /* o : maximum energy value Q0 */ +) +{ + Word16 j, ind; + Word64 W_tmp, W_tmp1; + Word64 emax; + + emax = W_mult0_32_32( vec[0], vec[0] ); + ind = 0; + move16(); + + FOR( j = 1; j < lvec; j++ ) + { + W_tmp = W_mult0_32_32( vec[j], vec[j] ); + W_tmp1 = W_sub( W_tmp, emax ); + if ( W_tmp1 > 0 ) + { + ind = j; + move16(); + } + if ( LE_64( emax, W_tmp ) ) + { + emax = W_tmp; + move64(); + } + } + + *ener_max = W_extract_l( W_shr( emax, add( Qvec, Qvec ) ) ); + move32(); + + return ind; +} + +/*-------------------------------------------------------------------* + * mean32: + * + * Find the mean of a 32 bits vector + *-------------------------------------------------------------------*/ +Word32 Mean32( /* o : mean of the elements of the vector */ + const Word32 in[], /* i : input vector */ + const Word16 L /* i : length of input vector */ +) +{ + Word32 Ltmp; + Word16 inv_L; + + inv_L = INV_BANDS9; + move16(); + if ( EQ_16( L, 10 ) ) + { + inv_L = INV_BANDS10; + move16(); + } + + Ltmp = sum32_fx( in, L ); + + Ltmp = Mult_32_16( Ltmp, inv_L ); + + return Ltmp; +} +Word32 sum32_fx( /* o : sum of all vector elements Qx*/ + const Word32 *vec, /* i : input vector Qx*/ + const Word16 lvec /* i : length of input vector */ +) +{ + Word16 i; + Word32 tmp; + + tmp = L_deposit_l( 0 ); + FOR( i = 0; i < lvec; i++ ) + { + tmp = L_add_sat( tmp, vec[i] ); /*Qx */ + } + + return tmp; +} +Word16 sum16_fx( /* o : sum of all vector elements Qx*/ + const Word16 *vec, /* i : input vector Qx*/ + const Word16 lvec /* i : length of input vector */ +) +{ + Word16 i; + Word16 tmp; + tmp = 0; + move16(); + FOR( i = 0; i < lvec; i++ ) + { + tmp = add_sat( tmp, vec[i] ); /*Qx */ + } + + return tmp; +} +/*------------------------------------------------------------------* + * function Random + * + * Signed 16 bits random generator. + *------------------------------------------------------------------*/ +Word16 Random( /* o : output random value */ + Word16 *seed /* i/o: random seed */ +) +{ + *seed = extract_l( L_mac0( 13849L, *seed, 31821 ) ); + move16(); + return *seed; +} + +Word16 own_random2_fx( Word16 seed ) +{ + return extract_l( L_mac0( 13849, seed, 31821 ) ); +} + +/*--------------------------------------------------------------------- + * sign_fx() + * + *---------------------------------------------------------------------*/ + +/*! r: sign of x (+1/-1) */ +Word16 sign_fx( + const Word32 x /* i : input value of x */ +) +{ + IF( LT_32( x, 0 ) ) + { + return -1; + } + ELSE + { + return 1; + } +} + +Word16 sign16_fx( + const Word16 x /* i : input value of x */ +) +{ + IF( LT_16( x, 0 ) ) + { + return -1; + } + ELSE + { + return 1; + } +} + +/*------------------------------------------------------------------* + * function Div_32_optmz + * + * Performs 32 bits interger division + *------------------------------------------------------------------*/ +static Word32 Div_32_optmz( Word32 L_num, Word16 denom_hi ) +{ + Word16 approx, hi, lo, n_hi, n_lo; + Word32 L_32; + + /* First approximation: 1 / L_denom = 1/denom_hi */ + + approx = div_s( (Word16) 0x3fff, denom_hi ); + + /* 1/L_denom = approx * (2.0 - L_denom * approx) */ + + L_32 = L_msu( (Word32) 0x7fffffffL, denom_hi, approx ); + + lo = L_Extract_lc( L_32, &hi ); + L_32 = Mpy_32_16( hi, lo, approx ); + + /* L_num * (1/L_denom) */ + + lo = L_Extract_lc( L_32, &hi ); + n_lo = L_Extract_lc( L_num, &n_hi ); + L_32 = Mpy_32( n_hi, n_lo, hi, lo ); + + return ( L_32 ); +} +/*------------------------------------------------------------------* + * function iDiv_and_mod_32 + * + * return the quotient and the modulo 32 bits numerator divided by a 16 bit denominator + * The denominator might be right shifted by 1 + *------------------------------------------------------------------*/ +void iDiv_and_mod_32( + const Word32 Numer, /* i : 32 bits numerator */ + const Word16 Denom, /* i : 16 bits denominator */ + Word32 *Int_quotient, /* o : integer result of the division (int)(num/den) */ + Word32 *Int_mod, /* o : modulo result of the division num-((int)(num/den)*den)*/ + const Word16 rshift /* i : 0 if no right shift / 1 if the denom is right shifted by 1 */ +) +{ + Word32 Quotient; + Word16 expA, expB; + Word32 N, TEMP; + Word16 D; + + /* Normalize 'Numer' & 'Denom' */ + /* Use Temporary to Preserve the Original Value */ + expA = norm_l( Numer ); + N = L_shl( Numer, expA ); + expB = norm_s( Denom ); + D = shl( Denom, expB ); + + /* Need to shift right 'Numer' by 1? */ + if ( L_mac( N, D, -32768L ) >= 0 ) + { + expA = sub( expA, 1 ); + } + N = L_shl( Numer, expA ); + + /* Perform Approximation of the Division + * Since 'lo' part is '0' AND 'denom' is supposed to be constant in the targeted usage + * one could import the Div32 code and pre-calc the div_s and eliminate all calcs + * with 'lo' to save some complexity */ + + Quotient = Div_32_optmz( N, D ); /* takes 36 clocks */ + /* Bring Back to Q0 (minus 2 because we removed the left shift by 2 in the Div32_optmz) */ + IF( rshift ) + { + Quotient = L_shr( Quotient, add( 15 - 2, sub( expA, sub( expB, 1 ) ) ) ); + } + ELSE + { + Quotient = L_shr( Quotient, add( 15 - 2, sub( expA, expB ) ) ); + } + + /* Cross Check (do Quotient x Divisor) + * The Quotient is unsigned but we cannot just use extract_h because + * extract_l on the low part will get the sign of the bit #15. + * In a 32 bits value, what is in bits 0-15 is un unsigned 16 bits value. + * So, we shift left by 1, extract the hi part and mult it by 32768 (hence the L_shl by 16-1. + * Then we take 15 bits left (mask the others) and multiply by Denom. + * Technically this could overflow. But since we are mutiplying to get + * back to the Numer value that fitted in a 32 bits, doing Divisor x Quotient + * must necessarily fit in a 32 bits + * It is assumed that all are positive values. If not, one could + * check the sign of the numer and denom, turn them into abs values + * and restore the sign after*/ + TEMP = L_shl( L_mult0( extract_h( L_shl( Quotient, 1 ) ), Denom ), 16 - 1 ); + TEMP = L_mac0( TEMP, extract_l( L_and( 0x7FFF, Quotient ) ), Denom ); + + + /* Here we test to see if the previous "Quotient x Divisor" (or TEMP) is too small + * that is the "Numer" minus TEMP is bigger or Equal to the Divisor. + * If it is then the quotient is too small. We need to increase it by 1. + * That is caused by our Div32 fractionnal division that can be off by 1 + * sometimes. + * In some cases, when the divisor is very small (like 10 or something) + * the quotient could be off by more than 1 and we would need a loop + * to check again. That is not the case here with the current divisor */ + IF( rshift ) + { + TEMP = L_shl( TEMP, 1 ); + WHILE( L_msu0( L_sub( Numer, TEMP ), 2, Denom ) >= 0 ) + { + Quotient = L_add( Quotient, 1 ); + TEMP = L_shl( L_mult0( extract_h( L_shl( Quotient, 1 ) ), Denom ), 16 - 1 ); + TEMP = L_mac0( TEMP, extract_l( L_and( 0x7FFF, Quotient ) ), Denom ); + TEMP = L_shl( TEMP, 1 ); + } + } + ELSE{ + WHILE( L_msu0( L_sub( Numer, TEMP ), 1, Denom ) >= 0 ){ + Quotient = L_add( Quotient, 1 ); + TEMP = L_shl( L_mult0( extract_h( L_shl( Quotient, 1 ) ), Denom ), 16 - 1 ); + TEMP = L_mac0( TEMP, extract_l( L_and( 0x7FFF, Quotient ) ), Denom ); +} +} +*Int_quotient = Quotient; +move32(); +IF( L_msu0( L_sub( Numer, TEMP ), 1, Denom ) == 0 ) +{ + *Int_mod = 0L; + move32(); +} +ELSE +{ + *Int_mod = L_sub( Numer, TEMP ); + move32(); +} +} + +/*===================================================================*/ +/* FUNCTION : pz_filter_sp_fx () */ +/*-------------------------------------------------------------------*/ +/* PURPOSE : Generic pole-zero filter routine, with single */ +/* precision memory */ +/*-------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* */ +/* _ (Word16 []) b : zero filter coefficients (Qc). */ +/* _ (Word16 []) a : pole filter coefficients (Qc), a(0)=1 in Qc */ +/* _ (Word16 []) x : input signal (Qn). */ +/* _ (Word16) PNR : NR filter order */ +/* _ (Word16) PDR : DR filter order */ +/* _ (Word16) N : number of input samples. */ +/* _ (Word16) Qa : Q factor compensation (Qa=16-Qc) */ +/*-------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* */ +/* _ (Word16 []) y : output signal (Qn) */ +/*-------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* */ +/* _ (Word16 []) buf : filter memory (Qn-Qa). */ +/*-------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : _ None. */ +/*===================================================================*/ + +void pz_filter_sp_fx( + const Word16 b[], + const Word16 a[], + Word16 x[], + Word16 y[], + Word16 buf[], + Word16 PNR, + Word16 PDR, + Word16 N, + Word16 Qa ) +{ + Word16 i, j; + Word16 s; + Word16 s_mem; + Word32 Ltemp1; + Word32 Lacc; + s = negate( Qa ); + s = add( s, s ); /* s=-2Qa*/ + s = add( s, 1 ); + FOR( i = 0; i < N; i++ ) + { + Lacc = L_deposit_h( x[i] ); /* Lacc in Q(16+Qn)*/ + Lacc = L_shl( Lacc, s ); /* Lacc=x[i] in Q(16+Qn-2Qa+1)*/ + FOR( j = PDR - 1; j >= 0; j-- ) + Lacc = L_msu_sat( Lacc, buf[j], a[j + 1] ); /*Q(16+Qn-2Qa+1)*/ + + + Lacc = L_shr( Lacc, 1 ); + Ltemp1 = L_add_sat( L_shl_sat( Lacc, Qa ), 0x08000 ); + s_mem = extract_h( Ltemp1 ); + + Lacc = L_deposit_l( 0 ); + FOR( j = PNR - 1; j >= 0; j-- ) + Lacc = L_mac_sat( Lacc, buf[j], b[j + 1] ); + Lacc = L_mac_sat( Lacc, s_mem, b[0] ); + /* Lacc in Q(1+Qc+Qn-Qa)*/ + + FOR( j = s_max( PDR, PNR ) - 1; j > 0; j-- ) + { + /* Update filter memory */ + buf[j] = buf[j - 1]; + move16(); + } + buf[0] = s_mem; + move16(); + + Ltemp1 = L_add_sat( L_shr_sat( Lacc, s ), 0x08000 ); /* Ltemp1 in Qc+Qa+Qn=Q(Qn) */ + y[i] = extract_h( Ltemp1 ); /* y[i] in Qn */ + move16(); + } +} + + +Word32 root_a_fx( + Word32 a, + Word16 Q_a, + Word16 *exp_out ) +{ + Word16 exp, tmp; + Word32 L_tmp; + + IF( a <= 0 ) + { + *exp_out = 0; + move16(); + return 0; + } + + exp = norm_l( a ); + tmp = extract_h( L_shl( a, exp ) ); + exp = sub( exp, sub( 30, Q_a ) ); + tmp = div_s( 16384, tmp ); + L_tmp = L_deposit_h( tmp ); + L_tmp = Isqrt_lc( L_tmp, &exp ); + + *exp_out = exp; + move16(); + + return L_tmp; +} + + +Word32 root_a_over_b_fx( + Word32 a, /* Q(Q_a) */ + Word16 Q_a, + Word32 b, /* Q(Q_b) */ + Word16 Q_b, + Word16 *exp_out ) +{ + Word16 tmp, num, den, scale; + Word16 exp, exp_num, exp_den; + Word32 L_tmp; +#ifndef ISSUE_1836_replace_overflow_libcom +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move32(); +#endif +#endif + test(); + IF( ( a <= 0 ) || ( b <= 0 ) ) + { + *exp_out = 0; + move16(); + return 0; + } + + exp_num = norm_l( b ); +#ifdef ISSUE_1836_replace_overflow_libcom + num = round_fx_sat( L_shl_sat( b, exp_num ) ); +#else + num = round_fx_o( L_shl_o( b, exp_num, &Overflow ), &Overflow ); +#endif + exp_num = sub( sub( 30, exp_num ), Q_b ); + + exp_den = norm_l( a ); +#ifdef ISSUE_1836_replace_overflow_libcom + den = round_fx_sat( L_shl_sat( a, exp_den ) ); +#else + den = round_fx_o( L_shl_o( a, exp_den, &Overflow ), &Overflow ); +#endif + exp_den = sub( sub( 30, exp_den ), Q_a ); + + scale = shr( sub( den, num ), 15 ); +#ifdef ISSUE_1836_replace_overflow_libcom + num = shl_sat( num, scale ); +#else + num = shl_o( num, scale, &Overflow ); +#endif + exp_num = sub( exp_num, scale ); + + tmp = div_s( num, den ); + exp = sub( exp_num, exp_den ); + + L_tmp = L_deposit_h( tmp ); + L_tmp = Isqrt_lc( L_tmp, &exp ); + + *exp_out = exp; + move16(); + + return L_tmp; +} + +Word32 root_a_over_b_ivas_fx( + Word32 a, /* Q(Q_a) */ + Word16 Q_a, + Word32 b, /* Q(Q_b) */ + Word16 Q_b, + Word16 *q_out ) +{ + Word16 shift_a, shift_b, shift; + Word32 mod_a, mod_b, one_in_Q_a, one_in_Q_b, half_in_Q_a, half_in_Q_b; + Word32 a_sqr, b_sqr, p0, p1, p2, approx; + Word16 exp; + + test(); + IF( ( a <= 0 ) || ( b <= 0 ) ) + { + *q_out = 0; + move16(); + return 0; + } + + one_in_Q_a = L_shl( 1, Q_a ); // 1.0f in Q_a + one_in_Q_b = L_shl( 1, Q_b ); // 1.0f in Q_b + half_in_Q_a = L_shr( one_in_Q_a, 1 ); // 0.5f in Q_a + half_in_Q_b = L_shr( one_in_Q_b, 1 ); // 0.5f in Q_b + + a = L_add( a, one_in_Q_a ); + b = L_add( b, one_in_Q_b ); + + /* This next piece of code implements a "norm" function */ + /* and returns the shift needed to scale "a" to have a */ + /* 1 in the (MSB-1) position. This is equivalent to */ + /* giving a value between 0.5 & 1.0. */ + + mod_a = a; + move32(); + + shift_a = 0; + move16(); + WHILE( GT_32( mod_a, one_in_Q_a ) ) + { + mod_a = L_shr( mod_a, 1 ); + shift_a = sub( shift_a, 1 ); + } + + WHILE( LT_32( mod_a, half_in_Q_a ) ) + { + mod_a = L_shl( mod_a, 1 ); + shift_a = add( shift_a, 1 ); + } + + shift_a = s_and( shift_a, -2 ); + mod_a = L_shl( a, shift_a ); // Q_a + + /* This next piece of code implements a "norm" function */ + /* and returns the shift needed to scale "b" to have a */ + /* 1 in the (MSB-1) position. This is equivalent to */ + /* giving a value between 0.5 & 1.0. */ + mod_b = b; + move32(); + + shift_b = 0; + move16(); + WHILE( GT_32( mod_b, one_in_Q_b ) ) + { + mod_b = L_shr( mod_b, 1 ); + shift_b = sub( shift_b, 1 ); + } + + WHILE( LT_32( mod_b, half_in_Q_b ) ) + { + mod_b = L_shl( mod_b, 1 ); + shift_b = add( shift_b, 1 ); + } + + shift_b = s_and( shift_b, -2 ); + mod_b = L_shl( b, shift_b ); // Q_b + + shift = shr( sub( shift_b, shift_a ), 1 ); + + a_sqr = W_extract_h( W_shl( W_mult0_32_32( mod_a, mod_a ), sub( 32, Q_a ) ) ); // Q_a + b_sqr = W_extract_h( W_shl( W_mult0_32_32( mod_b, mod_b ), sub( 32, Q_b ) ) ); // Q_b + + p2 = L_shl( -408505077 /* -0.7609f in Q29 */, sub( Q_b, 31 ) ); // Qb-2 + p1 = L_shl( 1444612250 /* 2.6908f in Q29 */, sub( Q_b, 31 ) ); // Qb-2 + p0 = L_shl( 385258566 /* 0.7176f in Q29 */, sub( Q_b, 31 ) ); // Qb-2 + + p2 = Madd_32_32( Madd_32_32( p2, 501759554 /* 0.9346f in Q29*/, mod_b ), -252060893 /* -0.4695f in Q29 */, b_sqr ); // Q_b-2 + p1 = Madd_32_32( Madd_32_32( p1, -1774680487 /* -3.3056f in Q29 */, mod_b ), 891635211 /* 1.6608f in Q29 */, b_sqr ); // Q_b-2 + p0 = Madd_32_32( Madd_32_32( p0, -473251709 /* -0.8815f in Q29 */, mod_b ), 237780127 /* 0.4429f in Q29 */, b_sqr ); // Q_b-2 + + /* approx = p0 + p1 * mod_a + p2 * mod_a * mod_a; */ + approx = Madd_32_32( Mpy_32_32( p1, mod_a ), p2, a_sqr ); // Q_a+Q_b-33 + approx = L_add( approx, L_shl( p0, sub( Q_a, 31 ) ) ); // Q_a+Q_b-33 + + exp = sub( norm_l( approx ), 1 ); + approx = L_shl( approx, exp ); // // Q_a+Q_b-33+exp + + *q_out = sub( add( sub( add( Q_a, Q_b ), 33 ), exp ), shift ); + move16(); + + return approx; +} + +/*===================================================================*/ +/* FUNCTION : fir_fx () */ +/*-------------------------------------------------------------------*/ +/* PURPOSE : Generic FIR filter routine */ +/*-------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* */ +/* _ (Word16 []) b : filter coefficients (Qc). */ +/* _ (Word16 []) x : input signal (Qn). */ +/* _ (Word16) P : filter order. */ +/* _ (Word16) N : number of input samples. */ +/* _ (Word16) Qa : Q factor compensation (Qa=16-Qc) */ +/*-------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* */ +/* _ (Word16 []) y : output signal (Qn) */ +/*-------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* */ +/* _ : None */ +/*-------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : _ None. */ +/*===================================================================*/ +void fir_fx( const Word16 x[], /* i : input vector Qx*/ + const Word16 h[], /* i : impulse response of the FIR filter Q12*/ + Word16 y[], /* o : output vector (result of filtering) Qx*/ + Word16 mem[], /* i/o: memory of the input signal (L samples) Qx*/ + const Word16 L, /* i : input vector size */ + const Word16 K, /* i : order of the FIR filter (K+1 coefs.) */ + const Word16 upd /* i : 1 = update the memory, 0 = not */ + , + Word16 shift /* i : difference between Q15 and scaling of h[] */ +) +{ + + Word16 buf_in[L_FRAME32k + L_FILT_MAX]; + Word16 i, j; + Word32 s; +#ifndef ISSUE_1836_replace_overflow_libcom +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move32(); +#endif +#endif + /* prepare the input buffer (copy and update memory) */ + Copy( mem, buf_in, K ); + Copy( x, buf_in + K, L ); + IF( upd ) + { + Copy( buf_in + L, mem, K ); + } + + /* do the filtering */ + FOR( i = 0; i < L; i++ ) + { +#ifdef ISSUE_1836_replace_overflow_libcom + s = L_mult_sat( buf_in[K + i], h[0] ); +#else + s = L_mult_o( buf_in[K + i], h[0], &Overflow ); +#endif + + FOR( j = 1; j <= K; j++ ) + { +#ifdef ISSUE_1836_replace_overflow_libcom + s = L_mac_sat( s, h[j], buf_in[K + i - j] ); +#else + s = L_mac_o( s, h[j], buf_in[K + i - j], &Overflow ); +#endif + } +#ifdef ISSUE_1836_replace_overflow_libcom + s = L_shl_sat( s, shift ); + y[i] = round_fx_sat( s ); /*Qx */ +#else + s = L_shl_o( s, shift, &Overflow ); + y[i] = round_fx_o( s, &Overflow ); /*Qx */ +#endif + move16(); + } +} + +/*-------------------------------------------------------------------* + * v_add_32() + * + * Addition of two vectors sample by sample + *-------------------------------------------------------------------*/ + +void v_add_32( + const Word32 x1[], /* i : Input vector 1 */ + const Word32 x2[], /* i : Input vector 2 */ + Word32 y[], /* o : Output vector that contains vector 1 + vector 2 */ + const Word16 N /* i : Vector length */ +) +{ + Word16 i; + + FOR( i = 0; i < N; i++ ) + { + y[i] = L_add( x1[i], x2[i] ); + move32(); + } + + return; +} + +void v_shr_32( + Word32 x1[], /* i : Input vector 1 */ + Word32 y[], /* o : Output vector that contains vector 1 + vector 2 */ + const Word16 N, /* i : Vector length */ + Word16 shift /*shift value*/ +) +{ + Word16 i; + + FOR( i = 0; i < N; i++ ) + { + y[i] = L_shr( x1[i], shift ); + move32(); + } + + return; +} + + +/*-------------------------------------------------------------------* + * v_sub_32() + * + * Subtraction of two vectors sample by sample + *-------------------------------------------------------------------*/ + +void v_sub_32( + const Word32 x1[], /* i : Input vector 1 */ + const Word32 x2[], /* i : Input vector 2 */ + Word32 y[], /* o : Output vector that contains vector 1 - vector 2 */ + const Word16 N /* i : Vector length */ +) +{ + Word16 i; + + FOR( i = 0; i < N; i++ ) + { + y[i] = L_sub( x1[i], x2[i] ); + move32(); + } + + return; +} + + +/*-------------------------------------------------------------------* + * v_add_16() + * + * Addition of two vectors sample by sample + *-------------------------------------------------------------------*/ + +void v_add_16( + const Word16 x1[], /* i : Input vector 1 */ + const Word16 x2[], /* i : Input vector 2 */ + Word16 y[], /* o : Output vector that contains vector 1 + vector 2 */ + const Word16 N /* i : Vector length */ +) +{ + Word16 i; + + FOR( i = 0; i < N; i++ ) + { + y[i] = add_sat( x1[i], x2[i] ); + move16(); + } + + return; +} + + +/*-------------------------------------------------------------------* + * v_sub_16() + * + * Subtraction of two vectors sample by sample + *-------------------------------------------------------------------*/ + +void v_sub_16( + const Word16 x1[], /* i : Input vector 1 */ + const Word16 x2[], /* i : Input vector 2 */ + Word16 y[], /* o : Output vector that contains vector 1 - vector 2 */ + const Word16 N /* i : Vector length */ +) +{ + Word16 i; + + FOR( i = 0; i < N; i++ ) + { + y[i] = sub_sat( x1[i], x2[i] ); + move16(); + } + + return; +} + + +/*--------------------------------------------------------------------------------*/ +/* squant_fx() */ +/*--------------------------------------------------------------------------------*/ +Word16 squant_fx( /* o: index of the winning codeword */ + const Word16 x, /* i: scalar value to quantize */ + Word16 *xq, /* o: quantized value */ + const Word16 cb[], /* i: codebook */ + const Word16 cbsize /* i: codebook size */ +) +{ + Word16 tmp; + Word16 c, idx; + Word32 L_mindist, L_dist; +#ifndef ISSUE_1836_replace_overflow_libcom +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif +#endif + + idx = 0; + move16(); + L_mindist = MAX_32; + move32(); + + FOR( c = 0; c < cbsize; c++ ) + { + L_dist = L_deposit_l( 0 ); +#ifdef ISSUE_1836_replace_overflow_libcom + tmp = sub_sat( x, cb[c] ); +#else + tmp = sub_o( x, cb[c], &Overflow ); +#endif + + /*dist += tmp*tmp; */ +#ifdef ISSUE_1836_replace_overflow_libcom + L_dist = L_mac_sat( L_dist, tmp, tmp ); +#else + L_dist = L_mac_o( L_dist, tmp, tmp, &Overflow ); +#endif + + if ( LT_32( L_dist, L_mindist ) ) + { + idx = c; + move16(); + } + L_mindist = L_min( L_mindist, L_dist ); + } + + *xq = cb[idx]; + move16(); + + return idx; +} + +/*! r: index of the winning codeword */ +Word16 squant_int_fx( + UWord8 x, /* i : scalar value to quantize */ + UWord8 *xq, /* o : quantized value */ + const UWord8 *cb, /* i : codebook */ + const Word16 cbsize /* i : codebook size */ +) +{ + Word16 i, idx; + Word32 mindist, d; + + idx = 0; + move16(); + mindist = 10000000; // Q0 + move32(); + FOR( i = 0; i < cbsize; i++ ) + { + d = L_mult0( sub( x, cb[i] ), sub( x, cb[i] ) ); + IF( LT_32( d, mindist ) ) + { + mindist = d; + move32(); + idx = i; + move16(); + } + } + *xq = cb[idx]; + move16(); + + return idx; +} + +/*===================================================================*/ +/* FUNCTION : pz_filter_dp_fx () */ +/*-------------------------------------------------------------------*/ +/* PURPOSE : Generic pole-zero filter routine, with double */ +/* precision memory, transposed direct form II */ +/*-------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* */ +/* _ (Word16 []) b : zero filter coefficients (Qc). */ +/* _ (Word16 []) a : pole filter coefficients (Qc), a(0)=1 */ +/* _ (Word16 []) x : input signal (Qx). */ +/* _ (Word16) P : filter order. */ +/* _ (Word16) N : number of input samples. */ +/* _ (Word16) Qa : Q factor compensation (Qa=16-Qc) */ +/*-------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* */ +/* _ (Word16 []) y : output signal (Qx) */ +/*-------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* */ +/* _ (Word32 []) buf : filter memory (Qx+Qc) */ +/*-------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : _ None. */ +/*===================================================================*/ + +void pz_filter_dp_fx( + const Word16 b[], + const Word16 a[], + Word16 x[], + Word16 y[], + Word32 buf[], + Word16 PNR, + Word16 PDR, + Word16 N, + Word16 Qa ) +{ + Word16 i, j; + Word16 s; + Word32 s_mem; + Word32 Ltemp1; + Word32 Lacc; + + s = negate( Qa ); + s = add( s, s ); /* s=-2Qa */ + s = add( s, 1 ); + FOR( i = 0; i < N; i++ ) + { + Lacc = L_deposit_h( x[i] ); /* Lacc in Q(16+Qn)*/ + Lacc = L_shl( Lacc, s ); /* Lacc=x[i] in Q(16+Qn-2Qa+1)*/ + FOR( j = PDR - 1; j >= 0; j-- ) + Lacc = Msub_32_16( Lacc, buf[j], a[j + 1] ); /*Q(16+Qn-2Qa+1)*/ + + s_mem = L_shl_sat( Lacc, sub( Qa, 1 ) ); /*Qn-Qa+16=Qn+Qc*/ + Lacc = L_deposit_l( 0 ); + FOR( j = PNR - 1; j >= 0; j-- ) + Lacc = Madd_32_16( Lacc, buf[j], b[j + 1] ); + Lacc = Madd_32_16( Lacc, s_mem, b[0] ); + /* Lacc in Q(1+Qc+Qn-Qa) */ + + FOR( j = s_max( PDR, PNR ) - 1; j > 0; j-- ) + { + /* Update filter memory */ + buf[j] = buf[j - 1]; + move16(); + } + buf[0] = s_mem; + move16(); + + Ltemp1 = L_shr_sat( Lacc, s ); /* Ltemp1 in Qc+Qa+Qn=Q(16+Qn) */ + y[i] = extract_h( Ltemp1 ); /* y[i] in Qn */ + move16(); + } +} + +/*-------------------------------------------------------------------* + * Copy_Scale_sig + * + * Up/down scale a 16 bits vector x and move it into y + *-------------------------------------------------------------------*/ +void Copy_Scale_sig32( + const Word32 x[], /* i : signal to scale input Qx */ + Word32 y[], /* o : scaled signal output Qx */ + const Word16 lg, /* i : size of x[] Q0 */ + const Word16 exp0 /* i : exponent: x = round(x << exp) Qx ?exp */ +) +{ + Word16 i; + Word32 L_tmp; + Word16 tmp = exp0; +#ifndef ISSUE_1836_replace_overflow_libcom +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move32(); +#endif +#endif + IF( exp0 == 0 ) + { + FOR( i = 0; i < lg; i++ ) + { + y[i] = x[i]; + move32(); + } + return; + } + IF( exp0 < 0 ) + { + FOR( i = 0; i < lg; i++ ) + { +#ifdef ISSUE_1836_replace_overflow_libcom + y[i] = L_shl_sat( x[i], tmp ); +#else + y[i] = L_shl_o( x[i], tmp, &Overflow ); +#endif + move16(); + } + return; + } +#ifdef ISSUE_1836_replace_overflow_libcom + L_tmp = L_shl_sat( 1, exp0 - 1 ); +#else + L_tmp = L_shl_o( 1, exp0 - 1, &Overflow ); +#endif + FOR( i = 0; i < lg; i++ ) + { + y[i] = W_extract_l( W_mult_32_32( L_tmp, x[i] ) ); + move32(); /* saturation can occur here */ + } +} + + +/*-------------------------------------------------------------------* + * Copy_Scale_sig32_16 + * + * Up/down scale a 32 bits vector and round to 16 bits vector + *-------------------------------------------------------------------*/ +void Copy_Scale_sig32_16( + const Word32 *src, /* i : signal to scale Qx */ + Word16 *dst, /* o : scaled signal Qx */ + Word16 len, /* i : size of x[] Q0 */ + Word16 exp0 ) /* i : exponent: x = round(x << exp) Qx ?exp */ +{ + Word16 i; + Word32 L_temp; + + IF( exp0 == 0 ) + { + FOR( i = 0; i < len; i++ ) + { + *dst++ = round_fx_sat( *src++ ); + move16(); + } + return; + } + + FOR( i = 0; i < len; i++ ) + { + L_temp = L_shl_sat( *src++, exp0 ); + + *dst++ = round_fx_sat( L_temp ); + move16(); + } +} + +/*-------------------------------------------------------------------* + * v_multc_att() + * + * Attenuation of a vector,, attenuation factor in Q15 + *-------------------------------------------------------------------*/ + +void v_multc_att( + const Word16 x[], /* i : Input vector Qx */ + const Word16 att, /* i : Constant Q15, <= MAX_16 */ + Word16 y[], /* o : Output vector that contains att*x */ + const Word16 N /* i : Vector length */ +) +{ + Word16 i; + IF( LT_16( att, 32767 ) ) + { + FOR( i = 0; i < N; i++ ) + { + y[i] = mult_r( x[i], att ); + move16(); + } + } +} /*-------------------------------------------------------------------* + * v_multc_att32() + * + * Attenuation of a vector,, attenuation factor in Q15 + *-------------------------------------------------------------------*/ + +void v_multc_att32( + const Word32 x[], /* i : Input vector Qx */ + const Word16 att, /* i : Constant Q15, <= MAX_16 */ + Word32 y[], /* o : Output vector that contains att*x */ + const Word16 N /* i : Vector length */ +) +{ + Word16 i; + IF( LT_16( att, 32767 ) ) + { + FOR( i = 0; i < N; i++ ) + { + y[i] = Mpy_32_16_r( x[i], att ); + move32(); + } + } +} + +/*-------------------------------------------------------------------* + * v_multc_att3232() + * + * Attenuation of a vector, attenuation factor in Q31 + *-------------------------------------------------------------------*/ + +void v_multc_att3232( + const Word32 x[], /* i : Input vector Qx */ + const Word32 att, /* i : Constant Q32, <= MAX_32 */ + Word32 y[], /* o : Output vector that contains att*x */ + const Word16 N /* i : Vector length */ +) +{ + Word16 i; + IF( LE_32( att, MAX_32 ) ) + { + FOR( i = 0; i < N; i++ ) + { + y[i] = Mpy_32_32_r( x[i], att ); + move32(); + } + } +} + +/*-------------------------------------------------------------------* + * v_L_mult_1616() + * + * Multiplication of two vectors, Output in Word32 + *-------------------------------------------------------------------*/ + +void v_L_mult_1616( + const Word16 x1[], /* i : Input vector 1 */ + const Word16 x2[], /* i : Input vector 2 */ + Word32 y[], /* o : Output vector that contains vector 1 .* vector 2 */ + const Word16 N /* i : Vector length */ +) +{ + Word16 i; + + for ( i = 0; i < N; i++ ) + { + y[i] = L_mult( x1[i], x2[i] ); + move32(); + } + + return; +} + +/*-------------------------------------------------------------------* + * v_L_mult_3216() + * + * Multiplication of two vectors, Output in Word32 + *-------------------------------------------------------------------*/ + +void v_L_mult_3216( + const Word32 x1[], /* i : Input vector 1 */ + const Word16 x2[], /* i : Input vector 2 */ + Word32 y[], /* o : Output vector that contains vector 1 .* vector 2 */ + const Word16 N /* i : Vector length */ +) +{ + Word16 i; + + for ( i = 0; i < N; i++ ) + { + y[i] = Mpy_32_16_1( x1[i], x2[i] ); + move32(); + } + + return; +} + +/*-------------------------------------------------------------------* + * add_vec() + * + * Addition of two vectors sample by sample + *-------------------------------------------------------------------*/ + +void add_vec_fx( + const Word16 x1[], /* i : Input vector 1 */ + const Word16 Qx1, /* i : SCaling of input 1 */ + const Word16 x2[], /* i : Input vector 2 */ + const Word16 Qx2, /* i : SCaling of input 1 */ + Word16 y[], /* o : Output vector that contains vector 1 + vector 2 */ + const Word16 Qy, /* i : SCaling of output 1 */ + const Word16 N /* i : Vector lenght */ +) +{ + Word16 i, Qyx1, Qyx2; +#ifndef ISSUE_1836_replace_overflow_libcom +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move32(); +#endif +#endif + Qyx1 = sub( Qx1, Qy ); + Qyx2 = sub( Qx2, Qy ); + IF( Qyx1 == 0 ) + { + FOR( i = 0; i < N; i++ ) + { +#ifdef ISSUE_1836_replace_overflow_libcom + y[i] = add_sat( x1[i], shr_r_sat( x2[i], Qyx2 ) ); +#else + y[i] = add_o( x1[i], shr_r_sat( x2[i], Qyx2 ), &Overflow ); +#endif + move16(); + } + } + ELSE + { + FOR( i = 0; i < N; i++ ) + { +#ifdef ISSUE_1836_replace_overflow_libcom + y[i] = add_sat( shr_r_sat( x1[i], Qyx1 ), shr_r_sat( x2[i], Qyx2 ) ); //!!sat //!!sat +#else + y[i] = add_o( shr_r_sat( x1[i], Qyx1 ), shr_r_sat( x2[i], Qyx2 ), &Overflow ); +#endif + move16(); + } + } + return; +} + +/*-------------------------------------------------------------------* + * Add_flt32_flt32 + * + * Add two Pseudo Float Value that are 32 Bits Mantisa and 16 Bits Exp + *-------------------------------------------------------------------*/ +Word32 Add_flt32_flt32( /* o: Result (Normalized) */ + Word32 a, /* i: 1st Value */ + Word16 exp_a, /* i: Exponent of 1st Value (Q of Value) */ + Word32 b, /* i: 2nd Value */ + Word16 exp_b, /* i: Exponent of 2nd Value (Q of Value) */ + Word16 *exp_out /* o: Exponent of Result */ +) +{ + Word16 temp, temp2; + Word32 L_temp; + + /* Subract 1 to further divide by 2 to avoid overflow on L_add */ + temp = sub( s_min( exp_a, exp_b ), 1 ); + + /* Put both to same exponent */ + exp_a = sub( exp_a, temp ); + a = L_shr( a, exp_a ); + exp_b = sub( exp_b, temp ); + b = L_shr( b, exp_b ); + + /* add them together */ + L_temp = L_add( a, b ); + temp2 = norm_l( L_temp ); + + *exp_out = add( temp, temp2 ); + move16(); + + return L_shl( L_temp, temp2 ); +} + +/*-------------------------------------------------------------------* + * Mul_flt32_Q15 + * + * Multiply one Pseudo Float Value (32 Bits Mantisa and 16 Bits Exp) + * with a Q15 value + *-------------------------------------------------------------------*/ +Word32 Mul_flt32_Q15( /* o: Result (Normalized) */ + Word32 value, /* i: Pseudo_float Value */ + Word16 *exp_v, /*i/o: Exponent of Value (Q of Value) */ + Word16 frac /* i: Q15 value */ +) +{ + Word16 temp; + Word32 L_temp; + + L_temp = Mult_32_16( value, frac ); + temp = norm_l( L_temp ); + + *exp_v = add( temp, *exp_v ); + move16(); + + return L_shl( L_temp, temp ); +} + +/*-------------------------------------------------------------------* + * Div_flt32_flt32 + * + * Divide one Pseudo Float Value (32 Bits Mantisa and 16 Bits Exp) + * by another one + *-------------------------------------------------------------------*/ +Word32 Div_flt32_flt32( /* o: Result (Normalized) */ + Word32 a, /* i: 1st Value */ + Word16 exp_a, /* i: Exponent of 1st Value (Q of Value) */ + Word32 b, /* i: 2nd Value */ + Word16 exp_b, /* i: Exponent of 2nd Value (Q of Value) */ + Word16 *exp_out /* o: Exponent of Result */ +) +{ + Word16 temp, temp2; + Word32 L_temp; + + temp = div_s( 16384, round_fx( b ) ); + L_temp = Mult_32_16( a, temp ); + temp2 = sub( 31 - 1, exp_b ); + temp2 = add( temp2, exp_a ); + + temp = norm_l( L_temp ); + + *exp_out = add( temp, temp2 ); + move16(); + + return L_shl( L_temp, temp ); +} + + +/*-------------------------------------------------------------------* + * Calc_Energy_Autoscaled + * + * Calculate Energy with overflow protection + *-------------------------------------------------------------------*/ +Word32 Calc_Energy_Autoscaled( /* o: Result (Energy) */ + const Word16 *signal, /* i: Signal */ + Word16 signal_exp, /* i: Exponent of Signal (Q of Signal) */ + Word16 len, /* i: Frame Length */ + Word16 *energy_exp /* o: Exponent of Energy (Q of Energy) */ +) +{ + Word16 temp, temp2; + Word32 L_temp, L_Energy; + Word16 i, j; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move32(); +#endif + + Overflow = 0; + move16(); + + temp2 = 0; + move16(); + L_Energy = L_deposit_l( 1 ); + j = s_and( 7, len ); + FOR( i = 0; i < j; i++ ) + { + /* divide by 2 so energy will be divided by 4 */ +#ifdef ISSUE_1836_replace_overflow_libcom + temp = mult_r( *signal++, 16384 ); +#else + temp = mult_ro( *signal++, 16384, &Overflow ); +#endif + L_Energy = L_mac0_o( L_Energy, temp, temp, &Overflow ); + } + FOR( i = j; i < len; i += 8 ) /* Process 8 Samples at a time */ + { + /* divide by 2 so energy will be divided by 4 */ + temp = mult_ro( *signal++, 16384, &Overflow ); + L_temp = L_mult0( temp, temp ); + FOR( j = 1; j < 8; j++ ) + { +#ifdef ISSUE_1836_replace_overflow_libcom + temp = mult_r( *signal++, 16384 ); +#else + temp = mult_ro( *signal++, 16384, &Overflow ); +#endif + L_temp = L_mac0_o( L_temp, temp, temp, &Overflow ); + } + /*Overfloe will never happen because temp2 is always positive*/ + L_temp = L_shr( L_temp, temp2 ); + /* Here we try the addition just to check if we can sum + the energy of the small (8 Iterations) loop with the + total energy calculated so far without an overflow. + The result is discarded. If there is an overflow both + energies are div by 2. Otherwise, nothing is done. + After the 'IF', the sum is done again and will always + be without an overflow. */ + L_add_o( L_Energy, L_temp, &Overflow ); + IF( Overflow != 0 ) + { + L_Energy = L_shr( L_Energy, 1 ); + L_temp = L_shr( L_temp, 1 ); + temp2 = add( temp2, 1 ); + Overflow = 0; + move16(); + } + L_Energy = L_add_o( L_Energy, L_temp, &Overflow ); + } + /* Calc Final Exponent (sub 2 because of the mult_r by 16384 that already divs the ener by 4) */ + temp2 = sub( sub( shl( signal_exp, 1 ), temp2 ), 2 ); + + *energy_exp = temp2; + move16(); + + return L_Energy; +} + +Word16 Find_Max_Norm16( const Word16 *src, Word16 len ) +{ + Word16 i; + Word16 max16; + + /* it starts at '0' and not '1' like in Find_Max_Norm32() */ + /* and that is necessary. */ + max16 = 0; + move16(); + + FOR( i = 0; i < len; i++ ) + { + max16 = s_max( max16, abs_s( *src++ ) ); + } + + return norm_s( max16 ); +} + +Word16 Find_Max_Norm32( const Word32 *src, Word16 len ) +{ + Word16 i; + Word32 max32; + + max32 = L_deposit_l( 1 ); + + FOR( i = 0; i < len; i++ ) + { + max32 = L_max( max32, L_abs( *src++ ) ); + } + + return norm_l( max32 ); +} + +/*-------------------------------------------------------------------* + * Sqrt_Ratio32 + * + * Calculate Sqrt of Val1/Val2 + *-------------------------------------------------------------------*/ +Word32 Sqrt_Ratio32( /* o: Result in Q31 */ + Word32 L_val1, /* i: Mantisa of Val1 */ + Word16 exp1, /* i: Exp of Val1 (>0: Val was Left Shifted, <0:Right Shifted) */ + Word32 L_val2, /* i: Mantisa of Val2 */ + Word16 exp2, /* i: Exp of Val2 (same as exp1) */ + Word16 *exp /* o: Exp of Result (# of 'L_shl' Req to get to Final Value) */ +) +{ + Word16 temp; + + /* Normalize Energy #1 */ + temp = norm_l( L_val1 ); + L_val1 = L_shl( L_val1, temp ); + /* Adjust Exponent of Energy #1 */ + exp1 = add( exp1, temp ); + + /* Normalize Energy #2 */ + temp = norm_l( L_val2 ); + L_val2 = L_shl( L_val2, temp ); + /* Adjust Exponent of Energy #1 */ + exp2 = add( exp2, temp ); + + /* Prepare for Inverse */ + temp = round_fx_sat( L_val1 ); + temp = div_s( 16384, temp ); + /* Mult Now */ + L_val2 = Mult_32_16( L_val2, temp ); + exp1 = add( sub( exp2, exp1 ), 15 * 2 ); + + /* Here Result of ('L_val2' / 2^'exp2') / ('L_val1' / 2^'exp1') is */ + /* 'L_val2' / 2^'exp1' */ + /* Which is val2/val1 instead of val1/val2 because we will use Inverted Square Root */ + /* Normalize before Square Root */ + temp = norm_l( L_val2 ); + L_val2 = L_shl( L_val2, temp ); + exp1 = add( temp, exp1 ); + /* Do Sqrt */ + temp = sub( 31, exp1 ); + L_val1 = Isqrt_lc( L_val2, &temp ); + + *exp = temp; + move16(); + + return L_val1; +} + +Word16 Invert16( /* result in Q'15 + 'exp' */ + Word16 val, + Word16 *exp ) +{ + Word16 temp; + + /* prevent 0 input */ + val = s_max( val, 1 ); + /* Normalize Value */ + temp = norm_s( val ); + val = shl( val, temp ); + + *exp = sub( sub( 15 - 1, *exp ), temp ); + move16(); /* -1 because of 0x4000 is 1.0 in Q14 (and not Q15) */ + + temp = div_s( 0x4000, val ); + + return temp; +} + +Word16 find_rem( Word16 n, Word16 m, Word16 *r ) +{ + Word16 i, q1, q2, qd; + Word32 Ltemp2; + Word32 Lacc; + + test(); + test(); + IF( n <= 0 || m <= 0 || n < m ) + { + *r = n; + move16(); + return ( 0 ); + } + + q1 = norm_s( n ); + q1 = sub( q1, 1 ); + Lacc = L_deposit_h( shl( n, q1 ) ); + qd = sub( q1, 1 ); + q2 = norm_s( m ); + q2 = sub( q2, 1 ); + Ltemp2 = L_deposit_h( shl( m, q2 ) ); + qd = sub( q2, qd ); + q2 = add( q2, 1 ); + + FOR( i = 0; i < qd; i++ ) + { + Lacc = L_sub( Lacc, Ltemp2 ); + IF( Lacc >= 0 ) + { + Lacc = L_add( L_shl( Lacc, 1 ), 1 ); + } + ELSE + { + Lacc = L_add( Lacc, Ltemp2 ); + Lacc = L_shl( Lacc, 1 ); + } + } + q1 = extract_l( Lacc ); + Ltemp2 = L_shr( Lacc, q2 ); + *r = extract_h( Ltemp2 ); + move16(); + return ( q1 ); +} + + +Word32 find_remd( Word32 n, Word32 m, Word32 *r ) +{ + Word16 i, q1, q2, qd; + Word32 Ltemp2, qo; + Word32 Lacc; + + test(); + test(); + IF( n <= 0 || m <= 0 || n < m ) + { + *r = n; + move16(); + return ( 0 ); + } + + q1 = norm_l( n ); + q1 = sub( q1, 1 ); + Lacc = L_shl( n, q1 ); + qd = sub( q1, 1 ); + q2 = norm_l( m ); + q2 = sub( q2, 1 ); + Ltemp2 = L_shl( m, q2 ); + qd = sub( q2, qd ); + q2 = add( q2, 1 ); + qo = 0; + move16(); + + FOR( i = 0; i < qd; i++ ) + { + Lacc = L_sub( Lacc, Ltemp2 ); + qo = L_shl( qo, 1 ); + IF( Lacc >= 0 ) + { + Lacc = L_shl( Lacc, 1 ); + qo = L_add( qo, 1 ); + } + ELSE + { + Lacc = L_add( Lacc, Ltemp2 ); + Lacc = L_shl( Lacc, 1 ); + } + } + *r = L_shr( Lacc, q2 ); + move16(); + return ( qo ); +} + +Word16 rint_new_fx( + Word32 x /*Q16 */ +) +{ + Word16 a; + Word32 L_tmp; + Word16 frac, tmp; + + /* middle value point test */ + frac = lshr( extract_l( x ), 1 ); /*Q15 */ + tmp = sub( frac, 0x4000 ); + + IF( !tmp ) + { + a = add( extract_h( x ), 1 ); + + IF( s_and( a, 1 ) == 0 ) + { + return a; + } + IF( s_and( a, 1 ) != 0 ) + { + return extract_h( x ); + } + return extract_h( x ); + } + ELSE + { + L_tmp = L_add( x, 32768 ); /*Q16 */ + return extract_h( L_tmp ); + } +} + + +/*===================================================================*/ +/* FUNCTION : erb_diff_search_fx () */ +/*-------------------------------------------------------------------*/ +/* PURPOSE : erb amplitude VQ search for QPPP */ +/*-------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16 []) prev_erb : Previous erb amplitude, Q13 */ +/* _ (Word16 []) curr_erb : Current erb amplitude, Q13 */ +/* _ (Word16 []) dif_erb: erb differential, Q13 */ +/* _ (Word16 []) pow_spec : LPC power spectrum, Q7 */ +/* _ (Word16 [][]) cb_fx : differential erb codebook, Q13 */ +/* _ (Word16) cb_size : codebook size */ +/* _ (Word16) cb_dim : codebook dimension */ +/* _ (Word16) offset : index to current segment of erb array */ +/* for quantization */ +/*-------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ None */ +/*-------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ None */ +/*-------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ (Word16) index: best codebook index */ +/*-------------------------------------------------------------------*/ +/* CALLED FROM : TX */ +/*===================================================================*/ + +Word16 erb_diff_search_fx( Word16 *prev_erb, const Word16 *curr_erb, Word16 *dif_erb, Word16 *pow_spec, const Word16 *cb_fx, Word16 cb_size, Word16 cb_dim, Word16 offset ) +{ + Word16 i, j, mmseindex; + Word16 dh, dl; + Word32 mmse; + Word32 Ltemp1; + Word32 Lacc; + + mmse = EVS_LW_MAX; + move32(); + mmseindex = -1; + move16(); + FOR( j = 0; j < cb_size; j++ ) + { + + Lacc = L_deposit_l( 0 ); + FOR( i = 0; i < cb_dim; i++ ) + { + IF( add_sat( cb_fx[j * cb_dim + i], prev_erb[i + offset] ) < 0 ) + { + Ltemp1 = L_mult( curr_erb[i + offset], curr_erb[i + offset] ); /* Q27 */ + dh = extract_h( Ltemp1 ); + dl = extract_l( Ltemp1 ); + IF( dl < 0 ) + { + Ltemp1 = L_shl( L_add( 65536, dl ), 14 ); /* */ + Ltemp1 = Mult_32_16( Ltemp1, pow_spec[i + offset] ); + Ltemp1 = L_shl( Ltemp1, 1 ); + } + ELSE + { + Ltemp1 = (Word32) L_mult0( pow_spec[i + offset], dl ); + } + Ltemp1 = L_add( L_shr( Ltemp1, 15 ), L_mult( pow_spec[i + offset], dh ) ); + } + ELSE + { + dh = sub_sat( dif_erb[i + offset], cb_fx[j * cb_dim + i] ); /* Q13 */ + Ltemp1 = L_mult_sat( dh, dh ); /* Q27 */ + dh = extract_h( Ltemp1 ); + dl = extract_l( Ltemp1 ); + + IF( dl < 0 ) + { + Ltemp1 = L_shl( L_add( 65536, dl ), 14 ); /* */ + Ltemp1 = Mult_32_16( Ltemp1, pow_spec[i + offset] ); + Ltemp1 = L_shl( Ltemp1, 1 ); + } + ELSE + { + Ltemp1 = (Word32) L_mult0( pow_spec[i + offset], dl ); /* Q33 */ + } + + Ltemp1 = L_add( L_shr( Ltemp1, 15 ), L_mult( pow_spec[i + offset], dh ) ); /* Q18 */ + } + + IF( LT_16( cb_fx[j * cb_dim + i], dif_erb[i + offset] ) ) + { + dh = extract_h( Ltemp1 ); + dl = extract_l( Ltemp1 ); + IF( dl < 0 ) + { + Ltemp1 = L_shl( L_add( 65536, dl ), 14 ); /* */ + Ltemp1 = Mult_32_16( Ltemp1, 29491 ); + Ltemp1 = L_shl( Ltemp1, 1 ); + } + ELSE + { + Ltemp1 = (Word32) L_mult0( 29491, dl ); /* 29491=0.9 in Q15 */ + } + Ltemp1 = L_add( L_shr( Ltemp1, 15 ), L_mult( dh, 29491 ) ); + } + Lacc = L_add( Lacc, Ltemp1 ); /* Q18 */ + } + + IF( LT_32( Lacc, mmse ) ) + { + mmse = L_add( Lacc, 0 ); + mmseindex = j; + move16(); + } + } + + return ( mmseindex ); +} +void Acelp_dec_total_exc( + Word16 *exc_fx, /* i/o: adapt. excitation exc */ + Word16 *exc2_fx, /* i/o: adapt. excitation/total exc */ + const Word16 gain_code16, /* i : Gain code Q0 */ + const Word16 gain_pit_fx, /* i ; Pitch gain in Q14 */ + const Word16 i_subfr, /* i ; subfr */ + const Word16 *code_fx, /* i : code in Q9 */ + const Word16 L_subfr /* i : Subframne lenght */ +) +{ + Word16 i; + Word32 L_tmp; + + FOR( i = 0; i < L_subfr; i++ ) + { + L_tmp = L_shl_sat( L_mult( gain_pit_fx, exc_fx[i + i_subfr] ), 1 ); /*Q16+Q_exc*/ + exc2_fx[i + i_subfr] = round_fx_sat( L_tmp ); /*Q_exc*/ + L_tmp = L_add_sat( L_tmp, L_shl_sat( L_mult( gain_code16, code_fx[i] ), 6 ) ); /*Q16+Q_exc*/ + exc_fx[i + i_subfr] = round_fx_sat( L_tmp ); /*Q_exc*/ + move16(); + move16(); + } +} + +/*-------------------------------------------------------------------* + * UL_inverse + * + * Calculate inverse of UL_val. Output in Q_exp. + *-------------------------------------------------------------------*/ +UWord32 UL_inverse( const UWord32 UL_val, Word16 *exp ) +{ + UWord32 UL_tmp; + + *exp = norm_ul( UL_val ); + move16(); + UL_tmp = UL_lshl( UL_val, *exp ); /* Q32 */ + + *exp = add( 32, sub( 31, *exp ) ); + move16(); + + return UL_div( 0x80000000, UL_tmp ); +} + +/*-------------------------------------------------------------------* + * UL_div + * + * Calculate UL_num/UL_den. UL_num assumed to be Q31, UL_den assumed + * to be Q32, then result is in Q32. + *-------------------------------------------------------------------*/ +UWord32 UL_div( const UWord32 UL_num, const UWord32 UL_den ) +{ + UWord32 UL_e, UL_Q; + UWord32 UL_msb, UL_lsb; + Word16 i; + + UL_e = UL_subNsD( 0xffffffff, UL_den ); + UL_Q = UL_num; + move32(); + + FOR( i = 0; i < 5; i++ ) + { + Mpy_32_32_uu( UL_Q, UL_e, &UL_msb, &UL_lsb ); /*31+32-32=31 */ + UL_Q = UL_addNsD( UL_Q, UL_msb ); + Mpy_32_32_uu( UL_e, UL_e, &UL_e, &UL_lsb ); /*32+32-32=32 */ + } + + return UL_Q; +} + +/*----------------------------------------------------------------------------- + * ratio() + * + * Divide the numerator by the denominator. + *----------------------------------------------------------------------------*/ +Word16 ratio( const Word32 numer, const Word32 denom, Word16 *expo ) +{ + Word16 expNumer, expDenom; + Word16 manNumer, manDenom; + Word16 quotient; + + expDenom = norm_l( denom ); /* exponent */ + manDenom = extract_h( L_shl( denom, expDenom ) ); /* mantissa */ + expNumer = norm_l( numer ); /* exponent */ + manNumer = extract_h( L_shl( numer, expNumer ) ); /* mantissa */ + manNumer = shr( manNumer, 1 ); /* Ensure the numerator < the denominator */ + quotient = div_s( manNumer, manDenom ); /* in Q14 */ + + *expo = sub( expNumer, expDenom ); + move16(); + return quotient; /* Q14 */ +} + +/*-----------------------------------------------------------------------* + * Function hp400_12k8() * + * * + * 2nd order Cheb2 high pass filter with cut off frequency at 400 Hz. * + * Optimized for fixed-point to get the following frequency response : * + * * + * frequency : 0Hz 100Hz 200Hz 300Hz 400Hz 630Hz 1.5kHz 3kHz * + * dB loss : -infdB -30dB -20dB -10dB -3dB +6dB +1dB 0dB * + * * + * Algorithm : * + * * + * y[i] = b[0]*x[i] + b[1]*x[i-1] + b[2]*x[i-2] * + * + a[1]*y[i-1] + a[2]*y[i-2]; * + * * + * short b[3] = {3660, -7320, 3660}; in Q12 * + * short a[3] = {4096, 7320, -3540}; in Q12 * + * * + * float --> b[3] = {0.893554687, -1.787109375, 0.893554687}; * + * a[3] = {1.000000000, 1.787109375, -0.864257812}; * + *-----------------------------------------------------------------------*/ +void hp400_12k8_fx( + Word16 signal[], /* i/o: input signal / output is divided by 16 */ + const Word16 lg, /* i : lenght of signal */ + Word16 mem[] /* i/o: filter memory [6] */ +) +{ + Word16 i; + Word16 y1_hi, y1_lo; + Word32 L_tmp, L_tmp2, L_tmp3; + + y1_hi = mem[2]; + move16(); + y1_lo = mem[3]; + move16(); + + L_tmp3 = L_mac( 16384L, mem[1], a_hp400_fx[2] ); /* rounding to maximize precision */ + L_tmp3 = L_mac( L_tmp3, y1_lo, a_hp400_fx[1] ); + L_tmp3 = L_shr( L_tmp3, 15 ); + L_tmp2 = L_mac( L_tmp3, mem[0], a_hp400_fx[2] ); + L_tmp2 = L_mac( L_tmp2, mem[5], b_hp400_fx[2] ); + L_tmp2 = L_mac( L_tmp2, mem[4], b_hp400_fx[1] ); + L_tmp3 = L_mult( mem[4], b_hp400_fx[2] ); + + mem[5] = signal[lg - 2]; + move16(); + FOR( i = 1; i < lg; i++ ) + { + /* y[i] = b[0]*x[i] + b[1]*x[i-1] + b[2]*x[i-2] */ + /* + a[1]*y[i-1] + a[2] * y[i-2] */ + + L_tmp = L_mac( L_tmp2, y1_hi, a_hp400_fx[1] ); + L_tmp = L_mac( L_tmp, *signal, b_hp400_fx[0] ); + + L_tmp = L_shl( L_tmp, 1 ); /* coeff Q12 --> Q13 */ + + L_tmp2 = L_mac( L_tmp3, y1_hi, a_hp400_fx[2] ); + L_tmp2 = L_mac( L_tmp2, *signal, b_hp400_fx[1] ); + L_tmp3 = L_mac( 16384L, y1_lo, a_hp400_fx[2] ); /* rounding to maximize precision */ + + y1_lo = L_Extract_lc( L_tmp, &y1_hi ); + + L_tmp3 = L_mac( L_tmp3, y1_lo, a_hp400_fx[1] ); + L_tmp3 = L_shr( L_tmp3, 15 ); + + L_tmp2 = L_add( L_tmp3, L_tmp2 ); + + L_tmp3 = L_mult( *signal, b_hp400_fx[2] ); + + /* signal is divided by 16 to avoid overflow in energy computation */ + *signal++ = round_fx( L_tmp ); + move16(); + } + + /* y[i] = b[0]*x[i] + b[1]*x[i-1] + b[2]*x[i-2] */ + /* + a[1]*y[i-1] + a[2] * y[i-2] */ + + L_tmp = L_mac( L_tmp2, y1_hi, a_hp400_fx[1] ); + + mem[4] = *signal; + move16(); + L_tmp = L_mac( L_tmp, mem[4], b_hp400_fx[0] ); + + L_tmp = L_shl( L_tmp, 1 ); /* coeff Q12 --> Q13 */ + + mem[0] = y1_hi; + move16(); + mem[1] = y1_lo; + move16(); + L_Extract( L_tmp, &mem[2], &mem[3] ); + + /* signal is divided by 16 to avoid overflow in energy computation */ + *signal++ = round_fx( L_tmp ); + move16(); + + return; +} + +void hp400_12k8_ivas_fx( + Word16 signal[], /* i/o: input signal / output is divided by 16 */ + const Word16 lg, /* i : lenght of signal */ + Word16 mem[] /* i/o: filter memory [6] */ +) +{ + Word16 i; + Word16 x0, x1, x2; + Word32 L_tmp, yy1, y2; + + yy1 = L_Comp( mem[2], mem[3] ); /* Q_syn + 13 */ + y2 = L_Comp( mem[0], mem[1] ); /* Q_syn + 13 */ + x0 = mem[4]; /* Q_syn */ + move16(); + x1 = mem[5]; /* Q_syn */ + move16(); + + FOR( i = 0; i < lg; i++ ) + { + x2 = x1; /* Q_syn */ + move16(); + x1 = x0; /* Q_syn */ + move16(); + x0 = signal[i]; /* Q_syn */ + move16(); + + L_tmp = Mpy_32_16_1( yy1, a_hp400_ivas_fx[1] ); /*yy1 * a_hp400[1]*/ /* Qx(Q_of_yy1) + 10 ---->( (Q_syn+13) + 12 - 15)*/ + L_tmp = Madd_32_16( L_tmp, y2, a_hp400_ivas_fx[2] ); /*y2 * a_hp400[2]*/ /* Qx + 10 ---->( (Q_syn+13) + 12 - 15)*/ + L_tmp = L_shl( L_tmp, 3 ); /* shifting by 3 to maintain same Q (Q_syn+13) */ + + L_tmp = L_mac( L_tmp, x0, b_hp400_fx[0] ); /* Q_syn + 13 */ + L_tmp = L_mac( L_tmp, x1, b_hp400_fx[1] ); /* Q_syn + 13 */ + L_tmp = L_mac( L_tmp, x2, b_hp400_fx[2] ); /* Q_syn + 13 */ + + y2 = yy1; /* Q_syn + 13 */ + move32(); + yy1 = L_tmp; /* Q_syn + 13 */ + move32(); + + signal[i] = round_fx( L_tmp ); /* Q_syn - 3 */ + move16(); + } + + L_Extract( yy1, &mem[2], &mem[3] ); + L_Extract( y2, &mem[0], &mem[1] ); + mem[4] = x0; /* Q_syn */ + mem[5] = x1; /* Q_syn */ + move16(); + move16(); + return; +} + +Word16 dot_prod_satcontr( const Word16 *x, const Word16 *y, Word16 qx, Word16 qy, Word16 *qo, Word16 len ) +{ + Word16 tmp_tab_x[L_FRAME16k]; + Word16 tmp_tab_y[L_FRAME16k]; + Word16 shift, q, ener, i; + Word32 L_tmp; + Word16 *pt1, *pt2; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move32(); +#endif + + + Copy( x, tmp_tab_x, len ); /* OPTIMIZE !!!!! the copy into local table is not necessary */ + Copy( y, tmp_tab_y, len ); /* could be reworked to do a 1st iteration with the original x[] and y[] */ + /* then check if there is an overflow and do a more complex 2nd, 3rd, ... processing */ + shift = 0; + move16(); + BASOP_SATURATE_WARNING_OFF_EVS + DO + { + Overflow = 0; + move16(); + L_tmp = L_shl_o( 1, s_max( sub( add( add( qx, qy ), 7 ), shift ), 0 ), &Overflow ); + pt1 = tmp_tab_x; + pt2 = tmp_tab_y; + FOR( i = 0; i < len; i++ ) + { + L_tmp = L_mac0_o( L_tmp, *pt1++, *pt2++, &Overflow ); /*Q(qx+qy-shift) */ + } + + IF( Overflow != 0 ) + { + Scale_sig( tmp_tab_x, len, -2 ); + Scale_sig( tmp_tab_y, len, -2 ); + shift = add( shift, 4 ); + } + } + WHILE( Overflow != 0 ); + BASOP_SATURATE_WARNING_ON_EVS + + q = norm_l( L_tmp ); + L_tmp = L_shl( L_tmp, q ); /*Q(qx+qy-shift+q) */ + ener = extract_h( L_tmp ); /*Q(qx+qy-shift+q-16) */ + q = add( q, add( qx, qy ) ); + *qo = sub( q, add( shift, 16 ) ); + move16(); + return ener; +} + + +/* + * E_UTIL_f_convolve + * + * Parameters: + * x I: input vector <14bits + * h I: impulse response (or second input vector) (1Q14) + * y O: output vetor (result of convolution) + * + * Function: + * Perform the convolution between two vectors x[] and h[] and + * write the result in the vector y[]. All vectors are of length L. + * Only the first L samples of the convolution are considered. + * Vector size = L_SUBFR + * + * Returns: + * void + */ +void E_UTIL_f_convolve( const Word16 x[], const Word16 h[], Word16 y[], const Word16 size ) +{ + Word16 i, n; + Word32 L_sum; + Word64 L64_sum; + + FOR( n = 0; n < size; n++ ) + { + L64_sum = 0; + move64(); + FOR( i = 0; i < n; i++ ) + { + L64_sum = W_mac_16_16( L64_sum, x[i], h[n - i] ); + } + L_sum = W_sat_l( L64_sum ); + y[n] = mac_r( L_sum, x[i], h[0] ); + move16(); + } + return; +} + +/*----------------------------------------------------------------------------- + * floating_point_add: + * + * Add two floating point numbers: x <- x + y. + *----------------------------------------------------------------------------*/ +void floating_point_add( + Word32 *mx, /* io: mantissa of the addend Q31 */ + Word16 *ex, /* io: exponent of the addend Q0 */ + const Word32 my, /* i: mantissa of the adder Q31 */ + const Word16 ey /* i: exponent of the adder Q0 */ +) +{ + Word32 accX, accY; + Word16 align, expo; + /* NB: This function will not work properly if the mantissa is zero and the exponent is not 32. + It is up to the caller function to avoid this condition. */ + /* Ensure 1 bit headroom before addition. */ + accX = L_shr( *mx, 1 ); + accY = L_shr( my, 1 ); + /* First, align the Q-points of the two operands. Then, add. */ + align = sub( *ex, ey ); + + IF( align < 0 ) + { + accX = L_add( accX, L_shl( accY, align ) ); + } + ELSE + { + accX = L_add( accY, L_shr( accX, align ) ); + *ex = ey; + move16(); + } + /* Normalize the result and update the mantissa and exponent. */ + expo = norm_l( accX ); + *mx = L_shl( accX, expo ); + *ex = sub( add( *ex, expo ), 1 ); /* Subtract 1 due to 1-bit down-shift above ensuring 1 bit headroom before addition. */ + move32(); + move16(); + return; +} + +/*-------------------------------------------------------------------* + * delay_signal_fx() + * + * Delay buffer by defined number of samples + *-------------------------------------------------------------------*/ + +void delay_signal_fx( + Word16 x[], /* i/o: signal to be delayed */ + const Word16 len, /* i : length of the input signal */ + Word16 mem[], /* i/o: synchronization memory */ + const Word16 delay /* i : delay in samples */ +) +{ + Word16 tmp_buffer[L_FRAME48k]; + + Copy( mem, tmp_buffer, delay ); + Copy( x + sub( len, delay ), mem, delay ); + Copy( x, x + delay, sub( len, delay ) ); + Copy( tmp_buffer, x, delay ); + + return; +} + +void delay_signal32_fx( + Word32 x[], /* i/o: signal to be delayed */ + const Word16 len, /* i : length of the input signal */ + Word32 mem[], /* i/o: synchronization memory */ + const Word16 delay /* i : delay in samples */ +) +{ + Word32 tmp_buffer[L_FRAME48k]; + + Copy32( mem, tmp_buffer, delay ); + Copy32( x + sub( len, delay ), mem, delay ); + Copy32( x, x + delay, sub( len, delay ) ); + Copy32( tmp_buffer, x, delay ); + + return; +} + +void delay_signal_q_adj_fx( + Word32 x[], /* i/o: signal to be delayed */ + const Word16 len, /* i : length of the input signal */ + Word32 mem[], /* i/o: synchronization memory */ + const Word16 delay, /* i : delay in samples */ + const Word16 q_x, + const Word16 q_mem ) +{ + + Word32 tmp_buffer[L_FRAME48k]; + + Copy32( mem, tmp_buffer, delay ); + Copy32( x + sub( len, delay ), mem, delay ); + Copy32( x, x + delay, sub( len, delay ) ); + + + IF( EQ_16( q_x, q_mem ) ) + { + Copy32( tmp_buffer, x, delay ); + } + ELSE + { + v_shr( tmp_buffer, sub( q_mem, q_x ), x, delay ); + } + + return; +} + +void v_add_fx( + const Word32 x1[], /* i : Input vector 1 */ + const Word32 x2[], /* i : Input vector 2 */ + Word32 y[], /* o : Output vector that contains vector 1 + vector 2 */ + const Word16 N /* i : Vector length */ +) +{ + Word16 i; + + FOR( i = 0; i < N; i++ ) + { + y[i] = L_add_sat( x1[i], x2[i] ); + move32(); + } + + return; +} +Word16 floor_log_2( Word32 num ) +{ + + IF( num == 0 ) + { + return 0; + } + + return ( sub( 30, norm_l( num ) ) ); +} + +void v_shr( + const Word32 x[], /* i : Input vector */ + const Word16 shift, /* i : Constant */ + Word32 y[], /* o : Output vector that contains x >> shift */ + const Word16 N /* i : Vector length */ +) +{ + Word16 i; + + FOR( i = 0; i < N; i++ ) + { + y[i] = L_shr( x[i], shift ); + move32(); + } + + return; +} + +void v_shr_16( + const Word16 x[], /* i : Input vector */ + const Word16 shift, /* i : Constant */ + Word16 y[], /* o : Output vector that contains x >> shift */ + const Word16 N /* i : Vector length */ +) +{ + Word16 i; + + FOR( i = 0; i < N; i++ ) + { + y[i] = shr( x[i], shift ); + move16(); + } + + return; +} + +/*---------------------------------------------------------------------* + * lin_interp_fx() + * + * Linearly maps x from source range to the target range + *---------------------------------------------------------------------*/ + +/*! r: mapped output value */ +Word16 lin_interp_fx( + const Word16 x, /* i : Q15 the value to be mapped */ + const Word16 x1, /* i : Q15 source range interval: low end */ + const Word16 y1, /* i : Q15 source range interval: high end */ + const Word16 x2, /* i : Q15 target range interval: low */ + const Word16 y2, /* i : Q15 target range interval: high */ + const Word16 flag_sat /* i : flag to indicate whether to apply saturation */ +) +{ + IF( sub( x2, x1 ) == 0 ) + { + return y1; + } + ELSE IF( flag_sat ) + { + IF( GE_16( x, s_max( x1, x2 ) ) ) + { + IF( GT_16( x1, x2 ) ) + { + return y1; + } + ELSE + { + return y2; + } + } + ELSE IF( LE_16( x, s_min( x1, x2 ) ) ) + { + IF( LT_16( x1, x2 ) ) + { + return y1; + } + ELSE + { + return y2; + } + } + } + + return add_sat( y1, mult( sub( x, x1 ), div_s( sub( y2, y1 ), sub( x2, x1 ) ) ) ); +} + + +Word16 lin_interp_ivas_fx( + const Word16 x, /* i : Q15 the value to be mapped */ + const Word16 x1, /* i : Q15 source range interval: low end */ + const Word16 y1, /* i : Q15 source range interval: high end */ + const Word16 x2, /* i : Q15 target range interval: low */ + const Word16 y2, /* i : Q15 target range interval: high */ + const Word16 flag_sat /* i : flag to indicate whether to apply saturation */ +) +{ + IF( EQ_16( sub( x2, x1 ), 0 ) ) + { + return y1; + } + ELSE IF( flag_sat ) + { + IF( GE_16( x, s_max( x1, x2 ) ) ) + { + return GT_16( x1, x2 ) ? y1 : y2; + } + ELSE IF( LE_16( x, s_min( x1, x2 ) ) ) + { + return LT_16( x1, x2 ) ? y1 : y2; + } + } + Word16 div_res_e; + Word16 div_res = BASOP_Util_Divide1616_Scale( sub( y2, y1 ), sub( x2, x1 ), &div_res_e ); + // div_res = shl( div_res, div_res_e ); + return add_sat( y1, round_fx( L_shl( L_mult( sub( x, x1 ), div_res ), div_res_e ) ) ); +} + +/*--------------------------------------------------------------------- + * sign_l() + * + *---------------------------------------------------------------------*/ + +/*! r: sign of x (+1/-1) */ +Word32 sign_l( + const Word32 x /* i : input value of x */ +) +{ + IF( x < 0 ) + { + return MIN_32; + } + ELSE + { + return MAX_32; + } +} + +void v_mult16_fixed( + const Word16 x1[], /* i : Input vector 1 */ + const Word16 x2[], /* i : Input vector 2 */ + Word16 y[], /* o : Output vector that contains vector 1 .* vector 2 */ + const Word16 N /* i : Vector length */ +) +{ + Word16 i; + + FOR( i = 0; i < N; i++ ) + { + y[i] = mult_r( x1[i], x2[i] ); + move16(); + } + + return; +} + +/*---------------------------------------------------------------------* + * set_zero_fx() + * + * Set a vector vec[] of dimension lvec to zero + *---------------------------------------------------------------------*/ + +void set_zero_fx( + Word32 *vec, /* o : input vector */ + const Word16 lvec /* i : length of the vector */ +) +{ + Word16 i; + + FOR( i = 0; i < lvec; i++ ) + { + *vec++ = 0; + move32(); + } + + return; +} +void set_zero2_fx( + Word32 *vec, /* o : input vector */ + const Word32 lvec /* i : length of the vector */ +) +{ + Word32 i; + + FOR( i = 0; i < lvec; i++ ) + { + *vec++ = 0; + move32(); + } + + return; +} + +void set16_zero_fx( + Word16 *vec, /* o : input vector */ + const Word16 lvec /* i : length of the vector */ +) +{ + Word16 i; + + FOR( i = 0; i < lvec; i++ ) + { + *vec++ = 0; + move16(); + } + + return; +} + +UWord32 mvl2s_r( + const Word32 x[], /* i : input vector */ + const Word16 q_x, + Word16 y[], /* o : output vector */ + const Word16 n /* i : vector size */ +) +{ + Word16 i; + Word32 temp; + UWord32 noClipping = 0; + move32(); + + IF( n <= 0 ) + { + /* cannot transfer vectors with size 0 */ + return 0; + } + + IF( (void *) y <= (const void *) x ) + { + Word32 tempd = L_shl( 1, sub( q_x, 1 ) ); + FOR( i = 0; i < n; i++ ) + { + temp = L_add( x[i], tempd ); + temp = L_shr( temp, q_x ); + + IF( GT_32( temp, MAX16B ) ) + { + temp = MAX16B; + move32(); + noClipping = L_add( (Word32) noClipping, 1 ); + } + ELSE IF( LT_32( temp, MIN16B ) ) + { + temp = MIN16B; + move32(); + noClipping = L_add( (Word32) noClipping, 1 ); + } + + y[i] = extract_l( temp ); + move16(); + } + } + ELSE + { + Word32 tempd = L_shl( 1, sub( q_x, 1 ) ); + FOR( i = n - 1; i >= 0; i-- ) + { + temp = L_add( x[i], tempd ); + temp = L_shr( temp, q_x ); + + IF( GT_32( temp, MAX16B ) ) + { + temp = MAX16B; + move32(); + noClipping = L_add( (Word32) noClipping, 1 ); + } + ELSE IF( LT_32( temp, MIN16B ) ) + { + temp = MIN16B; + move32(); + noClipping = L_add( (Word32) noClipping, 1 ); + } + + y[i] = extract_l( temp ); + move16(); + } + } + + return noClipping; +} + +Word32 dotp_me_fx( + const Word32 x[], /* i : vector x[] */ + const Word32 y[], /* i : vector y[] */ + const Word16 n, /* i : vector length */ + Word16 exp_x, + Word16 exp_y, + Word16 *exp_suma ) +{ + Word16 i; + Word32 suma; + Word32 mul; + Word16 mul_exp = add( exp_x, exp_y ); + suma = Mpy_32_32( x[0], y[0] ); + *exp_suma = mul_exp; + FOR( i = 1; i < n; i++ ) + { + mul = Mpy_32_32( x[i], y[i] ); + suma = BASOP_Util_Add_Mant32Exp( suma, *exp_suma, mul, mul_exp, exp_suma ); // exp_x+exp_A + } + + return suma; +} + +Word32 dotp_fixed_guarded( + const Word32 x[], /* i : vector x[] */ + const Word32 y[], /* i : vector y[] */ + const Word16 n /* i : vector length */ +) +{ + Word16 i; + Word32 suma; + Word16 guarded_bits = find_guarded_bits_fx( n ); + suma = L_shr( Mpy_32_32( x[0], y[0] ), guarded_bits ); + + FOR( i = 1; i < n; i++ ) + { + suma = L_add( suma, L_shr( Mpy_32_32( x[i], y[i] ), guarded_bits ) ); + } + + return suma; +} + + +Word32 dotp_fixed_ivas_fx( + const Word32 x[], /* i : vector x[] */ + Word16 x_e, + const Word32 y[], /* i : vector y[] */ + Word16 y_e, + const Word16 n, /* i : vector length */ + Word16 *out_e ) +{ + Word16 i, exp; + Word32 suma = 0; + + exp = 31; + move16(); + + FOR( i = 0; i < n; i++ ) + { + suma = BASOP_Util_Add_Mant32Exp( suma, exp, Mpy_32_32( x[i], y[i] ), x_e + y_e, &exp ); + } + + *out_e = exp; + move16(); + return suma; +} + +/*-------------------------------------------------------------------* + * v_mult() + * + * Multiplication of two vectors + *-------------------------------------------------------------------*/ + + +void v_mult_fixed( + const Word32 x1[], /* i : Input vector 1 */ + const Word32 x2[], /* i : Input vector 2 */ + Word32 y[], /* o : Output vector that contains vector 1 .* vector 2 */ + const Word16 N /* i : Vector length */ +) +{ + Word16 i; + + FOR( i = 0; i < N; i++ ) + { + y[i] = Mpy_32_32( x1[i], x2[i] ); + move32(); + } + + return; +} + +/*-------------------------------------------------------------------* + * anint_fixed() + * + * Round to the nearest integer. + *-------------------------------------------------------------------*/ +Word32 anint_fixed( Word32 x, Word16 exp ) +{ + IF( x == 0 ) + { + return 0; + } + IF( x >= 0 ) + { + return L_add( x, L_shl( 1, sub( exp, 1 ) ) ); + } + ELSE + { + return L_sub( x, L_shl( 1, sub( exp, 1 ) ) ); + } +} + +/*-------------------------------------------------------------------* + * ceil_fixed() + * + * Ceil to the next multiple of (1 << exp). + *-------------------------------------------------------------------*/ +Word32 ceil_fixed( Word32 x, Word16 exp ) +{ + Word32 step; + // step = x / L_shl( 1, exp ); + step = L_shr( x, exp ); + IF( ( x % L_shl( 1, exp ) ) > 0 ) + { + step = L_add( step, 1 ); + } + return L_shl( step, exp ); +} + +void sort_l( + Word32 *x, /* i/o: Vector to be sorted */ + Word16 len /* i/o: vector length */ +) +{ + Word16 i, j; + Word32 tempr; + + FOR( i = len - 2; i >= 0; i-- ) + { + tempr = x[i]; + move32(); + FOR( j = i + 1; ( j < len ) && ( tempr > x[j] ); j++ ) + { + x[j - 1] = x[j]; + move32(); + } + x[j - 1] = tempr; + move32(); + } + + return; +} + +/*-------------------------------------------------------------------* + * v_add_fixed() + * + * Subtraction of two vectors sample by sample + *-------------------------------------------------------------------*/ + +void v_add_fixed( + const Word32 x1[], /* i : Input vector 1 */ + const Word32 x2[], /* i : Input vector 2 */ + Word32 y[], /* o : Output vector that contains vector 1 - vector 2 */ + const Word16 N, /* i : Vector length */ + const Word16 hdrm /* i : headroom for when subtraction result > 1 or < -1 */ +) +{ + Word16 i; + + FOR( i = 0; i < N; i++ ) + { + y[i] = L_add( L_shr( x1[i], hdrm ), L_shr( x2[i], hdrm ) ); + move32(); + } + + return; +} + +void v_add_fixed_no_hdrm( + const Word32 x1[], /* i : Input vector 1 */ + const Word32 x2[], /* i : Input vector 2 */ + Word32 y[], /* o : Output vector that contains vector 1 + vector 2 */ + const Word16 N /* i : Vector length */ +) +{ + Word16 i; + + FOR( i = 0; i < N; i++ ) + { + y[i] = L_add( x1[i], x2[i] ); + move32(); + } + + return; +} + +void v_add_fixed_me( + const Word32 x1[], /* i : Input vector 1 */ + const Word16 x1_e, /* i : Exponent for input vector 1 */ + const Word32 x2[], /* i : Input vector 2 */ + const Word16 x2_e, /* i : Exponent for input vector 2 */ + Word32 y[], /* o : Output vector that contains vector 1 - vector 2 */ + Word16 *y_e, /* i : Exponent for output vector */ + const Word16 N, /* i : Vector length */ + const Word16 hdrm /* i : headroom for when subtraction result > 1 or < -1 */ +) +{ + Word16 i; + Word16 x1_shift = sub( s_max( x1_e, x2_e ), x1_e ); + Word16 x2_shift = sub( s_max( x1_e, x2_e ), x2_e ); + + FOR( i = 0; i < N; i++ ) + { + y[i] = L_add( L_shr( x1[i], hdrm + x1_shift ), L_shr( x2[i], hdrm + x2_shift ) ); + move32(); + } + + *y_e = add( s_max( x1_e, x2_e ), hdrm ); + move16(); + + return; +} + +Word16 find_guarded_bits_fx( Word32 n ) +{ + // return n <= 1 ? 0 : n <= 2 ? 1 + // : n <= 4 ? 2 + // : n <= 8 ? 3 + // : n <= 16 ? 4 + // : n <= 32 ? 5 + // : n <= 64 ? 6 + // : n <= 128 ? 7 + // : n <= 256 ? 8 + // : n <= 512 ? 9 + // : n <= 1024 ? 10 + // : n <= 2048 ? 11 + // : n <= 4096 ? 12 + // : n <= 8192 ? 13 + // : n <= 16384 ? 14 + // : 15; + /*Word16 val = 0; + move32(); + test(); + WHILE( GT_32( n, L_shl( 1, val ) ) && LT_32( val, 16 ) ) + { + val = add( val, 1 ); + }*/ + IF( LE_32( n, 1 ) ) + { + return 0; + } + ELSE + { + + return sub( 31, norm_l( L_sub( n, 1 ) ) ); + } +} + +Word16 L_norm_arr( const Word32 *arr, Word16 size ) +{ + Word16 q = 31; + move16(); + FOR( Word16 i = 0; i < size; i++ ) + { + Word16 q_tst; + + q_tst = norm_l( arr[i] ); + if ( arr[i] != 0 ) + { + q = s_min( q, q_tst ); + } + } + + return q; +} + +Word16 norm_arr( Word16 *arr, Word16 size ) +{ + Word16 q = 15; + Word16 exp = 0; + move16(); + move16(); + FOR( Word16 i = 0; i < size; i++ ) + { + if ( arr[i] != 0 ) + { + exp = norm_s( arr[i] ); + } + if ( arr[i] != 0 ) + { + q = s_min( q, exp ); + } + } + return q; +} + +Word16 W_norm_arr( Word64 *arr, Word16 size ) +{ + Word16 q = 63; + Word16 exp = 0; + move16(); + move16(); + FOR( Word16 i = 0; i < size; i++ ) + { + if ( arr[i] != 0 ) + { + exp = W_norm( arr[i] ); + } + if ( arr[i] != 0 ) + { + q = s_min( q, exp ); + } + } + return q; +} + +Word16 get_min_scalefactor( Word32 x, Word32 y ) +{ + Word16 scf_y; + Word16 scf = Q31; + move16(); + + test(); + if ( x == 0 && y == 0 ) + { + scf = 0; + move16(); + } + + if ( x != 0 ) + { + scf = norm_l( x ); + } + + scf_y = norm_l( y ); + if ( y != 0 ) + { + scf = s_min( scf_y, scf ); + } + + return scf; +} + + +Flag is_zero_arr( Word32 *arr, Word16 size ) +{ + FOR( Word16 i = 0; i < size; i++ ) + IF( arr[i] != 0 ) + { + return 0; + } + + return 1; +} + +Flag is_zero_arr16( Word16 *arr, Word16 size ) +{ + FOR( Word16 i = 0; i < size; i++ ) + IF( arr[i] != 0 ) + { + return 0; + } + + return 1; +} + +Flag is_zero_arr64( Word64 *arr, Word16 size ) +{ + FOR( Word16 i = 0; i < size; i++ ) + { + IF( arr[i] != 0 ) + { + return 0; + } + } + return 1; +} + +void Scale_sig64( + Word64 x[], /* i/o: signal to scale Qx */ + Word16 len, /* i : size of x[] Q0 */ + Word16 exp /* i : exponent: x = round(x << exp) Qx exp */ +) +{ + Word16 i; + assert( exp <= 63 && exp >= -63 ); + IF( exp == 0 ) + { + return; + } + + FOR( i = 0; i < len; i++ ) + { + /* saturation can occur here */ + x[i] = W_shl( x[i], exp ); + move64(); + } +} diff --git a/Workspace_msvc/enc_temp_folder/ba9e794e4af04046f8293c8af70d4da/options.h b/Workspace_msvc/enc_temp_folder/ba9e794e4af04046f8293c8af70d4da/options.h new file mode 100644 index 000000000..c94ad0ef3 --- /dev/null +++ b/Workspace_msvc/enc_temp_folder/ba9e794e4af04046f8293c8af70d4da/options.h @@ -0,0 +1,102 @@ +/****************************************************************************************************** + + (C) 2022-2025 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 + ====================================================================================*/ + +#ifndef OPTIONS_H +#define OPTIONS_H + +/* clang-format off */ + +/* ################### Start DEBUGGING switches ######################## */ + +/*#define DEBUGGING*/ /* Allows debugging message to be printed out during runtime */ +#ifdef DEBUGGING +/*#define DBG_BITSTREAM_ANALYSIS*/ /* Write bitstream with annotations to a text file */ +#define DEBUG_MODE_INFO /* Define to output most important parameters to the subdirectory "res/" */ +#define DEBUG_MODE_INFO_TWEAK /* Enable command line switch to specify subdirectory for debug info output inside "./res/" */ +#define DEBUG_FORCE_MDCT_STEREO_MODE /* Force stereo mode decision for MDCT stereo: -stereo 3 1 forces L/R coding and -stereo 3 2 forces full M/S coding */ +/*#define DEBUG_FORCE_DIR*/ /* Force modes/parameters by reading from external binary files */ +/*#define DBG_WAV_WRITER*/ /* Enable dbgwrite_wav() function for generating ".wav" files */ +#define SUPPORT_FORCE_TCX10_TCX20 /* VA: Enable -force tcx10|tcx20 command-line option */ +/*#define DEBUG_MODE_JBM */ /* define to output JBM relevant parameters */ +#endif + +#define SUPPORT_JBM_TRACEFILE /* Support for JBM tracefile, which is needed for 3GPP objective/subjective testing, but not relevant for real-world implementations */ + +/*#define WMOPS*/ /* Activate complexity and memory counters */ +#ifdef WMOPS +#define WMOPS_PER_FRAME /* Output per-frame complexity (writes one float value per frame to the file "wmops_analysis") */ +#define WMOPS_DETAIL /* Output detailed complexity printout for every function. Increases runtime overhead */ +#define WMOPS_WC_FRAME_ANALYSIS /* Output detailed complexity analysis for the worst-case frame */ +/*define MEM_COUNT_DETAILS*/ /* Output detailed memory analysis for the worst-case frame (writes to the file "mem_analysis.csv") */ +#endif + +/*#define DISABLE_LIMITER*/ + +/* #################### End DEBUGGING switches ############################ */ + +#ifndef BASOP_NOGLOB_DEV_USE_GLOBALS +#define BASOP_NOGLOB_DECLARE_LOCAL +#endif + +/* Note: each compile switch (FIX_1101_...) is independent from the other ones */ + +#define ISSUE_1836_replace_overflow_libcom /* FhG: replace overflow operators by non-overflow-alternatives in lib_com - BE */ +#define FIX_1942_ASSERTION_LOWSHELF /* FhG: Modified the target_gains_db_fx calculation in compute_t60_coeffs_fx() */ +#define FIX_1944_CRASH_FOR_STEREO /* FhG: improve TonalMDCTConceal_InsertNoise calculation precision */ +#define FIX_1970_SBA_CRASH /* Dlb: Fix for issue 1970, SBA crash */ + +#define FIX_1978_SAT_MISSING_IN_GAIN_ENC /* VA: Fix add saturation missing that lead to a crash in P800-10 */ +//#define FIX_1981_MAXIMUM_EXP_FX /* FhG: Fix bug in function to find maximum value in vector */ + +#define FIX_1979_SAT_MISSING_IN_LSF_ENC /* VA: Proposal to fix 1979, saturation in lsf_enc, NOkia to review */ +#define FIX_1946_CRASH_JBM_PROCESSING /* FhG: Increased guard bits of DFT_fx */ +#define FIX_1980_CRASH_FDCNG_ENCODESID /* FhG: Add one bit of headroom in e_fx calculation in FdCng_encodeSID_ivas_fx() */ +#define FIX_1987_CRASH_OMASA_ENERGY /* FhG: Replace cldfbAnalysis_ts_fx_fix_q() with cldfbAnalysis_ts_fx_var_q() to avoid assertion error */ +#define FIX_1985_SBA_714_HF_LOSS /* Dlb: Fix for issue 1985, improved dirac ref pow precision*/ + +/* #################### Start BASOP porting switches ############################ */ + +#define NONBE_1244_FIX_SWB_BWE_MEMORY /* VA: issue 1244: fix to SWB BWE memory in case of switching from FB coding - pending a review by Huawei */ +#define FIX_1129_EXT_REND_OUTPUT_HIGH /* Philips: issue 1129: External renderer BINAURAL_ROOM_REVERB format output level too high compared to internal rendering output */ +#define NONBE_1302_FIX_OMASA_JBM_FLUSH /* VA: issue 1302: fix OMASA JBM bitrate switching flush in binaural output */ +#define NONBE_1328_FIX_NON_LINEARITY /* VA: Fix possible issue when computing bwe_exc_extended and previous frame were almost 0, float issue 1328 */ +#define FIX_1319_STACK_SBA_DECODER /* VA: issue 1319: Optimize the definition of buffer lengths in the SBA decoder */ +#define FIX_1320_STACK_CPE_DECODER /* VA: issue 1320: Optimize the stack memory consumption in the CPE decoder */ +#define FIX_1984_SAT_IN_PSYCHAD /* VA: Issue 1984: proposal to fix an assert */ + +/* #################### End BASOP porting switches ############################ */ + +#endif diff --git a/Workspace_msvc/enc_temp_folder/d76ccfdc3b9fa9da476bcd2a44fe879/pitch_ol_fx.c b/Workspace_msvc/enc_temp_folder/d76ccfdc3b9fa9da476bcd2a44fe879/pitch_ol_fx.c new file mode 100644 index 000000000..56647f7b1 --- /dev/null +++ b/Workspace_msvc/enc_temp_folder/d76ccfdc3b9fa9da476bcd2a44fe879/pitch_ol_fx.c @@ -0,0 +1,2475 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "options.h" +#include "cnst.h" +// #include "prot_fx.h" +#include "basop_util.h" +#include "rom_com_fx.h" +#include "rom_com.h" +#include "rom_enc.h" +#include "prot_fx.h" /* Function prototypes */ +#include "prot_fx_enc.h" /* Function prototypes */ + +/*-----------------------------------------------------------------* + * Local Constants + *-----------------------------------------------------------------*/ +#define PIT_MIN2 20 /* pit_min for pitch tracking */ +#define PIT_MIN_1 44 /* for second pitch track */ +#define PIT_MIN2_1 24 + +#define THR_relE -2816 /* -11 (Q8) */ + +#define THRES0 4792 /* Threshold to favor smaller pitch lags; 1.17 (Q12) */ +#define DELTA0 2 /* multiples' search range initial */ +#define STEP 1 /* multiples' search range increment */ + +#define THRES1 13107 /* Threshold to favor pitch lags coherence for neighbours; 0.4 (Q15) */ +#define DELTA_COH 14 /* Maximum pitch lags difference for neighbours to be considered as coherent */ +#define THRES3 22938 /* Threshold to favor pitch lags coherence with previous frames; 0.7 (Q15) */ + +#define CORR_TH0 13107 /* Noise threshold for past frame correlations; 0.4 (Q15) */ +#define CORR_TH1 16384 /* Noise threshold for past frame correlations; 0.5 (Q15) */ + +#define LEN_X ( ( PIT_MAX / OPL_DECIM ) - ( PIT_MIN2 / OPL_DECIM ) + 1 ) /* Correlation buffer length */ +#define COH_FAC 5734 /* Factor for measuring the pitch coherence; 1.4 (Q12) */ + +#define NSUBSECT 7 +#define NSECT 4 +#define NHFR 3 +#define L_FIR_PO 5 +#define L_MEM ( L_FIR_PO - 2 ) + + +/*-----------------------------------------------------------------* + * Local function prototypes + *-----------------------------------------------------------------*/ + +static void LP_Decim2_Copy( const Word16 x[], Word16 y[], Word16 l, Word16 mem[] ); + +static void pitch_neighbour_fx( Word16 sect0, Word16 pitch_tmp[], Word16 pitch[3][2 * NSECT], Word16 corr_tmp[], Word16 corr[3][2 * NSECT], Word16 thres1[2 * NHFR], Word16 ind_tmp[2 * NHFR] ); + +static void find_mult_fx( Word16 *fac, Word16 pitch0, Word16 pitch1, Word16 pit_max0, Word16 *corr, Word16 *old_pitch, Word16 *old_corr, Word16 delta, Word16 step ); + +static Word16 pitch_coherence_fx( Word16 pitch0, Word16 pitch1, Word16 fac_max, Word16 diff_max ); + +static Word32 Dot_product12_OL( Word16 *sum1, const Word16 x[], const Word16 y[], const Word16 lg, const Word16 lg2, Word16 *exp, Word16 *exp2 ); + +static Word32 Dot_product12_OL_back( Word16 *sum1, const Word16 x[], const Word16 y[], const Word16 lg, const Word16 lg2, Word16 *exp, Word16 *exp2 ); + +/*-----------------------------------------------------------------* + * pitch_ol_init() + * + * Open loop pitch variable initialization + *-----------------------------------------------------------------*/ +void pitch_ol_init_fx( + Word16 *old_thres, /* o : threshold for reinforcement of past pitch influence */ + Word16 *old_pitch, /* o : pitch of the 2nd half-frame of previous frame */ + Word16 *delta_pit, /* o : pitch evolution extrapolation */ + Word16 *old_corr /* o : correlation */ +) +{ + *old_thres = 0; + move16(); + *old_pitch = 0; + move16(); + *delta_pit = 0; + move16(); + *old_corr = 0; + move16(); +} + + +/*==================================================================================*/ +/* FUNCTION : pitch_ol_fx() */ +/*----------------------------------------------------------------------------------*/ +/* PURPOSE : + * Compute the open loop pitch lag. + * + * The pitch lag search is divided into two sets. + * Each set is divided into three sections. + * Each section cannot have a pitch multiple. + * We find a maximum for each section. + * We compare the maxima of each section. + * + * 1st set 2nd set + * 1st section: lag delay = 115 down to 62 and 115 down to 78 + * 2nd section: lag delay = 61 down to 32 and 77 down to 41 + * 3rd section: lag delay = 31 down to 17 and 40 down to 22 + * 4th section: lag delay = 16 down to 10 and 21 down to 12 + * + * As there is a margin between section overlaps, especially for + * longer delays, this section selection is more robust for not + * to find multiples in the same section when pitch evolves rapidly. + * + * For each section, the length of the vectors to correlate is + * greater/equal to the longest pitch delay. */ +/*----------------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16[]) old_pitch : OL pitch of the 2nd half-frame of the last frame Q0 */ +/* _ (Word16[]) old_corr_fx : correlation Q15 */ +/* _ (Word16[]) corr_shift_fx : normalized correlation correction Q15 */ +/* _ (Word16[]) old_thres_fx : maximum correlation weighting with respect */ +/* to past frame pitch Q15 */ +/* _ (Word16[]) delta_pit : old pitch extrapolation correction Q0 */ +/* _ (Word16[]) st_old_wsp2_fx: weighted speech memory qwsp */ +/* _ (Word16[]) wsp_fx : weighted speech for current frame & look-ahead qwsp */ +/* _ (Word16[]) mem_decim2_fx : wsp decimation filter memory qwsp */ +/* _ (Word16[]) relE_fx : relative frame energy Q8 */ +/* _ (Word16[]) L_look : look-ahead Q0 */ +/* _ (Word16[]) Opt_SC_VBR : SC-VBR flag Q0 */ +/* _ (Word16*) qwsp : wsp & filter memory Qformat */ +/*----------------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16[]) pitch : open loop pitch lag for each half-frame Q0 */ +/* _ (Word16[]) T_op : open loop pitch lag for each half-frm for quant Q0 */ +/* _ (Word16[]) voicing_fx : max normalized correlation for each half-frame QIn */ +/* _ (Word16[]) old_pitch : OL pitch of the 2nd half-frame of the last frame Q0 */ +/* _ (Word16[]) old_corr_fx : correlation Q15 */ +/* _ (Word16[]) old_thres_fx : maximum correlation weighting with respect */ +/* to past frame pitch Q15 */ +/* _ (Word16[]) delta_pit : old pitch extrapolation correction Q0 */ +/* _ (Word16[]) st_old_wsp2_fx: weighted speech memory qwsp */ +/* _ (Word16[]) mem_decim2_fx : wsp decimation filter memory qwsp */ +/*----------------------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*==================================================================================*/ + +void pitch_ol_fx( + Word16 pitch[3], /* o : open loop pitch lag for each half-frame in range [29,231] Q0 */ + Word16 voicing[3], /* o : maximum normalized correlation for each half-frame in [0,1.0[ Q15 */ + Word16 *old_pitch, /* i/o: pitch of the 2nd half-frame of previous frame (i.e. pitch[1]) Q0 */ + Word16 *old_corr, /* i/o: correlation of old_pitch (i.e. voicing[1] or corr_mean) Q15 */ + Word16 corr_shift, /* i : normalized correlation correction Q15 */ + Word16 *old_thres, /* i/o: maximum correlation weighting with respect to past frame pitch Q15 */ + Word16 *delta_pit, /* i/o: old pitch extrapolation correction in range [-14,+14] Q0 */ + Word16 *st_old_wsp2, /* i/o: weighted speech memory qwsp */ + const Word16 *wsp, /* i : weighted speech for current frame and look-ahead qwsp */ + Word16 mem_decim2[3], /* i/o: wsp decimation filter memory qwsp */ + const Word16 relE, /* i : relative frame energy Q8 */ + const Word16 last_class, /* i : frame classification of last frame */ + const Word16 bwidth, /* i : bandwidth */ + const Word16 Opt_SC_VBR /* i : SC-VBR flag */ +) +{ + Word16 ftmp, old_wsp2[( L_WSP - L_INTERPOL ) / OPL_DECIM], *wsp2; + Word16 tmp_mem[3]; + + Word16 scale1[2 * DELTA_COH - 1]; + Word16 scaled_buf[2 * LEN_X + 3 * ( DELTA_COH - 1 )]; + Word16 scaled_buf_exp[2 * LEN_X + 3 * ( DELTA_COH - 1 )], exp_sect[8], exp_sect1[8], exp_sect0; + Word16 cor_buf[2 * LEN_X]; + Word16 *pt_exp1, *pt_exp2, *pt_exp3, *pt_exp4; + Word16 *pt1, *pt2, *pt3, *pt4, *pt5, *pt6; + Word16 *pt_cor0, *pt_cor1, *pt_cor2, *pt_cor3, *pt_cor4, *pt_cor5, *pt_cor6; + Word16 thres1[6]; + Word16 diff, cnt, ind, ind1, offset, offset1, offset_la, offset_la1, coh_flag, coh_flag1; + Word16 ind_corX, ind1_corX; + + Word16 i, j, k, m, pit_min, pit_min1, sect0, subsect0, add_sect0, sub_sect0, old_tmp, old_tmp1, len_x, len_x1; + Word16 len_temp; + Word16 pitchX[NHFR][2 * NSECT], pitch_tmp[2 * NHFR], ind_tmp[2 * NHFR], tmp_buf[NHFR + 1]; + + Word16 enr0[NSECT], enr0_exp[NSECT], enr0_1[NSECT], enr0_1_exp[NSECT], enr1, enr1_exp, enr2_exp; + Word32 enr, enr2, Ltmp; + Word16 fac, tmp16, tmp16_2; + Word16 qCorX, qScaledX; + Word16 scaledX[NHFR][2 * NSECT], corX[NHFR][2 * NSECT], cor_tmp[2 * NHFR], cor_mean; + const Word16 *len, *len1, *sublen, *sublen1, *pit_max, *sec_length, *sec_length1; + + Word16 pit_min_coding; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + /*--------------------------------------------------------------* + * Initialization + *--------------------------------------------------------------*/ + len = len_12k8; + len1 = len1_12k8; + sublen = sublen_12k8; + sublen1 = sublen1_12k8; + pit_max = pit_max_12k8; + sec_length = sec_length_12k8; + sec_length1 = sec_length1_12k8; + + test(); + if ( ( LT_16( last_class, VOICED_TRANSITION ) ) && ( NE_16( bwidth, NB ) ) ) + { + /*reset last pitch reinforcement in case of unvoiced or transitions: it avoids some pitch doublings*/ + *old_thres = 0; + move16(); + } + + pit_min_coding = PIT_MIN_EXTEND; + move16(); + test(); + test(); + test(); + test(); + IF( ( ( NE_16( bwidth, NB ) ) && ( GT_16( *old_pitch, PIT_MIN ) ) ) || + ( ( EQ_16( bwidth, NB ) ) && ( ( GT_16( *old_pitch, PIT_MIN2_1 ) ) || ( LT_16( *old_thres, 3277 ) ) ) ) ) /* 0.1 inQ15*/ + { + pit_min = PIT_MIN / OPL_DECIM; + move16(); + pit_min1 = PIT_MIN_1 / OPL_DECIM; + move16(); + subsect0 = 2; + move16(); + sect0 = 1; + move16(); + } + ELSE + { + pit_min = PIT_MIN2 / OPL_DECIM; + move16(); + pit_min1 = PIT_MIN2_1 / OPL_DECIM; + move16(); + subsect0 = 0; + move16(); + sect0 = 0; + move16(); + } + + len_x = ( PIT_MAX / OPL_DECIM - pit_min + 1 ); + move16(); + len_x1 = ( PIT_MAX / OPL_DECIM - pit_min1 + 1 ); + move16(); + + /*--------------------------------------------------------------* + * Find decimated weighted speech + * Update wsp buffer with the memory + * decimation of wsp[] to search pitch in LF and to reduce complexity + * Extend the decimation of wsp to the end of the speech buffer + * Update wsp memory + *--------------------------------------------------------------*/ + Copy( st_old_wsp2, old_wsp2, ( L_WSP_MEM - L_INTERPOL ) / OPL_DECIM ); + wsp2 = old_wsp2 + ( ( L_WSP_MEM - L_INTERPOL ) / OPL_DECIM ); + + LP_Decim2_Copy( wsp, wsp2, L_FRAME, mem_decim2 ); + + /* Avoid uninitialized memory access */ + set16_fx( wsp2 + L_FRAME / 2, 0, sizeof( old_wsp2 ) / sizeof( Word16 ) - ( ( L_WSP_MEM - L_INTERPOL ) / OPL_DECIM ) - L_FRAME / 2 ); + tmp_mem[0] = mem_decim2[0]; + move16(); + tmp_mem[1] = mem_decim2[1]; + move16(); + tmp_mem[2] = mem_decim2[2]; + move16(); + + LP_Decim2_Copy( &wsp[L_FRAME], &wsp2[( L_FRAME / 2 )], L_LOOK_12k8, tmp_mem ); /* shr() used instead of division by OPL_DECIM*/ + + Copy( &old_wsp2[L_FRAME / 2], st_old_wsp2, ( L_WSP_MEM - L_INTERPOL ) / OPL_DECIM ); + + /*-----------------------------------------------------------------* + * Attenuate the correlation correction factor due to noise. + * Reset correlation buffer outside the useful range. + * Find the scaling functions for immediate neigbours and + * further ones. + *-----------------------------------------------------------------*/ + + corr_shift = shr( corr_shift, 1 ); + + set16_fx( scaled_buf, 0, DELTA_COH - 1 ); + set16_fx( scaled_buf + ( DELTA_COH - 1 ) + len_x, 0, DELTA_COH - 1 ); + set16_fx( scaled_buf + 2 * ( DELTA_COH - 1 ) + len_x + len_x1, 0, DELTA_COH - 1 ); + set16_fx( scaled_buf_exp, 0, len_x + len_x1 + 3 * ( DELTA_COH - 1 ) ); + + pt1 = scale1 + DELTA_COH - 1; + pt2 = pt1; + tmp16 = mult( negate( *old_thres ), MAX_16 / DELTA_COH ); + k = *old_thres; + move16(); + FOR( i = 0; i < DELTA_COH; i++ ) + { + /* + * *pt1 = ( -(*old_thres)/DELTA_COH * i + *old_thres+1.0f ); + * To keep Q15 values, the following code does not add 1 to the result. + * A scaling factor must be applied accordingly (see next use of scale1) + */ + *pt1 = k; + move16(); + k = add( k, tmp16 ); + *pt2-- = *pt1++; + move16(); + } + + /*-----------------------------------------------------------------------------* + * Estimate the new pitch by extrapolating the old pitch value for 2 half-frames + *-----------------------------------------------------------------------------*/ + old_tmp = add( *old_pitch, *delta_pit ); + old_tmp = s_min( old_tmp, PIT_MAX / OPL_DECIM ); + old_tmp = s_max( old_tmp, pit_min ); + old_tmp1 = add( old_tmp, *delta_pit ); + old_tmp1 = s_min( old_tmp1, PIT_MAX / OPL_DECIM ); + old_tmp1 = s_max( old_tmp1, pit_min ); + + /*-----------------------------------------------------------------* + * Loop for all three half-frames (current frame + look-ahead) + *-----------------------------------------------------------------*/ + pt_cor0 = scaled_buf + DELTA_COH - 1; + + pt_cor2 = pt_cor0 - pit_min + old_tmp; + pt_cor4 = pt_cor0 - pit_min1 + old_tmp + ( DELTA_COH - 1 ) + len_x; + + FOR( i = 0; i < NHFR; i++ ) /* i = 0, 1, 2 */ + { + pt1 = wsp2 + i * 2 * ( L_SUBFR / OPL_DECIM ); /* *pt1 -> Q12 */ + pt2 = pt1 - pit_min; /* *pt2 -> Q12 */ + pt4 = pt1 - pit_min1; /* *pt4 -> Q12 */ + + enr = L_deposit_l( 1 ); + + pt_cor1 = pt_cor0; + pt_cor3 = pt_cor0 + ( DELTA_COH - 1 ) + len_x; + + pt_exp1 = scaled_buf_exp + DELTA_COH - 1; + pt_exp2 = pt_exp1; + pt_exp3 = scaled_buf_exp + 2 * ( DELTA_COH - 1 ) + len_x; + pt_exp4 = pt_exp3; + + IF( LT_16( i, NHFR - 1 ) ) /* First two half-frames (current frame) */ + { + pt3 = pt1; + pt5 = pt1; + + FOR( j = sect0; j < NSECT; j++ ) /* loop for each section */ + { + /*-----------------------------------------------------------------* + * Find fixed vector energy + *-----------------------------------------------------------------*/ + + /* 1st set */ + k = (Word16) ( pt1 - pt3 ); + move16(); + + FOR( k = add( k, len[j] ); k > 0; k-- ) + { + enr = L_mac0( enr, *pt3, *pt3 ); + pt3++; + } + /* keep Q15 normalized result */ + cnt = norm_l( enr ); + enr0[j] = extract_h( L_shl( enr, cnt ) ); + enr0_exp[j] = sub( 30, cnt ); + move16(); + + /* Reduce complexity (length of 'enr2' section is equal or larger than 'enr') */ + pt5 = pt3; + enr2 = enr; /* sets to 'enr' in 1 clock */ + move32(); + + /* 2nd set */ + k = (Word16) ( pt1 - pt5 ); + move16(); + + FOR( k = add( k, len1[j] ); k > 0; k-- ) + { + enr2 = L_mac0( enr2, *pt5, *pt5 ); + pt5++; + } + cnt = norm_l( enr2 ); + enr0_1[j] = extract_h( L_shl( enr2, cnt ) ); + enr0_1_exp[j] = sub( 30, cnt ); + move16(); + } + + /*----------------------------------------------------------* + * Find correlation for the non-overlapping pitch lag values + *----------------------------------------------------------*/ + exp_sect[subsect0] = 0; + move16(); + pt_cor5 = pt_cor1; + pt_cor6 = pt_cor3; + + tmp16 = exp_sect[subsect0]; + move16(); + + k = (Word16) ( pt2 - pt1 + pit_max[subsect0] ); + + IF( k >= 0 ) + { + len_temp = sublen[0]; + move16(); + + FOR( ; k >= 0; k-- ) + { + /* Keep Q15 normalized result */ + /* shr by 1 to make room for scaling in the neighbourhood of the extrapolated pitch */ + /* Update exponent to reflect shr by 1 */ + *pt_cor1 = extract_h( L_shr( Dot_product12( pt1, pt2--, len_temp, pt_exp1 ), 1 ) ); + + /* save the biggest exponent */ + tmp16 = s_max( tmp16, *pt_exp1 ); + + pt_cor1++; + pt_exp1++; + } + } + exp_sect[subsect0] = tmp16; + move16(); + + /*----------------------------------------------------------* + * For each subsection, find the correlation + *----------------------------------------------------------*/ + FOR( j = subsect0; j < NSUBSECT; j++ ) + { + len_temp = sublen[j]; + move16(); + + k = (Word16) ( pt2 - pt1 ); + move16(); + k = add( k, pit_max[j + 1] ); + exp_sect[j + 1] = 0; + move16(); + exp_sect1[j] = 0; + move16(); + + IF( k >= 0 ) + { + ind = exp_sect[j + 1]; + move16(); + ind1 = exp_sect1[j]; + move16(); + + FOR( ; k >= 0; k-- ) + { + /* Keep Q15 normalized result */ + /* shr by 1 to make room for scaling in the neighbourhood of the extrapolated pitch */ + /* Update exponent to reflect shr by 1 (done in Dot_product12_OL() for pt_cor3/pt_exp3) */ + *pt_cor1 = extract_h( L_shr( Dot_product12_OL( pt_cor3, pt1, pt2--, sublen[j], sublen1[j], pt_exp1, pt_exp3 ), 1 ) ); + /* The line above replaces: + * *pt_cor1 = shr(extract_h(Dot_product12(pt1, pt2, Sublen[j], pt_exp1)),1); move16(); + * *pt_cor3 = shr(extract_h(Dot_product12(pt1, pt2--, Sublen1[j+i*7], pt_exp3)),1); move16(); + */ + + /* save the biggest exponent */ + ind = s_max( ind, *pt_exp1 ); + ind1 = s_max( ind1, *pt_exp3 ); + + pt_cor1++; + pt_exp1++; + pt_cor3++; + pt_exp3++; + } + exp_sect[j + 1] = ind; + move16(); + exp_sect1[j] = ind1; + move16(); + } /* IF (k >= 0) */ + } /* FOR (j = subsect0; ... */ + } + ELSE /* 3rd half-frame (look-ahead) */ + { + pt6 = pt1 + L_LOOK_12k8 / OPL_DECIM - 1; + pt3 = pt6; + pt5 = pt6; + + /*-----------------------------------------------------------------* + * For each section in both sets, find fixed vector energy + *-----------------------------------------------------------------*/ + + FOR( j = sect0; j < NSECT; j++ ) /* loop for each section */ + { + /* 1st set */ + k = (Word16) ( pt3 - pt6 ); + move16(); + + FOR( k = add( k, len[j] ); k > 0; k-- ) + { + enr = L_mac0( enr, *pt3, *pt3 ); + pt3--; + } + + cnt = norm_l( enr ); + enr0[j] = extract_h( L_shl( enr, cnt ) ); /*qwsp+cnt-16*/ + enr0_exp[j] = sub( 30, cnt ); + move16(); + + /* Reduce complexity (length of 'enr2' section is equal or larger than 'enr') */ + pt5 = pt3; + enr2 = enr; + move16(); + + /* 2nd set */ + k = (Word16) ( pt5 - pt6 ); + move16(); + + FOR( k = add( k, len1[j] ); k > 0; k-- ) + { + enr2 = L_mac0( enr2, *pt5, *pt5 ); + pt5--; + } + + cnt = norm_l( enr2 ); + enr0_1[j] = extract_h( L_shl( enr2, cnt ) ); /*qwsp+cnt-16*/ + enr0_1_exp[j] = sub( 30, cnt ); + move16(); + } + + /* Set pointers */ + IF( sect0 != 0 ) + { + pt2 = pt6 - add( pit_max[1], 1 ); + k = sub( pit_max[2], pit_max[1] ); + move16(); + } + ELSE + { + pt2 = pt6 - pit_min; + k = 2; + move16(); + } + + /*-----------------------------------------------------------------* + * Find correlation for the non-overlapping pitch lag values + *-----------------------------------------------------------------*/ + exp_sect[subsect0] = 0; + move16(); + pt_cor5 = pt_cor1; + pt_cor6 = pt_cor3; + + tmp16 = exp_sect[subsect0]; + move16(); + + IF( k > 0 ) + { + len_temp = sublen[0]; + move16(); + + FOR( ; k > 0; k-- ) + { + /* Following lines are equivalent of Dot_product12() but with a backward incrementing */ + Ltmp = L_deposit_l( 1 ); + FOR( m = 0; m < len_temp; m++ ) + { + Ltmp = L_mac( Ltmp, pt6[-m], pt2[-m] ); + } + + /* Normalize acc in Q31 */ + tmp16_2 = norm_l( Ltmp ); + Ltmp = L_shl( Ltmp, tmp16_2 ); + *pt_exp1 = sub( 30, tmp16_2 ); + move16(); /* exponent = 0..30 */ + + /* Save result */ + *pt_cor1 = extract_h( L_shr( Ltmp, 1 ) ); + + /* Save the biggest exponent */ + tmp16 = s_max( tmp16, *pt_exp1 ); + + pt_cor1++; + pt_exp1++; + pt2--; + } + exp_sect[subsect0] = tmp16; + move16(); + } + + /*-----------------------------------------------------------------* + * For each subsection, find the correlation (overlapping pitch lag values) + *-----------------------------------------------------------------*/ + + FOR( j = subsect0; j < NSUBSECT; j++ ) + { + exp_sect[j + 1] = 0; + move16(); + exp_sect1[j] = 0; + move16(); + + ind = exp_sect[j + 1]; + move16(); + ind1 = exp_sect1[j]; + move16(); + + k = sub( pit_max[j + 1], pit_max[j] ); + + FOR( ; k > 0; k-- ) + { + *pt_cor1 = extract_h( L_shr( Dot_product12_OL_back( pt_cor3, pt6, pt2--, sublen[j], sublen1[j], pt_exp1, pt_exp3 ), 1 ) ); + + /* Save the biggest exponent */ + ind = s_max( ind, *pt_exp1 ); + ind1 = s_max( ind1, *pt_exp3 ); + + pt_cor1++; + pt_exp1++; + pt_cor3++; + pt_exp3++; + } + exp_sect[j + 1] = ind; + move16(); + exp_sect1[j] = ind1; + move16(); + } + } /* 3rd half-frame (look-ahead) */ + + /* Scale all values in each section to the same exponent for upcoming Find_max() */ + offset = 0; + move16(); + offset1 = 0; + move16(); + exp_sect1[7] = 0; /* padding */ + move16(); + FOR( j = sect0; j < NSECT; j++ ) + { + exp_sect0 = s_max( exp_sect[j * 2], exp_sect[j * 2 + 1] ); + + /* scaling of exp for track 1 */ + offset = add( offset, sec_length[j] ); + k = (Word16) ( pt_cor0 - pt_cor5 ); + move16(); + FOR( k = add( k, offset ); k > 0; k-- ) + { + cnt = sub( exp_sect0, *pt_exp2 ); + tmp16 = s_min( 15, cnt ); + if ( cnt > 0 ) + { + tmp16 = shr( *pt_cor5, tmp16 ); + } + if ( cnt > 0 ) + { + *pt_cor5 = tmp16; + move16(); + } + *pt_exp2 = s_max( *pt_exp2, exp_sect0 ); + move16(); + pt_cor5++; + pt_exp2++; + } + + exp_sect0 = s_max( exp_sect1[j * 2], exp_sect1[j * 2 + 1] ); + + /* scaling of exp for track 2 */ + offset1 = add( offset1, sec_length1[j] ); + k = (Word16) ( pt_cor0 - pt_cor6 + ( DELTA_COH - 1 ) ); + move16(); + k = add( k, len_x ); + FOR( k = add( k, offset1 ); k > 0; k-- ) + { + cnt = sub( exp_sect0, *pt_exp4 ); + tmp16 = s_min( 15, cnt ); + if ( cnt > 0 ) + { + tmp16 = shr( *pt_cor6, tmp16 ); + } + if ( cnt > 0 ) + { + *pt_cor6 = tmp16; + move16(); + } + *pt_exp4 = s_max( *pt_exp4, exp_sect0 ); + move16(); + pt_cor6++; + pt_exp4++; + } + } /* FOR (j = sect0; ... */ + + Copy( pt_cor0, cor_buf, len_x ); /* Save unscaled correlation vector */ + Copy( pt_cor0 + ( DELTA_COH - 1 ) + len_x, cor_buf + len_x, len_x1 ); + + /*-----------------------------------------------------------------* + * Scale correlation function in the neighbourhood of + * the extrapolated pitch + *-----------------------------------------------------------------*/ + pt_cor1 = pt_cor2 - ( DELTA_COH - 1 ); + pt_cor3 = pt_cor4 - ( DELTA_COH - 1 ); + pt2 = scale1; + + FOR( k = 0; k < 2 * DELTA_COH - 1; k++ ) + { + /* all Q15 here */ + *pt_cor1 = add( *pt_cor1, mult( *pt_cor1, *pt2 ) ); + move16(); + *pt_cor3 = add( *pt_cor3, mult( *pt_cor3, *pt2++ ) ); + move16(); + + pt_cor1++; + pt_cor3++; + } + + /* Update for next half-frame & look-ahead */ + pt_cor2 = pt_cor0 - pit_min + old_tmp1; + pt_cor4 = pt_cor0 - pit_min1 + old_tmp1 + ( DELTA_COH - 1 ) + len_x; + + /*-----------------------------------------------------------------* + * For each section, find maximum correlation and compute + * normalized correlation + *-----------------------------------------------------------------*/ + + pt_cor1 = pt_cor0; + pt_exp1 = scaled_buf_exp + DELTA_COH - 1; + offset = 0; + move16(); + pt_cor3 = pt_cor0 + ( DELTA_COH - 1 ) + len_x; + pt_exp3 = scaled_buf_exp + 2 * ( DELTA_COH - 1 ) + len_x; + offset1 = 0; + move16(); + + FOR( j = sect0; j < NSECT; j++ ) /* loop for each section */ + { + /* 1st set */ + offset_la = 0; + move16(); + if ( EQ_16( i, 2 ) ) + { + offset_la = sub( L_LOOK_12k8 / OPL_DECIM, len[j] ); + } + + /* 2nd set */ + offset_la1 = 0; + move16(); + if ( EQ_16( i, 2 ) ) + { + offset_la1 = sub( L_LOOK_12k8 / OPL_DECIM, len1[j] ); + } + + /* 1st set of candidates */ + ind = add( maximum_fx( pt_cor1, sec_length[j], &ftmp ), offset ); + pitchX[i][j] = add( ind, pit_min ); + move16(); + pt2 = pt1 - pitchX[i][j] + /*-*/ offset_la; /* selected moving vector */ + + enr1_exp = 0; + move16(); + enr1 = add_o( extract_h( dotp_fx( pt2, pt2, len[j], &enr1_exp ) ), 1, &Overflow ); + + enr2 = L_mult( enr0[j], enr1 ); + enr2_exp = norm_l( enr2 ); + enr2 = L_shl( enr2, enr2_exp ); + enr2_exp = sub( 31, add( sub( 28, add( enr0_exp[j], enr1_exp ) ), add( enr2_exp, 1 ) ) ); + + enr2 = Isqrt_lc( enr2, &enr2_exp ); /* 1/sqrt(energy) */ /*31-enr2_exp*/ + enr1_exp = norm_l( enr2 ); + enr1 = extract_h( L_shl( enr2, enr1_exp ) ); /*31-enr2_exp+enr1_exp-16*/ + enr1_exp = sub( enr2_exp, enr1_exp ); /*15-enr1_exp*/ + + Ltmp = L_mult0( cor_buf[ind], enr1 ); + qCorX = add( sub( 15, enr1_exp ), sub( 14, pt_exp1[ind] ) ); + corX[i][j] = extract_h( L_shr_sat( Ltmp, sub( qCorX, 31 ) ) ); + qCorX = 31; + move16(); + + Ltmp = L_mult0( pt_cor0[ind], enr1 ); + qScaledX = add( sub( 15, enr1_exp ), sub( 14, pt_exp1[ind] ) ); + scaledX[i][j] = round_fx( L_shl( Ltmp, sub( 16 + 12, qScaledX ) ) ); + qScaledX = 12; + move16(); + + pt_cor1 += sec_length[j]; + move16(); + offset = add( offset, sec_length[j] ); + + /* 2nd set of candidates */ + ind1 = add( maximum_fx( pt_cor3, sec_length1[j], &ftmp ), offset1 ); + pitchX[i][j + NSECT] = add( ind1, pit_min1 ); + move16(); + pt4 = pt1 - pitchX[i][j + NSECT] + /*-*/ offset_la1; + move16(); /* selected moving vector */ + enr1_exp = 0; + move16(); + enr1 = add_o( extract_h( dotp_fx( pt4, pt4, len1[j], &enr1_exp ) ), 1, &Overflow ); + + enr2 = L_mult( enr0_1[j], enr1 ); + enr2_exp = norm_l( enr2 ); + enr2 = L_shl( enr2, enr2_exp ); + + enr2_exp = sub( 31, add( sub( 28, add( enr0_1_exp[j], enr1_exp ) ), add( enr2_exp, 1 ) ) ); + enr2 = Isqrt_lc( enr2, &enr2_exp ); /* 1/sqrt(energy) */ /*31-enr2_exp*/ + enr1_exp = norm_l( enr2 ); + enr1 = extract_h( L_shl( enr2, enr1_exp ) ); /*31-enr2_exp+enr1_exp-16*/ + enr1_exp = sub( enr2_exp, enr1_exp ); /*15-enr1_exp*/ + + Ltmp = L_mult0( cor_buf[ind1 + len_x], enr1 ); + + qCorX = add( sub( 15, enr1_exp ), sub( 14, pt_exp3[ind1] ) ); + corX[i][j + NSECT] = extract_h( L_shr_sat( Ltmp, qCorX - 31 ) ); + qCorX = 31; + move16(); + + Ltmp = L_mult0( pt_cor0[ind1 + ( DELTA_COH - 1 ) + len_x], enr1 ); + qScaledX = add( sub( 15, enr1_exp ), sub( 14, pt_exp3[ind1] ) ); + scaledX[i][j + NSECT] = round_fx( L_shl( Ltmp, sub( 16 + 12, qScaledX ) ) ); + /*scaledX[i][j+NSECT] = saturate(L_shr(Ltmp, qScaledX-12));*/ + qScaledX = 12; + move16(); + + pt_cor3 += sec_length1[j]; + move16(); + offset1 = add( offset1, sec_length1[j] ); + + } /* FOR j < NSECT */ + } /* FOR i < NHFR */ + + /*-----------------------------------------------------------------* + * Favor a smaller delay if it happens that it has its multiple + * in the longer-delay sections (harmonics check) + *-----------------------------------------------------------------*/ + + FOR( i = 0; i < 2; i++ ) /* loop for the 2 half-frames */ + { + fac = THRES0; + move16(); + find_mult_fx( &fac, pitchX[i][2], pitchX[i][3], pit_max[7], &scaledX[i][2], old_pitch, old_corr, DELTA0, STEP ); /* Multiples in 3rd section */ + find_mult_fx( &fac, pitchX[i][1], pitchX[i][2], pit_max[5], &scaledX[i][1], old_pitch, old_corr, DELTA0, STEP ); /* Multiples in 2nd section */ + test(); + IF( ( sect0 == 0 ) && GE_16( shl( pitchX[i][0], 1 ), pit_min_coding ) ) + { + find_mult_fx( &fac, pitchX[i][0], pitchX[i][1], pit_max[3], &scaledX[i][0], old_pitch, old_corr, DELTA0, STEP ); /* Multiples in 2nd section */ + } + fac = THRES0; + move16(); + find_mult_fx( &fac, pitchX[i][NSECT + 2], pitchX[i][NSECT + 3], pit_max[7], &scaledX[i][NSECT + 2], old_pitch, old_corr, DELTA0, STEP ); /* Multiples in 3rd section */ + find_mult_fx( &fac, pitchX[i][NSECT + 1], pitchX[i][NSECT + 2], pit_max[6], &scaledX[i][NSECT + 1], old_pitch, old_corr, DELTA0, STEP ); /* Multiples in 2nd section */ + test(); + IF( ( sect0 == 0 ) && GE_16( shl( pitchX[i][NSECT + 0], 1 ), pit_min_coding ) ) + { + find_mult_fx( &fac, pitchX[i][NSECT + 0], pitchX[i][NSECT + 1], pit_max[4], &scaledX[i][NSECT + 0], old_pitch, old_corr, DELTA0, STEP ); /* Multiples in 2nd section */ + } + } + + fac = THRES0; + move16(); /* the look-ahead */ + find_mult_fx( &fac, pitchX[i][2], pitchX[i][3], pit_max[7], &scaledX[i][2], old_pitch, old_corr, 2, 2 ); /* Multiples in 3rd section */ + find_mult_fx( &fac, pitchX[i][1], pitchX[i][2], pit_max[5], &scaledX[i][1], old_pitch, old_corr, DELTA0, STEP ); /* Multiples in 2nd section */ + test(); + IF( ( sect0 == 0 ) && GE_16( shl( pitchX[i][0], 1 ), pit_min_coding ) ) + { + find_mult_fx( &fac, pitchX[i][0], pitchX[i][1], pit_max[3], &scaledX[i][0], old_pitch, old_corr, DELTA0, STEP ); /* Multiples in 2nd section */ + } + fac = THRES0; + move16(); + find_mult_fx( &fac, pitchX[i][NSECT + 2], pitchX[i][NSECT + 3], pit_max[7], &scaledX[i][NSECT + 2], old_pitch, old_corr, 2, 2 ); /* Multiples in 3rd section */ + find_mult_fx( &fac, pitchX[i][NSECT + 1], pitchX[i][NSECT + 2], pit_max[6], &scaledX[i][NSECT + 1], old_pitch, old_corr, DELTA0, STEP ); /* Multiples in 2nd section */ + test(); + IF( ( sect0 == 0 ) && GE_16( shl( pitchX[i][NSECT + 0], 1 ), pit_min_coding ) ) + { + find_mult_fx( &fac, pitchX[i][NSECT + 0], pitchX[i][NSECT + 1], pit_max[4], &scaledX[i][NSECT + 0], old_pitch, old_corr, DELTA0, STEP ); /* Multiples in 2nd section */ /* Multiples in 2nd section */ + } + + /*-----------------------------------------------------------------* + * Do 1st estimate for pitch values + * Adjust the normalized correlation using estimated noise level + * Compute the maximum scaling for the neighbour correlation + * reinforcement + *-----------------------------------------------------------------*/ + add_sect0 = add( NSECT, sect0 ); + sub_sect0 = sub( NSECT, sect0 ); + FOR( i = 0; i < NHFR; i++ ) + { + /* 1st set of pitch candidates */ + ind = add( maximum_fx( scaledX[i] + sect0, sub_sect0, &ftmp ), sect0 ); + ind_tmp[i] = ind; + move16(); + pitch_tmp[i] = pitchX[i][ind]; + move16(); + cor_tmp[i] = add_o( corX[i][ind], corr_shift, &Overflow ); + move16(); + + /* Higher is the neighbour's correlation, higher is the weighting */ + /* operands are Q15, result is Q15 */ + thres1[i] = mult( THRES1, cor_tmp[i] ); + move16(); + + /* 2nd set of pitch candidates */ + ind1 = add( maximum_fx( scaledX[i] + add_sect0, sub_sect0, &ftmp ), add_sect0 ); + ind_tmp[i + NHFR] = ind1; + move16(); + pitch_tmp[i + NHFR] = pitchX[i][ind1]; + move16(); + cor_tmp[i + NHFR] = add_o( corX[i][ind1], corr_shift, &Overflow ); + move16(); + + /* Higher is the neighbour's correlation, higher is the weighting */ + /* operands are Q15, result is Q15 */ + thres1[i + NHFR] = mult( THRES1, cor_tmp[i + NHFR] ); + move16(); + } + /*-----------------------------------------------------------------* + * Take into account previous and next pitch values of the present + * frame and look-ahead. Choose the pitch lags and normalize + * correlations for each half-frame & look-ahead + *-----------------------------------------------------------------*/ + + pitch_neighbour_fx( sect0, pitch_tmp, pitchX, cor_tmp, scaledX, thres1, ind_tmp ); + FOR( i = 0; i < NHFR; i++ ) + { + ind = add( maximum_fx( scaledX[i] + sect0, sub_sect0, &ftmp ), sect0 ); + ind_corX = add( maximum_fx( corX[i] + sect0, sub_sect0, &ftmp ), sect0 ); + + ind1 = add( maximum_fx( scaledX[i] + add_sect0, sub_sect0, &ftmp ), add_sect0 ); + ind1_corX = add( maximum_fx( corX[i] + add_sect0, sub_sect0, &ftmp ), add_sect0 ); + + if ( GT_16( scaledX[i][ind1], scaledX[i][ind] ) ) + { + ind = ind1; + move16(); + } + test(); + if ( Opt_SC_VBR && GT_16( corX[i][ind1_corX], corX[i][ind_corX] ) ) + { + ind_corX = ind1_corX; + move16(); + } + test(); + test(); + test(); + IF( Opt_SC_VBR && ( LT_16( mult( pitchX[i][ind], 13107 /*0.4 in Q15*/ ), pitchX[i][ind_corX] ) ) && + ( GT_16( mult( pitchX[i][ind], 19661 /*0.6 in Q15*/ ), pitchX[i][ind_corX] ) ) && + ( GE_16( corX[i][ind_corX], 29491 /*0.9 in Q15*/ ) ) ) + { + pitch[i] = pitchX[i][ind_corX]; + move16(); + voicing[i] = corX[i][ind_corX]; + move16(); + } + ELSE + { + pitch[i] = pitchX[i][ind]; + move16(); + voicing[i] = corX[i][ind]; + move16(); + } + } + + /*-----------------------------------------------------------------* + * Increase the threshold for correlation reinforcement with + * the past if correlation high and pitch stable + *-----------------------------------------------------------------*/ + + /* all Q15 here */ + /* cor_mean = 0.5f * (voicing[0] + voicing[1]) + corr_shift; */ + Ltmp = L_mult( voicing[0], 16384 ); + Ltmp = L_mac( Ltmp, voicing[1], 16384 ); + cor_mean = round_fx( L_add( Ltmp, corr_shift ) ); + + /* pitch unstable in present frame or from previous frame or normalized correlation too low */ + coh_flag = pitch_coherence_fx( pitch[0], pitch[1], COH_FAC, DELTA_COH ); + move16(); + coh_flag1 = pitch_coherence_fx( pitch[0], *old_pitch, COH_FAC, DELTA_COH ); + move16(); + + test(); + test(); + test(); + IF( ( coh_flag == 0 ) || ( coh_flag1 == 0 ) || ( LT_16( cor_mean, CORR_TH0 ) ) || ( LT_16( relE, THR_relE ) ) ) + { + /* Reset the threshold */ + *old_thres = 0; + move16(); + } + ELSE + { + /* The threshold increase is directly dependent on normalized correlation */ + /* *old_thres += (0.16f * cor_mean); */ + *old_thres = round_fx( L_mac( L_deposit_h( *old_thres ), 5243, cor_mean ) ); + } + + *old_thres = s_min( *old_thres, THRES3 ); + move16(); + + IF( GT_16( voicing[1], voicing[0] ) ) + { + *old_corr = voicing[1]; + move16(); + } + ELSE + { + *old_corr = cor_mean; + move16(); + } + + /*-----------------------------------------------------------------* + * Extrapolate the pitch value for the next frame by estimating + * the pitch evolution. This value is added to the old_pitch + * in the next frame and is then used when the normalized + * correlation is reinforced by the past estimate + *-----------------------------------------------------------------*/ + tmp_buf[0] = *old_pitch; + move16(); + FOR( i = 0; i < NHFR; i++ ) + { + tmp_buf[i + 1] = pitch[i]; + move16(); + } + + *delta_pit = 0; + move16(); + cnt = 0; + move16(); + + FOR( i = 0; i < NHFR; i++ ) + { + diff = sub( tmp_buf[i + 1], tmp_buf[i] ); + move16(); + coh_flag = pitch_coherence_fx( tmp_buf[i], tmp_buf[i + 1], COH_FAC, DELTA_COH ); + + if ( coh_flag != 0 ) + { + *delta_pit = add( *delta_pit, diff ); + move16(); + } + cnt = add( cnt, coh_flag ); + } + if ( EQ_16( cnt, 2 ) ) + { + /* *delta_pit /= 2; */ + *delta_pit = shr( *delta_pit, 1 ); + move16(); + } + IF( EQ_16( cnt, 3 ) ) + { + k = *delta_pit; + move16(); + /* *delta_pit /= 3; */ + if ( k < 0 ) + { + *delta_pit = mult( *delta_pit, -32768 ); + move16(); + } + tmp16 = mult( *delta_pit, 10923 ); + if ( k < 0 ) + { + tmp16 = mult( tmp16, -32768 ); + } + *delta_pit = tmp16; + move16(); + } + + /*--------------------------------------------------------------* + * Update old pitch, upsample pitch, + *--------------------------------------------------------------*/ + + *old_pitch = pitch[1]; + move16(); + + FOR( i = 0; i < NHFR; i++ ) + { + /* compensate decimation */ + pitch[i] = i_mult2( pitch[i], OPL_DECIM ); + move16(); + } + + return; +} + +void pitch_ol_ivas_fx( + Word16 pitch[3], /* o : open loop pitch lag for each half-frame in range [29,231] Q0 */ + Word16 voicing[3], /* o : maximum normalized correlation for each half-frame in [0,1.0[ Q15 */ + Word16 *old_pitch, /* i/o: pitch of the 2nd half-frame of previous frame (i.e. pitch[1]) Q0 */ + Word16 *old_corr, /* i/o: correlation of old_pitch (i.e. voicing[1] or corr_mean) Q15 */ + Word16 corr_shift, /* i : normalized correlation correction Q15 */ + Word16 *old_thres, /* i/o: maximum correlation weighting with respect to past frame pitch Q14 */ + Word16 *delta_pit, /* i/o: old pitch extrapolation correction in range [-14,+14] Q0 */ + Word16 *st_old_wsp2, /* i/o: weighted speech memory qwsp */ + const Word16 *wsp, /* i : weighted speech for current frame and look-ahead qwsp */ + Word16 mem_decim2[3], /* i/o: wsp decimation filter memory qwsp */ + const Word16 relE, /* i : relative frame energy Q8 */ + const Word16 last_class, /* i : frame classification of last frame */ + const Word16 bwidth, /* i : bandwidth */ + const Word16 Opt_SC_VBR, /* i : SC-VBR flag */ + Word16 qwsp /* i : Q factor for wsp Q0 */ +) +{ + Word16 ftmp, old_wsp2[( L_WSP - L_INTERPOL ) / OPL_DECIM], *wsp2; + Word16 tmp_mem[3]; + + Word16 scale1[2 * DELTA_COH - 1]; + Word16 scaled_buf[2 * LEN_X + 3 * ( DELTA_COH - 1 )]; + Word16 scaled_buf_exp[2 * LEN_X + 3 * ( DELTA_COH - 1 )]; + Word16 cor_buf[2 * LEN_X], cor_buf_exp[2 * LEN_X]; + Word16 *pt1, *pt2, *pt3, *pt4, *pt5, *pt6; + Word16 *pt_cor0, *pt_cor1, *pt_cor2, *pt_cor3, *pt_cor4; + Word16 *pt_cor0_exp, *pt_cor1_exp, *pt_cor2_exp, *pt_cor3_exp, *pt_cor4_exp; + Word16 thres1[6]; + Word16 diff, cnt, ind, ind1, offset, offset1, offset_la, offset_la1, coh_flag, coh_flag1; + Word16 ind_corX, ind1_corX; + + Word16 i, j, k, m, pit_min, pit_min1, sect0, subsect0, add_sect0, sub_sect0, old_tmp, old_tmp1, len_x, len_x1; + Word16 len_temp; + Word16 pitchX[NHFR][2 * NSECT], pitch_tmp[2 * NHFR], ind_tmp[2 * NHFR], tmp_buf[NHFR + 1]; + + Word16 enr0_exp[NSECT], enr0_1_exp[NSECT], enr1_exp; + Word32 enr0[NSECT], enr0_1[NSECT], enr1; + Word64 temp, temp1; + Word32 Ltmp; + Word16 fac, tmp16, tmp16_2; + Word16 scaledX[NHFR][2 * NSECT], corX[NHFR][2 * NSECT], cor_tmp[2 * NHFR], cor_mean; + const Word16 *len, *len1, *sublen, *sublen1, *pit_max, *sec_length, *sec_length1; + + Word16 pit_min_coding; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + Word16 new_q; + new_q = sub( 63, shl( qwsp, 1 ) ); + + /*--------------------------------------------------------------* + * Initialization + *--------------------------------------------------------------*/ + len = len_12k8; + len1 = len1_12k8; + sublen = sublen_12k8; + sublen1 = sublen1_12k8; + pit_max = pit_max_12k8; + sec_length = sec_length_12k8; + sec_length1 = sec_length1_12k8; + + test(); + if ( ( LT_16( last_class, VOICED_TRANSITION ) ) && ( NE_16( bwidth, NB ) ) ) + { + /*reset last pitch reinforcement in case of unvoiced or transitions: it avoids some pitch doublings*/ + *old_thres = 0; + move16(); + } + + pit_min_coding = PIT_MIN_EXTEND; + move16(); + test(); + test(); + test(); + test(); + IF( ( ( NE_16( bwidth, NB ) ) && ( GT_16( *old_pitch, PIT_MIN ) ) ) || + ( ( EQ_16( bwidth, NB ) ) && ( ( GT_16( *old_pitch, PIT_MIN2_1 ) ) || ( LT_16( *old_thres, 1638 /* 0.1 in Q14*/ ) ) ) ) ) + { + pit_min = PIT_MIN / OPL_DECIM; + move16(); + pit_min1 = PIT_MIN_1 / OPL_DECIM; + move16(); + subsect0 = 2; + move16(); + sect0 = 1; + move16(); + } + ELSE + { + pit_min = PIT_MIN2 / OPL_DECIM; + move16(); + pit_min1 = PIT_MIN2_1 / OPL_DECIM; + move16(); + subsect0 = 0; + move16(); + sect0 = 0; + move16(); + } + + len_x = ( PIT_MAX / OPL_DECIM - pit_min + 1 ); + move16(); + len_x1 = ( PIT_MAX / OPL_DECIM - pit_min1 + 1 ); + move16(); + + /*--------------------------------------------------------------* + * Find decimated weighted speech + * Update wsp buffer with the memory + * decimation of wsp[] to search pitch in LF and to reduce complexity + * Extend the decimation of wsp to the end of the speech buffer + * Update wsp memory + *--------------------------------------------------------------*/ + Copy( st_old_wsp2, old_wsp2, ( L_WSP_MEM - L_INTERPOL ) / OPL_DECIM ); + wsp2 = old_wsp2 + ( ( L_WSP_MEM - L_INTERPOL ) / OPL_DECIM ); + + LP_Decim2_Copy( wsp, wsp2, L_FRAME, mem_decim2 ); + + /* Avoid uninitialized memory access */ + set16_fx( wsp2 + L_FRAME / 2, 0, sizeof( old_wsp2 ) / sizeof( Word16 ) - ( ( L_WSP_MEM - L_INTERPOL ) / OPL_DECIM ) - L_FRAME / 2 ); + tmp_mem[0] = mem_decim2[0]; + move16(); + tmp_mem[1] = mem_decim2[1]; + move16(); + tmp_mem[2] = mem_decim2[2]; + move16(); + + LP_Decim2_Copy( &wsp[L_FRAME], &wsp2[L_FRAME / 2], L_LOOK_12k8, tmp_mem ); /* shr() used instead of division by OPL_DECIM*/ + + Copy( &old_wsp2[L_FRAME / 2], st_old_wsp2, ( L_WSP_MEM - L_INTERPOL ) / OPL_DECIM ); + + /*-----------------------------------------------------------------* + * Attenuate the correlation correction factor due to noise. + * Reset correlation buffer outside the useful range. + * Find the scaling functions for immediate neigbours and + * further ones. + *-----------------------------------------------------------------*/ + + corr_shift = shr( corr_shift, 1 ); + + set16_fx( scaled_buf, 0, DELTA_COH - 1 ); + set16_fx( scaled_buf + ( DELTA_COH - 1 ) + len_x, 0, DELTA_COH - 1 ); + set16_fx( scaled_buf + 2 * ( DELTA_COH - 1 ) + len_x + len_x1, 0, DELTA_COH - 1 ); + set16_fx( scaled_buf_exp, 0, len_x + len_x1 + 3 * ( DELTA_COH - 1 ) ); + + pt1 = scale1 + DELTA_COH - 1; + pt2 = pt1; + tmp16 = mult( *old_thres, -32768 / DELTA_COH ); // Q14 + k = add( *old_thres, ONE_IN_Q14 ); // Q14 + FOR( i = 0; i < DELTA_COH; i++ ) + { + *pt1 = k; // Q14 + *pt2-- = *pt1++; // Q14 + move16(); + move16(); + + k = add( k, tmp16 ); // Q14 + } + + /*-----------------------------------------------------------------------------* + * Estimate the new pitch by extrapolating the old pitch value for 2 half-frames + *-----------------------------------------------------------------------------*/ + old_tmp = add( *old_pitch, *delta_pit ); + old_tmp = s_min( old_tmp, PIT_MAX / OPL_DECIM ); + old_tmp = s_max( old_tmp, pit_min ); + old_tmp1 = add( old_tmp, *delta_pit ); + old_tmp1 = s_min( old_tmp1, PIT_MAX / OPL_DECIM ); + old_tmp1 = s_max( old_tmp1, pit_min ); + + /*-----------------------------------------------------------------* + * Loop for all three half-frames (current frame + look-ahead) + *-----------------------------------------------------------------*/ + pt_cor0 = scaled_buf + DELTA_COH - 1; + pt_cor0_exp = scaled_buf_exp + DELTA_COH - 1; + + pt_cor2 = pt_cor0 - pit_min + old_tmp; + pt_cor2_exp = pt_cor0_exp - pit_min + old_tmp; + + pt_cor4 = pt_cor0 - pit_min1 + old_tmp + ( DELTA_COH - 1 ) + len_x; + pt_cor4_exp = pt_cor0_exp - pit_min1 + old_tmp + ( DELTA_COH - 1 ) + len_x; + + FOR( i = 0; i < NHFR; i++ ) /* i = 0, 1, 2 */ + { + pt1 = wsp2 + i * 2 * ( L_SUBFR / OPL_DECIM ); /* *pt1 -> Q12 */ + pt2 = pt1 - pit_min; /* *pt2 -> Q12 */ + pt4 = pt1 - pit_min1; /* *pt4 -> Q12 */ + + temp = 0; + move64(); + + pt_cor1 = pt_cor0; + pt_cor1_exp = pt_cor0_exp; + + pt_cor3 = pt_cor0 + ( DELTA_COH - 1 ) + len_x; + pt_cor3_exp = pt_cor0_exp + ( DELTA_COH - 1 ) + len_x; + + IF( LT_16( i, NHFR - 1 ) ) /* First two half-frames (current frame) */ + { + pt3 = pt1; + pt5 = pt1; + + FOR( j = sect0; j < NSECT; j++ ) /* loop for each section */ + { + /*-----------------------------------------------------------------* + * Find fixed vector energy + *-----------------------------------------------------------------*/ + + /* 1st set */ + k = (Word16) ( pt1 - pt3 ); + move16(); + FOR( k = add( k, len[j] ); k > 0; k-- ) + { + temp = W_mac0_16_16( temp, *pt3, *pt3 ); // 2*qwsp + pt3++; + } + IF( temp == 0 ) + { + enr0[j] = 21474836; // 0.01 in Q31 + enr0_exp[j] = 0; + move32(); + move16(); + } + ELSE + { + cnt = W_norm( temp ); + enr0[j] = W_extract_h( W_shl( temp, cnt ) ); // 2*qwsp+cnt-32 + enr0_exp[j] = sub( new_q, cnt ); // 31-(2*qwsp+cnt-32) + move32(); + move16(); + } + + /* Reduce complexity (length of 'enr2' section is equal or larger than 'enr') */ + pt5 = pt3; + + /* 2nd set */ + k = (Word16) ( pt1 - pt5 ); + move16(); + + temp1 = temp; + move64(); + FOR( k = ( k + len1[j] ); k > 0; k-- ) + { + temp1 = W_mac0_16_16( temp1, *pt5, *pt5 ); // 2*qwsp + pt5++; + } + IF( temp1 == 0 ) + { + enr0_1[j] = 21474836; // 0.01 in Q31 + enr0_1_exp[j] = 0; + move32(); + move16(); + } + ELSE + { + cnt = W_norm( temp1 ); + enr0_1[j] = W_extract_h( W_shl( temp1, cnt ) ); // 2*qwsp+cnt-32 + enr0_1_exp[j] = sub( new_q, cnt ); // 31-(2*qwsp+cnt-32) + move32(); + move16(); + } + } + + /*----------------------------------------------------------* + * Find correlation for the non-overlapping pitch lag values + *----------------------------------------------------------*/ + + k = (Word16) ( pt2 - pt1 + pit_max[subsect0] ); + move16(); + + FOR( ; k >= 0; k-- ) + { + temp = 0; + move64(); + FOR( m = 0; m < sublen[0]; m++ ) + { + temp = W_mac0_16_16( temp, pt1[m], pt2[m] ); // 2*qwsp + } + cnt = W_norm( temp ); + *pt_cor1 = extract_h( W_extract_h( W_shl( temp, cnt ) ) ); // 2*qwsp+cnt-32-16 + *pt_cor1_exp = sub( new_q, cnt ); // 15-(2*qwsp+cnt-32-16) + move16(); + move16(); + + pt2--; + pt_cor1++; + pt_cor1_exp++; + } + + /*----------------------------------------------------------* + * For each subsection, find the correlation + *----------------------------------------------------------*/ + FOR( j = subsect0; j < NSUBSECT; j++ ) + { + len_temp = sublen[j]; + move16(); + + k = (Word16) ( pt2 - pt1 ); + move16(); + k = add( k, pit_max[j + 1] ); + + /* Keep Q15 normalized result */ + IF( LT_16( sublen[j], sublen1[j] ) ) + { + FOR( ; k >= 0; k-- ) + { + temp = W_mult0_16_16( pt1[0], pt2[0] ); // 2*qwsp + FOR( m = 1; m < sublen[j]; m++ ) + { + temp = W_mac0_16_16( temp, pt1[m], pt2[m] ); // 2*qwsp + } + cnt = W_norm( temp ); + *pt_cor1 = extract_h( W_extract_h( W_shl( temp, cnt ) ) ); // 2*qwsp+cnt-32-16 + *pt_cor1_exp = sub( new_q, cnt ); + move16(); + move16(); + + FOR( ; m < sublen1[j]; m++ ) + { + temp = W_mac0_16_16( temp, pt1[m], pt2[m] ); // 2*qwsp + } + cnt = W_norm( temp ); + *pt_cor3 = extract_h( W_extract_h( W_shl( temp, cnt ) ) ); // 2*qwsp+cnt-32-16 + *pt_cor3_exp = sub( new_q, cnt ); + move16(); + move16(); + + pt_cor1++; + pt_cor1_exp++; + pt_cor3++; + pt_cor3_exp++; + pt2--; + } + } + ELSE + { + FOR( ; k >= 0; k-- ) + { + temp = W_mult0_16_16( pt1[0], pt2[0] ); // 2*qwsp + FOR( m = 1; m < sublen1[j]; m++ ) + { + temp = W_mac0_16_16( temp, pt1[m], pt2[m] ); // 2*qwsp + } + cnt = W_norm( temp ); + *pt_cor3 = extract_h( W_extract_h( W_shl( temp, cnt ) ) ); // 2*qwsp+cnt-32-16 + *pt_cor3_exp = sub( new_q, cnt ); + move16(); + move16(); + + FOR( ; m < sublen[j]; m++ ) + { + temp = W_mac0_16_16( temp, pt1[m], pt2[m] ); // 2*qwsp + } + cnt = W_norm( temp ); + *pt_cor1 = extract_h( W_extract_h( W_shl( temp, cnt ) ) ); // 2*qwsp+cnt-32-16 + *pt_cor1_exp = sub( new_q, cnt ); + move16(); + move16(); + + pt_cor1++; + pt_cor1_exp++; + pt_cor3++; + pt_cor3_exp++; + pt2--; + } + } + } /* FOR (j = subsect0; ... */ + } + ELSE /* 3rd half-frame (look-ahead) */ + { + pt6 = pt1 + L_LOOK_12k8 / OPL_DECIM - 1; + pt3 = pt6; + pt5 = pt6; + + /*-----------------------------------------------------------------* + * For each section in both sets, find fixed vector energy + *-----------------------------------------------------------------*/ + FOR( j = sect0; j < NSECT; j++ ) /* loop for each section */ + { + /* 1st set */ + k = (Word16) ( pt3 - pt6 ); + move16(); + + FOR( k = add( k, len[j] ); k > 0; k-- ) + { + temp = W_mac0_16_16( temp, *pt3, *pt3 ); + pt3--; + } + IF( temp == 0 ) + { + enr0[j] = 21474836; // 0.01 in Q31 + enr0_exp[j] = 0; + move32(); + move16(); + } + ELSE + { + cnt = W_norm( temp ); + enr0[j] = W_extract_h( W_shl( temp, cnt ) ); // 2*qwsp+cnt-32 + enr0_exp[j] = sub( new_q, cnt ); // 31-(2*qwsp+cnt-32) + move32(); + move16(); + } + + /* Reduce complexity (length of 'enr2' section is equal or larger than 'enr') */ + pt5 = pt3; + temp1 = temp; + move64(); + + /* 2nd set */ + k = (Word16) ( pt5 - pt6 ); + move16(); + FOR( k = add( k, len1[j] ); k > 0; k-- ) + { + temp1 = W_mac0_16_16( temp1, *pt5, *pt5 ); // 2*qwsp + pt5--; + } + IF( temp1 == 0 ) + { + enr0_1[j] = 21474836; // 0.01 in Q31 + enr0_1_exp[j] = 0; + move32(); + move16(); + } + ELSE + { + cnt = W_norm( temp1 ); + temp1 = W_shl( temp1, cnt ); // 2*qwsp+cnt + enr0_1[j] = W_extract_h( temp1 ); // 2*qwsp+cnt-32 + enr0_1_exp[j] = sub( new_q, cnt ); // 31-(2*qwsp+cnt-32) + move32(); + move16(); + } + } + + /* Set pointers: same as IF/ELSE block */ + pt2 = pt6 - pit_min; + k = 2; + move16(); + IF( sect0 != 0 ) + { + pt2 = pt6 - add( pit_max[1], 1 ); + k = sub( pit_max[2], pit_max[1] ); + move16(); + } + + /*-----------------------------------------------------------------* + * Find correlation for the non-overlapping pitch lag values + *-----------------------------------------------------------------*/ + + len_temp = sublen[0]; + move16(); + + FOR( ; k > 0; k-- ) + { + temp = 0; + move64(); + FOR( m = 0; m < len_temp; m++ ) + { + temp = W_mac0_16_16( temp, pt6[-m], pt2[-m] ); // 2*qwsp + } + tmp16_2 = W_norm( temp ); + *pt_cor1 = extract_h( W_extract_h( W_shl( temp, tmp16_2 ) ) ); // 2*qwsp+tmp16_2 + *pt_cor1_exp = sub( new_q, tmp16_2 ); // 2*qwsp+tmp16_2-32-16 + move16(); + move16(); + + pt_cor1++; + pt_cor1_exp++; + pt2--; + } + + /*-----------------------------------------------------------------* + * For each subsection, find the correlation (overlapping pitch lag values) + *-----------------------------------------------------------------*/ + + FOR( j = subsect0; j < NSUBSECT; j++ ) + { + k = sub( pit_max[j + 1], pit_max[j] ); + + IF( LT_16( sublen[j], sublen1[j] ) ) + { + FOR( ; k > 0; k-- ) + { + temp = W_mult0_16_16( pt6[0], pt2[0] ); // 2*qwsp + FOR( m = 1; m < sublen[j]; m++ ) + { + temp = W_mac0_16_16( temp, pt6[-m], pt2[-m] ); // 2*qwsp + } + cnt = W_norm( temp ); + *pt_cor1 = extract_h( W_extract_h( W_shl( temp, cnt ) ) ); // 2*qwsp+cnt-32-16 + *pt_cor1_exp = sub( new_q, cnt ); + move16(); + move16(); + + FOR( ; m < sublen1[j]; m++ ) + { + temp = W_mac0_16_16( temp, pt6[-m], pt2[-m] ); // 2*qwsp + } + cnt = W_norm( temp ); + *pt_cor3 = extract_h( W_extract_h( W_shl( temp, cnt ) ) ); // 2*qwsp+cnt-32-16 + *pt_cor3_exp = sub( new_q, cnt ); + move16(); + move16(); + + pt_cor1++; + pt_cor1_exp++; + pt_cor3++; + pt_cor3_exp++; + pt2--; + } + } + ELSE + { + FOR( ; k > 0; k-- ) + { + temp = W_mult0_16_16( pt6[0], pt2[0] ); // 2*qwsp + FOR( m = 1; m < sublen1[j]; m++ ) + { + temp = W_mac0_16_16( temp, pt6[-m], pt2[-m] ); // 2*qwsp + } + cnt = W_norm( temp ); + *pt_cor3 = extract_h( W_extract_h( W_shl( temp, cnt ) ) ); // 2*qwsp+cnt-32-16 + *pt_cor3_exp = sub( new_q, cnt ); + move16(); + move16(); + + FOR( ; m < sublen[j]; m++ ) + { + temp = W_mac0_16_16( temp, pt6[-m], pt2[-m] ); // 2*qwsp + } + cnt = W_norm( temp ); + *pt_cor1 = extract_h( W_extract_h( W_shl( temp, cnt ) ) ); // 2*qwsp+cnt-32-16 + *pt_cor1_exp = sub( new_q, cnt ); + move16(); + move16(); + + pt_cor1++; + pt_cor1_exp++; + pt_cor3++; + pt_cor3_exp++; + pt2--; + } + } + } + } /* 3rd half-frame (look-ahead) */ + + /* Scale all values in each section to the same exponent for upcoming Find_max() */ + Copy( pt_cor0, cor_buf, len_x ); /* Save unscaled correlation vector */ + Copy( pt_cor0_exp, cor_buf_exp, len_x ); /* Save unscaled correlation vector */ + Copy( pt_cor0 + ( DELTA_COH - 1 ) + len_x, cor_buf + len_x, len_x1 ); + Copy( pt_cor0_exp + ( DELTA_COH - 1 ) + len_x, cor_buf_exp + len_x, len_x1 ); + + /*-----------------------------------------------------------------* + * Scale correlation function in the neighbourhood of + * the extrapolated pitch + *-----------------------------------------------------------------*/ + pt_cor1 = pt_cor2 - ( DELTA_COH - 1 ); + pt_cor1_exp = pt_cor2_exp - ( DELTA_COH - 1 ); + pt_cor3 = pt_cor4 - ( DELTA_COH - 1 ); + pt_cor3_exp = pt_cor4_exp - ( DELTA_COH - 1 ); + pt2 = scale1; + + FOR( k = 0; k < 2 * DELTA_COH - 1; k++ ) + { + *pt_cor1 = mult( *pt_cor1, *pt2 ); // *pt_cor1_exp+1 + *pt_cor1_exp = add( *pt_cor1_exp, 1 ); // *pt_cor1_exp+1 + move16(); + move16(); + + *pt_cor3 = mult( *pt_cor3, *pt2++ ); // *pt_cor3_exp+1 + *pt_cor3_exp = add( *pt_cor3_exp, 1 ); // *pt_cor1_exp+1 + move16(); + move16(); + + pt_cor1++; + pt_cor1_exp++; + pt_cor3++; + pt_cor3_exp++; + } + + /* Update for next half-frame & look-ahead */ + pt_cor2 = pt_cor0 - pit_min + old_tmp1; + pt_cor2_exp = pt_cor0_exp - pit_min + old_tmp1; + + pt_cor4 = pt_cor0 - pit_min1 + old_tmp1 + ( DELTA_COH - 1 ) + len_x; + pt_cor4_exp = pt_cor0_exp - pit_min1 + old_tmp1 + ( DELTA_COH - 1 ) + len_x; + + /*-----------------------------------------------------------------* + * For each section, find maximum correlation and compute + * normalized correlation + *-----------------------------------------------------------------*/ + + pt_cor1 = pt_cor0; + pt_cor1_exp = pt_cor0_exp; + offset = 0; + move16(); + pt_cor3 = pt_cor0 + ( DELTA_COH - 1 ) + len_x; + pt_cor3_exp = pt_cor0_exp + ( DELTA_COH - 1 ) + len_x; + offset1 = 0; + move16(); + + FOR( j = sect0; j < NSECT; j++ ) /* loop for each section */ + { + /* 1st set */ + offset_la = 0; + move16(); + if ( EQ_16( i, 2 ) ) + { + offset_la = sub( L_LOOK_12k8 / OPL_DECIM, len[j] ); + } + + /* 2nd set */ + offset_la1 = 0; + move16(); + if ( EQ_16( i, 2 ) ) + { + offset_la1 = sub( L_LOOK_12k8 / OPL_DECIM, len1[j] ); + } + + /* 1st set of candidates */ + ind = add( maximum_exp_fx( pt_cor1, pt_cor1_exp, sec_length[j] ), offset ); + pitchX[i][j] = add( ind, pit_min ); + move16(); + pt2 = pt1 - pitchX[i][j] + /*-*/ offset_la; /* selected moving vector */ + + enr1_exp = 0; + move16(); + + /* enr1 = dotp( pt2, pt2, len[j] ) + 0.01f; */ + temp = 0; + move64(); + FOR( m = 0; m < len[j]; m++ ) + { + temp = W_mac0_16_16( temp, pt2[m], pt2[m] ); // 2*qwsp + } + + temp = W_shl( temp, sub( Q24, shl( qwsp, 1 ) ) ); // Q24 + + temp = W_add( temp, 167772 ); /*0.01f in Q24*/ + + enr1_exp = W_norm( temp ); + enr1 = W_extract_h( W_shl( temp, enr1_exp ) ); // enr1_exp+24-32 + enr1_exp = sub( 39, enr1_exp ); // 31-(enr1_exp+24-32) + + enr1 = Mpy_32_32( enr0[j], enr1 ); + enr1_exp = add( enr0_exp[j], enr1_exp ); + + enr1 = ISqrt32( enr1, &enr1_exp ); /* 1/sqrt(energy) */ /*31-enr2_exp*/ + + Ltmp = Mpy_32_16_1( enr1, cor_buf[ind] ); + corX[i][j] = extract_h( L_shl_o( Ltmp, add( enr1_exp, cor_buf_exp[ind] ), &Overflow ) ); // Q15 + move16(); + + Ltmp = Mpy_32_16_1( enr1, pt_cor0[ind] ); + scaledX[i][j] = round_fx( L_shl( Ltmp, sub( add( enr1_exp, pt_cor0_exp[ind] ), 3 ) ) ); // Q12 + move16(); + + pt_cor1 += sec_length[j]; + pt_cor1_exp += sec_length[j]; + offset = add( offset, sec_length[j] ); + + /* 2nd set of candidates */ + ind1 = add( maximum_exp_fx( pt_cor3, pt_cor3_exp, sec_length1[j] ), offset1 ); + pitchX[i][j + NSECT] = add( ind1, pit_min1 ); + move16(); + pt4 = pt1 - pitchX[i][j + NSECT] + /*-*/ offset_la1; + move16(); /* selected moving vector */ + enr1_exp = 0; + move16(); + + /* enr1 = dotp(pt4, pt4, len1[j]) + 0.01f; */ + temp = 0; + move64(); + move64(); + FOR( m = 0; m < len1[j]; m++ ) + { + temp = W_mac0_16_16( temp, pt4[m], pt4[m] ); // 2*qwsp + } + + temp = W_shl( temp, sub( Q24, shl( qwsp, 1 ) ) ); // Q24 + + temp = W_add( temp, 167772 ); /*0.01f in Q24*/ + + enr1_exp = W_norm( temp ); + enr1 = W_extract_h( W_shl( temp, enr1_exp ) ); // enr1_exp+24-32 + enr1_exp = sub( 39, enr1_exp ); // 31-(enr1_exp+24-32) + + enr1 = Mpy_32_32( enr0_1[j], enr1 ); + enr1_exp = add( enr0_1_exp[j], enr1_exp ); + + enr1 = ISqrt32( enr1, &enr1_exp ); /* 1/sqrt(energy) */ /*31-enr1_exp*/ + + Ltmp = Mpy_32_16_1( enr1, cor_buf[ind1 + len_x] ); + corX[i][j + NSECT] = extract_h( L_shl_o( Ltmp, add( enr1_exp, cor_buf_exp[ind1 + len_x] ), &Overflow ) ); // Q15 + move16(); + + Ltmp = Mpy_32_16_1( enr1, pt_cor0[ind1 + ( DELTA_COH - 1 ) + len_x] ); + scaledX[i][j + NSECT] = round_fx( L_shl( Ltmp, sub( add( enr1_exp, pt_cor0_exp[ind1 + ( DELTA_COH - 1 ) + len_x] ), 3 ) ) ); // Q12 + move16(); + /*scaledX[i][j+NSECT] = saturate(L_shr(Ltmp, qScaledX-12));*/ + + pt_cor3 += sec_length1[j]; + pt_cor3_exp += sec_length1[j]; + offset1 = add( offset1, sec_length1[j] ); + + } /* FOR j < NSECT */ + } /* FOR i < NHFR */ + + /*-----------------------------------------------------------------* + * Favor a smaller delay if it happens that it has its multiple + * in the longer-delay sections (harmonics check) + *-----------------------------------------------------------------*/ + + FOR( i = 0; i < 2; i++ ) /* loop for the 2 half-frames */ + { + fac = THRES0; + move16(); + find_mult_fx( &fac, pitchX[i][2], pitchX[i][3], pit_max[7], &scaledX[i][2], old_pitch, old_corr, DELTA0, STEP ); /* Multiples in 3rd section */ + find_mult_fx( &fac, pitchX[i][1], pitchX[i][2], pit_max[5], &scaledX[i][1], old_pitch, old_corr, DELTA0, STEP ); /* Multiples in 2nd section */ + test(); + IF( ( sect0 == 0 ) && GE_16( shl( pitchX[i][0], 1 ), pit_min_coding ) ) + { + find_mult_fx( &fac, pitchX[i][0], pitchX[i][1], pit_max[3], &scaledX[i][0], old_pitch, old_corr, DELTA0, STEP ); /* Multiples in 2nd section */ + } + fac = THRES0; + move16(); + find_mult_fx( &fac, pitchX[i][NSECT + 2], pitchX[i][NSECT + 3], pit_max[7], &scaledX[i][NSECT + 2], old_pitch, old_corr, DELTA0, STEP ); /* Multiples in 3rd section */ + find_mult_fx( &fac, pitchX[i][NSECT + 1], pitchX[i][NSECT + 2], pit_max[6], &scaledX[i][NSECT + 1], old_pitch, old_corr, DELTA0, STEP ); /* Multiples in 2nd section */ + test(); + IF( ( sect0 == 0 ) && GE_16( shl( pitchX[i][NSECT + 0], 1 ), pit_min_coding ) ) + { + find_mult_fx( &fac, pitchX[i][NSECT + 0], pitchX[i][NSECT + 1], pit_max[4], &scaledX[i][NSECT + 0], old_pitch, old_corr, DELTA0, STEP ); /* Multiples in 2nd section */ + } + } + + fac = THRES0; + move16(); /* the look-ahead */ + find_mult_fx( &fac, pitchX[i][2], pitchX[i][3], pit_max[7], &scaledX[i][2], old_pitch, old_corr, 2, 2 ); /* Multiples in 3rd section */ + find_mult_fx( &fac, pitchX[i][1], pitchX[i][2], pit_max[5], &scaledX[i][1], old_pitch, old_corr, DELTA0, STEP ); /* Multiples in 2nd section */ + test(); + IF( ( sect0 == 0 ) && GE_16( shl( pitchX[i][0], 1 ), pit_min_coding ) ) + { + find_mult_fx( &fac, pitchX[i][0], pitchX[i][1], pit_max[3], &scaledX[i][0], old_pitch, old_corr, DELTA0, STEP ); /* Multiples in 2nd section */ + } + fac = THRES0; + move16(); + find_mult_fx( &fac, pitchX[i][NSECT + 2], pitchX[i][NSECT + 3], pit_max[7], &scaledX[i][NSECT + 2], old_pitch, old_corr, 2, 2 ); /* Multiples in 3rd section */ + find_mult_fx( &fac, pitchX[i][NSECT + 1], pitchX[i][NSECT + 2], pit_max[6], &scaledX[i][NSECT + 1], old_pitch, old_corr, DELTA0, STEP ); /* Multiples in 2nd section */ + test(); + IF( ( sect0 == 0 ) && GE_16( shl( pitchX[i][NSECT + 0], 1 ), pit_min_coding ) ) + { + find_mult_fx( &fac, pitchX[i][NSECT + 0], pitchX[i][NSECT + 1], pit_max[4], &scaledX[i][NSECT + 0], old_pitch, old_corr, DELTA0, STEP ); /* Multiples in 2nd section */ /* Multiples in 2nd section */ + } + + /*-----------------------------------------------------------------* + * Do 1st estimate for pitch values + * Adjust the normalized correlation using estimated noise level + * Compute the maximum scaling for the neighbour correlation + * reinforcement + *-----------------------------------------------------------------*/ + add_sect0 = add( NSECT, sect0 ); + sub_sect0 = sub( NSECT, sect0 ); + FOR( i = 0; i < NHFR; i++ ) + { + /* 1st set of pitch candidates */ + ind = add( maximum_fx( scaledX[i] + sect0, sub_sect0, &ftmp ), sect0 ); + ind_tmp[i] = ind; + move16(); + pitch_tmp[i] = pitchX[i][ind]; + move16(); + cor_tmp[i] = add_o( corX[i][ind], corr_shift, &Overflow ); + move16(); + + /* Higher is the neighbour's correlation, higher is the weighting */ + /* operands are Q15, result is Q15 */ + thres1[i] = mult( THRES1, cor_tmp[i] ); + move16(); + + /* 2nd set of pitch candidates */ + ind1 = add( maximum_fx( scaledX[i] + add_sect0, sub_sect0, &ftmp ), add_sect0 ); + ind_tmp[i + NHFR] = ind1; + move16(); + pitch_tmp[i + NHFR] = pitchX[i][ind1]; + move16(); + cor_tmp[i + NHFR] = add_o( corX[i][ind1], corr_shift, &Overflow ); + move16(); + + /* Higher is the neighbour's correlation, higher is the weighting */ + /* operands are Q15, result is Q15 */ + thres1[i + NHFR] = mult( THRES1, cor_tmp[i + NHFR] ); + move16(); + } + /*-----------------------------------------------------------------* + * Take into account previous and next pitch values of the present + * frame and look-ahead. Choose the pitch lags and normalize + * correlations for each half-frame & look-ahead + *-----------------------------------------------------------------*/ + + pitch_neighbour_fx( sect0, pitch_tmp, pitchX, cor_tmp, scaledX, thres1, ind_tmp ); + FOR( i = 0; i < NHFR; i++ ) + { + ind = add( maximum_fx( scaledX[i] + sect0, sub_sect0, &ftmp ), sect0 ); + ind_corX = add( maximum_fx( corX[i] + sect0, sub_sect0, &ftmp ), sect0 ); + + ind1 = add( maximum_fx( scaledX[i] + add_sect0, sub_sect0, &ftmp ), add_sect0 ); + ind1_corX = add( maximum_fx( corX[i] + add_sect0, sub_sect0, &ftmp ), add_sect0 ); + + if ( GT_16( scaledX[i][ind1], scaledX[i][ind] ) ) + { + ind = ind1; + move16(); + } + test(); + if ( Opt_SC_VBR && GT_16( corX[i][ind1_corX], corX[i][ind_corX] ) ) + { + ind_corX = ind1_corX; + move16(); + } + test(); + test(); + test(); + IF( Opt_SC_VBR && ( LT_16( mult( pitchX[i][ind], 13107 /*0.4 in Q15*/ ), pitchX[i][ind_corX] ) ) && + ( GT_16( mult( pitchX[i][ind], 19661 /*0.6 in Q15*/ ), pitchX[i][ind_corX] ) ) && + ( GE_16( corX[i][ind_corX], 29491 /*0.9 in Q15*/ ) ) ) + { + pitch[i] = pitchX[i][ind_corX]; + move16(); + voicing[i] = corX[i][ind_corX]; + move16(); + } + ELSE + { + pitch[i] = pitchX[i][ind]; + move16(); + voicing[i] = corX[i][ind]; + move16(); + } + } + + /*-----------------------------------------------------------------* + * Increase the threshold for correlation reinforcement with + * the past if correlation high and pitch stable + *-----------------------------------------------------------------*/ + + /* all Q15 here */ + /* cor_mean = 0.5f * (voicing[0] + voicing[1]) + corr_shift; */ + Ltmp = L_mult( voicing[0], 16384 /*.5 Q15*/ ); + Ltmp = L_mac( Ltmp, voicing[1], 16384 /*.5 Q15*/ ); + cor_mean = round_fx( L_add( Ltmp, corr_shift ) ); + + /* pitch unstable in present frame or from previous frame or normalized correlation too low */ + coh_flag = pitch_coherence_fx( pitch[0], pitch[1], COH_FAC, DELTA_COH ); + move16(); + coh_flag1 = pitch_coherence_fx( pitch[0], *old_pitch, COH_FAC, DELTA_COH ); + move16(); + + test(); + test(); + test(); + IF( ( coh_flag == 0 ) || ( coh_flag1 == 0 ) || ( LT_16( cor_mean, CORR_TH0 ) ) || ( LT_16( relE, THR_relE ) ) ) + { + /* Reset the threshold */ + *old_thres = 0; + move16(); + } + ELSE + { + /* The threshold increase is directly dependent on normalized correlation */ + /* *old_thres += (0.16f * cor_mean); */ + *old_thres = round_fx( L_mac0( L_deposit_h( *old_thres ), 5243 /* 0.16f in Q15 */, cor_mean ) ); // Q14 + move16(); + } + + *old_thres = s_min( *old_thres, 11469 /* 0.7f in Q14 */ ); // Q14 + move16(); + + IF( GT_16( voicing[1], voicing[0] ) ) + { + *old_corr = voicing[1]; + move16(); + } + ELSE + { + *old_corr = cor_mean; + move16(); + } + + /*-----------------------------------------------------------------* + * Extrapolate the pitch value for the next frame by estimating + * the pitch evolution. This value is added to the old_pitch + * in the next frame and is then used when the normalized + * correlation is reinforced by the past estimate + *-----------------------------------------------------------------*/ + tmp_buf[0] = *old_pitch; + move16(); + FOR( i = 0; i < NHFR; i++ ) + { + tmp_buf[i + 1] = pitch[i]; + move16(); + } + + *delta_pit = 0; + move16(); + cnt = 0; + move16(); + + FOR( i = 0; i < NHFR; i++ ) + { + diff = sub( tmp_buf[i + 1], tmp_buf[i] ); + move16(); + coh_flag = pitch_coherence_fx( tmp_buf[i], tmp_buf[i + 1], COH_FAC, DELTA_COH ); + + if ( coh_flag != 0 ) + { + *delta_pit = add( *delta_pit, diff ); + move16(); + } + cnt = add( cnt, coh_flag ); + } + if ( EQ_16( cnt, 2 ) ) + { + /* *delta_pit /= 2; */ + *delta_pit = shr( *delta_pit, 1 ); + move16(); + } + IF( EQ_16( cnt, 3 ) ) + { + k = *delta_pit; + move16(); + /* *delta_pit /= 3; */ + if ( k < 0 ) + { + *delta_pit = mult( *delta_pit, -32768 /*-1 Q15*/ ); + move16(); + } + tmp16 = mult( *delta_pit, 10923 /*1/3 Q15*/ ); + if ( k < 0 ) + { + tmp16 = mult( tmp16, -32768 /*-1 Q15*/ ); + } + *delta_pit = tmp16; + move16(); + } + + /*--------------------------------------------------------------* + * Update old pitch, upsample pitch, + *--------------------------------------------------------------*/ + + *old_pitch = pitch[1]; + move16(); + + FOR( i = 0; i < NHFR; i++ ) + { + /* compensate decimation */ + pitch[i] = i_mult2( pitch[i], OPL_DECIM ); + move16(); + } + + return; +} + + +/*-----------------------------------------------------------------* + * find_mult_fx + * + * Verifies whether max pitch delays in higher sections have multiples + * in lower sections + *-----------------------------------------------------------------*/ +static void find_mult_fx( + Word16 *fac, /* i/o: correlation scaling factor Q12 */ + Word16 pitch0, /* i : pitch of max correlation in the c section */ + Word16 pitch1, /* i : pitch of max correlation in the longer-delay section*/ + Word16 pit_max0, /* i : max pitch delay in the longer-delay section */ + Word16 *corr, /* i/o: max correlation in the shorter-delay section Q12 */ + Word16 *old_pitch, /* i : pitch from previous frame */ + Word16 *old_corr, /* i : max correlation from previous frame */ + Word16 delta, /* i : initial multiples search range */ + Word16 step /* i : increment in range of multiples search */ +) +{ + Word16 pit_min; + Word32 L_tmp; + + pit_min = shl( pitch0, 1 ); /* double the higher section pitch */ + + WHILE( LE_16( pit_min, add( pit_max0, delta ) ) ) /* check for section boundary */ + { + IF( LE_16( abs_s( sub( pit_min, pitch1 ) ), delta ) ) /* if multiple in the allowed range */ + { + L_tmp = L_shl( L_mult( *corr, *fac ), 3 ); + + /* if ( *old_corr < 0.6f || (float)pitch0 > (float)*old_pitch * 0.4f ) */ + IF( s_max( sub( 19660 /*.6 Q15*/, *old_corr ), sub( pitch0, mult( *old_pitch, 13107 /*.4 Q15*/ ) ) ) > 0 ) + { + /* reinforce the normalized correlation */ + /* operands are Q12, result is Q12 */ + *corr = extract_h( L_tmp ); + } + /* operands are Q12, result is Q12 */ + *fac = extract_h( L_shl( L_mult( *fac, THRES0 ), 3 ) ); + } + pit_min = add( pit_min, pitch0 ); /* next multiple */ + delta = add( delta, step ); /* the incertitude to the allowed range */ + } +} + +/*---------------------------------------------------------------------------* + * pitch_neighbour_fx + * + * Verifies if the maximum correlation pitch lag is coherent with neighbour + * values + *---------------------------------------------------------------------------*/ +static void pitch_neighbour_fx( + Word16 sect0, /* i : indicates whether section 0 (below PIT_MIN) is used */ + Word16 pitch_tmp[], /* i : estimated pitch values for each half-frame & look-ahead */ + Word16 pitch[3][2 * NSECT], /* i : tested pitch values for each half-frame & look-ahead */ + Word16 corr_tmp[], /* i : raw normalized correlation (before different scalings) Q15*/ + Word16 corr[3][2 * NSECT], /* i/o: normalized correlation for each half-frame & look-ahead Q12 */ + Word16 thres1[2 * NHFR], /* i : maximum scaling for the immediate neighbours Q15 */ + Word16 ind_tmp[2 * NHFR] /* i : best section index for each half-frame & look-ahead */ +) +{ + Word16 delta, i, j, k, K, coh_flag, fac; + + /*--------------------- + * 1st set of sections + ---------------------*/ + FOR( k = sect0; k < NSECT; k++ ) /* loop for each section */ + { + K = 3; + move16(); + if ( EQ_16( k, ( NSECT - 1 ) ) ) /* the number of tests depends on the section */ + { + K = 2; + move16(); + } + /*pt = &pitch[i][k] and pt = &corr[i][k]*/ + FOR( i = 0; i < K; i++ ) /* for the 2 half-frames and look-ahead */ + { + /* Compare pitch values of the present frame */ + FOR( j = 0; j < K; j++ ) /* Verify pitch coherence with neighbours (including past pitch) */ + { + IF( NE_16( j, i ) ) /* Exclude itself, of course */ + { + IF( GE_16( corr_tmp[j], CORR_TH1 ) ) /* reinforcement can happen only if the correlation is high enough */ + { + delta = abs_s( sub( pitch[i][k], pitch_tmp[j] ) ); /* Find difference of pitch values */ + coh_flag = pitch_coherence_fx( pitch[i][k], pitch_tmp[j], COH_FAC, DELTA_COH ); + + IF( coh_flag != 0 ) + { + /* Favour stability across sections, favour closer values */ + IF( EQ_16( ind_tmp[j], k ) ) + { + /* corr[i][k] *= ( -thres1[j]/DELTA1 * delta + thres1[j]+1 ); */ + /* operands are Q15, except corr[i][k] which is Q12 */ + fac = mult( negate( thres1[j] ), MAX_16 / DELTA_COH ); + fac = add( i_mult2( fac, delta ), thres1[j] ); + } + ELSE + { + /* corr[i][k] *= ( -thres1[j]/DELTA1 * 0.625f * delta + 0.625f * thres1[j] +1.0f ); */ + fac = mult( negate( thres1[j] ), 20479 / DELTA_COH ); + fac = add( i_mult2( fac, delta ), mult( 20479 /*.625 Q15*/, thres1[j] ) ); + } + corr[i][k] = add_sat( corr[i][k], mult( fac, corr[i][k] ) ); + move16(); + } + } + } + } + } + } + + /*--------------------- + * 2nd set of sections + ---------------------*/ + FOR( k = sect0; k < NSECT; k++ ) /* loop for each section */ + { + K = 3; + move16(); + if ( EQ_16( k, ( NSECT - 1 ) ) ) /* the number of tests depends on the section */ + { + K = 2; + move16(); + } + /*pt = &pitch[i][k] and pt = &corr[i][k]*/ + FOR( i = 0; i < K; i++ ) /* BRANCH(1); for the 2 half-frames and look-ahead */ + { + /* Compare pitch values of the present frame */ + FOR( j = 0; j < K; j++ ) /* Verify pitch coherence with neighbours (including past pitch) */ + { + IF( NE_16( j, i ) ) /* Exclude itself, of course */ + { + IF( GE_16( corr_tmp[j + NHFR], CORR_TH1 ) ) /* reinforcement can happen only if the correlation is high enough */ + { + delta = abs_s( sub( pitch[i][NSECT + k], pitch_tmp[j + NHFR] ) ); /* Find difference of pitch values */ + coh_flag = pitch_coherence_fx( pitch[i][NSECT + k], pitch_tmp[j + NHFR], COH_FAC, DELTA_COH ); + + IF( coh_flag != 0 ) + { + /* Favour stability across sections, favour closer values */ + IF( EQ_16( ind_tmp[j + NHFR], add( NSECT, k ) ) ) + { + /* corr[i][k] *= ( -thres1[j+NHFR]/DELTA1 * delta + thres1[j+NHFR]+1 ); */ + /* operands are Q15, except corr[i][NSECT+k] which is Q12 */ + fac = mult( negate( thres1[j + NHFR] ), MAX_16 / DELTA_COH ); + fac = add( extract_l( L_shr( L_mult( fac, delta ), 1 ) ), thres1[j + NHFR] ); + corr[i][NSECT + k] = add_sat( corr[i][NSECT + k], mult( fac, corr[i][NSECT + k] ) ); + move16(); + } + ELSE + { + /* corr[i][k] *= ( -thres1[j+NHFR]/DELTA1 * 0.625f * delta + 0.625f * thres1[j+NHFR] +1.0f ); */ + fac = mult( negate( thres1[j + NHFR] ), 20479 / DELTA_COH ); + fac = add( extract_l( L_shr( L_mult( fac, delta ), 1 ) ), mult( 20479, thres1[j + NHFR] ) ); + corr[i][NSECT + k] = add( corr[i][NSECT + k], mult( fac, corr[i][NSECT + k] ) ); + move16(); + } + } + } + } + } + } + } +} + +/*-----------------------------------------------------------------* + * pitch_coherence_fx + * + * Verify if pitch evolution is smooth + *-----------------------------------------------------------------*/ +static Word16 pitch_coherence_fx( + Word16 pitch0, /* i : first pitch to compare */ + Word16 pitch1, /* i : 2nd pitch to compare */ + Word16 fac_max, /* i : max ratio of both values Q12 */ + Word16 diff_max /* i : max difference of both values */ +) +{ + Word16 smaller, larger; + Word16 pc; + + smaller = s_min( pitch0, pitch1 ); + larger = s_max( pitch0, pitch1 ); + + pc = 0; + move16(); + test(); + if ( ( LE_16( larger, extract_h( L_shl( L_mult( fac_max, smaller ), 3 ) ) ) ) && /* Changed to <= to keep BE */ + ( LT_16( sub( larger, smaller ), diff_max ) ) ) + { + pc = 1; + move16(); + } + + return pc; +} + +/*-----------------------------------------------------------------* + * LP_Decim2_Copy: + * + * Decimate a vector by 2 with 2nd order fir filter. + *-----------------------------------------------------------------*/ +static void LP_Decim2_Copy( + const Word16 x[], /* i: signal to process */ + Word16 y[], /* o: signal to process */ + Word16 l, /* i : size of filtering */ + Word16 mem[] /* i/o: memory (size=3) */ +) +{ + Word16 *p_x, x_buf[L_FRAME + L_MEM]; + Word16 i, j, k; + Word32 L_tmp; + + /* copy initial filter states into buffer */ + p_x = x_buf; + FOR( i = 0; i < L_MEM; i++ ) + { + *p_x++ = mem[i]; + move16(); + } + FOR( i = 0; i < l; i++ ) + { + *p_x++ = x[i]; + move16(); + } + if ( s_and( l, 1 ) ) /* Fix for valgrind error in case l is odd. Anyway this function will be removed. */ + { + *p_x = *( p_x - 1 ); + move16(); + } + + FOR( i = 0; i < L_MEM; i++ ) + { + mem[i] = x[l - L_MEM + i]; + move16(); + } + p_x = x_buf; + j = 0; + move16(); + FOR( i = 0; i < l; i += 2 ) + { + L_tmp = L_mult( *p_x, h_fir_fx[0] ); + FOR( k = 1; k < L_FIR_PO; k++ ) + { + L_tmp = L_mac( L_tmp, p_x[k], h_fir_fx[k] ); + } + p_x += 2; + + y[j++] = round_fx( L_tmp ); + move16(); + } +} +/*---------------------------------------------------------------------* + * Dot_product12_OL + * + * two different length dot products of x and y + *---------------------------------------------------------------------*/ +static Word32 Dot_product12_OL( /* o : Q31: normalized result (1 < val <= -1) */ + Word16 *sum1, /* o : Q31: normalized result 2 */ + const Word16 x[], /* i : 12bits: x vector */ + const Word16 y[], /* i : 12bits: y vector */ + const Word16 lg, /* i : vector length */ + const Word16 lg2, /* i : vector length 2 */ + Word16 *exp, /* o : exponent of result (0..+30) */ + Word16 *exp2 /* o : exponent of result 2 (0..+30) */ +) +{ + Word16 i, sft; + Word32 L_sum, L_sum2; + + L_sum = L_mac( 1, x[0], y[0] ); + IF( LE_16( lg, lg2 ) ) + { + FOR( i = 1; i < lg; i++ ) + { + L_sum = L_mac( L_sum, x[i], y[i] ); + } + /* sets to 'L_sum' in 1 clock */ + L_sum2 = L_sum; + move32(); + FOR( ; i < lg2; i++ ) + { + L_sum2 = L_mac( L_sum2, x[i], y[i] ); + } + } + ELSE + { + FOR( i = 1; i < lg2; i++ ) + { + L_sum = L_mac( L_sum, x[i], y[i] ); + } + /* sets to 'L_sum' in 1 clock */ + L_sum2 = L_sum; + move32(); + FOR( ; i < lg; i++ ) + { + L_sum = L_mac( L_sum, x[i], y[i] ); + } + } + + /* Q31 */ + sft = norm_l( L_sum ); + L_sum = L_shl( L_sum, sft ); + *exp = sub( 30, sft ); + move16(); /* exponent = 0..30 */ + + sft = norm_l( L_sum2 ); + L_sum2 = L_shl( L_sum2, sft ); + *exp2 = sub( 30, sft ); + move16(); /* exponent = 0..30 */ + + *sum1 = extract_h( L_shr( L_sum2, 1 ) ); + move16(); + return L_sum; +} + +/*---------------------------------------------------------------------* + * Dot_product12_OL_back() + * + * two different length dot products of x and y, computed backward + *---------------------------------------------------------------------*/ +static Word32 Dot_product12_OL_back( /* o : Q31: normalized result (1 < val <= -1) */ + Word16 *sum1, /* o : Q31: normalized result 2 */ + const Word16 x[], /* i : 12bits: x vector */ + const Word16 y[], /* i : 12bits: y vector */ + const Word16 lg, /* i : vector length */ + const Word16 lg2, /* i : vector length 2 */ + Word16 *exp, /* o : exponent of result (0..+30) */ + Word16 *exp2 /* o : exponent of result 2 (0..+30) */ +) +{ + Word16 i, sft; + Word32 L_sum, L_sum2; + + L_sum = L_mac( 1, x[0], y[0] ); + IF( LE_16( lg, lg2 ) ) + { + FOR( i = 1; i < lg; i++ ) + { + L_sum = L_mac( L_sum, x[-i], y[-i] ); + } + /* sets to 'L_sum' in 1 clock */ + L_sum2 = L_sum; + move32(); + FOR( ; i < lg2; i++ ) + { + L_sum2 = L_mac( L_sum2, x[-i], y[-i] ); + } + } + ELSE + { + FOR( i = 1; i < lg2; i++ ) + { + L_sum = L_mac( L_sum, x[-i], y[-i] ); + } + /* sets to 'L_sum' in 1 clock */ + L_sum2 = L_sum; + move32(); + FOR( ; i < lg; i++ ) + { + L_sum = L_mac( L_sum, x[-i], y[-i] ); + } + } + + /* Q31 */ + sft = norm_l( L_sum ); + L_sum = L_shl( L_sum, sft ); + *exp = sub( 30, sft ); + move16(); /* exponent = 0..30 */ + + sft = norm_l( L_sum2 ); + L_sum2 = L_shl( L_sum2, sft ); + *exp2 = sub( 30, sft ); + move16(); /* exponent = 0..30 */ + + *sum1 = extract_h( L_shr( L_sum2, 1 ) ); + move16(); + return L_sum; +} + +void pitchDoubling_det_fx( + Word16 *wspeech, + Word16 *pitch_ol, + Word16 *T_op_fr, + Word16 *voicing_fr ) +{ + Word16 new_op_fr[2]; + Word16 new_voicing[2]; + Word16 new_Top[2]; + Word16 m, T; + + + /*save initial values*/ + + new_Top[0] = pitch_ol[0]; + move16(); + new_Top[1] = pitch_ol[1]; + move16(); + + FOR( m = 2; m < 5; m++ ) + { + + /* T= pitch_ol[0]/m; */ + T = mult( pitch_ol[0], One_div_fx[m - 1] ); + + IF( GE_16( T, PIT_MIN_12k8 ) ) + { + pitch_ol2_fx( PIT_MIN_SHORTER, T, &( new_op_fr[0] ), &new_voicing[0], 0, wspeech, 2, EVS_MONO ); + pitch_ol2_fx( PIT_MIN_SHORTER, T, &( new_op_fr[1] ), &new_voicing[1], L_SUBFR, wspeech, 2, EVS_MONO ); + /* IF(sub(add(new_voicing[0],new_voicing[1]),add(voicing_fr[0],voicing_fr[1]))>0 */ + IF( L_msu( L_msu( L_mac( L_mult( new_voicing[0], 8192 ), new_voicing[1], 8192 ), voicing_fr[0], 8192 ), voicing_fr[1], 8192 ) > 0 ) + { + new_Top[0] = T; + move16(); + T_op_fr[0] = new_op_fr[0]; + move16(); + T_op_fr[1] = new_op_fr[1]; + move16(); + voicing_fr[0] = new_voicing[0]; + move16(); + voicing_fr[1] = new_voicing[1]; + move16(); + } + } + + /* T= pitch_ol[1]/m; */ + T = mult( pitch_ol[1], One_div_fx[m - 1] ); + + IF( GE_16( T, PIT_MIN_12k8 ) ) + { + pitch_ol2_fx( PIT_MIN_SHORTER, T, &( new_op_fr[0] ), &new_voicing[0], 2 * L_SUBFR, wspeech, 2, EVS_MONO ); + pitch_ol2_fx( PIT_MIN_SHORTER, T, &( new_op_fr[1] ), &new_voicing[1], 3 * L_SUBFR, wspeech, 2, EVS_MONO ); + /* IF(sub(add(new_voicing[0],new_voicing[1]),add(voicing_fr[2],voicing_fr[3]))>0) */ + IF( L_msu( L_msu( L_mac( L_mult( new_voicing[0], 8192 ), new_voicing[1], 8192 ), voicing_fr[2], 8192 ), voicing_fr[3], 8192 ) > 0 ) + { + new_Top[1] = T; + move16(); + T_op_fr[2] = new_op_fr[0]; + move16(); + T_op_fr[3] = new_op_fr[1]; + move16(); + voicing_fr[2] = new_voicing[0]; + move16(); + voicing_fr[3] = new_voicing[1]; + move16(); + } + } + } + + pitch_ol[0] = new_Top[0]; + move16(); + pitch_ol[1] = new_Top[1]; + move16(); + +} /*end of pitch doubling detection*/ diff --git a/lib_com/options.h b/lib_com/options.h index 017a29936..632c43d74 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -80,6 +80,8 @@ #define FIX_1978_SAT_MISSING_IN_GAIN_ENC /* VA: Fix add saturation missing that lead to a crash in P800-10 */ #define FIX_1981_MAXIMUM_EXP_FX /* FhG: Fix bug in function to find maximum value in vector */ +//#define PITCH_OL_PRINTIND +//#define PITCH_OL_PRINTVAL #define FIX_1979_SAT_MISSING_IN_LSF_ENC /* VA: Proposal to fix 1979, saturation in lsf_enc, NOkia to review */ #define FIX_1946_CRASH_JBM_PROCESSING /* FhG: Increased guard bits of DFT_fx */ diff --git a/lib_com/tools_fx.c b/lib_com/tools_fx.c index 87dd3b886..75c7769d2 100644 --- a/lib_com/tools_fx.c +++ b/lib_com/tools_fx.c @@ -1246,6 +1246,8 @@ Word16 maximum_exp_fx( /* o : index of the maximum value #ifdef FIX_1981_MAXIMUM_EXP_FX scale = sub( norm_s( vec_fx[ind] ), 1 ); + tmp = shl( vec_fx[ind], scale ); + exp = sub( exp_vec[ind], scale ); FOR( j = 1; j < lvec_fx; j++ ) { @@ -1256,8 +1258,8 @@ Word16 maximum_exp_fx( /* o : index of the maximum value move16(); scale = sub( norm_s( vec_fx[ind] ), 1 ); - tmp = shl( vec_fx[j], scale ); - exp = sub( exp_vec[j], scale ); + tmp = shl( vec_fx[ind], scale ); + exp = sub( exp_vec[ind], scale ); } } #else @@ -1272,7 +1274,8 @@ Word16 maximum_exp_fx( /* o : index of the maximum value Word32 tmp32, tmp32_1; tmp16 = tmp; tmp32 = L_deposit_l( tmp ); - tmp16_1 = shr_sat( vec_fx[j], sub( exp, exp_vec[j] ) ); + + tmp16_1 = shr_sat( vec_fx[j] , sub( exp, exp_vec[j] ) ); tmp32_1 = L_shr_sat( L_deposit_l( vec_fx[j] ), sub( exp, exp_vec[j] ) ); if ( ( LT_16( tmp16, tmp16_1 ) != LT_32( tmp32, tmp32_1 ) ) ) @@ -1295,8 +1298,8 @@ Word16 maximum_exp_fx( /* o : index of the maximum value } } #endif -#if 0 /*value out*/ - printf( "\n val= %15.15f", vec_fx[ind] * pow(2,exp_vec[ind] - 15) ); +#ifdef PITCH_OL_PRINTVAL /*value out*/ + printf( "\n val= %15.15f", (float)vec_fx[ind] * pow(2,exp_vec[ind] - 15) ); #endif return ind; diff --git a/lib_enc/pitch_ol_fx.c b/lib_enc/pitch_ol_fx.c index 56647f7b1..1fbedcc00 100644 --- a/lib_enc/pitch_ol_fx.c +++ b/lib_enc/pitch_ol_fx.c @@ -13,6 +13,7 @@ #include "prot_fx.h" /* Function prototypes */ #include "prot_fx_enc.h" /* Function prototypes */ + /*-----------------------------------------------------------------* * Local Constants *-----------------------------------------------------------------*/ @@ -731,6 +732,9 @@ void pitch_ol_fx( /* 1st set of candidates */ ind = add( maximum_fx( pt_cor1, sec_length[j], &ftmp ), offset ); +#ifdef PITCH_OL_PRINTIND + printf( "\n ind = %d", ind ); +#endif pitchX[i][j] = add( ind, pit_min ); move16(); pt2 = pt1 - pitchX[i][j] + /*-*/ offset_la; /* selected moving vector */ @@ -767,6 +771,9 @@ void pitch_ol_fx( /* 2nd set of candidates */ ind1 = add( maximum_fx( pt_cor3, sec_length1[j], &ftmp ), offset1 ); +#ifdef PITCH_OL_PRINTIND + printf( "\n ind = %d", ind ); +#endif pitchX[i][j + NSECT] = add( ind1, pit_min1 ); move16(); pt4 = pt1 - pitchX[i][j + NSECT] + /*-*/ offset_la1; @@ -1678,6 +1685,9 @@ void pitch_ol_ivas_fx( /* 1st set of candidates */ ind = add( maximum_exp_fx( pt_cor1, pt_cor1_exp, sec_length[j] ), offset ); +#ifdef PITCH_OL_PRINTIND + printf( "\n ind = %d", ind ); +#endif pitchX[i][j] = add( ind, pit_min ); move16(); pt2 = pt1 - pitchX[i][j] + /*-*/ offset_la; /* selected moving vector */ @@ -1720,6 +1730,9 @@ void pitch_ol_ivas_fx( /* 2nd set of candidates */ ind1 = add( maximum_exp_fx( pt_cor3, pt_cor3_exp, sec_length1[j] ), offset1 ); +#ifdef PITCH_OL_PRINTIND + printf( "\n ind = %d", ind ); +#endif pitchX[i][j + NSECT] = add( ind1, pit_min1 ); move16(); pt4 = pt1 - pitchX[i][j + NSECT] + /*-*/ offset_la1; -- GitLab From 2fc8fbcef3a3cc19532290a701401800986a1260 Mon Sep 17 00:00:00 2001 From: Fabian Bauer Date: Wed, 3 Sep 2025 09:50:22 +0200 Subject: [PATCH 13/32] clang patch --- .../tools_fx.c | 5026 ----------------- .../ba9e794e4af04046f8293c8af70d4da/options.h | 102 - .../pitch_ol_fx.c | 2475 -------- lib_com/options.h | 2 +- 4 files changed, 1 insertion(+), 7604 deletions(-) delete mode 100644 Workspace_msvc/enc_temp_folder/75f9146d81645fb7408b2c8c144cfa7/tools_fx.c delete mode 100644 Workspace_msvc/enc_temp_folder/ba9e794e4af04046f8293c8af70d4da/options.h delete mode 100644 Workspace_msvc/enc_temp_folder/d76ccfdc3b9fa9da476bcd2a44fe879/pitch_ol_fx.c diff --git a/Workspace_msvc/enc_temp_folder/75f9146d81645fb7408b2c8c144cfa7/tools_fx.c b/Workspace_msvc/enc_temp_folder/75f9146d81645fb7408b2c8c144cfa7/tools_fx.c deleted file mode 100644 index 15e2631e2..000000000 --- a/Workspace_msvc/enc_temp_folder/75f9146d81645fb7408b2c8c144cfa7/tools_fx.c +++ /dev/null @@ -1,5026 +0,0 @@ -/****************************************************************************************************** - - (C) 2022-2025 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 -#include -#include "options.h" -#include "stl.h" -#include -#include "cnst.h" -#include "prot_fx.h" -#include "basop_util.h" -#include "basop32.h" -#include "wmc_auto.h" -#include "prot_fx_enc.h" -#include "ivas_prot_fx.h" - -#define INV_BANDS10 3277 /* 1/10 in Q15 */ -#define INV_BANDS9 3641 /* 1/9 in Q15 */ -#define INV_BANDS3 10923 /* 1/9 in Q15 */ -const Word16 b_hp400_fx[3] = { 3660, -7320, 3660 }; /* Q12 (/4) */ -const Word16 a_hp400_fx[3] = { 16384, 29280, -14160 }; -const Word16 a_hp400_ivas_fx[3] = { 4096, 7320, -3540 }; /*Q12*/ - -#define WMC_TOOL_SKIP - -// conversion functions: -Word32 float_to_fix( float number, Word32 Q ) -{ - assert( Q >= 0 ); - if ( number == 1.0f && Q == Q31 ) - { - return ONE_IN_Q31; - } - if ( isnan( number ) ) - { - number = 0; - } - assert( fabs( number ) < pow( 2, 31 - Q ) ); - Word32 ret = (Word32) ( number * ( (UWord32) 1 << Q ) ); - return ret; -} - -float fix_to_float( Word32 number, Word32 Q ) -{ - assert( Q >= 0 ); - float ret = (float) number / ( (UWord32) 1 << Q ); - return ret; -} - -Word16 float_to_fix16( float number, Word16 Q ) -{ - assert( Q >= 0 ); - IF( isnan( number ) ) - return 0; - if ( number == 1.0f && Q == Q15 ) - return MAX16B; - if ( number == -1.0f && Q == Q15 ) - return MIN16B; - assert( fabs( number ) < pow( 2, 15 - Q ) ); - Word16 ret = (Word16) ( number * ( (UWord16) 1 << Q ) ); - return ret; -} - -Word16 float_to_fix16_thrld( float number, Word16 Q ) -{ - assert( Q >= 0 ); - if ( number == 1.0f && Q == Q15 ) - return MAX16B; - float limit = (float) pow( 2, 15 - Q ); - /*Add threshold*/ - if ( number > MAX16B_FLT ) - { - number = MAX16B_FLT; - } - else if ( number < MIN16B_FLT ) - { - number = MIN16B_FLT; - } - assert( number <= limit && number >= -limit ); - Word16 ret = (Word16) ( number * ( (UWord16) 1 << Q ) ); - return ret; -} - -float fix16_to_float( Word16 number, Word16 Q ) -{ - assert( Q >= 0 ); - float ret = (float) number / ( (UWord16) 1 << Q ); - return ret; -} - -// Float to 32-bit Mantissa and Exponent -void f2me( float n, Word32 *mantissa, Word16 *expo ) -{ - Word32 e; - float mf = (float) frexp( n, &e ); - *expo = (Word16) e; - *mantissa = float_to_fix( mf, Q31 ); -} - -// 32-bit Mantissa and Exponent to Float -float me2f( Word32 m, Word16 expo ) -{ - float mf = fix_to_float( m, Q31 ); - return (float) ldexp( mf, expo ); -} - -// Float buffer to 32-bit mantissa buffer and common exponent. -void f2me_buf( const float *x, Word32 *m, Word16 *e, const Word32 n ) -{ - Word16 max_e = -32, tmp_e; - Word32 i; - - for ( i = 0; i < n; i++ ) - { - f2me( x[i], &m[i], &tmp_e ); - max_e = ( max_e > tmp_e ) ? max_e : tmp_e; - } - - for ( i = 0; i < n; i++ ) - { - f2me( x[i], &m[i], &tmp_e ); - m[i] = L_shr( m[i], max_e - tmp_e ); - } - - *e = max_e; -} - -// 32-bit Mantissa buffer and exponent into float buffer. -void me2f_buf( const Word32 *m, const Word16 e, float *out, const Word32 n ) -{ - for ( int i = 0; i < n; i++ ) - { - out[i] = me2f( m[i], e ); - } -} - -// Float to 16-bit Mantissa and Exponent -void f2me_16( float n, Word16 *mantissa, Word16 *expo ) -{ - Word32 e; - float mf = (float) frexp( n, &e ); - *expo = (Word16) e; - *mantissa = float_to_fix16( mf, 15 ); -} - -// 16-bit Mantissa and Exponent to Float -float me2f_16( Word16 m, Word16 expo ) -{ - float mf = fix16_to_float( m, 15 ); - return (float) ldexp( mf, expo ); -} - -// Float buffer to 16-bit mantissa buffer and common exponent. -void f2me_buf_16( const float *x, Word16 *m, Word16 *e, const Word32 n ) -{ - Word16 max_e = -16, tmp_e; - Word32 i; - - for ( i = 0; i < n; i++ ) - { - f2me_16( x[i], &m[i], &tmp_e ); - max_e = ( max_e > tmp_e ) ? max_e : tmp_e; - } - - for ( i = 0; i < n; i++ ) - { - f2me_16( x[i], &m[i], &tmp_e ); - m[i] = shr( m[i], max_e - tmp_e ); - } - - *e = max_e; -} - -// 16-bit Mantissa buffer and exponent into float buffer. -void me2f_buf_16( const Word16 *m, const Word16 e, float *out, const Word32 n ) -{ - for ( int i = 0; i < n; i++ ) - { - out[i] = me2f_16( m[i], e ); - } -} -void f2fix( float *var_flt, Word32 *var_fix, Word32 expo ) -{ - *var_fix = (Word32) ( *var_flt * pow( 2, 31 - expo ) ); -} - -void fix2f( Word32 *var_fix, float *var_flt, Word32 expo ) -{ - float mf = fix_to_float( *var_fix, 31 ); - *var_flt = (float) ldexp( mf, expo ); -} - -void f2fix_16( float *var_flt, Word16 *var_fix, Word32 expo ) -{ - *var_fix = (Word16) ( *var_flt * pow( 2, 15 - expo ) ); -} - -void fix2f_16( Word16 *var_fix, float *var_flt, Word32 expo ) -{ - float mf = fix16_to_float( *var_fix, 15 ); - *var_flt = (float) ldexp( mf, expo ); -} - -#undef WMC_TOOL_SKIP - -/*-------------------------------------------------------------------* - * usdequant_fx() - * - * Uniform scalar de-quantizer routine - * - * Applies de-quantization based on scale and round operations. - *-------------------------------------------------------------------*/ -Word16 usdequant_fx( /* Qx*/ - const Word16 idx, /* i: quantizer index Q0*/ - const Word16 qlow, /* i: lowest codebook entry (index 0) Qx*/ - const Word16 delta /* i: quantization step Qx-1*/ -) -{ - Word16 g; - Word32 L_tmp; - - /*g = idx * delta + qlow;*/ - L_tmp = L_deposit_l( qlow ); /*Qx */ - L_tmp = L_mac( L_tmp, idx, delta ); /*Qx */ - g = round_fx_sat( L_shl_sat( L_tmp, 16 ) ); /*Qx */ - return ( g ); -} - -Word32 usdequant32_fx( /* Qx*/ - const Word16 idx, /* i: quantizer index Q0*/ - const Word32 qlow, /* i: lowest codebook entry (index 0) Qx*/ - const Word32 delta /* i: quantization step Qx-1*/ -) -{ - Word32 g; - Word64 L_tmp; - - /*g = idx * delta + qlow;*/ - L_tmp = W_deposit32_l( qlow ); /*Qx */ - L_tmp = W_mac_32_16( L_tmp, delta, idx ); - IF( GE_64( L_tmp, MAX_32 ) ) - { - g = MAX_32; - move32(); - } - ELSE - { - g = W_extract_l( L_tmp ); /*Qx */ - } - return ( g ); -} - -/*-------------------------------------------------------------------* - * usquant() - * - * Uniform scalar quantizer according to MMSE criterion - * (nearest neighbour in Euclidean space) - * - * Applies quantization based on scale and round operations. - * Index of the winning codeword and the winning codeword itself are returned. - *-------------------------------------------------------------------*/ -Word16 usquant_fx( /* o: index of the winning codeword */ - const Word16 x, /* i: scalar value to quantize Qx*/ - Word16 *xq, /* o: quantized value Qx*/ - const Word16 qlow, /* i: lowest codebook entry (index 0) Qx*/ - const Word16 delta, /* i: quantization step Qx-1*/ - const Word16 cbsize /* i: codebook size */ -) -{ - Word16 idx; - Word16 tmp, exp; - Word32 L_tmp; -#ifndef ISSUE_1836_replace_overflow_libcom -#ifdef BASOP_NOGLOB_DECLARE_LOCAL - Flag Overflow = 0; - move32(); -#endif -#endif - - /* idx = (short)( (x - qlow)/delta + 0.5f); */ - exp = norm_s( delta ); - tmp = div_s( shl( 1, sub( 14, exp ) ), delta ); /*Q(29-exp-(Qx-1))->Q(30-exp-Qx) */ -#ifdef ISSUE_1836_replace_overflow_libcom - L_tmp = L_mult( sub_sat( x, qlow ), tmp ); /*Q(31-exp) */ - idx = extract_l( L_shr_r( L_add( L_tmp, shl_sat( 1, sub( 30, exp ) ) ), sub( 31, exp ) ) ); /*Q0 */ -#else - L_tmp = L_mult( sub_o( x, qlow, &Overflow ), tmp ); /*Q(31-exp) */ - idx = extract_l( L_shr_r( L_add( L_tmp, shl_o( 1, sub( 30, exp ), &Overflow ) ), sub( 31, exp ) ) ); /*Q0 */ -#endif - - idx = s_min( idx, sub( cbsize, 1 ) ); - idx = s_max( idx, 0 ); - - /* *xq = idx*delta + qlow; */ - L_tmp = L_deposit_l( qlow ); /*Qx */ - L_tmp = L_mac( L_tmp, idx, delta ); /*Qx */ -#ifdef ISSUE_1836_replace_overflow_libcom - *xq = round_fx_sat( L_shl_sat( L_tmp, 16 ) ); /*Qx */ -#else - *xq = round_fx_o( L_shl_o( L_tmp, 16, &Overflow ), &Overflow ); /*Qx */ -#endif - return idx; -} -/*-------------------------------------------------------------------* - * Dot_product: - * - * Compute scalar product of using accumulator. - * Performs no normalization, as opposed to Dot_product12() - *-------------------------------------------------------------------*/ -Word32 Dot_product( /* o : Sum */ - const Word16 x[], /* i : 12bits: x vector */ - const Word16 y[], /* i : 12bits: y vector */ - const Word16 lg /* i : vector length */ -) -{ - Word16 i; - Word32 L_sum; - Word64 L64_sum; - - L64_sum = 1; - move64(); - FOR( i = 0; i < lg; i++ ) - { - L64_sum = W_mac_16_16( L64_sum, x[i], y[i] ); - } - L_sum = W_sat_l( L64_sum ); - return L_sum; -} -/*---------------------------------------------------------------------* - * dotp_fx() - * - * Dot product of vector x[] and vector y[] - *---------------------------------------------------------------------*/ - -Word32 dotp_fx( /* o : dot product of x[] and y[] */ - const Word16 x[], /* i : vector x[] */ - const Word16 y[], /* i : vector y[] */ - const Word16 n, /* i : vector length */ - Word16 *exp /* (o) : exponent of result (0..+30) */ -) -{ - Word16 sft; - Word32 L_sum; - - assert( *exp == 0 ); - - L_sum = L_add( L_shr( Dot_product( x, y, n ), 1 ), 1 ); - - /* Normalize acc in Q31 */ - - sft = norm_l( L_sum ); - L_sum = L_shl( L_sum, sft ); - - *exp = sub( 30, sft ); - move16(); /* exponent = 0..30 */ - - return L_sum; -} - -Word32 sum2_fx( /* o : sum of all squared vector elements Q(2x+1)*/ - const Word16 *vec, /* i : input vector Qx*/ - const Word16 lvec /* i : length of input vector */ -) -{ - Word16 i; - Word32 L_tmp; -#ifndef ISSUE_1836_replace_overflow_libcom -#ifdef BASOP_NOGLOB_DECLARE_LOCAL - Flag Overflow = 0; - move32(); -#endif -#endif - L_tmp = L_deposit_l( 0 ); - FOR( i = 0; i < lvec; i++ ) - { -#ifdef ISSUE_1836_replace_overflow_libcom - L_tmp = L_mac_sat( L_tmp, vec[i], vec[i] ); /*Q(2x+1) */ -#else - L_tmp = L_mac_o( L_tmp, vec[i], vec[i], &Overflow ); /*Q(2x+1) */ -#endif - } - - return L_tmp; -} - -Word64 sum2_fx_no_sat( /* o : sum of all squared vector elements Q(2*Qx)*/ - const Word16 *vec, /* i : input vector Qx*/ - const Word16 lvec /* i : length of input vector */ -) -{ - Word16 i; - Word64 sum; - - sum = 0; - move64(); - FOR( i = 0; i < lvec; i++ ) - { - sum = W_mac0_16_16( sum, vec[i], vec[i] ); // 2*Qx - } - - return sum; -} - -Word32 sum_32_fx( - const Word32 *vec, /* i : input vector */ - const Word16 lvec, /* i : length of input vector */ - Word16 *e ) -{ - Word16 i, shift; - Word64 tmp = 0; - move64(); - Word32 ans; - - FOR( i = 0; i < lvec; i++ ) - { - tmp = W_add( tmp, vec[i] ); // e - } - shift = W_norm( tmp ); - tmp = W_shl( tmp, shift ); // shift + (31 - e) - ans = W_extract_h( tmp ); // shift + (31 - e) - 32 - *e = add( sub( *e, shift ), 32 ); - move16(); - - return ans; -} - -Word32 sum2_fx_mod( /* o : sum of all squared vector elements Q(2x+1 -5)*/ - const Word16 *vec, /* i : input vector Qx*/ - const Word16 lvec /* i : length of input vector */ -) -{ - Word16 i; - Word32 L_tmp; -#ifndef ISSUE_1836_replace_overflow_libcom -#ifdef BASOP_NOGLOB_DECLARE_LOCAL - Flag Overflow = 0; - move32(); -#endif -#endif - - L_tmp = L_deposit_l( 0 ); - FOR( i = 0; i < lvec; i++ ) - { -#ifdef ISSUE_1836_replace_overflow_libcom - L_tmp = L_add_sat( L_tmp, L_shr( L_mult_sat( vec[i], vec[i] ), 9 ) ); -#else - L_tmp = L_add_o( L_tmp, L_shr( L_mult_o( vec[i], vec[i], &Overflow ), 9 ), &Overflow ); -#endif - } - - return L_tmp; -} -/*-------------------------------------------------------------------* - * Copy: - * - * Copy vector x[] to y[] - * - *-------------------------------------------------------------------*/ -void Copy( - const Word16 x[], /* i : input vector */ - Word16 y[], /* o : output vector */ - const Word16 L /* i : vector length */ -) -{ - Word16 i; - - IF( y < x ) - { - FOR( i = 0; i < L; i++ ) - { - y[i] = x[i]; - move16(); - } - - /* Location of x and y may differ depending on platform/memory allocation. Since IF and ELSE has different complexity count, the early return is used instead of ELSE to ensure the same complexity number regardless of x and y memory addresses. */ - return; - } - - FOR( i = L - 1; i >= 0; i-- ) - { - y[i] = x[i]; - move16(); - } - - return; -} -/*-------------------------------------------------------------------* - * Copy64: - * - * Copy vector x[] to y[] (64 bits) - *-------------------------------------------------------------------*/ -void Copy64( - const Word64 x[], /* i : input vector */ - Word64 y[], /* o : output vector */ - const Word16 L /* i : vector length */ -) -{ - Word16 i; - IF( y < x ) - { - FOR( i = 0; i < L; i++ ) - { - y[i] = x[i]; - move64(); - } - - /* Location of x and y may differ depending on platform/memory allocation. Since IF and ELSE has different complexity count, the early return is used instead of ELSE to ensure the same complexity number regardless of x and y memory addresses. */ - return; - } - - FOR( i = L - 1; i >= 0; i-- ) - { - y[i] = x[i]; - move64(); - } - - return; -} - -void set64_fx( - Word64 y[], /* i/o: Vector to set */ - const Word64 a, /* i : Value to set the vector to */ - const Word16 N /* i : Lenght of the vector */ -) -{ - Word16 i; - FOR( i = 0; i < N; i++ ) - { - y[i] = a; - move64(); - } - - return; -} - -void Copy_pword( - const PWord16 x[], /* i : input vector */ - PWord16 y[], /* o : output vector */ - const Word16 L /* i : vector length */ -) -{ - Word16 i; - - IF( y < x ) - { - FOR( i = 0; i < L; i++ ) - { - y[i].v.im = x[i].v.im; - y[i].v.re = x[i].v.re; - move16(); - move16(); - } - - /* Location of x and y may differ depending on platform/memory allocation. Since IF and ELSE has different complexity count, the early return is used instead of ELSE to ensure the same complexity number regardless of x and y memory addresses. */ - return; - } - - FOR( i = L - 1; i >= 0; i-- ) - { - y[i].v.im = x[i].v.im; - y[i].v.re = x[i].v.re; - move16(); - move16(); - } - - return; -} -/*-------------------------------------------------------------------* - * Copy32: - * - * Copy vector x[] to y[] (32 bits) - *-------------------------------------------------------------------*/ -void Copy32( - const Word32 x[], /* i : input vector */ - Word32 y[], /* o : output vector */ - const Word16 L /* i : vector length */ -) -{ - Word16 i; - IF( y < x ) - { - FOR( i = 0; i < L; i++ ) - { - y[i] = x[i]; - move32(); - } - - return; - } - - FOR( i = L - 1; i >= 0; i-- ) - { - y[i] = x[i]; - move32(); - } -} - -void set8_fx( - Word8 y[], /* i/o: Vector to set */ - const Word8 a, /* i : Value to set the vector to */ - const Word16 N /* i : Lenght of the vector */ -) -{ - Word16 i; - - FOR( i = 0; i < N; i++ ) - { - y[i] = a; - move16(); - } - - return; -} - -/*-------------------------------------------------------------------* - * set16_fx() - * set32_fx() - * - * Set the vector elements to a value - *-------------------------------------------------------------------*/ -void set16_fx( - Word16 y[], /* i/o: Vector to set */ - const Word16 a, /* i : Value to set the vector to */ - const Word16 N /* i : Lenght of the vector */ -) -{ - Word16 i; - - FOR( i = 0; i < N; i++ ) - { - y[i] = a; - move16(); - } - - return; -} - -void set32_fx( - Word32 y[], /* i/o: Vector to set */ - const Word32 a, /* i : Value to set the vector to */ - const Word16 N /* i : Lenght of the vector */ -) -{ - Word16 i; - - FOR( i = 0; i < N; i++ ) - { - y[i] = a; - move32(); - } - - return; -} -/*-------------------------------------------------------------------* - * Copy_Scale_sig - * - * Up/down scale a 16 bits vector x and move it into y - *-------------------------------------------------------------------*/ -void Copy_Scale_sig( - const Word16 x[], /* i : signal to scale input Qx */ - Word16 y[], /* o : scaled signal output Qx */ - const Word16 lg, /* i : size of x[] Q0 */ - const Word16 exp0 /* i : exponent: x = round(x << exp) Qx ?exp */ -) -{ - Word16 i; - Word16 tmp; -#ifndef ISSUE_1836_replace_overflow_libcom -#ifdef BASOP_NOGLOB_DECLARE_LOCAL - Flag Overflow = 0; - move32(); -#endif -#endif - IF( exp0 == 0 ) - { - FOR( i = 0; i < lg; i++ ) - { - y[i] = x[i]; - move16(); - } - return; - } - IF( exp0 < 0 ) - { - tmp = shl( -32768, exp0 ); /* we use negative to correctly represent 1.0 */ - FOR( i = 0; i < lg; i++ ) - { - y[i] = msu_r( 0, x[i], tmp ); - move16(); - } - return; - } - FOR( i = 0; i < lg; i++ ) - { -#ifdef ISSUE_1836_replace_overflow_libcom - y[i] = shl_sat( x[i], exp0 ); -#else - y[i] = shl_o( x[i], exp0, &Overflow ); -#endif - move16(); /* saturation can occur here */ - } -} -/*-------------------------------------------------------------------* - * Copy_Scale_sig - * - * Up/down scale a 16 bits vector x and move it into y - *-------------------------------------------------------------------*/ -void Copy_Scale_sig_16_32_DEPREC( - const Word16 x[], /* i : signal to scale input Qx */ - Word32 y[], /* o : scaled signal output Qx */ - const Word16 lg, /* i : size of x[] Q0 */ - const Word16 exp0 /* i : exponent: x = round(x << exp) Qx ?exp */ -) -{ - Word16 i; - Word16 tmp; -#ifndef ISSUE_1836_replace_overflow_libcom -#ifdef BASOP_NOGLOB_DECLARE_LOCAL - Flag Overflow = 0; - move32(); -#endif -#endif - - - IF( exp0 == 0 ) - { - FOR( i = 0; i < lg; i++ ) - { - y[i] = L_deposit_l( x[i] ); - move32(); - } - return; - } - IF( exp0 < 0 ) - { - /*Should not happen */ - FOR( i = 0; i < lg; i++ ) - { -#ifdef ISSUE_1836_replace_overflow_libcom - y[i] = L_deposit_l( shl_sat( x[i], exp0 ) ); -#else - y[i] = L_deposit_l( shl_o( x[i], exp0, &Overflow ) ); -#endif - move32(); - } - return; - } -#ifdef DEBUGGING - if ( exp0 >= 16 ) - { - printf( "Issue in Copy_Scale_sig_16_32_DEPREC\n" ); - } -#else - assert( exp0 < 16 ); -#endif -#ifdef ISSUE_1836_replace_overflow_libcom - tmp = shl_sat( 1, exp0 ); -#else - tmp = shl_o( 1, exp0, &Overflow ); -#endif - FOR( i = 0; i < lg; i++ ) - { - y[i] = L_mult0( x[i], tmp ); - move32(); /* saturation can occur here */ - } -} - -void Copy_Scale_sig_16_32_no_sat( - const Word16 x[], /* i : signal to scale input Qx */ - Word32 y[], /* o : scaled signal output Qx */ - const Word16 lg, /* i : size of x[] Q0 */ - const Word16 exp0 /* i : exponent: x = round(x << exp) Qx ?exp */ -) -{ - Word16 i; - Word32 L_tmp; -#ifndef ISSUE_1836_replace_overflow_libcom -#ifdef BASOP_NOGLOB_DECLARE_LOCAL - Flag Overflow = 0; - move32(); -#endif -#endif - - - IF( exp0 == 0 ) - { - FOR( i = 0; i < lg; i++ ) - { - y[i] = L_deposit_l( x[i] ); - move32(); - } - return; - } - IF( exp0 < 0 ) - { - /*Should not happen */ - FOR( i = 0; i < lg; i++ ) - { -#ifdef ISSUE_1836_replace_overflow_libcom - y[i] = L_deposit_l( shl_sat( x[i], exp0 ) ); -#else - y[i] = L_deposit_l( shl_o( x[i], exp0, &Overflow ) ); -#endif - move32(); - } - return; - } -#ifdef ISSUE_1836_replace_overflow_libcom - L_tmp = L_shl_sat( 1, exp0 - 1 ); -#else - L_tmp = L_shl_o( 1, exp0 - 1, &Overflow ); -#endif - - IF( L_tmp >= 0x7FFF ) - { - FOR( i = 0; i < lg; i++ ) - { - // y[i] = L_mult0(x[i], L_tmp); - y[i] = W_extract_l( W_mult_32_16( L_tmp, x[i] ) ); - move32(); /* Overflow can occur here */ - } - return; - } - // ELSE - { - Word16 tmp = extract_l( L_tmp ); - FOR( i = 0; i < lg; i++ ) - { - y[i] = L_mult( x[i], tmp ); - move32(); - } - } -} - -void Copy_Scale_sig_32_16( - const Word32 x[], /* i : signal to scale input Qx */ - Word16 y[], /* o : scaled signal output Qx */ - const Word16 lg, /* i : size of x[] Q0 */ - const Word16 exp0 /* i : exponent: x = round(x << exp) Qx ?exp */ -) -{ - Word16 i; - Word16 tmp; -#ifndef ISSUE_1836_replace_overflow_libcom -#ifdef BASOP_NOGLOB_DECLARE_LOCAL - Flag Overflow = 0; - move32(); -#endif -#endif - - tmp = add( 16, exp0 ); - IF( tmp != 0 ) - { - FOR( i = 0; i < lg; i++ ) - { -#ifdef ISSUE_1836_replace_overflow_libcom - y[i] = round_fx_sat( L_shl_sat( x[i], tmp ) ); -#else - y[i] = round_fx_o( L_shl_o( x[i], tmp, &Overflow ), &Overflow ); -#endif - move16(); - } - } - ELSE - { - FOR( i = 0; i < lg; i++ ) - { -#ifdef ISSUE_1836_replace_overflow_libcom - y[i] = round_fx_sat( x[i] ); -#else - y[i] = round_fx_o( x[i], &Overflow ); -#endif - move16(); - } - } -} - -/*-------------------------------------------------------------------* - * Scale_sig32 - * - * Up/down scale a 32 bits vector - *-------------------------------------------------------------------*/ -void Scale_sig32( - Word32 x[], /* i/o: signal to scale Qx */ - const Word16 lg, /* i : size of x[] Q0 */ - const Word16 exp0 /* i : exponent: x = round(x << exp) Qx ?exp */ -) -{ - Word16 i; -#ifndef ISSUE_1836_replace_overflow_libcom -#ifdef BASOP_NOGLOB_DECLARE_LOCAL - Flag Overflow = 0; - move32(); -#endif -#endif - IF( 0 == exp0 ) - { - return; - } - - FOR( i = 0; i < lg; i++ ) - { -#ifdef ISSUE_1836_replace_overflow_libcom - x[i] = L_shl_sat( x[i], exp0 ); -#else - x[i] = L_shl_o( x[i], exp0, &Overflow ); -#endif - move32(); /* saturation can occur here */ - } -} - -/*------------------------------------------------------------------* - * function Random_Fill - * - * Signed 16 bits random generator. - * (Avoids Store of Seed to Memory for 'n' Random Values and - * Combines Scaling Operation.) - *------------------------------------------------------------------*/ -void Random_Fill( - Word16 *seed, /* i/o: random seed */ - Word16 n, /* i : number of values */ - Word16 *y, /* o : output values */ - Word16 scaling /* i : scaling of values */ -) -{ - Word16 i; - Word16 local_seed; - - local_seed = *seed; - move16(); - FOR( i = 0; i < n; i++ ) - { - local_seed = extract_l( L_mac0( 13849L, local_seed, 31821 ) ); - *y++ = shr( local_seed, scaling ); - move16(); - } - *seed = local_seed; - move16(); -} -/*-------------------------------------------------------------------* - * Scale_sig - * Up/down scale a 16 bits vector - *-------------------------------------------------------------------*/ -void Scale_sig( - Word16 x[], /* i/o: signal to scale Qx */ - const Word16 lg, /* i : size of x[] Q0 */ - const Word16 exp0 /* i : exponent: x = round(x << exp) Qx ?exp */ -) -{ - Word16 i; - Word16 tmp; - - IF( exp0 > 0 ) - { - FOR( i = 0; i < lg; i++ ) - { - x[i] = shl_sat( x[i], exp0 ); - move16(); /* saturation can occur here */ - } - return; - } - IF( exp0 < 0 ) - { - tmp = shl_sat( -32768, exp0 ); /* we use negative to correctly represent 1.0 */ - FOR( i = 0; i < lg; i++ ) - { - x[i] = msu_r_sat( 0, x[i], tmp ); - move16(); /* msu instead of mac because factor is negative */ - } - return; - } -} - -/*-------------------------------------------------------------------* - * scale_sig - * Up/down scale a 16 bits vector - *-------------------------------------------------------------------*/ -void scale_sig( - Word16 x[], /* i/o: signal to scale Qx */ - const Word16 lg, /* i : size of x[] Q0 */ - const Word16 exp0 /* i : exponent: x = round(x << exp) Qx exp */ -) -{ - Word16 i; - - IF( exp0 != 0 ) - { - FOR( i = 0; i < lg; i++ ) - { - x[i] = shl( x[i], exp0 ); - move16(); - } - } -} - -/*---------------------------------------------------------------------* - * mean_fx() - * - *---------------------------------------------------------------------*/ -Word16 mean_fx( /* o : mean of vector */ - const Word16 *vec_fx, /* i : input vector */ - const Word16 lvec_fx /* i : length of input vector */ -) -{ - Word16 tmp; - // PMT("TBV : this function could be written differently to minimize the risk of saturation"); - tmp = sum16_fx( vec_fx, lvec_fx ); - tmp = mult_r( tmp, div_s( 1, lvec_fx ) ); - - return tmp; -} - -Word16 mean_no_sat_fx( /* o : mean of vector Qx */ - const Word16 *vec_fx, /* i : input vector Qx */ - const Word16 lvec_fx /* i : length of input vector */ -) -{ - Word16 i; - Word32 L_tmp = 0; - move32(); - FOR( i = 0; i < lvec_fx; ++i ) - { - L_tmp = L_add( L_tmp, vec_fx[i] ); - } - L_tmp = Mpy_32_16_1( L_tmp, div_s( 1, lvec_fx ) ); /* Qx */ - - return extract_l( L_tmp ); -} -Word32 mean_no_sat_Word32_fx( /* o : mean of vector Qx */ - const Word32 *vec_fx, /* i : input vector Qx */ - const Word16 lvec_fx, /* i : length of input vector */ - const Word16 gb ) -{ - Word16 i; - Word32 L_tmp = 0; - move32(); - FOR( i = 0; i < lvec_fx; ++i ) - { - L_tmp = L_add( L_tmp, L_shr( vec_fx[i], gb ) ); - } - L_tmp = Mpy_32_16_1( L_tmp, div_s( 1, lvec_fx ) ); /* Qx-gb */ - - return L_tmp; -} -/*-------------------------------------------------------------------* - * Vr_add - * - * Add two Word16 vectors together integer by integer - *-------------------------------------------------------------------*/ -void Vr_add( - const Word16 *in1, /* i : Input vector 1 */ - const Word16 *in2, /* i : Input vector 2 */ - Word16 *out, /* o : Output vector that contains vector 1 + vector 2 */ - Word16 Len /* i : Vector lenght */ -) -{ - Word16 i; - - FOR( i = 0; i < Len; i++ ) - { - out[i] = add_sat( in1[i], in2[i] ); - move16(); - } -} - -void sort_fx( - Word16 *r, /* i/o: Vector to be sorted in place */ - Word16 lo, /* i : Low limit of sorting range */ - Word16 up /* I : High limit of sorting range */ -) -{ - Word16 i, j, i1; - Word16 tempr; - - FOR( i = sub( up, 1 ); i >= lo; i-- ) - { - i1 = add( i, 1 ); - tempr = r[i]; - move16(); - move16(); /*supplementary move for the j-1 PTR initialization*/ - FOR( j = i1; j <= up; j++ ) - { - IF( LE_16( tempr, r[j] ) ) - { - BREAK; - } - - r[j - 1] = r[j]; - move16(); - } - r[j - 1] = tempr; - move16(); - } -} - -void sort_32_fx( - Word32 *r, /* i/o: Vector to be sorted in place */ - const Word16 lo, /* i : Low limit of sorting range */ - const Word16 up /* I : High limit of sorting range */ -) -{ - Word16 i, j; - Word32 tempr; - FOR( i = sub( up, 1 ); i >= lo; i-- ) - { - tempr = r[i]; - move32(); - FOR( j = add( i, 1 ); j <= up; j++ ) - { - IF( LE_32( tempr, r[j] ) ) - { - BREAK; - } - r[j - 1] = r[j]; - move32(); - } - - r[j - 1] = tempr; - move32(); - } - - return; -} - -Word16 minimum_fx( /* o : index of the minimum value in the input vector */ - const Word16 *vec_fx, /* i : input vector */ - const Word16 lvec_fx, /* i : length of input vector */ - Word16 *min_fx /* o : minimum value in the input vector */ -) -{ - Word16 j, ind; - Word16 tmp; - ind = 0; - move16(); - tmp = vec_fx[0]; - move16(); - - FOR( j = 1; j < lvec_fx; j++ ) - { - if ( LT_16( vec_fx[j], tmp ) ) - { - ind = j; - move16(); - /*tmp = vec_fx[j]; move16(); */ - } - tmp = s_min( tmp, vec_fx[j] ); - } - - *min_fx = tmp; - move16(); - - return ind; -} - -Word16 maximum_fx( /* o : index of the maximum value in the input vector */ - const Word16 *vec_fx, /* i : input vector */ - const Word16 lvec_fx, /* i : length of input vector */ - Word16 *max_fx /* o : maximum value in the input vector */ -) -{ - Word16 j, ind; - Word16 tmp; - ind = 0; - move16(); - tmp = vec_fx[0]; - move16(); - - FOR( j = 1; j < lvec_fx; j++ ) - { - if ( GT_16( vec_fx[j], tmp ) ) - { - ind = j; - move16(); - } - tmp = s_max( tmp, vec_fx[j] ); - } - *max_fx = tmp; - move16(); - - return ind; -} - -Word16 maximum_exp_fx( /* o : index of the maximum value in the input vector */ - const Word16 *vec_fx, /* i : input vector */ - const Word16 *exp_vec, /* i : exponents of input vector */ - const Word16 lvec_fx /* i : length of input vector */ -) -{ - Word16 j, ind; -#ifndef FIX_1981_MAXIMUM_EXP_FX - Word16 tmp, exp; - ind = 0; - move16(); - tmp = vec_fx[0]; - move16(); - exp = exp_vec[0]; - move16(); -#else - Word16 tmp, exp, scale; - ind = 0; - move16(); -#endif - -#if 0 - - float vec_float[1024]; - for ( int ii = 0; ii < lvec_fx; ii++ ) - vec_float[ii] = vec_fx[ii] * pow( 2, exp_vec[ii] - 31 ); - -#endif - - -#ifdef FIX_1981_MAXIMUM_EXP_FX - scale = sub( norm_s( vec_fx[ind] ), 1 ); - - FOR( j = 1; j < lvec_fx; j++ ) - { - - IF( LT_16( tmp, shr_sat( vec_fx[j], sub( exp, exp_vec[j] ) ) ) ) - { - ind = j; - move16(); - - scale = sub( norm_s( vec_fx[ind] ), 1 ); - tmp = shl( vec_fx[j], scale ); - exp = sub( exp_vec[j], scale ); - } - } -#else - FOR( j = 1; j < lvec_fx; j++ ) - { -#if 0 - // insert assert to find critical bitstreams - { - static int calls = 0; - calls++; - Word16 tmp16, tmp16_1; - Word32 tmp32, tmp32_1; - tmp16 = tmp; - tmp32 = L_deposit_l( tmp ); - - tmp16_1 = shr_sat( vec_fx[j] , sub( exp, exp_vec[j] ) ); - tmp32_1 = L_shr_sat( L_deposit_l( vec_fx[j] ), sub( exp, exp_vec[j] ) ); - - if ( ( LT_16( tmp16, tmp16_1 ) != LT_32( tmp32, tmp32_1 ) ) ) - { - tmp16 = LT_16( tmp16, tmp16_1 ); - tmp32 = LT_32( tmp32, tmp32_1 ); - assert( tmp16 == tmp32 ); - } - } -#endif - - IF( LT_16( tmp, shr_sat( vec_fx[j], sub( exp, exp_vec[j] ) ) ) ) - { - ind = j; - move16(); - tmp = vec_fx[j]; - move16(); - exp = exp_vec[j]; - move16(); - } - } -#endif -#if 1 /*value out*/ - printf( "\n val= %15.15f", (float)vec_fx[ind] * pow(2,exp_vec[ind] - 15) ); -#endif - - return ind; -} - -/*---------------------------------------------------------------------* - * maximum_abs_16_fx() - * - * Find index and value of the absolute maximum in a vector - *---------------------------------------------------------------------*/ - -Word16 maximum_abs_16_fx( /* o : index of the maximum abs value in the input vector */ - const Word16 *vec, /* i : input vector */ - const Word16 lvec, /* i : length of input vector */ - Word16 *max_val /* o : maximum value in the input vector */ -) -{ - Word16 j, ind; - Word16 tmp; - ind = 0; - move16(); - tmp = abs_s( vec[0] ); - - FOR( j = 1; j < lvec; j++ ) - { - if ( GT_16( abs_s( vec[j] ), tmp ) ) - { - ind = j; - move16(); - } - tmp = s_max( tmp, abs_s( vec[j] ) ); - } - *max_val = tmp; - move16(); - - return ind; -} - -/*---------------------------------------------------------------------* - * minimum_abs32_fx() - * - * Find index and value of the absolute minimum in a vector - *---------------------------------------------------------------------*/ -Word16 minimum_abs32_fx( /* o : index of the minimum value in the input vector */ - const Word32 *vec_fx, /* i : input vector */ - const Word16 lvec_fx, /* i : length of input vector */ - Word32 *min_fx /* o : minimum value in the input vector */ -) -{ - Word16 j, ind; - Word32 tmp; - ind = 0; - move16(); - tmp = vec_fx[0]; - move16(); - - FOR( j = 1; j < lvec_fx; j++ ) - { - IF( LT_32( L_abs( vec_fx[j] ), tmp ) ) - { - ind = j; - move16(); - /*tmp = vec_fx[j]; move16(); */ - } - tmp = L_min( tmp, L_abs( vec_fx[j] ) ); - } - - *min_fx = tmp; - move16(); - - return ind; -} - -/*---------------------------------------------------------------------* - * minimum_32_fx() - * - * Find index and value of the minimum in a vector - *---------------------------------------------------------------------*/ - -Word16 minimum_32_fx( /* o : index of the minimum value in the input vector */ - const Word32 *vec_fx, /* i : input vector */ - const Word16 lvec_fx, /* i : length of input vector */ - Word32 *min_fx /* o : minimum value in the input vector */ -) -{ - Word16 j, ind; - Word32 tmp; - ind = 0; - move16(); - tmp = vec_fx[0]; - move16(); - - FOR( j = 1; j < lvec_fx; j++ ) - { - if ( LT_32( vec_fx[j], tmp ) ) - { - ind = j; - move16(); - /*tmp = vec_fx[j]; move32(); */ - } - tmp = L_min( tmp, vec_fx[j] ); - } - if ( min_fx != NULL ) - { - *min_fx = tmp; - } - move32(); - - return ind; -} - -/*---------------------------------------------------------------------* - * maximum_32_fx() - * - * Find index and value of the maximum in a vector - *---------------------------------------------------------------------*/ - -Word16 maximum_32_fx( /* o : index of the maximum value in the input vector */ - const Word32 *vec, /* i : input vector */ - const Word16 lvec, /* i : length of input vector */ - Word32 *max_val /* o : maximum value in the input vector */ -) -{ - Word16 j, ind; - Word32 tmp; - ind = 0; - move16(); - tmp = vec[0]; - move16(); - - FOR( j = 1; j < lvec; j++ ) - { - IF( GT_32( vec[j], tmp ) ) - { - ind = j; - move16(); - } - tmp = L_max( tmp, vec[j] ); - } - if ( max_val != NULL ) - { - *max_val = tmp; - } - move32(); - - return ind; -} - -Word16 maximum_abs_32_fx( /* o : index of the maximum abs value in the input vector */ - const Word32 *vec, /* i : input vector */ - const Word16 lvec, /* i : length of input vector */ - Word32 *max_val /* o : maximum value in the input vector */ -) -{ - Word16 j, ind; - Word32 tmp; - ind = 0; - move16(); - tmp = L_abs( vec[0] ); - - FOR( j = 1; j < lvec; j++ ) - { - if ( GT_32( L_abs( vec[j] ), tmp ) ) - { - ind = j; - move16(); - } - tmp = L_max( tmp, L_abs( vec[j] ) ); - } - *max_val = tmp; - move32(); - - return ind; -} - - -/*---------------------------------------------------------------- - *Function: - *Finds number of shifts to normalize a 16-bit array variable. - *Return value - *Number of shifts - *----------------------------------------------------------------*/ -Word16 Exp16Array( - const Word16 n, /* (i): Array size */ - const Word16 *sx /* (i): Data array */ -) -{ - Word16 k; - Word16 exp; - Word16 sMax; - Word16 sAbs; - - sMax = abs_s( sx[0] ); - move16(); - - FOR( k = 1; k < n; k++ ) - { - sAbs = abs_s( sx[k] ); - sMax = s_max( sMax, sAbs ); - } - - exp = norm_s( sMax ); - return exp; -} - -Word16 Exp32Array( - const Word16 n, /* (i): Array size */ - const Word32 *sx /* (i): Data array */ -) -{ - Word16 k; - Word16 exp; - Word32 L_Max; - Word32 L_Abs; - - L_Max = L_abs( sx[0] ); - FOR( k = 1; k < n; k++ ) - { - L_Abs = L_abs( sx[k] ); - L_Max = L_max( L_Max, L_Abs ); - } - exp = norm_l( L_Max ); - - if ( L_Max == 0 ) - { - exp = 31; - move16(); - } - return exp; -} - -Word32 sum16_32_fx( /* o : sum of all vector elements Qx*/ - const Word16 *vec, /* i : input vector Qx*/ - const Word16 lvec /* i : length of input vector */ -) -{ - Word16 i; - Word32 tmp, L_var; - tmp = 0; - move16(); - FOR( i = 0; i < lvec; i++ ) - { - L_var = L_deposit_l( vec[i] ); - tmp = L_add( tmp, L_var ); /*Qx */ - } - - return tmp; -} - -Word32 sum32_sat( /* o : sum of all vector elements Qx*/ - const Word32 *vec, /* i : input vector Qx*/ - const Word16 lvec /* i : length of input vector */ -) -{ - Word16 i; - Word32 tmp; - tmp = 0; - move16(); - FOR( i = 0; i < lvec; i++ ) - { - tmp = L_add_sat( tmp, vec[i] ); /*Qx */ - } - - return tmp; -} - -Word32 var_fx_32( /* o: variance of vector Qx+16*/ - const Word16 *x, /* i: input vector Qx*/ - const Word16 Qx, - const Word16 len /* i: length of inputvector */ -) -{ - Word16 m; - Word32 v; - Word16 i; - Word16 tmp, exp, inv_len; - Word32 L_tmp; - - - L_tmp = L_add( x[0], 0 ); - FOR( i = 1; i < len; i++ ) - { - L_tmp = L_add( L_tmp, x[i] ); /*Qx */ - } - exp = norm_s( len ); - inv_len = div_s( shl( 1, sub( 14, exp ) ), len ); /*Q(29-exp) */ - L_tmp = Mult_32_16( L_tmp, inv_len ); /*Q(14-exp+Qx) */ - m = round_fx( L_shl( L_tmp, add( exp, 2 ) ) ); /*Qx */ - - v = L_deposit_l( 0 ); - FOR( i = 0; i < len; i++ ) - { - tmp = sub( x[i], m ); /*Qx */ - v = L_mac0_sat( v, tmp, tmp ); /*(Qx+Qx) */ - } - L_tmp = Mult_32_16( v, inv_len ); /*Q(14-exp+Qx+Qx) */ - v = L_shl( L_tmp, add( exp, sub( 2, Qx ) ) ); /*Qx+16 */ - - return v; -} - -Word32 var_fx_32in_32out( /* o: variance of vector Qx*/ - const Word32 *x, /* i: input vector Qx*/ - Word16 *Qx, /*i/o:Q for input/output */ - const Word16 len, /* i: length of inputvector */ - const Word16 gb ) -{ - Word16 i; - Word16 shift; - Word32 L_tmp1, L_tmp; - Word64 W_temp; - - L_tmp = mean_no_sat_Word32_fx( x, len, gb ); /*Qx-gb */ - W_temp = 0; - FOR( i = 0; i < len; i++ ) - { - L_tmp1 = L_sub( L_shr( x[i], gb ), L_tmp ); /*Qx-gb */ - W_temp = W_add( W_temp, W_mult0_32_32( L_tmp1, L_tmp1 ) ); /*Qx-gb +Qx-gb*/ - } - shift = W_norm( W_temp ); - L_tmp = Mult_32_16( W_extract_h( W_shl( W_temp, shift ) ), div_s( 1, len ) ); /*Q2*(Qx-gb)+shift -32 */ - - *Qx = sub( add( shl( sub( *Qx, gb ), 1 ), shift ), 32 ); - move16(); - return L_tmp; -} -/*-------------------------------------------------------------------* - * conv() - * - * Convolution between vectors x[] and h[] written to y[] - * All vectors are of length L. Only the first L samples of the - * convolution are considered. - *-------------------------------------------------------------------*/ - -Flag conv_fx( - const Word16 x[], /* i : input vector Q_new*/ - const Word16 h[], /* i : impulse response (or second input vector) Q(15)*/ - Word16 y[], /* o : output vetor (result of convolution) 12 bits*/ - const Word16 L /* i : vector size */ -) -{ - - Word16 i, n; - Word32 L_sum; -#ifdef BASOP_NOGLOB_DECLARE_LOCAL - Flag Overflow = 0; - move32(); -#endif - y[0] = mult_r( x[0], h[0] ); - move16(); - FOR( n = 1; n < L; n++ ) - { - L_sum = L_mult( x[0], h[n] ); - FOR( i = 1; i < n; i++ ) - { - L_sum = L_mac_o( L_sum, x[i], h[n - i], &Overflow ); - } - y[n] = mac_ro( L_sum, x[i], h[0], &Overflow ); - move16(); - } - return Overflow; -} - -/*-------------------------------------------------------------------* - * conv_fx_32() - * - * Convolution between vectors x[] and h[] written to y[] - * All vectors are of length L. Only the first L samples of the - * convolution are considered. - *-------------------------------------------------------------------*/ -Flag conv_fx_32( - const Word16 x[], /* i : input vector Q_new*/ - const Word16 h[], /* i : impulse response (or second input vector) Q(15)*/ - Word32 y[], /* o : output vetor (result of convolution) 12 bits*/ - const Word16 L /* i : vector size */ -) -{ - - Word16 i, n; - Word32 L_sum; - Flag Overflow = 0; - y[0] = L_mult( x[0], h[0] ); - move32(); - FOR( n = 1; n < L; n++ ) - { - L_sum = L_mult( x[0], h[n] ); - FOR( i = 1; i < n; i++ ) - { - L_sum = L_mac_o( L_sum, x[i], h[n - i], &Overflow ); - } - y[n] = L_mac_o( L_sum, x[i], h[0], &Overflow ); - move32(); - } - return Overflow; -} -Word16 var_fx( /* o: variance of vector Qx*/ - const Word16 *x, /* i: input vector Qx*/ - const Word16 Qx, - const Word16 len /* i: length of inputvector */ -) -{ - Word16 m; - Word32 v; - Word16 v_16; - Word16 i; - Word16 tmp, exp, inv_len; - Word32 L_tmp; - - L_tmp = x[0]; - move32(); - FOR( i = 1; i < len; i++ ) - { - L_tmp = L_add( L_tmp, x[i] ); /*Qx */ - } - exp = norm_s( len ); - inv_len = div_s( shl( 1, sub( 14, exp ) ), len ); /*Q(29-exp) */ - L_tmp = Mult_32_16( L_tmp, inv_len ); /*Q(14-exp+Qx) */ - m = round_fx( L_shl( L_tmp, add( exp, 2 ) ) ); /*Qx */ - - v = L_deposit_l( 0 ); - FOR( i = 0; i < len; i++ ) - { - tmp = sub_sat( x[i], m ); /*Qx */ - v = L_mac0_sat( v, tmp, tmp ); /*(Qx+Qx) */ - } - L_tmp = Mult_32_16( v, inv_len ); /*Q(14-exp+Qx+Qx) */ - v_16 = round_fx_sat( L_shl_sat( L_tmp, add( exp, sub( 2, Qx ) ) ) ); /*Qx */ - - return v_16; -} - -/*---------------------------------------------------------------------* - * std_fx() - * - * Calculate the standard deviation of a vector - *---------------------------------------------------------------------*/ - -Word16 std_fx( /* o: standard deviation */ - const Word16 x[], /* i: input vector */ - const Word16 len /* i: length of the input vector */ -) -{ - Word16 i; - Word32 L_tmp; - Word16 exp1, exp2, tmp; - Word32 stdev; - - stdev = 0; - move16(); - FOR( i = 0; i < len; i++ ) - { - L_tmp = L_mult( x[i], x[i] ); /*29 */ - stdev = L_add( stdev, L_shr( L_tmp, 3 ) ); /*26 */ - } - - IF( stdev != 0 ) - { - exp1 = norm_l( stdev ); - tmp = div_s( 16384, extract_h( L_shl( stdev, exp1 ) ) ); /*15 + 14 - (26 + exp1 - 16) */ - L_tmp = L_mult( tmp, len ); /*15 + 14 - (26 + exp1 - 16) + 1 */ - exp2 = norm_l( L_tmp ); - exp1 = add( sub( exp1, exp2 ), 11 ); - stdev = Isqrt_lc( L_shl( L_tmp, exp2 ), &exp1 ); /*31-exp1 */ - stdev = L_shl( stdev, sub( exp1, 1 ) ); /*30 */ - } - - - return extract_h( stdev ); -} - -Word32 dot_product_mat_fx( /* o : the dot product x'*A*x */ - const Word16 *x, /* i : vector x Q15 */ - const Word32 *A, /* i : matrix A Q0*/ - const Word16 m /* i : vector & matrix size */ - -) -{ - Word16 i, j; - Word64 tmp_sum_64; - Word32 suma, tmp_sum; - const Word32 *pt_A; - const Word16 *pt_x; - - pt_A = A; - suma = L_deposit_l( 0 ); - - FOR( i = 0; i < m; i++ ) - { - tmp_sum_64 = 0; - move64(); - pt_x = x; - FOR( j = 0; j < m; j++ ) - { - tmp_sum_64 = W_mac_32_16( tmp_sum_64, *pt_A, *pt_x ); /*Q0 */ - pt_A++; - pt_x++; - } - tmp_sum = W_sat_m( tmp_sum_64 ); - suma = Madd_32_16( suma, tmp_sum, x[i] ); /*Q0 */ - } - return suma; -} -/*-------------------------------------------------------------------* - * Vr_subt - * - * Subtract two Word16 vectors integer by integer - *-------------------------------------------------------------------*/ -void Vr_subt( - const Word16 x1[], /* i : Input vector 1 */ - const Word16 x2[], /* i : Input vector 2 */ - Word16 y[], /* o : Output vector that contains vector 1 - vector 2 */ - Word16 N /* i : Vector lenght */ -) -{ - Word16 i; - - FOR( i = 0; i < N; i++ ) - { - y[i] = sub_sat( x1[i], x2[i] ); - move16(); - } -} -/*-------------------------------------------------------------------* - * vquant() - * - * Vector quantizer according to MMSE criterion (nearest neighbour in Euclidean space) - * - * Searches a given codebook to find the nearest neighbour in Euclidean space. - * Index of the winning codevector and the winning vector itself are returned. - *-------------------------------------------------------------------*/ -Word16 vquant_ivas_fx( /* o: index of the winning codevector */ - Word32 x[], /* i: vector to quantize Q25 */ - const Word32 x_mean[], /* i: vector mean to subtract (0 if none) Q25 */ - Word32 xq[], /* o: quantized vector Q25 */ - const Word32 cb[], /* i: codebook Q25 */ - const Word16 dim, /* i: dimension of codebook vectors */ - const Word16 cbsize /* i: codebook size */ -) -{ - Word16 c, d, idx, j; - Word32 L_dist, L_tmp, L_mindist; - - idx = 0; - move16(); - L_mindist = MAX_32; - move32(); - IF( x_mean != 0 ) - { - FOR( d = 0; d < dim; d++ ) - { - /*x[d] -= x_mean[d]; */ - x[d] = L_sub( x[d], x_mean[d] ); - move32(); /*Qx */ - } - } - j = 0; - move16(); - FOR( c = 0; c < cbsize; c++ ) - { - L_dist = 0; - move32(); - - FOR( d = 0; d < dim; d++ ) - { - /*tmp = x[d] - cb[j++];*/ - L_tmp = L_sub( x[d], cb[j++] ); // Q25 - L_dist = L_add( L_dist, Mpy_32_32( L_tmp, L_tmp ) ); // (Q25, Q25) -> Q19 - } - if ( LT_32( L_dist, L_mindist ) ) // Q19 - { - idx = c; - move16(); - } - L_mindist = L_min( L_mindist, L_dist ); // Q19 - } - IF( xq == 0 ) - { - return idx; - } - - /*j = idx*dim;*/ - j = i_mult2( idx, dim ); - FOR( d = 0; d < dim; d++ ) - { - xq[d] = cb[j++]; // Q25 - move32(); - } - IF( x_mean != 0 ) - { - FOR( d = 0; d < dim; d++ ) - { - /*xq[d] += x_mean[d]; */ - xq[d] = L_add( xq[d], x_mean[d] ); // Q25 - move32(); - } - } - - return idx; -} - -Word16 vquant_fx( /* o: index of the winning codevector */ - Word16 x[], /* i: vector to quantize Q13 */ - const Word16 x_mean[], /* i: vector mean to subtract (0 if none) Q13 */ - Word16 xq[], /* o: quantized vector Q13 */ - const Word16 cb[], /* i: codebook Q13 */ - const Word16 dim, /* i: dimension of codebook vectors */ - const Word16 cbsize /* i: codebook size */ -) -{ - Word16 tmp; - Word16 c, d, idx, j; - Word32 L_dist, /*L_tmp,*/ L_mindist; - - idx = 0; - move16(); - L_mindist = MAX_32; - move32(); - IF( x_mean != 0 ) - { - FOR( d = 0; d < dim; d++ ) - { - /*x[d] -= x_mean[d]; */ - x[d] = sub( x[d], x_mean[d] ); - move16(); /*Qx */ - } - } - j = 0; - move16(); - FOR( c = 0; c < cbsize; c++ ) - { - L_dist = 0; - move32(); - - FOR( d = 0; d < dim; d++ ) - { - /*tmp = x[d] - cb[j++];*/ - tmp = sub( x[d], cb[j++] ); /*Qx */ - L_dist = L_mac0( L_dist, tmp, tmp ); - } - if ( LT_32( L_dist, L_mindist ) ) - { - idx = c; - move16(); - } - L_mindist = L_min( L_mindist, L_dist ); - } - IF( xq == 0 ) - { - return idx; - } - - /*j = idx*dim;*/ - j = i_mult2( idx, dim ); - FOR( d = 0; d < dim; d++ ) - { - xq[d] = cb[j++]; - move16(); - } - IF( x_mean != 0 ) - { - FOR( d = 0; d < dim; d++ ) - { - /*xq[d] += x_mean[d]; */ - xq[d] = add( xq[d], x_mean[d] ); - move16(); - } - } - - return idx; -} - -/*-------------------------------------------------------------------* - * w_vquant_fx() - * - * Vector quantizer according to MMSE criterion (nearest neighbour in Euclidean space) - * - * Searches a given codebook to find the nearest neighbour in Euclidean space. - * Weights are put on the error for each vector element. - * Index of the winning codevector and the winning vector itself are returned. - *-------------------------------------------------------------------*/ -Word16 w_vquant_fx( - Word16 x[], /* i: vector to quantize in Q10 */ - Word16 Qx, - const Word16 weights[], /* i: error weights in Q0 */ - Word16 xq[], /* o: quantized vector in Q15 */ - const Word16 cb[], /* i: codebook in Q15 */ - const Word16 cbsize, /* i: codebook size */ - const Word16 rev_vect /* i: reverse codebook vectors */ -) -{ - Word16 tmp; - Word16 c, idx, j; - Word32 dist, minDist; -#ifndef ISSUE_1836_replace_overflow_libcom -#ifdef BASOP_NOGLOB_DECLARE_LOCAL - Flag Overflow = 0; - move32(); -#endif -#endif - - - idx = 0; - move16(); - minDist = 0x7fffffffL; - move32(); - Qx = sub( 15, Qx ); - - j = 0; - move16(); - IF( rev_vect ) - { - FOR( c = 0; c < cbsize; c++ ) - { - dist = L_deposit_l( 0 ); - -#ifdef ISSUE_1836_replace_overflow_libcom - tmp = sub_sat( x[3], shr( cb[j++], Qx ) ); - if ( weights[3] != 0 ) - { - dist = L_mac0_sat( dist, tmp, tmp ); - } - tmp = sub_sat( x[2], shr( cb[j++], Qx ) ); - if ( weights[2] != 0 ) - { - dist = L_mac0_sat( dist, tmp, tmp ); - } - tmp = sub_sat( x[1], shr( cb[j++], Qx ) ); - if ( weights[1] != 0 ) - { - dist = L_mac0_sat( dist, tmp, tmp ); - } - tmp = sub_sat( x[0], shr( cb[j++], Qx ) ); - if ( weights[0] != 0 ) - { - dist = L_mac0_sat( dist, tmp, tmp ); - } -#else - tmp = sub_o( x[3], shr( cb[j++], Qx ), &Overflow ); - if ( weights[3] != 0 ) - { - dist = L_mac0_o( dist, tmp, tmp, &Overflow ); - } - tmp = sub_o( x[2], shr( cb[j++], Qx ), &Overflow ); - if ( weights[2] != 0 ) - { - dist = L_mac0_o( dist, tmp, tmp, &Overflow ); - } - tmp = sub_o( x[1], shr( cb[j++], Qx ), &Overflow ); - if ( weights[1] != 0 ) - { - dist = L_mac0_o( dist, tmp, tmp, &Overflow ); - } - tmp = sub_o( x[0], shr( cb[j++], Qx ), &Overflow ); - if ( weights[0] != 0 ) - { - dist = L_mac0_o( dist, tmp, tmp, &Overflow ); - } -#endif - if ( LT_32( dist, minDist ) ) - { - idx = c; - move16(); - } - minDist = L_min( minDist, dist ); - } - - IF( xq == 0 ) - { - return idx; - } - - j = shl( idx, 2 ); - xq[3] = cb[j++]; - move16(); /* in Q15 */ - xq[2] = cb[j++]; - move16(); /* in Q15 */ - xq[1] = cb[j++]; - move16(); /* in Q15 */ - xq[0] = cb[j++]; - move16(); /* in Q15 */ - } - ELSE - { - FOR( c = 0; c < cbsize; c++ ) - { - dist = L_deposit_l( 0 ); - -#ifdef ISSUE_1836_replace_overflow_libcom - tmp = sub_sat( x[0], shr( cb[j++], Qx ) ); - if ( weights[0] != 0 ) - { - dist = L_mac0_sat( dist, tmp, tmp ); - } - tmp = sub_sat( x[1], shr( cb[j++], Qx ) ); - if ( weights[1] != 0 ) - { - dist = L_mac0_sat( dist, tmp, tmp ); - } - tmp = sub_sat( x[2], shr( cb[j++], Qx ) ); - if ( weights[2] != 0 ) - { - dist = L_mac0_sat( dist, tmp, tmp ); - } - tmp = sub_sat( x[3], shr( cb[j++], Qx ) ); - if ( weights[3] != 0 ) - { - dist = L_mac0_sat( dist, tmp, tmp ); - } -#else - tmp = sub_o( x[0], shr( cb[j++], Qx ), &Overflow ); - if ( weights[0] != 0 ) - { - dist = L_mac0_o( dist, tmp, tmp, &Overflow ); - } - tmp = sub_o( x[1], shr( cb[j++], Qx ), &Overflow ); - if ( weights[1] != 0 ) - { - dist = L_mac0_o( dist, tmp, tmp, &Overflow ); - } - tmp = sub_o( x[2], shr( cb[j++], Qx ), &Overflow ); - if ( weights[2] != 0 ) - { - dist = L_mac0_o( dist, tmp, tmp, &Overflow ); - } - tmp = sub_o( x[3], shr( cb[j++], Qx ), &Overflow ); - if ( weights[3] != 0 ) - { - dist = L_mac0_o( dist, tmp, tmp, &Overflow ); - } -#endif - if ( LT_32( dist, minDist ) ) - { - idx = c; - move16(); - } - minDist = L_min( minDist, dist ); - } - - IF( xq == 0 ) - { - return idx; - } - - j = shl( idx, 2 ); - xq[0] = cb[j++]; - move16(); /* in Q15 */ - xq[1] = cb[j++]; - move16(); /* in Q15 */ - xq[2] = cb[j++]; - move16(); /* in Q15 */ - xq[3] = cb[j++]; - move16(); /* in Q15 */ - } - - return idx; -} -/*-------------------------------------------------------------------* - * Emaximum: - * - * Find index of a maximum energy in a vector - *-------------------------------------------------------------------*/ -Word16 emaximum_fx( /* o : return index with max energy value in vector Q0 */ - const Word16 Qvec, /* i : Q of input vector Q0 */ - const Word16 *vec, /* i : input vector Qx */ - const Word16 lvec, /* i : length of input vector Q0 */ - Word32 *ener_max /* o : maximum energy value Q0 */ -) -{ - Word16 j, ind; - Word32 L_tmp, L_tmp1; - Word32 emax; - - emax = L_mult0( vec[0], vec[0] ); - ind = 0; - move16(); - - FOR( j = 1; j < lvec; j++ ) - { - L_tmp = L_mult0( vec[j], vec[j] ); - L_tmp1 = L_sub( L_tmp, emax ); - if ( L_tmp1 > 0 ) - { - ind = j; - move16(); - } - emax = L_max( emax, L_tmp ); - } - - *ener_max = L_shr_sat( emax, add( Qvec, Qvec ) ); - move32(); - - return ind; -} - -Word16 emaximum_32fx( /* o : return index with max energy value in vector Q0 */ - const Word16 Qvec, /* i : Q of input vector Q0 */ - const Word32 *vec, /* i : input vector Qx */ - const Word16 lvec, /* i : length of input vector Q0 */ - Word32 *ener_max /* o : maximum energy value Q0 */ -) -{ - Word16 j, ind; - Word64 W_tmp, W_tmp1; - Word64 emax; - - emax = W_mult0_32_32( vec[0], vec[0] ); - ind = 0; - move16(); - - FOR( j = 1; j < lvec; j++ ) - { - W_tmp = W_mult0_32_32( vec[j], vec[j] ); - W_tmp1 = W_sub( W_tmp, emax ); - if ( W_tmp1 > 0 ) - { - ind = j; - move16(); - } - if ( LE_64( emax, W_tmp ) ) - { - emax = W_tmp; - move64(); - } - } - - *ener_max = W_extract_l( W_shr( emax, add( Qvec, Qvec ) ) ); - move32(); - - return ind; -} - -/*-------------------------------------------------------------------* - * mean32: - * - * Find the mean of a 32 bits vector - *-------------------------------------------------------------------*/ -Word32 Mean32( /* o : mean of the elements of the vector */ - const Word32 in[], /* i : input vector */ - const Word16 L /* i : length of input vector */ -) -{ - Word32 Ltmp; - Word16 inv_L; - - inv_L = INV_BANDS9; - move16(); - if ( EQ_16( L, 10 ) ) - { - inv_L = INV_BANDS10; - move16(); - } - - Ltmp = sum32_fx( in, L ); - - Ltmp = Mult_32_16( Ltmp, inv_L ); - - return Ltmp; -} -Word32 sum32_fx( /* o : sum of all vector elements Qx*/ - const Word32 *vec, /* i : input vector Qx*/ - const Word16 lvec /* i : length of input vector */ -) -{ - Word16 i; - Word32 tmp; - - tmp = L_deposit_l( 0 ); - FOR( i = 0; i < lvec; i++ ) - { - tmp = L_add_sat( tmp, vec[i] ); /*Qx */ - } - - return tmp; -} -Word16 sum16_fx( /* o : sum of all vector elements Qx*/ - const Word16 *vec, /* i : input vector Qx*/ - const Word16 lvec /* i : length of input vector */ -) -{ - Word16 i; - Word16 tmp; - tmp = 0; - move16(); - FOR( i = 0; i < lvec; i++ ) - { - tmp = add_sat( tmp, vec[i] ); /*Qx */ - } - - return tmp; -} -/*------------------------------------------------------------------* - * function Random - * - * Signed 16 bits random generator. - *------------------------------------------------------------------*/ -Word16 Random( /* o : output random value */ - Word16 *seed /* i/o: random seed */ -) -{ - *seed = extract_l( L_mac0( 13849L, *seed, 31821 ) ); - move16(); - return *seed; -} - -Word16 own_random2_fx( Word16 seed ) -{ - return extract_l( L_mac0( 13849, seed, 31821 ) ); -} - -/*--------------------------------------------------------------------- - * sign_fx() - * - *---------------------------------------------------------------------*/ - -/*! r: sign of x (+1/-1) */ -Word16 sign_fx( - const Word32 x /* i : input value of x */ -) -{ - IF( LT_32( x, 0 ) ) - { - return -1; - } - ELSE - { - return 1; - } -} - -Word16 sign16_fx( - const Word16 x /* i : input value of x */ -) -{ - IF( LT_16( x, 0 ) ) - { - return -1; - } - ELSE - { - return 1; - } -} - -/*------------------------------------------------------------------* - * function Div_32_optmz - * - * Performs 32 bits interger division - *------------------------------------------------------------------*/ -static Word32 Div_32_optmz( Word32 L_num, Word16 denom_hi ) -{ - Word16 approx, hi, lo, n_hi, n_lo; - Word32 L_32; - - /* First approximation: 1 / L_denom = 1/denom_hi */ - - approx = div_s( (Word16) 0x3fff, denom_hi ); - - /* 1/L_denom = approx * (2.0 - L_denom * approx) */ - - L_32 = L_msu( (Word32) 0x7fffffffL, denom_hi, approx ); - - lo = L_Extract_lc( L_32, &hi ); - L_32 = Mpy_32_16( hi, lo, approx ); - - /* L_num * (1/L_denom) */ - - lo = L_Extract_lc( L_32, &hi ); - n_lo = L_Extract_lc( L_num, &n_hi ); - L_32 = Mpy_32( n_hi, n_lo, hi, lo ); - - return ( L_32 ); -} -/*------------------------------------------------------------------* - * function iDiv_and_mod_32 - * - * return the quotient and the modulo 32 bits numerator divided by a 16 bit denominator - * The denominator might be right shifted by 1 - *------------------------------------------------------------------*/ -void iDiv_and_mod_32( - const Word32 Numer, /* i : 32 bits numerator */ - const Word16 Denom, /* i : 16 bits denominator */ - Word32 *Int_quotient, /* o : integer result of the division (int)(num/den) */ - Word32 *Int_mod, /* o : modulo result of the division num-((int)(num/den)*den)*/ - const Word16 rshift /* i : 0 if no right shift / 1 if the denom is right shifted by 1 */ -) -{ - Word32 Quotient; - Word16 expA, expB; - Word32 N, TEMP; - Word16 D; - - /* Normalize 'Numer' & 'Denom' */ - /* Use Temporary to Preserve the Original Value */ - expA = norm_l( Numer ); - N = L_shl( Numer, expA ); - expB = norm_s( Denom ); - D = shl( Denom, expB ); - - /* Need to shift right 'Numer' by 1? */ - if ( L_mac( N, D, -32768L ) >= 0 ) - { - expA = sub( expA, 1 ); - } - N = L_shl( Numer, expA ); - - /* Perform Approximation of the Division - * Since 'lo' part is '0' AND 'denom' is supposed to be constant in the targeted usage - * one could import the Div32 code and pre-calc the div_s and eliminate all calcs - * with 'lo' to save some complexity */ - - Quotient = Div_32_optmz( N, D ); /* takes 36 clocks */ - /* Bring Back to Q0 (minus 2 because we removed the left shift by 2 in the Div32_optmz) */ - IF( rshift ) - { - Quotient = L_shr( Quotient, add( 15 - 2, sub( expA, sub( expB, 1 ) ) ) ); - } - ELSE - { - Quotient = L_shr( Quotient, add( 15 - 2, sub( expA, expB ) ) ); - } - - /* Cross Check (do Quotient x Divisor) - * The Quotient is unsigned but we cannot just use extract_h because - * extract_l on the low part will get the sign of the bit #15. - * In a 32 bits value, what is in bits 0-15 is un unsigned 16 bits value. - * So, we shift left by 1, extract the hi part and mult it by 32768 (hence the L_shl by 16-1. - * Then we take 15 bits left (mask the others) and multiply by Denom. - * Technically this could overflow. But since we are mutiplying to get - * back to the Numer value that fitted in a 32 bits, doing Divisor x Quotient - * must necessarily fit in a 32 bits - * It is assumed that all are positive values. If not, one could - * check the sign of the numer and denom, turn them into abs values - * and restore the sign after*/ - TEMP = L_shl( L_mult0( extract_h( L_shl( Quotient, 1 ) ), Denom ), 16 - 1 ); - TEMP = L_mac0( TEMP, extract_l( L_and( 0x7FFF, Quotient ) ), Denom ); - - - /* Here we test to see if the previous "Quotient x Divisor" (or TEMP) is too small - * that is the "Numer" minus TEMP is bigger or Equal to the Divisor. - * If it is then the quotient is too small. We need to increase it by 1. - * That is caused by our Div32 fractionnal division that can be off by 1 - * sometimes. - * In some cases, when the divisor is very small (like 10 or something) - * the quotient could be off by more than 1 and we would need a loop - * to check again. That is not the case here with the current divisor */ - IF( rshift ) - { - TEMP = L_shl( TEMP, 1 ); - WHILE( L_msu0( L_sub( Numer, TEMP ), 2, Denom ) >= 0 ) - { - Quotient = L_add( Quotient, 1 ); - TEMP = L_shl( L_mult0( extract_h( L_shl( Quotient, 1 ) ), Denom ), 16 - 1 ); - TEMP = L_mac0( TEMP, extract_l( L_and( 0x7FFF, Quotient ) ), Denom ); - TEMP = L_shl( TEMP, 1 ); - } - } - ELSE{ - WHILE( L_msu0( L_sub( Numer, TEMP ), 1, Denom ) >= 0 ){ - Quotient = L_add( Quotient, 1 ); - TEMP = L_shl( L_mult0( extract_h( L_shl( Quotient, 1 ) ), Denom ), 16 - 1 ); - TEMP = L_mac0( TEMP, extract_l( L_and( 0x7FFF, Quotient ) ), Denom ); -} -} -*Int_quotient = Quotient; -move32(); -IF( L_msu0( L_sub( Numer, TEMP ), 1, Denom ) == 0 ) -{ - *Int_mod = 0L; - move32(); -} -ELSE -{ - *Int_mod = L_sub( Numer, TEMP ); - move32(); -} -} - -/*===================================================================*/ -/* FUNCTION : pz_filter_sp_fx () */ -/*-------------------------------------------------------------------*/ -/* PURPOSE : Generic pole-zero filter routine, with single */ -/* precision memory */ -/*-------------------------------------------------------------------*/ -/* INPUT ARGUMENTS : */ -/* */ -/* _ (Word16 []) b : zero filter coefficients (Qc). */ -/* _ (Word16 []) a : pole filter coefficients (Qc), a(0)=1 in Qc */ -/* _ (Word16 []) x : input signal (Qn). */ -/* _ (Word16) PNR : NR filter order */ -/* _ (Word16) PDR : DR filter order */ -/* _ (Word16) N : number of input samples. */ -/* _ (Word16) Qa : Q factor compensation (Qa=16-Qc) */ -/*-------------------------------------------------------------------*/ -/* OUTPUT ARGUMENTS : */ -/* */ -/* _ (Word16 []) y : output signal (Qn) */ -/*-------------------------------------------------------------------*/ -/* INPUT/OUTPUT ARGUMENTS : */ -/* */ -/* _ (Word16 []) buf : filter memory (Qn-Qa). */ -/*-------------------------------------------------------------------*/ -/* RETURN ARGUMENTS : _ None. */ -/*===================================================================*/ - -void pz_filter_sp_fx( - const Word16 b[], - const Word16 a[], - Word16 x[], - Word16 y[], - Word16 buf[], - Word16 PNR, - Word16 PDR, - Word16 N, - Word16 Qa ) -{ - Word16 i, j; - Word16 s; - Word16 s_mem; - Word32 Ltemp1; - Word32 Lacc; - s = negate( Qa ); - s = add( s, s ); /* s=-2Qa*/ - s = add( s, 1 ); - FOR( i = 0; i < N; i++ ) - { - Lacc = L_deposit_h( x[i] ); /* Lacc in Q(16+Qn)*/ - Lacc = L_shl( Lacc, s ); /* Lacc=x[i] in Q(16+Qn-2Qa+1)*/ - FOR( j = PDR - 1; j >= 0; j-- ) - Lacc = L_msu_sat( Lacc, buf[j], a[j + 1] ); /*Q(16+Qn-2Qa+1)*/ - - - Lacc = L_shr( Lacc, 1 ); - Ltemp1 = L_add_sat( L_shl_sat( Lacc, Qa ), 0x08000 ); - s_mem = extract_h( Ltemp1 ); - - Lacc = L_deposit_l( 0 ); - FOR( j = PNR - 1; j >= 0; j-- ) - Lacc = L_mac_sat( Lacc, buf[j], b[j + 1] ); - Lacc = L_mac_sat( Lacc, s_mem, b[0] ); - /* Lacc in Q(1+Qc+Qn-Qa)*/ - - FOR( j = s_max( PDR, PNR ) - 1; j > 0; j-- ) - { - /* Update filter memory */ - buf[j] = buf[j - 1]; - move16(); - } - buf[0] = s_mem; - move16(); - - Ltemp1 = L_add_sat( L_shr_sat( Lacc, s ), 0x08000 ); /* Ltemp1 in Qc+Qa+Qn=Q(Qn) */ - y[i] = extract_h( Ltemp1 ); /* y[i] in Qn */ - move16(); - } -} - - -Word32 root_a_fx( - Word32 a, - Word16 Q_a, - Word16 *exp_out ) -{ - Word16 exp, tmp; - Word32 L_tmp; - - IF( a <= 0 ) - { - *exp_out = 0; - move16(); - return 0; - } - - exp = norm_l( a ); - tmp = extract_h( L_shl( a, exp ) ); - exp = sub( exp, sub( 30, Q_a ) ); - tmp = div_s( 16384, tmp ); - L_tmp = L_deposit_h( tmp ); - L_tmp = Isqrt_lc( L_tmp, &exp ); - - *exp_out = exp; - move16(); - - return L_tmp; -} - - -Word32 root_a_over_b_fx( - Word32 a, /* Q(Q_a) */ - Word16 Q_a, - Word32 b, /* Q(Q_b) */ - Word16 Q_b, - Word16 *exp_out ) -{ - Word16 tmp, num, den, scale; - Word16 exp, exp_num, exp_den; - Word32 L_tmp; -#ifndef ISSUE_1836_replace_overflow_libcom -#ifdef BASOP_NOGLOB_DECLARE_LOCAL - Flag Overflow = 0; - move32(); -#endif -#endif - test(); - IF( ( a <= 0 ) || ( b <= 0 ) ) - { - *exp_out = 0; - move16(); - return 0; - } - - exp_num = norm_l( b ); -#ifdef ISSUE_1836_replace_overflow_libcom - num = round_fx_sat( L_shl_sat( b, exp_num ) ); -#else - num = round_fx_o( L_shl_o( b, exp_num, &Overflow ), &Overflow ); -#endif - exp_num = sub( sub( 30, exp_num ), Q_b ); - - exp_den = norm_l( a ); -#ifdef ISSUE_1836_replace_overflow_libcom - den = round_fx_sat( L_shl_sat( a, exp_den ) ); -#else - den = round_fx_o( L_shl_o( a, exp_den, &Overflow ), &Overflow ); -#endif - exp_den = sub( sub( 30, exp_den ), Q_a ); - - scale = shr( sub( den, num ), 15 ); -#ifdef ISSUE_1836_replace_overflow_libcom - num = shl_sat( num, scale ); -#else - num = shl_o( num, scale, &Overflow ); -#endif - exp_num = sub( exp_num, scale ); - - tmp = div_s( num, den ); - exp = sub( exp_num, exp_den ); - - L_tmp = L_deposit_h( tmp ); - L_tmp = Isqrt_lc( L_tmp, &exp ); - - *exp_out = exp; - move16(); - - return L_tmp; -} - -Word32 root_a_over_b_ivas_fx( - Word32 a, /* Q(Q_a) */ - Word16 Q_a, - Word32 b, /* Q(Q_b) */ - Word16 Q_b, - Word16 *q_out ) -{ - Word16 shift_a, shift_b, shift; - Word32 mod_a, mod_b, one_in_Q_a, one_in_Q_b, half_in_Q_a, half_in_Q_b; - Word32 a_sqr, b_sqr, p0, p1, p2, approx; - Word16 exp; - - test(); - IF( ( a <= 0 ) || ( b <= 0 ) ) - { - *q_out = 0; - move16(); - return 0; - } - - one_in_Q_a = L_shl( 1, Q_a ); // 1.0f in Q_a - one_in_Q_b = L_shl( 1, Q_b ); // 1.0f in Q_b - half_in_Q_a = L_shr( one_in_Q_a, 1 ); // 0.5f in Q_a - half_in_Q_b = L_shr( one_in_Q_b, 1 ); // 0.5f in Q_b - - a = L_add( a, one_in_Q_a ); - b = L_add( b, one_in_Q_b ); - - /* This next piece of code implements a "norm" function */ - /* and returns the shift needed to scale "a" to have a */ - /* 1 in the (MSB-1) position. This is equivalent to */ - /* giving a value between 0.5 & 1.0. */ - - mod_a = a; - move32(); - - shift_a = 0; - move16(); - WHILE( GT_32( mod_a, one_in_Q_a ) ) - { - mod_a = L_shr( mod_a, 1 ); - shift_a = sub( shift_a, 1 ); - } - - WHILE( LT_32( mod_a, half_in_Q_a ) ) - { - mod_a = L_shl( mod_a, 1 ); - shift_a = add( shift_a, 1 ); - } - - shift_a = s_and( shift_a, -2 ); - mod_a = L_shl( a, shift_a ); // Q_a - - /* This next piece of code implements a "norm" function */ - /* and returns the shift needed to scale "b" to have a */ - /* 1 in the (MSB-1) position. This is equivalent to */ - /* giving a value between 0.5 & 1.0. */ - mod_b = b; - move32(); - - shift_b = 0; - move16(); - WHILE( GT_32( mod_b, one_in_Q_b ) ) - { - mod_b = L_shr( mod_b, 1 ); - shift_b = sub( shift_b, 1 ); - } - - WHILE( LT_32( mod_b, half_in_Q_b ) ) - { - mod_b = L_shl( mod_b, 1 ); - shift_b = add( shift_b, 1 ); - } - - shift_b = s_and( shift_b, -2 ); - mod_b = L_shl( b, shift_b ); // Q_b - - shift = shr( sub( shift_b, shift_a ), 1 ); - - a_sqr = W_extract_h( W_shl( W_mult0_32_32( mod_a, mod_a ), sub( 32, Q_a ) ) ); // Q_a - b_sqr = W_extract_h( W_shl( W_mult0_32_32( mod_b, mod_b ), sub( 32, Q_b ) ) ); // Q_b - - p2 = L_shl( -408505077 /* -0.7609f in Q29 */, sub( Q_b, 31 ) ); // Qb-2 - p1 = L_shl( 1444612250 /* 2.6908f in Q29 */, sub( Q_b, 31 ) ); // Qb-2 - p0 = L_shl( 385258566 /* 0.7176f in Q29 */, sub( Q_b, 31 ) ); // Qb-2 - - p2 = Madd_32_32( Madd_32_32( p2, 501759554 /* 0.9346f in Q29*/, mod_b ), -252060893 /* -0.4695f in Q29 */, b_sqr ); // Q_b-2 - p1 = Madd_32_32( Madd_32_32( p1, -1774680487 /* -3.3056f in Q29 */, mod_b ), 891635211 /* 1.6608f in Q29 */, b_sqr ); // Q_b-2 - p0 = Madd_32_32( Madd_32_32( p0, -473251709 /* -0.8815f in Q29 */, mod_b ), 237780127 /* 0.4429f in Q29 */, b_sqr ); // Q_b-2 - - /* approx = p0 + p1 * mod_a + p2 * mod_a * mod_a; */ - approx = Madd_32_32( Mpy_32_32( p1, mod_a ), p2, a_sqr ); // Q_a+Q_b-33 - approx = L_add( approx, L_shl( p0, sub( Q_a, 31 ) ) ); // Q_a+Q_b-33 - - exp = sub( norm_l( approx ), 1 ); - approx = L_shl( approx, exp ); // // Q_a+Q_b-33+exp - - *q_out = sub( add( sub( add( Q_a, Q_b ), 33 ), exp ), shift ); - move16(); - - return approx; -} - -/*===================================================================*/ -/* FUNCTION : fir_fx () */ -/*-------------------------------------------------------------------*/ -/* PURPOSE : Generic FIR filter routine */ -/*-------------------------------------------------------------------*/ -/* INPUT ARGUMENTS : */ -/* */ -/* _ (Word16 []) b : filter coefficients (Qc). */ -/* _ (Word16 []) x : input signal (Qn). */ -/* _ (Word16) P : filter order. */ -/* _ (Word16) N : number of input samples. */ -/* _ (Word16) Qa : Q factor compensation (Qa=16-Qc) */ -/*-------------------------------------------------------------------*/ -/* OUTPUT ARGUMENTS : */ -/* */ -/* _ (Word16 []) y : output signal (Qn) */ -/*-------------------------------------------------------------------*/ -/* INPUT/OUTPUT ARGUMENTS : */ -/* */ -/* _ : None */ -/*-------------------------------------------------------------------*/ -/* RETURN ARGUMENTS : _ None. */ -/*===================================================================*/ -void fir_fx( const Word16 x[], /* i : input vector Qx*/ - const Word16 h[], /* i : impulse response of the FIR filter Q12*/ - Word16 y[], /* o : output vector (result of filtering) Qx*/ - Word16 mem[], /* i/o: memory of the input signal (L samples) Qx*/ - const Word16 L, /* i : input vector size */ - const Word16 K, /* i : order of the FIR filter (K+1 coefs.) */ - const Word16 upd /* i : 1 = update the memory, 0 = not */ - , - Word16 shift /* i : difference between Q15 and scaling of h[] */ -) -{ - - Word16 buf_in[L_FRAME32k + L_FILT_MAX]; - Word16 i, j; - Word32 s; -#ifndef ISSUE_1836_replace_overflow_libcom -#ifdef BASOP_NOGLOB_DECLARE_LOCAL - Flag Overflow = 0; - move32(); -#endif -#endif - /* prepare the input buffer (copy and update memory) */ - Copy( mem, buf_in, K ); - Copy( x, buf_in + K, L ); - IF( upd ) - { - Copy( buf_in + L, mem, K ); - } - - /* do the filtering */ - FOR( i = 0; i < L; i++ ) - { -#ifdef ISSUE_1836_replace_overflow_libcom - s = L_mult_sat( buf_in[K + i], h[0] ); -#else - s = L_mult_o( buf_in[K + i], h[0], &Overflow ); -#endif - - FOR( j = 1; j <= K; j++ ) - { -#ifdef ISSUE_1836_replace_overflow_libcom - s = L_mac_sat( s, h[j], buf_in[K + i - j] ); -#else - s = L_mac_o( s, h[j], buf_in[K + i - j], &Overflow ); -#endif - } -#ifdef ISSUE_1836_replace_overflow_libcom - s = L_shl_sat( s, shift ); - y[i] = round_fx_sat( s ); /*Qx */ -#else - s = L_shl_o( s, shift, &Overflow ); - y[i] = round_fx_o( s, &Overflow ); /*Qx */ -#endif - move16(); - } -} - -/*-------------------------------------------------------------------* - * v_add_32() - * - * Addition of two vectors sample by sample - *-------------------------------------------------------------------*/ - -void v_add_32( - const Word32 x1[], /* i : Input vector 1 */ - const Word32 x2[], /* i : Input vector 2 */ - Word32 y[], /* o : Output vector that contains vector 1 + vector 2 */ - const Word16 N /* i : Vector length */ -) -{ - Word16 i; - - FOR( i = 0; i < N; i++ ) - { - y[i] = L_add( x1[i], x2[i] ); - move32(); - } - - return; -} - -void v_shr_32( - Word32 x1[], /* i : Input vector 1 */ - Word32 y[], /* o : Output vector that contains vector 1 + vector 2 */ - const Word16 N, /* i : Vector length */ - Word16 shift /*shift value*/ -) -{ - Word16 i; - - FOR( i = 0; i < N; i++ ) - { - y[i] = L_shr( x1[i], shift ); - move32(); - } - - return; -} - - -/*-------------------------------------------------------------------* - * v_sub_32() - * - * Subtraction of two vectors sample by sample - *-------------------------------------------------------------------*/ - -void v_sub_32( - const Word32 x1[], /* i : Input vector 1 */ - const Word32 x2[], /* i : Input vector 2 */ - Word32 y[], /* o : Output vector that contains vector 1 - vector 2 */ - const Word16 N /* i : Vector length */ -) -{ - Word16 i; - - FOR( i = 0; i < N; i++ ) - { - y[i] = L_sub( x1[i], x2[i] ); - move32(); - } - - return; -} - - -/*-------------------------------------------------------------------* - * v_add_16() - * - * Addition of two vectors sample by sample - *-------------------------------------------------------------------*/ - -void v_add_16( - const Word16 x1[], /* i : Input vector 1 */ - const Word16 x2[], /* i : Input vector 2 */ - Word16 y[], /* o : Output vector that contains vector 1 + vector 2 */ - const Word16 N /* i : Vector length */ -) -{ - Word16 i; - - FOR( i = 0; i < N; i++ ) - { - y[i] = add_sat( x1[i], x2[i] ); - move16(); - } - - return; -} - - -/*-------------------------------------------------------------------* - * v_sub_16() - * - * Subtraction of two vectors sample by sample - *-------------------------------------------------------------------*/ - -void v_sub_16( - const Word16 x1[], /* i : Input vector 1 */ - const Word16 x2[], /* i : Input vector 2 */ - Word16 y[], /* o : Output vector that contains vector 1 - vector 2 */ - const Word16 N /* i : Vector length */ -) -{ - Word16 i; - - FOR( i = 0; i < N; i++ ) - { - y[i] = sub_sat( x1[i], x2[i] ); - move16(); - } - - return; -} - - -/*--------------------------------------------------------------------------------*/ -/* squant_fx() */ -/*--------------------------------------------------------------------------------*/ -Word16 squant_fx( /* o: index of the winning codeword */ - const Word16 x, /* i: scalar value to quantize */ - Word16 *xq, /* o: quantized value */ - const Word16 cb[], /* i: codebook */ - const Word16 cbsize /* i: codebook size */ -) -{ - Word16 tmp; - Word16 c, idx; - Word32 L_mindist, L_dist; -#ifndef ISSUE_1836_replace_overflow_libcom -#ifdef BASOP_NOGLOB_DECLARE_LOCAL - Flag Overflow = 0; -#endif -#endif - - idx = 0; - move16(); - L_mindist = MAX_32; - move32(); - - FOR( c = 0; c < cbsize; c++ ) - { - L_dist = L_deposit_l( 0 ); -#ifdef ISSUE_1836_replace_overflow_libcom - tmp = sub_sat( x, cb[c] ); -#else - tmp = sub_o( x, cb[c], &Overflow ); -#endif - - /*dist += tmp*tmp; */ -#ifdef ISSUE_1836_replace_overflow_libcom - L_dist = L_mac_sat( L_dist, tmp, tmp ); -#else - L_dist = L_mac_o( L_dist, tmp, tmp, &Overflow ); -#endif - - if ( LT_32( L_dist, L_mindist ) ) - { - idx = c; - move16(); - } - L_mindist = L_min( L_mindist, L_dist ); - } - - *xq = cb[idx]; - move16(); - - return idx; -} - -/*! r: index of the winning codeword */ -Word16 squant_int_fx( - UWord8 x, /* i : scalar value to quantize */ - UWord8 *xq, /* o : quantized value */ - const UWord8 *cb, /* i : codebook */ - const Word16 cbsize /* i : codebook size */ -) -{ - Word16 i, idx; - Word32 mindist, d; - - idx = 0; - move16(); - mindist = 10000000; // Q0 - move32(); - FOR( i = 0; i < cbsize; i++ ) - { - d = L_mult0( sub( x, cb[i] ), sub( x, cb[i] ) ); - IF( LT_32( d, mindist ) ) - { - mindist = d; - move32(); - idx = i; - move16(); - } - } - *xq = cb[idx]; - move16(); - - return idx; -} - -/*===================================================================*/ -/* FUNCTION : pz_filter_dp_fx () */ -/*-------------------------------------------------------------------*/ -/* PURPOSE : Generic pole-zero filter routine, with double */ -/* precision memory, transposed direct form II */ -/*-------------------------------------------------------------------*/ -/* INPUT ARGUMENTS : */ -/* */ -/* _ (Word16 []) b : zero filter coefficients (Qc). */ -/* _ (Word16 []) a : pole filter coefficients (Qc), a(0)=1 */ -/* _ (Word16 []) x : input signal (Qx). */ -/* _ (Word16) P : filter order. */ -/* _ (Word16) N : number of input samples. */ -/* _ (Word16) Qa : Q factor compensation (Qa=16-Qc) */ -/*-------------------------------------------------------------------*/ -/* OUTPUT ARGUMENTS : */ -/* */ -/* _ (Word16 []) y : output signal (Qx) */ -/*-------------------------------------------------------------------*/ -/* INPUT/OUTPUT ARGUMENTS : */ -/* */ -/* _ (Word32 []) buf : filter memory (Qx+Qc) */ -/*-------------------------------------------------------------------*/ -/* RETURN ARGUMENTS : _ None. */ -/*===================================================================*/ - -void pz_filter_dp_fx( - const Word16 b[], - const Word16 a[], - Word16 x[], - Word16 y[], - Word32 buf[], - Word16 PNR, - Word16 PDR, - Word16 N, - Word16 Qa ) -{ - Word16 i, j; - Word16 s; - Word32 s_mem; - Word32 Ltemp1; - Word32 Lacc; - - s = negate( Qa ); - s = add( s, s ); /* s=-2Qa */ - s = add( s, 1 ); - FOR( i = 0; i < N; i++ ) - { - Lacc = L_deposit_h( x[i] ); /* Lacc in Q(16+Qn)*/ - Lacc = L_shl( Lacc, s ); /* Lacc=x[i] in Q(16+Qn-2Qa+1)*/ - FOR( j = PDR - 1; j >= 0; j-- ) - Lacc = Msub_32_16( Lacc, buf[j], a[j + 1] ); /*Q(16+Qn-2Qa+1)*/ - - s_mem = L_shl_sat( Lacc, sub( Qa, 1 ) ); /*Qn-Qa+16=Qn+Qc*/ - Lacc = L_deposit_l( 0 ); - FOR( j = PNR - 1; j >= 0; j-- ) - Lacc = Madd_32_16( Lacc, buf[j], b[j + 1] ); - Lacc = Madd_32_16( Lacc, s_mem, b[0] ); - /* Lacc in Q(1+Qc+Qn-Qa) */ - - FOR( j = s_max( PDR, PNR ) - 1; j > 0; j-- ) - { - /* Update filter memory */ - buf[j] = buf[j - 1]; - move16(); - } - buf[0] = s_mem; - move16(); - - Ltemp1 = L_shr_sat( Lacc, s ); /* Ltemp1 in Qc+Qa+Qn=Q(16+Qn) */ - y[i] = extract_h( Ltemp1 ); /* y[i] in Qn */ - move16(); - } -} - -/*-------------------------------------------------------------------* - * Copy_Scale_sig - * - * Up/down scale a 16 bits vector x and move it into y - *-------------------------------------------------------------------*/ -void Copy_Scale_sig32( - const Word32 x[], /* i : signal to scale input Qx */ - Word32 y[], /* o : scaled signal output Qx */ - const Word16 lg, /* i : size of x[] Q0 */ - const Word16 exp0 /* i : exponent: x = round(x << exp) Qx ?exp */ -) -{ - Word16 i; - Word32 L_tmp; - Word16 tmp = exp0; -#ifndef ISSUE_1836_replace_overflow_libcom -#ifdef BASOP_NOGLOB_DECLARE_LOCAL - Flag Overflow = 0; - move32(); -#endif -#endif - IF( exp0 == 0 ) - { - FOR( i = 0; i < lg; i++ ) - { - y[i] = x[i]; - move32(); - } - return; - } - IF( exp0 < 0 ) - { - FOR( i = 0; i < lg; i++ ) - { -#ifdef ISSUE_1836_replace_overflow_libcom - y[i] = L_shl_sat( x[i], tmp ); -#else - y[i] = L_shl_o( x[i], tmp, &Overflow ); -#endif - move16(); - } - return; - } -#ifdef ISSUE_1836_replace_overflow_libcom - L_tmp = L_shl_sat( 1, exp0 - 1 ); -#else - L_tmp = L_shl_o( 1, exp0 - 1, &Overflow ); -#endif - FOR( i = 0; i < lg; i++ ) - { - y[i] = W_extract_l( W_mult_32_32( L_tmp, x[i] ) ); - move32(); /* saturation can occur here */ - } -} - - -/*-------------------------------------------------------------------* - * Copy_Scale_sig32_16 - * - * Up/down scale a 32 bits vector and round to 16 bits vector - *-------------------------------------------------------------------*/ -void Copy_Scale_sig32_16( - const Word32 *src, /* i : signal to scale Qx */ - Word16 *dst, /* o : scaled signal Qx */ - Word16 len, /* i : size of x[] Q0 */ - Word16 exp0 ) /* i : exponent: x = round(x << exp) Qx ?exp */ -{ - Word16 i; - Word32 L_temp; - - IF( exp0 == 0 ) - { - FOR( i = 0; i < len; i++ ) - { - *dst++ = round_fx_sat( *src++ ); - move16(); - } - return; - } - - FOR( i = 0; i < len; i++ ) - { - L_temp = L_shl_sat( *src++, exp0 ); - - *dst++ = round_fx_sat( L_temp ); - move16(); - } -} - -/*-------------------------------------------------------------------* - * v_multc_att() - * - * Attenuation of a vector,, attenuation factor in Q15 - *-------------------------------------------------------------------*/ - -void v_multc_att( - const Word16 x[], /* i : Input vector Qx */ - const Word16 att, /* i : Constant Q15, <= MAX_16 */ - Word16 y[], /* o : Output vector that contains att*x */ - const Word16 N /* i : Vector length */ -) -{ - Word16 i; - IF( LT_16( att, 32767 ) ) - { - FOR( i = 0; i < N; i++ ) - { - y[i] = mult_r( x[i], att ); - move16(); - } - } -} /*-------------------------------------------------------------------* - * v_multc_att32() - * - * Attenuation of a vector,, attenuation factor in Q15 - *-------------------------------------------------------------------*/ - -void v_multc_att32( - const Word32 x[], /* i : Input vector Qx */ - const Word16 att, /* i : Constant Q15, <= MAX_16 */ - Word32 y[], /* o : Output vector that contains att*x */ - const Word16 N /* i : Vector length */ -) -{ - Word16 i; - IF( LT_16( att, 32767 ) ) - { - FOR( i = 0; i < N; i++ ) - { - y[i] = Mpy_32_16_r( x[i], att ); - move32(); - } - } -} - -/*-------------------------------------------------------------------* - * v_multc_att3232() - * - * Attenuation of a vector, attenuation factor in Q31 - *-------------------------------------------------------------------*/ - -void v_multc_att3232( - const Word32 x[], /* i : Input vector Qx */ - const Word32 att, /* i : Constant Q32, <= MAX_32 */ - Word32 y[], /* o : Output vector that contains att*x */ - const Word16 N /* i : Vector length */ -) -{ - Word16 i; - IF( LE_32( att, MAX_32 ) ) - { - FOR( i = 0; i < N; i++ ) - { - y[i] = Mpy_32_32_r( x[i], att ); - move32(); - } - } -} - -/*-------------------------------------------------------------------* - * v_L_mult_1616() - * - * Multiplication of two vectors, Output in Word32 - *-------------------------------------------------------------------*/ - -void v_L_mult_1616( - const Word16 x1[], /* i : Input vector 1 */ - const Word16 x2[], /* i : Input vector 2 */ - Word32 y[], /* o : Output vector that contains vector 1 .* vector 2 */ - const Word16 N /* i : Vector length */ -) -{ - Word16 i; - - for ( i = 0; i < N; i++ ) - { - y[i] = L_mult( x1[i], x2[i] ); - move32(); - } - - return; -} - -/*-------------------------------------------------------------------* - * v_L_mult_3216() - * - * Multiplication of two vectors, Output in Word32 - *-------------------------------------------------------------------*/ - -void v_L_mult_3216( - const Word32 x1[], /* i : Input vector 1 */ - const Word16 x2[], /* i : Input vector 2 */ - Word32 y[], /* o : Output vector that contains vector 1 .* vector 2 */ - const Word16 N /* i : Vector length */ -) -{ - Word16 i; - - for ( i = 0; i < N; i++ ) - { - y[i] = Mpy_32_16_1( x1[i], x2[i] ); - move32(); - } - - return; -} - -/*-------------------------------------------------------------------* - * add_vec() - * - * Addition of two vectors sample by sample - *-------------------------------------------------------------------*/ - -void add_vec_fx( - const Word16 x1[], /* i : Input vector 1 */ - const Word16 Qx1, /* i : SCaling of input 1 */ - const Word16 x2[], /* i : Input vector 2 */ - const Word16 Qx2, /* i : SCaling of input 1 */ - Word16 y[], /* o : Output vector that contains vector 1 + vector 2 */ - const Word16 Qy, /* i : SCaling of output 1 */ - const Word16 N /* i : Vector lenght */ -) -{ - Word16 i, Qyx1, Qyx2; -#ifndef ISSUE_1836_replace_overflow_libcom -#ifdef BASOP_NOGLOB_DECLARE_LOCAL - Flag Overflow = 0; - move32(); -#endif -#endif - Qyx1 = sub( Qx1, Qy ); - Qyx2 = sub( Qx2, Qy ); - IF( Qyx1 == 0 ) - { - FOR( i = 0; i < N; i++ ) - { -#ifdef ISSUE_1836_replace_overflow_libcom - y[i] = add_sat( x1[i], shr_r_sat( x2[i], Qyx2 ) ); -#else - y[i] = add_o( x1[i], shr_r_sat( x2[i], Qyx2 ), &Overflow ); -#endif - move16(); - } - } - ELSE - { - FOR( i = 0; i < N; i++ ) - { -#ifdef ISSUE_1836_replace_overflow_libcom - y[i] = add_sat( shr_r_sat( x1[i], Qyx1 ), shr_r_sat( x2[i], Qyx2 ) ); //!!sat //!!sat -#else - y[i] = add_o( shr_r_sat( x1[i], Qyx1 ), shr_r_sat( x2[i], Qyx2 ), &Overflow ); -#endif - move16(); - } - } - return; -} - -/*-------------------------------------------------------------------* - * Add_flt32_flt32 - * - * Add two Pseudo Float Value that are 32 Bits Mantisa and 16 Bits Exp - *-------------------------------------------------------------------*/ -Word32 Add_flt32_flt32( /* o: Result (Normalized) */ - Word32 a, /* i: 1st Value */ - Word16 exp_a, /* i: Exponent of 1st Value (Q of Value) */ - Word32 b, /* i: 2nd Value */ - Word16 exp_b, /* i: Exponent of 2nd Value (Q of Value) */ - Word16 *exp_out /* o: Exponent of Result */ -) -{ - Word16 temp, temp2; - Word32 L_temp; - - /* Subract 1 to further divide by 2 to avoid overflow on L_add */ - temp = sub( s_min( exp_a, exp_b ), 1 ); - - /* Put both to same exponent */ - exp_a = sub( exp_a, temp ); - a = L_shr( a, exp_a ); - exp_b = sub( exp_b, temp ); - b = L_shr( b, exp_b ); - - /* add them together */ - L_temp = L_add( a, b ); - temp2 = norm_l( L_temp ); - - *exp_out = add( temp, temp2 ); - move16(); - - return L_shl( L_temp, temp2 ); -} - -/*-------------------------------------------------------------------* - * Mul_flt32_Q15 - * - * Multiply one Pseudo Float Value (32 Bits Mantisa and 16 Bits Exp) - * with a Q15 value - *-------------------------------------------------------------------*/ -Word32 Mul_flt32_Q15( /* o: Result (Normalized) */ - Word32 value, /* i: Pseudo_float Value */ - Word16 *exp_v, /*i/o: Exponent of Value (Q of Value) */ - Word16 frac /* i: Q15 value */ -) -{ - Word16 temp; - Word32 L_temp; - - L_temp = Mult_32_16( value, frac ); - temp = norm_l( L_temp ); - - *exp_v = add( temp, *exp_v ); - move16(); - - return L_shl( L_temp, temp ); -} - -/*-------------------------------------------------------------------* - * Div_flt32_flt32 - * - * Divide one Pseudo Float Value (32 Bits Mantisa and 16 Bits Exp) - * by another one - *-------------------------------------------------------------------*/ -Word32 Div_flt32_flt32( /* o: Result (Normalized) */ - Word32 a, /* i: 1st Value */ - Word16 exp_a, /* i: Exponent of 1st Value (Q of Value) */ - Word32 b, /* i: 2nd Value */ - Word16 exp_b, /* i: Exponent of 2nd Value (Q of Value) */ - Word16 *exp_out /* o: Exponent of Result */ -) -{ - Word16 temp, temp2; - Word32 L_temp; - - temp = div_s( 16384, round_fx( b ) ); - L_temp = Mult_32_16( a, temp ); - temp2 = sub( 31 - 1, exp_b ); - temp2 = add( temp2, exp_a ); - - temp = norm_l( L_temp ); - - *exp_out = add( temp, temp2 ); - move16(); - - return L_shl( L_temp, temp ); -} - - -/*-------------------------------------------------------------------* - * Calc_Energy_Autoscaled - * - * Calculate Energy with overflow protection - *-------------------------------------------------------------------*/ -Word32 Calc_Energy_Autoscaled( /* o: Result (Energy) */ - const Word16 *signal, /* i: Signal */ - Word16 signal_exp, /* i: Exponent of Signal (Q of Signal) */ - Word16 len, /* i: Frame Length */ - Word16 *energy_exp /* o: Exponent of Energy (Q of Energy) */ -) -{ - Word16 temp, temp2; - Word32 L_temp, L_Energy; - Word16 i, j; -#ifdef BASOP_NOGLOB_DECLARE_LOCAL - Flag Overflow = 0; - move32(); -#endif - - Overflow = 0; - move16(); - - temp2 = 0; - move16(); - L_Energy = L_deposit_l( 1 ); - j = s_and( 7, len ); - FOR( i = 0; i < j; i++ ) - { - /* divide by 2 so energy will be divided by 4 */ -#ifdef ISSUE_1836_replace_overflow_libcom - temp = mult_r( *signal++, 16384 ); -#else - temp = mult_ro( *signal++, 16384, &Overflow ); -#endif - L_Energy = L_mac0_o( L_Energy, temp, temp, &Overflow ); - } - FOR( i = j; i < len; i += 8 ) /* Process 8 Samples at a time */ - { - /* divide by 2 so energy will be divided by 4 */ - temp = mult_ro( *signal++, 16384, &Overflow ); - L_temp = L_mult0( temp, temp ); - FOR( j = 1; j < 8; j++ ) - { -#ifdef ISSUE_1836_replace_overflow_libcom - temp = mult_r( *signal++, 16384 ); -#else - temp = mult_ro( *signal++, 16384, &Overflow ); -#endif - L_temp = L_mac0_o( L_temp, temp, temp, &Overflow ); - } - /*Overfloe will never happen because temp2 is always positive*/ - L_temp = L_shr( L_temp, temp2 ); - /* Here we try the addition just to check if we can sum - the energy of the small (8 Iterations) loop with the - total energy calculated so far without an overflow. - The result is discarded. If there is an overflow both - energies are div by 2. Otherwise, nothing is done. - After the 'IF', the sum is done again and will always - be without an overflow. */ - L_add_o( L_Energy, L_temp, &Overflow ); - IF( Overflow != 0 ) - { - L_Energy = L_shr( L_Energy, 1 ); - L_temp = L_shr( L_temp, 1 ); - temp2 = add( temp2, 1 ); - Overflow = 0; - move16(); - } - L_Energy = L_add_o( L_Energy, L_temp, &Overflow ); - } - /* Calc Final Exponent (sub 2 because of the mult_r by 16384 that already divs the ener by 4) */ - temp2 = sub( sub( shl( signal_exp, 1 ), temp2 ), 2 ); - - *energy_exp = temp2; - move16(); - - return L_Energy; -} - -Word16 Find_Max_Norm16( const Word16 *src, Word16 len ) -{ - Word16 i; - Word16 max16; - - /* it starts at '0' and not '1' like in Find_Max_Norm32() */ - /* and that is necessary. */ - max16 = 0; - move16(); - - FOR( i = 0; i < len; i++ ) - { - max16 = s_max( max16, abs_s( *src++ ) ); - } - - return norm_s( max16 ); -} - -Word16 Find_Max_Norm32( const Word32 *src, Word16 len ) -{ - Word16 i; - Word32 max32; - - max32 = L_deposit_l( 1 ); - - FOR( i = 0; i < len; i++ ) - { - max32 = L_max( max32, L_abs( *src++ ) ); - } - - return norm_l( max32 ); -} - -/*-------------------------------------------------------------------* - * Sqrt_Ratio32 - * - * Calculate Sqrt of Val1/Val2 - *-------------------------------------------------------------------*/ -Word32 Sqrt_Ratio32( /* o: Result in Q31 */ - Word32 L_val1, /* i: Mantisa of Val1 */ - Word16 exp1, /* i: Exp of Val1 (>0: Val was Left Shifted, <0:Right Shifted) */ - Word32 L_val2, /* i: Mantisa of Val2 */ - Word16 exp2, /* i: Exp of Val2 (same as exp1) */ - Word16 *exp /* o: Exp of Result (# of 'L_shl' Req to get to Final Value) */ -) -{ - Word16 temp; - - /* Normalize Energy #1 */ - temp = norm_l( L_val1 ); - L_val1 = L_shl( L_val1, temp ); - /* Adjust Exponent of Energy #1 */ - exp1 = add( exp1, temp ); - - /* Normalize Energy #2 */ - temp = norm_l( L_val2 ); - L_val2 = L_shl( L_val2, temp ); - /* Adjust Exponent of Energy #1 */ - exp2 = add( exp2, temp ); - - /* Prepare for Inverse */ - temp = round_fx_sat( L_val1 ); - temp = div_s( 16384, temp ); - /* Mult Now */ - L_val2 = Mult_32_16( L_val2, temp ); - exp1 = add( sub( exp2, exp1 ), 15 * 2 ); - - /* Here Result of ('L_val2' / 2^'exp2') / ('L_val1' / 2^'exp1') is */ - /* 'L_val2' / 2^'exp1' */ - /* Which is val2/val1 instead of val1/val2 because we will use Inverted Square Root */ - /* Normalize before Square Root */ - temp = norm_l( L_val2 ); - L_val2 = L_shl( L_val2, temp ); - exp1 = add( temp, exp1 ); - /* Do Sqrt */ - temp = sub( 31, exp1 ); - L_val1 = Isqrt_lc( L_val2, &temp ); - - *exp = temp; - move16(); - - return L_val1; -} - -Word16 Invert16( /* result in Q'15 + 'exp' */ - Word16 val, - Word16 *exp ) -{ - Word16 temp; - - /* prevent 0 input */ - val = s_max( val, 1 ); - /* Normalize Value */ - temp = norm_s( val ); - val = shl( val, temp ); - - *exp = sub( sub( 15 - 1, *exp ), temp ); - move16(); /* -1 because of 0x4000 is 1.0 in Q14 (and not Q15) */ - - temp = div_s( 0x4000, val ); - - return temp; -} - -Word16 find_rem( Word16 n, Word16 m, Word16 *r ) -{ - Word16 i, q1, q2, qd; - Word32 Ltemp2; - Word32 Lacc; - - test(); - test(); - IF( n <= 0 || m <= 0 || n < m ) - { - *r = n; - move16(); - return ( 0 ); - } - - q1 = norm_s( n ); - q1 = sub( q1, 1 ); - Lacc = L_deposit_h( shl( n, q1 ) ); - qd = sub( q1, 1 ); - q2 = norm_s( m ); - q2 = sub( q2, 1 ); - Ltemp2 = L_deposit_h( shl( m, q2 ) ); - qd = sub( q2, qd ); - q2 = add( q2, 1 ); - - FOR( i = 0; i < qd; i++ ) - { - Lacc = L_sub( Lacc, Ltemp2 ); - IF( Lacc >= 0 ) - { - Lacc = L_add( L_shl( Lacc, 1 ), 1 ); - } - ELSE - { - Lacc = L_add( Lacc, Ltemp2 ); - Lacc = L_shl( Lacc, 1 ); - } - } - q1 = extract_l( Lacc ); - Ltemp2 = L_shr( Lacc, q2 ); - *r = extract_h( Ltemp2 ); - move16(); - return ( q1 ); -} - - -Word32 find_remd( Word32 n, Word32 m, Word32 *r ) -{ - Word16 i, q1, q2, qd; - Word32 Ltemp2, qo; - Word32 Lacc; - - test(); - test(); - IF( n <= 0 || m <= 0 || n < m ) - { - *r = n; - move16(); - return ( 0 ); - } - - q1 = norm_l( n ); - q1 = sub( q1, 1 ); - Lacc = L_shl( n, q1 ); - qd = sub( q1, 1 ); - q2 = norm_l( m ); - q2 = sub( q2, 1 ); - Ltemp2 = L_shl( m, q2 ); - qd = sub( q2, qd ); - q2 = add( q2, 1 ); - qo = 0; - move16(); - - FOR( i = 0; i < qd; i++ ) - { - Lacc = L_sub( Lacc, Ltemp2 ); - qo = L_shl( qo, 1 ); - IF( Lacc >= 0 ) - { - Lacc = L_shl( Lacc, 1 ); - qo = L_add( qo, 1 ); - } - ELSE - { - Lacc = L_add( Lacc, Ltemp2 ); - Lacc = L_shl( Lacc, 1 ); - } - } - *r = L_shr( Lacc, q2 ); - move16(); - return ( qo ); -} - -Word16 rint_new_fx( - Word32 x /*Q16 */ -) -{ - Word16 a; - Word32 L_tmp; - Word16 frac, tmp; - - /* middle value point test */ - frac = lshr( extract_l( x ), 1 ); /*Q15 */ - tmp = sub( frac, 0x4000 ); - - IF( !tmp ) - { - a = add( extract_h( x ), 1 ); - - IF( s_and( a, 1 ) == 0 ) - { - return a; - } - IF( s_and( a, 1 ) != 0 ) - { - return extract_h( x ); - } - return extract_h( x ); - } - ELSE - { - L_tmp = L_add( x, 32768 ); /*Q16 */ - return extract_h( L_tmp ); - } -} - - -/*===================================================================*/ -/* FUNCTION : erb_diff_search_fx () */ -/*-------------------------------------------------------------------*/ -/* PURPOSE : erb amplitude VQ search for QPPP */ -/*-------------------------------------------------------------------*/ -/* INPUT ARGUMENTS : */ -/* _ (Word16 []) prev_erb : Previous erb amplitude, Q13 */ -/* _ (Word16 []) curr_erb : Current erb amplitude, Q13 */ -/* _ (Word16 []) dif_erb: erb differential, Q13 */ -/* _ (Word16 []) pow_spec : LPC power spectrum, Q7 */ -/* _ (Word16 [][]) cb_fx : differential erb codebook, Q13 */ -/* _ (Word16) cb_size : codebook size */ -/* _ (Word16) cb_dim : codebook dimension */ -/* _ (Word16) offset : index to current segment of erb array */ -/* for quantization */ -/*-------------------------------------------------------------------*/ -/* OUTPUT ARGUMENTS : */ -/* _ None */ -/*-------------------------------------------------------------------*/ -/* INPUT/OUTPUT ARGUMENTS : */ -/* _ None */ -/*-------------------------------------------------------------------*/ -/* RETURN ARGUMENTS : */ -/* _ (Word16) index: best codebook index */ -/*-------------------------------------------------------------------*/ -/* CALLED FROM : TX */ -/*===================================================================*/ - -Word16 erb_diff_search_fx( Word16 *prev_erb, const Word16 *curr_erb, Word16 *dif_erb, Word16 *pow_spec, const Word16 *cb_fx, Word16 cb_size, Word16 cb_dim, Word16 offset ) -{ - Word16 i, j, mmseindex; - Word16 dh, dl; - Word32 mmse; - Word32 Ltemp1; - Word32 Lacc; - - mmse = EVS_LW_MAX; - move32(); - mmseindex = -1; - move16(); - FOR( j = 0; j < cb_size; j++ ) - { - - Lacc = L_deposit_l( 0 ); - FOR( i = 0; i < cb_dim; i++ ) - { - IF( add_sat( cb_fx[j * cb_dim + i], prev_erb[i + offset] ) < 0 ) - { - Ltemp1 = L_mult( curr_erb[i + offset], curr_erb[i + offset] ); /* Q27 */ - dh = extract_h( Ltemp1 ); - dl = extract_l( Ltemp1 ); - IF( dl < 0 ) - { - Ltemp1 = L_shl( L_add( 65536, dl ), 14 ); /* */ - Ltemp1 = Mult_32_16( Ltemp1, pow_spec[i + offset] ); - Ltemp1 = L_shl( Ltemp1, 1 ); - } - ELSE - { - Ltemp1 = (Word32) L_mult0( pow_spec[i + offset], dl ); - } - Ltemp1 = L_add( L_shr( Ltemp1, 15 ), L_mult( pow_spec[i + offset], dh ) ); - } - ELSE - { - dh = sub_sat( dif_erb[i + offset], cb_fx[j * cb_dim + i] ); /* Q13 */ - Ltemp1 = L_mult_sat( dh, dh ); /* Q27 */ - dh = extract_h( Ltemp1 ); - dl = extract_l( Ltemp1 ); - - IF( dl < 0 ) - { - Ltemp1 = L_shl( L_add( 65536, dl ), 14 ); /* */ - Ltemp1 = Mult_32_16( Ltemp1, pow_spec[i + offset] ); - Ltemp1 = L_shl( Ltemp1, 1 ); - } - ELSE - { - Ltemp1 = (Word32) L_mult0( pow_spec[i + offset], dl ); /* Q33 */ - } - - Ltemp1 = L_add( L_shr( Ltemp1, 15 ), L_mult( pow_spec[i + offset], dh ) ); /* Q18 */ - } - - IF( LT_16( cb_fx[j * cb_dim + i], dif_erb[i + offset] ) ) - { - dh = extract_h( Ltemp1 ); - dl = extract_l( Ltemp1 ); - IF( dl < 0 ) - { - Ltemp1 = L_shl( L_add( 65536, dl ), 14 ); /* */ - Ltemp1 = Mult_32_16( Ltemp1, 29491 ); - Ltemp1 = L_shl( Ltemp1, 1 ); - } - ELSE - { - Ltemp1 = (Word32) L_mult0( 29491, dl ); /* 29491=0.9 in Q15 */ - } - Ltemp1 = L_add( L_shr( Ltemp1, 15 ), L_mult( dh, 29491 ) ); - } - Lacc = L_add( Lacc, Ltemp1 ); /* Q18 */ - } - - IF( LT_32( Lacc, mmse ) ) - { - mmse = L_add( Lacc, 0 ); - mmseindex = j; - move16(); - } - } - - return ( mmseindex ); -} -void Acelp_dec_total_exc( - Word16 *exc_fx, /* i/o: adapt. excitation exc */ - Word16 *exc2_fx, /* i/o: adapt. excitation/total exc */ - const Word16 gain_code16, /* i : Gain code Q0 */ - const Word16 gain_pit_fx, /* i ; Pitch gain in Q14 */ - const Word16 i_subfr, /* i ; subfr */ - const Word16 *code_fx, /* i : code in Q9 */ - const Word16 L_subfr /* i : Subframne lenght */ -) -{ - Word16 i; - Word32 L_tmp; - - FOR( i = 0; i < L_subfr; i++ ) - { - L_tmp = L_shl_sat( L_mult( gain_pit_fx, exc_fx[i + i_subfr] ), 1 ); /*Q16+Q_exc*/ - exc2_fx[i + i_subfr] = round_fx_sat( L_tmp ); /*Q_exc*/ - L_tmp = L_add_sat( L_tmp, L_shl_sat( L_mult( gain_code16, code_fx[i] ), 6 ) ); /*Q16+Q_exc*/ - exc_fx[i + i_subfr] = round_fx_sat( L_tmp ); /*Q_exc*/ - move16(); - move16(); - } -} - -/*-------------------------------------------------------------------* - * UL_inverse - * - * Calculate inverse of UL_val. Output in Q_exp. - *-------------------------------------------------------------------*/ -UWord32 UL_inverse( const UWord32 UL_val, Word16 *exp ) -{ - UWord32 UL_tmp; - - *exp = norm_ul( UL_val ); - move16(); - UL_tmp = UL_lshl( UL_val, *exp ); /* Q32 */ - - *exp = add( 32, sub( 31, *exp ) ); - move16(); - - return UL_div( 0x80000000, UL_tmp ); -} - -/*-------------------------------------------------------------------* - * UL_div - * - * Calculate UL_num/UL_den. UL_num assumed to be Q31, UL_den assumed - * to be Q32, then result is in Q32. - *-------------------------------------------------------------------*/ -UWord32 UL_div( const UWord32 UL_num, const UWord32 UL_den ) -{ - UWord32 UL_e, UL_Q; - UWord32 UL_msb, UL_lsb; - Word16 i; - - UL_e = UL_subNsD( 0xffffffff, UL_den ); - UL_Q = UL_num; - move32(); - - FOR( i = 0; i < 5; i++ ) - { - Mpy_32_32_uu( UL_Q, UL_e, &UL_msb, &UL_lsb ); /*31+32-32=31 */ - UL_Q = UL_addNsD( UL_Q, UL_msb ); - Mpy_32_32_uu( UL_e, UL_e, &UL_e, &UL_lsb ); /*32+32-32=32 */ - } - - return UL_Q; -} - -/*----------------------------------------------------------------------------- - * ratio() - * - * Divide the numerator by the denominator. - *----------------------------------------------------------------------------*/ -Word16 ratio( const Word32 numer, const Word32 denom, Word16 *expo ) -{ - Word16 expNumer, expDenom; - Word16 manNumer, manDenom; - Word16 quotient; - - expDenom = norm_l( denom ); /* exponent */ - manDenom = extract_h( L_shl( denom, expDenom ) ); /* mantissa */ - expNumer = norm_l( numer ); /* exponent */ - manNumer = extract_h( L_shl( numer, expNumer ) ); /* mantissa */ - manNumer = shr( manNumer, 1 ); /* Ensure the numerator < the denominator */ - quotient = div_s( manNumer, manDenom ); /* in Q14 */ - - *expo = sub( expNumer, expDenom ); - move16(); - return quotient; /* Q14 */ -} - -/*-----------------------------------------------------------------------* - * Function hp400_12k8() * - * * - * 2nd order Cheb2 high pass filter with cut off frequency at 400 Hz. * - * Optimized for fixed-point to get the following frequency response : * - * * - * frequency : 0Hz 100Hz 200Hz 300Hz 400Hz 630Hz 1.5kHz 3kHz * - * dB loss : -infdB -30dB -20dB -10dB -3dB +6dB +1dB 0dB * - * * - * Algorithm : * - * * - * y[i] = b[0]*x[i] + b[1]*x[i-1] + b[2]*x[i-2] * - * + a[1]*y[i-1] + a[2]*y[i-2]; * - * * - * short b[3] = {3660, -7320, 3660}; in Q12 * - * short a[3] = {4096, 7320, -3540}; in Q12 * - * * - * float --> b[3] = {0.893554687, -1.787109375, 0.893554687}; * - * a[3] = {1.000000000, 1.787109375, -0.864257812}; * - *-----------------------------------------------------------------------*/ -void hp400_12k8_fx( - Word16 signal[], /* i/o: input signal / output is divided by 16 */ - const Word16 lg, /* i : lenght of signal */ - Word16 mem[] /* i/o: filter memory [6] */ -) -{ - Word16 i; - Word16 y1_hi, y1_lo; - Word32 L_tmp, L_tmp2, L_tmp3; - - y1_hi = mem[2]; - move16(); - y1_lo = mem[3]; - move16(); - - L_tmp3 = L_mac( 16384L, mem[1], a_hp400_fx[2] ); /* rounding to maximize precision */ - L_tmp3 = L_mac( L_tmp3, y1_lo, a_hp400_fx[1] ); - L_tmp3 = L_shr( L_tmp3, 15 ); - L_tmp2 = L_mac( L_tmp3, mem[0], a_hp400_fx[2] ); - L_tmp2 = L_mac( L_tmp2, mem[5], b_hp400_fx[2] ); - L_tmp2 = L_mac( L_tmp2, mem[4], b_hp400_fx[1] ); - L_tmp3 = L_mult( mem[4], b_hp400_fx[2] ); - - mem[5] = signal[lg - 2]; - move16(); - FOR( i = 1; i < lg; i++ ) - { - /* y[i] = b[0]*x[i] + b[1]*x[i-1] + b[2]*x[i-2] */ - /* + a[1]*y[i-1] + a[2] * y[i-2] */ - - L_tmp = L_mac( L_tmp2, y1_hi, a_hp400_fx[1] ); - L_tmp = L_mac( L_tmp, *signal, b_hp400_fx[0] ); - - L_tmp = L_shl( L_tmp, 1 ); /* coeff Q12 --> Q13 */ - - L_tmp2 = L_mac( L_tmp3, y1_hi, a_hp400_fx[2] ); - L_tmp2 = L_mac( L_tmp2, *signal, b_hp400_fx[1] ); - L_tmp3 = L_mac( 16384L, y1_lo, a_hp400_fx[2] ); /* rounding to maximize precision */ - - y1_lo = L_Extract_lc( L_tmp, &y1_hi ); - - L_tmp3 = L_mac( L_tmp3, y1_lo, a_hp400_fx[1] ); - L_tmp3 = L_shr( L_tmp3, 15 ); - - L_tmp2 = L_add( L_tmp3, L_tmp2 ); - - L_tmp3 = L_mult( *signal, b_hp400_fx[2] ); - - /* signal is divided by 16 to avoid overflow in energy computation */ - *signal++ = round_fx( L_tmp ); - move16(); - } - - /* y[i] = b[0]*x[i] + b[1]*x[i-1] + b[2]*x[i-2] */ - /* + a[1]*y[i-1] + a[2] * y[i-2] */ - - L_tmp = L_mac( L_tmp2, y1_hi, a_hp400_fx[1] ); - - mem[4] = *signal; - move16(); - L_tmp = L_mac( L_tmp, mem[4], b_hp400_fx[0] ); - - L_tmp = L_shl( L_tmp, 1 ); /* coeff Q12 --> Q13 */ - - mem[0] = y1_hi; - move16(); - mem[1] = y1_lo; - move16(); - L_Extract( L_tmp, &mem[2], &mem[3] ); - - /* signal is divided by 16 to avoid overflow in energy computation */ - *signal++ = round_fx( L_tmp ); - move16(); - - return; -} - -void hp400_12k8_ivas_fx( - Word16 signal[], /* i/o: input signal / output is divided by 16 */ - const Word16 lg, /* i : lenght of signal */ - Word16 mem[] /* i/o: filter memory [6] */ -) -{ - Word16 i; - Word16 x0, x1, x2; - Word32 L_tmp, yy1, y2; - - yy1 = L_Comp( mem[2], mem[3] ); /* Q_syn + 13 */ - y2 = L_Comp( mem[0], mem[1] ); /* Q_syn + 13 */ - x0 = mem[4]; /* Q_syn */ - move16(); - x1 = mem[5]; /* Q_syn */ - move16(); - - FOR( i = 0; i < lg; i++ ) - { - x2 = x1; /* Q_syn */ - move16(); - x1 = x0; /* Q_syn */ - move16(); - x0 = signal[i]; /* Q_syn */ - move16(); - - L_tmp = Mpy_32_16_1( yy1, a_hp400_ivas_fx[1] ); /*yy1 * a_hp400[1]*/ /* Qx(Q_of_yy1) + 10 ---->( (Q_syn+13) + 12 - 15)*/ - L_tmp = Madd_32_16( L_tmp, y2, a_hp400_ivas_fx[2] ); /*y2 * a_hp400[2]*/ /* Qx + 10 ---->( (Q_syn+13) + 12 - 15)*/ - L_tmp = L_shl( L_tmp, 3 ); /* shifting by 3 to maintain same Q (Q_syn+13) */ - - L_tmp = L_mac( L_tmp, x0, b_hp400_fx[0] ); /* Q_syn + 13 */ - L_tmp = L_mac( L_tmp, x1, b_hp400_fx[1] ); /* Q_syn + 13 */ - L_tmp = L_mac( L_tmp, x2, b_hp400_fx[2] ); /* Q_syn + 13 */ - - y2 = yy1; /* Q_syn + 13 */ - move32(); - yy1 = L_tmp; /* Q_syn + 13 */ - move32(); - - signal[i] = round_fx( L_tmp ); /* Q_syn - 3 */ - move16(); - } - - L_Extract( yy1, &mem[2], &mem[3] ); - L_Extract( y2, &mem[0], &mem[1] ); - mem[4] = x0; /* Q_syn */ - mem[5] = x1; /* Q_syn */ - move16(); - move16(); - return; -} - -Word16 dot_prod_satcontr( const Word16 *x, const Word16 *y, Word16 qx, Word16 qy, Word16 *qo, Word16 len ) -{ - Word16 tmp_tab_x[L_FRAME16k]; - Word16 tmp_tab_y[L_FRAME16k]; - Word16 shift, q, ener, i; - Word32 L_tmp; - Word16 *pt1, *pt2; -#ifdef BASOP_NOGLOB_DECLARE_LOCAL - Flag Overflow = 0; - move32(); -#endif - - - Copy( x, tmp_tab_x, len ); /* OPTIMIZE !!!!! the copy into local table is not necessary */ - Copy( y, tmp_tab_y, len ); /* could be reworked to do a 1st iteration with the original x[] and y[] */ - /* then check if there is an overflow and do a more complex 2nd, 3rd, ... processing */ - shift = 0; - move16(); - BASOP_SATURATE_WARNING_OFF_EVS - DO - { - Overflow = 0; - move16(); - L_tmp = L_shl_o( 1, s_max( sub( add( add( qx, qy ), 7 ), shift ), 0 ), &Overflow ); - pt1 = tmp_tab_x; - pt2 = tmp_tab_y; - FOR( i = 0; i < len; i++ ) - { - L_tmp = L_mac0_o( L_tmp, *pt1++, *pt2++, &Overflow ); /*Q(qx+qy-shift) */ - } - - IF( Overflow != 0 ) - { - Scale_sig( tmp_tab_x, len, -2 ); - Scale_sig( tmp_tab_y, len, -2 ); - shift = add( shift, 4 ); - } - } - WHILE( Overflow != 0 ); - BASOP_SATURATE_WARNING_ON_EVS - - q = norm_l( L_tmp ); - L_tmp = L_shl( L_tmp, q ); /*Q(qx+qy-shift+q) */ - ener = extract_h( L_tmp ); /*Q(qx+qy-shift+q-16) */ - q = add( q, add( qx, qy ) ); - *qo = sub( q, add( shift, 16 ) ); - move16(); - return ener; -} - - -/* - * E_UTIL_f_convolve - * - * Parameters: - * x I: input vector <14bits - * h I: impulse response (or second input vector) (1Q14) - * y O: output vetor (result of convolution) - * - * Function: - * Perform the convolution between two vectors x[] and h[] and - * write the result in the vector y[]. All vectors are of length L. - * Only the first L samples of the convolution are considered. - * Vector size = L_SUBFR - * - * Returns: - * void - */ -void E_UTIL_f_convolve( const Word16 x[], const Word16 h[], Word16 y[], const Word16 size ) -{ - Word16 i, n; - Word32 L_sum; - Word64 L64_sum; - - FOR( n = 0; n < size; n++ ) - { - L64_sum = 0; - move64(); - FOR( i = 0; i < n; i++ ) - { - L64_sum = W_mac_16_16( L64_sum, x[i], h[n - i] ); - } - L_sum = W_sat_l( L64_sum ); - y[n] = mac_r( L_sum, x[i], h[0] ); - move16(); - } - return; -} - -/*----------------------------------------------------------------------------- - * floating_point_add: - * - * Add two floating point numbers: x <- x + y. - *----------------------------------------------------------------------------*/ -void floating_point_add( - Word32 *mx, /* io: mantissa of the addend Q31 */ - Word16 *ex, /* io: exponent of the addend Q0 */ - const Word32 my, /* i: mantissa of the adder Q31 */ - const Word16 ey /* i: exponent of the adder Q0 */ -) -{ - Word32 accX, accY; - Word16 align, expo; - /* NB: This function will not work properly if the mantissa is zero and the exponent is not 32. - It is up to the caller function to avoid this condition. */ - /* Ensure 1 bit headroom before addition. */ - accX = L_shr( *mx, 1 ); - accY = L_shr( my, 1 ); - /* First, align the Q-points of the two operands. Then, add. */ - align = sub( *ex, ey ); - - IF( align < 0 ) - { - accX = L_add( accX, L_shl( accY, align ) ); - } - ELSE - { - accX = L_add( accY, L_shr( accX, align ) ); - *ex = ey; - move16(); - } - /* Normalize the result and update the mantissa and exponent. */ - expo = norm_l( accX ); - *mx = L_shl( accX, expo ); - *ex = sub( add( *ex, expo ), 1 ); /* Subtract 1 due to 1-bit down-shift above ensuring 1 bit headroom before addition. */ - move32(); - move16(); - return; -} - -/*-------------------------------------------------------------------* - * delay_signal_fx() - * - * Delay buffer by defined number of samples - *-------------------------------------------------------------------*/ - -void delay_signal_fx( - Word16 x[], /* i/o: signal to be delayed */ - const Word16 len, /* i : length of the input signal */ - Word16 mem[], /* i/o: synchronization memory */ - const Word16 delay /* i : delay in samples */ -) -{ - Word16 tmp_buffer[L_FRAME48k]; - - Copy( mem, tmp_buffer, delay ); - Copy( x + sub( len, delay ), mem, delay ); - Copy( x, x + delay, sub( len, delay ) ); - Copy( tmp_buffer, x, delay ); - - return; -} - -void delay_signal32_fx( - Word32 x[], /* i/o: signal to be delayed */ - const Word16 len, /* i : length of the input signal */ - Word32 mem[], /* i/o: synchronization memory */ - const Word16 delay /* i : delay in samples */ -) -{ - Word32 tmp_buffer[L_FRAME48k]; - - Copy32( mem, tmp_buffer, delay ); - Copy32( x + sub( len, delay ), mem, delay ); - Copy32( x, x + delay, sub( len, delay ) ); - Copy32( tmp_buffer, x, delay ); - - return; -} - -void delay_signal_q_adj_fx( - Word32 x[], /* i/o: signal to be delayed */ - const Word16 len, /* i : length of the input signal */ - Word32 mem[], /* i/o: synchronization memory */ - const Word16 delay, /* i : delay in samples */ - const Word16 q_x, - const Word16 q_mem ) -{ - - Word32 tmp_buffer[L_FRAME48k]; - - Copy32( mem, tmp_buffer, delay ); - Copy32( x + sub( len, delay ), mem, delay ); - Copy32( x, x + delay, sub( len, delay ) ); - - - IF( EQ_16( q_x, q_mem ) ) - { - Copy32( tmp_buffer, x, delay ); - } - ELSE - { - v_shr( tmp_buffer, sub( q_mem, q_x ), x, delay ); - } - - return; -} - -void v_add_fx( - const Word32 x1[], /* i : Input vector 1 */ - const Word32 x2[], /* i : Input vector 2 */ - Word32 y[], /* o : Output vector that contains vector 1 + vector 2 */ - const Word16 N /* i : Vector length */ -) -{ - Word16 i; - - FOR( i = 0; i < N; i++ ) - { - y[i] = L_add_sat( x1[i], x2[i] ); - move32(); - } - - return; -} -Word16 floor_log_2( Word32 num ) -{ - - IF( num == 0 ) - { - return 0; - } - - return ( sub( 30, norm_l( num ) ) ); -} - -void v_shr( - const Word32 x[], /* i : Input vector */ - const Word16 shift, /* i : Constant */ - Word32 y[], /* o : Output vector that contains x >> shift */ - const Word16 N /* i : Vector length */ -) -{ - Word16 i; - - FOR( i = 0; i < N; i++ ) - { - y[i] = L_shr( x[i], shift ); - move32(); - } - - return; -} - -void v_shr_16( - const Word16 x[], /* i : Input vector */ - const Word16 shift, /* i : Constant */ - Word16 y[], /* o : Output vector that contains x >> shift */ - const Word16 N /* i : Vector length */ -) -{ - Word16 i; - - FOR( i = 0; i < N; i++ ) - { - y[i] = shr( x[i], shift ); - move16(); - } - - return; -} - -/*---------------------------------------------------------------------* - * lin_interp_fx() - * - * Linearly maps x from source range to the target range - *---------------------------------------------------------------------*/ - -/*! r: mapped output value */ -Word16 lin_interp_fx( - const Word16 x, /* i : Q15 the value to be mapped */ - const Word16 x1, /* i : Q15 source range interval: low end */ - const Word16 y1, /* i : Q15 source range interval: high end */ - const Word16 x2, /* i : Q15 target range interval: low */ - const Word16 y2, /* i : Q15 target range interval: high */ - const Word16 flag_sat /* i : flag to indicate whether to apply saturation */ -) -{ - IF( sub( x2, x1 ) == 0 ) - { - return y1; - } - ELSE IF( flag_sat ) - { - IF( GE_16( x, s_max( x1, x2 ) ) ) - { - IF( GT_16( x1, x2 ) ) - { - return y1; - } - ELSE - { - return y2; - } - } - ELSE IF( LE_16( x, s_min( x1, x2 ) ) ) - { - IF( LT_16( x1, x2 ) ) - { - return y1; - } - ELSE - { - return y2; - } - } - } - - return add_sat( y1, mult( sub( x, x1 ), div_s( sub( y2, y1 ), sub( x2, x1 ) ) ) ); -} - - -Word16 lin_interp_ivas_fx( - const Word16 x, /* i : Q15 the value to be mapped */ - const Word16 x1, /* i : Q15 source range interval: low end */ - const Word16 y1, /* i : Q15 source range interval: high end */ - const Word16 x2, /* i : Q15 target range interval: low */ - const Word16 y2, /* i : Q15 target range interval: high */ - const Word16 flag_sat /* i : flag to indicate whether to apply saturation */ -) -{ - IF( EQ_16( sub( x2, x1 ), 0 ) ) - { - return y1; - } - ELSE IF( flag_sat ) - { - IF( GE_16( x, s_max( x1, x2 ) ) ) - { - return GT_16( x1, x2 ) ? y1 : y2; - } - ELSE IF( LE_16( x, s_min( x1, x2 ) ) ) - { - return LT_16( x1, x2 ) ? y1 : y2; - } - } - Word16 div_res_e; - Word16 div_res = BASOP_Util_Divide1616_Scale( sub( y2, y1 ), sub( x2, x1 ), &div_res_e ); - // div_res = shl( div_res, div_res_e ); - return add_sat( y1, round_fx( L_shl( L_mult( sub( x, x1 ), div_res ), div_res_e ) ) ); -} - -/*--------------------------------------------------------------------- - * sign_l() - * - *---------------------------------------------------------------------*/ - -/*! r: sign of x (+1/-1) */ -Word32 sign_l( - const Word32 x /* i : input value of x */ -) -{ - IF( x < 0 ) - { - return MIN_32; - } - ELSE - { - return MAX_32; - } -} - -void v_mult16_fixed( - const Word16 x1[], /* i : Input vector 1 */ - const Word16 x2[], /* i : Input vector 2 */ - Word16 y[], /* o : Output vector that contains vector 1 .* vector 2 */ - const Word16 N /* i : Vector length */ -) -{ - Word16 i; - - FOR( i = 0; i < N; i++ ) - { - y[i] = mult_r( x1[i], x2[i] ); - move16(); - } - - return; -} - -/*---------------------------------------------------------------------* - * set_zero_fx() - * - * Set a vector vec[] of dimension lvec to zero - *---------------------------------------------------------------------*/ - -void set_zero_fx( - Word32 *vec, /* o : input vector */ - const Word16 lvec /* i : length of the vector */ -) -{ - Word16 i; - - FOR( i = 0; i < lvec; i++ ) - { - *vec++ = 0; - move32(); - } - - return; -} -void set_zero2_fx( - Word32 *vec, /* o : input vector */ - const Word32 lvec /* i : length of the vector */ -) -{ - Word32 i; - - FOR( i = 0; i < lvec; i++ ) - { - *vec++ = 0; - move32(); - } - - return; -} - -void set16_zero_fx( - Word16 *vec, /* o : input vector */ - const Word16 lvec /* i : length of the vector */ -) -{ - Word16 i; - - FOR( i = 0; i < lvec; i++ ) - { - *vec++ = 0; - move16(); - } - - return; -} - -UWord32 mvl2s_r( - const Word32 x[], /* i : input vector */ - const Word16 q_x, - Word16 y[], /* o : output vector */ - const Word16 n /* i : vector size */ -) -{ - Word16 i; - Word32 temp; - UWord32 noClipping = 0; - move32(); - - IF( n <= 0 ) - { - /* cannot transfer vectors with size 0 */ - return 0; - } - - IF( (void *) y <= (const void *) x ) - { - Word32 tempd = L_shl( 1, sub( q_x, 1 ) ); - FOR( i = 0; i < n; i++ ) - { - temp = L_add( x[i], tempd ); - temp = L_shr( temp, q_x ); - - IF( GT_32( temp, MAX16B ) ) - { - temp = MAX16B; - move32(); - noClipping = L_add( (Word32) noClipping, 1 ); - } - ELSE IF( LT_32( temp, MIN16B ) ) - { - temp = MIN16B; - move32(); - noClipping = L_add( (Word32) noClipping, 1 ); - } - - y[i] = extract_l( temp ); - move16(); - } - } - ELSE - { - Word32 tempd = L_shl( 1, sub( q_x, 1 ) ); - FOR( i = n - 1; i >= 0; i-- ) - { - temp = L_add( x[i], tempd ); - temp = L_shr( temp, q_x ); - - IF( GT_32( temp, MAX16B ) ) - { - temp = MAX16B; - move32(); - noClipping = L_add( (Word32) noClipping, 1 ); - } - ELSE IF( LT_32( temp, MIN16B ) ) - { - temp = MIN16B; - move32(); - noClipping = L_add( (Word32) noClipping, 1 ); - } - - y[i] = extract_l( temp ); - move16(); - } - } - - return noClipping; -} - -Word32 dotp_me_fx( - const Word32 x[], /* i : vector x[] */ - const Word32 y[], /* i : vector y[] */ - const Word16 n, /* i : vector length */ - Word16 exp_x, - Word16 exp_y, - Word16 *exp_suma ) -{ - Word16 i; - Word32 suma; - Word32 mul; - Word16 mul_exp = add( exp_x, exp_y ); - suma = Mpy_32_32( x[0], y[0] ); - *exp_suma = mul_exp; - FOR( i = 1; i < n; i++ ) - { - mul = Mpy_32_32( x[i], y[i] ); - suma = BASOP_Util_Add_Mant32Exp( suma, *exp_suma, mul, mul_exp, exp_suma ); // exp_x+exp_A - } - - return suma; -} - -Word32 dotp_fixed_guarded( - const Word32 x[], /* i : vector x[] */ - const Word32 y[], /* i : vector y[] */ - const Word16 n /* i : vector length */ -) -{ - Word16 i; - Word32 suma; - Word16 guarded_bits = find_guarded_bits_fx( n ); - suma = L_shr( Mpy_32_32( x[0], y[0] ), guarded_bits ); - - FOR( i = 1; i < n; i++ ) - { - suma = L_add( suma, L_shr( Mpy_32_32( x[i], y[i] ), guarded_bits ) ); - } - - return suma; -} - - -Word32 dotp_fixed_ivas_fx( - const Word32 x[], /* i : vector x[] */ - Word16 x_e, - const Word32 y[], /* i : vector y[] */ - Word16 y_e, - const Word16 n, /* i : vector length */ - Word16 *out_e ) -{ - Word16 i, exp; - Word32 suma = 0; - - exp = 31; - move16(); - - FOR( i = 0; i < n; i++ ) - { - suma = BASOP_Util_Add_Mant32Exp( suma, exp, Mpy_32_32( x[i], y[i] ), x_e + y_e, &exp ); - } - - *out_e = exp; - move16(); - return suma; -} - -/*-------------------------------------------------------------------* - * v_mult() - * - * Multiplication of two vectors - *-------------------------------------------------------------------*/ - - -void v_mult_fixed( - const Word32 x1[], /* i : Input vector 1 */ - const Word32 x2[], /* i : Input vector 2 */ - Word32 y[], /* o : Output vector that contains vector 1 .* vector 2 */ - const Word16 N /* i : Vector length */ -) -{ - Word16 i; - - FOR( i = 0; i < N; i++ ) - { - y[i] = Mpy_32_32( x1[i], x2[i] ); - move32(); - } - - return; -} - -/*-------------------------------------------------------------------* - * anint_fixed() - * - * Round to the nearest integer. - *-------------------------------------------------------------------*/ -Word32 anint_fixed( Word32 x, Word16 exp ) -{ - IF( x == 0 ) - { - return 0; - } - IF( x >= 0 ) - { - return L_add( x, L_shl( 1, sub( exp, 1 ) ) ); - } - ELSE - { - return L_sub( x, L_shl( 1, sub( exp, 1 ) ) ); - } -} - -/*-------------------------------------------------------------------* - * ceil_fixed() - * - * Ceil to the next multiple of (1 << exp). - *-------------------------------------------------------------------*/ -Word32 ceil_fixed( Word32 x, Word16 exp ) -{ - Word32 step; - // step = x / L_shl( 1, exp ); - step = L_shr( x, exp ); - IF( ( x % L_shl( 1, exp ) ) > 0 ) - { - step = L_add( step, 1 ); - } - return L_shl( step, exp ); -} - -void sort_l( - Word32 *x, /* i/o: Vector to be sorted */ - Word16 len /* i/o: vector length */ -) -{ - Word16 i, j; - Word32 tempr; - - FOR( i = len - 2; i >= 0; i-- ) - { - tempr = x[i]; - move32(); - FOR( j = i + 1; ( j < len ) && ( tempr > x[j] ); j++ ) - { - x[j - 1] = x[j]; - move32(); - } - x[j - 1] = tempr; - move32(); - } - - return; -} - -/*-------------------------------------------------------------------* - * v_add_fixed() - * - * Subtraction of two vectors sample by sample - *-------------------------------------------------------------------*/ - -void v_add_fixed( - const Word32 x1[], /* i : Input vector 1 */ - const Word32 x2[], /* i : Input vector 2 */ - Word32 y[], /* o : Output vector that contains vector 1 - vector 2 */ - const Word16 N, /* i : Vector length */ - const Word16 hdrm /* i : headroom for when subtraction result > 1 or < -1 */ -) -{ - Word16 i; - - FOR( i = 0; i < N; i++ ) - { - y[i] = L_add( L_shr( x1[i], hdrm ), L_shr( x2[i], hdrm ) ); - move32(); - } - - return; -} - -void v_add_fixed_no_hdrm( - const Word32 x1[], /* i : Input vector 1 */ - const Word32 x2[], /* i : Input vector 2 */ - Word32 y[], /* o : Output vector that contains vector 1 + vector 2 */ - const Word16 N /* i : Vector length */ -) -{ - Word16 i; - - FOR( i = 0; i < N; i++ ) - { - y[i] = L_add( x1[i], x2[i] ); - move32(); - } - - return; -} - -void v_add_fixed_me( - const Word32 x1[], /* i : Input vector 1 */ - const Word16 x1_e, /* i : Exponent for input vector 1 */ - const Word32 x2[], /* i : Input vector 2 */ - const Word16 x2_e, /* i : Exponent for input vector 2 */ - Word32 y[], /* o : Output vector that contains vector 1 - vector 2 */ - Word16 *y_e, /* i : Exponent for output vector */ - const Word16 N, /* i : Vector length */ - const Word16 hdrm /* i : headroom for when subtraction result > 1 or < -1 */ -) -{ - Word16 i; - Word16 x1_shift = sub( s_max( x1_e, x2_e ), x1_e ); - Word16 x2_shift = sub( s_max( x1_e, x2_e ), x2_e ); - - FOR( i = 0; i < N; i++ ) - { - y[i] = L_add( L_shr( x1[i], hdrm + x1_shift ), L_shr( x2[i], hdrm + x2_shift ) ); - move32(); - } - - *y_e = add( s_max( x1_e, x2_e ), hdrm ); - move16(); - - return; -} - -Word16 find_guarded_bits_fx( Word32 n ) -{ - // return n <= 1 ? 0 : n <= 2 ? 1 - // : n <= 4 ? 2 - // : n <= 8 ? 3 - // : n <= 16 ? 4 - // : n <= 32 ? 5 - // : n <= 64 ? 6 - // : n <= 128 ? 7 - // : n <= 256 ? 8 - // : n <= 512 ? 9 - // : n <= 1024 ? 10 - // : n <= 2048 ? 11 - // : n <= 4096 ? 12 - // : n <= 8192 ? 13 - // : n <= 16384 ? 14 - // : 15; - /*Word16 val = 0; - move32(); - test(); - WHILE( GT_32( n, L_shl( 1, val ) ) && LT_32( val, 16 ) ) - { - val = add( val, 1 ); - }*/ - IF( LE_32( n, 1 ) ) - { - return 0; - } - ELSE - { - - return sub( 31, norm_l( L_sub( n, 1 ) ) ); - } -} - -Word16 L_norm_arr( const Word32 *arr, Word16 size ) -{ - Word16 q = 31; - move16(); - FOR( Word16 i = 0; i < size; i++ ) - { - Word16 q_tst; - - q_tst = norm_l( arr[i] ); - if ( arr[i] != 0 ) - { - q = s_min( q, q_tst ); - } - } - - return q; -} - -Word16 norm_arr( Word16 *arr, Word16 size ) -{ - Word16 q = 15; - Word16 exp = 0; - move16(); - move16(); - FOR( Word16 i = 0; i < size; i++ ) - { - if ( arr[i] != 0 ) - { - exp = norm_s( arr[i] ); - } - if ( arr[i] != 0 ) - { - q = s_min( q, exp ); - } - } - return q; -} - -Word16 W_norm_arr( Word64 *arr, Word16 size ) -{ - Word16 q = 63; - Word16 exp = 0; - move16(); - move16(); - FOR( Word16 i = 0; i < size; i++ ) - { - if ( arr[i] != 0 ) - { - exp = W_norm( arr[i] ); - } - if ( arr[i] != 0 ) - { - q = s_min( q, exp ); - } - } - return q; -} - -Word16 get_min_scalefactor( Word32 x, Word32 y ) -{ - Word16 scf_y; - Word16 scf = Q31; - move16(); - - test(); - if ( x == 0 && y == 0 ) - { - scf = 0; - move16(); - } - - if ( x != 0 ) - { - scf = norm_l( x ); - } - - scf_y = norm_l( y ); - if ( y != 0 ) - { - scf = s_min( scf_y, scf ); - } - - return scf; -} - - -Flag is_zero_arr( Word32 *arr, Word16 size ) -{ - FOR( Word16 i = 0; i < size; i++ ) - IF( arr[i] != 0 ) - { - return 0; - } - - return 1; -} - -Flag is_zero_arr16( Word16 *arr, Word16 size ) -{ - FOR( Word16 i = 0; i < size; i++ ) - IF( arr[i] != 0 ) - { - return 0; - } - - return 1; -} - -Flag is_zero_arr64( Word64 *arr, Word16 size ) -{ - FOR( Word16 i = 0; i < size; i++ ) - { - IF( arr[i] != 0 ) - { - return 0; - } - } - return 1; -} - -void Scale_sig64( - Word64 x[], /* i/o: signal to scale Qx */ - Word16 len, /* i : size of x[] Q0 */ - Word16 exp /* i : exponent: x = round(x << exp) Qx exp */ -) -{ - Word16 i; - assert( exp <= 63 && exp >= -63 ); - IF( exp == 0 ) - { - return; - } - - FOR( i = 0; i < len; i++ ) - { - /* saturation can occur here */ - x[i] = W_shl( x[i], exp ); - move64(); - } -} diff --git a/Workspace_msvc/enc_temp_folder/ba9e794e4af04046f8293c8af70d4da/options.h b/Workspace_msvc/enc_temp_folder/ba9e794e4af04046f8293c8af70d4da/options.h deleted file mode 100644 index c94ad0ef3..000000000 --- a/Workspace_msvc/enc_temp_folder/ba9e794e4af04046f8293c8af70d4da/options.h +++ /dev/null @@ -1,102 +0,0 @@ -/****************************************************************************************************** - - (C) 2022-2025 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 - ====================================================================================*/ - -#ifndef OPTIONS_H -#define OPTIONS_H - -/* clang-format off */ - -/* ################### Start DEBUGGING switches ######################## */ - -/*#define DEBUGGING*/ /* Allows debugging message to be printed out during runtime */ -#ifdef DEBUGGING -/*#define DBG_BITSTREAM_ANALYSIS*/ /* Write bitstream with annotations to a text file */ -#define DEBUG_MODE_INFO /* Define to output most important parameters to the subdirectory "res/" */ -#define DEBUG_MODE_INFO_TWEAK /* Enable command line switch to specify subdirectory for debug info output inside "./res/" */ -#define DEBUG_FORCE_MDCT_STEREO_MODE /* Force stereo mode decision for MDCT stereo: -stereo 3 1 forces L/R coding and -stereo 3 2 forces full M/S coding */ -/*#define DEBUG_FORCE_DIR*/ /* Force modes/parameters by reading from external binary files */ -/*#define DBG_WAV_WRITER*/ /* Enable dbgwrite_wav() function for generating ".wav" files */ -#define SUPPORT_FORCE_TCX10_TCX20 /* VA: Enable -force tcx10|tcx20 command-line option */ -/*#define DEBUG_MODE_JBM */ /* define to output JBM relevant parameters */ -#endif - -#define SUPPORT_JBM_TRACEFILE /* Support for JBM tracefile, which is needed for 3GPP objective/subjective testing, but not relevant for real-world implementations */ - -/*#define WMOPS*/ /* Activate complexity and memory counters */ -#ifdef WMOPS -#define WMOPS_PER_FRAME /* Output per-frame complexity (writes one float value per frame to the file "wmops_analysis") */ -#define WMOPS_DETAIL /* Output detailed complexity printout for every function. Increases runtime overhead */ -#define WMOPS_WC_FRAME_ANALYSIS /* Output detailed complexity analysis for the worst-case frame */ -/*define MEM_COUNT_DETAILS*/ /* Output detailed memory analysis for the worst-case frame (writes to the file "mem_analysis.csv") */ -#endif - -/*#define DISABLE_LIMITER*/ - -/* #################### End DEBUGGING switches ############################ */ - -#ifndef BASOP_NOGLOB_DEV_USE_GLOBALS -#define BASOP_NOGLOB_DECLARE_LOCAL -#endif - -/* Note: each compile switch (FIX_1101_...) is independent from the other ones */ - -#define ISSUE_1836_replace_overflow_libcom /* FhG: replace overflow operators by non-overflow-alternatives in lib_com - BE */ -#define FIX_1942_ASSERTION_LOWSHELF /* FhG: Modified the target_gains_db_fx calculation in compute_t60_coeffs_fx() */ -#define FIX_1944_CRASH_FOR_STEREO /* FhG: improve TonalMDCTConceal_InsertNoise calculation precision */ -#define FIX_1970_SBA_CRASH /* Dlb: Fix for issue 1970, SBA crash */ - -#define FIX_1978_SAT_MISSING_IN_GAIN_ENC /* VA: Fix add saturation missing that lead to a crash in P800-10 */ -//#define FIX_1981_MAXIMUM_EXP_FX /* FhG: Fix bug in function to find maximum value in vector */ - -#define FIX_1979_SAT_MISSING_IN_LSF_ENC /* VA: Proposal to fix 1979, saturation in lsf_enc, NOkia to review */ -#define FIX_1946_CRASH_JBM_PROCESSING /* FhG: Increased guard bits of DFT_fx */ -#define FIX_1980_CRASH_FDCNG_ENCODESID /* FhG: Add one bit of headroom in e_fx calculation in FdCng_encodeSID_ivas_fx() */ -#define FIX_1987_CRASH_OMASA_ENERGY /* FhG: Replace cldfbAnalysis_ts_fx_fix_q() with cldfbAnalysis_ts_fx_var_q() to avoid assertion error */ -#define FIX_1985_SBA_714_HF_LOSS /* Dlb: Fix for issue 1985, improved dirac ref pow precision*/ - -/* #################### Start BASOP porting switches ############################ */ - -#define NONBE_1244_FIX_SWB_BWE_MEMORY /* VA: issue 1244: fix to SWB BWE memory in case of switching from FB coding - pending a review by Huawei */ -#define FIX_1129_EXT_REND_OUTPUT_HIGH /* Philips: issue 1129: External renderer BINAURAL_ROOM_REVERB format output level too high compared to internal rendering output */ -#define NONBE_1302_FIX_OMASA_JBM_FLUSH /* VA: issue 1302: fix OMASA JBM bitrate switching flush in binaural output */ -#define NONBE_1328_FIX_NON_LINEARITY /* VA: Fix possible issue when computing bwe_exc_extended and previous frame were almost 0, float issue 1328 */ -#define FIX_1319_STACK_SBA_DECODER /* VA: issue 1319: Optimize the definition of buffer lengths in the SBA decoder */ -#define FIX_1320_STACK_CPE_DECODER /* VA: issue 1320: Optimize the stack memory consumption in the CPE decoder */ -#define FIX_1984_SAT_IN_PSYCHAD /* VA: Issue 1984: proposal to fix an assert */ - -/* #################### End BASOP porting switches ############################ */ - -#endif diff --git a/Workspace_msvc/enc_temp_folder/d76ccfdc3b9fa9da476bcd2a44fe879/pitch_ol_fx.c b/Workspace_msvc/enc_temp_folder/d76ccfdc3b9fa9da476bcd2a44fe879/pitch_ol_fx.c deleted file mode 100644 index 56647f7b1..000000000 --- a/Workspace_msvc/enc_temp_folder/d76ccfdc3b9fa9da476bcd2a44fe879/pitch_ol_fx.c +++ /dev/null @@ -1,2475 +0,0 @@ -/*==================================================================================== - EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 - ====================================================================================*/ - -#include -#include "options.h" -#include "cnst.h" -// #include "prot_fx.h" -#include "basop_util.h" -#include "rom_com_fx.h" -#include "rom_com.h" -#include "rom_enc.h" -#include "prot_fx.h" /* Function prototypes */ -#include "prot_fx_enc.h" /* Function prototypes */ - -/*-----------------------------------------------------------------* - * Local Constants - *-----------------------------------------------------------------*/ -#define PIT_MIN2 20 /* pit_min for pitch tracking */ -#define PIT_MIN_1 44 /* for second pitch track */ -#define PIT_MIN2_1 24 - -#define THR_relE -2816 /* -11 (Q8) */ - -#define THRES0 4792 /* Threshold to favor smaller pitch lags; 1.17 (Q12) */ -#define DELTA0 2 /* multiples' search range initial */ -#define STEP 1 /* multiples' search range increment */ - -#define THRES1 13107 /* Threshold to favor pitch lags coherence for neighbours; 0.4 (Q15) */ -#define DELTA_COH 14 /* Maximum pitch lags difference for neighbours to be considered as coherent */ -#define THRES3 22938 /* Threshold to favor pitch lags coherence with previous frames; 0.7 (Q15) */ - -#define CORR_TH0 13107 /* Noise threshold for past frame correlations; 0.4 (Q15) */ -#define CORR_TH1 16384 /* Noise threshold for past frame correlations; 0.5 (Q15) */ - -#define LEN_X ( ( PIT_MAX / OPL_DECIM ) - ( PIT_MIN2 / OPL_DECIM ) + 1 ) /* Correlation buffer length */ -#define COH_FAC 5734 /* Factor for measuring the pitch coherence; 1.4 (Q12) */ - -#define NSUBSECT 7 -#define NSECT 4 -#define NHFR 3 -#define L_FIR_PO 5 -#define L_MEM ( L_FIR_PO - 2 ) - - -/*-----------------------------------------------------------------* - * Local function prototypes - *-----------------------------------------------------------------*/ - -static void LP_Decim2_Copy( const Word16 x[], Word16 y[], Word16 l, Word16 mem[] ); - -static void pitch_neighbour_fx( Word16 sect0, Word16 pitch_tmp[], Word16 pitch[3][2 * NSECT], Word16 corr_tmp[], Word16 corr[3][2 * NSECT], Word16 thres1[2 * NHFR], Word16 ind_tmp[2 * NHFR] ); - -static void find_mult_fx( Word16 *fac, Word16 pitch0, Word16 pitch1, Word16 pit_max0, Word16 *corr, Word16 *old_pitch, Word16 *old_corr, Word16 delta, Word16 step ); - -static Word16 pitch_coherence_fx( Word16 pitch0, Word16 pitch1, Word16 fac_max, Word16 diff_max ); - -static Word32 Dot_product12_OL( Word16 *sum1, const Word16 x[], const Word16 y[], const Word16 lg, const Word16 lg2, Word16 *exp, Word16 *exp2 ); - -static Word32 Dot_product12_OL_back( Word16 *sum1, const Word16 x[], const Word16 y[], const Word16 lg, const Word16 lg2, Word16 *exp, Word16 *exp2 ); - -/*-----------------------------------------------------------------* - * pitch_ol_init() - * - * Open loop pitch variable initialization - *-----------------------------------------------------------------*/ -void pitch_ol_init_fx( - Word16 *old_thres, /* o : threshold for reinforcement of past pitch influence */ - Word16 *old_pitch, /* o : pitch of the 2nd half-frame of previous frame */ - Word16 *delta_pit, /* o : pitch evolution extrapolation */ - Word16 *old_corr /* o : correlation */ -) -{ - *old_thres = 0; - move16(); - *old_pitch = 0; - move16(); - *delta_pit = 0; - move16(); - *old_corr = 0; - move16(); -} - - -/*==================================================================================*/ -/* FUNCTION : pitch_ol_fx() */ -/*----------------------------------------------------------------------------------*/ -/* PURPOSE : - * Compute the open loop pitch lag. - * - * The pitch lag search is divided into two sets. - * Each set is divided into three sections. - * Each section cannot have a pitch multiple. - * We find a maximum for each section. - * We compare the maxima of each section. - * - * 1st set 2nd set - * 1st section: lag delay = 115 down to 62 and 115 down to 78 - * 2nd section: lag delay = 61 down to 32 and 77 down to 41 - * 3rd section: lag delay = 31 down to 17 and 40 down to 22 - * 4th section: lag delay = 16 down to 10 and 21 down to 12 - * - * As there is a margin between section overlaps, especially for - * longer delays, this section selection is more robust for not - * to find multiples in the same section when pitch evolves rapidly. - * - * For each section, the length of the vectors to correlate is - * greater/equal to the longest pitch delay. */ -/*----------------------------------------------------------------------------------*/ -/* INPUT ARGUMENTS : */ -/* _ (Word16[]) old_pitch : OL pitch of the 2nd half-frame of the last frame Q0 */ -/* _ (Word16[]) old_corr_fx : correlation Q15 */ -/* _ (Word16[]) corr_shift_fx : normalized correlation correction Q15 */ -/* _ (Word16[]) old_thres_fx : maximum correlation weighting with respect */ -/* to past frame pitch Q15 */ -/* _ (Word16[]) delta_pit : old pitch extrapolation correction Q0 */ -/* _ (Word16[]) st_old_wsp2_fx: weighted speech memory qwsp */ -/* _ (Word16[]) wsp_fx : weighted speech for current frame & look-ahead qwsp */ -/* _ (Word16[]) mem_decim2_fx : wsp decimation filter memory qwsp */ -/* _ (Word16[]) relE_fx : relative frame energy Q8 */ -/* _ (Word16[]) L_look : look-ahead Q0 */ -/* _ (Word16[]) Opt_SC_VBR : SC-VBR flag Q0 */ -/* _ (Word16*) qwsp : wsp & filter memory Qformat */ -/*----------------------------------------------------------------------------------*/ -/* OUTPUT ARGUMENTS : */ -/* _ (Word16[]) pitch : open loop pitch lag for each half-frame Q0 */ -/* _ (Word16[]) T_op : open loop pitch lag for each half-frm for quant Q0 */ -/* _ (Word16[]) voicing_fx : max normalized correlation for each half-frame QIn */ -/* _ (Word16[]) old_pitch : OL pitch of the 2nd half-frame of the last frame Q0 */ -/* _ (Word16[]) old_corr_fx : correlation Q15 */ -/* _ (Word16[]) old_thres_fx : maximum correlation weighting with respect */ -/* to past frame pitch Q15 */ -/* _ (Word16[]) delta_pit : old pitch extrapolation correction Q0 */ -/* _ (Word16[]) st_old_wsp2_fx: weighted speech memory qwsp */ -/* _ (Word16[]) mem_decim2_fx : wsp decimation filter memory qwsp */ -/*----------------------------------------------------------------------------------*/ - -/*----------------------------------------------------------------------------------*/ -/* RETURN ARGUMENTS : */ -/* _ None */ -/*==================================================================================*/ - -void pitch_ol_fx( - Word16 pitch[3], /* o : open loop pitch lag for each half-frame in range [29,231] Q0 */ - Word16 voicing[3], /* o : maximum normalized correlation for each half-frame in [0,1.0[ Q15 */ - Word16 *old_pitch, /* i/o: pitch of the 2nd half-frame of previous frame (i.e. pitch[1]) Q0 */ - Word16 *old_corr, /* i/o: correlation of old_pitch (i.e. voicing[1] or corr_mean) Q15 */ - Word16 corr_shift, /* i : normalized correlation correction Q15 */ - Word16 *old_thres, /* i/o: maximum correlation weighting with respect to past frame pitch Q15 */ - Word16 *delta_pit, /* i/o: old pitch extrapolation correction in range [-14,+14] Q0 */ - Word16 *st_old_wsp2, /* i/o: weighted speech memory qwsp */ - const Word16 *wsp, /* i : weighted speech for current frame and look-ahead qwsp */ - Word16 mem_decim2[3], /* i/o: wsp decimation filter memory qwsp */ - const Word16 relE, /* i : relative frame energy Q8 */ - const Word16 last_class, /* i : frame classification of last frame */ - const Word16 bwidth, /* i : bandwidth */ - const Word16 Opt_SC_VBR /* i : SC-VBR flag */ -) -{ - Word16 ftmp, old_wsp2[( L_WSP - L_INTERPOL ) / OPL_DECIM], *wsp2; - Word16 tmp_mem[3]; - - Word16 scale1[2 * DELTA_COH - 1]; - Word16 scaled_buf[2 * LEN_X + 3 * ( DELTA_COH - 1 )]; - Word16 scaled_buf_exp[2 * LEN_X + 3 * ( DELTA_COH - 1 )], exp_sect[8], exp_sect1[8], exp_sect0; - Word16 cor_buf[2 * LEN_X]; - Word16 *pt_exp1, *pt_exp2, *pt_exp3, *pt_exp4; - Word16 *pt1, *pt2, *pt3, *pt4, *pt5, *pt6; - Word16 *pt_cor0, *pt_cor1, *pt_cor2, *pt_cor3, *pt_cor4, *pt_cor5, *pt_cor6; - Word16 thres1[6]; - Word16 diff, cnt, ind, ind1, offset, offset1, offset_la, offset_la1, coh_flag, coh_flag1; - Word16 ind_corX, ind1_corX; - - Word16 i, j, k, m, pit_min, pit_min1, sect0, subsect0, add_sect0, sub_sect0, old_tmp, old_tmp1, len_x, len_x1; - Word16 len_temp; - Word16 pitchX[NHFR][2 * NSECT], pitch_tmp[2 * NHFR], ind_tmp[2 * NHFR], tmp_buf[NHFR + 1]; - - Word16 enr0[NSECT], enr0_exp[NSECT], enr0_1[NSECT], enr0_1_exp[NSECT], enr1, enr1_exp, enr2_exp; - Word32 enr, enr2, Ltmp; - Word16 fac, tmp16, tmp16_2; - Word16 qCorX, qScaledX; - Word16 scaledX[NHFR][2 * NSECT], corX[NHFR][2 * NSECT], cor_tmp[2 * NHFR], cor_mean; - const Word16 *len, *len1, *sublen, *sublen1, *pit_max, *sec_length, *sec_length1; - - Word16 pit_min_coding; -#ifdef BASOP_NOGLOB_DECLARE_LOCAL - Flag Overflow = 0; -#endif - - /*--------------------------------------------------------------* - * Initialization - *--------------------------------------------------------------*/ - len = len_12k8; - len1 = len1_12k8; - sublen = sublen_12k8; - sublen1 = sublen1_12k8; - pit_max = pit_max_12k8; - sec_length = sec_length_12k8; - sec_length1 = sec_length1_12k8; - - test(); - if ( ( LT_16( last_class, VOICED_TRANSITION ) ) && ( NE_16( bwidth, NB ) ) ) - { - /*reset last pitch reinforcement in case of unvoiced or transitions: it avoids some pitch doublings*/ - *old_thres = 0; - move16(); - } - - pit_min_coding = PIT_MIN_EXTEND; - move16(); - test(); - test(); - test(); - test(); - IF( ( ( NE_16( bwidth, NB ) ) && ( GT_16( *old_pitch, PIT_MIN ) ) ) || - ( ( EQ_16( bwidth, NB ) ) && ( ( GT_16( *old_pitch, PIT_MIN2_1 ) ) || ( LT_16( *old_thres, 3277 ) ) ) ) ) /* 0.1 inQ15*/ - { - pit_min = PIT_MIN / OPL_DECIM; - move16(); - pit_min1 = PIT_MIN_1 / OPL_DECIM; - move16(); - subsect0 = 2; - move16(); - sect0 = 1; - move16(); - } - ELSE - { - pit_min = PIT_MIN2 / OPL_DECIM; - move16(); - pit_min1 = PIT_MIN2_1 / OPL_DECIM; - move16(); - subsect0 = 0; - move16(); - sect0 = 0; - move16(); - } - - len_x = ( PIT_MAX / OPL_DECIM - pit_min + 1 ); - move16(); - len_x1 = ( PIT_MAX / OPL_DECIM - pit_min1 + 1 ); - move16(); - - /*--------------------------------------------------------------* - * Find decimated weighted speech - * Update wsp buffer with the memory - * decimation of wsp[] to search pitch in LF and to reduce complexity - * Extend the decimation of wsp to the end of the speech buffer - * Update wsp memory - *--------------------------------------------------------------*/ - Copy( st_old_wsp2, old_wsp2, ( L_WSP_MEM - L_INTERPOL ) / OPL_DECIM ); - wsp2 = old_wsp2 + ( ( L_WSP_MEM - L_INTERPOL ) / OPL_DECIM ); - - LP_Decim2_Copy( wsp, wsp2, L_FRAME, mem_decim2 ); - - /* Avoid uninitialized memory access */ - set16_fx( wsp2 + L_FRAME / 2, 0, sizeof( old_wsp2 ) / sizeof( Word16 ) - ( ( L_WSP_MEM - L_INTERPOL ) / OPL_DECIM ) - L_FRAME / 2 ); - tmp_mem[0] = mem_decim2[0]; - move16(); - tmp_mem[1] = mem_decim2[1]; - move16(); - tmp_mem[2] = mem_decim2[2]; - move16(); - - LP_Decim2_Copy( &wsp[L_FRAME], &wsp2[( L_FRAME / 2 )], L_LOOK_12k8, tmp_mem ); /* shr() used instead of division by OPL_DECIM*/ - - Copy( &old_wsp2[L_FRAME / 2], st_old_wsp2, ( L_WSP_MEM - L_INTERPOL ) / OPL_DECIM ); - - /*-----------------------------------------------------------------* - * Attenuate the correlation correction factor due to noise. - * Reset correlation buffer outside the useful range. - * Find the scaling functions for immediate neigbours and - * further ones. - *-----------------------------------------------------------------*/ - - corr_shift = shr( corr_shift, 1 ); - - set16_fx( scaled_buf, 0, DELTA_COH - 1 ); - set16_fx( scaled_buf + ( DELTA_COH - 1 ) + len_x, 0, DELTA_COH - 1 ); - set16_fx( scaled_buf + 2 * ( DELTA_COH - 1 ) + len_x + len_x1, 0, DELTA_COH - 1 ); - set16_fx( scaled_buf_exp, 0, len_x + len_x1 + 3 * ( DELTA_COH - 1 ) ); - - pt1 = scale1 + DELTA_COH - 1; - pt2 = pt1; - tmp16 = mult( negate( *old_thres ), MAX_16 / DELTA_COH ); - k = *old_thres; - move16(); - FOR( i = 0; i < DELTA_COH; i++ ) - { - /* - * *pt1 = ( -(*old_thres)/DELTA_COH * i + *old_thres+1.0f ); - * To keep Q15 values, the following code does not add 1 to the result. - * A scaling factor must be applied accordingly (see next use of scale1) - */ - *pt1 = k; - move16(); - k = add( k, tmp16 ); - *pt2-- = *pt1++; - move16(); - } - - /*-----------------------------------------------------------------------------* - * Estimate the new pitch by extrapolating the old pitch value for 2 half-frames - *-----------------------------------------------------------------------------*/ - old_tmp = add( *old_pitch, *delta_pit ); - old_tmp = s_min( old_tmp, PIT_MAX / OPL_DECIM ); - old_tmp = s_max( old_tmp, pit_min ); - old_tmp1 = add( old_tmp, *delta_pit ); - old_tmp1 = s_min( old_tmp1, PIT_MAX / OPL_DECIM ); - old_tmp1 = s_max( old_tmp1, pit_min ); - - /*-----------------------------------------------------------------* - * Loop for all three half-frames (current frame + look-ahead) - *-----------------------------------------------------------------*/ - pt_cor0 = scaled_buf + DELTA_COH - 1; - - pt_cor2 = pt_cor0 - pit_min + old_tmp; - pt_cor4 = pt_cor0 - pit_min1 + old_tmp + ( DELTA_COH - 1 ) + len_x; - - FOR( i = 0; i < NHFR; i++ ) /* i = 0, 1, 2 */ - { - pt1 = wsp2 + i * 2 * ( L_SUBFR / OPL_DECIM ); /* *pt1 -> Q12 */ - pt2 = pt1 - pit_min; /* *pt2 -> Q12 */ - pt4 = pt1 - pit_min1; /* *pt4 -> Q12 */ - - enr = L_deposit_l( 1 ); - - pt_cor1 = pt_cor0; - pt_cor3 = pt_cor0 + ( DELTA_COH - 1 ) + len_x; - - pt_exp1 = scaled_buf_exp + DELTA_COH - 1; - pt_exp2 = pt_exp1; - pt_exp3 = scaled_buf_exp + 2 * ( DELTA_COH - 1 ) + len_x; - pt_exp4 = pt_exp3; - - IF( LT_16( i, NHFR - 1 ) ) /* First two half-frames (current frame) */ - { - pt3 = pt1; - pt5 = pt1; - - FOR( j = sect0; j < NSECT; j++ ) /* loop for each section */ - { - /*-----------------------------------------------------------------* - * Find fixed vector energy - *-----------------------------------------------------------------*/ - - /* 1st set */ - k = (Word16) ( pt1 - pt3 ); - move16(); - - FOR( k = add( k, len[j] ); k > 0; k-- ) - { - enr = L_mac0( enr, *pt3, *pt3 ); - pt3++; - } - /* keep Q15 normalized result */ - cnt = norm_l( enr ); - enr0[j] = extract_h( L_shl( enr, cnt ) ); - enr0_exp[j] = sub( 30, cnt ); - move16(); - - /* Reduce complexity (length of 'enr2' section is equal or larger than 'enr') */ - pt5 = pt3; - enr2 = enr; /* sets to 'enr' in 1 clock */ - move32(); - - /* 2nd set */ - k = (Word16) ( pt1 - pt5 ); - move16(); - - FOR( k = add( k, len1[j] ); k > 0; k-- ) - { - enr2 = L_mac0( enr2, *pt5, *pt5 ); - pt5++; - } - cnt = norm_l( enr2 ); - enr0_1[j] = extract_h( L_shl( enr2, cnt ) ); - enr0_1_exp[j] = sub( 30, cnt ); - move16(); - } - - /*----------------------------------------------------------* - * Find correlation for the non-overlapping pitch lag values - *----------------------------------------------------------*/ - exp_sect[subsect0] = 0; - move16(); - pt_cor5 = pt_cor1; - pt_cor6 = pt_cor3; - - tmp16 = exp_sect[subsect0]; - move16(); - - k = (Word16) ( pt2 - pt1 + pit_max[subsect0] ); - - IF( k >= 0 ) - { - len_temp = sublen[0]; - move16(); - - FOR( ; k >= 0; k-- ) - { - /* Keep Q15 normalized result */ - /* shr by 1 to make room for scaling in the neighbourhood of the extrapolated pitch */ - /* Update exponent to reflect shr by 1 */ - *pt_cor1 = extract_h( L_shr( Dot_product12( pt1, pt2--, len_temp, pt_exp1 ), 1 ) ); - - /* save the biggest exponent */ - tmp16 = s_max( tmp16, *pt_exp1 ); - - pt_cor1++; - pt_exp1++; - } - } - exp_sect[subsect0] = tmp16; - move16(); - - /*----------------------------------------------------------* - * For each subsection, find the correlation - *----------------------------------------------------------*/ - FOR( j = subsect0; j < NSUBSECT; j++ ) - { - len_temp = sublen[j]; - move16(); - - k = (Word16) ( pt2 - pt1 ); - move16(); - k = add( k, pit_max[j + 1] ); - exp_sect[j + 1] = 0; - move16(); - exp_sect1[j] = 0; - move16(); - - IF( k >= 0 ) - { - ind = exp_sect[j + 1]; - move16(); - ind1 = exp_sect1[j]; - move16(); - - FOR( ; k >= 0; k-- ) - { - /* Keep Q15 normalized result */ - /* shr by 1 to make room for scaling in the neighbourhood of the extrapolated pitch */ - /* Update exponent to reflect shr by 1 (done in Dot_product12_OL() for pt_cor3/pt_exp3) */ - *pt_cor1 = extract_h( L_shr( Dot_product12_OL( pt_cor3, pt1, pt2--, sublen[j], sublen1[j], pt_exp1, pt_exp3 ), 1 ) ); - /* The line above replaces: - * *pt_cor1 = shr(extract_h(Dot_product12(pt1, pt2, Sublen[j], pt_exp1)),1); move16(); - * *pt_cor3 = shr(extract_h(Dot_product12(pt1, pt2--, Sublen1[j+i*7], pt_exp3)),1); move16(); - */ - - /* save the biggest exponent */ - ind = s_max( ind, *pt_exp1 ); - ind1 = s_max( ind1, *pt_exp3 ); - - pt_cor1++; - pt_exp1++; - pt_cor3++; - pt_exp3++; - } - exp_sect[j + 1] = ind; - move16(); - exp_sect1[j] = ind1; - move16(); - } /* IF (k >= 0) */ - } /* FOR (j = subsect0; ... */ - } - ELSE /* 3rd half-frame (look-ahead) */ - { - pt6 = pt1 + L_LOOK_12k8 / OPL_DECIM - 1; - pt3 = pt6; - pt5 = pt6; - - /*-----------------------------------------------------------------* - * For each section in both sets, find fixed vector energy - *-----------------------------------------------------------------*/ - - FOR( j = sect0; j < NSECT; j++ ) /* loop for each section */ - { - /* 1st set */ - k = (Word16) ( pt3 - pt6 ); - move16(); - - FOR( k = add( k, len[j] ); k > 0; k-- ) - { - enr = L_mac0( enr, *pt3, *pt3 ); - pt3--; - } - - cnt = norm_l( enr ); - enr0[j] = extract_h( L_shl( enr, cnt ) ); /*qwsp+cnt-16*/ - enr0_exp[j] = sub( 30, cnt ); - move16(); - - /* Reduce complexity (length of 'enr2' section is equal or larger than 'enr') */ - pt5 = pt3; - enr2 = enr; - move16(); - - /* 2nd set */ - k = (Word16) ( pt5 - pt6 ); - move16(); - - FOR( k = add( k, len1[j] ); k > 0; k-- ) - { - enr2 = L_mac0( enr2, *pt5, *pt5 ); - pt5--; - } - - cnt = norm_l( enr2 ); - enr0_1[j] = extract_h( L_shl( enr2, cnt ) ); /*qwsp+cnt-16*/ - enr0_1_exp[j] = sub( 30, cnt ); - move16(); - } - - /* Set pointers */ - IF( sect0 != 0 ) - { - pt2 = pt6 - add( pit_max[1], 1 ); - k = sub( pit_max[2], pit_max[1] ); - move16(); - } - ELSE - { - pt2 = pt6 - pit_min; - k = 2; - move16(); - } - - /*-----------------------------------------------------------------* - * Find correlation for the non-overlapping pitch lag values - *-----------------------------------------------------------------*/ - exp_sect[subsect0] = 0; - move16(); - pt_cor5 = pt_cor1; - pt_cor6 = pt_cor3; - - tmp16 = exp_sect[subsect0]; - move16(); - - IF( k > 0 ) - { - len_temp = sublen[0]; - move16(); - - FOR( ; k > 0; k-- ) - { - /* Following lines are equivalent of Dot_product12() but with a backward incrementing */ - Ltmp = L_deposit_l( 1 ); - FOR( m = 0; m < len_temp; m++ ) - { - Ltmp = L_mac( Ltmp, pt6[-m], pt2[-m] ); - } - - /* Normalize acc in Q31 */ - tmp16_2 = norm_l( Ltmp ); - Ltmp = L_shl( Ltmp, tmp16_2 ); - *pt_exp1 = sub( 30, tmp16_2 ); - move16(); /* exponent = 0..30 */ - - /* Save result */ - *pt_cor1 = extract_h( L_shr( Ltmp, 1 ) ); - - /* Save the biggest exponent */ - tmp16 = s_max( tmp16, *pt_exp1 ); - - pt_cor1++; - pt_exp1++; - pt2--; - } - exp_sect[subsect0] = tmp16; - move16(); - } - - /*-----------------------------------------------------------------* - * For each subsection, find the correlation (overlapping pitch lag values) - *-----------------------------------------------------------------*/ - - FOR( j = subsect0; j < NSUBSECT; j++ ) - { - exp_sect[j + 1] = 0; - move16(); - exp_sect1[j] = 0; - move16(); - - ind = exp_sect[j + 1]; - move16(); - ind1 = exp_sect1[j]; - move16(); - - k = sub( pit_max[j + 1], pit_max[j] ); - - FOR( ; k > 0; k-- ) - { - *pt_cor1 = extract_h( L_shr( Dot_product12_OL_back( pt_cor3, pt6, pt2--, sublen[j], sublen1[j], pt_exp1, pt_exp3 ), 1 ) ); - - /* Save the biggest exponent */ - ind = s_max( ind, *pt_exp1 ); - ind1 = s_max( ind1, *pt_exp3 ); - - pt_cor1++; - pt_exp1++; - pt_cor3++; - pt_exp3++; - } - exp_sect[j + 1] = ind; - move16(); - exp_sect1[j] = ind1; - move16(); - } - } /* 3rd half-frame (look-ahead) */ - - /* Scale all values in each section to the same exponent for upcoming Find_max() */ - offset = 0; - move16(); - offset1 = 0; - move16(); - exp_sect1[7] = 0; /* padding */ - move16(); - FOR( j = sect0; j < NSECT; j++ ) - { - exp_sect0 = s_max( exp_sect[j * 2], exp_sect[j * 2 + 1] ); - - /* scaling of exp for track 1 */ - offset = add( offset, sec_length[j] ); - k = (Word16) ( pt_cor0 - pt_cor5 ); - move16(); - FOR( k = add( k, offset ); k > 0; k-- ) - { - cnt = sub( exp_sect0, *pt_exp2 ); - tmp16 = s_min( 15, cnt ); - if ( cnt > 0 ) - { - tmp16 = shr( *pt_cor5, tmp16 ); - } - if ( cnt > 0 ) - { - *pt_cor5 = tmp16; - move16(); - } - *pt_exp2 = s_max( *pt_exp2, exp_sect0 ); - move16(); - pt_cor5++; - pt_exp2++; - } - - exp_sect0 = s_max( exp_sect1[j * 2], exp_sect1[j * 2 + 1] ); - - /* scaling of exp for track 2 */ - offset1 = add( offset1, sec_length1[j] ); - k = (Word16) ( pt_cor0 - pt_cor6 + ( DELTA_COH - 1 ) ); - move16(); - k = add( k, len_x ); - FOR( k = add( k, offset1 ); k > 0; k-- ) - { - cnt = sub( exp_sect0, *pt_exp4 ); - tmp16 = s_min( 15, cnt ); - if ( cnt > 0 ) - { - tmp16 = shr( *pt_cor6, tmp16 ); - } - if ( cnt > 0 ) - { - *pt_cor6 = tmp16; - move16(); - } - *pt_exp4 = s_max( *pt_exp4, exp_sect0 ); - move16(); - pt_cor6++; - pt_exp4++; - } - } /* FOR (j = sect0; ... */ - - Copy( pt_cor0, cor_buf, len_x ); /* Save unscaled correlation vector */ - Copy( pt_cor0 + ( DELTA_COH - 1 ) + len_x, cor_buf + len_x, len_x1 ); - - /*-----------------------------------------------------------------* - * Scale correlation function in the neighbourhood of - * the extrapolated pitch - *-----------------------------------------------------------------*/ - pt_cor1 = pt_cor2 - ( DELTA_COH - 1 ); - pt_cor3 = pt_cor4 - ( DELTA_COH - 1 ); - pt2 = scale1; - - FOR( k = 0; k < 2 * DELTA_COH - 1; k++ ) - { - /* all Q15 here */ - *pt_cor1 = add( *pt_cor1, mult( *pt_cor1, *pt2 ) ); - move16(); - *pt_cor3 = add( *pt_cor3, mult( *pt_cor3, *pt2++ ) ); - move16(); - - pt_cor1++; - pt_cor3++; - } - - /* Update for next half-frame & look-ahead */ - pt_cor2 = pt_cor0 - pit_min + old_tmp1; - pt_cor4 = pt_cor0 - pit_min1 + old_tmp1 + ( DELTA_COH - 1 ) + len_x; - - /*-----------------------------------------------------------------* - * For each section, find maximum correlation and compute - * normalized correlation - *-----------------------------------------------------------------*/ - - pt_cor1 = pt_cor0; - pt_exp1 = scaled_buf_exp + DELTA_COH - 1; - offset = 0; - move16(); - pt_cor3 = pt_cor0 + ( DELTA_COH - 1 ) + len_x; - pt_exp3 = scaled_buf_exp + 2 * ( DELTA_COH - 1 ) + len_x; - offset1 = 0; - move16(); - - FOR( j = sect0; j < NSECT; j++ ) /* loop for each section */ - { - /* 1st set */ - offset_la = 0; - move16(); - if ( EQ_16( i, 2 ) ) - { - offset_la = sub( L_LOOK_12k8 / OPL_DECIM, len[j] ); - } - - /* 2nd set */ - offset_la1 = 0; - move16(); - if ( EQ_16( i, 2 ) ) - { - offset_la1 = sub( L_LOOK_12k8 / OPL_DECIM, len1[j] ); - } - - /* 1st set of candidates */ - ind = add( maximum_fx( pt_cor1, sec_length[j], &ftmp ), offset ); - pitchX[i][j] = add( ind, pit_min ); - move16(); - pt2 = pt1 - pitchX[i][j] + /*-*/ offset_la; /* selected moving vector */ - - enr1_exp = 0; - move16(); - enr1 = add_o( extract_h( dotp_fx( pt2, pt2, len[j], &enr1_exp ) ), 1, &Overflow ); - - enr2 = L_mult( enr0[j], enr1 ); - enr2_exp = norm_l( enr2 ); - enr2 = L_shl( enr2, enr2_exp ); - enr2_exp = sub( 31, add( sub( 28, add( enr0_exp[j], enr1_exp ) ), add( enr2_exp, 1 ) ) ); - - enr2 = Isqrt_lc( enr2, &enr2_exp ); /* 1/sqrt(energy) */ /*31-enr2_exp*/ - enr1_exp = norm_l( enr2 ); - enr1 = extract_h( L_shl( enr2, enr1_exp ) ); /*31-enr2_exp+enr1_exp-16*/ - enr1_exp = sub( enr2_exp, enr1_exp ); /*15-enr1_exp*/ - - Ltmp = L_mult0( cor_buf[ind], enr1 ); - qCorX = add( sub( 15, enr1_exp ), sub( 14, pt_exp1[ind] ) ); - corX[i][j] = extract_h( L_shr_sat( Ltmp, sub( qCorX, 31 ) ) ); - qCorX = 31; - move16(); - - Ltmp = L_mult0( pt_cor0[ind], enr1 ); - qScaledX = add( sub( 15, enr1_exp ), sub( 14, pt_exp1[ind] ) ); - scaledX[i][j] = round_fx( L_shl( Ltmp, sub( 16 + 12, qScaledX ) ) ); - qScaledX = 12; - move16(); - - pt_cor1 += sec_length[j]; - move16(); - offset = add( offset, sec_length[j] ); - - /* 2nd set of candidates */ - ind1 = add( maximum_fx( pt_cor3, sec_length1[j], &ftmp ), offset1 ); - pitchX[i][j + NSECT] = add( ind1, pit_min1 ); - move16(); - pt4 = pt1 - pitchX[i][j + NSECT] + /*-*/ offset_la1; - move16(); /* selected moving vector */ - enr1_exp = 0; - move16(); - enr1 = add_o( extract_h( dotp_fx( pt4, pt4, len1[j], &enr1_exp ) ), 1, &Overflow ); - - enr2 = L_mult( enr0_1[j], enr1 ); - enr2_exp = norm_l( enr2 ); - enr2 = L_shl( enr2, enr2_exp ); - - enr2_exp = sub( 31, add( sub( 28, add( enr0_1_exp[j], enr1_exp ) ), add( enr2_exp, 1 ) ) ); - enr2 = Isqrt_lc( enr2, &enr2_exp ); /* 1/sqrt(energy) */ /*31-enr2_exp*/ - enr1_exp = norm_l( enr2 ); - enr1 = extract_h( L_shl( enr2, enr1_exp ) ); /*31-enr2_exp+enr1_exp-16*/ - enr1_exp = sub( enr2_exp, enr1_exp ); /*15-enr1_exp*/ - - Ltmp = L_mult0( cor_buf[ind1 + len_x], enr1 ); - - qCorX = add( sub( 15, enr1_exp ), sub( 14, pt_exp3[ind1] ) ); - corX[i][j + NSECT] = extract_h( L_shr_sat( Ltmp, qCorX - 31 ) ); - qCorX = 31; - move16(); - - Ltmp = L_mult0( pt_cor0[ind1 + ( DELTA_COH - 1 ) + len_x], enr1 ); - qScaledX = add( sub( 15, enr1_exp ), sub( 14, pt_exp3[ind1] ) ); - scaledX[i][j + NSECT] = round_fx( L_shl( Ltmp, sub( 16 + 12, qScaledX ) ) ); - /*scaledX[i][j+NSECT] = saturate(L_shr(Ltmp, qScaledX-12));*/ - qScaledX = 12; - move16(); - - pt_cor3 += sec_length1[j]; - move16(); - offset1 = add( offset1, sec_length1[j] ); - - } /* FOR j < NSECT */ - } /* FOR i < NHFR */ - - /*-----------------------------------------------------------------* - * Favor a smaller delay if it happens that it has its multiple - * in the longer-delay sections (harmonics check) - *-----------------------------------------------------------------*/ - - FOR( i = 0; i < 2; i++ ) /* loop for the 2 half-frames */ - { - fac = THRES0; - move16(); - find_mult_fx( &fac, pitchX[i][2], pitchX[i][3], pit_max[7], &scaledX[i][2], old_pitch, old_corr, DELTA0, STEP ); /* Multiples in 3rd section */ - find_mult_fx( &fac, pitchX[i][1], pitchX[i][2], pit_max[5], &scaledX[i][1], old_pitch, old_corr, DELTA0, STEP ); /* Multiples in 2nd section */ - test(); - IF( ( sect0 == 0 ) && GE_16( shl( pitchX[i][0], 1 ), pit_min_coding ) ) - { - find_mult_fx( &fac, pitchX[i][0], pitchX[i][1], pit_max[3], &scaledX[i][0], old_pitch, old_corr, DELTA0, STEP ); /* Multiples in 2nd section */ - } - fac = THRES0; - move16(); - find_mult_fx( &fac, pitchX[i][NSECT + 2], pitchX[i][NSECT + 3], pit_max[7], &scaledX[i][NSECT + 2], old_pitch, old_corr, DELTA0, STEP ); /* Multiples in 3rd section */ - find_mult_fx( &fac, pitchX[i][NSECT + 1], pitchX[i][NSECT + 2], pit_max[6], &scaledX[i][NSECT + 1], old_pitch, old_corr, DELTA0, STEP ); /* Multiples in 2nd section */ - test(); - IF( ( sect0 == 0 ) && GE_16( shl( pitchX[i][NSECT + 0], 1 ), pit_min_coding ) ) - { - find_mult_fx( &fac, pitchX[i][NSECT + 0], pitchX[i][NSECT + 1], pit_max[4], &scaledX[i][NSECT + 0], old_pitch, old_corr, DELTA0, STEP ); /* Multiples in 2nd section */ - } - } - - fac = THRES0; - move16(); /* the look-ahead */ - find_mult_fx( &fac, pitchX[i][2], pitchX[i][3], pit_max[7], &scaledX[i][2], old_pitch, old_corr, 2, 2 ); /* Multiples in 3rd section */ - find_mult_fx( &fac, pitchX[i][1], pitchX[i][2], pit_max[5], &scaledX[i][1], old_pitch, old_corr, DELTA0, STEP ); /* Multiples in 2nd section */ - test(); - IF( ( sect0 == 0 ) && GE_16( shl( pitchX[i][0], 1 ), pit_min_coding ) ) - { - find_mult_fx( &fac, pitchX[i][0], pitchX[i][1], pit_max[3], &scaledX[i][0], old_pitch, old_corr, DELTA0, STEP ); /* Multiples in 2nd section */ - } - fac = THRES0; - move16(); - find_mult_fx( &fac, pitchX[i][NSECT + 2], pitchX[i][NSECT + 3], pit_max[7], &scaledX[i][NSECT + 2], old_pitch, old_corr, 2, 2 ); /* Multiples in 3rd section */ - find_mult_fx( &fac, pitchX[i][NSECT + 1], pitchX[i][NSECT + 2], pit_max[6], &scaledX[i][NSECT + 1], old_pitch, old_corr, DELTA0, STEP ); /* Multiples in 2nd section */ - test(); - IF( ( sect0 == 0 ) && GE_16( shl( pitchX[i][NSECT + 0], 1 ), pit_min_coding ) ) - { - find_mult_fx( &fac, pitchX[i][NSECT + 0], pitchX[i][NSECT + 1], pit_max[4], &scaledX[i][NSECT + 0], old_pitch, old_corr, DELTA0, STEP ); /* Multiples in 2nd section */ /* Multiples in 2nd section */ - } - - /*-----------------------------------------------------------------* - * Do 1st estimate for pitch values - * Adjust the normalized correlation using estimated noise level - * Compute the maximum scaling for the neighbour correlation - * reinforcement - *-----------------------------------------------------------------*/ - add_sect0 = add( NSECT, sect0 ); - sub_sect0 = sub( NSECT, sect0 ); - FOR( i = 0; i < NHFR; i++ ) - { - /* 1st set of pitch candidates */ - ind = add( maximum_fx( scaledX[i] + sect0, sub_sect0, &ftmp ), sect0 ); - ind_tmp[i] = ind; - move16(); - pitch_tmp[i] = pitchX[i][ind]; - move16(); - cor_tmp[i] = add_o( corX[i][ind], corr_shift, &Overflow ); - move16(); - - /* Higher is the neighbour's correlation, higher is the weighting */ - /* operands are Q15, result is Q15 */ - thres1[i] = mult( THRES1, cor_tmp[i] ); - move16(); - - /* 2nd set of pitch candidates */ - ind1 = add( maximum_fx( scaledX[i] + add_sect0, sub_sect0, &ftmp ), add_sect0 ); - ind_tmp[i + NHFR] = ind1; - move16(); - pitch_tmp[i + NHFR] = pitchX[i][ind1]; - move16(); - cor_tmp[i + NHFR] = add_o( corX[i][ind1], corr_shift, &Overflow ); - move16(); - - /* Higher is the neighbour's correlation, higher is the weighting */ - /* operands are Q15, result is Q15 */ - thres1[i + NHFR] = mult( THRES1, cor_tmp[i + NHFR] ); - move16(); - } - /*-----------------------------------------------------------------* - * Take into account previous and next pitch values of the present - * frame and look-ahead. Choose the pitch lags and normalize - * correlations for each half-frame & look-ahead - *-----------------------------------------------------------------*/ - - pitch_neighbour_fx( sect0, pitch_tmp, pitchX, cor_tmp, scaledX, thres1, ind_tmp ); - FOR( i = 0; i < NHFR; i++ ) - { - ind = add( maximum_fx( scaledX[i] + sect0, sub_sect0, &ftmp ), sect0 ); - ind_corX = add( maximum_fx( corX[i] + sect0, sub_sect0, &ftmp ), sect0 ); - - ind1 = add( maximum_fx( scaledX[i] + add_sect0, sub_sect0, &ftmp ), add_sect0 ); - ind1_corX = add( maximum_fx( corX[i] + add_sect0, sub_sect0, &ftmp ), add_sect0 ); - - if ( GT_16( scaledX[i][ind1], scaledX[i][ind] ) ) - { - ind = ind1; - move16(); - } - test(); - if ( Opt_SC_VBR && GT_16( corX[i][ind1_corX], corX[i][ind_corX] ) ) - { - ind_corX = ind1_corX; - move16(); - } - test(); - test(); - test(); - IF( Opt_SC_VBR && ( LT_16( mult( pitchX[i][ind], 13107 /*0.4 in Q15*/ ), pitchX[i][ind_corX] ) ) && - ( GT_16( mult( pitchX[i][ind], 19661 /*0.6 in Q15*/ ), pitchX[i][ind_corX] ) ) && - ( GE_16( corX[i][ind_corX], 29491 /*0.9 in Q15*/ ) ) ) - { - pitch[i] = pitchX[i][ind_corX]; - move16(); - voicing[i] = corX[i][ind_corX]; - move16(); - } - ELSE - { - pitch[i] = pitchX[i][ind]; - move16(); - voicing[i] = corX[i][ind]; - move16(); - } - } - - /*-----------------------------------------------------------------* - * Increase the threshold for correlation reinforcement with - * the past if correlation high and pitch stable - *-----------------------------------------------------------------*/ - - /* all Q15 here */ - /* cor_mean = 0.5f * (voicing[0] + voicing[1]) + corr_shift; */ - Ltmp = L_mult( voicing[0], 16384 ); - Ltmp = L_mac( Ltmp, voicing[1], 16384 ); - cor_mean = round_fx( L_add( Ltmp, corr_shift ) ); - - /* pitch unstable in present frame or from previous frame or normalized correlation too low */ - coh_flag = pitch_coherence_fx( pitch[0], pitch[1], COH_FAC, DELTA_COH ); - move16(); - coh_flag1 = pitch_coherence_fx( pitch[0], *old_pitch, COH_FAC, DELTA_COH ); - move16(); - - test(); - test(); - test(); - IF( ( coh_flag == 0 ) || ( coh_flag1 == 0 ) || ( LT_16( cor_mean, CORR_TH0 ) ) || ( LT_16( relE, THR_relE ) ) ) - { - /* Reset the threshold */ - *old_thres = 0; - move16(); - } - ELSE - { - /* The threshold increase is directly dependent on normalized correlation */ - /* *old_thres += (0.16f * cor_mean); */ - *old_thres = round_fx( L_mac( L_deposit_h( *old_thres ), 5243, cor_mean ) ); - } - - *old_thres = s_min( *old_thres, THRES3 ); - move16(); - - IF( GT_16( voicing[1], voicing[0] ) ) - { - *old_corr = voicing[1]; - move16(); - } - ELSE - { - *old_corr = cor_mean; - move16(); - } - - /*-----------------------------------------------------------------* - * Extrapolate the pitch value for the next frame by estimating - * the pitch evolution. This value is added to the old_pitch - * in the next frame and is then used when the normalized - * correlation is reinforced by the past estimate - *-----------------------------------------------------------------*/ - tmp_buf[0] = *old_pitch; - move16(); - FOR( i = 0; i < NHFR; i++ ) - { - tmp_buf[i + 1] = pitch[i]; - move16(); - } - - *delta_pit = 0; - move16(); - cnt = 0; - move16(); - - FOR( i = 0; i < NHFR; i++ ) - { - diff = sub( tmp_buf[i + 1], tmp_buf[i] ); - move16(); - coh_flag = pitch_coherence_fx( tmp_buf[i], tmp_buf[i + 1], COH_FAC, DELTA_COH ); - - if ( coh_flag != 0 ) - { - *delta_pit = add( *delta_pit, diff ); - move16(); - } - cnt = add( cnt, coh_flag ); - } - if ( EQ_16( cnt, 2 ) ) - { - /* *delta_pit /= 2; */ - *delta_pit = shr( *delta_pit, 1 ); - move16(); - } - IF( EQ_16( cnt, 3 ) ) - { - k = *delta_pit; - move16(); - /* *delta_pit /= 3; */ - if ( k < 0 ) - { - *delta_pit = mult( *delta_pit, -32768 ); - move16(); - } - tmp16 = mult( *delta_pit, 10923 ); - if ( k < 0 ) - { - tmp16 = mult( tmp16, -32768 ); - } - *delta_pit = tmp16; - move16(); - } - - /*--------------------------------------------------------------* - * Update old pitch, upsample pitch, - *--------------------------------------------------------------*/ - - *old_pitch = pitch[1]; - move16(); - - FOR( i = 0; i < NHFR; i++ ) - { - /* compensate decimation */ - pitch[i] = i_mult2( pitch[i], OPL_DECIM ); - move16(); - } - - return; -} - -void pitch_ol_ivas_fx( - Word16 pitch[3], /* o : open loop pitch lag for each half-frame in range [29,231] Q0 */ - Word16 voicing[3], /* o : maximum normalized correlation for each half-frame in [0,1.0[ Q15 */ - Word16 *old_pitch, /* i/o: pitch of the 2nd half-frame of previous frame (i.e. pitch[1]) Q0 */ - Word16 *old_corr, /* i/o: correlation of old_pitch (i.e. voicing[1] or corr_mean) Q15 */ - Word16 corr_shift, /* i : normalized correlation correction Q15 */ - Word16 *old_thres, /* i/o: maximum correlation weighting with respect to past frame pitch Q14 */ - Word16 *delta_pit, /* i/o: old pitch extrapolation correction in range [-14,+14] Q0 */ - Word16 *st_old_wsp2, /* i/o: weighted speech memory qwsp */ - const Word16 *wsp, /* i : weighted speech for current frame and look-ahead qwsp */ - Word16 mem_decim2[3], /* i/o: wsp decimation filter memory qwsp */ - const Word16 relE, /* i : relative frame energy Q8 */ - const Word16 last_class, /* i : frame classification of last frame */ - const Word16 bwidth, /* i : bandwidth */ - const Word16 Opt_SC_VBR, /* i : SC-VBR flag */ - Word16 qwsp /* i : Q factor for wsp Q0 */ -) -{ - Word16 ftmp, old_wsp2[( L_WSP - L_INTERPOL ) / OPL_DECIM], *wsp2; - Word16 tmp_mem[3]; - - Word16 scale1[2 * DELTA_COH - 1]; - Word16 scaled_buf[2 * LEN_X + 3 * ( DELTA_COH - 1 )]; - Word16 scaled_buf_exp[2 * LEN_X + 3 * ( DELTA_COH - 1 )]; - Word16 cor_buf[2 * LEN_X], cor_buf_exp[2 * LEN_X]; - Word16 *pt1, *pt2, *pt3, *pt4, *pt5, *pt6; - Word16 *pt_cor0, *pt_cor1, *pt_cor2, *pt_cor3, *pt_cor4; - Word16 *pt_cor0_exp, *pt_cor1_exp, *pt_cor2_exp, *pt_cor3_exp, *pt_cor4_exp; - Word16 thres1[6]; - Word16 diff, cnt, ind, ind1, offset, offset1, offset_la, offset_la1, coh_flag, coh_flag1; - Word16 ind_corX, ind1_corX; - - Word16 i, j, k, m, pit_min, pit_min1, sect0, subsect0, add_sect0, sub_sect0, old_tmp, old_tmp1, len_x, len_x1; - Word16 len_temp; - Word16 pitchX[NHFR][2 * NSECT], pitch_tmp[2 * NHFR], ind_tmp[2 * NHFR], tmp_buf[NHFR + 1]; - - Word16 enr0_exp[NSECT], enr0_1_exp[NSECT], enr1_exp; - Word32 enr0[NSECT], enr0_1[NSECT], enr1; - Word64 temp, temp1; - Word32 Ltmp; - Word16 fac, tmp16, tmp16_2; - Word16 scaledX[NHFR][2 * NSECT], corX[NHFR][2 * NSECT], cor_tmp[2 * NHFR], cor_mean; - const Word16 *len, *len1, *sublen, *sublen1, *pit_max, *sec_length, *sec_length1; - - Word16 pit_min_coding; -#ifdef BASOP_NOGLOB_DECLARE_LOCAL - Flag Overflow = 0; -#endif - Word16 new_q; - new_q = sub( 63, shl( qwsp, 1 ) ); - - /*--------------------------------------------------------------* - * Initialization - *--------------------------------------------------------------*/ - len = len_12k8; - len1 = len1_12k8; - sublen = sublen_12k8; - sublen1 = sublen1_12k8; - pit_max = pit_max_12k8; - sec_length = sec_length_12k8; - sec_length1 = sec_length1_12k8; - - test(); - if ( ( LT_16( last_class, VOICED_TRANSITION ) ) && ( NE_16( bwidth, NB ) ) ) - { - /*reset last pitch reinforcement in case of unvoiced or transitions: it avoids some pitch doublings*/ - *old_thres = 0; - move16(); - } - - pit_min_coding = PIT_MIN_EXTEND; - move16(); - test(); - test(); - test(); - test(); - IF( ( ( NE_16( bwidth, NB ) ) && ( GT_16( *old_pitch, PIT_MIN ) ) ) || - ( ( EQ_16( bwidth, NB ) ) && ( ( GT_16( *old_pitch, PIT_MIN2_1 ) ) || ( LT_16( *old_thres, 1638 /* 0.1 in Q14*/ ) ) ) ) ) - { - pit_min = PIT_MIN / OPL_DECIM; - move16(); - pit_min1 = PIT_MIN_1 / OPL_DECIM; - move16(); - subsect0 = 2; - move16(); - sect0 = 1; - move16(); - } - ELSE - { - pit_min = PIT_MIN2 / OPL_DECIM; - move16(); - pit_min1 = PIT_MIN2_1 / OPL_DECIM; - move16(); - subsect0 = 0; - move16(); - sect0 = 0; - move16(); - } - - len_x = ( PIT_MAX / OPL_DECIM - pit_min + 1 ); - move16(); - len_x1 = ( PIT_MAX / OPL_DECIM - pit_min1 + 1 ); - move16(); - - /*--------------------------------------------------------------* - * Find decimated weighted speech - * Update wsp buffer with the memory - * decimation of wsp[] to search pitch in LF and to reduce complexity - * Extend the decimation of wsp to the end of the speech buffer - * Update wsp memory - *--------------------------------------------------------------*/ - Copy( st_old_wsp2, old_wsp2, ( L_WSP_MEM - L_INTERPOL ) / OPL_DECIM ); - wsp2 = old_wsp2 + ( ( L_WSP_MEM - L_INTERPOL ) / OPL_DECIM ); - - LP_Decim2_Copy( wsp, wsp2, L_FRAME, mem_decim2 ); - - /* Avoid uninitialized memory access */ - set16_fx( wsp2 + L_FRAME / 2, 0, sizeof( old_wsp2 ) / sizeof( Word16 ) - ( ( L_WSP_MEM - L_INTERPOL ) / OPL_DECIM ) - L_FRAME / 2 ); - tmp_mem[0] = mem_decim2[0]; - move16(); - tmp_mem[1] = mem_decim2[1]; - move16(); - tmp_mem[2] = mem_decim2[2]; - move16(); - - LP_Decim2_Copy( &wsp[L_FRAME], &wsp2[L_FRAME / 2], L_LOOK_12k8, tmp_mem ); /* shr() used instead of division by OPL_DECIM*/ - - Copy( &old_wsp2[L_FRAME / 2], st_old_wsp2, ( L_WSP_MEM - L_INTERPOL ) / OPL_DECIM ); - - /*-----------------------------------------------------------------* - * Attenuate the correlation correction factor due to noise. - * Reset correlation buffer outside the useful range. - * Find the scaling functions for immediate neigbours and - * further ones. - *-----------------------------------------------------------------*/ - - corr_shift = shr( corr_shift, 1 ); - - set16_fx( scaled_buf, 0, DELTA_COH - 1 ); - set16_fx( scaled_buf + ( DELTA_COH - 1 ) + len_x, 0, DELTA_COH - 1 ); - set16_fx( scaled_buf + 2 * ( DELTA_COH - 1 ) + len_x + len_x1, 0, DELTA_COH - 1 ); - set16_fx( scaled_buf_exp, 0, len_x + len_x1 + 3 * ( DELTA_COH - 1 ) ); - - pt1 = scale1 + DELTA_COH - 1; - pt2 = pt1; - tmp16 = mult( *old_thres, -32768 / DELTA_COH ); // Q14 - k = add( *old_thres, ONE_IN_Q14 ); // Q14 - FOR( i = 0; i < DELTA_COH; i++ ) - { - *pt1 = k; // Q14 - *pt2-- = *pt1++; // Q14 - move16(); - move16(); - - k = add( k, tmp16 ); // Q14 - } - - /*-----------------------------------------------------------------------------* - * Estimate the new pitch by extrapolating the old pitch value for 2 half-frames - *-----------------------------------------------------------------------------*/ - old_tmp = add( *old_pitch, *delta_pit ); - old_tmp = s_min( old_tmp, PIT_MAX / OPL_DECIM ); - old_tmp = s_max( old_tmp, pit_min ); - old_tmp1 = add( old_tmp, *delta_pit ); - old_tmp1 = s_min( old_tmp1, PIT_MAX / OPL_DECIM ); - old_tmp1 = s_max( old_tmp1, pit_min ); - - /*-----------------------------------------------------------------* - * Loop for all three half-frames (current frame + look-ahead) - *-----------------------------------------------------------------*/ - pt_cor0 = scaled_buf + DELTA_COH - 1; - pt_cor0_exp = scaled_buf_exp + DELTA_COH - 1; - - pt_cor2 = pt_cor0 - pit_min + old_tmp; - pt_cor2_exp = pt_cor0_exp - pit_min + old_tmp; - - pt_cor4 = pt_cor0 - pit_min1 + old_tmp + ( DELTA_COH - 1 ) + len_x; - pt_cor4_exp = pt_cor0_exp - pit_min1 + old_tmp + ( DELTA_COH - 1 ) + len_x; - - FOR( i = 0; i < NHFR; i++ ) /* i = 0, 1, 2 */ - { - pt1 = wsp2 + i * 2 * ( L_SUBFR / OPL_DECIM ); /* *pt1 -> Q12 */ - pt2 = pt1 - pit_min; /* *pt2 -> Q12 */ - pt4 = pt1 - pit_min1; /* *pt4 -> Q12 */ - - temp = 0; - move64(); - - pt_cor1 = pt_cor0; - pt_cor1_exp = pt_cor0_exp; - - pt_cor3 = pt_cor0 + ( DELTA_COH - 1 ) + len_x; - pt_cor3_exp = pt_cor0_exp + ( DELTA_COH - 1 ) + len_x; - - IF( LT_16( i, NHFR - 1 ) ) /* First two half-frames (current frame) */ - { - pt3 = pt1; - pt5 = pt1; - - FOR( j = sect0; j < NSECT; j++ ) /* loop for each section */ - { - /*-----------------------------------------------------------------* - * Find fixed vector energy - *-----------------------------------------------------------------*/ - - /* 1st set */ - k = (Word16) ( pt1 - pt3 ); - move16(); - FOR( k = add( k, len[j] ); k > 0; k-- ) - { - temp = W_mac0_16_16( temp, *pt3, *pt3 ); // 2*qwsp - pt3++; - } - IF( temp == 0 ) - { - enr0[j] = 21474836; // 0.01 in Q31 - enr0_exp[j] = 0; - move32(); - move16(); - } - ELSE - { - cnt = W_norm( temp ); - enr0[j] = W_extract_h( W_shl( temp, cnt ) ); // 2*qwsp+cnt-32 - enr0_exp[j] = sub( new_q, cnt ); // 31-(2*qwsp+cnt-32) - move32(); - move16(); - } - - /* Reduce complexity (length of 'enr2' section is equal or larger than 'enr') */ - pt5 = pt3; - - /* 2nd set */ - k = (Word16) ( pt1 - pt5 ); - move16(); - - temp1 = temp; - move64(); - FOR( k = ( k + len1[j] ); k > 0; k-- ) - { - temp1 = W_mac0_16_16( temp1, *pt5, *pt5 ); // 2*qwsp - pt5++; - } - IF( temp1 == 0 ) - { - enr0_1[j] = 21474836; // 0.01 in Q31 - enr0_1_exp[j] = 0; - move32(); - move16(); - } - ELSE - { - cnt = W_norm( temp1 ); - enr0_1[j] = W_extract_h( W_shl( temp1, cnt ) ); // 2*qwsp+cnt-32 - enr0_1_exp[j] = sub( new_q, cnt ); // 31-(2*qwsp+cnt-32) - move32(); - move16(); - } - } - - /*----------------------------------------------------------* - * Find correlation for the non-overlapping pitch lag values - *----------------------------------------------------------*/ - - k = (Word16) ( pt2 - pt1 + pit_max[subsect0] ); - move16(); - - FOR( ; k >= 0; k-- ) - { - temp = 0; - move64(); - FOR( m = 0; m < sublen[0]; m++ ) - { - temp = W_mac0_16_16( temp, pt1[m], pt2[m] ); // 2*qwsp - } - cnt = W_norm( temp ); - *pt_cor1 = extract_h( W_extract_h( W_shl( temp, cnt ) ) ); // 2*qwsp+cnt-32-16 - *pt_cor1_exp = sub( new_q, cnt ); // 15-(2*qwsp+cnt-32-16) - move16(); - move16(); - - pt2--; - pt_cor1++; - pt_cor1_exp++; - } - - /*----------------------------------------------------------* - * For each subsection, find the correlation - *----------------------------------------------------------*/ - FOR( j = subsect0; j < NSUBSECT; j++ ) - { - len_temp = sublen[j]; - move16(); - - k = (Word16) ( pt2 - pt1 ); - move16(); - k = add( k, pit_max[j + 1] ); - - /* Keep Q15 normalized result */ - IF( LT_16( sublen[j], sublen1[j] ) ) - { - FOR( ; k >= 0; k-- ) - { - temp = W_mult0_16_16( pt1[0], pt2[0] ); // 2*qwsp - FOR( m = 1; m < sublen[j]; m++ ) - { - temp = W_mac0_16_16( temp, pt1[m], pt2[m] ); // 2*qwsp - } - cnt = W_norm( temp ); - *pt_cor1 = extract_h( W_extract_h( W_shl( temp, cnt ) ) ); // 2*qwsp+cnt-32-16 - *pt_cor1_exp = sub( new_q, cnt ); - move16(); - move16(); - - FOR( ; m < sublen1[j]; m++ ) - { - temp = W_mac0_16_16( temp, pt1[m], pt2[m] ); // 2*qwsp - } - cnt = W_norm( temp ); - *pt_cor3 = extract_h( W_extract_h( W_shl( temp, cnt ) ) ); // 2*qwsp+cnt-32-16 - *pt_cor3_exp = sub( new_q, cnt ); - move16(); - move16(); - - pt_cor1++; - pt_cor1_exp++; - pt_cor3++; - pt_cor3_exp++; - pt2--; - } - } - ELSE - { - FOR( ; k >= 0; k-- ) - { - temp = W_mult0_16_16( pt1[0], pt2[0] ); // 2*qwsp - FOR( m = 1; m < sublen1[j]; m++ ) - { - temp = W_mac0_16_16( temp, pt1[m], pt2[m] ); // 2*qwsp - } - cnt = W_norm( temp ); - *pt_cor3 = extract_h( W_extract_h( W_shl( temp, cnt ) ) ); // 2*qwsp+cnt-32-16 - *pt_cor3_exp = sub( new_q, cnt ); - move16(); - move16(); - - FOR( ; m < sublen[j]; m++ ) - { - temp = W_mac0_16_16( temp, pt1[m], pt2[m] ); // 2*qwsp - } - cnt = W_norm( temp ); - *pt_cor1 = extract_h( W_extract_h( W_shl( temp, cnt ) ) ); // 2*qwsp+cnt-32-16 - *pt_cor1_exp = sub( new_q, cnt ); - move16(); - move16(); - - pt_cor1++; - pt_cor1_exp++; - pt_cor3++; - pt_cor3_exp++; - pt2--; - } - } - } /* FOR (j = subsect0; ... */ - } - ELSE /* 3rd half-frame (look-ahead) */ - { - pt6 = pt1 + L_LOOK_12k8 / OPL_DECIM - 1; - pt3 = pt6; - pt5 = pt6; - - /*-----------------------------------------------------------------* - * For each section in both sets, find fixed vector energy - *-----------------------------------------------------------------*/ - FOR( j = sect0; j < NSECT; j++ ) /* loop for each section */ - { - /* 1st set */ - k = (Word16) ( pt3 - pt6 ); - move16(); - - FOR( k = add( k, len[j] ); k > 0; k-- ) - { - temp = W_mac0_16_16( temp, *pt3, *pt3 ); - pt3--; - } - IF( temp == 0 ) - { - enr0[j] = 21474836; // 0.01 in Q31 - enr0_exp[j] = 0; - move32(); - move16(); - } - ELSE - { - cnt = W_norm( temp ); - enr0[j] = W_extract_h( W_shl( temp, cnt ) ); // 2*qwsp+cnt-32 - enr0_exp[j] = sub( new_q, cnt ); // 31-(2*qwsp+cnt-32) - move32(); - move16(); - } - - /* Reduce complexity (length of 'enr2' section is equal or larger than 'enr') */ - pt5 = pt3; - temp1 = temp; - move64(); - - /* 2nd set */ - k = (Word16) ( pt5 - pt6 ); - move16(); - FOR( k = add( k, len1[j] ); k > 0; k-- ) - { - temp1 = W_mac0_16_16( temp1, *pt5, *pt5 ); // 2*qwsp - pt5--; - } - IF( temp1 == 0 ) - { - enr0_1[j] = 21474836; // 0.01 in Q31 - enr0_1_exp[j] = 0; - move32(); - move16(); - } - ELSE - { - cnt = W_norm( temp1 ); - temp1 = W_shl( temp1, cnt ); // 2*qwsp+cnt - enr0_1[j] = W_extract_h( temp1 ); // 2*qwsp+cnt-32 - enr0_1_exp[j] = sub( new_q, cnt ); // 31-(2*qwsp+cnt-32) - move32(); - move16(); - } - } - - /* Set pointers: same as IF/ELSE block */ - pt2 = pt6 - pit_min; - k = 2; - move16(); - IF( sect0 != 0 ) - { - pt2 = pt6 - add( pit_max[1], 1 ); - k = sub( pit_max[2], pit_max[1] ); - move16(); - } - - /*-----------------------------------------------------------------* - * Find correlation for the non-overlapping pitch lag values - *-----------------------------------------------------------------*/ - - len_temp = sublen[0]; - move16(); - - FOR( ; k > 0; k-- ) - { - temp = 0; - move64(); - FOR( m = 0; m < len_temp; m++ ) - { - temp = W_mac0_16_16( temp, pt6[-m], pt2[-m] ); // 2*qwsp - } - tmp16_2 = W_norm( temp ); - *pt_cor1 = extract_h( W_extract_h( W_shl( temp, tmp16_2 ) ) ); // 2*qwsp+tmp16_2 - *pt_cor1_exp = sub( new_q, tmp16_2 ); // 2*qwsp+tmp16_2-32-16 - move16(); - move16(); - - pt_cor1++; - pt_cor1_exp++; - pt2--; - } - - /*-----------------------------------------------------------------* - * For each subsection, find the correlation (overlapping pitch lag values) - *-----------------------------------------------------------------*/ - - FOR( j = subsect0; j < NSUBSECT; j++ ) - { - k = sub( pit_max[j + 1], pit_max[j] ); - - IF( LT_16( sublen[j], sublen1[j] ) ) - { - FOR( ; k > 0; k-- ) - { - temp = W_mult0_16_16( pt6[0], pt2[0] ); // 2*qwsp - FOR( m = 1; m < sublen[j]; m++ ) - { - temp = W_mac0_16_16( temp, pt6[-m], pt2[-m] ); // 2*qwsp - } - cnt = W_norm( temp ); - *pt_cor1 = extract_h( W_extract_h( W_shl( temp, cnt ) ) ); // 2*qwsp+cnt-32-16 - *pt_cor1_exp = sub( new_q, cnt ); - move16(); - move16(); - - FOR( ; m < sublen1[j]; m++ ) - { - temp = W_mac0_16_16( temp, pt6[-m], pt2[-m] ); // 2*qwsp - } - cnt = W_norm( temp ); - *pt_cor3 = extract_h( W_extract_h( W_shl( temp, cnt ) ) ); // 2*qwsp+cnt-32-16 - *pt_cor3_exp = sub( new_q, cnt ); - move16(); - move16(); - - pt_cor1++; - pt_cor1_exp++; - pt_cor3++; - pt_cor3_exp++; - pt2--; - } - } - ELSE - { - FOR( ; k > 0; k-- ) - { - temp = W_mult0_16_16( pt6[0], pt2[0] ); // 2*qwsp - FOR( m = 1; m < sublen1[j]; m++ ) - { - temp = W_mac0_16_16( temp, pt6[-m], pt2[-m] ); // 2*qwsp - } - cnt = W_norm( temp ); - *pt_cor3 = extract_h( W_extract_h( W_shl( temp, cnt ) ) ); // 2*qwsp+cnt-32-16 - *pt_cor3_exp = sub( new_q, cnt ); - move16(); - move16(); - - FOR( ; m < sublen[j]; m++ ) - { - temp = W_mac0_16_16( temp, pt6[-m], pt2[-m] ); // 2*qwsp - } - cnt = W_norm( temp ); - *pt_cor1 = extract_h( W_extract_h( W_shl( temp, cnt ) ) ); // 2*qwsp+cnt-32-16 - *pt_cor1_exp = sub( new_q, cnt ); - move16(); - move16(); - - pt_cor1++; - pt_cor1_exp++; - pt_cor3++; - pt_cor3_exp++; - pt2--; - } - } - } - } /* 3rd half-frame (look-ahead) */ - - /* Scale all values in each section to the same exponent for upcoming Find_max() */ - Copy( pt_cor0, cor_buf, len_x ); /* Save unscaled correlation vector */ - Copy( pt_cor0_exp, cor_buf_exp, len_x ); /* Save unscaled correlation vector */ - Copy( pt_cor0 + ( DELTA_COH - 1 ) + len_x, cor_buf + len_x, len_x1 ); - Copy( pt_cor0_exp + ( DELTA_COH - 1 ) + len_x, cor_buf_exp + len_x, len_x1 ); - - /*-----------------------------------------------------------------* - * Scale correlation function in the neighbourhood of - * the extrapolated pitch - *-----------------------------------------------------------------*/ - pt_cor1 = pt_cor2 - ( DELTA_COH - 1 ); - pt_cor1_exp = pt_cor2_exp - ( DELTA_COH - 1 ); - pt_cor3 = pt_cor4 - ( DELTA_COH - 1 ); - pt_cor3_exp = pt_cor4_exp - ( DELTA_COH - 1 ); - pt2 = scale1; - - FOR( k = 0; k < 2 * DELTA_COH - 1; k++ ) - { - *pt_cor1 = mult( *pt_cor1, *pt2 ); // *pt_cor1_exp+1 - *pt_cor1_exp = add( *pt_cor1_exp, 1 ); // *pt_cor1_exp+1 - move16(); - move16(); - - *pt_cor3 = mult( *pt_cor3, *pt2++ ); // *pt_cor3_exp+1 - *pt_cor3_exp = add( *pt_cor3_exp, 1 ); // *pt_cor1_exp+1 - move16(); - move16(); - - pt_cor1++; - pt_cor1_exp++; - pt_cor3++; - pt_cor3_exp++; - } - - /* Update for next half-frame & look-ahead */ - pt_cor2 = pt_cor0 - pit_min + old_tmp1; - pt_cor2_exp = pt_cor0_exp - pit_min + old_tmp1; - - pt_cor4 = pt_cor0 - pit_min1 + old_tmp1 + ( DELTA_COH - 1 ) + len_x; - pt_cor4_exp = pt_cor0_exp - pit_min1 + old_tmp1 + ( DELTA_COH - 1 ) + len_x; - - /*-----------------------------------------------------------------* - * For each section, find maximum correlation and compute - * normalized correlation - *-----------------------------------------------------------------*/ - - pt_cor1 = pt_cor0; - pt_cor1_exp = pt_cor0_exp; - offset = 0; - move16(); - pt_cor3 = pt_cor0 + ( DELTA_COH - 1 ) + len_x; - pt_cor3_exp = pt_cor0_exp + ( DELTA_COH - 1 ) + len_x; - offset1 = 0; - move16(); - - FOR( j = sect0; j < NSECT; j++ ) /* loop for each section */ - { - /* 1st set */ - offset_la = 0; - move16(); - if ( EQ_16( i, 2 ) ) - { - offset_la = sub( L_LOOK_12k8 / OPL_DECIM, len[j] ); - } - - /* 2nd set */ - offset_la1 = 0; - move16(); - if ( EQ_16( i, 2 ) ) - { - offset_la1 = sub( L_LOOK_12k8 / OPL_DECIM, len1[j] ); - } - - /* 1st set of candidates */ - ind = add( maximum_exp_fx( pt_cor1, pt_cor1_exp, sec_length[j] ), offset ); - pitchX[i][j] = add( ind, pit_min ); - move16(); - pt2 = pt1 - pitchX[i][j] + /*-*/ offset_la; /* selected moving vector */ - - enr1_exp = 0; - move16(); - - /* enr1 = dotp( pt2, pt2, len[j] ) + 0.01f; */ - temp = 0; - move64(); - FOR( m = 0; m < len[j]; m++ ) - { - temp = W_mac0_16_16( temp, pt2[m], pt2[m] ); // 2*qwsp - } - - temp = W_shl( temp, sub( Q24, shl( qwsp, 1 ) ) ); // Q24 - - temp = W_add( temp, 167772 ); /*0.01f in Q24*/ - - enr1_exp = W_norm( temp ); - enr1 = W_extract_h( W_shl( temp, enr1_exp ) ); // enr1_exp+24-32 - enr1_exp = sub( 39, enr1_exp ); // 31-(enr1_exp+24-32) - - enr1 = Mpy_32_32( enr0[j], enr1 ); - enr1_exp = add( enr0_exp[j], enr1_exp ); - - enr1 = ISqrt32( enr1, &enr1_exp ); /* 1/sqrt(energy) */ /*31-enr2_exp*/ - - Ltmp = Mpy_32_16_1( enr1, cor_buf[ind] ); - corX[i][j] = extract_h( L_shl_o( Ltmp, add( enr1_exp, cor_buf_exp[ind] ), &Overflow ) ); // Q15 - move16(); - - Ltmp = Mpy_32_16_1( enr1, pt_cor0[ind] ); - scaledX[i][j] = round_fx( L_shl( Ltmp, sub( add( enr1_exp, pt_cor0_exp[ind] ), 3 ) ) ); // Q12 - move16(); - - pt_cor1 += sec_length[j]; - pt_cor1_exp += sec_length[j]; - offset = add( offset, sec_length[j] ); - - /* 2nd set of candidates */ - ind1 = add( maximum_exp_fx( pt_cor3, pt_cor3_exp, sec_length1[j] ), offset1 ); - pitchX[i][j + NSECT] = add( ind1, pit_min1 ); - move16(); - pt4 = pt1 - pitchX[i][j + NSECT] + /*-*/ offset_la1; - move16(); /* selected moving vector */ - enr1_exp = 0; - move16(); - - /* enr1 = dotp(pt4, pt4, len1[j]) + 0.01f; */ - temp = 0; - move64(); - move64(); - FOR( m = 0; m < len1[j]; m++ ) - { - temp = W_mac0_16_16( temp, pt4[m], pt4[m] ); // 2*qwsp - } - - temp = W_shl( temp, sub( Q24, shl( qwsp, 1 ) ) ); // Q24 - - temp = W_add( temp, 167772 ); /*0.01f in Q24*/ - - enr1_exp = W_norm( temp ); - enr1 = W_extract_h( W_shl( temp, enr1_exp ) ); // enr1_exp+24-32 - enr1_exp = sub( 39, enr1_exp ); // 31-(enr1_exp+24-32) - - enr1 = Mpy_32_32( enr0_1[j], enr1 ); - enr1_exp = add( enr0_1_exp[j], enr1_exp ); - - enr1 = ISqrt32( enr1, &enr1_exp ); /* 1/sqrt(energy) */ /*31-enr1_exp*/ - - Ltmp = Mpy_32_16_1( enr1, cor_buf[ind1 + len_x] ); - corX[i][j + NSECT] = extract_h( L_shl_o( Ltmp, add( enr1_exp, cor_buf_exp[ind1 + len_x] ), &Overflow ) ); // Q15 - move16(); - - Ltmp = Mpy_32_16_1( enr1, pt_cor0[ind1 + ( DELTA_COH - 1 ) + len_x] ); - scaledX[i][j + NSECT] = round_fx( L_shl( Ltmp, sub( add( enr1_exp, pt_cor0_exp[ind1 + ( DELTA_COH - 1 ) + len_x] ), 3 ) ) ); // Q12 - move16(); - /*scaledX[i][j+NSECT] = saturate(L_shr(Ltmp, qScaledX-12));*/ - - pt_cor3 += sec_length1[j]; - pt_cor3_exp += sec_length1[j]; - offset1 = add( offset1, sec_length1[j] ); - - } /* FOR j < NSECT */ - } /* FOR i < NHFR */ - - /*-----------------------------------------------------------------* - * Favor a smaller delay if it happens that it has its multiple - * in the longer-delay sections (harmonics check) - *-----------------------------------------------------------------*/ - - FOR( i = 0; i < 2; i++ ) /* loop for the 2 half-frames */ - { - fac = THRES0; - move16(); - find_mult_fx( &fac, pitchX[i][2], pitchX[i][3], pit_max[7], &scaledX[i][2], old_pitch, old_corr, DELTA0, STEP ); /* Multiples in 3rd section */ - find_mult_fx( &fac, pitchX[i][1], pitchX[i][2], pit_max[5], &scaledX[i][1], old_pitch, old_corr, DELTA0, STEP ); /* Multiples in 2nd section */ - test(); - IF( ( sect0 == 0 ) && GE_16( shl( pitchX[i][0], 1 ), pit_min_coding ) ) - { - find_mult_fx( &fac, pitchX[i][0], pitchX[i][1], pit_max[3], &scaledX[i][0], old_pitch, old_corr, DELTA0, STEP ); /* Multiples in 2nd section */ - } - fac = THRES0; - move16(); - find_mult_fx( &fac, pitchX[i][NSECT + 2], pitchX[i][NSECT + 3], pit_max[7], &scaledX[i][NSECT + 2], old_pitch, old_corr, DELTA0, STEP ); /* Multiples in 3rd section */ - find_mult_fx( &fac, pitchX[i][NSECT + 1], pitchX[i][NSECT + 2], pit_max[6], &scaledX[i][NSECT + 1], old_pitch, old_corr, DELTA0, STEP ); /* Multiples in 2nd section */ - test(); - IF( ( sect0 == 0 ) && GE_16( shl( pitchX[i][NSECT + 0], 1 ), pit_min_coding ) ) - { - find_mult_fx( &fac, pitchX[i][NSECT + 0], pitchX[i][NSECT + 1], pit_max[4], &scaledX[i][NSECT + 0], old_pitch, old_corr, DELTA0, STEP ); /* Multiples in 2nd section */ - } - } - - fac = THRES0; - move16(); /* the look-ahead */ - find_mult_fx( &fac, pitchX[i][2], pitchX[i][3], pit_max[7], &scaledX[i][2], old_pitch, old_corr, 2, 2 ); /* Multiples in 3rd section */ - find_mult_fx( &fac, pitchX[i][1], pitchX[i][2], pit_max[5], &scaledX[i][1], old_pitch, old_corr, DELTA0, STEP ); /* Multiples in 2nd section */ - test(); - IF( ( sect0 == 0 ) && GE_16( shl( pitchX[i][0], 1 ), pit_min_coding ) ) - { - find_mult_fx( &fac, pitchX[i][0], pitchX[i][1], pit_max[3], &scaledX[i][0], old_pitch, old_corr, DELTA0, STEP ); /* Multiples in 2nd section */ - } - fac = THRES0; - move16(); - find_mult_fx( &fac, pitchX[i][NSECT + 2], pitchX[i][NSECT + 3], pit_max[7], &scaledX[i][NSECT + 2], old_pitch, old_corr, 2, 2 ); /* Multiples in 3rd section */ - find_mult_fx( &fac, pitchX[i][NSECT + 1], pitchX[i][NSECT + 2], pit_max[6], &scaledX[i][NSECT + 1], old_pitch, old_corr, DELTA0, STEP ); /* Multiples in 2nd section */ - test(); - IF( ( sect0 == 0 ) && GE_16( shl( pitchX[i][NSECT + 0], 1 ), pit_min_coding ) ) - { - find_mult_fx( &fac, pitchX[i][NSECT + 0], pitchX[i][NSECT + 1], pit_max[4], &scaledX[i][NSECT + 0], old_pitch, old_corr, DELTA0, STEP ); /* Multiples in 2nd section */ /* Multiples in 2nd section */ - } - - /*-----------------------------------------------------------------* - * Do 1st estimate for pitch values - * Adjust the normalized correlation using estimated noise level - * Compute the maximum scaling for the neighbour correlation - * reinforcement - *-----------------------------------------------------------------*/ - add_sect0 = add( NSECT, sect0 ); - sub_sect0 = sub( NSECT, sect0 ); - FOR( i = 0; i < NHFR; i++ ) - { - /* 1st set of pitch candidates */ - ind = add( maximum_fx( scaledX[i] + sect0, sub_sect0, &ftmp ), sect0 ); - ind_tmp[i] = ind; - move16(); - pitch_tmp[i] = pitchX[i][ind]; - move16(); - cor_tmp[i] = add_o( corX[i][ind], corr_shift, &Overflow ); - move16(); - - /* Higher is the neighbour's correlation, higher is the weighting */ - /* operands are Q15, result is Q15 */ - thres1[i] = mult( THRES1, cor_tmp[i] ); - move16(); - - /* 2nd set of pitch candidates */ - ind1 = add( maximum_fx( scaledX[i] + add_sect0, sub_sect0, &ftmp ), add_sect0 ); - ind_tmp[i + NHFR] = ind1; - move16(); - pitch_tmp[i + NHFR] = pitchX[i][ind1]; - move16(); - cor_tmp[i + NHFR] = add_o( corX[i][ind1], corr_shift, &Overflow ); - move16(); - - /* Higher is the neighbour's correlation, higher is the weighting */ - /* operands are Q15, result is Q15 */ - thres1[i + NHFR] = mult( THRES1, cor_tmp[i + NHFR] ); - move16(); - } - /*-----------------------------------------------------------------* - * Take into account previous and next pitch values of the present - * frame and look-ahead. Choose the pitch lags and normalize - * correlations for each half-frame & look-ahead - *-----------------------------------------------------------------*/ - - pitch_neighbour_fx( sect0, pitch_tmp, pitchX, cor_tmp, scaledX, thres1, ind_tmp ); - FOR( i = 0; i < NHFR; i++ ) - { - ind = add( maximum_fx( scaledX[i] + sect0, sub_sect0, &ftmp ), sect0 ); - ind_corX = add( maximum_fx( corX[i] + sect0, sub_sect0, &ftmp ), sect0 ); - - ind1 = add( maximum_fx( scaledX[i] + add_sect0, sub_sect0, &ftmp ), add_sect0 ); - ind1_corX = add( maximum_fx( corX[i] + add_sect0, sub_sect0, &ftmp ), add_sect0 ); - - if ( GT_16( scaledX[i][ind1], scaledX[i][ind] ) ) - { - ind = ind1; - move16(); - } - test(); - if ( Opt_SC_VBR && GT_16( corX[i][ind1_corX], corX[i][ind_corX] ) ) - { - ind_corX = ind1_corX; - move16(); - } - test(); - test(); - test(); - IF( Opt_SC_VBR && ( LT_16( mult( pitchX[i][ind], 13107 /*0.4 in Q15*/ ), pitchX[i][ind_corX] ) ) && - ( GT_16( mult( pitchX[i][ind], 19661 /*0.6 in Q15*/ ), pitchX[i][ind_corX] ) ) && - ( GE_16( corX[i][ind_corX], 29491 /*0.9 in Q15*/ ) ) ) - { - pitch[i] = pitchX[i][ind_corX]; - move16(); - voicing[i] = corX[i][ind_corX]; - move16(); - } - ELSE - { - pitch[i] = pitchX[i][ind]; - move16(); - voicing[i] = corX[i][ind]; - move16(); - } - } - - /*-----------------------------------------------------------------* - * Increase the threshold for correlation reinforcement with - * the past if correlation high and pitch stable - *-----------------------------------------------------------------*/ - - /* all Q15 here */ - /* cor_mean = 0.5f * (voicing[0] + voicing[1]) + corr_shift; */ - Ltmp = L_mult( voicing[0], 16384 /*.5 Q15*/ ); - Ltmp = L_mac( Ltmp, voicing[1], 16384 /*.5 Q15*/ ); - cor_mean = round_fx( L_add( Ltmp, corr_shift ) ); - - /* pitch unstable in present frame or from previous frame or normalized correlation too low */ - coh_flag = pitch_coherence_fx( pitch[0], pitch[1], COH_FAC, DELTA_COH ); - move16(); - coh_flag1 = pitch_coherence_fx( pitch[0], *old_pitch, COH_FAC, DELTA_COH ); - move16(); - - test(); - test(); - test(); - IF( ( coh_flag == 0 ) || ( coh_flag1 == 0 ) || ( LT_16( cor_mean, CORR_TH0 ) ) || ( LT_16( relE, THR_relE ) ) ) - { - /* Reset the threshold */ - *old_thres = 0; - move16(); - } - ELSE - { - /* The threshold increase is directly dependent on normalized correlation */ - /* *old_thres += (0.16f * cor_mean); */ - *old_thres = round_fx( L_mac0( L_deposit_h( *old_thres ), 5243 /* 0.16f in Q15 */, cor_mean ) ); // Q14 - move16(); - } - - *old_thres = s_min( *old_thres, 11469 /* 0.7f in Q14 */ ); // Q14 - move16(); - - IF( GT_16( voicing[1], voicing[0] ) ) - { - *old_corr = voicing[1]; - move16(); - } - ELSE - { - *old_corr = cor_mean; - move16(); - } - - /*-----------------------------------------------------------------* - * Extrapolate the pitch value for the next frame by estimating - * the pitch evolution. This value is added to the old_pitch - * in the next frame and is then used when the normalized - * correlation is reinforced by the past estimate - *-----------------------------------------------------------------*/ - tmp_buf[0] = *old_pitch; - move16(); - FOR( i = 0; i < NHFR; i++ ) - { - tmp_buf[i + 1] = pitch[i]; - move16(); - } - - *delta_pit = 0; - move16(); - cnt = 0; - move16(); - - FOR( i = 0; i < NHFR; i++ ) - { - diff = sub( tmp_buf[i + 1], tmp_buf[i] ); - move16(); - coh_flag = pitch_coherence_fx( tmp_buf[i], tmp_buf[i + 1], COH_FAC, DELTA_COH ); - - if ( coh_flag != 0 ) - { - *delta_pit = add( *delta_pit, diff ); - move16(); - } - cnt = add( cnt, coh_flag ); - } - if ( EQ_16( cnt, 2 ) ) - { - /* *delta_pit /= 2; */ - *delta_pit = shr( *delta_pit, 1 ); - move16(); - } - IF( EQ_16( cnt, 3 ) ) - { - k = *delta_pit; - move16(); - /* *delta_pit /= 3; */ - if ( k < 0 ) - { - *delta_pit = mult( *delta_pit, -32768 /*-1 Q15*/ ); - move16(); - } - tmp16 = mult( *delta_pit, 10923 /*1/3 Q15*/ ); - if ( k < 0 ) - { - tmp16 = mult( tmp16, -32768 /*-1 Q15*/ ); - } - *delta_pit = tmp16; - move16(); - } - - /*--------------------------------------------------------------* - * Update old pitch, upsample pitch, - *--------------------------------------------------------------*/ - - *old_pitch = pitch[1]; - move16(); - - FOR( i = 0; i < NHFR; i++ ) - { - /* compensate decimation */ - pitch[i] = i_mult2( pitch[i], OPL_DECIM ); - move16(); - } - - return; -} - - -/*-----------------------------------------------------------------* - * find_mult_fx - * - * Verifies whether max pitch delays in higher sections have multiples - * in lower sections - *-----------------------------------------------------------------*/ -static void find_mult_fx( - Word16 *fac, /* i/o: correlation scaling factor Q12 */ - Word16 pitch0, /* i : pitch of max correlation in the c section */ - Word16 pitch1, /* i : pitch of max correlation in the longer-delay section*/ - Word16 pit_max0, /* i : max pitch delay in the longer-delay section */ - Word16 *corr, /* i/o: max correlation in the shorter-delay section Q12 */ - Word16 *old_pitch, /* i : pitch from previous frame */ - Word16 *old_corr, /* i : max correlation from previous frame */ - Word16 delta, /* i : initial multiples search range */ - Word16 step /* i : increment in range of multiples search */ -) -{ - Word16 pit_min; - Word32 L_tmp; - - pit_min = shl( pitch0, 1 ); /* double the higher section pitch */ - - WHILE( LE_16( pit_min, add( pit_max0, delta ) ) ) /* check for section boundary */ - { - IF( LE_16( abs_s( sub( pit_min, pitch1 ) ), delta ) ) /* if multiple in the allowed range */ - { - L_tmp = L_shl( L_mult( *corr, *fac ), 3 ); - - /* if ( *old_corr < 0.6f || (float)pitch0 > (float)*old_pitch * 0.4f ) */ - IF( s_max( sub( 19660 /*.6 Q15*/, *old_corr ), sub( pitch0, mult( *old_pitch, 13107 /*.4 Q15*/ ) ) ) > 0 ) - { - /* reinforce the normalized correlation */ - /* operands are Q12, result is Q12 */ - *corr = extract_h( L_tmp ); - } - /* operands are Q12, result is Q12 */ - *fac = extract_h( L_shl( L_mult( *fac, THRES0 ), 3 ) ); - } - pit_min = add( pit_min, pitch0 ); /* next multiple */ - delta = add( delta, step ); /* the incertitude to the allowed range */ - } -} - -/*---------------------------------------------------------------------------* - * pitch_neighbour_fx - * - * Verifies if the maximum correlation pitch lag is coherent with neighbour - * values - *---------------------------------------------------------------------------*/ -static void pitch_neighbour_fx( - Word16 sect0, /* i : indicates whether section 0 (below PIT_MIN) is used */ - Word16 pitch_tmp[], /* i : estimated pitch values for each half-frame & look-ahead */ - Word16 pitch[3][2 * NSECT], /* i : tested pitch values for each half-frame & look-ahead */ - Word16 corr_tmp[], /* i : raw normalized correlation (before different scalings) Q15*/ - Word16 corr[3][2 * NSECT], /* i/o: normalized correlation for each half-frame & look-ahead Q12 */ - Word16 thres1[2 * NHFR], /* i : maximum scaling for the immediate neighbours Q15 */ - Word16 ind_tmp[2 * NHFR] /* i : best section index for each half-frame & look-ahead */ -) -{ - Word16 delta, i, j, k, K, coh_flag, fac; - - /*--------------------- - * 1st set of sections - ---------------------*/ - FOR( k = sect0; k < NSECT; k++ ) /* loop for each section */ - { - K = 3; - move16(); - if ( EQ_16( k, ( NSECT - 1 ) ) ) /* the number of tests depends on the section */ - { - K = 2; - move16(); - } - /*pt = &pitch[i][k] and pt = &corr[i][k]*/ - FOR( i = 0; i < K; i++ ) /* for the 2 half-frames and look-ahead */ - { - /* Compare pitch values of the present frame */ - FOR( j = 0; j < K; j++ ) /* Verify pitch coherence with neighbours (including past pitch) */ - { - IF( NE_16( j, i ) ) /* Exclude itself, of course */ - { - IF( GE_16( corr_tmp[j], CORR_TH1 ) ) /* reinforcement can happen only if the correlation is high enough */ - { - delta = abs_s( sub( pitch[i][k], pitch_tmp[j] ) ); /* Find difference of pitch values */ - coh_flag = pitch_coherence_fx( pitch[i][k], pitch_tmp[j], COH_FAC, DELTA_COH ); - - IF( coh_flag != 0 ) - { - /* Favour stability across sections, favour closer values */ - IF( EQ_16( ind_tmp[j], k ) ) - { - /* corr[i][k] *= ( -thres1[j]/DELTA1 * delta + thres1[j]+1 ); */ - /* operands are Q15, except corr[i][k] which is Q12 */ - fac = mult( negate( thres1[j] ), MAX_16 / DELTA_COH ); - fac = add( i_mult2( fac, delta ), thres1[j] ); - } - ELSE - { - /* corr[i][k] *= ( -thres1[j]/DELTA1 * 0.625f * delta + 0.625f * thres1[j] +1.0f ); */ - fac = mult( negate( thres1[j] ), 20479 / DELTA_COH ); - fac = add( i_mult2( fac, delta ), mult( 20479 /*.625 Q15*/, thres1[j] ) ); - } - corr[i][k] = add_sat( corr[i][k], mult( fac, corr[i][k] ) ); - move16(); - } - } - } - } - } - } - - /*--------------------- - * 2nd set of sections - ---------------------*/ - FOR( k = sect0; k < NSECT; k++ ) /* loop for each section */ - { - K = 3; - move16(); - if ( EQ_16( k, ( NSECT - 1 ) ) ) /* the number of tests depends on the section */ - { - K = 2; - move16(); - } - /*pt = &pitch[i][k] and pt = &corr[i][k]*/ - FOR( i = 0; i < K; i++ ) /* BRANCH(1); for the 2 half-frames and look-ahead */ - { - /* Compare pitch values of the present frame */ - FOR( j = 0; j < K; j++ ) /* Verify pitch coherence with neighbours (including past pitch) */ - { - IF( NE_16( j, i ) ) /* Exclude itself, of course */ - { - IF( GE_16( corr_tmp[j + NHFR], CORR_TH1 ) ) /* reinforcement can happen only if the correlation is high enough */ - { - delta = abs_s( sub( pitch[i][NSECT + k], pitch_tmp[j + NHFR] ) ); /* Find difference of pitch values */ - coh_flag = pitch_coherence_fx( pitch[i][NSECT + k], pitch_tmp[j + NHFR], COH_FAC, DELTA_COH ); - - IF( coh_flag != 0 ) - { - /* Favour stability across sections, favour closer values */ - IF( EQ_16( ind_tmp[j + NHFR], add( NSECT, k ) ) ) - { - /* corr[i][k] *= ( -thres1[j+NHFR]/DELTA1 * delta + thres1[j+NHFR]+1 ); */ - /* operands are Q15, except corr[i][NSECT+k] which is Q12 */ - fac = mult( negate( thres1[j + NHFR] ), MAX_16 / DELTA_COH ); - fac = add( extract_l( L_shr( L_mult( fac, delta ), 1 ) ), thres1[j + NHFR] ); - corr[i][NSECT + k] = add_sat( corr[i][NSECT + k], mult( fac, corr[i][NSECT + k] ) ); - move16(); - } - ELSE - { - /* corr[i][k] *= ( -thres1[j+NHFR]/DELTA1 * 0.625f * delta + 0.625f * thres1[j+NHFR] +1.0f ); */ - fac = mult( negate( thres1[j + NHFR] ), 20479 / DELTA_COH ); - fac = add( extract_l( L_shr( L_mult( fac, delta ), 1 ) ), mult( 20479, thres1[j + NHFR] ) ); - corr[i][NSECT + k] = add( corr[i][NSECT + k], mult( fac, corr[i][NSECT + k] ) ); - move16(); - } - } - } - } - } - } - } -} - -/*-----------------------------------------------------------------* - * pitch_coherence_fx - * - * Verify if pitch evolution is smooth - *-----------------------------------------------------------------*/ -static Word16 pitch_coherence_fx( - Word16 pitch0, /* i : first pitch to compare */ - Word16 pitch1, /* i : 2nd pitch to compare */ - Word16 fac_max, /* i : max ratio of both values Q12 */ - Word16 diff_max /* i : max difference of both values */ -) -{ - Word16 smaller, larger; - Word16 pc; - - smaller = s_min( pitch0, pitch1 ); - larger = s_max( pitch0, pitch1 ); - - pc = 0; - move16(); - test(); - if ( ( LE_16( larger, extract_h( L_shl( L_mult( fac_max, smaller ), 3 ) ) ) ) && /* Changed to <= to keep BE */ - ( LT_16( sub( larger, smaller ), diff_max ) ) ) - { - pc = 1; - move16(); - } - - return pc; -} - -/*-----------------------------------------------------------------* - * LP_Decim2_Copy: - * - * Decimate a vector by 2 with 2nd order fir filter. - *-----------------------------------------------------------------*/ -static void LP_Decim2_Copy( - const Word16 x[], /* i: signal to process */ - Word16 y[], /* o: signal to process */ - Word16 l, /* i : size of filtering */ - Word16 mem[] /* i/o: memory (size=3) */ -) -{ - Word16 *p_x, x_buf[L_FRAME + L_MEM]; - Word16 i, j, k; - Word32 L_tmp; - - /* copy initial filter states into buffer */ - p_x = x_buf; - FOR( i = 0; i < L_MEM; i++ ) - { - *p_x++ = mem[i]; - move16(); - } - FOR( i = 0; i < l; i++ ) - { - *p_x++ = x[i]; - move16(); - } - if ( s_and( l, 1 ) ) /* Fix for valgrind error in case l is odd. Anyway this function will be removed. */ - { - *p_x = *( p_x - 1 ); - move16(); - } - - FOR( i = 0; i < L_MEM; i++ ) - { - mem[i] = x[l - L_MEM + i]; - move16(); - } - p_x = x_buf; - j = 0; - move16(); - FOR( i = 0; i < l; i += 2 ) - { - L_tmp = L_mult( *p_x, h_fir_fx[0] ); - FOR( k = 1; k < L_FIR_PO; k++ ) - { - L_tmp = L_mac( L_tmp, p_x[k], h_fir_fx[k] ); - } - p_x += 2; - - y[j++] = round_fx( L_tmp ); - move16(); - } -} -/*---------------------------------------------------------------------* - * Dot_product12_OL - * - * two different length dot products of x and y - *---------------------------------------------------------------------*/ -static Word32 Dot_product12_OL( /* o : Q31: normalized result (1 < val <= -1) */ - Word16 *sum1, /* o : Q31: normalized result 2 */ - const Word16 x[], /* i : 12bits: x vector */ - const Word16 y[], /* i : 12bits: y vector */ - const Word16 lg, /* i : vector length */ - const Word16 lg2, /* i : vector length 2 */ - Word16 *exp, /* o : exponent of result (0..+30) */ - Word16 *exp2 /* o : exponent of result 2 (0..+30) */ -) -{ - Word16 i, sft; - Word32 L_sum, L_sum2; - - L_sum = L_mac( 1, x[0], y[0] ); - IF( LE_16( lg, lg2 ) ) - { - FOR( i = 1; i < lg; i++ ) - { - L_sum = L_mac( L_sum, x[i], y[i] ); - } - /* sets to 'L_sum' in 1 clock */ - L_sum2 = L_sum; - move32(); - FOR( ; i < lg2; i++ ) - { - L_sum2 = L_mac( L_sum2, x[i], y[i] ); - } - } - ELSE - { - FOR( i = 1; i < lg2; i++ ) - { - L_sum = L_mac( L_sum, x[i], y[i] ); - } - /* sets to 'L_sum' in 1 clock */ - L_sum2 = L_sum; - move32(); - FOR( ; i < lg; i++ ) - { - L_sum = L_mac( L_sum, x[i], y[i] ); - } - } - - /* Q31 */ - sft = norm_l( L_sum ); - L_sum = L_shl( L_sum, sft ); - *exp = sub( 30, sft ); - move16(); /* exponent = 0..30 */ - - sft = norm_l( L_sum2 ); - L_sum2 = L_shl( L_sum2, sft ); - *exp2 = sub( 30, sft ); - move16(); /* exponent = 0..30 */ - - *sum1 = extract_h( L_shr( L_sum2, 1 ) ); - move16(); - return L_sum; -} - -/*---------------------------------------------------------------------* - * Dot_product12_OL_back() - * - * two different length dot products of x and y, computed backward - *---------------------------------------------------------------------*/ -static Word32 Dot_product12_OL_back( /* o : Q31: normalized result (1 < val <= -1) */ - Word16 *sum1, /* o : Q31: normalized result 2 */ - const Word16 x[], /* i : 12bits: x vector */ - const Word16 y[], /* i : 12bits: y vector */ - const Word16 lg, /* i : vector length */ - const Word16 lg2, /* i : vector length 2 */ - Word16 *exp, /* o : exponent of result (0..+30) */ - Word16 *exp2 /* o : exponent of result 2 (0..+30) */ -) -{ - Word16 i, sft; - Word32 L_sum, L_sum2; - - L_sum = L_mac( 1, x[0], y[0] ); - IF( LE_16( lg, lg2 ) ) - { - FOR( i = 1; i < lg; i++ ) - { - L_sum = L_mac( L_sum, x[-i], y[-i] ); - } - /* sets to 'L_sum' in 1 clock */ - L_sum2 = L_sum; - move32(); - FOR( ; i < lg2; i++ ) - { - L_sum2 = L_mac( L_sum2, x[-i], y[-i] ); - } - } - ELSE - { - FOR( i = 1; i < lg2; i++ ) - { - L_sum = L_mac( L_sum, x[-i], y[-i] ); - } - /* sets to 'L_sum' in 1 clock */ - L_sum2 = L_sum; - move32(); - FOR( ; i < lg; i++ ) - { - L_sum = L_mac( L_sum, x[-i], y[-i] ); - } - } - - /* Q31 */ - sft = norm_l( L_sum ); - L_sum = L_shl( L_sum, sft ); - *exp = sub( 30, sft ); - move16(); /* exponent = 0..30 */ - - sft = norm_l( L_sum2 ); - L_sum2 = L_shl( L_sum2, sft ); - *exp2 = sub( 30, sft ); - move16(); /* exponent = 0..30 */ - - *sum1 = extract_h( L_shr( L_sum2, 1 ) ); - move16(); - return L_sum; -} - -void pitchDoubling_det_fx( - Word16 *wspeech, - Word16 *pitch_ol, - Word16 *T_op_fr, - Word16 *voicing_fr ) -{ - Word16 new_op_fr[2]; - Word16 new_voicing[2]; - Word16 new_Top[2]; - Word16 m, T; - - - /*save initial values*/ - - new_Top[0] = pitch_ol[0]; - move16(); - new_Top[1] = pitch_ol[1]; - move16(); - - FOR( m = 2; m < 5; m++ ) - { - - /* T= pitch_ol[0]/m; */ - T = mult( pitch_ol[0], One_div_fx[m - 1] ); - - IF( GE_16( T, PIT_MIN_12k8 ) ) - { - pitch_ol2_fx( PIT_MIN_SHORTER, T, &( new_op_fr[0] ), &new_voicing[0], 0, wspeech, 2, EVS_MONO ); - pitch_ol2_fx( PIT_MIN_SHORTER, T, &( new_op_fr[1] ), &new_voicing[1], L_SUBFR, wspeech, 2, EVS_MONO ); - /* IF(sub(add(new_voicing[0],new_voicing[1]),add(voicing_fr[0],voicing_fr[1]))>0 */ - IF( L_msu( L_msu( L_mac( L_mult( new_voicing[0], 8192 ), new_voicing[1], 8192 ), voicing_fr[0], 8192 ), voicing_fr[1], 8192 ) > 0 ) - { - new_Top[0] = T; - move16(); - T_op_fr[0] = new_op_fr[0]; - move16(); - T_op_fr[1] = new_op_fr[1]; - move16(); - voicing_fr[0] = new_voicing[0]; - move16(); - voicing_fr[1] = new_voicing[1]; - move16(); - } - } - - /* T= pitch_ol[1]/m; */ - T = mult( pitch_ol[1], One_div_fx[m - 1] ); - - IF( GE_16( T, PIT_MIN_12k8 ) ) - { - pitch_ol2_fx( PIT_MIN_SHORTER, T, &( new_op_fr[0] ), &new_voicing[0], 2 * L_SUBFR, wspeech, 2, EVS_MONO ); - pitch_ol2_fx( PIT_MIN_SHORTER, T, &( new_op_fr[1] ), &new_voicing[1], 3 * L_SUBFR, wspeech, 2, EVS_MONO ); - /* IF(sub(add(new_voicing[0],new_voicing[1]),add(voicing_fr[2],voicing_fr[3]))>0) */ - IF( L_msu( L_msu( L_mac( L_mult( new_voicing[0], 8192 ), new_voicing[1], 8192 ), voicing_fr[2], 8192 ), voicing_fr[3], 8192 ) > 0 ) - { - new_Top[1] = T; - move16(); - T_op_fr[2] = new_op_fr[0]; - move16(); - T_op_fr[3] = new_op_fr[1]; - move16(); - voicing_fr[2] = new_voicing[0]; - move16(); - voicing_fr[3] = new_voicing[1]; - move16(); - } - } - } - - pitch_ol[0] = new_Top[0]; - move16(); - pitch_ol[1] = new_Top[1]; - move16(); - -} /*end of pitch doubling detection*/ diff --git a/lib_com/options.h b/lib_com/options.h index 632c43d74..e804fe911 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -80,7 +80,7 @@ #define FIX_1978_SAT_MISSING_IN_GAIN_ENC /* VA: Fix add saturation missing that lead to a crash in P800-10 */ #define FIX_1981_MAXIMUM_EXP_FX /* FhG: Fix bug in function to find maximum value in vector */ -//#define PITCH_OL_PRINTIND +#define PITCH_OL_PRINTIND //#define PITCH_OL_PRINTVAL #define FIX_1979_SAT_MISSING_IN_LSF_ENC /* VA: Proposal to fix 1979, saturation in lsf_enc, NOkia to review */ -- GitLab From b00dd119282d7ef95038ae3804edba8d93574a91 Mon Sep 17 00:00:00 2001 From: Fabian Bauer Date: Wed, 3 Sep 2025 09:53:02 +0200 Subject: [PATCH 14/32] deactivate printout --- lib_com/options.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib_com/options.h b/lib_com/options.h index e804fe911..632c43d74 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -80,7 +80,7 @@ #define FIX_1978_SAT_MISSING_IN_GAIN_ENC /* VA: Fix add saturation missing that lead to a crash in P800-10 */ #define FIX_1981_MAXIMUM_EXP_FX /* FhG: Fix bug in function to find maximum value in vector */ -#define PITCH_OL_PRINTIND +//#define PITCH_OL_PRINTIND //#define PITCH_OL_PRINTVAL #define FIX_1979_SAT_MISSING_IN_LSF_ENC /* VA: Proposal to fix 1979, saturation in lsf_enc, NOkia to review */ -- GitLab From 21a39b1baebb0c42ac0bb27499a54d2755591205 Mon Sep 17 00:00:00 2001 From: Fabian Bauer Date: Wed, 3 Sep 2025 10:05:16 +0200 Subject: [PATCH 15/32] clang patch --- lib_com/tools_fx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib_com/tools_fx.c b/lib_com/tools_fx.c index 75c7769d2..ebd06c8a6 100644 --- a/lib_com/tools_fx.c +++ b/lib_com/tools_fx.c @@ -1299,7 +1299,7 @@ Word16 maximum_exp_fx( /* o : index of the maximum value } #endif #ifdef PITCH_OL_PRINTVAL /*value out*/ - printf( "\n val= %15.15f", (float)vec_fx[ind] * pow(2,exp_vec[ind] - 15) ); + printf( "\n val= %15.15f", (float) vec_fx[ind] * pow( 2, exp_vec[ind] - 15 ) ); #endif return ind; -- GitLab From c33d51724d05ad40063595d063053eeeabf39284 Mon Sep 17 00:00:00 2001 From: Fabian Bauer Date: Wed, 3 Sep 2025 12:17:16 +0200 Subject: [PATCH 16/32] cleanup a bit --- lib_com/options.h | 2 -- lib_com/tools_fx.c | 34 ---------------------------------- lib_enc/pitch_ol_fx.c | 12 ------------ 3 files changed, 48 deletions(-) diff --git a/lib_com/options.h b/lib_com/options.h index 632c43d74..017a29936 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -80,8 +80,6 @@ #define FIX_1978_SAT_MISSING_IN_GAIN_ENC /* VA: Fix add saturation missing that lead to a crash in P800-10 */ #define FIX_1981_MAXIMUM_EXP_FX /* FhG: Fix bug in function to find maximum value in vector */ -//#define PITCH_OL_PRINTIND -//#define PITCH_OL_PRINTVAL #define FIX_1979_SAT_MISSING_IN_LSF_ENC /* VA: Proposal to fix 1979, saturation in lsf_enc, NOkia to review */ #define FIX_1946_CRASH_JBM_PROCESSING /* FhG: Increased guard bits of DFT_fx */ diff --git a/lib_com/tools_fx.c b/lib_com/tools_fx.c index ebd06c8a6..70b730c8a 100644 --- a/lib_com/tools_fx.c +++ b/lib_com/tools_fx.c @@ -1235,15 +1235,6 @@ Word16 maximum_exp_fx( /* o : index of the maximum value move16(); #endif -#if 0 - - float vec_float[1024]; - for ( int ii = 0; ii < lvec_fx; ii++ ) - vec_float[ii] = vec_fx[ii] * pow( 2, exp_vec[ii] - 31 ); - -#endif - - #ifdef FIX_1981_MAXIMUM_EXP_FX scale = sub( norm_s( vec_fx[ind] ), 1 ); tmp = shl( vec_fx[ind], scale ); @@ -1265,28 +1256,6 @@ Word16 maximum_exp_fx( /* o : index of the maximum value #else FOR( j = 1; j < lvec_fx; j++ ) { -#if 0 - // insert assert to find critical bitstreams - { - static int calls = 0; - calls++; - Word16 tmp16, tmp16_1; - Word32 tmp32, tmp32_1; - tmp16 = tmp; - tmp32 = L_deposit_l( tmp ); - - tmp16_1 = shr_sat( vec_fx[j] , sub( exp, exp_vec[j] ) ); - tmp32_1 = L_shr_sat( L_deposit_l( vec_fx[j] ), sub( exp, exp_vec[j] ) ); - - if ( ( LT_16( tmp16, tmp16_1 ) != LT_32( tmp32, tmp32_1 ) ) ) - { - tmp16 = LT_16( tmp16, tmp16_1 ); - tmp32 = LT_32( tmp32, tmp32_1 ); - assert( tmp16 == tmp32 ); - } - } -#endif - IF( LT_16( tmp, shr_sat( vec_fx[j], sub( exp, exp_vec[j] ) ) ) ) { ind = j; @@ -1298,9 +1267,6 @@ Word16 maximum_exp_fx( /* o : index of the maximum value } } #endif -#ifdef PITCH_OL_PRINTVAL /*value out*/ - printf( "\n val= %15.15f", (float) vec_fx[ind] * pow( 2, exp_vec[ind] - 15 ) ); -#endif return ind; } diff --git a/lib_enc/pitch_ol_fx.c b/lib_enc/pitch_ol_fx.c index 1fbedcc00..92fd6ee23 100644 --- a/lib_enc/pitch_ol_fx.c +++ b/lib_enc/pitch_ol_fx.c @@ -732,9 +732,6 @@ void pitch_ol_fx( /* 1st set of candidates */ ind = add( maximum_fx( pt_cor1, sec_length[j], &ftmp ), offset ); -#ifdef PITCH_OL_PRINTIND - printf( "\n ind = %d", ind ); -#endif pitchX[i][j] = add( ind, pit_min ); move16(); pt2 = pt1 - pitchX[i][j] + /*-*/ offset_la; /* selected moving vector */ @@ -771,9 +768,6 @@ void pitch_ol_fx( /* 2nd set of candidates */ ind1 = add( maximum_fx( pt_cor3, sec_length1[j], &ftmp ), offset1 ); -#ifdef PITCH_OL_PRINTIND - printf( "\n ind = %d", ind ); -#endif pitchX[i][j + NSECT] = add( ind1, pit_min1 ); move16(); pt4 = pt1 - pitchX[i][j + NSECT] + /*-*/ offset_la1; @@ -1685,9 +1679,6 @@ void pitch_ol_ivas_fx( /* 1st set of candidates */ ind = add( maximum_exp_fx( pt_cor1, pt_cor1_exp, sec_length[j] ), offset ); -#ifdef PITCH_OL_PRINTIND - printf( "\n ind = %d", ind ); -#endif pitchX[i][j] = add( ind, pit_min ); move16(); pt2 = pt1 - pitchX[i][j] + /*-*/ offset_la; /* selected moving vector */ @@ -1730,9 +1721,6 @@ void pitch_ol_ivas_fx( /* 2nd set of candidates */ ind1 = add( maximum_exp_fx( pt_cor3, pt_cor3_exp, sec_length1[j] ), offset1 ); -#ifdef PITCH_OL_PRINTIND - printf( "\n ind = %d", ind ); -#endif pitchX[i][j + NSECT] = add( ind1, pit_min1 ); move16(); pt4 = pt1 - pitchX[i][j + NSECT] + /*-*/ offset_la1; -- GitLab From 101a3cb148123b9ffe5d6f1e1bccaed39d969417 Mon Sep 17 00:00:00 2001 From: Fabian Bauer Date: Wed, 3 Sep 2025 12:26:24 +0200 Subject: [PATCH 17/32] revert changes --- lib_enc/pitch_ol_fx.c | 1 - 1 file changed, 1 deletion(-) diff --git a/lib_enc/pitch_ol_fx.c b/lib_enc/pitch_ol_fx.c index 92fd6ee23..56647f7b1 100644 --- a/lib_enc/pitch_ol_fx.c +++ b/lib_enc/pitch_ol_fx.c @@ -13,7 +13,6 @@ #include "prot_fx.h" /* Function prototypes */ #include "prot_fx_enc.h" /* Function prototypes */ - /*-----------------------------------------------------------------* * Local Constants *-----------------------------------------------------------------*/ -- GitLab From 2df7ea725c24992a1fb2e2dfeaf519353648812f Mon Sep 17 00:00:00 2001 From: Fabian Bauer Date: Wed, 3 Sep 2025 12:38:44 +0200 Subject: [PATCH 18/32] change to easy-readable changes --- lib_com/tools_fx.c | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/lib_com/tools_fx.c b/lib_com/tools_fx.c index 70b730c8a..9ff739356 100644 --- a/lib_com/tools_fx.c +++ b/lib_com/tools_fx.c @@ -1221,52 +1221,41 @@ Word16 maximum_exp_fx( /* o : index of the maximum value ) { Word16 j, ind; -#ifndef FIX_1981_MAXIMUM_EXP_FX Word16 tmp, exp; ind = 0; move16(); +#ifndef FIX_1981_MAXIMUM_EXP_FX tmp = vec_fx[0]; move16(); exp = exp_vec[0]; move16(); #else - Word16 tmp, exp, scale; - ind = 0; - move16(); -#endif + Word16 scale; -#ifdef FIX_1981_MAXIMUM_EXP_FX scale = sub( norm_s( vec_fx[ind] ), 1 ); tmp = shl( vec_fx[ind], scale ); exp = sub( exp_vec[ind], scale ); +#endif FOR( j = 1; j < lvec_fx; j++ ) { - IF( LT_16( tmp, shr_sat( vec_fx[j], sub( exp, exp_vec[j] ) ) ) ) { ind = j; move16(); - +#ifdef FIX_1981_MAXIMUM_EXP_FX scale = sub( norm_s( vec_fx[ind] ), 1 ); tmp = shl( vec_fx[ind], scale ); exp = sub( exp_vec[ind], scale ); - } - } #else - FOR( j = 1; j < lvec_fx; j++ ) - { - IF( LT_16( tmp, shr_sat( vec_fx[j], sub( exp, exp_vec[j] ) ) ) ) - { - ind = j; - move16(); tmp = vec_fx[j]; move16(); exp = exp_vec[j]; move16(); +#endif } } -#endif + return ind; } -- GitLab From 447200ac6f719c19a591805b1bdf424b116f08fc Mon Sep 17 00:00:00 2001 From: Fabian Bauer Date: Wed, 3 Sep 2025 15:06:16 +0200 Subject: [PATCH 19/32] add testing of headroom equality --- lib_com/tools_fx.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/lib_com/tools_fx.c b/lib_com/tools_fx.c index 9ff739356..f0b88d508 100644 --- a/lib_com/tools_fx.c +++ b/lib_com/tools_fx.c @@ -1220,6 +1220,7 @@ Word16 maximum_exp_fx( /* o : index of the maximum value const Word16 lvec_fx /* i : length of input vector */ ) { +//#define TEST_HR Word16 j, ind; Word16 tmp, exp; ind = 0; @@ -1235,10 +1236,26 @@ Word16 maximum_exp_fx( /* o : index of the maximum value scale = sub( norm_s( vec_fx[ind] ), 1 ); tmp = shl( vec_fx[ind], scale ); exp = sub( exp_vec[ind], scale ); +#ifdef TEST_HR + // Insert assert for testing purposes + Word16 nzHR = 33; + if ( vec_fx[0] != 0) + nzHR = norm_s( vec_fx[0] ); +#endif #endif FOR( j = 1; j < lvec_fx; j++ ) { +#ifdef TEST_HR + //Insert assert for testing purposes + if ( vec_fx[j] != 0 ) + { + if ( nzHR != 33 ) + assert( norm_s( vec_fx[j] ) == nzHR ); + + nzHR = norm_s( vec_fx[0] ); + } +#endif IF( LT_16( tmp, shr_sat( vec_fx[j], sub( exp, exp_vec[j] ) ) ) ) { ind = j; -- GitLab From e043963a563646c78749f808d210830a4ad40719 Mon Sep 17 00:00:00 2001 From: Fabian Bauer Date: Wed, 3 Sep 2025 15:06:45 +0200 Subject: [PATCH 20/32] remove testing of headroom equality --- lib_com/tools_fx.c | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/lib_com/tools_fx.c b/lib_com/tools_fx.c index f0b88d508..9ff739356 100644 --- a/lib_com/tools_fx.c +++ b/lib_com/tools_fx.c @@ -1220,7 +1220,6 @@ Word16 maximum_exp_fx( /* o : index of the maximum value const Word16 lvec_fx /* i : length of input vector */ ) { -//#define TEST_HR Word16 j, ind; Word16 tmp, exp; ind = 0; @@ -1236,26 +1235,10 @@ Word16 maximum_exp_fx( /* o : index of the maximum value scale = sub( norm_s( vec_fx[ind] ), 1 ); tmp = shl( vec_fx[ind], scale ); exp = sub( exp_vec[ind], scale ); -#ifdef TEST_HR - // Insert assert for testing purposes - Word16 nzHR = 33; - if ( vec_fx[0] != 0) - nzHR = norm_s( vec_fx[0] ); -#endif #endif FOR( j = 1; j < lvec_fx; j++ ) { -#ifdef TEST_HR - //Insert assert for testing purposes - if ( vec_fx[j] != 0 ) - { - if ( nzHR != 33 ) - assert( norm_s( vec_fx[j] ) == nzHR ); - - nzHR = norm_s( vec_fx[0] ); - } -#endif IF( LT_16( tmp, shr_sat( vec_fx[j], sub( exp, exp_vec[j] ) ) ) ) { ind = j; -- GitLab From b13f5d519d0834690009883e77357021d567c8b1 Mon Sep 17 00:00:00 2001 From: Fabian Bauer Date: Wed, 3 Sep 2025 15:19:54 +0200 Subject: [PATCH 21/32] add new fix: cheaper --- lib_com/tools_fx.c | 56 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 47 insertions(+), 9 deletions(-) diff --git a/lib_com/tools_fx.c b/lib_com/tools_fx.c index 9ff739356..ab3800669 100644 --- a/lib_com/tools_fx.c +++ b/lib_com/tools_fx.c @@ -1219,23 +1219,17 @@ Word16 maximum_exp_fx( /* o : index of the maximum value const Word16 *exp_vec, /* i : exponents of input vector */ const Word16 lvec_fx /* i : length of input vector */ ) +#ifdef FIX_1981_MAXIMUM_EXP_FX_ { Word16 j, ind; Word16 tmp, exp; ind = 0; move16(); -#ifndef FIX_1981_MAXIMUM_EXP_FX - tmp = vec_fx[0]; - move16(); - exp = exp_vec[0]; - move16(); -#else Word16 scale; scale = sub( norm_s( vec_fx[ind] ), 1 ); tmp = shl( vec_fx[ind], scale ); exp = sub( exp_vec[ind], scale ); -#endif FOR( j = 1; j < lvec_fx; j++ ) { @@ -1243,22 +1237,66 @@ Word16 maximum_exp_fx( /* o : index of the maximum value { ind = j; move16(); -#ifdef FIX_1981_MAXIMUM_EXP_FX scale = sub( norm_s( vec_fx[ind] ), 1 ); tmp = shl( vec_fx[ind], scale ); exp = sub( exp_vec[ind], scale ); + } + } + + + return ind; +} +#elif 1 +{ + Word16 j, ind; + Word16 tmp, exp; + ind = 0; + move16(); + tmp = vec_fx[0]; + move16(); + exp = exp_vec[0]; + move16(); + + FOR( j = 1; j < lvec_fx; j++ ) + { + if( LT_32( L_deposit_l(vec_fx[ind]), L_shr_sat( L_deposit_l(vec_fx[j]), sub( exp_vec[ind], exp_vec[j] ) ) ) ) + { + ind = j; + move16(); + } + } + + + return ind; +} #else +{ + Word16 j, ind; + Word16 tmp, exp; + ind = 0; + move16(); + tmp = vec_fx[0]; + move16(); + exp = exp_vec[0]; + move16(); + + FOR( j = 1; j < lvec_fx; j++ ) + { + IF( LT_16( tmp, shr_sat( vec_fx[j], sub( exp, exp_vec[j] ) ) ) ) + { + ind = j; + move16(); tmp = vec_fx[j]; move16(); exp = exp_vec[j]; move16(); -#endif } } return ind; } +#endif /*---------------------------------------------------------------------* * maximum_abs_16_fx() -- GitLab From fd1c02f047a3b7f520189e35d765194d8d59bd8b Mon Sep 17 00:00:00 2001 From: Fabian Bauer Date: Wed, 3 Sep 2025 15:39:12 +0200 Subject: [PATCH 22/32] clang patch --- lib_com/tools_fx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib_com/tools_fx.c b/lib_com/tools_fx.c index ab3800669..724d23e87 100644 --- a/lib_com/tools_fx.c +++ b/lib_com/tools_fx.c @@ -1259,7 +1259,7 @@ Word16 maximum_exp_fx( /* o : index of the maximum value FOR( j = 1; j < lvec_fx; j++ ) { - if( LT_32( L_deposit_l(vec_fx[ind]), L_shr_sat( L_deposit_l(vec_fx[j]), sub( exp_vec[ind], exp_vec[j] ) ) ) ) + if ( LT_32( L_deposit_l( vec_fx[ind] ), L_shr_sat( L_deposit_l( vec_fx[j] ), sub( exp_vec[ind], exp_vec[j] ) ) ) ) { ind = j; move16(); -- GitLab From 053cf80adf91ecec004a6bc56eb1be3f775b9ed1 Mon Sep 17 00:00:00 2001 From: Fabian Bauer Date: Wed, 3 Sep 2025 15:51:22 +0200 Subject: [PATCH 23/32] warnings --- lib_com/tools_fx.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/lib_com/tools_fx.c b/lib_com/tools_fx.c index 724d23e87..bfbcb6978 100644 --- a/lib_com/tools_fx.c +++ b/lib_com/tools_fx.c @@ -1249,13 +1249,8 @@ Word16 maximum_exp_fx( /* o : index of the maximum value #elif 1 { Word16 j, ind; - Word16 tmp, exp; ind = 0; move16(); - tmp = vec_fx[0]; - move16(); - exp = exp_vec[0]; - move16(); FOR( j = 1; j < lvec_fx; j++ ) { -- GitLab From a86643032127a10df170833ccf6b62be00f87348 Mon Sep 17 00:00:00 2001 From: Fabian Bauer Date: Thu, 4 Sep 2025 10:39:27 +0200 Subject: [PATCH 24/32] added faster method --- lib_com/tools_fx.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/lib_com/tools_fx.c b/lib_com/tools_fx.c index bfbcb6978..6ad434d85 100644 --- a/lib_com/tools_fx.c +++ b/lib_com/tools_fx.c @@ -1230,6 +1230,11 @@ Word16 maximum_exp_fx( /* o : index of the maximum value scale = sub( norm_s( vec_fx[ind] ), 1 ); tmp = shl( vec_fx[ind], scale ); exp = sub( exp_vec[ind], scale ); +#if 1 + static int cnt = 0; + cnt++; +#endif + FOR( j = 1; j < lvec_fx; j++ ) { @@ -1243,7 +1248,7 @@ Word16 maximum_exp_fx( /* o : index of the maximum value } } - + //printf( "\nind = %d", ind ); return ind; } #elif 1 @@ -1251,17 +1256,29 @@ Word16 maximum_exp_fx( /* o : index of the maximum value Word16 j, ind; ind = 0; move16(); +#if 1 + static int cnt = 0; + cnt++; +#endif + FOR( j = 1; j < lvec_fx; j++ ) { +#if 0 if ( LT_32( L_deposit_l( vec_fx[ind] ), L_shr_sat( L_deposit_l( vec_fx[j] ), sub( exp_vec[ind], exp_vec[j] ) ) ) ) +#else + /* if(vec[j] > vec[ind]) //means */ + /* if( GT_32( L_shr_sat( L_deposit_l( vec_fx[j] ) ), sub( exp_vec[ind], exp_vec[j] ) , L_deposit_l( vec_fx[ind] ))) //is like */ + if ( L_mac0_sat( L_shr_sat( L_mult0( vec_fx[j], 0x0001 ), sub( exp_vec[ind], exp_vec[j] ) ), vec_fx[ind], -0x0001 ) > 0 ) +#endif { ind = j; move16(); } - } + } + //printf( "\n%d:ind = %d", cnt, ind ); return ind; } #else @@ -1288,7 +1305,7 @@ Word16 maximum_exp_fx( /* o : index of the maximum value } } - + // printf( "\nind = %d", ind ); return ind; } #endif -- GitLab From 1aed62ee193cf8a2d32241b8db0b44dcfc5f2f89 Mon Sep 17 00:00:00 2001 From: Fabian Bauer Date: Thu, 4 Sep 2025 11:50:56 +0200 Subject: [PATCH 25/32] clang patch --- lib_com/tools_fx.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/lib_com/tools_fx.c b/lib_com/tools_fx.c index 6ad434d85..901933032 100644 --- a/lib_com/tools_fx.c +++ b/lib_com/tools_fx.c @@ -1248,7 +1248,7 @@ Word16 maximum_exp_fx( /* o : index of the maximum value } } - //printf( "\nind = %d", ind ); + // printf( "\nind = %d", ind ); return ind; } #elif 1 @@ -1275,10 +1275,9 @@ Word16 maximum_exp_fx( /* o : index of the maximum value ind = j; move16(); } + } - } - - //printf( "\n%d:ind = %d", cnt, ind ); + // printf( "\n%d:ind = %d", cnt, ind ); return ind; } #else -- GitLab From d09772da6d9cb3ac28bf22652b100d1506a1256d Mon Sep 17 00:00:00 2001 From: Fabian Bauer Date: Thu, 4 Sep 2025 11:52:07 +0200 Subject: [PATCH 26/32] easy to read --- lib_com/tools_fx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib_com/tools_fx.c b/lib_com/tools_fx.c index 901933032..5d7f2e457 100644 --- a/lib_com/tools_fx.c +++ b/lib_com/tools_fx.c @@ -1268,8 +1268,8 @@ Word16 maximum_exp_fx( /* o : index of the maximum value if ( LT_32( L_deposit_l( vec_fx[ind] ), L_shr_sat( L_deposit_l( vec_fx[j] ), sub( exp_vec[ind], exp_vec[j] ) ) ) ) #else /* if(vec[j] > vec[ind]) //means */ - /* if( GT_32( L_shr_sat( L_deposit_l( vec_fx[j] ) ), sub( exp_vec[ind], exp_vec[j] ) , L_deposit_l( vec_fx[ind] ))) //is like */ - if ( L_mac0_sat( L_shr_sat( L_mult0( vec_fx[j], 0x0001 ), sub( exp_vec[ind], exp_vec[j] ) ), vec_fx[ind], -0x0001 ) > 0 ) + /* if( GT_32( L_shr_sat( L_deposit_l( vec_fx[j])), sub( exp_vec[ind], exp_vec[j] ) , L_deposit_l( vec_fx[ind] ))) //is like */ + if ( L_mac0_sat( L_shl_sat( L_deposit_l( vec_fx[j] ), sub( exp_vec[j] , exp_vec[ind] ) ), vec_fx[ind], -0x0001 ) > 0 ) #endif { ind = j; -- GitLab From efffa44d2487959d19a17d7d0450c7660494abc6 Mon Sep 17 00:00:00 2001 From: Fabian Bauer Date: Thu, 4 Sep 2025 12:18:28 +0200 Subject: [PATCH 27/32] clang patch --- lib_com/tools_fx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib_com/tools_fx.c b/lib_com/tools_fx.c index 5d7f2e457..f8a203b72 100644 --- a/lib_com/tools_fx.c +++ b/lib_com/tools_fx.c @@ -1269,7 +1269,7 @@ Word16 maximum_exp_fx( /* o : index of the maximum value #else /* if(vec[j] > vec[ind]) //means */ /* if( GT_32( L_shr_sat( L_deposit_l( vec_fx[j])), sub( exp_vec[ind], exp_vec[j] ) , L_deposit_l( vec_fx[ind] ))) //is like */ - if ( L_mac0_sat( L_shl_sat( L_deposit_l( vec_fx[j] ), sub( exp_vec[j] , exp_vec[ind] ) ), vec_fx[ind], -0x0001 ) > 0 ) + if ( L_mac0_sat( L_shl_sat( L_deposit_l( vec_fx[j] ), sub( exp_vec[j], exp_vec[ind] ) ), vec_fx[ind], -0x0001 ) > 0 ) #endif { ind = j; -- GitLab From f7f2cae13b6d438c42aca0ecce512691222aae54 Mon Sep 17 00:00:00 2001 From: Fabian Bauer Date: Thu, 4 Sep 2025 13:57:43 +0200 Subject: [PATCH 28/32] add another assert to test 0 values --- lib_com/tools_fx.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib_com/tools_fx.c b/lib_com/tools_fx.c index f8a203b72..1eda86ab3 100644 --- a/lib_com/tools_fx.c +++ b/lib_com/tools_fx.c @@ -1264,7 +1264,13 @@ Word16 maximum_exp_fx( /* o : index of the maximum value FOR( j = 1; j < lvec_fx; j++ ) { -#if 0 + #if 1 + if ( ( vec_fx[j] == 0 && vec_fx[j - 1] != 0 && vec_fx[j+1] != 0 && lvec_fx > j )) + { + assert(0); + } + #endif +#if 1 if ( LT_32( L_deposit_l( vec_fx[ind] ), L_shr_sat( L_deposit_l( vec_fx[j] ), sub( exp_vec[ind], exp_vec[j] ) ) ) ) #else /* if(vec[j] > vec[ind]) //means */ -- GitLab From e3cbe3f9782f54076c1aab46e99c2ded6087da93 Mon Sep 17 00:00:00 2001 From: Fabian Bauer Date: Thu, 4 Sep 2025 14:03:50 +0200 Subject: [PATCH 29/32] clang patch --- lib_com/tools_fx.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib_com/tools_fx.c b/lib_com/tools_fx.c index 1eda86ab3..bfa2653de 100644 --- a/lib_com/tools_fx.c +++ b/lib_com/tools_fx.c @@ -1264,12 +1264,12 @@ Word16 maximum_exp_fx( /* o : index of the maximum value FOR( j = 1; j < lvec_fx; j++ ) { - #if 1 - if ( ( vec_fx[j] == 0 && vec_fx[j - 1] != 0 && vec_fx[j+1] != 0 && lvec_fx > j )) +#if 1 + if ( ( vec_fx[j] == 0 && vec_fx[j - 1] != 0 && vec_fx[j + 1] != 0 && lvec_fx > j ) ) { - assert(0); + assert( 0 ); } - #endif +#endif #if 1 if ( LT_32( L_deposit_l( vec_fx[ind] ), L_shr_sat( L_deposit_l( vec_fx[j] ), sub( exp_vec[ind], exp_vec[j] ) ) ) ) #else -- GitLab From fd254bdf133369424cdbb9d99866958741badca2 Mon Sep 17 00:00:00 2001 From: Fabian Bauer Date: Thu, 4 Sep 2025 14:33:41 +0200 Subject: [PATCH 30/32] deactivate last assert --- lib_com/tools_fx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib_com/tools_fx.c b/lib_com/tools_fx.c index bfa2653de..2fd628797 100644 --- a/lib_com/tools_fx.c +++ b/lib_com/tools_fx.c @@ -1264,7 +1264,7 @@ Word16 maximum_exp_fx( /* o : index of the maximum value FOR( j = 1; j < lvec_fx; j++ ) { -#if 1 +#if 0 if ( ( vec_fx[j] == 0 && vec_fx[j - 1] != 0 && vec_fx[j + 1] != 0 && lvec_fx > j ) ) { assert( 0 ); -- GitLab From f8ae606e9542dbd078e759b2e907e38d8490cfa1 Mon Sep 17 00:00:00 2001 From: Fabian Bauer Date: Thu, 4 Sep 2025 16:11:31 +0200 Subject: [PATCH 31/32] current best solution --- lib_com/tools_fx.c | 50 +--------------------------------------------- 1 file changed, 1 insertion(+), 49 deletions(-) diff --git a/lib_com/tools_fx.c b/lib_com/tools_fx.c index 2fd628797..778aa68b4 100644 --- a/lib_com/tools_fx.c +++ b/lib_com/tools_fx.c @@ -1219,71 +1219,23 @@ Word16 maximum_exp_fx( /* o : index of the maximum value const Word16 *exp_vec, /* i : exponents of input vector */ const Word16 lvec_fx /* i : length of input vector */ ) -#ifdef FIX_1981_MAXIMUM_EXP_FX_ +#ifdef FIX_1981_MAXIMUM_EXP_FX { Word16 j, ind; - Word16 tmp, exp; ind = 0; move16(); - Word16 scale; - - scale = sub( norm_s( vec_fx[ind] ), 1 ); - tmp = shl( vec_fx[ind], scale ); - exp = sub( exp_vec[ind], scale ); -#if 1 - static int cnt = 0; - cnt++; -#endif - FOR( j = 1; j < lvec_fx; j++ ) { - IF( LT_16( tmp, shr_sat( vec_fx[j], sub( exp, exp_vec[j] ) ) ) ) - { - ind = j; - move16(); - scale = sub( norm_s( vec_fx[ind] ), 1 ); - tmp = shl( vec_fx[ind], scale ); - exp = sub( exp_vec[ind], scale ); - } - } - - // printf( "\nind = %d", ind ); - return ind; -} -#elif 1 -{ - Word16 j, ind; - ind = 0; - move16(); -#if 1 - static int cnt = 0; - cnt++; -#endif - - - FOR( j = 1; j < lvec_fx; j++ ) - { -#if 0 - if ( ( vec_fx[j] == 0 && vec_fx[j - 1] != 0 && vec_fx[j + 1] != 0 && lvec_fx > j ) ) - { - assert( 0 ); - } -#endif -#if 1 - if ( LT_32( L_deposit_l( vec_fx[ind] ), L_shr_sat( L_deposit_l( vec_fx[j] ), sub( exp_vec[ind], exp_vec[j] ) ) ) ) -#else /* if(vec[j] > vec[ind]) //means */ /* if( GT_32( L_shr_sat( L_deposit_l( vec_fx[j])), sub( exp_vec[ind], exp_vec[j] ) , L_deposit_l( vec_fx[ind] ))) //is like */ if ( L_mac0_sat( L_shl_sat( L_deposit_l( vec_fx[j] ), sub( exp_vec[j], exp_vec[ind] ) ), vec_fx[ind], -0x0001 ) > 0 ) -#endif { ind = j; move16(); } } - // printf( "\n%d:ind = %d", cnt, ind ); return ind; } #else -- GitLab From df1a70d163562ef91d74d04f567c23ad9ec095ee Mon Sep 17 00:00:00 2001 From: Fabian Bauer Date: Thu, 4 Sep 2025 16:14:50 +0200 Subject: [PATCH 32/32] cosmetics --- lib_com/tools_fx.c | 1 - 1 file changed, 1 deletion(-) diff --git a/lib_com/tools_fx.c b/lib_com/tools_fx.c index 778aa68b4..4dd405b24 100644 --- a/lib_com/tools_fx.c +++ b/lib_com/tools_fx.c @@ -1262,7 +1262,6 @@ Word16 maximum_exp_fx( /* o : index of the maximum value } } - // printf( "\nind = %d", ind ); return ind; } #endif -- GitLab