From b2c8c341fc06d2e5495fbb2dcd46780e8f5d6164 Mon Sep 17 00:00:00 2001 From: Sandesh Venkatesh Date: Wed, 7 Aug 2024 22:54:49 +0530 Subject: [PATCH] Fixed point changes for 3gpp issue 764 floating point changes [x] LFE PLC functions changed from double to float precision. Corresponding fixed point changes are implemented in this commit. --- lib_com/cnst.h | 6 + lib_com/ivas_cnst.h | 4 + lib_com/ivas_prot.h | 15 +- lib_com/ivas_rom_com.c | 23 ++- lib_com/ivas_rom_com.h | 4 + lib_com/lpc_tools.c | 2 +- lib_com/lsf_tools.c | 19 +- lib_com/options.h | 2 +- lib_com/prot.h | 5 + lib_dec/ivas_lfe_plc.c | 212 +++++++++++++++++++-- lib_dec/ivas_lfe_plc_fx.c | 382 ++++++++++++++++++++++++++++++++++++-- lib_enc/ivas_lfe_enc.c | 4 + 12 files changed, 636 insertions(+), 42 deletions(-) diff --git a/lib_com/cnst.h b/lib_com/cnst.h index c55628603..50f851427 100644 --- a/lib_com/cnst.h +++ b/lib_com/cnst.h @@ -719,6 +719,9 @@ enum #define L_SUBFR16k ( L_FRAME16k / NB_SUBFR ) /* subframe size at 16kHz */ #define L_HALFR16k ( 2 * L_SUBFR16k ) /* half-frame size at 16kHz */ +#ifdef NONE_BE_FIX_816_LFE_PLC_FLOAT +#define MAX_LP_FILTER_ORDER 20 /* Max order of an LP filter */ +#endif #define L_INTERPOL2 16 /* Length of filter for interpolation */ #define L_INTERPOL ( L_INTERPOL2 + 1 ) /* Length of filter for interpolation */ #define TILT_FAC 0.68f /* tilt factor (denominator) */ @@ -773,6 +776,9 @@ enum #define L_FILT_2OVER3 12 #define L_FILT_2OVER3_LP 3 +#ifdef NONE_BE_FIX_816_LFE_PLC_FLOAT +#define MAX_LP_FILTER_ORDER 20 /* Max order of an LP filter */ +#endif typedef enum { diff --git a/lib_com/ivas_cnst.h b/lib_com/ivas_cnst.h index 87efbcaf9..d6ac3843e 100644 --- a/lib_com/ivas_cnst.h +++ b/lib_com/ivas_cnst.h @@ -1592,7 +1592,11 @@ typedef enum /* LFE PLC */ #define LFE_PLC_BUFLEN 240 #define LFE_PLC_FS 1600 +#ifdef NONE_BE_FIX_816_LFE_PLC_FLOAT +#define L_FRAME_1k6 ( LFE_PLC_FS / FRAMES_PER_SEC ) +#else #define L_FRAME_1k6 ( 20 * LFE_PLC_FS / 1000 ) +#endif #define LFE_PLC_LENANA LFE_PLC_BUFLEN #define LFE_PLC_FDEL 300 diff --git a/lib_com/ivas_prot.h b/lib_com/ivas_prot.h index 1ef5879dc..1f22a9355 100644 --- a/lib_com/ivas_prot.h +++ b/lib_com/ivas_prot.h @@ -7559,13 +7559,16 @@ void ivas_lfe_dec( float output_lfe_ch[] /* o : output LFE synthesis */ ); #endif -void ivas_lfe_tdplc( - LFE_DEC_HANDLE hLFE, /* i/o: LFE decoder handle */ - const float *prevsynth, /* i : previous frame synthesis */ - float *ytda, /* o : output time-domain buffer */ - const int16_t output_frame /* i : output frame length */ +void ivas_lfe_tdplc( + LFE_DEC_HANDLE hLFE, /* i/o: LFE decoder handle */ +#ifdef NONE_BE_FIX_816_LFE_PLC_FLOAT + float *prevsynth, /* i : previous frame synthesis */ +#else + double *prevsynth, /* i : previous frame synthesis */ +#endif + float *ytda, /* o : output time-domain buffer */ + const int16_t output_frame /* i : output frame length */ ); - void ivas_lfe_window_init( LFE_WINDOW_HANDLE hLFEWindow, /* i/o: LFE window handle */ const int32_t sampling_rate, /* i : sampling rate */ diff --git a/lib_com/ivas_rom_com.c b/lib_com/ivas_rom_com.c index 8733ad0bd..1cda9e51e 100644 --- a/lib_com/ivas_rom_com.c +++ b/lib_com/ivas_rom_com.c @@ -3530,7 +3530,26 @@ const int16_t ivas_lfe_min_shift_tbl[IVAS_LFE_NUM_COEFFS_IN_SUBGRP] = { 1, 0 }; const float ivas_lfe_lpf_delay[2] = { 0.00175f, 0.0035f }; const Word16 ivas_lfe_lpf_delay_Q15[2] = { 57, 114 }; - +#ifdef NONE_BE_FIX_816_LFE_PLC_FLOAT +const float hamm_lfe_plc[LFE_PLC_LENANA / 2] = +{ + 0.08000000000000002f, 0.08015895227847719f, 0.08063569926248770f, 0.08142991147368656f, 0.08254104003450596f, 0.08396831704748331f, 0.08571075612595230f, 0.08776715307573196f, + 0.09013608672734141f, 0.09281591991816535f, 0.09580480062389246f, 0.09910066323844335f, 0.10270123000150438f, 0.10660401257268071f, 0.11080631375118072f, 0.11530522933984272f, + 0.12009765015221685f, 0.12518026416131367f, 0.13054955878853602f, 0.13620182333121073f, 0.14213315152704381f, 0.14833944425372619f, 0.15481641236182375f, 0.16155957963899570f, + 0.16856428590349043f, 0.17582569022478273f, 0.18333877426912554f, 0.19109834576770490f, 0.19909904210500018f, 0.20733533402487142f, 0.21580152945181053f, 0.22449177742471671f, + 0.23340007214047787f, 0.24252025710456171f, 0.25184602938575001f, 0.26137094397207467f, 0.27108841822494550f, 0.28099173642839037f, 0.29107405443026624f, 0.30132840437223085f, + 0.31174769950520753f, 0.32232473908701620f, 0.33305221335878232f, 0.34392270859668939f, 0.35492871223557998f, 0.36606261806086549f, 0.37731673146515798f, 0.38868327476598852f, + 0.40015439258093899f, 0.41172215725647360f, 0.42337857434671339f, 0.43511558813837425f, 0.44692508721804453f, 0.45879891007795709f, 0.47072885075638249f, 0.48270666450874267f, + 0.49472407350552849f, 0.50677277255308162f, 0.51884443483328757f, 0.53093071765821398f, 0.54302326823571601f, 0.55511372944202464f, 0.56719374559732838f, 0.57925496824035816f, + 0.59128906189798180f, 0.60328770984582458f, 0.61524261985593010f, 0.62714552992749328f, 0.63898821399670414f, 0.65076248762175315f, 0.66246021363907504f, 0.67407330778691554f, + 0.68559374429233988f, 0.69701356141781945f, 0.70832486696356345f, 0.71951984372179334f, 0.73059075487919101f, 0.74152994936378558f, 0.75232986713258543f, 0.76298304439630038f, + 0.77348211877754336f, 0.78381983439894576f, 0.79398904689767136f, 0.80398272836286389f, 0.81379397219261318f, 0.82341599786708708f, 0.83284215563452701f, 0.84206593110687011f, + 0.85108094976182280f, 0.85988098134827329f, 0.86845994419199846f, 0.87681190939868969f, 0.88493110495139349f, 0.89281191969953333f, 0.90044890723675941f, 0.90783678966494241f, + 0.91497046124171255f, 0.92184499190902180f, 0.92845563070029180f, 0.93479780902379184f, 0.94086714381997805f, 0.94665944059061280f, 0.95217069629756890f, 0.95739710212931617f, + 0.96233504613317988f, 0.96698111571154954f, 0.97133209998031445f, 0.97538499198789563f, 0.97913699079334116f, 0.98258550340204664f, 0.98572814655776630f, 0.98856274838967395f, + 0.99108734991333569f, 0.99330020638455863f, 0.99519978850517732f, 0.99678478347994692f, 0.99805409592381300f, 0.99900684861892730f, 0.99964238312089115f, 0.99996026021380402f +}; +#else const double d_hamm_lfe_plc[LFE_PLC_LENANA / 2] = { 0.08000000000000002, 0.08015895227847719, 0.08063569926248770, 0.08142991147368656, 0.08254104003450596, 0.08396831704748331, 0.08571075612595230, 0.08776715307573196, @@ -3549,7 +3568,7 @@ const double d_hamm_lfe_plc[LFE_PLC_LENANA / 2] = 0.96233504613317988, 0.96698111571154954, 0.97133209998031445, 0.97538499198789563, 0.97913699079334116, 0.98258550340204664, 0.98572814655776630, 0.98856274838967395, 0.99108734991333569, 0.99330020638455863, 0.99519978850517732, 0.99678478347994692, 0.99805409592381300, 0.99900684861892730, 0.99964238312089115, 0.99996026021380402 }; - +#endif /*------------------------------------------------------------------------------------------* * MDFT/iMDFT ROM tables *------------------------------------------------------------------------------------------*/ diff --git a/lib_com/ivas_rom_com.h b/lib_com/ivas_rom_com.h index a89745452..6c1f30646 100644 --- a/lib_com/ivas_rom_com.h +++ b/lib_com/ivas_rom_com.h @@ -380,7 +380,11 @@ extern const int16_t ivas_lfe_min_shift_tbl[IVAS_LFE_NUM_COEFFS_IN_SUBGRP]; extern const ivas_lfe_freq_models ivas_str_lfe_freq_models; extern const float ivas_lfe_lpf_delay[2]; extern const Word16 ivas_lfe_lpf_delay_Q15[2]; +#ifdef NONE_BE_FIX_816_LFE_PLC_FLOAT +extern const float hamm_lfe_plc[LFE_PLC_LENANA / 2]; +#else extern const double d_hamm_lfe_plc[LFE_PLC_LENANA / 2]; +#endif extern const float ivas_sin_twiddle_480[IVAS_480_PT_LEN >> 1]; extern const float ivas_cos_twiddle_480[IVAS_480_PT_LEN >> 1]; extern const float ivas_sin_twiddle_320[IVAS_320_PT_LEN >> 1]; diff --git a/lib_com/lpc_tools.c b/lib_com/lpc_tools.c index ff6dfea48..d3635d286 100644 --- a/lib_com/lpc_tools.c +++ b/lib_com/lpc_tools.c @@ -129,7 +129,7 @@ void autocorr( * of input signal *---------------------------------------------------------------------*/ -/*! r: energy of prediction error */ +/*! r: stability flag */ int16_t lev_dur( float *a, /* o : LP coefficients (a[0] = 1.0) */ const float *r, /* i : vector of autocorrelations */ diff --git a/lib_com/lsf_tools.c b/lib_com/lsf_tools.c index 4a6b5c2a6..34a0e6f89 100644 --- a/lib_com/lsf_tools.c +++ b/lib_com/lsf_tools.c @@ -949,13 +949,22 @@ void isp2isf( * Convert from LPC to reflection coeff *-------------------------------------------------------------------*/ +#ifndef NONE_BE_FIX_816_LFE_PLC_FLOAT void a2rc( +#else +/*! r: stability flag */ +uint16_t a2rc( +#endif const float *a, /* i : LPC coefficients */ float *refl, /* o : Reflection co-efficients */ const int16_t lpcorder /* i : LPC order */ ) { +#ifndef NONE_BE_FIX_816_LFE_PLC_FLOAT float f[M]; +#else + float f[MAX_LP_FILTER_ORDER]; +#endif int16_t m, j, n; float km, denom, x; @@ -974,8 +983,11 @@ void a2rc( { refl[j] = 0.f; } - +#ifndef NONE_BE_FIX_816_LFE_PLC_FLOAT return; +#else + return 0; +#endif } refl[m] = -km; @@ -994,8 +1006,11 @@ void a2rc( f[j] = denom * f[j] + km * denom * f[j]; } } - +#ifndef NONE_BE_FIX_816_LFE_PLC_FLOAT return; +#else + return 1; +#endif } diff --git a/lib_com/options.h b/lib_com/options.h index ab59819f7..134412481 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -157,7 +157,7 @@ #ifdef FIX_826_PRECISION_LOST_AND_COMPL #define FIX_833_CORRECTION_to_826 /* VA : fix indexing error introduced in 826 */ #endif - +#define NONE_BE_FIX_816_LFE_PLC_FLOAT /* DLB: issue 816: reduce required precision to float for LFE-PLC*/ /* ################## End DEVELOPMENT switches ######################### */ /* clang-format on */ diff --git a/lib_com/prot.h b/lib_com/prot.h index 05ffc64e7..13b0042da 100644 --- a/lib_com/prot.h +++ b/lib_com/prot.h @@ -3022,7 +3022,12 @@ void a2isf( const float *old_isf, const int16_t lpcOrder ); +#ifndef NONE_BE_FIX_816_LFE_PLC_FLOAT void a2rc( +#else +/*! r: stability flag */ +uint16_t a2rc( +#endif const float *a, /* i : LPC coefficients */ float *refl, /* o : Reflection co-efficients */ const int16_t lpcorder /* i : LPC order */ diff --git a/lib_dec/ivas_lfe_plc.c b/lib_dec/ivas_lfe_plc.c index fe25ad1ef..99509970c 100644 --- a/lib_dec/ivas_lfe_plc.c +++ b/lib_dec/ivas_lfe_plc.c @@ -36,25 +36,35 @@ #include "ivas_prot.h" #include "ivas_rom_com.h" #include +#ifdef DEBUGGING +#include "debug.h" +#endif #include "wmc_auto.h" /*------------------------------------------------------------------------------------------* * Local constants *------------------------------------------------------------------------------------------*/ -#define LFE_PLC_DSF ( 48000 / LFE_PLC_FS ) -#define LFE_PLC_LPCORD ( 20 ) -#define LFE_PLC_MAXITER ( 10 ) +#define LFE_PLC_DSF ( 48000 / LFE_PLC_FS ) +#ifndef NONE_BE_FIX_816_LFE_PLC_FLOAT +#define LFE_PLC_LPCORD ( 20 ) +#else +#define LFE_PLC_LPCORD ( MAX_LP_FILTER_ORDER ) +#endif #define POW_THR ( 1.0e-8f ) #define LFE_PLC_RECLEN_48K ( ( IVAS_LFE_NUM_COEFFS_IN_SUBGRP + 1 ) * L_FRAME48k / IVAS_LFE_NUM_COEFFS_IN_SUBGRP + LFE_PLC_FDEL ) #define LFE_PLC_RECLEN ( ( LFE_PLC_RECLEN_48K / LFE_PLC_DSF ) ) #define LFE_PLC_MUTE_THR ( 10 ) -#define LFE_PLC_BURST_ATT ( pow( pow( 10.0, -3.0 / 20.0 ), 1.0 / ( LFE_PLC_FS * 0.02 ) ) ) /* attenuate 3dB per frame starting with 10th consecutive loss */ - -#define MAX_LEN_LP 960 +#ifdef NONE_BE_FIX_816_LFE_PLC_FLOAT +#define LFE_PLC_BURST_ATT ( powf( powf( 10.0f, -3.0f / 20.0f ), 1.0f / ( LFE_PLC_FS * 20 / 1000 ) ) ) /* attenuate 3dB per frame starting with 10th consecutive loss */ +#define EPS_STOP 1e-5f +#else +#define LFE_PLC_BURST_ATT ( pow( pow( 10.0, -3.0 / 20.0 ), 1.0 / ( LFE_PLC_FS * 0.02 ) ) ) /* attenuate 3dB per frame starting with 10th consecutive loss */ +#define MAX_LEN_LP 960 +#define EPS_STOP 1e-5 +#endif -#define EPS_STOP 1e-5 -#ifndef IVAS_FLOAT_FIXED +#ifndef NONE_BE_FIX_816_LFE_PLC_FLOAT /*------------------------------------------------------------------------------------------* * Static function declarations * @@ -199,10 +209,12 @@ static int16_t d_lev_dur( } rc[i - 1] = ( -s ) / err; + if ( fabs( rc[i - 1] ) > 0.99945f ) { flag = 1; /* Test for unstable filter. If unstable keep old A(z) */ } + for ( j = 1; j <= i / 2; j++ ) { l = i - j; @@ -228,13 +240,82 @@ static int16_t d_lev_dur( return ( flag ); } +#else +/*---------------------------------------------------------------------* + * lfeplc_lev_dur() + * + * Wiener-Levinson-Durbin algorithm to compute LP parameters from the autocorrelations + * of input signal + *---------------------------------------------------------------------*/ +/*! r: stability flag */ +static int16_t lfeplc_lev_dur( + float *a_out, /* o : LP coefficients (a[0] = 1.0) */ + const float *r, /* i : vector of autocorrelations */ + const int16_t m /* i : order of LP filter */ +) +{ + int16_t i, j, l; + float buf[TCXLTP_LTP_ORDER]; + float *rc; /* reflection coefficients 0,...,m-1 */ + float s, at, err; + float a[LFE_PLC_LPCORD + 1]; + + set_f( a, 0.f, LFE_PLC_LPCORD + 1 ); + set_f( a_out, 0.f, LFE_PLC_LPCORD + 1 ); + rc = &buf[0]; + a[0] = 1.f; + err = r[0]; + a_out[0] = a[0]; + rc[0] = ( -r[1] ) / r[0]; + s = r[1]; + a[1] = rc[0]; + a_out[1] = a[1]; + + i = 1; + while ( i < m ) + { + for ( j = 1; j <= i / 2; j++ ) + { + l = i - j; + at = a[j] + rc[i - 1] * a[l]; + a[l] += rc[i - 1] * a[j]; + a[j] = at; + } + + a[i] = rc[i - 1]; + err += rc[i - 1] * s; + s = 0.f; + i++; + for ( j = 0; j < i; j++ ) + { + s += r[i - j] * a[j]; + } + rc[i - 1] = ( -s ) / err; + if ( fabsf( rc[i - 1] ) > 0.99945f ) + { + return 1; + } + else + { + for ( j = 0; j <= m; j++ ) + { + a_out[j] = a[j]; + } + } + } + + return 0; +} + +#endif + +#ifndef NONE_BE_FIX_816_LFE_PLC_FLOAT /*-------------------------------------------------------------------* * a2rc() * * Convert from LPC to reflection coeff *-------------------------------------------------------------------*/ - static uint16_t d_a2rc( const double *a, /* i : LPC coefficients */ double *refl, /* o : Reflection co-efficients */ @@ -242,8 +323,8 @@ static uint16_t d_a2rc( ) { double ff[LFE_PLC_LPCORD]; - int16_t m, j, n; double km, denom, x; + int16_t m, j, n; for ( m = 0; m < lpcorder; m++ ) { @@ -283,7 +364,6 @@ static uint16_t d_a2rc( return 1; } - static void d_syn_filt( const double a[], /* i : LP filter coefficients */ const int16_t m, /* i : order of LP filter */ @@ -325,7 +405,7 @@ static void d_syn_filt( return; } - +#endif /*-----------------------------------------------------------------------------------------* * Function check_stab() @@ -333,17 +413,31 @@ static void d_syn_filt( * LPC filter stability check applying given sharpening value delta *-----------------------------------------------------------------------------------------*/ +#ifndef NONE_BE_FIX_816_LFE_PLC_FLOAT static uint16_t check_stab( const double *a, double delta ) { double amod[LFE_PLC_LPCORD], refl[LFE_PLC_LPCORD]; - int16_t i; double fac; double fac1; +#else +static uint16_t check_stab( + const float *a, + const float delta ) +{ + float amod[LFE_PLC_LPCORD], refl[LFE_PLC_LPCORD]; + float fac; + float fac1; +#endif + int16_t i; uint16_t stable; +#ifndef NONE_BE_FIX_816_LFE_PLC_FLOAT fac = 1.0 + delta; +#else + fac = 1.0f + delta; +#endif fac1 = fac; for ( i = 0; i < LFE_PLC_LPCORD; i++ ) @@ -351,7 +445,12 @@ static uint16_t check_stab( amod[i] = a[i] * fac; fac *= fac1; } + +#ifndef NONE_BE_FIX_816_LFE_PLC_FLOAT stable = d_a2rc( amod, refl, LFE_PLC_LPCORD ); +#else + stable = a2rc( amod, refl, LFE_PLC_LPCORD ); +#endif return stable; } @@ -363,16 +462,30 @@ static uint16_t check_stab( * Find maximum LPC filter sharpening by iteration to get a filter that is almost instable *-----------------------------------------------------------------------------------------*/ +#ifndef NONE_BE_FIX_816_LFE_PLC_FLOAT static double find_max_delta( double *a ) { double delta; double eps; - uint16_t stable; double fac; +#else +static float find_max_delta( + float *a ) +{ + float delta; + float eps; + float fac; +#endif + uint16_t stable; +#ifndef NONE_BE_FIX_816_LFE_PLC_FLOAT delta = 0.0; eps = 0.01; +#else + delta = 0.0f; + eps = 0.01f; +#endif fac = 2; stable = FALSE; @@ -382,7 +495,11 @@ static double find_max_delta( eps *= fac; stable = TRUE; } +#ifndef NONE_BE_FIX_816_LFE_PLC_FLOAT fac = 0.5; +#else + fac = 0.5f; +#endif if ( stable ) { @@ -404,6 +521,7 @@ static double find_max_delta( delta += eps; stable = check_stab( a, delta ); +#ifndef NONE_BE_FIX_816_LFE_PLC_FLOAT if ( !stable ) { if ( fabs( eps ) > EPS_STOP ) @@ -423,6 +541,27 @@ static double find_max_delta( } eps = fabs( eps ) * fac; } +#else + if ( !stable ) + { + if ( fabsf( eps ) > EPS_STOP ) + { + eps = -fabsf( eps ) * fac; + } + else + { + eps = -fabsf( eps ); + } + } + else + { + if ( fabsf( eps ) < EPS_STOP ) + { + break; + } + eps = fabsf( eps ) * fac; + } +#endif } return delta; @@ -437,28 +576,54 @@ static double find_max_delta( static void recover_samples( const int16_t bfi_count, +#ifndef NONE_BE_FIX_816_LFE_PLC_FLOAT const float *outbuf, +#else + float *outbuf, +#endif float *rec_frame ) { int16_t i; float zeroes[LFE_PLC_RECLEN]; +#ifndef NONE_BE_FIX_816_LFE_PLC_FLOAT double delta, fac, att; double d_outbuf[LFE_PLC_BUFLEN], d_r[LFE_PLC_LPCORD + 1], d_a[LFE_PLC_LPCORD + 1], d_pee[LFE_PLC_LPCORD + 1]; + mvr2d( outbuf, d_outbuf, LFE_PLC_BUFLEN ); d_autocorr( d_outbuf, d_r, LFE_PLC_LPCORD, LFE_PLC_BUFLEN, d_hamm_lfe_plc, 0, 1, 1 ); +#else + float delta, fac, att; + float r[LFE_PLC_LPCORD + 1], a[LFE_PLC_LPCORD + 1]; + autocorr( outbuf, r, LFE_PLC_LPCORD, LFE_PLC_BUFLEN, hamm_lfe_plc, 0, 1, 1 ); +#endif + +#ifndef NONE_BE_FIX_816_LFE_PLC_FLOAT if ( d_r[0] < POW_THR * LFE_PLC_BUFLEN ) +#else + if ( r[0] < POW_THR * LFE_PLC_BUFLEN ) +#endif { set_zero( rec_frame, LFE_PLC_RECLEN ); return; } + +#ifndef NONE_BE_FIX_816_LFE_PLC_FLOAT d_lev_dur( d_a, d_r, LFE_PLC_LPCORD, d_pee ); delta = find_max_delta( d_a + 1 ); fac = 1.0 + delta; att = 1.0; +#else + lfeplc_lev_dur( a, r, LFE_PLC_LPCORD ); + + delta = find_max_delta( a + 1 ); + + fac = 1.0f + delta; + att = 1.0f; +#endif if ( bfi_count >= LFE_PLC_MUTE_THR ) { @@ -468,12 +633,22 @@ static void recover_samples( for ( i = 1; i <= LFE_PLC_LPCORD; i++ ) { +#ifndef NONE_BE_FIX_816_LFE_PLC_FLOAT d_a[i] = d_a[i] * fac; fac *= att * ( 1.0 + delta ); +#else + a[i] = a[i] * fac; + fac *= att * ( 1.0f + delta ); +#endif } set_zero( zeroes, LFE_PLC_RECLEN ); + +#ifndef NONE_BE_FIX_816_LFE_PLC_FLOAT d_syn_filt( d_a, LFE_PLC_LPCORD, zeroes, rec_frame, LFE_PLC_RECLEN, outbuf + LFE_PLC_BUFLEN - LFE_PLC_LPCORD ); +#else + syn_filt( a, LFE_PLC_LPCORD, zeroes, rec_frame, LFE_PLC_RECLEN, outbuf + LFE_PLC_BUFLEN - LFE_PLC_LPCORD, 0 ); +#endif return; } @@ -486,8 +661,12 @@ static void recover_samples( *-----------------------------------------------------------------------------------------*/ void ivas_lfe_tdplc( - LFE_DEC_HANDLE hLFE, /* i/o: LFE decoder handle */ - const float *prevsynth, /* i : previous frame synthesis */ + LFE_DEC_HANDLE hLFE, /* i/o: LFE decoder handle */ +#ifdef NONE_BE_FIX_816_LFE_PLC_FLOAT + float *prevsynth, /* i : previous frame synthesis */ +#else + double *prevsynth, /* i : previous frame synthesis */ +#endif float *ytda, /* o : output time-domain buffer */ const int16_t output_frame /* i : output frame length */ ) @@ -535,4 +714,3 @@ void ivas_lfe_tdplc( return; } -#endif diff --git a/lib_dec/ivas_lfe_plc_fx.c b/lib_dec/ivas_lfe_plc_fx.c index 6a65839b8..f47cc5454 100644 --- a/lib_dec/ivas_lfe_plc_fx.c +++ b/lib_dec/ivas_lfe_plc_fx.c @@ -49,18 +49,26 @@ * Local constants *------------------------------------------------------------------------------------------*/ -#define LFE_PLC_DSF ( 48000 / LFE_PLC_FS ) -#define LFE_PLC_LPCORD ( 20 ) +#define LFE_PLC_DSF ( 48000 / LFE_PLC_FS ) +#ifndef NONE_BE_FIX_816_LFE_PLC_FLOAT +#define LFE_PLC_LPCORD ( 20 ) +#else +#define LFE_PLC_LPCORD ( MAX_LP_FILTER_ORDER ) +#endif #define LFE_PLC_MAXITER ( 10 ) #define POW_THR ( 1.0e-8f ) #define LFE_PLC_RECLEN_48K ( ( IVAS_LFE_NUM_COEFFS_IN_SUBGRP + 1 ) * L_FRAME48k / IVAS_LFE_NUM_COEFFS_IN_SUBGRP + LFE_PLC_FDEL ) #define LFE_PLC_RECLEN ( ( LFE_PLC_RECLEN_48K / LFE_PLC_DSF ) ) #define LFE_PLC_MUTE_THR ( 10 ) -#define LFE_PLC_BURST_ATT ( pow( pow( 10.0, -3.0 / 20.0 ), 1.0 / ( LFE_PLC_FS * 0.02 ) ) ) /* attenuate 3dB per frame starting with 10th consecutive loss */ - -#define MAX_LEN_LP 960 - -#define EPS_STOP 1e-5 +#ifdef NONE_BE_FIX_816_LFE_PLC_FLOAT +#define LFE_PLC_BURST_ATT ( powf( powf( 10.0f, -3.0f / 20.0f ), 1.0f / ( LFE_PLC_FS * 20 / 1000 ) ) ) /* attenuate 3dB per frame starting with 10th consecutive loss */ +#define EPS_STOP 1e-5f +#define MAX_LEN_LP 960 +#else +#define MAX_LEN_LP 960 +#define LFE_PLC_BURST_ATT ( pow( pow( 10.0, -3.0 / 20.0 ), 1.0 / ( LFE_PLC_FS * 0.02 ) ) ) /* attenuate 3dB per frame starting with 10th consecutive loss */ +#define EPS_STOP 1e-5 +#endif #ifdef IVAS_FLOAT_FIXED #define POW_THR_Q50 ( 11258999 ) #define EPS_STOP_Q31 ( 21475 ) @@ -73,7 +81,6 @@ * float functions defined in tools.c, lpc_tools.c and syn_filt.c. * Double precision arithmetic is required for proper functioning of the lfe_plc. *------------------------------------------------------------------------------------------*/ - /*---------------------------------------------------------------------* * autocorr_fx() * @@ -190,7 +197,7 @@ static void d_autocorr_fx( return; } - +#ifndef NONE_BE_FIX_816_LFE_PLC_FLOAT /*---------------------------------------------------------------------* * lev_dur_fx() * @@ -418,7 +425,250 @@ static Word16 d_lev_dur_fx( return ( flag ); } +#else +/*---------------------------------------------------------------------* + * lfeplc_lev_dur() + * + * Wiener-Levinson-Durbin algorithm to compute LP parameters from the autocorrelations + * of input signal + *---------------------------------------------------------------------*/ + +/*! r: stability flag */ +static Word16 lfeplc_lev_dur_fx( + Word32 *a_out_fx, /* o : LP coefficients (a[0] = 1.0) */ + Word16 *a_out_q_fx, + Word32 *r_fx, /* i : vector of autocorrelations */ + Word16 *r_q_fx, + const Word16 m ) +{ + Word16 i, j, l; + Word32 buf_fx[TCXLTP_LTP_ORDER]; + Word16 rc_q_fx[TCXLTP_LTP_ORDER]; + Word32 *rc_fx; /* reflection coefficients 0,...,m-1 */ + Word32 temp1, temp2, err_fx, at_fx, s; + Word16 temp_q1, temp_q2, s_q_fx, err_q_fx, exp1, exp2; + Word64 s_fx; + Word32 a_fx[LFE_PLC_LPCORD + 1]; + Word16 a_q_fx[LFE_PLC_LPCORD + 1]; + + set32_fx( a_fx, 0, LFE_PLC_LPCORD + 1 ); + set16_fx( a_q_fx, 31, LFE_PLC_LPCORD + 1 ); + set32_fx( a_out_fx, 0, LFE_PLC_LPCORD + 1 ); + set16_fx( a_out_q_fx, 31, LFE_PLC_LPCORD + 1 ); + + s_q_fx = 0; + move16(); + + rc_fx = &buf_fx[0]; + a_fx[0] = ONE_IN_Q30; + move32(); + a_q_fx[0] = 30; + move16(); + err_fx = r_fx[0]; + move32(); + err_q_fx = r_q_fx[0]; + move16(); + a_out_fx[0] = a_fx[0]; + move32(); + a_out_q_fx[0] = 30; + move16(); + + rc_fx[0] = BASOP_Util_Divide3232_Scale_cadence( -r_fx[1], r_fx[0], &temp_q2 ); + move32(); + rc_q_fx[0] = add( sub( r_q_fx[1], r_q_fx[0] ), sub( 31, temp_q2 ) ); + move16(); + + s = r_fx[1]; + s_q_fx = r_q_fx[1]; + + a_fx[1] = rc_fx[0]; + move32(); + a_q_fx[1] = rc_q_fx[0]; + move32(); + + a_out_fx[1] = a_fx[1]; + move32(); + a_out_q_fx[1] = a_q_fx[1]; + move32(); + + i = 1; + move16(); + WHILE( LT_16( i, m ) ) + { + FOR( j = 1; j <= i / 2; j++ ) + { + l = sub( i, j ); + exp1 = sub( norm_l( rc_fx[i - 1] ), 1 ); + exp2 = sub( norm_l( a_fx[l] ), 1 ); + rc_fx[i - 1] = L_shl( rc_fx[i - 1], exp1 ); + move32(); + rc_q_fx[i - 1] = add( rc_q_fx[i - 1], exp1 ); + move16(); + a_fx[l] = L_shl( a_fx[l], exp2 ); + move32(); + a_q_fx[l] = add( a_q_fx[l], exp2 ); + move16(); + + exp2 = sub( norm_l( a_fx[j] ), 1 ); + a_fx[j] = L_shl( a_fx[j], exp2 ); + move32(); + a_q_fx[j] = add( a_q_fx[j], exp2 ); + move16(); + + temp2 = Mpy_32_32( rc_fx[i - 1], a_fx[l] ); + temp_q2 = sub( add( rc_q_fx[i - 1], a_q_fx[l] ), 31 ); + IF( temp2 == 0 ) + { + temp_q2 = 31; + } + + IF( LT_16( temp_q2, a_q_fx[j] ) ) + { + at_fx = L_add( L_shr( a_fx[j], sub( a_q_fx[j], temp_q2 ) ), temp2 ); + temp_q1 = temp_q2; + move16(); + } + ELSE + { + at_fx = L_add( a_fx[j], L_shr( temp2, sub( temp_q2, a_q_fx[j] ) ) ); + temp_q1 = a_q_fx[j]; + move16(); + } + + temp2 = Mpy_32_32( rc_fx[i - 1], a_fx[j] ); + temp_q2 = sub( add( rc_q_fx[sub( i, 1 )], a_q_fx[j] ), 31 ); + IF( temp2 == 0 ) + { + temp_q2 = 31; + } + + IF( LT_16( temp_q2, a_q_fx[l] ) ) + { + a_fx[l] = L_add( L_shr( a_fx[l], sub( a_q_fx[l], temp_q2 ) ), temp2 ); + move32(); + a_q_fx[l] = temp_q2; + move16(); + } + ELSE + { + a_fx[l] = L_add( a_fx[l], L_shr( temp2, sub( temp_q2, a_q_fx[l] ) ) ); + move16(); + } + a_fx[j] = at_fx; + move32(); + a_q_fx[j] = temp_q1; + move16(); + } + + a_fx[i] = rc_fx[sub( i, 1 )]; + move32(); + a_q_fx[i] = rc_q_fx[sub( i, 1 )]; + move16(); + + exp1 = sub( norm_l( rc_fx[sub( i, 1 )] ), 1 ); + exp2 = norm_l( s ); + temp1 = Mpy_32_32( L_shl( rc_fx[sub( i, 1 )], exp1 ), L_shl( s, exp2 ) ); + temp_q1 = sub( add( add( rc_q_fx[sub( i, 1 )], exp1 ), add( s_q_fx, exp2 ) ), 31 ); + IF( temp1 == 0 ) + { + temp_q1 = 31; + } + + IF( LT_16( temp_q1, err_q_fx ) ) + { + err_fx = L_add( L_shr( err_fx, sub( err_q_fx, temp_q1 ) ), temp1 ); + err_q_fx = temp_q1; + move16(); + } + ELSE + { + err_fx = L_add( err_fx, L_shr( temp1, sub( temp_q1, err_q_fx ) ) ); + } + + s_fx = 0; + move32(); + s_q_fx = 0; + move16(); + i = add( i, 1 ); + s_fx = 0; + move64(); + + FOR( j = 0; j < i; j++ ) + { + exp1 = norm_l( r_fx[i - j] ); + exp2 = norm_l( a_fx[j] ); + temp1 = Mpy_32_32( L_shl( r_fx[i - j], exp1 ), L_shl( a_fx[j], exp2 ) ); + temp_q1 = sub( add( add( r_q_fx[i - j], exp1 ), add( a_q_fx[j], exp2 ) ), 31 ); + IF( temp1 == 0 ) + { + temp_q1 = 31; + } + + IF( EQ_16( j, 0 ) ) + { + s_fx = W_deposit32_l( temp1 ); + s_q_fx = temp_q1; + move16(); + } + ELSE + { + IF( LT_16( temp_q1, s_q_fx ) ) + { + s_fx = W_add( W_shr( s_fx, sub( s_q_fx, temp_q1 ) ), W_deposit32_l( temp1 ) ); + s_q_fx = temp_q1; + move16(); + } + ELSE + { + s_fx = W_add( s_fx, W_shr( W_deposit32_l( temp1 ), sub( temp_q1, s_q_fx ) ) ); + } + } + } + + exp1 = W_norm( s_fx ); + s = W_extract_h( W_shl( s_fx, exp1 ) ); + s_q_fx = sub( add( s_q_fx, exp1 ), 32 ); + + rc_fx[i - 1] = L_shr( BASOP_Util_Divide3232_Scale_cadence( -s, err_fx, &temp_q2 ), 1 ); + move32(); + rc_q_fx[i - 1] = sub( add( sub( s_q_fx, err_q_fx ), sub( 31, temp_q2 ) ), 1 ); + move16(); + + IF( LT_16( rc_q_fx[i - 1], 31 ) ) + { + IF( GT_32( abs( rc_fx[i - 1] ), L_shr( 2146302532, sub( 31, rc_q_fx[i - 1] ) ) ) ) // 2146302532 = 0.99945f in Q31 + { + return 1; + } + ELSE + { + FOR( j = 0; j <= m; j++ ) + { + a_out_fx[j] = a_fx[j]; + a_out_q_fx[j] = a_q_fx[j]; + } + } + } + ELSE + { + IF( GT_32( abs( L_shr( rc_fx[i - 1], sub( rc_q_fx[i - 1], 31 ) ) ), 2146302532 ) ) // 2146302532 = 0.00045f in Q31 + { + return 1; + } + ELSE + { + FOR( j = 0; j <= m; j++ ) + { + a_out_fx[j] = a_fx[j]; + a_out_q_fx[j] = a_q_fx[j]; + } + } + } + } + return 0; +} +#endif /*-------------------------------------------------------------------* * a2rc_fx() * @@ -490,7 +740,10 @@ static Word16 d_a2rc_fx( exp2 = sub( norm_l( temp2 ), 1 ); temp = Mpy_32_32( L_shl( km_fx, exp1 ), L_shl( temp2, exp2 ) ); temp_q = sub( add( add( km_q_fx, exp1 ), add( temp_q2, exp2 ) ), 31 ); - + IF( temp == 0 ) + { + temp_q = 31; + } IF( LT_16( temp_q, temp_q1 ) ) { ff_fx[j] = L_add( L_shr( temp1, sub( temp_q1, temp_q ) ), temp ); @@ -510,7 +763,10 @@ static Word16 d_a2rc_fx( exp2 = sub( norm_l( temp1 ), 1 ); temp = Mpy_32_32( L_shl( km_fx, exp1 ), L_shl( temp1, exp2 ) ); temp_q = sub( add( add( km_q_fx, exp1 ), add( temp_q1, exp2 ) ), 31 ); - + IF( temp == 0 ) + { + temp_q = 31; + } IF( LT_16( temp_q, temp_q2 ) ) { ff_fx[n] = L_add( L_shr( temp2, sub( temp_q2, temp_q ) ), temp ); @@ -688,11 +944,18 @@ static Word16 check_stab_fx( move32(); amod_q_fx[i] = sub( add( add( a_q_fx[i], exp1 ), add( fac_q_fx, exp2 ) ), 31 ); move16(); - + IF( amod_fx[i] == 0 ) + { + amod_q_fx[i] = 31; + } exp1 = norm_l( fac_fx ); exp2 = norm_l( fac1_fx ); fac_fx = Mpy_32_32( L_shl( fac_fx, exp1 ), L_shl( fac1_fx, exp2 ) ); fac_q_fx = sub( add( add( fac_q_fx, exp1 ), add( fac1_q_fx, exp2 ) ), 31 ); + IF( fac_fx == 0 ) + { + fac_q_fx = 0; + } } stable = d_a2rc_fx( amod_fx, amod_q_fx, refl_fx, LFE_PLC_LPCORD ); @@ -822,7 +1085,7 @@ static Word32 find_max_delta_fx( * * recover lost samples by extrapolation of signal buffer *-----------------------------------------------------------------------------------------*/ - +#ifndef NONE_BE_FIX_816_LFE_PLC_FLOAT static void recover_samples_fx( const Word16 bfi_count, const Word32 *outbuf_fx, @@ -911,7 +1174,100 @@ static void recover_samples_fx( return; } +#else +static void recover_samples_fx( + const Word16 bfi_count, + const Word32 *outbuf_fx, + Word16 outbuf_q_fx, + Word32 *rec_frame_fx, + Word16 *rec_frame_q_fx ) +{ + Word16 i; + Word32 d_outbuf_fx[LFE_PLC_BUFLEN], d_a_fx[LFE_PLC_LPCORD + 1]; + Word16 d_r_q_fx[LFE_PLC_LPCORD + 1], d_a_q_fx[LFE_PLC_LPCORD + 1]; + Word32 d_r_fx[LFE_PLC_LPCORD + 1], zeroes_fx[LFE_PLC_RECLEN]; + Word32 delta_fx, fac_fx, att_fx, temp; + Word16 delta_q_fx, fac_q_fx, att_q_fx, temp_q, exp1, exp2; + + Copy32( outbuf_fx, d_outbuf_fx, LFE_PLC_BUFLEN ); + d_autocorr_fx( d_outbuf_fx, outbuf_q_fx, d_r_fx, d_r_q_fx, LFE_PLC_LPCORD, LFE_PLC_BUFLEN, d_hamm_lfe_plc_fx, 0, 1, 1 ); + + IF( LT_64( W_shr( d_r_fx[0], sub( d_r_q_fx[0], Q19 ) ), W_deposit32_l( Mpy_32_32( POW_THR_Q50, LFE_PLC_BUFLEN ) ) ) ) + { + set_zero_fx( rec_frame_fx, LFE_PLC_RECLEN ); + return; + } + + lfeplc_lev_dur_fx( d_a_fx, d_a_q_fx, d_r_fx, d_r_q_fx, LFE_PLC_LPCORD ); + + delta_fx = find_max_delta_fx( d_a_fx + 1, d_a_q_fx + 1, &delta_q_fx ); + + IF( LT_16( delta_q_fx, Q29 ) ) + { + fac_fx = L_add( L_shr( ONE_IN_Q29, sub( Q29, delta_q_fx ) ), delta_fx ); + fac_q_fx = delta_q_fx; + move16(); + } + ELSE + { + fac_fx = L_add( ONE_IN_Q29, L_shr( delta_fx, sub( delta_q_fx, Q29 ) ) ); + fac_q_fx = Q29; + move16(); + } + att_fx = ONE_IN_Q30; + move32(); + att_q_fx = Q30; + move16(); + + IF( GE_16( bfi_count, LFE_PLC_MUTE_THR ) ) + { + att_fx = LFE_PLC_BURST_ATT_Q31; + move32(); + fac_fx = Mpy_32_32( fac_fx, att_fx ); + fac_q_fx = sub( add( fac_q_fx, att_q_fx ), 31 ); + } + + FOR( i = 1; i <= LFE_PLC_LPCORD; i++ ) + { + d_a_fx[i] = Mpy_32_32( d_a_fx[i], fac_fx ); + move32(); + d_a_q_fx[i] = sub( add( d_a_q_fx[i], fac_q_fx ), 31 ); + move16(); + IF( d_a_fx[i] == 0 ) + { + d_a_q_fx[i] = 31; + } + IF( LT_16( delta_q_fx, Q30 ) ) + { + temp = L_add( L_shr( ONE_IN_Q30, sub( Q30, delta_q_fx ) ), delta_fx ); + temp_q = delta_q_fx; + move16(); + } + ELSE + { + temp = L_add( ONE_IN_Q30, L_shr( delta_fx, sub( delta_q_fx, Q30 ) ) ); + temp_q = Q30; + move16(); + } + exp1 = norm_l( att_fx ); + exp2 = norm_l( temp ); + temp = Mpy_32_32( L_shl( att_fx, exp1 ), L_shl( temp, exp2 ) ); + temp_q = sub( add( add( att_q_fx, exp1 ), add( temp_q, exp2 ) ), 31 ); + + exp1 = norm_l( fac_fx ); + exp2 = norm_l( temp ); + fac_fx = Mpy_32_32( L_shl( fac_fx, exp1 ), L_shl( temp, exp2 ) ); + fac_q_fx = sub( add( add( fac_q_fx, exp1 ), add( temp_q, exp2 ) ), 31 ); + } + + set_zero_fx( zeroes_fx, LFE_PLC_RECLEN ); + + d_syn_filt_fx( d_a_fx, d_a_q_fx, LFE_PLC_LPCORD, zeroes_fx, rec_frame_fx, rec_frame_q_fx, LFE_PLC_RECLEN, outbuf_fx + LFE_PLC_BUFLEN - LFE_PLC_LPCORD, outbuf_q_fx ); + + return; +} +#endif /*-----------------------------------------------------------------------------------------* * Function ivas_lfe_tdplc_fx() * diff --git a/lib_enc/ivas_lfe_enc.c b/lib_enc/ivas_lfe_enc.c index 636658d25..ced67ef50 100644 --- a/lib_enc/ivas_lfe_enc.c +++ b/lib_enc/ivas_lfe_enc.c @@ -206,7 +206,11 @@ static void ivas_lfe_enc_quant( } else { +#ifdef NONE_BE_FIX_816_LFE_PLC_FLOAT + shift = (int16_t) floorf( IVAS_LFE_SHIFTS_PER_DOUBLE * log2_f( max_value / lfe_abs_sum ) ); +#else shift = (int16_t) floor( IVAS_LFE_SHIFTS_PER_DOUBLE * log2_f( max_value / lfe_abs_sum ) ); +#endif } shift = max( min_shift * IVAS_LFE_SHIFTS_PER_DOUBLE, min( max_shift, shift ) ); -- GitLab