From e8ba4648b6fc4a5c90908d73c8c782734cb45b0e Mon Sep 17 00:00:00 2001 From: Sandesh Venkatesh Date: Wed, 22 Nov 2023 13:59:24 +0530 Subject: [PATCH] TCX Harmonic model related changes [x] TCX Harmonic model and TCX arithmetic decode envelope functions converted to fixed. [x] Floating code output is bit exact with base version IVAS code. --- lib_com/ari_hm.c | 188 ++++++++++++++++++++++++++++++++++++++ lib_com/prot.h | 60 ++++++++++++ lib_com/rom_com.c | 121 ++++++++++++++++++++++++ lib_com/rom_com.h | 36 ++++++++ lib_dec/ari_dec.c | 27 ++++++ lib_dec/ari_hm_dec.c | 98 ++++++++++++++++++++ lib_dec/arith_coder_dec.c | 183 +++++++++++++++++++++++++++++++++++++ lib_dec/dec_tcx.c | 12 +++ 8 files changed, 725 insertions(+) diff --git a/lib_com/ari_hm.c b/lib_com/ari_hm.c index 5d6d3315b..411ebe016 100644 --- a/lib_com/ari_hm.c +++ b/lib_com/ari_hm.c @@ -100,6 +100,70 @@ void UnmapIndex( return; } +void UnmapIndex_fx( + const Word16 PeriodicityIndex, + const Word16 Bandwidth, + const Word16 LtpPitchLag, + const Word8 SmallerLags, + Word16 *FractionalResolution, + Word32 *Lag +) +{ + Word16 LtpPitchIndex, Multiplier; + Word16 Lag16; + + test(); + IF ((LtpPitchLag > 0) && (s_and(PeriodicityIndex, kLtpHmFlag) != 0)) + { + LtpPitchIndex = shr(PeriodicityIndex, 9); + Multiplier = s_and(PeriodicityIndex, 0xff); + + assert(0 <= LtpPitchIndex && LtpPitchIndex <= 16); + assert(1 <= Multiplier && Multiplier <= (1 << NumRatioBits[Bandwidth][LtpPitchIndex])); + + *FractionalResolution = kLtpHmFractionalResolution; + move16(); + *Lag = L_shr(L_mult0(LtpPitchLag, Ratios_fx[Bandwidth][LtpPitchIndex][Multiplier-1]), 8); + move32(); + } + ELSE + { + IF (LT_16(PeriodicityIndex, 16)) + { + *FractionalResolution = 3; + move16(); + Lag16 = add(PeriodicityIndex, GET_ADJ2(0, 6, 3)); + } + ELSE IF (LT_16(PeriodicityIndex, 80)) + { + *FractionalResolution = 4; + move16(); + Lag16 = add(PeriodicityIndex, GET_ADJ2(16, 8, 4)); + } + ELSE IF (LT_16(PeriodicityIndex, 208)) + { + *FractionalResolution = 3; + move16(); + Lag16 = add(PeriodicityIndex, GET_ADJ2(80, 12, 3)); + } + ELSE { + test(); + IF (LT_16(PeriodicityIndex, 224)||SmallerLags!=0) + { + *FractionalResolution = 1; + move16(); + Lag16 = add(PeriodicityIndex, GET_ADJ2(208, 28, 1)); + } + ELSE { + *FractionalResolution = 0; + move16(); + Lag16 = add(PeriodicityIndex, GET_ADJ2(224, 188, 0)); + } + } + *Lag = L_deposit_l(Lag16); + } +} + /*-------------------------------------------------------------------* * ConfigureContextHm() @@ -196,6 +260,27 @@ int16_t CountIndexBits( return 8; } +Word16 CountIndexBits_fx( + Word16 Bandwidth, + Word16 PeriodicityIndex +) +{ + Word16 result; + Word16 PeriodicityIndexS; + + result = 8; + move16(); + PeriodicityIndexS = shr(PeriodicityIndex, 9); + + if (s_and(PeriodicityIndex, kLtpHmFlag) != 0) + { + result = NumRatioBits[Bandwidth][PeriodicityIndexS]; + move16(); + } + + return result; +} + #define WMC_TOOL_SKIP /*-------------------------------------------------------------------* @@ -256,6 +341,61 @@ int16_t tcx_hm_render( return 0; } +Word32 tcx_hm_render_fx( + const Word32 lag, /* i: pitch lag Q0 */ + const Word16 fract_res, /* i: fractional resolution of the lag Q0 */ + Word16 p[] /* o: harmonic model Q13 */ +) +{ + Word16 k, tmp, height; + Word16 PeakDeviation; + Word32 f0, tmp32; + + /* Set up overall shape */ + f0 = L_shl(lag, sub(15, fract_res)); /* Q31 */ + + tmp32 = Mpy_32_16_1(f0, -26474); + tmp32 = L_shr_r(BASOP_Util_InvLog2(L_shl(tmp32, 7)), 2); + tmp32 = L_sub(603979776L, tmp32); + tmp32 = L_add(L_add(tmp32, tmp32), Mpy_32_16_1(tmp32, 26214)); + height = round_fx(tmp32); /* Q13 */ + + tmp32 = Mpy_32_16_1(f0, -18910); + tmp32 = L_shr_r(BASOP_Util_InvLog2(L_shl(tmp32, 7)), 2); + tmp32 = L_sub(1395864371L, tmp32); + PeakDeviation = round_fx(tmp32); /* Q14 */ + + IF( GT_16(13915,PeakDeviation)) + { + /* A bit error was encountered */ + return 1; + } + ELSE + { + tmp = div_s(13915, PeakDeviation); + tmp = mult_r(tmp, tmp); /* Q15 */ + } + + tmp = div_s(13915, PeakDeviation); + tmp = mult_r(tmp, tmp); /* Q15 */ + + /* Render the prototype peak */ + p[kTcxHmParabolaHalfWidth] = height; + move16(); + + FOR (k=1; k<=kTcxHmParabolaHalfWidth; ++k) + { + p[kTcxHmParabolaHalfWidth+k] = round_fx(Mpy_32_16_1(BASOP_Util_InvLog2(L_shl(L_mult0(i_mult2(negate(k),k), tmp),10)), height)); + } + /* Mirror */ + FOR (k=-kTcxHmParabolaHalfWidth; k<0; ++k) + { + p[kTcxHmParabolaHalfWidth+k] = p[kTcxHmParabolaHalfWidth-k]; + move16(); + } + + return 0; +} /*-------------------------------------------------------------------* * tcx_hm_modify_envelope() @@ -302,4 +442,52 @@ void tcx_hm_modify_envelope( return; } +void tcx_hm_modify_envelope_fx( + const Word16 gain, /* i: HM gain Q11 */ + const Word32 lag, /* i: pitch lag Q0 */ + const Word16 fract_res, /* i: fractional resolution of the lag Q0 */ + const Word16 p[], /* i: harmonic model Q13 */ + Word32 env[], /* i/o: envelope Q16 */ + const Word16 L_frame /* i: number of spectral lines Q0 */ +) +{ + Word16 k, h, x, l1,l2, L_frame_m1, L_frame_for_loop; + Word16 inv_shape[2*kTcxHmParabolaHalfWidth+1]; + + IF ( gain == 0 ) + { + return; + } + + FOR (k=0; k<2*kTcxHmParabolaHalfWidth+1; ++k) + { + /* Q24 = Q11 * Q13; 512 = 1.0 in Q24 format */ + inv_shape[k] = div_s(512, add(512, mult_r(gain, p[k]))); + move16(); + } + + h = 1; + move16(); + k = extract_l(L_shr(lag,fract_res)); + + L_frame_m1 = sub(L_frame,1); + L_frame_for_loop = add(L_frame,kTcxHmParabolaHalfWidth - 1); + + WHILE ( LE_16(k,L_frame_for_loop)) + { + l1 = s_max(0, sub(k,kTcxHmParabolaHalfWidth)); + l2 = s_min(add(k,kTcxHmParabolaHalfWidth), L_frame_m1); + FOR (x=l1; x<=l2; ++x) + { + env[x] = Mpy_32_16_1(env[x], inv_shape[x-k+kTcxHmParabolaHalfWidth]); + move32(); + } + + h = add(h,1); + k = extract_l(L_shr(imult3216(lag,h),fract_res)); + } + +} + + #undef WMC_TOOL_SKIP diff --git a/lib_com/prot.h b/lib_com/prot.h index 62a8a706f..0f64e4760 100644 --- a/lib_com/prot.h +++ b/lib_com/prot.h @@ -7580,6 +7580,12 @@ int16_t ari_start_decoding_14bits_prm( int16_t bp, Tastat *s ); +Word16 ari_start_decoding_14bits_prm_fx( + const Word16 *ptr, + Word16 bp, + Tastat *s +); + void ari_decode_14bits_s17_ext( Decoder_State *st, uint16_t *res, @@ -7699,6 +7705,23 @@ void tcx_arith_decode_envelope( const int16_t low_complexity /* i : low-complexity flag */ ); +void tcx_arith_decode_envelope_fx( + Decoder_State *st, /* i/o: coder state */ + Word32 q_spectrum[], /* o : quantised MDCT coefficients */ + Word16 *q_spectrum_e, /* o : MDCT exponent */ + const Word16 L_frame, /* i : frame or MDCT length */ + Word16 L_spec, /* i : length w/o BW limitation */ + const Word16 A_ind[], /* i : quantised LPC coefficients */ + const Word16 target_bits, /* i : number of available bits */ + const Word16 prm[], /* i : bitstream parameters */ + const Word16 use_hm, /* i : use HM in current frame? */ + const Word16 prm_hm[], /* i : HM parameter area */ + Word16 tcxltp_pitch, /* i : TCX LTP pitch in FD, -1 if n/a*/ + Word16 *arith_bits, /* o : bits used for ari. coding */ + Word16 *signaling_bits, /* o : bits used for signaling */ + const Word16 low_complexity /* i : low-complexity flag */ +); + void UnmapIndex( const int16_t PeriodicityIndex, const int16_t Bandwidth, @@ -7707,6 +7730,14 @@ void UnmapIndex( int16_t *FractionalResolution, int32_t *Lag ); +void UnmapIndex_fx( + const Word16 PeriodicityIndex, + const Word16 Bandwidth, + const Word16 LtpPitchLag, + const Word8 SmallerLags, + Word16 *FractionalResolution, + Word32 *Lag); + /*! r: PeriodicityIndex */ int16_t SearchPeriodicityIndex( const float Mdct[], /* i : Coefficients, Mdct[0..NumCoeffs-1] */ @@ -7735,6 +7766,10 @@ int16_t CountIndexBits( const int16_t Bandwidth, /* o : NB, 1: (S)WB */ const int16_t PeriodicityIndex ); +Word16 CountIndexBits_fx( + Word16 Bandwidth, /* 0: NB, 1: (S)WB */ + Word16 PeriodicityIndex ); + int16_t DecodeIndex( Decoder_State *st, const int16_t Bandwidth, /* o : NB, 1: (S)WB */ @@ -7749,6 +7784,12 @@ int16_t tcx_hm_render( Word16 p[] /* o : harmonic model (Q13) */ ); +Word32 tcx_hm_render_fx( + const Word32 lag, /* i: pitch lag Q0 */ + const Word16 fract_res, /* i: fractional resolution of the lag Q0 */ + Word16 p[] /* o: harmonic model Q13 */ +); + void tcx_hm_modify_envelope( const Word16 gain, /* i : HM gain (Q11) */ const int16_t lag, @@ -7758,6 +7799,15 @@ void tcx_hm_modify_envelope( const int16_t L_frame /* i : number of spectral lines */ ); +void tcx_hm_modify_envelope_fx( + const Word16 gain, /* i: HM gain Q11 */ + const Word32 lag, /* i: pitch lag Q0 */ + const Word16 fract_res, /* i: fractional resolution of the lag Q0 */ + const Word16 p[], /* i: harmonic model Q13 */ + Word32 env[], /* i/o: envelope Q16 */ + const Word16 L_frame /* i: number of spectral lines Q0 */ +); + void tcx_hm_analyse( const float abs_spectrum[], /* i : absolute spectrum */ const int16_t L_frame, /* i : number of spectral lines */ @@ -7780,6 +7830,16 @@ void tcx_hm_decode( int16_t *hm_bits /* o : bit consumption */ ); +void tcx_hm_decode_fx( + const Word16 L_frame, /* i : number of spectral lines */ + Word32 env[], /* i/o: envelope shape (Q16) */ + const Word16 targetBits, /* i : target bit budget */ + const Word16 coder_type, /* i : GC/VC coder type */ + const Word16 prm_hm[], /* i : HM parameters */ + const Word16 LtpPitchLag, /* i : LTP pitch lag or -1 if none */ + Word16 *hm_bits /* o : bit consumption */ +); + void coder_tcx( Encoder_State *st, /* i/o: encoder state structure */ TCX_CONFIG_HANDLE hTcxCfg, /* i : configuration of TCX */ diff --git a/lib_com/rom_com.c b/lib_com/rom_com.c index 316abf397..75157e8f4 100644 --- a/lib_com/rom_com.c +++ b/lib_com/rom_com.c @@ -26354,6 +26354,127 @@ const float * const Ratios[2][17] = } }; +/* 7Q8 */ +const Word16 Ratios_WB_2_fx[32] = +/* 2 */{ 768, 1024, 1280, 1536, 1792, 2048, 2304, 2560, 2816, 3072, 3328, 3584, 3840, 4096, 4352, 4608, 4864, 5120, 5376, 5632, 6144, 6656, 7168, 7680, 8192, 8704, 9216, 9728, 10240, 15360, 16384, 18432 }; +const Word16 Ratios_WB_3_fx[32] = +/* 3 */{ 256, 512, 768, 1024, 1280, 1536, 1792, 2048, 2304, 2560, 3072, 3584, 4096, 4608, 5120, 5632, 6144, 6656, 7168, 7680, 8192, 8704, 9216, 9728, 10240, 11264, 12288, 13824, 15360, 17408, 19968, 20480 }; +const Word16 Ratios_WB_4_fx[32] = +/* 4 */{ 384, 512, 640, 768, 1024, 1280, 1536, 1792, 2048, 2304, 2560, 3072, 3584, 4096, 4608, 5120, 5632, 6144, 6656, 7168, 7680, 8192, 8704, 9216, 9728, 10240, 10752, 11264, 12288, 13312, 13824, 17408 }; +const Word16 Ratios_WB_5_fx[32] = +/* 5 */{ 256, 384, 512, 640, 768, 1024, 1280, 1536, 1792, 2048, 2304, 2560, 2816, 3072, 3328, 3584, 3840, 4096, 4608, 5120, 5632, 6144, 6656, 7168, 7680, 8192, 8704, 9216, 10240, 11264, 12288, 13824 }; +const Word16 Ratios_WB_6_fx[32] = +/* 6 */{ 256, 384, 512, 640, 768, 896, 1024, 1152, 1280, 1408, 1536, 1664, 1792, 1920, 2048, 2304, 2560, 2816, 3072, 3328, 3584, 3840, 4096, 4608, 5120, 5632, 6144, 6656, 7168, 8704, 10240, 10496 }; +const Word16 Ratios_WB_7_fx[32] = +/* 7 */{ 256, 384, 512, 640, 768, 896, 1024, 1152, 1280, 1536, 1792, 2048, 2304, 2560, 2816, 3072, 3328, 3584, 3840, 4096, 4352, 4608, 4864, 5120, 5376, 5760, 6144, 6400, 6912, 7168, 7680, 8960 }; +const Word16 Ratios_WB_8_fx[16] = +/* 8 */{ 128, 256, 384, 512, 640, 768, 896, 1024, 1152, 1280, 1408, 1536, 1792, 2048, 2304, 2560 }; +const Word16 Ratios_WB_9_fx[16] = +/* 9 */{ 256, 512, 640, 768, 1024, 1280, 1536, 1792, 2048, 2304, 2560, 3072, 3840, 4096, 4608, 6912 }; +const Word16 Ratios_WB_10_fx[16] = +/* 10 */{ 256, 384, 512, 640, 768, 896, 1024, 1280, 1536, 2048, 2560, 3840, 4608, 5632, 6144, 6656 }; +const Word16 Ratios_WB_11_fx[16] = +/* 11 */{ 256, 384, 512, 640, 768, 896, 1024, 1280, 1536, 2048, 2560, 3072, 3328, 3584, 4608, 5376 }; +const Word16 Ratios_WB_12_fx[16] = +/* 12 */{ 128, 256, 384, 512, 640, 768, 1024, 1280, 1536, 2048, 2304, 2816, 3072, 3456, 4096, 5120 }; +const Word16 Ratios_WB_13_fx[16] = +/* 13 */{ 128, 256, 384, 512, 640, 768, 1024, 1280, 1536, 1792, 2048, 2560, 2816, 3072, 3584, 5120 }; +const Word16 Ratios_WB_14_fx[16] = +/* 14 */{ 128, 256, 384, 512, 640, 768, 1024, 1152, 1536, 1920, 2304, 2560, 3072, 3584, 3840, 4608 }; +const Word16 Ratios_WB_15_fx[16] = +/* 15 */{ 128, 256, 320, 384, 448, 512, 640, 768, 896, 1024, 1152, 1280, 1536, 2048, 2304, 3584 }; +const Word16 Ratios_WB_16_fx[4] = +/* 16 */{ 128, 256, 512, 1024 }; +const Word16 Ratios_WB_17_fx[4] = +/* 17 */{ 256, 384, 512, 1024 }; +const Word16 Ratios_WB_18_fx[4] = +/* 18 */{ 256, 512, 768, 1024 }; + +/******************************************************************************/ + +/* 7Q8 */ +const Word16 Ratios_NB_2_fx[32] = +/* 2 */{ 768, 1024, 1280, 1536, 1792, 2048, 2304, 2560, 2816, 3072, 3328, 3584, 3840, 4096, 4352, 4608, 4864, 5120, 5376, 5632, 5888, 6144, 6400, 6656, 6912, 7168, 7680, 8192, 8704, 9216, 9728, 10240 }; +const Word16 Ratios_NB_3_fx[16] = +/* 3 */{ 128, 256, 512, 768, 1024, 1280, 1536, 1792, 2048, 2304, 2560, 3072, 4096, 5120, 6144, 7680 }; +const Word16 Ratios_NB_4_fx[16] = +/* 4 */{ 512, 768, 1024, 1280, 1536, 1792, 2048, 2304, 2560, 3072, 3584, 4096, 4608, 5120, 6144, 7680 }; +const Word16 Ratios_NB_5_fx[16] = +/* 5 */{ 512, 768, 1024, 1280, 1536, 1792, 2048, 2304, 2560, 3072, 3584, 4096, 4608, 5120, 6144, 7680 }; +const Word16 Ratios_NB_6_fx[16] = +/* 6 */{ 512, 640, 768, 896, 1024, 1280, 1536, 1792, 2048, 2304, 2560, 3072, 3584, 4096, 4608, 5120 }; +const Word16 Ratios_NB_7_fx[16] = +/* 7 */{ 256, 512, 640, 768, 1024, 1280, 1536, 1792, 2048, 2304, 2560, 3072, 3584, 4096, 4608, 5120 }; +const Word16 Ratios_NB_8_fx[16] = +/* 8 */{ 256, 384, 512, 640, 768, 896, 1024, 1152, 1280, 1536, 1792, 2048, 2304, 2560, 3072, 4096 }; +const Word16 Ratios_NB_9_fx[8] = +/* 9 */{ 256, 512, 768, 1024, 1280, 1536, 2048, 2560 }; +const Word16 Ratios_NB_10_fx[8] = +/* 10 */{ 256, 512, 768, 1024, 1280, 1536, 2048, 2560 }; +const Word16 Ratios_NB_11_fx[8] = +/* 11 */{ 256, 384, 512, 768, 1024, 1280, 1536, 2048 }; +const Word16 Ratios_NB_12_fx[8] = +/* 12 */{ 256, 512, 640, 768, 1024, 1280, 1536, 2048 }; +const Word16 Ratios_NB_13_fx[4] = +/* 13 */{ 256, 512, 768, 1024 }; +const Word16 Ratios_NB_14_fx[4] = +/* 14 */{ 256, 512, 1024, 1536 }; +const Word16 Ratios_NB_15_fx[4] = +/* 15 */{ 256, 512, 768, 1024 }; +const Word16 Ratios_NB_16_fx[4] = +/* 16 */{ 256, 384, 512, 1024 }; +const Word16 Ratios_NB_17_fx[4] = +/* 17 */{ 256, 384, 512, 768 }; +const Word16 Ratios_NB_18_fx[4] = +/* 18 */{ 128, 256, 512, 768 }; + +/******************************************************************************/ + +const Word16 *const Ratios_fx[2][17] = +{ + /* NB */ + { + Ratios_NB_2_fx, + Ratios_NB_3_fx, + Ratios_NB_4_fx, + Ratios_NB_5_fx, + Ratios_NB_6_fx, + Ratios_NB_7_fx, + Ratios_NB_8_fx, + Ratios_NB_9_fx, + Ratios_NB_10_fx, + Ratios_NB_11_fx, + Ratios_NB_12_fx, + Ratios_NB_13_fx, + Ratios_NB_14_fx, + Ratios_NB_15_fx + , Ratios_NB_16_fx + , Ratios_NB_17_fx + , Ratios_NB_18_fx + }, + + /* WB */ + { + Ratios_WB_2_fx, + Ratios_WB_3_fx, + Ratios_WB_4_fx, + Ratios_WB_5_fx, + Ratios_WB_6_fx, + Ratios_WB_7_fx, + Ratios_WB_8_fx, + Ratios_WB_9_fx, + Ratios_WB_10_fx, + Ratios_WB_11_fx, + Ratios_WB_12_fx, + Ratios_WB_13_fx, + Ratios_WB_14_fx, + Ratios_WB_15_fx + , Ratios_WB_16_fx + , Ratios_WB_17_fx + , Ratios_WB_18_fx + } +}; + #define QGC(x) FL2WORD16_SCALE(x, 4) const Word16 qGains[2][1 << kTcxHmNumGainBits] = { diff --git a/lib_com/rom_com.h b/lib_com/rom_com.h index 1c84d3870..08abfedda 100644 --- a/lib_com/rom_com.h +++ b/lib_com/rom_com.h @@ -1473,6 +1473,42 @@ extern const float Ratios_NB_17[4]; extern const float Ratios_NB_18[4]; extern const float *const Ratios[2][17]; +extern const Word16 Ratios_WB_2_fx[32]; +extern const Word16 Ratios_WB_3_fx[32]; +extern const Word16 Ratios_WB_4_fx[32]; +extern const Word16 Ratios_WB_5_fx[32]; +extern const Word16 Ratios_WB_6_fx[32]; +extern const Word16 Ratios_WB_7_fx[32]; +extern const Word16 Ratios_WB_8_fx[16]; +extern const Word16 Ratios_WB_9_fx[16]; +extern const Word16 Ratios_WB_10_fx[16]; +extern const Word16 Ratios_WB_11_fx[16]; +extern const Word16 Ratios_WB_12_fx[16]; +extern const Word16 Ratios_WB_13_fx[16]; +extern const Word16 Ratios_WB_14_fx[16]; +extern const Word16 Ratios_WB_15_fx[16]; +extern const Word16 Ratios_WB_16_fx[4]; +extern const Word16 Ratios_WB_17_fx[4]; +extern const Word16 Ratios_WB_18_fx[4]; +extern const Word16 Ratios_NB_2_fx[32]; +extern const Word16 Ratios_NB_3_fx[16]; +extern const Word16 Ratios_NB_4_fx[16]; +extern const Word16 Ratios_NB_5_fx[16]; +extern const Word16 Ratios_NB_6_fx[16]; +extern const Word16 Ratios_NB_7_fx[16]; +extern const Word16 Ratios_NB_8_fx[16]; +extern const Word16 Ratios_NB_9_fx[8]; +extern const Word16 Ratios_NB_10_fx[8]; +extern const Word16 Ratios_NB_11_fx[8]; +extern const Word16 Ratios_NB_12_fx[8]; +extern const Word16 Ratios_NB_13_fx[4]; +extern const Word16 Ratios_NB_14_fx[4]; +extern const Word16 Ratios_NB_15_fx[4]; +extern const Word16 Ratios_NB_16_fx[4]; +extern const Word16 Ratios_NB_17_fx[4]; +extern const Word16 Ratios_NB_18_fx[4]; +extern const Word16 *const Ratios_fx[2][17]; + extern const Word16 qGains[2][1 << kTcxHmNumGainBits]; /*----------------------------------------------------------------------------------* diff --git a/lib_dec/ari_dec.c b/lib_dec/ari_dec.c index 31df466f0..fa8958660 100644 --- a/lib_dec/ari_dec.c +++ b/lib_dec/ari_dec.c @@ -100,6 +100,33 @@ int16_t ari_start_decoding_14bits_prm( return bp; } +Word16 ari_start_decoding_14bits_prm_fx( + const Word16 *ptr, + Word16 bp, + Tastat *s +) +{ + Word32 val; + Word16 i; + const Word16 *p; + + val = L_deposit_l(0); + + p = ptr + bp; + + FOR(i = 0; i < cbitsnew; i++) + { + val = L_or(L_shl(val, 1), *(p + i)); + } + s->low = L_deposit_l(0); + s->high = ari_q4new; + move32(); + s->value = val; + move32(); + + return add(bp, i); +} + /*--------------------------------------------------------------- * ari_decode_14bits_s17_ext() * diff --git a/lib_dec/ari_hm_dec.c b/lib_dec/ari_hm_dec.c index 9a8f03c89..d2d7ffe55 100644 --- a/lib_dec/ari_hm_dec.c +++ b/lib_dec/ari_hm_dec.c @@ -104,6 +104,30 @@ static int16_t tcx_hm_dequantize_gain( } +static Word16 tcx_hm_dequantize_gain_fx( + Word16 coder_type, /* i : coder type Q0 */ + Word16 gain_idx, /* i: quantization index Q0 */ + Word16 *gain /* o: dequantized gain Q11 */ +) +{ + + assert(0 <= coder_type && coder_type <= UNVOICED); + + /* safety check in case of bit errors */ + test(); + IF(!(0 <= gain_idx && LT_16(gain_idx, (1 << kTcxHmNumGainBits)))) + { + *gain = 0; + return 1; + } + + *gain = qGains[coder_type][gain_idx]; + move16(); + + return 0; +} + + /*-------------------------------------------------------------------* * tcx_hm_decode() * @@ -166,3 +190,77 @@ void tcx_hm_decode( return; } + +void tcx_hm_decode_fx( + const Word16 L_frame, /* i : number of spectral lines */ + Word32 env[], /* i/o: envelope shape (Q16) */ + const Word16 targetBits, /* i : target bit budget */ + const Word16 coder_type, /* i : GC/VC coder type */ + const Word16 prm_hm[], /* i : HM parameters */ + const Word16 LtpPitchLag, /* i : LTP pitch lag or -1 if none */ + Word16 *hm_bits /* o : bit consumption */ +) +{ + Word16 NumTargetBits; + Word16 fract_res; + Word32 lag; + Word16 gain; + Word16 L_frame_m_256; + Word16 p[2 * kTcxHmParabolaHalfWidth + 1]; + + + *hm_bits = 0; + move16(); + + L_frame_m_256 = sub(L_frame, 256); + + test(); + IF(!(EQ_16(coder_type, VOICED) || EQ_16(coder_type, GENERIC))) + { + /* A bit error was encountered */ + *hm_bits = -1; + move16(); + return; + } + + NumTargetBits = CountIndexBits_fx((L_frame_m_256 >= 0), prm_hm[1]); + + NumTargetBits = add(NumTargetBits, targetBits); + + if (EQ_16(coder_type, VOICED)) + { + NumTargetBits = add(NumTargetBits, kTcxHmNumGainBits); + } + + *hm_bits = add(sub(NumTargetBits, targetBits), 1); + move16(); + + /* Convert the index to lag */ + UnmapIndex_fx(prm_hm[1], (L_frame_m_256 >= 0), LtpPitchLag, + ((LE_16(NumTargetBits, kSmallerLagsTargetBitsThreshold)) || (L_frame_m_256 < 0)), + &fract_res, &lag); + test(); + test(); + + /* Render the harmonic model */ + IF(tcx_hm_render_fx(lag, fract_res, p)) + { + /* A bit error was encountered */ + *hm_bits = -1; + move16(); + return; + } + + /* Dequantize gain */ + IF(tcx_hm_dequantize_gain_fx((Word16)EQ_16(coder_type, VOICED), prm_hm[2], &gain)) + { + /* A bit error was encountered */ + *hm_bits = -1; + return; + } + + tcx_hm_modify_envelope_fx(gain, lag, fract_res, p, env, L_frame); + + + return; +} \ No newline at end of file diff --git a/lib_dec/arith_coder_dec.c b/lib_dec/arith_coder_dec.c index b2609cd73..12103c511 100644 --- a/lib_dec/arith_coder_dec.c +++ b/lib_dec/arith_coder_dec.c @@ -43,6 +43,7 @@ #include "basop_util.h" #include "basop_proto_func.h" #include "wmc_auto.h" +#include "prot_fx1.h" /*-------------------------------------------------------* * tcx_arith_decode() @@ -114,6 +115,75 @@ static int16_t tcx_arith_decode( return bp; } +static Word16 tcx_arith_decode_fx( + const Word16 L_frame, /* i : number of spectral lines */ + const Word16 envelope[], /* i : scaled envelope (Q15-e) */ + Word16 envelope_e, /* i : scaled envelope exponent (Q0) */ + const Word16 target_bits, /* i : target bit budget */ + const Word16 prm[], /* i : bitstream parameters */ + Word32 q_spectrum[], /* o : scalar quantized spectrum */ + Word16 *q_spectrum_e /* o : spectrum exponent */ +) +{ + Word16 bp, k, q; + UWord16 s; + Tastat as; + UWord16 exp_k; + Word16 tmp; + Word32 L_tmp; + + bp = ari_start_decoding_14bits_prm_fx( prm, 0, &as ); + + tmp = sub(envelope_e, 1); + + L_tmp = L_deposit_l(0); + + FOR (k = 0; k < L_frame; k++) + { + IF( envelope[k] == 0 ) /* safety check in case of bit errors */ + { + set32_fx(q_spectrum, 0, L_frame); + return -1; + } + ELSE + { + exp_k = expfp( negate( envelope[k] ), tmp ); + } + + /* decode line magnitude */ + bp = ari_decode_14bits_pow( prm, bp, target_bits, &q, &as, exp_k ); + + IF ( q != 0 ) + { + /* line is non-zero, decode sign */ + bp = ari_decode_14bits_sign( prm, bp, target_bits, &s, &as ); + q_spectrum[k] = L_mult(q, sub(3, shl(s, 1))); + q_spectrum[k] = L_shl(q_spectrum[k], 30 - SPEC_EXP_DEC); + } + ELSE + { + /* line is zero, no sign needed */ + q_spectrum[k] = L_deposit_l(0); + } + + IF (LE_32(as.high, as.low)) + { + IF ( LT_16(bp, target_bits) ) /* safety check in case of bit errors */ + { + bp = -1; + move16(); + } + BREAK; /* no bits left, so exit loop */ + } + } + *q_spectrum_e = SPEC_EXP_DEC; + move16(); + + set32_fx(q_spectrum + k, 0, sub(L_frame, k)); + + return bp; +} + /*-------------------------------------------------------* * tcx_arith_decode_envelope() @@ -219,3 +289,116 @@ void tcx_arith_decode_envelope( return; } + +void tcx_arith_decode_envelope_fx( + Decoder_State *st, /* i/o: coder state */ + Word32 q_spectrum[], /* o : quantised MDCT coefficients */ + Word16 *q_spectrum_e, /* o : MDCT exponent */ + const Word16 L_frame, /* i : frame or MDCT length */ + Word16 L_spec, /* i : length w/o BW limitation */ + const Word16 A_ind[], /* i : quantised LPC coefficients */ + const Word16 target_bits, /* i : number of available bits */ + const Word16 prm[], /* i : bitstream parameters */ + const Word16 use_hm, /* i : use HM in current frame? */ + const Word16 prm_hm[], /* i : HM parameter area */ + Word16 tcxltp_pitch, /* i : TCX LTP pitch in FD, -1 if n/a*/ + Word16 *arith_bits, /* o : bits used for ari. coding */ + Word16 *signaling_bits, /* o : bits used for signaling */ + const Word16 low_complexity /* i : low-complexity flag */ +) +{ + Word32 env[N_MAX_ARI]; /* unscaled envelope (Q16) */ + Word16 *envelope; /* scaled envelope (Q15-e) */ + Word16 envelope_e; + Word16 L_spec_core; + TCX_CONFIG_HANDLE hTcxCfg; + TCX_DEC_HANDLE hTcxDec; + Word16 gamma_w, gamma_uw; + Word16 hm_bits; + + IF(GT_16(L_spec, N_MAX_ARI) || (EQ_16(st->element_mode, EVS_MONO) && GT_16(target_bits, (ACELP_13k20 / FRAMES_PER_SEC))) || + (EQ_16(st->element_mode, IVAS_SCE) && (GT_16(st->bits_frame_nominal, (LPC_SHAPED_ARI_MAX_RATE / FRAMES_PER_SEC)))) || + (GT_16(st->element_mode, IVAS_SCE) && (GT_16(st->bits_frame_nominal, (LPC_SHAPED_ARI_MAX_RATE_CPE / FRAMES_PER_SEC)))) || + (target_bits <= 0)) + { + /* this could happen in case of bit errors */ + st->BER_detect = 1; + move16(); + L_spec = N_MAX_ARI; + move16(); + *signaling_bits = 0; + move16(); + *arith_bits = 0; + move16(); + set32_fx( q_spectrum, 0, L_frame ); + + return; + } + + hTcxCfg = st->hTcxCfg; + hTcxDec = st->hTcxDec; + *signaling_bits = 0; + + assert( hTcxDec->enableTcxLpc ); + gamma_w = MAX16B; + move16(); + gamma_uw = st->inv_gamma; + move16(); + +#define WMC_TOOL_SKIP + tcx_arith_render_envelope( A_ind, L_frame, L_spec, hTcxCfg->preemph_fac, gamma_w, gamma_uw, env ); +#undef WMC_TOOL_SKIP + + IF (use_hm != 0) + { + IF (prm_hm[0] != 0) + { + tcx_hm_decode_fx( L_spec, env, target_bits, st->coder_type, prm_hm, tcxltp_pitch, &hm_bits ); + + IF (hm_bits < 0) + { + st->BER_detect = 1; + move16(); + *signaling_bits = 0; + move16(); + *arith_bits = 0; + move16(); + set32_fx( q_spectrum, 0, L_frame ); + + return; + } + } + else + { + hm_bits = 1; + move16(); + } + *signaling_bits = add(*signaling_bits, hm_bits); + move16(); + } + + L_spec_core = L_spec; + move16(); + if ( st->igf ) + { + L_spec_core = s_min( L_spec_core, st->hIGFDec->infoIGFStartLine ); + } + + envelope = (Word16 *) env; + tcx_arith_scale_envelope( L_spec, L_spec_core, env, target_bits, low_complexity, envelope, &envelope_e ); + + *arith_bits = tcx_arith_decode_fx( L_spec, envelope, envelope_e, target_bits, prm, q_spectrum, q_spectrum_e ); + move16(); + + /* safety check in case of bit errors */ + IF ( *arith_bits < 0 ) + { + st->BER_detect = 1; + move16(); + set32_fx( q_spectrum, 0, L_frame ); + } + + set32_fx(q_spectrum + L_spec, 0, sub(L_frame, L_spec)); + + return; +} diff --git a/lib_dec/dec_tcx.c b/lib_dec/dec_tcx.c index 6715f5ece..320519d49 100644 --- a/lib_dec/dec_tcx.c +++ b/lib_dec/dec_tcx.c @@ -792,7 +792,19 @@ void decoder_tcx_invQ( prm_target = prm_sqQ; prm_sqQ = prm_target + 1; +#ifdef IVAS_FLOAT_FIXED + Word32 x_fx[N_MAX]; + Word16 x_e; + st->hTcxCfg->preemph_fac = FL2WORD16(st->hTcxCfg->preemph_fac_flt); + st->inv_gamma = FL2WORD16_SCALE(1 / st->gamma_float, 1); + tcx_arith_decode_envelope_fx( st, x_fx, &x_e, L_frame, L_spec, Aind, *prm_target, prm_sqQ, st->last_core_from_bs != ACELP_CORE, prm_hm, /* HM parameter area */ hTcxDec->tcx_hm_LtpPitchLag, &arith_bits, &signaling_bits, ( st->bwidth > WB ) ? 1 : 0 ); + for (int k = 0; k < N_MAX; ++k) + { + x[k] = ((float)x_fx[k] / ((unsigned)1 << (31 - x_e))); + } +#else tcx_arith_decode_envelope( st, x, L_frame, L_spec, Aind, *prm_target, prm_sqQ, st->last_core_from_bs != ACELP_CORE, prm_hm, /* HM parameter area */ hTcxDec->tcx_hm_LtpPitchLag, &arith_bits, &signaling_bits, ( st->bwidth > WB ) ? 1 : 0 ); +#endif hTcxDec->resQBits[frame_cnt] = *prm_target - arith_bits; -- GitLab