From 51ff74c1d2280a7c582468775bc7be6f4638d05d Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Tue, 28 Oct 2025 16:11:54 +0100 Subject: [PATCH 01/11] Update LC3plus to v.1.6.1 --- Workspace_msvc/lib_lc3plus.vcxproj | 16 +- lib_isar/isar_lc3plus_common.c | 2 +- lib_isar/isar_lc3plus_common.h | 2 +- lib_isar/isar_lc3plus_dec.c | 2 +- lib_isar/isar_lc3plus_dec.h | 2 +- lib_isar/isar_lc3plus_enc.c | 2 +- lib_isar/isar_lc3plus_enc.h | 2 +- lib_isar/isar_lc3plus_payload.h | 2 +- lib_lc3plus/adjust_global_gain_fx.c | 28 +- lib_lc3plus/al_fec.c | 137 +- lib_lc3plus/apply_global_gain_fx.c | 12 +- lib_lc3plus/ari_codec.c | 182 ++- lib_lc3plus/attack_detector_fx.c | 6 +- lib_lc3plus/basop_mpy_lc3plus.c | 30 +- lib_lc3plus/basop_mpy_lc3plus.h | 14 +- lib_lc3plus/basop_util_lc3plus.c | 216 ++- lib_lc3plus/basop_util_lc3plus.h | 45 +- lib_lc3plus/com_entropy.c | 27 + lib_lc3plus/constants.c | 1094 ++++++++++++++- lib_lc3plus/constants.h | 103 +- lib_lc3plus/cutoff_bandwidth.c | 6 +- lib_lc3plus/dct2_fx.c | 191 ++- lib_lc3plus/dct4_fx.c | 17 +- lib_lc3plus/dec_entropy.c | 861 ++++++++++-- lib_lc3plus/{dec_lc3.c => dec_lc3plus.c} | 204 ++- lib_lc3plus/defines.h | 263 +++- lib_lc3plus/detect_cutoff_warped_fx.c | 29 +- lib_lc3plus/dynmem.c | 2 + lib_lc3plus/enc_entropy.c | 377 ++++- lib_lc3plus/{enc_lc3.c => enc_lc3plus.c} | 225 ++- lib_lc3plus/estimate_global_gain_fx.c | 627 +++++++-- lib_lc3plus/fft_lc3plus.c | 23 +- lib_lc3plus/functions.h | 291 +++- lib_lc3plus/imdct_fx.c | 26 +- lib_lc3plus/{lc3.c => lc3plus.c} | 67 +- lib_lc3plus/{lc3.h => lc3plus.h} | 46 +- lib_lc3plus/levinson_fx.c | 4 +- lib_lc3plus/license.h | 8 +- lib_lc3plus/ltpf_coder_fx.c | 147 +- lib_lc3plus/ltpf_decoder_fx.c | 690 +++++++-- lib_lc3plus/makefile | 180 --- lib_lc3plus/mdct_fx.c | 8 +- lib_lc3plus/mdct_shaping_fx.c | 4 +- lib_lc3plus/near_nyquist_detector_fx.c | 49 +- lib_lc3plus/noise_factor_fx.c | 42 +- lib_lc3plus/noise_filling_fx.c | 24 +- lib_lc3plus/olpa_fx.c | 46 +- lib_lc3plus/pc_apply_fx.c | 18 +- lib_lc3plus/pc_classify_fx.c | 79 +- lib_lc3plus/pc_main_fx.c | 6 +- lib_lc3plus/pc_update_fx.c | 10 +- lib_lc3plus/per_band_energy_fx.c | 44 +- lib_lc3plus/plc_apply_fx.c | 53 +- lib_lc3plus/plc_classify_fx.c | 101 +- lib_lc3plus/plc_damping_scrambling_fx.c | 135 +- lib_lc3plus/plc_lpc_scaling_fx.c | 6 +- lib_lc3plus/plc_main_fx.c | 6 +- lib_lc3plus/plc_noise_substitution_fx.c | 4 +- lib_lc3plus/plc_phecu_f0_refine_first_fx.c | 4 +- lib_lc3plus/plc_phecu_fec_hq_fx.c | 11 +- lib_lc3plus/plc_phecu_lf_peak_analysis_fx.c | 4 +- lib_lc3plus/plc_phecu_peak_locator_fx.c | 4 +- lib_lc3plus/plc_phecu_setf0hz_fx.c | 4 +- lib_lc3plus/plc_phecu_tools_fx.c | 12 +- lib_lc3plus/plc_tdac_fx.c | 10 +- lib_lc3plus/plc_tdc_inverse_odft_fx.c | 23 +- lib_lc3plus/plc_tdc_lagwin_fx.c | 4 +- lib_lc3plus/plc_tdc_main_fx.c | 157 ++- lib_lc3plus/plc_tdc_pre_emphasis_fx.c | 29 +- lib_lc3plus/plc_update_aft_imdct_fx.c | 4 +- lib_lc3plus/plc_update_fx.c | 8 +- lib_lc3plus/plc_xcorr_fx.c | 4 +- lib_lc3plus/pvq_dec_fx.c | 136 +- lib_lc3plus/pvq_enc_fx.c | 718 +++++++++- lib_lc3plus/pvq_index_fx.c | 4 +- lib_lc3plus/quantize_spec_fx.c | 40 +- lib_lc3plus/reorder_bitstream_fx.c | 4 +- lib_lc3plus/resamp12k8_fx.c | 24 +- lib_lc3plus/residual_coding_fx.c | 56 +- lib_lc3plus/residual_decoding_fx.c | 56 +- lib_lc3plus/rom_basop_util_lc3plus.c | 66 +- lib_lc3plus/rom_basop_util_lc3plus.h | 18 +- lib_lc3plus/scale_signal24_fx.c | 4 +- lib_lc3plus/setup_com_lc3plus.c | 39 + .../{setup_dec_lc3.c => setup_dec_lc3plus.c} | 230 ++- .../{setup_dec_lc3.h => setup_dec_lc3plus.h} | 54 +- .../{setup_enc_lc3.c => setup_enc_lc3plus.c} | 319 ++++- .../{setup_enc_lc3.h => setup_enc_lc3plus.h} | 19 +- lib_lc3plus/sns_compute_scf_fx.c | 459 +++++- lib_lc3plus/sns_interpolate_scf_fx.c | 4 +- lib_lc3plus/sns_quantize_scf_fx.c | 1237 ++++++++++++++++- lib_lc3plus/tinywavein_c.h | 603 -------- lib_lc3plus/tinywaveout_c.h | 889 ------------ lib_lc3plus/tns_coder_fx.c | 49 +- lib_lc3plus/tns_decoder_fx.c | 34 +- 95 files changed, 9275 insertions(+), 2908 deletions(-) create mode 100644 lib_lc3plus/com_entropy.c rename lib_lc3plus/{dec_lc3.c => dec_lc3plus.c} (81%) rename lib_lc3plus/{enc_lc3.c => enc_lc3plus.c} (76%) rename lib_lc3plus/{lc3.c => lc3plus.c} (88%) rename lib_lc3plus/{lc3.h => lc3plus.h} (95%) delete mode 100644 lib_lc3plus/makefile mode change 100755 => 100644 lib_lc3plus/rom_basop_util_lc3plus.c create mode 100644 lib_lc3plus/setup_com_lc3plus.c rename lib_lc3plus/{setup_dec_lc3.c => setup_dec_lc3plus.c} (76%) rename lib_lc3plus/{setup_dec_lc3.h => setup_dec_lc3plus.h} (79%) rename lib_lc3plus/{setup_enc_lc3.c => setup_enc_lc3plus.c} (67%) rename lib_lc3plus/{setup_enc_lc3.h => setup_enc_lc3plus.h} (89%) delete mode 100644 lib_lc3plus/tinywavein_c.h delete mode 100644 lib_lc3plus/tinywaveout_c.h diff --git a/Workspace_msvc/lib_lc3plus.vcxproj b/Workspace_msvc/lib_lc3plus.vcxproj index 71bb8e2a1..4d937cf64 100644 --- a/Workspace_msvc/lib_lc3plus.vcxproj +++ b/Workspace_msvc/lib_lc3plus.vcxproj @@ -113,15 +113,15 @@ - + - + - + @@ -166,8 +166,8 @@ - - + + @@ -181,11 +181,11 @@ - + - - + + diff --git a/lib_isar/isar_lc3plus_common.c b/lib_isar/isar_lc3plus_common.c index 78269491c..28435cea9 100644 --- a/lib_isar/isar_lc3plus_common.c +++ b/lib_isar/isar_lc3plus_common.c @@ -33,7 +33,7 @@ #include "options.h" #include "isar_lc3plus_common.h" #include "ivas_error.h" -#include "lc3.h" +#include "lc3plus.h" /*-----------------------------------------------------------------------------------------* * Function ISAR_LC3PLUS_LC3plusErrToIvasErr() diff --git a/lib_isar/isar_lc3plus_common.h b/lib_isar/isar_lc3plus_common.h index b99348e0e..eb3e7b0ad 100644 --- a/lib_isar/isar_lc3plus_common.h +++ b/lib_isar/isar_lc3plus_common.h @@ -37,7 +37,7 @@ #include #include "options.h" #include "ivas_error.h" -#include "lc3.h" +#include "lc3plus.h" #include "isar_lc3plus_payload.h" /*! common configuration parameters between encoder and decoder */ diff --git a/lib_isar/isar_lc3plus_dec.c b/lib_isar/isar_lc3plus_dec.c index 279daee41..f8cbe9582 100644 --- a/lib_isar/isar_lc3plus_dec.c +++ b/lib_isar/isar_lc3plus_dec.c @@ -36,7 +36,7 @@ #include "ivas_prot_fx.h" #include "isar_lc3plus_dec.h" #include "isar_lc3plus_common.h" -#include "lc3.h" +#include "lc3plus.h" #include "ivas_error_utils.h" #include "wmc_auto.h" diff --git a/lib_isar/isar_lc3plus_dec.h b/lib_isar/isar_lc3plus_dec.h index f3e969940..8328b1fa7 100644 --- a/lib_isar/isar_lc3plus_dec.h +++ b/lib_isar/isar_lc3plus_dec.h @@ -35,7 +35,7 @@ #include #include "options.h" -#include "lc3.h" +#include "lc3plus.h" #include "ivas_error.h" #include "ivas_cnst.h" #include "isar_lc3plus_common.h" diff --git a/lib_isar/isar_lc3plus_enc.c b/lib_isar/isar_lc3plus_enc.c index 2ed3cdb7b..af89213e6 100644 --- a/lib_isar/isar_lc3plus_enc.c +++ b/lib_isar/isar_lc3plus_enc.c @@ -32,7 +32,7 @@ #include "isar_lc3plus_enc.h" #include "isar_lc3plus_common.h" -#include "lc3.h" +#include "lc3plus.h" #include "ivas_error_utils.h" #include "prot_fx.h" #include "wmc_auto.h" diff --git a/lib_isar/isar_lc3plus_enc.h b/lib_isar/isar_lc3plus_enc.h index f0c37afc8..6dd08733f 100644 --- a/lib_isar/isar_lc3plus_enc.h +++ b/lib_isar/isar_lc3plus_enc.h @@ -35,7 +35,7 @@ #include #include "ivas_error.h" -#include "lc3.h" +#include "lc3plus.h" #include "isar_lc3plus_common.h" #include "typedef.h" #include "isar_lc3plus_payload.h" diff --git a/lib_isar/isar_lc3plus_payload.h b/lib_isar/isar_lc3plus_payload.h index e95128578..580a58ca6 100644 --- a/lib_isar/isar_lc3plus_payload.h +++ b/lib_isar/isar_lc3plus_payload.h @@ -35,7 +35,7 @@ #include #include -#include "lc3.h" +#include "lc3plus.h" #include "options.h" diff --git a/lib_lc3plus/adjust_global_gain_fx.c b/lib_lc3plus/adjust_global_gain_fx.c index 0c3442061..5edf9b9fc 100644 --- a/lib_lc3plus/adjust_global_gain_fx.c +++ b/lib_lc3plus/adjust_global_gain_fx.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,6 +7,8 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "functions.h" @@ -20,7 +22,7 @@ void processAdjustGlobalGain_fx(Word16 *gg_idx, Word16 gg_idx_min, Word16 gg_idx Word16 *gain_e, Word16 target, Word16 nBits, Word16 *gainChange, Word16 fs_idx #ifdef ENABLE_HR_MODE - , Word16 hrmode, Word16 frame_dms + , Word16 hrmode, LC3PLUS_FrameDuration frame_dms #endif ) { @@ -53,7 +55,7 @@ void processAdjustGlobalGain_fx(Word16 *gg_idx, Word16 gg_idx_min, Word16 gg_idx #endif /* DYNMEM_COUNT */ #ifdef ENABLE_HR_MODE - IF (sub(frame_dms, 25) == 0) + IF (sub(frame_dms, LC3PLUS_FRAME_DURATION_2p5MS) == 0) { IF (sub(target, 520) < 0) { @@ -64,14 +66,14 @@ void processAdjustGlobalGain_fx(Word16 *gg_idx, Word16 gg_idx_min, Word16 gg_idx gg_idx_inc_max = 40; move16(); } } - ELSE IF (sub(frame_dms, 50) == 0) + ELSE IF (sub(frame_dms, LC3PLUS_FRAME_DURATION_5MS) == 0) { factor = 2; move16(); gg_idx_inc_max = 20; move16(); } - ELSE IF (sub(frame_dms, 75) == 0) + ELSE IF (sub(frame_dms, LC3PLUS_FRAME_DURATION_7p5MS) == 0) { - factor = 40265318; move16(); // factor = 1.2 * 2^25 + factor = 40265318; move16(); /* factor = 1.2 * 2^25 */ gg_idx_inc_max = 12 ; move16(); } ELSE @@ -116,17 +118,17 @@ void processAdjustGlobalGain_fx(Word16 *gg_idx, Word16 gg_idx_min, Word16 gg_idx IF (sub(nBits, target) > 0) { gg_idx_inc = sub(nBits, target); - IF (sub(frame_dms, 75) == 0) + IF (sub(frame_dms, LC3PLUS_FRAME_DURATION_7p5MS) == 0) { - gg_idx_inc = extract_l(L_shr_pos(Mpy_32_16_lc3plus(factor, gg_idx_inc), 10)); // Mpy_32_16_lc3plus(1.2*2^25, gg_idx_inc), 25 - 15) - gg_idx_inc = BASOP_Util_Divide1616_Scale_lc3plus(gg_idx_inc, delta, &gg_idx_inc_s); + gg_idx_inc = extract_l(L_shr_pos(Mpy_32_16_lc3plus(factor, gg_idx_inc), 10)); + gg_idx_inc = BASOP_Util_Divide1616_Scale(gg_idx_inc, delta, &gg_idx_inc_s); gg_idx_inc = shr_sat(gg_idx_inc, sub(15, gg_idx_inc_s)); - gg_idx_inc = add(gg_idx_inc, 1); // adding 1 instead of 1.2 + gg_idx_inc = add(gg_idx_inc, 1); } ELSE { gg_idx_inc = extract_l(L_mult0(gg_idx_inc, factor)); - gg_idx_inc = BASOP_Util_Divide1616_Scale_lc3plus(gg_idx_inc, delta, &gg_idx_inc_s); + gg_idx_inc = BASOP_Util_Divide1616_Scale(gg_idx_inc, delta, &gg_idx_inc_s); gg_idx_inc = shr_sat(gg_idx_inc, sub(15, gg_idx_inc_s)); gg_idx_inc = add(gg_idx_inc, factor); } @@ -164,9 +166,9 @@ void processAdjustGlobalGain_fx(Word16 *gg_idx, Word16 gg_idx_min, Word16 gg_idx #endif *gain_e = add(extract_l(L_shr_pos(L_tmp, 25)), 1); /* get exponent */ #ifdef ENABLE_HR_MODE - *gain = BASOP_Util_InvLog2_lc3plus(L_or(L_tmp, (Word32)0xFE000000)); + *gain = BASOP_Util_InvLog2(L_or(L_tmp, (Word32)0xFE000000)); #else - *gain = round_fx(BASOP_Util_InvLog2_lc3plus(L_or(L_tmp, (Word32)0xFE000000))); + *gain = round_fx(BASOP_Util_InvLog2(L_or(L_tmp, (Word32)0xFE000000))); #endif *gainChange = 1; move16(); } diff --git a/lib_lc3plus/al_fec.c b/lib_lc3plus/al_fec.c index efd1ed063..f8f1ee3b8 100644 --- a/lib_lc3plus/al_fec.c +++ b/lib_lc3plus/al_fec.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,6 +7,8 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "defines.h" @@ -43,7 +45,7 @@ #define ERROR_REPORT_EP1_OK ((0x1000)>>1) #define ERROR_REPORT_EP2_OK ((0x2000)>>1) #define ERROR_REPORT_EP3_OK ((0x4000)>>1) -#define ERROR_REPORT_EP4_OK ((0x8000)>>1) +#define ERROR_REPORT_EP4_OK ((0x8000)>>1) #define ERROR_REPORT_ALL_OK (ERROR_REPORT_EP1_OK | ERROR_REPORT_EP2_OK | ERROR_REPORT_EP3_OK | ERROR_REPORT_EP4_OK) /* debugging switches */ @@ -271,7 +273,7 @@ FEC_STATIC Word16 get_codeword_length(Word16 n_codewords, Word16 slot_nibbles, W ); slot_nibbles = sub(slot_nibbles, add(codeword_index, 1)); - slot_nibbles = sub(slot_nibbles, DEPR_i_mult(n_codewords, 13)); + slot_nibbles = sub(slot_nibbles, i_mult(n_codewords, 13)); FOR (i = 12; slot_nibbles >= 0; i++) { @@ -304,7 +306,7 @@ Word16 fec_get_data_size(Word16 fec_mode, Word16 ccc_flag, Word16 slot_bytes) } ELSE { - payload_size = sub(payload_size, DEPR_i_mult(sub(fec_mode, 1), n_codewords)); + payload_size = sub(payload_size, i_mult(sub(fec_mode, 1), n_codewords)); } IF (slot_bytes == 40) { @@ -336,7 +338,7 @@ Word16 fec_get_n_pc(Word16 fec_mode, Word16 n_pccw, Word16 slot_bytes) n_codewords = get_n_codewords(slot_bytes); assert(n_codewords == (2 * slot_bytes + RS16_CW_LEN_MAX - 1) / RS16_CW_LEN_MAX); - pc_split = DEPR_i_mult(DEPR_i_mult(n_pccw, -2), sub(fec_mode, 1)); + pc_split = i_mult(i_mult(n_pccw, -2), sub(fec_mode, 1)); IF (fec_mode == 1 || slot_bytes < 80) { @@ -499,9 +501,9 @@ void fec_encoder(Word16 mode, Word16 epmr, UWord8 *iobuf, Word16 data_bytes, Wor int tmp = slot_bytes; assert((slot_bytes >= FEC_SLOT_BYTES_MIN && slot_bytes <= FEC_SLOT_BYTES_MAX) && "fec_encoder: slot_bytes out of range"); - tmp -= mode == 1 ? 1 : n_codewords * (mode - 1); // reed solomon redundancy - tmp -= slot_bytes == 40 ? crc1_bytes_by_mode0[mode] : crc1_bytes_by_mode1[mode]; // crc1 - tmp -= (n_pccw > 0) && (mode > 1) ? crc2_bytes_by_mode[mode] : 0; // crc2 + tmp -= mode == 1 ? 1 : n_codewords * (mode - 1); /* reed solomon redundancy */ + tmp -= slot_bytes == 40 ? crc1_bytes_by_mode0[mode] : crc1_bytes_by_mode1[mode]; /* crc1 */ + tmp -= (n_pccw > 0) && (mode > 1) ? crc2_bytes_by_mode[mode] : 0; /* crc2 */ assert(data_bytes == tmp && "fec_encoder: inconsistent payload size"); assert(n_codewords - n_pccw >= 6); } @@ -631,7 +633,7 @@ FEC_STATIC void fec_interleave_pack(UWord8 *out, UWord8 *in, Word16 n_nibbles, W assert(codeword_length == (n_nibbles - i - 1) / n_codewords + 1); FOR (j = 0; j < codeword_length; j++) { - out_offset = add(DEPR_i_mult(j, n_codewords), i); + out_offset = add(i_mult(j, n_codewords), i); out_offset = sub(n_nibbles, add(out_offset, 1)); out[out_offset >> 1] = (UWord8)s_or(out[out_offset >> 1], shl(in[cw_offset], shl(s_and(out_offset, 1), 2))); move16(); @@ -781,7 +783,7 @@ int fec_decoder(UWord8 *iobuf, Word16 slot_bytes, int *data_bytes, Word16 *epmr, } } #endif - + IF (sub(*bfi, 1) == 0) { *data_bytes = 0; move16(); @@ -794,6 +796,7 @@ int fec_decoder(UWord8 *iobuf, Word16 slot_bytes, int *data_bytes, Word16 *epmr, *data_bytes = fec_get_data_size(mode, ccc_flag, slot_bytes); move32(); pc_split = fec_get_n_pc(mode, *n_pccw, slot_bytes); n_crc = get_total_crc_size(slot_bytes, mode, pc_split); + UNUSED(n_crc); /* decoding of first code word */ redundancy_nibbles = sub(hamming_distance_by_mode0[mode], 1); @@ -897,7 +900,7 @@ FEC_STATIC void fec_deinterleave_unpack(UWord8 *out, UWord8 *in, Word16 n_nibble codeword_length = get_codeword_length(n_codewords, n_nibbles, i); FOR (j = 0; j < codeword_length; (j++, out_offset++)) { - in_offset = add(DEPR_i_mult(j, n_codewords), i); + in_offset = add(i_mult(j, n_codewords), i); in_offset = sub(n_nibbles, add(in_offset, 1)); out[out_offset] = (UWord8)s_and(shr(in[in_offset >> 1], shl(s_and(in_offset, 1), 2)), 15); move16(); } @@ -1060,7 +1063,7 @@ FEC_STATIC int rs16_detect_and_correct(UWord8 *iobuf, int n_symb, int n_codeword n_mode_candidates = 0; move16(); risk_min_f.mantissa = SIMPLE_FLOAT_1_MANTISSA; move16(); risk_min_f.exponent = 0; move16(); - + IF (n_symb <= 80) { ep_risk_thresh.mantissa = EP_RISK_THRESH_NS_M; move16(); @@ -1071,16 +1074,16 @@ FEC_STATIC int rs16_detect_and_correct(UWord8 *iobuf, int n_symb, int n_codeword ep_risk_thresh.mantissa = EP_RISK_THRESH_OS_M; move16(); ep_risk_thresh.exponent = EP_RISK_THRESH_OS_E; move16(); } - + syndr_calc[0] = &rs16_calculate_two_syndromes; syndr_calc[1] = &rs16_calculate_four_syndromes; syndr_calc[2] = &rs16_calculate_six_syndromes; - + FOR (i = 0; i < FEC_N_MODES; i++) { t[i] = (Word8)shr(sub(hamming_distance[i], 1), 1); move16(); } - + syndromes = my_scratch; my_scratch += FEC_TOTAL_SYNDROME_SIZE; elp = my_scratch; @@ -1091,25 +1094,25 @@ FEC_STATIC int rs16_detect_and_correct(UWord8 *iobuf, int n_symb, int n_codeword my_scratch += FEC_TOTAL_ERROR_SIZE; deg_elp = (Word8 *)my_scratch; my_scratch += FEC_TOTAL_DEG_ELP_SIZE; - + *error_report = 0; move16(); *bfi = 0; move32(); - + /* mode detection (stage 1) */ codeword_length = get_codeword_length(n_codewords, n_symb, 0); - + epmr_position = sub(codeword_length, 1); - + rs16_calculate_two_syndromes(syndromes + SYNDROME_IDX(0, 0), iobuf, sub(codeword_length, 1)); - + IF (s_or(syndromes[0 + SYNDROME_IDX(0, 0)], syndromes[1 + SYNDROME_IDX(0, 0)]) == 0) { - + /* data validation for fec mode 1 */ *epmr = cw0_get_epmr(iobuf, epmr_position); - + dw0_bitswap(iobuf + 2, 1, n_symb / 2); - + IF (!crc1(iobuf + 8, sub(n_symb, 8), *epmr, iobuf + 2, 3, 1)) { mode = 0; move16(); @@ -1121,27 +1124,27 @@ FEC_STATIC int rs16_detect_and_correct(UWord8 *iobuf, int n_symb, int n_codeword { /* reverse bit swap */ dw0_bitswap(iobuf + 2, 1, n_symb / 2); - + *epmr = add(*epmr, 4); move16(); } } - + blacklist[0] = 1; move16(); - + /* mode detection (stage 2) */ - + /* calculate syndromes of code words 0 to 5 and modes 1 to 3 */ cw_offset = 0; move16(); - + FOR (cw_counter = 0; cw_counter < 6; cw_counter++) { codeword_length = get_codeword_length(n_codewords, n_symb, cw_counter); - + rs16_calculate_six_syndromes(syndromes + SYNDROME_IDX(1, cw_counter), iobuf + cw_offset, sub(codeword_length, 1)); - + cw_offset = add(cw_offset, codeword_length); - + FOR (mode_counter = FEC_N_MODES - 1; mode_counter >= 1; mode_counter--) { FOR (i = 0; i < sub(hamming_distance[mode_counter], 1); i++) @@ -1168,14 +1171,14 @@ FEC_STATIC int rs16_detect_and_correct(UWord8 *iobuf, int n_symb, int n_codeword n_broken_cw = add(n_broken_cw, 1); } } - + IF (n_broken_cw == 0) { mode = mode_counter; move16(); cw_offset = 0; move16(); - + *epmr = cw0_get_epmr(iobuf, epmr_position); - + FOR (cw_counter = 0; cw_counter < 6; cw_counter++) { codeword_length = get_codeword_length(n_codewords, n_symb, cw_counter); @@ -1187,7 +1190,7 @@ FEC_STATIC int rs16_detect_and_correct(UWord8 *iobuf, int n_symb, int n_codeword } } } - + IF (mode < 0) /* mode hasn't been detected so far -> errors occurred in transmission */ { /* calculate error locator polynomials for code words 0 to 5 */ @@ -1205,13 +1208,13 @@ FEC_STATIC int rs16_detect_and_correct(UWord8 *iobuf, int n_symb, int n_codeword } } } - + /* risk analysis for mode candidate selection */ FOR (mode_counter = 1; mode_counter < FEC_N_MODES; mode_counter++) { dec_risk_f[mode_counter].mantissa = SIMPLE_FLOAT_1_MANTISSA; move16(); dec_risk_f[mode_counter].exponent = 0; move16(); - + IF (blacklist[mode_counter] == 0) { FOR (cw_counter = 0; cw_counter < 6; cw_counter++) @@ -1220,26 +1223,26 @@ FEC_STATIC int rs16_detect_and_correct(UWord8 *iobuf, int n_symb, int n_codeword dec_risk_f[mode_counter], risk_table_f[mode_counter][deg_elp[DEG_ELP_IDX(mode_counter, cw_counter)]]); move16(); } - + IF (simple_float_cmp(dec_risk_f[mode_counter], ep_risk_thresh) <= 0) { mode_candidates[n_mode_candidates++] = mode_counter; move16(); } - + IF (simple_float_cmp(dec_risk_f[mode_counter], risk_min_f) < 0) { risk_min_f = dec_risk_f[mode_counter]; move16(); } } } - assert(n_mode_candidates <= 4); // suppress false gcc warning when OPTIM=3 - + assert(n_mode_candidates <= 4); /* suppress false gcc warning when OPTIM=3 */ + /* sort mode candidates by risk */ FOR (i = 0; i < n_mode_candidates; i++) { idx_min = i; move16(); val_min_f = dec_risk_f[mode_candidates[i]]; move16(); - + FOR (j = i + 1; j < n_mode_candidates; j++) { IF (simple_float_cmp(dec_risk_f[mode_candidates[j]], val_min_f) < 0) @@ -1248,24 +1251,24 @@ FEC_STATIC int rs16_detect_and_correct(UWord8 *iobuf, int n_symb, int n_codeword idx_min = j; move16(); } } - + IF (sub(idx_min, i) > 0) - { + { tmp = mode_candidates[i]; move16(); mode_candidates[i] = mode_candidates[idx_min]; move16(); mode_candidates[idx_min] = tmp; move16(); } } - + /* try out candidate modes */ FOR (i = 0; i < n_mode_candidates; i++) { mode = mode_candidates[i]; move16(); - + FOR (cw_counter = 0; cw_counter < 6; cw_counter++) { codeword_length = get_codeword_length(n_codewords, n_symb, cw_counter); - + IF (deg_elp[DEG_ELP_IDX(mode, cw_counter)]) { IF (rs16_factorize_elp(err_pos + ERR_POS_IDX(mode, cw_counter), elp + ELP_IDX(mode, cw_counter), @@ -1283,34 +1286,34 @@ FEC_STATIC int rs16_detect_and_correct(UWord8 *iobuf, int n_symb, int n_codeword BREAK; } } - + IF (mode < 0) { /* no decodable mode has been found */ *error_report = ERROR_REPORT_BEC_MASK; move16(); *bfi = 1; move32(); mode = -1; move16(); - + *epmr = fec_estimate_epmr_from_cw0(iobuf, t, syndromes, elp, deg_elp, err_pos, err_symb, n_codewords, n_symb); - + Dyn_Mem_Deluxe_Out(); return mode; } - + /* perform error correction */ cw_offset = 0; move16(); *error_report = 0; move16(); FOR (cw_counter = 0; cw_counter < 6; cw_counter++) { codeword_length = get_codeword_length(n_codewords, n_symb, cw_counter); - + IF (deg_elp[DEG_ELP_IDX(mode, cw_counter)]) { rs16_calculate_errors( err_symb + ERR_SYMB_IDX(mode, cw_counter), err_pos + ERR_POS_IDX(mode, cw_counter), syndromes + SYNDROME_IDX(mode, cw_counter), deg_elp[DEG_ELP_IDX(mode, cw_counter)], t[mode]); - + /* correct errors and sum up number of corrected bits */ FOR (i = 0; i < deg_elp[DEG_ELP_IDX(mode, cw_counter)]; i++) { @@ -1329,17 +1332,17 @@ FEC_STATIC int rs16_detect_and_correct(UWord8 *iobuf, int n_symb, int n_codeword } } } - + FOR (i = 0; i <= EP_SIG_POLY_DEG; i++) { iobuf[cw_offset + i] = GF16_ADD(iobuf[cw_offset + i], sig_polys[mode][i]); } cw_offset = add(cw_offset, codeword_length); } - + /* set epmr according to risk value of cw0 */ epmr_dec_fail_increment = 8; - + IF (add(risk_table_f[mode][deg_elp[DEG_ELP_IDX(mode, 0)]].exponent, 8) <= 0) { epmr_dec_fail_increment = sub(epmr_dec_fail_increment, 4); @@ -1348,10 +1351,10 @@ FEC_STATIC int rs16_detect_and_correct(UWord8 *iobuf, int n_symb, int n_codeword { epmr_dec_fail_increment = sub(epmr_dec_fail_increment, 4); } - + *epmr = cw0_get_epmr(iobuf, epmr_position) + epmr_dec_fail_increment; } - + /* mode has been successfully detected -> now check and try to correct remaining code words*/ *n_pccw = fec_get_n_pccw(n_symb / 2, mode + 1, ccc_flag); IF (ccc_flag == 0) @@ -1363,15 +1366,15 @@ FEC_STATIC int rs16_detect_and_correct(UWord8 *iobuf, int n_symb, int n_codeword { n_pccw0 = 0; } - + FOR (cw_counter = 6; cw_counter < n_codewords; cw_counter++) { /* usual error correction scheme: syndromes -> elp's, errors, etc. */ codeword_length = get_codeword_length(n_codewords, n_symb, cw_counter); array_of_trust[n_codewords - 1 - cw_counter] = 1; move16(); - + syndr_calc[sub(t[mode], 1)](syndromes, iobuf + cw_offset, sub(codeword_length, 1)); - + deg_elp[0] = rs16_calculate_elp(elp, syndromes, t[mode]); move16(); FOR (i = 0; i < mode; i ++) @@ -1393,7 +1396,7 @@ FEC_STATIC int rs16_detect_and_correct(UWord8 *iobuf, int n_symb, int n_codeword *error_report = ERROR_REPORT_BEC_MASK; move16(); mode = -1; move16(); *bfi = 1; move32(); - + BREAK; } ELSE @@ -1403,7 +1406,7 @@ FEC_STATIC int rs16_detect_and_correct(UWord8 *iobuf, int n_symb, int n_codeword CONTINUE; } } - + IF (deg_elp[0]) { IF (rs16_factorize_elp(err_pos, elp, deg_elp[0], sub(codeword_length, 1))) @@ -1418,7 +1421,7 @@ FEC_STATIC int rs16_detect_and_correct(UWord8 *iobuf, int n_symb, int n_codeword *error_report = ERROR_REPORT_BEC_MASK; move16(); mode = -1; move16(); *bfi = 1; move32(); - + BREAK; } ELSE @@ -1428,9 +1431,9 @@ FEC_STATIC int rs16_detect_and_correct(UWord8 *iobuf, int n_symb, int n_codeword CONTINUE; } } - + rs16_calculate_errors(err_symb, err_pos, syndromes, deg_elp[0], t[mode]); - + /* correct errors and sum up number of corrected bits */ FOR (i = 0; i < deg_elp[0]; i++) { @@ -1459,7 +1462,7 @@ FEC_STATIC int rs16_detect_and_correct(UWord8 *iobuf, int n_symb, int n_codeword { return add(mode, 1); } - + return -1; } diff --git a/lib_lc3plus/apply_global_gain_fx.c b/lib_lc3plus/apply_global_gain_fx.c index 14b75f5c7..7fa960267 100644 --- a/lib_lc3plus/apply_global_gain_fx.c +++ b/lib_lc3plus/apply_global_gain_fx.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,11 +7,13 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "functions.h" void processApplyGlobalGain_fx(Word32 x[], Word16 *x_e, Word16 xLen, Word16 global_gain_idx, Word16 global_gain_off) { - Word32 i; + Counter i; #ifdef ENABLE_HR_MODE Word32 global_gain; #else @@ -31,7 +33,7 @@ void processApplyGlobalGain_fx(Word32 x[], Word16 *x_e, Word16 xLen, Word16 glob #ifdef ENABLE_HR_MODE /* 1 / (28 * log 2) is 0x797D in Q18, L_shl_pos by 7 results in Q25 tmp32 */ /* round(2^31 / (28 * log10(2))) = 254778081 */ - //tmp32 = L_shl_pos(Mpy_32_16_lc3plus(254778081, add(global_gain_idx, global_gain_off)), 9); + Word32 mh; UWord16 ml; @@ -39,11 +41,11 @@ void processApplyGlobalGain_fx(Word32 x[], Word16 *x_e, Word16 xLen, Word16 glob tmp32 = L_shl_pos(mh, 9) | L_deposit_l((shr((Word16)ml, 7)) & 0x1ff); move16(); /* Uses an argument in Q25 */ - global_gain = BASOP_Util_InvLog2_lc3plus(L_or(tmp32, (Word32)0xFE000000)); + global_gain = BASOP_Util_InvLog2(L_or(tmp32, (Word32)0xFE000000)); #else tmp32 = L_shl_pos(L_mult0(add(global_gain_idx, global_gain_off), 0x797D), 7); /* Uses an argument in Q25 */ - global_gain = round_fx(BASOP_Util_InvLog2_lc3plus(L_or(tmp32, (Word32)0xFE000000))); + global_gain = round_fx(BASOP_Util_InvLog2(L_or(tmp32, (Word32)0xFE000000))); #endif global_gain_e = add(extract_l(L_shr_pos(tmp32, 25)), 1); diff --git a/lib_lc3plus/ari_codec.c b/lib_lc3plus/ari_codec.c index 72e5f0b12..05055122d 100644 --- a/lib_lc3plus/ari_codec.c +++ b/lib_lc3plus/ari_codec.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.4.5 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,6 +7,8 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "functions.h" @@ -73,7 +75,16 @@ static Word16 ac_enc_finish_fx(UWord8 *ptr, Word16 *bp, Encoder_State_fx *st_fx static Word16 ac_decode_fx( /* o : Decoded cumulative frequency */ Decoder_State_fx *st_fx, /* i/o: Decoder State */ - Word16 pki); + Word16 pki +#ifdef CR13_B_FIX_PC_BINS + , + Word16 *bp, + Word16 *bp_side, + Word16 *mask_side, + Word16 cur_bin, + Word16 from_left +#endif + ); static Word16 ac_decode_tns_order( /* o : Decoded cumulative frequency */ Decoder_State_fx *st_fx, /* i/o: Decoder State */ Word16 enable_lpc_weighting); @@ -99,7 +110,7 @@ Word16 processAriEncoder_fx(UWord8 *bytes, Word16 bp_side_in, Word16 mask_side_i Dyn_Mem_Deluxe_In(Encoder_State_fx st; Word16 bp, bp_side, mask_side, extra_bits; Word32 a1, b1, a1_i, b1_i, a1_msb, b1_msb; Word16 lev1; Word16 nbits_side; Word16 tmp; - Word16 fill_bits; UWord8 * ptr; Word16 numResBitsEnc; Word16 * lsb, nlsbs; Word32 i, n, k, lev;); + Word16 fill_bits; UWord8 * ptr; Word16 numResBitsEnc; Word16 * lsb, nlsbs; Counter i, n, k, lev;); lsb = (Word16 *)scratchAlign(scratchBuffer, 0); /* size = 2 * lastnz */ @@ -743,7 +754,7 @@ Word16 processAriEncoder_fx(UWord8 *bytes, Word16 bp_side_in, Word16 mask_side_i void processAriDecoder_fx(UWord8 *bytes, Word16 *bp_side, Word16 *mask_side, Word16 nbbits, Word16 L_spec, Word16 fs_idx, Word16 enable_lpc_weighting, Word16 tns_numfilters, Word16 lsbMode, Word16 lastnz, Word16 *bfi, Word16 *tns_order, Word16 fac_ns_idx, Word16 gg_idx, - Word16 frame_dms, + LC3PLUS_FrameDuration frame_dms, Word16 n_pc, Word16 be_bp_left, Word16 be_bp_right, Word16 mode, Word16 *spec_inv_idx, Word16 *b_left, Word16 *resBits, @@ -777,8 +788,8 @@ void processAriDecoder_fx(UWord8 *bytes, Word16 *bp_side, Word16 *mask_side, Wor Word16 lsb_ind_c; Word16 * lsb_ind; Word16 tmp; - Word32 n, k, lev; - Word32 i; + Counter n, k, lev; + Counter i; Word16 max_lev = 14; #ifdef DYNMEM_COUNT @@ -825,7 +836,7 @@ Decoder_State_fx st; if (fs_idx != 5) /* Don't update rateFlag for 96000 Hz */ #endif { - if (sub(nbbits, add(160, DEPR_i_mult(fs_idx, 160))) > 0) + if (sub(nbbits, add(160, i_mult(fs_idx, 160))) > 0) { rateFlag = 2 << NBITS_CONTEXT; move16(); @@ -865,11 +876,11 @@ ac_dec_init_fx(ptr, &bp, bp_side, mask_side, &st); /* Decode TNS data */ tmp = MAXLAG; -IF (sub(frame_dms, 25) == 0) +IF (sub(frame_dms, LC3PLUS_FRAME_DURATION_2p5MS) == 0) { tmp = shr_pos(tmp, 1); } -IF (sub(frame_dms, 50) == 0) +IF (sub(frame_dms, LC3PLUS_FRAME_DURATION_5MS) == 0) { tmp = shr_pos(tmp, 1); } @@ -928,7 +939,16 @@ if (sub(k, nt_half) > 0) t = add(t, 1 << NBITS_CONTEXT); } - r = ac_decode_fx(&st, ari_spec_lookup[t]); + r = ac_decode_fx(&st, ari_spec_lookup[t] +#ifdef CR13_B_FIX_PC_BINS + , + &bp, + bp_side, + mask_side, + k, + 1 +#endif + ); if (ac_dec_update_fx(ptr, &bp, bp_side, mask_side, k, &st, ari_spec_cumfreq[ari_spec_lookup[t]][r], ari_spec_freq[ari_spec_lookup[t]][r]) != 0) { @@ -987,7 +1007,16 @@ if (check_pc_bytes(&bp, bp_side, mask_side, a1_i, 0, &st.pc) != 0) GOTO ber_detect; } b = read_bit(ptr, bp_side, mask_side); - r = ac_decode_fx(&st, ari_spec_lookup[t + Tab_esc_nb[1]]); + r = ac_decode_fx(&st, ari_spec_lookup[t + Tab_esc_nb[1]] +#ifdef CR13_B_FIX_PC_BINS + , + &bp, + bp_side, + mask_side, + k, + 1 +#endif + ); if (ac_dec_update_fx(ptr, &bp, bp_side, mask_side, k, &st, ari_spec_cumfreq[ari_spec_lookup[t + Tab_esc_nb[1]]][r], ari_spec_freq[ari_spec_lookup[t + Tab_esc_nb[1]]][r]) != 0) @@ -1043,7 +1072,16 @@ if (check_pc_bytes(&bp, bp_side, mask_side, a1_i, 0, &st.pc) != 0) FOR (lev = 2; lev < max_lev; lev++) { esc_nb = s_min(lev, 3); - r = ac_decode_fx(&st, ari_spec_lookup[t + Tab_esc_nb[esc_nb]]); + r = ac_decode_fx(&st, ari_spec_lookup[t + Tab_esc_nb[esc_nb]] +#ifdef CR13_B_FIX_PC_BINS + , + &bp, + bp_side, + mask_side, + k, + 1 +#endif + ); if (ac_dec_update_fx(ptr, &bp, bp_side, mask_side, k, &st, ari_spec_cumfreq[ari_spec_lookup[t + Tab_esc_nb[esc_nb]]][r], ari_spec_freq[ari_spec_lookup[t + Tab_esc_nb[esc_nb]]][r]) != 0) @@ -1153,7 +1191,16 @@ if (sub(k, nt_half) > 0) t = add(t, 1 << NBITS_CONTEXT); } - r = ac_decode_fx(&st, ari_spec_lookup[t]); + r = ac_decode_fx(&st, ari_spec_lookup[t] +#ifdef CR13_B_FIX_PC_BINS + , + &bp, + bp_side, + mask_side, + k, + 1 +#endif + ); if (ac_dec_update_fx(ptr, &bp, bp_side, mask_side, k, &st, ari_spec_cumfreq[ari_spec_lookup[t]][r], ari_spec_freq[ari_spec_lookup[t]][r]) != 0) { @@ -1202,7 +1249,16 @@ if (check_pc_bytes(&bp, bp_side, mask_side, b1_i, 0, &st.pc) != 0) } ELSE { - r = ac_decode_fx(&st, ari_spec_lookup[t + Tab_esc_nb[1]]); + r = ac_decode_fx(&st, ari_spec_lookup[t + Tab_esc_nb[1]] +#ifdef CR13_B_FIX_PC_BINS + , + &bp, + bp_side, + mask_side, + k, + 1 +#endif + ); if (ac_dec_update_fx(ptr, &bp, bp_side, mask_side, k, &st, ari_spec_cumfreq[ari_spec_lookup[t + Tab_esc_nb[1]]][r], ari_spec_freq[ari_spec_lookup[t + Tab_esc_nb[1]]][r]) != 0) @@ -1260,7 +1316,16 @@ if (check_pc_bytes(&bp, bp_side, mask_side, a1_i, 0, &st.pc) != 0) FOR (lev = 2; lev < max_lev; lev++) { esc_nb = s_min(lev, 3); - r = ac_decode_fx(&st, ari_spec_lookup[t + Tab_esc_nb[esc_nb]]); + r = ac_decode_fx(&st, ari_spec_lookup[t + Tab_esc_nb[esc_nb]] +#ifdef CR13_B_FIX_PC_BINS + , + &bp, + bp_side, + mask_side, + k, + 1 +#endif + ); if (ac_dec_update_fx(ptr, &bp, bp_side, mask_side, k, &st, ari_spec_cumfreq[ari_spec_lookup[t + Tab_esc_nb[esc_nb]]][r], ari_spec_freq[ari_spec_lookup[t + Tab_esc_nb[esc_nb]]][r]) != 0) @@ -1397,6 +1462,14 @@ GOTO ber_detect; move16(); i=0; +#ifdef CR9_C_ADD_1p25MS + Counter l, lMax = 1; + if (frame_dms == LC3PLUS_FRAME_DURATION_1p25MS) { + lMax = 3; + } + FOR (l = 0; l < lMax; l++) + { +#endif #ifdef ENABLE_HR_MODE FOR (k = 0; k < L_spec; k++) { @@ -1443,7 +1516,9 @@ GOTO ber_detect; } } #endif - +#ifdef CR9_C_ADD_1p25MS + } +#endif #ifdef ENABLE_HR_MODE if (hrmode) { @@ -1711,7 +1786,7 @@ void processAriDecoderScaling_fx( #endif Word16 dataLen, Word32 *data32, Word16 *data_e) { - Word32 i; + Counter i; #ifdef ENABLE_HR_MODE Dyn_Mem_Deluxe_In(Word16 shift; Word32 tmp, x_min, x_max;); @@ -1802,7 +1877,7 @@ Word16 find_last_nz_pair(const Word32 x[], Word16 length) Word16 find_last_nz_pair(const Word16 x[], Word16 length) #endif { - Dyn_Mem_Deluxe_In(Word16 last_nz, lobs[4]; Word32 stage, i;); + Dyn_Mem_Deluxe_In(Word16 last_nz, lobs[4]; Counter stage, i;); lobs[0] = 4; move16(); @@ -1866,7 +1941,7 @@ void write_bit_backward(UWord8 *ptr, Word16 *bp, Word16 *mask, Word16 bit) void write_indice_backward(UWord8 *ptr, Word16 *bp, Word16 *mask, Word16 indice, Word16 numbits) { - Dyn_Mem_Deluxe_In(Word32 k; Word16 bit;); + Dyn_Mem_Deluxe_In(Counter k; Word16 bit;); FOR (k = 0; k < numbits; k++) { @@ -1881,7 +1956,7 @@ void write_indice_backward(UWord8 *ptr, Word16 *bp, Word16 *mask, Word16 indice, static __forceinline void write_indice_forward(UWord8 *ptr, Word16 bp, Word16 indice, Word16 numbits) { - Dyn_Mem_Deluxe_In(Word32 k; Word16 bit, mask, tmp;); + Dyn_Mem_Deluxe_In(Counter k; Word16 bit, mask, tmp;); tmp = (Word16)ptr[bp]; move16(); @@ -2093,7 +2168,7 @@ __forceinline Word16 read_bit(UWord8 *ptr, Word16 *bp, Word16 *mask) static __forceinline void ac_dec_init_fx(UWord8 *ptr, Word16 *bp, Word16 *bp_side, Word16 *mask_side, Decoder_State_fx *st_fx) /* i/o: Decoder State */ { - Dyn_Mem_Deluxe_In(Word32 i;); + Dyn_Mem_Deluxe_In(Counter i;); st_fx->ac_low_fx = L_deposit_l(0); @@ -2119,11 +2194,74 @@ static __forceinline void ac_dec_init_fx(UWord8 *ptr, Word16 *bp, Word16 *bp_sid Dyn_Mem_Deluxe_Out(); } +#ifdef CR13_B_FIX_PC_BINS +static Word16 pc_check_bytes_ac_decode_fx( + Word16 *bp, + Word16 *bp_side, + Word16 *mask_side, + Word16 cur_bin, + Word16 from_left, + Pc_State_fx *pc +) +{ + Word16 bp_local, bp_side_local; + + if (pc->bytes > 0) + { + bp_local = *bp; + bp_side_local = *bp_side; + + if (from_left) + { + if (*mask_side == 1) + { + bp_side_local = add(bp_side_local, 1); + } + } + else + { + bp_local = sub(bp_local, 1); + } + + if (!pc->enc && pc->b_right > -1) + { + if (pc->bfi == 2) + { + if (pc->c_bp && bp_local > pc->be_bp_left) + { + pc->inv_bin = cur_bin; + return 1; + } + } + } + } + + return 0; +} +#endif + /* o : Decoded cumulative frequency */ static __forceinline Word16 ac_decode_fx(Decoder_State_fx *st_fx, /* i/o: Decoder State */ - Word16 pki) + Word16 pki +#ifdef CR13_B_FIX_PC_BINS + , + Word16 *bp, + Word16 *bp_side, + Word16 *mask_side, + Word16 cur_bin, + Word16 from_left +#endif + ) { Dyn_Mem_Deluxe_In(UWord16 sgn; Word16 val, r;); + +#ifdef CR13_B_FIX_PC_BINS + IF (pc_check_bytes_ac_decode_fx(bp, bp_side, mask_side, cur_bin, from_left, &st_fx->pc)) + { + st_fx->BER_detect = 1; + return 0; + } +#endif st_fx->ac_help_fx = UL_lshr_pos(st_fx->ac_range_fx, 10); move32(); diff --git a/lib_lc3plus/attack_detector_fx.c b/lib_lc3plus/attack_detector_fx.c index fad58543b..dd2541fd6 100644 --- a/lib_lc3plus/attack_detector_fx.c +++ b/lib_lc3plus/attack_detector_fx.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,6 +7,8 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "functions.h" void attack_detector_fx(LC3PLUS_Enc *enc, EncSetup *setup, Word16 *input, Word16 input_scaling, void *scratch) @@ -21,7 +23,7 @@ void attack_detector_fx(LC3PLUS_Enc *enc, EncSetup *setup, Word16 *input, Word16 block_energy = scratchAlign(scratch, 0); input_16k = scratchAlign(block_energy, 4 * 4 + 4); - frame_length_16k = DEPR_i_mult(enc->attdec_nblocks, 40); + frame_length_16k = i_mult(enc->attdec_nblocks, 40); IF (setup->attack_handling) { diff --git a/lib_lc3plus/basop_mpy_lc3plus.c b/lib_lc3plus/basop_mpy_lc3plus.c index aa29bf209..b570b9358 100644 --- a/lib_lc3plus/basop_mpy_lc3plus.c +++ b/lib_lc3plus/basop_mpy_lc3plus.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,6 +7,8 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "defines.h" #include "functions.h" @@ -31,6 +33,32 @@ Word32 Mpy_32_16_0(Word32 x, Word16 y) } #endif +/* Is this port necessary ? */ +#ifdef CR9_C_ADD_1p25MS_LRSNS +#if !defined(__arm__) && !defined(__hexagon__) +/*#define Mpy_32_16_0_DEFINED */ +/* +Word32 Mpy_32_16_0(Word32 x, Word16 y) +{ + Word32 z; + + z = L_shr(L_add(Mpy_32_16_lc3plus(x, y), 1), 1); + + return (z); +} +*/ + + + +Word32 Mpy_32_16_0_0(Word32 x, Word16 y) +{ + Word32 z; + z = L_shr_pos(Mpy_32_16_lc3plus(x, y), 1); /* stay downshifted, no rounding, to exactly match a single SMULWB */ + return (z); +} +#endif +#endif + Word32 Mpy_32_16_lc3plus(Word32 x, Word16 y) { Word32 mh; diff --git a/lib_lc3plus/basop_mpy_lc3plus.h b/lib_lc3plus/basop_mpy_lc3plus.h index 055a27fd1..7d45f6fff 100644 --- a/lib_lc3plus/basop_mpy_lc3plus.h +++ b/lib_lc3plus/basop_mpy_lc3plus.h @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,10 +7,12 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "defines.h" -#ifndef __BASOP_MPY_LC3PLUS_H -#define __BASOP_MPY_LC3PLUS_H +#ifndef __BASOP_MPY_H +#define __BASOP_MPY_H #include "functions.h" @@ -24,6 +26,10 @@ Word32 Mac_32_32_0(Word32 z, Word32 x, Word32 y); Word32 Msu_32_16_0(Word32 z, Word32 x, Word16 y); Word32 Msu_32_32_0(Word32 z, Word32 x, Word32 y); +#ifdef CR9_C_ADD_1p25MS_LRSNS +Word32 Mpy_32_16_0_0(Word32 x, Word16 y); /* non-rounding, no upshift */ +#endif + /** * \brief 32*16 Bit fractional Multiplication using 40 bit OPS * Performs a multiplication of a 32-bit variable x by @@ -69,4 +75,4 @@ void cplxMpy_32_16(Word32 *c_Re, Word32 *c_Im, const Word32 a_Re, const Word32 a void cplxMpy_32_32(Word32 *c_Re, Word32 *c_Im, const Word32 a_Re, const Word32 a_Im, const Word32 b_Re, const Word32 b_Im); -#endif /* __BASOP_MPY_LC3PLUS_H */ +#endif /* __BASOP_MPY_H */ diff --git a/lib_lc3plus/basop_util_lc3plus.c b/lib_lc3plus/basop_util_lc3plus.c index bb2c0413a..bb7f572d3 100644 --- a/lib_lc3plus/basop_util_lc3plus.c +++ b/lib_lc3plus/basop_util_lc3plus.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,21 +7,23 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "defines.h" #include "functions.h" #include "rom_basop_util_lc3plus.h" #include "basop_util_lc3plus.h" -extern const Word32 SqrtTable_lc3plus[32]; -extern const Word16 SqrtDiffTable_lc3plus[32]; +extern const Word32 SqrtTable[32]; +extern const Word16 SqrtDiffTable[32]; -extern const Word32 ISqrtTable_lc3plus[32]; -extern const Word16 ISqrtDiffTable_lc3plus[32]; +extern const Word32 ISqrtTable[32]; +extern const Word16 ISqrtDiffTable[32]; -extern const Word32 InvTable_lc3plus[32]; -extern const Word16 InvDiffTable_lc3plus[32]; +extern const Word32 InvTable[32]; +extern const Word16 InvDiffTable[32]; -Word32 BASOP_Util_Log2_lc3plus(Word32 x) +Word32 BASOP_Util_Log2(Word32 x) { Word32 exp; Word16 exp_e; @@ -48,31 +50,31 @@ Word32 BASOP_Util_Log2_lc3plus(Word32 x) /* approximate ln() for fractional part (nIn *c0 + nIn^2*c1 + nIn^3*c2 + ... + nIn^8 *c7) */ /* iteration 1, no need for accumulation */ - accuRes = L_mult(nIn, ldCoeff_lc3plus[0]); /* nIn^i * coeff[0] */ + accuRes = L_mult(nIn, ldCoeff[0]); /* nIn^i * coeff[0] */ accuSqr = mult(nIn, nIn); /* nIn^2, nIn^3 .... */ /* iteration 2 */ - accuRes = L_mac(accuRes, accuSqr, ldCoeff_lc3plus[1]); /* nIn^i * coeff[1] */ + accuRes = L_mac(accuRes, accuSqr, ldCoeff[1]); /* nIn^i * coeff[1] */ accuSqr = mult(accuSqr, nIn); /* nIn^2, nIn^3 .... */ /* iteration 3 */ - accuRes = L_mac(accuRes, accuSqr, ldCoeff_lc3plus[2]); /* nIn^i * coeff[2] */ + accuRes = L_mac(accuRes, accuSqr, ldCoeff[2]); /* nIn^i * coeff[2] */ accuSqr = mult(accuSqr, nIn); /* nIn^2, nIn^3 .... */ /* iteration 4 */ - accuRes = L_mac(accuRes, accuSqr, ldCoeff_lc3plus[3]); /* nIn^i * coeff[3] */ + accuRes = L_mac(accuRes, accuSqr, ldCoeff[3]); /* nIn^i * coeff[3] */ accuSqr = mult(accuSqr, nIn); /* nIn^2, nIn^3 .... */ /* iteration 5 */ - accuRes = L_mac(accuRes, accuSqr, ldCoeff_lc3plus[4]); /* nIn^i * coeff[4] */ + accuRes = L_mac(accuRes, accuSqr, ldCoeff[4]); /* nIn^i * coeff[4] */ accuSqr = mult(accuSqr, nIn); /* nIn^2, nIn^3 .... */ /* iteration 6 */ - accuRes = L_mac(accuRes, accuSqr, ldCoeff_lc3plus[5]); /* nIn^i * coeff[5] */ + accuRes = L_mac(accuRes, accuSqr, ldCoeff[5]); /* nIn^i * coeff[5] */ accuSqr = mult(accuSqr, nIn); /* nIn^2, nIn^3 .... */ /* iteration 7, no need to calculate accuSqr any more */ - accuRes = L_mac(accuRes, accuSqr, ldCoeff_lc3plus[6]); /* nIn^i * coeff[6] */ + accuRes = L_mac(accuRes, accuSqr, ldCoeff[6]); /* nIn^i * coeff[6] */ /* ld(fractional part) = ln(fractional part)/ln(2), 1/ln(2) = (1 + 0.44269504) */ accuRes = L_mac0(L_shr(accuRes, 1), extract_h(accuRes), 14506); @@ -84,7 +86,152 @@ Word32 BASOP_Util_Log2_lc3plus(Word32 x) return (accuRes); } -Word32 BASOP_Util_InvLog2_lc3plus(Word32 x) + + +#ifdef LOG2_LC_APPROX +/* LC log2 with 16 segment piecewise 2nd order minmax optimized approximation */ + +Word32 BASOP_Util_Log2_LC(Word32 L_x) +{ + Word16 exp_e0; + Word32 L_accuRes; + +#define L2LC_TABSIZE_BITS 4 /* 16 segments */ +#define L2LC_TABWIDTH 2 +#define L2LC_TABLENGTH (1<> 6/*0.044*/ , 277633165 >> 6, 449797678 >> 6, 612896598 >> 6, + 767837083 >> 6, 915396590 >> 6, 1056246482 >> 6, 1190970490 >> 6, + 1320079339 >> 6, 1444022426 >> 6, 1563197273 >> 6, 1677957208 >> 6, + 1788617686 >> 6, 1895461516 >> 6, 1998743213 >> 6, 2098692655 >> 6 /*0.9773*/ + }; + + Word32 L_pow2Const[31] = + { /* The Table implements L_shl_pos( L_deposit_l(add(exp_e0,1)), 25)) */ + ((0L + 1) << 25), /* orig exp_e0==0 */ + ((0L + 2) << 25), + ((0L + 3) << 25), + ((0L + 4) << 25), + ((0L + 5) << 25), + ((0L + 6) << 25), + ((0L + 7) << 25), + ((0L + 8) << 25), + ((0L + 9) << 25), + ((0L + 10) << 25), + + ((0L + 11) << 25), + ((0L + 12) << 25), + ((0L + 13) << 25), + ((0L + 14) << 25), + ((0L + 15) << 25), + ((0L + 16) << 25), + ((0L + 17) << 25), + ((0L + 18) << 25), + ((0L + 19) << 25), + ((0L + 20) << 25), + + ((0L + 21) << 25), + ((0L + 22) << 25), + ((0L + 23) << 25), + ((0L + 24) << 25), + ((0L + 25) << 25), + ((0L + 26) << 25), + ((0L + 27) << 25), + ((0L + 28) << 25), + ((0L + 29) << 25), + ((0L + 30) << 25), + ((0L + 31) << 25), /* orig exp_e0==30 */ + }; + + Word32 L_x_up; + Word16 dx; + Word32 L_segm_ind; + Word32 L_tail_frac_indQ32; + Word16* cXPtr; /* C1C2 row pointer */ + Word32 L_tmp; + + + cXPtr = &(log2_LC_TabValC1C2_Qx[0][0]); /* C1C2 table init */ + assert(L_x >= 0); + + if (L_x == 0) /* logic kept from non LC version */ + { /* do not call this function with 0 */ + return ((Word32)MIN_32); + } + + /* start of actual BASOP approximation */ + exp_e0 = norm_l(L_x); /* exp_e0 = number of upshifts for L_x to get into 0.5 to 1.0 */ + L_x_up = L_shl_pos(L_x, exp_e0); /* max upshift to a get a mantissa fractional value range .5 to 1.0 */ + + /* apply total_frac=(2*x-1) to move to region 1.0 to 2.0 , and extract tail fraction to approximation ox log2(1+x/16) )*/ + + L_segm_ind = L_shr_pos_pos(L_and(L_x_up, 0x3c000000), 30 - 4); /* 2 ops to pick segment */ + + /* use 16 bits after the segment index, and put them it in a Q16 short variable as in segment range -.5 to .5 */ + L_tail_frac_indQ32 = L_and(L_x_up, 0x03ffffff); /* mask away to a positive value in Q26 */ + L_tail_frac_indQ32 = L_sub(L_tail_frac_indQ32, 1L << (26 - 1)); /* subtract 0.5 at Q26 */ + L_tail_frac_indQ32 = L_shl_pos(L_tail_frac_indQ32, 6); /* shift up to Q32 */ + dx = extract_h(L_tail_frac_indQ32); /* 4 ops to get a the signed tail fraction into a Word16 */ + + + ASSERT(L_segm_ind >= 0 && L_segm_ind <= L2LC_TABLENGTH); + /* Table ptr init to [segm_ind][0,1,2] */ + cXPtr += (L_segm_ind*L2LC_TABWIDTH); /* allows for ptr increment , for the Word16 table segment adressing */ + + /* ops pre = 8 , mid = 6 , tail = 1, sum= 15 (25-15)/25 = 40% reduction */ + /* Horners rule ((C2*x+ C1)*x) + C0 , maintains precision until final summation */ + + L_tmp = L_mult0(cXPtr[1], dx); /* Q23*Q16 -> Q39 C2*x */ + L_tmp = L_shr_pos(L_tmp, 39 - 34); /* Q39 to -> Q34 */ + + L_tmp = L_msu(L_tmp, cXPtr[0], SHRT_MIN); /* add C1, with L_msu , no extra cycle cost for C1 Word16 storage in Q18 , Q34=18+15+1 */ + + L_tmp = Mpy_32_16_lc3plus(L_tmp, dx); /*Q34*Q16 to -> Q50-16+1 = Q35 , (x*c2+c1)x*/ + L_tmp = L_shr_pos(L_tmp, 35 - 25); /*Q34+1 to -> Q25 */ /* fractional to final Q25 */ + + L_tmp = L_add(L_tmp, L_log2_LC_TabValC0Q25[L_segm_ind]); /* Q25 to -> Q25 */ + + /* back to 0..1 from log2(1+x/16) range */ + ASSERT(exp_e0 >= 0 && exp_e0 <= 30); + L_accuRes = L_sub(L_tmp, L_pow2Const[exp_e0]); /* result = integer_partQ25*2^-1 + fractional partQ25 */ + + return (L_accuRes); +} +#endif + + +Word32 BASOP_Util_InvLog2(Word32 x) { #ifdef ENABLE_HR_MODE /* Original code was used for negative x and hence the exp was always 0, which is assumed */ @@ -129,8 +276,8 @@ Word32 BASOP_Util_InvLog2_lc3plus(Word32 x) exp = negate(exp); } - lookup3f = L_add(exp2x_tab_long_lc3plus[index3], L_shr_pos(Mpy_32_16_lc3plus(0x0016302F, frac), 1)); - lookup12 = Mpy_32_32_lc3plus(exp2_tab_long_lc3plus[index1], exp2w_tab_long_lc3plus[index2]); + lookup3f = L_add(exp2x_tab_long[index3], L_shr_pos(Mpy_32_16_lc3plus(0x0016302F, frac), 1)); + lookup12 = Mpy_32_32_lc3plus(exp2_tab_long[index1], exp2w_tab_long[index2]); lookup = Mpy_32_32_lc3plus(lookup12, lookup3f); retVal = L_shr(lookup, sub(exp, 3)); @@ -171,9 +318,14 @@ Word32 BASOP_Util_InvLog2_pos(Word32 x, Word16 *exp) } ELSE IF(x == 0) { +#ifdef LRSNS_ALLZERO_FIX + *exp = 2; move16(); + return (1L << 29); /* 2^29/(2^(31-(+2)) = 1.0 exactly */ +#else *exp = -1; move16(); return 0x10000000; +#endif } frac = extract_l(L_and(x, 0x3FF)); @@ -182,8 +334,8 @@ Word32 BASOP_Util_InvLog2_pos(Word32 x, Word16 *exp) index2 = L_and(L_shr(x, 15), 0x1F); index1 = L_and(L_shr(x, 20), 0x1F); - lookup3f = L_add(exp2x_tab_long_lc3plus[index3], L_shr(Mpy_32_16_lc3plus(0x0016302F, frac), 1)); - lookup12 = Mpy_32_32_lc3plus(exp2_tab_long_lc3plus[index1], exp2w_tab_long_lc3plus[index2]); + lookup3f = L_add(exp2x_tab_long[index3], L_shr(Mpy_32_16_lc3plus(0x0016302F, frac), 1)); + lookup12 = Mpy_32_32_lc3plus(exp2_tab_long[index1], exp2w_tab_long[index2]); lookup = Mpy_32_32_lc3plus(lookup12, lookup3f); IF (x > 0) @@ -204,7 +356,7 @@ Word32 BASOP_Util_InvLog2_pos(Word32 x, Word16 *exp) } #endif -/* local function for Sqrt16_lc3plus and Sqrt16norm */ +/* local function for Sqrt16 and Sqrt16norm */ static Word16 Sqrt16_common(Word16 m, Word16 e) { Word16 index, frac; @@ -221,7 +373,7 @@ static Word16 Sqrt16_common(Word16 m, Word16 e) /* interpolate */ if (m != 0) { - m = mac_r(SqrtTable_lc3plus[index], SqrtDiffTable_lc3plus[index], frac); + m = mac_r(SqrtTable[index], SqrtDiffTable[index], frac); } /* handle odd exponents */ @@ -246,7 +398,7 @@ static Word16 ISqrt16_common(Word16 m, Word16 e) frac = s_and(m, 0x1FF); /* Q9 */ /* interpolate */ - m = msu_r(ISqrtTable_lc3plus[index], ISqrtDiffTable_lc3plus[index], frac); + m = msu_r(ISqrtTable[index], ISqrtDiffTable[index], frac); /* handle even exponents */ if (s_and(e, 1) == 0) @@ -255,7 +407,7 @@ static Word16 ISqrt16_common(Word16 m, Word16 e) return m; } -Word16 Sqrt16_lc3plus( /*!< output mantissa */ +Word16 Sqrt16( /*!< output mantissa */ Word16 mantissa, /*!< input mantissa */ Word16 *exponent /*!< pointer to exponent */ ) @@ -303,7 +455,7 @@ Word16 ISqrt16( /*!< output mantissa */ return mantissa; } -Word16 Inv16_lc3plus( /*!< output mantissa */ +Word16 Inv16( /*!< output mantissa */ Word16 mantissa, /*!< input mantissa */ Word16 *exponent /*!< pointer to exponent */ ) @@ -331,7 +483,7 @@ Word16 Inv16_lc3plus( /*!< output mantissa */ frac = shl(s_and(m, 0x1FF), 1); /* Q10 */ /* interpolate */ - m = msu_r(InvTable_lc3plus[index], InvDiffTable_lc3plus[index], frac); + m = msu_r(InvTable[index], InvDiffTable[index], frac); /* restore sign */ if (mantissa < 0) @@ -437,7 +589,7 @@ Word16 getScaleFactor16_0( /* o: measured headroom in range [ and -2147483648 <= x <= -1073741824 for negative x */ -Word16 getScaleFactor32_lc3plus( /* o: measured headroom in range [0..31], 0 if all x[i] == 0 */ +Word16 getScaleFactor32( /* o: measured headroom in range [0..31], 0 if all x[i] == 0 */ const Word32 *x, /* i: array containing 32-bit data */ const Word16 len_x) /* i: length of the array to scan */ { @@ -511,7 +663,7 @@ Word16 getScaleFactor32_0( /* o: measured headroom in range [ return i; } -Word16 BASOP_Util_Divide3216_Scale_lc3plus( /* o: result of division x/y, not normalized */ +Word16 BASOP_Util_Divide3216_Scale( /* o: result of division x/y, not normalized */ Word32 x, /* i: numerator, signed */ Word16 y, /* i: denominator, signed */ Word16 *s) /* o: scaling, 0, if x==0 */ @@ -551,7 +703,7 @@ Word16 BASOP_Util_Divide3216_Scale_lc3plus( /* o: result of division x return z; } -Word16 BASOP_Util_Divide1616_Scale_lc3plus(Word16 x, Word16 y, Word16 *s) +Word16 BASOP_Util_Divide1616_Scale(Word16 x, Word16 y, Word16 *s) { Word16 z; Word16 sx; @@ -695,7 +847,7 @@ void Copy_Scale_sig(const Word16 x[], /* i : signal to scale input Qx } } -Word32 BASOP_Util_Add_Mant32Exp_lc3plus /*!< o: normalized result mantissa */ +Word32 BASOP_Util_Add_Mant32Exp /*!< o: normalized result mantissa */ (Word32 a_m, /*!< i: Mantissa of 1st operand a */ Word16 a_e, /*!< i: Exponent of 1st operand a */ Word32 b_m, /*!< i: Mantissa of 2nd operand b */ @@ -745,7 +897,7 @@ Word32 BASOP_Util_Add_Mant32Exp_lc3plus /*!< o: normalized result mantissa */ return (L_tmp); } -Word16 BASOP_Util_Cmp_Mant32Exp_lc3plus /*!< o: flag: result of comparison */ +Word16 BASOP_Util_Cmp_Mant32Exp /*!< o: flag: result of comparison */ /* 0, if a == b */ /* 1, if a > b */ /* -1, if a < b */ @@ -835,7 +987,7 @@ Word16 BASOP_Util_Cmp_Mant32Exp_lc3plus /*!< o: flag: result of comparison */ } /*----------------------------------------------------------------------------------* - * Function: Isqrt + * Function: Isqrt_lc3plus * * Description: * diff --git a/lib_lc3plus/basop_util_lc3plus.h b/lib_lc3plus/basop_util_lc3plus.h index 577c65f54..c8eb0b25f 100644 --- a/lib_lc3plus/basop_util_lc3plus.h +++ b/lib_lc3plus/basop_util_lc3plus.h @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -10,6 +10,8 @@ #ifndef __BASOP_UTIL_LC3PLUS_H__ #define __BASOP_UTIL_LC3PLUS_H__ +#include "options.h" +#include "wmc_auto.h" #include "defines.h" #include "functions.h" #include @@ -79,7 +81,7 @@ typedef struct The exponent is addressed via pointers and will be overwritten with the result. */ -Word16 Sqrt16_lc3plus( /*!< output mantissa */ +Word16 Sqrt16( /*!< output mantissa */ Word16 mantissa, /*!< input mantissa */ Word16 *exponent /*!< pointer to exponent */ ); @@ -99,7 +101,7 @@ Word16 ISqrt16( /*!< output mantissa */ The function uses a table lookup and a newton iteration. */ -Word16 Inv16_lc3plus( /*!< output mantissa */ +Word16 Inv16( /*!< output mantissa */ Word16 mantissa, /*!< input mantissa */ Word16 *exponent /*!< pointer to exponent */ ); @@ -142,7 +144,7 @@ Word16 getScaleFactor16_0( /* o: measured headroom in range and -2147483648 <= x <= -1073741824 for negative x */ -Word16 getScaleFactor32_lc3plus( /* o: measured headroom in range [0..31], 0 if all x[i] == 0 */ +Word16 getScaleFactor32( /* o: measured headroom in range [0..31], 0 if all x[i] == 0 */ const Word32 *x, /* i: array containing 32-bit data */ const Word16 len_x); /* i: length of the array to scan */ @@ -167,7 +169,7 @@ Word16 getScaleFactor32_0( /* o: measured headroom in range \return fractional Word16 integer z = arg1(32bits)/arg2(16bits) , z not normalized */ -Word16 BASOP_Util_Divide3216_Scale_lc3plus(Word32 x, /*!< i : Numerator */ +Word16 BASOP_Util_Divide3216_Scale(Word32 x, /*!< i : Numerator */ Word16 y, /*!< i : Denominator*/ Word16 *s); /*!< o : Additional scalefactor difference*/ @@ -178,7 +180,7 @@ Word16 BASOP_Util_Divide3216_Scale_lc3plus(Word32 x, /*!< i : Numerator */ \return fractional Q15 Word16 z = arg1(Q15)/arg2(Q15) with scaling s */ -Word16 BASOP_Util_Divide1616_Scale_lc3plus(Word16 x, /*!< i : Numerator*/ +Word16 BASOP_Util_Divide1616_Scale(Word16 x, /*!< i : Numerator*/ Word16 y, /*!< i : Denominator*/ Word16 *s); /*!< o : Additional scalefactor difference*/ @@ -191,7 +193,20 @@ Word16 BASOP_Util_Divide1616_Scale_lc3plus(Word16 x, /*!< i : Numerator*/ \return log2(x)/64 */ /************************************************************************/ -Word32 BASOP_Util_Log2_lc3plus(Word32 x); +Word32 BASOP_Util_Log2(Word32 x); + +#ifdef LOG2_LC_APPROX +/************************************************************************/ +/*! + \brief Low Complex Binary logarithm with 16 sections and 2nd order polynom + + \param x + + \return log2(x)/64 + */ + /************************************************************************/ +Word32 BASOP_Util_Log2_LC(Word32 L_x); +#endif /************************************************************************/ /*! @@ -213,9 +228,9 @@ Word32 BASOP_Util_Log2_lc3plus(Word32 x); Due to the fact, that all lookup values contain a factor 0.5 the result has to be shifted by 3 to the right also. - Table exp2_tab_long_lc3plus contains the log2 for 0 to 1.0 in steps - of 1/32, table exp2w_tab_long_lc3plus the log2 for 0 to 1/32 in steps - of 1/1024, table exp2x_tab_long_lc3plus the log2 for 0 to 1/1024 in + Table exp2_tab_long contains the log2 for 0 to 1.0 in steps + of 1/32, table exp2w_tab_long the log2 for 0 to 1/32 in steps + of 1/1024, table exp2x_tab_long the log2 for 0 to 1/1024 in steps of 1/32768. Since the 2-logarithm of very very small negative value is rather linear, we can use interpolation. @@ -232,10 +247,10 @@ Word32 BASOP_Util_Log2_lc3plus(Word32 x); \return pow(2,(x/64)) */ /************************************************************************/ -Word32 BASOP_Util_InvLog2_lc3plus(Word32 x); +Word32 BASOP_Util_InvLog2(Word32 x); #ifdef ENABLE_HR_MODE -/* New function which works with positive x, BASOP_Util_InvLog2_lc3plus does not give +/* New function which works with positive x, BASOP_Util_InvLog2 does not give accurate results for x > 0 */ Word32 BASOP_Util_InvLog2_pos(Word32 x, Word16 *exp); #endif @@ -257,7 +272,7 @@ Word32 Norm32Norm(const Word32 *x, const Word16 headroom, const Word16 length, W The base for exponents is 2. Example: \f$ a = a\_m * 2^{a\_e} \f$
************************************************************************/ -Word32 BASOP_Util_Add_Mant32Exp_lc3plus /*!< o: normalized result mantissa */ +Word32 BASOP_Util_Add_Mant32Exp /*!< o: normalized result mantissa */ (Word32 a_m, /*!< i: Mantissa of 1st operand a */ Word16 a_e, /*!< i: Exponent of 1st operand a */ Word32 b_m, /*!< i: Mantissa of 2nd operand b */ @@ -271,7 +286,7 @@ Word32 BASOP_Util_Add_Mant32Exp_lc3plus /*!< o: normalized result mantissa */ The base for exponents is 2. Example: \f$ a = a\_m * 2^{a\_e} \f$
************************************************************************/ -Word16 BASOP_Util_Cmp_Mant32Exp_lc3plus /*!< o: flag: result of comparison */ +Word16 BASOP_Util_Cmp_Mant32Exp /*!< o: flag: result of comparison */ (Word32 a_m, /*!< i: Mantissa of 1st operand a */ Word16 a_e, /*!< i: Exponent of 1st operand a */ Word32 b_m, /*!< i: Mantissa of 2nd operand b */ @@ -312,7 +327,7 @@ Word32 invFixp(Word32 op_m, Word16 *op_e); #endif #define BASOP_CFFT_MAX_LENGTH 480 -void BASOP_cfft_lc3plus(Word32 *re, Word32 *im, Word16 sizeOfFft, Word16 s, Word16 *scale, Word32 *x); +void BASOP_cfft(Word32 *re, Word32 *im, Word16 sizeOfFft, Word16 s, Word16 *scale, Word32 *x); void BASOP_rfftN(Word32 *re, Word16 sizeOfFft, Word16 *scale, Word8 *scratchBuffer); void BASOP_irfftN(Word32 *re, Word16 sizeOfFft, Word16 *scale, Word8 *scratchBuffer); diff --git a/lib_lc3plus/com_entropy.c b/lib_lc3plus/com_entropy.c new file mode 100644 index 000000000..6d8cb89b9 --- /dev/null +++ b/lib_lc3plus/com_entropy.c @@ -0,0 +1,27 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.6.1 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "options.h" +#include "wmc_auto.h" +#include "functions.h" + +Word16 getLastNzBits_fx (Word16 N) +{ + Dyn_Mem_Deluxe_In( Word16 minBits;); + minBits = sub(14, norm_s(negate(N))); +#ifdef CR9_C_ADD_1p25MS + /* minimum of 2 spare bits */ + if (sub(sub(shl(1,minBits),shr(N,1)),2) < 0) + { + minBits = add(minBits,1); + } +#endif + Dyn_Mem_Deluxe_Out(); + return minBits; +} diff --git a/lib_lc3plus/constants.c b/lib_lc3plus/constants.c index 9f1992bf7..1d00d56e0 100644 --- a/lib_lc3plus/constants.c +++ b/lib_lc3plus/constants.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,10 +7,548 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "basop_util_lc3plus.h" #include "constants.h" #include "defines.h" +#ifdef LTPF_ADAPTIVE_GAIN +RAM_ALIGN const Word16 adaptive_gain_step = 328; +RAM_ALIGN const Word16 max_adaptive_gain[4] = { 19661, 18022, 16384, 14746 }; +RAM_ALIGN const Word16 max_adaptive_gain_step[4] = { 983, 901, 819, 737 }; +#endif + +#ifdef LTPF_ADAPTIVE_GAIN +RAM_ALIGN const Word16 tilt_filter_1p25ms[5][4][11] = { + { {19343, 13480, -605}, {19251, 13480, -512}, {19164, 13480, -425}, {19083, 13480, -344} }, + { {19343, 13480, -605}, {19251, 13480, -512}, {19164, 13480, -425}, {19083, 13480, -344} }, + { {12812, 16514, 3225, -411, -50}, + {12680, 16454, 3350, -351, -43}, + {12556, 16397, 3468, -294, -36}, + {12438, 16343, 3579, -239, -30} }, + { {9577, 14941, 6763, 1210, -326, -81, -10}, + {9453, 14834, 6838, 1306, -279, -70, -9}, + {9337, 14732, 6909, 1397, -234, -59, -7}, + {9226, 14634, 6975, 1484, -191, -48, -6} }, + { {6363, 11318, 8072, 4573, 1832, 298, -232, -102, -36, -9, -1}, + {6264, 11190, 8060, 4628, 1904, 356, -199, -88, -31, -8, -1}, + {6171, 11069, 8048, 4679, 1972, 411, -167, -74, -26, -7, -1}, + {6084, 10954, 8036, 4727, 2037, 463, -137, -60, -22, -6, -1} } +}; +#endif + +RAM_ALIGN const Word16 lpc_warp_pre_adapt_emphasis_64_48000[64] = +{ + 0x0000, 0x0334, 0x074e, 0x0c81, 0x1308, 0x1b27, 0x2532, 0x18c6, 0x2056, 0x298c, 0x34bd, 0x4247, 0x52a0, 0x3326, 0x3ef7, 0x4d21, + 0x5e12, 0x724e, 0x4537, 0x5395, 0x64aa, 0x78f3, 0x4883, 0x56c6, 0x67aa, 0x7ba5, 0x49a1, 0x5794, 0x680a, 0x7b75, 0x492c, 0x56a8, + 0x6688, 0x7937, 0x4798, 0x5484, 0x63b2, 0x7589, 0x453d, 0x5189, 0x5ff6, 0x70e3, 0x425f, 0x4e02, 0x5ba6, 0x6ba2, 0x7e5c, 0x4a25, + 0x56fd, 0x6607, 0x77a0, 0x461d, 0x522a, 0x6044, 0x70c2, 0x4207, 0x4d4e, 0x5a7f, 0x69ea, 0x7bf0, 0x4881, 0x54d0, 0x6333, 0x7402 +}; + +RAM_ALIGN const Word16 lpc_warp_pre_adapt_emphasis_64_32000[64] = +{ + 0x0000, 0x02ba, 0x061d, 0x0a48, 0x0f5f, 0x158b, 0x1cff, 0x25f1, 0x1853, 0x1eb3, 0x2646, 0x2f3f, 0x39d9, 0x4658, 0x550b, 0x3326, + 0x3d43, 0x4919, 0x56ee, 0x6712, 0x79e2, 0x47e5, 0x54a1, 0x636e, 0x749c, 0x4445, 0x4fd1, 0x5d31, 0x6cab, 0x7e92, 0x49a1, 0x5595, + 0x6361, 0x734e, 0x42d6, 0x4d6d, 0x59a0, 0x67af, 0x77df, 0x4541, 0x4ff9, 0x5c4e, 0x6a7d, 0x7acb, 0x46c5, 0x5189, 0x5de7, 0x6c1c, + 0x7c6b, 0x4792, 0x5251, 0x5ea5, 0x6cca, 0x7d04, 0x47d0, 0x527b, 0x5eb7, 0x6cbc, 0x7ccf, 0x479d, 0x522a, 0x5e41, 0x6c1b, 0x7bf8 +}; + +RAM_ALIGN const Word8 lpc_warp_pre_adapt_emphasis_64_e_32000[64] = +{ + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, + 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x08, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c +}; + +RAM_ALIGN const Word16 *const lpc_pre_adapt_emphasis[NUM_SAMP_FREQ] = {NULL, + NULL, + NULL, + lpc_warp_pre_adapt_emphasis_64_32000, + lpc_warp_pre_adapt_emphasis_64_48000, + NULL}; + +RAM_ALIGN const Word8 lpc_warp_pre_adapt_emphasis_64_e_48000[64] = +{ + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, + 0x07, 0x07, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0c, 0x0c, 0x0c, 0x0c, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0e, 0x0e, 0x0e, 0x0e +}; + +RAM_ALIGN const Word8 *const lpc_pre_adapt_emphasis_e[NUM_SAMP_FREQ] = {NULL, + NULL, + NULL, + lpc_warp_pre_adapt_emphasis_64_e_32000, + lpc_warp_pre_adapt_emphasis_64_e_48000, + NULL}; + +#ifdef CR9_C_ADD_1p25MS +#ifdef ENABLE_HR_MODE +const Word16 LowDelayShapes_n960_len_1_25ms[6] = {20, 40, 60, 80, 120, 240}; +#else +const Word16 LowDelayShapes_n960_len_1_25ms[5] = {20, 40, 60, 80, 120}; +#endif + +#ifdef ENABLE_HR_MODE +const Word32 MDCT_WINDOW_FS_8000_frame_ms_1_25[20] = { + 150701702, 448394330, 735046002, 1003598401, 1247438878, 1460563269, 1637723745, + 1774558027, 1867696801, 1914846681, -1914846681, -1867696801, -1774558027, -1637723745, + -1460563269, -1247438878, -1003598401, -735046002, -448394330, -150701702 + }; + +const Word32 MDCT_WINDOW_FS_16000_frame_ms_1_25[40] = { + 53322207, 159637873, 264969317, 368667138, 470092003, 568618595, 663639464, + 754568775, 840845919, 921938968, 997347957, 1066607963, 1129291978, 1185013531, + 1233429082, 1274240133, 1307195069, 1332090713, 1348773575, 1357140799, -1357140799, + -1348773575, -1332090713, -1307195069, -1274240133, -1233429082, -1185013531, -1129291978, + -1066607963, -997347957, -921938968, -840845919, -754568775, -663639464, -568618595, + -470092003, -368667138, -264969317, -159637873, -53322207 + }; + +const Word32 MDCT_WINDOW_FS_24000_frame_ms_1_25[60] = { + 29029078, 87007668, 144747776, 202091141, 258880587, 314960460, 370177048, + 424379007, 477417772, 529147969, 579427807, 628119474, 675089510, 720209172, + 763354790, 804408107, 843256596, 879793778, 913919506, 945540245, 974569323, + 1000927175, 1024541554, 1045347737, 1063288694, 1078315251, 1090386220, 1099468517, + 1105537247, 1108575776, -1108575776, -1105537247, -1099468517, -1090386220, -1078315251, + -1063288694, -1045347737, -1024541554, -1000927175, -974569323, -945540245, -913919506, + -879793778, -843256596, -804408107, -763354790, -720209172, -675089510, -628119474, + -579427807, -529147969, -477417772, -424379007, -370177048, -314960460, -258880587, + -202091141, -144747776, -87007668, -29029078 + }; + +const Word32 MDCT_WINDOW_FS_32000_frame_ms_1_25[80] = { + 37711764, 113077142, 188268164, 263168890, 337663828, 411638113, 484977683, + 557569451, 629301488, 700063188, 769745441, 838240803, 905443658, 971250384, + 1035559513, 1098271884, 1159290799, 1218522172, 1275874672, 1331259866, 1384592353, + 1435789900, 1484773562, 1531467812, 1575800649, 1617703715, 1657112400, 1693965938, + 1728207502, 1759784297, 1788647631, 1814753000, 1838060152, 1858533148, 1876140421, + 1890854821, 1902653660, 1911518745, 1917436407, 1920397521, -1920397521, -1917436407, + -1911518745, -1902653660, -1890854821, -1876140421, -1858533148, -1838060152, -1814753000, + -1788647631, -1759784297, -1728207502, -1693965938, -1657112400, -1617703715, -1575800649, + -1531467812, -1484773562, -1435789900, -1384592353, -1331259866, -1275874672, -1218522172, + -1159290799, -1098271884, -1035559513, -971250384, -905443658, -838240803, -769745441, + -700063188, -629301488, -557569451, -484977683, -411638113, -337663828, -263168890, + -188268164, -113077142, -37711764 + }; + +const Word32 MDCT_WINDOW_FS_48000_frame_ms_1_25[120] = { + 20528417, 61571181, 102571748, 143502017, 184333937, 225039524, 265590880, + 305960213, 346119857, 386042287, 425700143, 465066245, 504113615, 542815489, + 581145346, 619076914, 656584198, 693641492, 730223399, 766304847, 801861108, + 836867813, 871300971, 905136983, 938352659, 970925235, 1002832388, 1034052249, + 1064563423, 1094344998, 1123376563, 1151638223, 1179110607, 1205774887, 1231612790, + 1256606606, 1280739208, 1303994054, 1326355209, 1347807345, 1368335762, 1387926390, + 1406565803, 1424241225, 1440940544, 1456652314, 1471365767, 1485070820, 1497758079, + 1509418850, 1520045141, 1529629668, 1538165864, 1545647877, 1552070581, 1557429573, + 1561721181, 1564942463, 1567091212, 1568165954, -1568165954, -1567091212, -1564942463, + -1561721181, -1557429573, -1552070581, -1545647877, -1538165864, -1529629668, -1520045141, + -1509418850, -1497758079, -1485070820, -1471365767, -1456652314, -1440940544, -1424241225, + -1406565803, -1387926390, -1368335762, -1347807345, -1326355209, -1303994054, -1280739208, + -1256606606, -1231612790, -1205774887, -1179110607, -1151638223, -1123376563, -1094344998, + -1064563423, -1034052249, -1002832388, -970925235, -938352659, -905136983, -871300971, + -836867813, -801861108, -766304847, -730223399, -693641492, -656584198, -619076914, + -581145346, -542815489, -504113615, -465066245, -425700143, -386042287, -346119857, + -305960213, -265590880, -225039524, -184333937, -143502017, -102571748, -61571181, + -20528417 +}; + +#else /* ENABLE_HR_MODE */ + +const Word16 MDCT_WINDOW_FS_8000_frame_ms_1_25[20] = { + 2300, + 6842, + 11216, + 15314, + 19034, + 22286, + 24990, + 27078, + 28499, + 29218, + -29218, + -28499, + -27078, + -24990, + -22286, + -19034, + -15314, + -11216, + -6842, + -2300 + }; + +const Word16 MDCT_WINDOW_FS_16000_frame_ms_1_25[40] = { + 814, + 2436, + 4043, + 5625, + 7173, + 8676, + 10126, + 11514, + 12830, + 14068, + 15218, + 16275, + 17232, + 18082, + 18821, + 19443, + 19946, + 20326, + 20581, + 20708, + -20708, + -20581, + -20326, + -19946, + -19443, + -18821, + -18082, + -17232, + -16275, + -15218, + -14068, + -12830, + -11514, + -10126, + -8676, + -7173, + -5625, + -4043, + -2436, + -814 + }; + +const Word16 MDCT_WINDOW_FS_24000_frame_ms_1_25[60] = { + 443, + 1328, + 2209, + 3084, + 3950, + 4806, + 5648, + 6476, + 7285, + 8074, + 8841, + 9584, + 10301, + 10990, + 11648, + 12274, + 12867, + 13425, + 13945, + 14428, + 14871, + 15273, + 15633, + 15951, + 16224, + 16454, + 16638, + 16777, + 16869, + 16916, + -16916, + -16869, + -16777, + -16638, + -16454, + -16224, + -15951, + -15633, + -15273, + -14871, + -14428, + -13945, + -13425, + -12867, + -12274, + -11648, + -10990, + -10301, + -9584, + -8841, + -8074, + -7285, + -6476, + -5648, + -4806, + -3950, + -3084, + -2209, + -1328, + -443 + }; + +const Word16 MDCT_WINDOW_FS_32000_frame_ms_1_25[80] = { + 575, + 1725, + 2873, + 4016, + 5152, + 6281, + 7400, + 8508, + 9602, + 10682, + 11745, + 12791, + 13816, + 14820, + 15801, + 16758, + 17689, + 18593, + 19468, + 20313, + 21127, + 21908, + 22656, + 23368, + 24045, + 24684, + 25286, + 25848, + 26370, + 26852, + 27293, + 27691, + 28047, + 28359, + 28628, + 28852, + 29032, + 29167, + 29258, + 29303, + -29303, + -29258, + -29167, + -29032, + -28852, + -28628, + -28359, + -28047, + -27691, + -27293, + -26852, + -26370, + -25848, + -25286, + -24684, + -24045, + -23368, + -22656, + -21908, + -21127, + -20313, + -19468, + -18593, + -17689, + -16758, + -15801, + -14820, + -13816, + -12791, + -11745, + -10682, + -9602, + -8508, + -7400, + -6281, + -5152, + -4016, + -2873, + -1725, + -575 + }; + +const Word16 MDCT_WINDOW_FS_48000_frame_ms_1_25[120] = { + 313, + 940, + 1565, + 2190, + 2813, + 3434, + 4053, + 4669, + 5281, + 5891, + 6496, + 7096, + 7692, + 8283, + 8868, + 9446, + 10019, + 10584, + 11142, + 11693, + 12235, + 12770, + 13295, + 13811, + 14318, + 14815, + 15302, + 15778, + 16244, + 16698, + 17141, + 17573, + 17992, + 18399, + 18793, + 19174, + 19543, + 19897, + 20239, + 20566, + 20879, + 21178, + 21462, + 21732, + 21987, + 22227, + 22451, + 22660, + 22854, + 23032, + 23194, + 23340, + 23471, + 23585, + 23683, + 23764, + 23830, + 23879, + 23912, + 23928, + -23928, + -23912, + -23879, + -23830, + -23764, + -23683, + -23585, + -23471, + -23340, + -23194, + -23032, + -22854, + -22660, + -22451, + -22227, + -21987, + -21732, + -21462, + -21178, + -20879, + -20566, + -20239, + -19897, + -19543, + -19174, + -18793, + -18399, + -17992, + -17573, + -17141, + -16698, + -16244, + -15778, + -15302, + -14815, + -14318, + -13811, + -13295, + -12770, + -12235, + -11693, + -11142, + -10584, + -10019, + -9446, + -8868, + -8283, + -7692, + -7096, + -6496, + -5891, + -5281, + -4669, + -4053, + -3434, + -2813, + -2190, + -1565, + -940, + -313 +}; +#endif /* ENABLE_HR_MODE */ + +#ifdef ENABLE_HR_MODE +const Word32 *const LowDelayShapes_n960_1_25ms[6] = { + MDCT_WINDOW_FS_8000_frame_ms_1_25, MDCT_WINDOW_FS_16000_frame_ms_1_25, MDCT_WINDOW_FS_24000_frame_ms_1_25, MDCT_WINDOW_FS_32000_frame_ms_1_25, MDCT_WINDOW_FS_48000_frame_ms_1_25, NULL }; +#else +const Word16 *const LowDelayShapes_n960_1_25ms[6] = { + MDCT_WINDOW_FS_8000_frame_ms_1_25, MDCT_WINDOW_FS_16000_frame_ms_1_25, MDCT_WINDOW_FS_24000_frame_ms_1_25, MDCT_WINDOW_FS_32000_frame_ms_1_25, MDCT_WINDOW_FS_48000_frame_ms_1_25, NULL }; +#endif + +const Word16 bands_offset_16000_lpc_warp_1_25ms[21] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20}; + +const Word16 bands_offset_24000_lpc_warp_1_25ms[28] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 26, 28, 30}; + +const Word16 bands_offset_32000_lpc_warp_1_25ms[32] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 27, 29, 31, 33, 35, 37, 40}; + +const Word16 bands_offset_48000_lpc_warp_1_25ms[34] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 43, 46, 50}; + +const Word16 *const bands_offset_1_25ms[6] = { + NULL, bands_offset_16000_lpc_warp_1_25ms, bands_offset_24000_lpc_warp_1_25ms, + bands_offset_32000_lpc_warp_1_25ms, bands_offset_48000_lpc_warp_1_25ms, NULL}; + +#ifdef ENABLE_HR_MODE +/* RAM_ALIGN const Word16 bands_number_1_25ms_HR[] = NULL; */ +const Word16 bands_number_1_25ms [] = {-1, 20, 27, 31, 33, 0}; +#else +const Word16 bands_number_1_25ms [] = {-1, 20, 27, 31, 33}; +#endif +#ifdef FIX_PLC_CONFORM_ISSUES +const Word16 bands_offset_with_one_max_1_25ms[NUM_OFFSETS] = {-1, 20, 20, 23, 20 +#ifdef ENABLE_HR_MODE + , -1, -1 +#endif +}; + +const Word16 bands_offset_with_two_max_1_25ms[NUM_OFFSETS] = {-1, 20, 20, 30, 30 +#ifdef ENABLE_HR_MODE + , -1, -1 +#endif +}; +#endif +#ifdef FIX_PLC_CONFORM_ISSUES +const Word16 bands_offset_with_one_max_lin_1_25ms[NUM_SAMP_FREQ] = {-1, 20, 30, 40, 50 +#ifdef ENABLE_HR_MODE + , 0 +#endif + }; +const Word16 bands_offset_with_two_max_lin_1_25ms[NUM_SAMP_FREQ] = {0, 0, 0, 0, 0 +#ifdef ENABLE_HR_MODE + , 0 +#endif + }; +#endif +#endif /* CR9_C_ADD_1p25MS */ + #ifdef ENABLE_HR_MODE const Word32 LowDelayShapes_n960_N480_HRA_7_5ms_IP[720] = { @@ -1410,7 +1948,7 @@ RAM_ALIGN const Word16 PhECU_whr16ms_ssWB_Q15[Lprot_hamm_len2_24k] = 23463, 24065, 24655, 25231, 25794, 26340, 26871, 27384, 27878, 28353, 28808, 29242, 29653, 30042, 30407, 30749, 31065, 31356, 31621, 31859, 32070, 32254, 32411, 32539, 32639, 32711, 32754}; #else -#define PhECU_whr16ms_sWB_Q15 NULL +#define PhECU_whr16ms_ssWB_Q15 NULL #endif #ifdef SUBSET_SWB RAM_ALIGN const Word16 PhECU_whr16ms_SWB_Q15[Lprot_hamm_len2_32k] = @@ -1553,7 +2091,7 @@ RAM_ALIGN const Word16 PhECU_preTdaFx16ms_ssWB_Q14[384] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; #else -#define PhECU_preTdaFx16ms_sWB_Q14 NULL +#define PhECU_preTdaFx16ms_ssWB_Q14 NULL #endif #ifdef SUBSET_SWB RAM_ALIGN const Word16 PhECU_preTdaFx16ms_SWB_Q14[512] = { @@ -3386,7 +3924,7 @@ RAM_ALIGN const UWord16 ari_spec_bits[64][17] = { {4202, 5716, 9733, 13138, 5598, 6099, 9437, 12683, 9300, 9168, 11485, 13988, 12479, 12109, 13988, 15725, 7804}, {4400, 5965, 9508, 12479, 6009, 6360, 9105, 11781, 9300, 8982, 10970, 13138, 12109, 11629, 13138, 14731, 6994}}; -RAM_ALIGN const Word32 tnsAcfWindow_lc3plus[MAXLAG] = {0x7FBF61E2, 0x7EFE4B00, 0x7DBF01E8, 0x7C0544D0, +RAM_ALIGN const Word32 tnsAcfWindow[MAXLAG] = {0x7FBF61E2, 0x7EFE4B00, 0x7DBF01E8, 0x7C0544D0, 0x79D636E9, 0x773846E0, 0x74330F61, 0x70CF3251}; RAM_ALIGN const Word16 tnsQuantPts[TNS_COEF_RES] = {-32628, -31517, -29333, -26149, -22076, -17250, -11837, -6021, 0, 6021, 11837, 17250, 22076, 26149, 29333, 31517, 32628}; @@ -3605,6 +4143,17 @@ RAM_ALIGN const Word16 lpc_lin_pre_emphasis_80_e_8000[80] = { #endif #ifdef SUBSET_WB +#ifdef FIX_PLC_CONFORM_ISSUES +RAM_ALIGN const Word16 lpc_lin_pre_emphasis_20_16000[20] = { + 0x54d4, 0x7906, 0x6043, 0x4a65, 0x6c65, 0x4aa6, 0x620c, 0x7bd2, 0x4baa, 0x59f2, 0x6869, 0x76b1, 0x4239, 0x48aa, 0x4e84, 0x53a1, + 0x57e1, 0x5b29, 0x5d65, 0x5e87 +}; +RAM_ALIGN const Word16 lpc_lin_pre_emphasis_20_e_16000[20] = { + (Word16)0xfffd, (Word16)0xfffd, (Word16)0xfffe, (Word16)0xffff, (Word16)0xffff, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, + (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002 +}; +#endif RAM_ALIGN const Word16 lpc_lin_pre_emphasis_40_16000[40] = { 0x516b, 0x5a81, 0x6c9d, 0x43d2, 0x55b6, 0x6bdd, 0x4313, 0x5233, 0x6336, 0x7602, 0x453d, 0x503e, 0x5bf4, 0x684b, 0x7530, 0x4148, 0x4829, 0x4f33, 0x5658, 0x5d8f, 0x64cc, 0x6c03, 0x7328, 0x7a32, 0x408a, 0x43e1, 0x471b, 0x4a31, @@ -3644,6 +4193,18 @@ RAM_ALIGN const Word16 lpc_lin_pre_emphasis_80_e_16000[80] = { #endif #ifdef SUBSET_SSWB +#ifdef FIX_PLC_CONFORM_ISSUES +RAM_ALIGN const Word16 lpc_lin_pre_emphasis_30_24000[30] = { + 0x46f5, 0x6bb5, 0x5a67, 0x485c, 0x6c1c, 0x4c07, 0x65dc, 0x41a2, 0x51f6, 0x63bd, 0x76c4, 0x456b, 0x4fde, 0x5a9d, 0x658a, 0x7087, + 0x7b74, 0x431a, 0x4853, 0x4d58, 0x5219, 0x568b, 0x5aa0, 0x5e4d, 0x6188, 0x6447, 0x6683, 0x6835, 0x695a, 0x69ed +}; +RAM_ALIGN const Word16 lpc_lin_pre_emphasis_30_e_24000[30] = { + (Word16)0xfffc, (Word16)0xfffc, (Word16)0xfffd, (Word16)0xfffe, (Word16)0xfffe, (Word16)0xffff, (Word16)0xffff, (Word16)0x0000, + (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, + (Word16)0x0001, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002 +}; +#endif RAM_ALIGN const Word16 lpc_lin_pre_emphasis_40_24000[40] = { 0x44f2, 0x59a3, 0x4172, 0x603b, 0x447d, 0x5db8, 0x7ba7, 0x4f0d, 0x626d, 0x77d6, 0x4793, 0x541b, 0x6171, 0x6f7f, 0x7e2f, 0x46b5, 0x4e8b, 0x568f, 0x5eb2, 0x66ea, 0x6f28, 0x775f, 0x7f83, 0x43c3, 0x47ae, 0x4b7d, 0x4f29, 0x52ac, @@ -3703,6 +4264,22 @@ RAM_ALIGN const Word16 lpc_lin_pre_emphasis_80_e_24000[80] = { #endif #ifdef SUBSET_SWB +RAM_ALIGN const Word16 lpc_lin_pre_emphasis_40_32000[40] = +{ + 0x400d, 0x4e74, 0x5584, 0x4d4b, 0x7b03, 0x59d0, 0x7b65, 0x5106, 0x66c3, 0x7ec8, 0x4c78, 0x5a88, 0x697e, 0x7942, 0x44de, 0x4d69, + 0x5634, 0x5f32, 0x6854, 0x718c, 0x7acb, 0x4201, 0x4692, 0x4b11, 0x4f77, 0x53bc, 0x57db, 0x5bcc, 0x5f89, 0x630d, 0x6652, 0x6953, + 0x6c0b, 0x6e75, 0x708e, 0x7253, 0x73c1, 0x74d5, 0x758f, 0x75eb +}; + +RAM_ALIGN const Word16 lpc_lin_pre_emphasis_40_e_32000[40] = +{ + (Word16)0xfffa, (Word16)0xfffb, (Word16)0xfffc, (Word16)0xfffd, (Word16)0xfffd, (Word16)0xfffe, (Word16)0xfffe, (Word16)0xffff, + (Word16)0xffff, (Word16)0xffff, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, (Word16)0x0001, (Word16)0x0001, + (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002 +}; + RAM_ALIGN const Word16 lpc_lin_pre_emphasis_80_32000[80] = { 0x6eab, 0x4e92, 0x7d03, 0x614a, 0x47cb, 0x64a9, 0x439a, 0x57af, 0x6e8c, 0x4414, 0x523c, 0x61b9, 0x7284, 0x424c, 0x4bf6, 0x563d, 0x611c, 0x6c8f, 0x7892, 0x4290, 0x491a, 0x4fe5, 0x56ed, 0x5e31, 0x65ac, 0x6d5d, 0x753f, 0x7d51, @@ -3846,6 +4423,25 @@ RAM_ALIGN const Word16 *const lpc_lin_pre_emphasis_e_2_5ms[NUM_SAMP_FREQ] = { #endif }; +#ifdef FIX_PLC_CONFORM_ISSUES +RAM_ALIGN const Word16 *const lpc_lin_pre_emphasis_1_25ms[NUM_SAMP_FREQ] = { + lpc_lin_pre_emphasis_20_8000, lpc_lin_pre_emphasis_20_16000, lpc_lin_pre_emphasis_30_24000, + lpc_lin_pre_emphasis_40_32000, lpc_lin_pre_emphasis_60_48000 +#ifdef ENABLE_HR_MODE + , lpc_lin_pre_emphasis_80_0_92 +#endif +}; + +RAM_ALIGN const Word16* const lpc_lin_pre_emphasis_e_1_25ms[NUM_SAMP_FREQ] = { + lpc_lin_pre_emphasis_20_e_8000, lpc_lin_pre_emphasis_20_e_16000, lpc_lin_pre_emphasis_30_e_24000, + lpc_lin_pre_emphasis_40_e_32000, lpc_lin_pre_emphasis_60_e_48000 +#ifdef ENABLE_HR_MODE + , lpc_lin_pre_emphasis_80_e_0_92 +#endif +}; +#endif + + RAM_ALIGN const Word16 lpc_lin_pre_emphasis_60_0_62[60] = { 0x4a26, 0x4be4, 0x4f5d, 0x5490, 0x5b79, 0x6414, 0x6e59, 0x7a43, 0x43e4, 0x4b6f, 0x53bf, 0x5ccc, 0x6690, 0x7106, 0x7c25, 0x43f3, 0x4a1f, 0x5095, 0x574e, 0x5e46, 0x6578, 0x6cdf, 0x7477, 0x7c39, 0x4210, 0x4613, 0x4a24, 0x4e3e, @@ -4402,6 +4998,16 @@ RAM_ALIGN const Word16 *const bands_offset_lin_2_5ms[NUM_SAMP_FREQ] = {bands_off #endif }; +#ifdef FIX_PLC_CONFORM_ISSUES +RAM_ALIGN const Word16 *const bands_offset_lin_1_25ms[NUM_SAMP_FREQ] = {bands_offset_8000_lpc_lin, bands_offset_8000_lpc_lin, + bands_offset_8000_lpc_lin, bands_offset_8000_lpc_lin, + bands_offset_8000_lpc_lin +#ifdef ENABLE_HR_MODE + , bands_offset_24000_lpc_lin +#endif + }; +#endif + RAM_ALIGN const Word16 bands_offset_with_one_max_lin[NUM_SAMP_FREQ] = {80, 0, 0, 0, 0 #ifdef ENABLE_HR_MODE , 0 @@ -4519,6 +5125,18 @@ RAM_ALIGN const Word32 inv_odft_twiddle_40_im[16] = { 0x05067734, 0x0a0af299, 0x0f0b7727, 0x14060b68, 0x18f8b83c, 0x1de189a6, 0x22be8f87, 0x278dde6e, 0x2c4d9050, 0x30fbc54d, 0x3596a46c, 0x3a1c5c57, 0x3e8b240e, 0x42e13ba4, 0x471cece7, 0x4b3c8c12}; +#ifdef FIX_PLC_CONFORM_ISSUES +RAM_ALIGN const Word32 inv_odft_twiddle_30_re[16] = { + 0x7fd317b4, 0x7f4c7e54, 0x7e6c9251, 0x7d33f0ca, 0x7ba3751d, 0x79bc384d, 0x777f903c, 0x74ef0ebc, + 0x720c8075, 0x6ed9eba1, 0x6b598ea3, 0x678dde6e, 0x637984d4, 0x5f1f5ea1, 0x5a82799a, 0x55a6125c +}; + +RAM_ALIGN const Word32 inv_odft_twiddle_30_im[16] = { + 0x06b2f1d2, 0x0d61304e, 0x14060b68, 0x1a9cd9ac, 0x2120fb83, 0x278dde6e, 0x2ddf0040, 0x340ff242, + 0x3a1c5c57, 0x40000000, 0x45b6bb5e, 0x4b3c8c12, 0x508d9211, 0x55a6125c, 0x5a82799a, 0x5f1f5ea1 +}; +#endif + RAM_ALIGN const Word32 inv_odft_twiddle_20_re[16] = { 0x7f9afcb9, 0x7e6c9251, 0x7c769e18, 0x79bc384d, 0x7641af3d, 0x720c8075, 0x6d23501b, 0x678dde6e, 0x6154fb91, 0x5a82799a, 0x53211d18, 0x4b3c8c12, 0x42e13ba4, 0x3a1c5c57, 0x30fbc54d, 0x278dde6e}; @@ -4773,6 +5391,19 @@ RAM_ALIGN const Word16 sns_Kval[4][2] = {{10, 1}, {10, 0}, {8, 0}, {6, RAM_ALIGN const UWord32 sns_MPVQ_Sz[4][2] = { {4780008U >> 1, (2U * 6U)}, {4780008U >> 1, (2U)}, {30316544U >> 1, 0U}, {MPVQ_SZ_OUTL_FAR, 0U}}; +#ifdef NEW_SIGNALLING_SCHEME_1p25 +RAM_ALIGN const Word16 lrsns_ltp_bits_fx[8] = { + 2, /*00(x=0) , ltp=0 ltpf=0 x is next param */ + 2, /*00(x=1) x is next param */ + 3 + 4, /*010 ltp=1 ltpf=0, phaseA or PhaseB(phaseB with reduced resolution) */ + 3 + 4, /*011 ltp=1 ltpf=0, PhaseB(phaseB with reduced resolution) */ + 2 + 4, /*10(x=0) ltp=1 ltpf=1, phase A, +extra bit */ + 2 + 4, /*10(x=1) */ + 2 + 5, /*11(x=0) ltp=1 ltpf=1, phase B , +extra bit */ + 2 + 5 /*11(x=1) */ +}; +#endif + #ifdef ENABLE_HR_MODE RAM_ALIGN const Word32 st1SCF0_7_base5_32x8_Q27[256] = { 303712392, 109160791, -71161366, -182086260, -214684177, -193406093, -153520450, -101361734, 395293327, @@ -4836,7 +5467,12 @@ RAM_ALIGN const Word32 st1SCF8_15_base5_32x8_Q27[256] = { 350549113, 357744389, 322261535, 236116337 }; #endif -RAM_ALIGN const Word16 st1SCF0_7_base5_32x8_Q11[256] = { +#ifdef CR9_C_ADD_1p25MS_LRSNS +RAM_ALIGN const Word16 st1SCF0_7_base5_32x8_Q11[32 * 8 * 2] = +#else +RAM_ALIGN const Word16 st1SCF0_7_base5_32x8_Q11[256] = +#endif +{ 4634, 1666, -1086, -2778, -3276, -2951, -2343, -1547, 6032, 4939, 1967, -908, -2517, -3186, -3066, -2287, -4477, -4038, -3660, -3929, -3674, -2780, -1445, -98, 1421, 1957, 1178, -235, -1323, -1950, -2200, -1553, -2657, -1516, -707, -642, -825, -762, -160, 199, 1873, 3570, 3910, 3162, 2239, 1326, 74, -608, @@ -4852,9 +5488,50 @@ RAM_ALIGN const Word16 st1SCF0_7_base5_32x8_Q11[256] = { 5188, 4327, 2586, 1560, 1069, 243, -926, -1434, 8190, 8354, 5781, 3535, 1325, -678, -1811, -2308, 1040, 3253, 3541, 2062, 772, 976, 2227, 2227, 6489, 6673, 4961, 3675, 3117, 2400, 1002, -128, 3879, 2562, 1209, 1246, 1798, 2292, 2086, 1271, 1943, 4367, 5578, 5673, 5208, 4138, 1700, -56, - -3851, -2589, 638, 3762, 4621, 4195, 4496, 4150, 505, 1957, 3114, 4048, 3974, 4575, 4072, 2606}; + -3851, -2589, 638, 3762, 4621, 4195, 4496, 4150, 505, 1957, 3114, 4048, 3974, 4575, 4072, 2606 + #ifdef CR9_C_ADD_1p25MS_LRSNS + /* negated part */ + , -4634, -1666, 1086, 2778, 3276, 2951, 2343, 1547, + -6032, -4939, -1967, 908, 2517, 3186, 3066, 2287, + 4477, 4038, 3660, 3929, 3674, 2780, 1445, 98, + -1421, -1957, -1178, 235, 1323, 1950, 2200, 1553, + 2657, 1516, 707, 642, 825, 762, 160, -199, + -1873, -3570, -3910, -3162, -2239, -1326, -74, 608, + 5149, 5922, 4105, 1538, -904, -2462, -2719, -2500, + 1889, -1295, -2227, -1246, -269, 607, 424, -276, + -1619, -1287, -805, -983, -917, -430, -13, 176, + -2965, -5579, -4733, -1915, 563, 1847, 1927, 1298, + -1625, -29, 1163, 1341, 982, 356, -139, -604, + -5579, -6061, -3788, -1154, -287, -737, -1412, -1310, + 1087, 436, -12, -870, -969, -1759, -2439, -2040, + -3456, -4989, -4772, -3645, -2958, -3113, -3015, -2002, + 6045, 3264, 225, -796, -1050, -1286, -1685, -1794, + -209, -1208, -1268, -2595, -4955, -4612, -1078, 812, + -5494, -2718, -267, 693, 754, 393, 317, 480, + -9886, -6389, -2857, -513, 806, 1318, 1316, 1481, + -180, 1167, 2345, 3420, 3779, 3204, 2289, 1094, + -2849, -4058, -2279, 451, 1587, 1217, -280, -1676, + -788, 329, 1105, 1084, -390, -5244, -5773, -1345, + -3957, -6165, -6278, -5122, -3954, -1172, 1662, 2409, + -359, 1537, 2129, 2326, 2134, 31, -4240, -7024, + 2433, -751, -2682, -3447, -2562, -1930, -1692, -901, + -5188, -4327, -2586, -1560, -1069, -243, 926, 1434, + -8190, -8354, -5781, -3535, -1325, 678, 1811, 2308, + -1040, -3253, -3541, -2062, -772, -976, -2227, -2227, + -6489, -6673, -4961, -3675, -3117, -2400, -1002, 128, + -3879, -2562, -1209, -1246, -1798, -2292, -2086, -1271, + -1943, -4367, -5578, -5673, -5208, -4138, -1700, 56, + 3851, 2589, -638, -3762, -4621, -4195, -4496, -4150, + -505, -1957, -3114, -4048, -3974, -4575, -4072, -2606 +#endif +}; -RAM_ALIGN const Word16 st1SCF8_15_base5_32x8_Q11[256] = { +#ifdef CR9_C_ADD_1p25MS_LRSNS +RAM_ALIGN const Word16 st1SCF8_15_base5_32x8_Q11[8 * 32 * 2] = +#else +RAM_ALIGN const Word16 st1SCF8_15_base5_32x8_Q11[256] = +#endif +{ 475, -2066, -4387, -4865, -4568, -4456, -4691, -5187, -2652, -3685, -3865, -3707, -3611, -3756, -3696, -3557, 285, -529, -1333, -2188, -3316, -4480, -5402, -6101, -648, -978, -1129, -993, -488, -293, 140, 181, 1801, 611, -1875, -4519, -5614, -5860, -5915, -6045, -608, -1997, -2782, -2015, -1337, -2027, -3307, -4930, @@ -4870,7 +5547,43 @@ RAM_ALIGN const Word16 st1SCF8_15_base5_32x8_Q11[256] = { 7679, 3120, -937, -1636, -792, -770, -1347, -2625, -2361, -2269, -1152, -452, -716, -1543, -2025, -2638, 2106, 2248, 1574, 422, -702, -1546, -2134, -3079, 264, 1412, 2301, 2682, 2775, 2915, 2370, 832, 2745, 2847, 2140, 1302, -563, -3173, -5002, -6194, 4380, 8698, 5934, 1910, -600, -1660, -1616, -1916, - 1157, 3260, 4911, 6220, 5456, 2853, 827, -1344, -865, 668, 2850, 4570, 5349, 5459, 4917, 3603}; + 1157, 3260, 4911, 6220, 5456, 2853, 827, -1344, -865, 668, 2850, 4570, 5349, 5459, 4917, 3603 + #ifdef CR9_C_ADD_1p25MS_LRSNS + /* negated part */ + , -475, 2066, 4387, 4865, 4568, 4456, 4691, 5187, + 2652, 3685, 3865, 3707, 3611, 3756, 3696, 3557, + -285, 529, 1333, 2188, 3316, 4480, 5402, 6101, + 648, 978, 1129, 993, 488, 293, -140, -181, + -1801, -611, 1875, 4519, 5614, 5860, 5915, 6045, + 608, 1997, 2782, 2015, 1337, 2027, 3307, 4930, + -698, -551, -115, -102, 195, 1557, 4767, 7724, + 2892, 3042, 2429, 1280, -315, -1180, -1628, -1222, + 469, 683, 1657, 3350, 3860, 3369, 2878, 3004, + 2194, 2903, 3172, 2976, 2113, 1414, 878, 1014, + 1210, 146, -708, -616, 2291, 4999, 4564, 3881, + 1738, 1194, -184, -1731, -2183, -1511, -525, 1008, + -2336, -1974, -781, 989, 3720, 5740, 6623, 7084, + 771, -87, -1058, -516, 443, 1094, 1312, 1781, + -1362, -2249, -2833, -2751, -1685, -442, 829, 2192, + 1692, 1375, 468, -1063, -2800, -4465, -5194, -4508, + -2888, -1545, 2674, 3832, 2540, 2595, 4171, 5933, + -740, 45, 1187, 1801, 1742, 1596, 1500, 1819, + -896, -626, 15, 1015, 1652, 2507, 3485, 4598, + -1327, -1397, -519, -151, -644, -481, -296, 140, + -2292, -2529, -1207, 2810, 4856, 4112, 3414, 3945, + -291, 227, 579, 14, -586, -94, 1234, 4640, + -1032, -1694, -2293, -2415, -2212, -1429, 1869, 7325, + 1026, 667, -58, -537, -738, -1302, -1964, -2678, + -7679, -3120, 937, 1636, 792, 770, 1347, 2625, + 2361, 2269, 1152, 452, 716, 1543, 2025, 2638, + -2106, -2248, -1574, -422, 702, 1546, 2134, 3079, + -264, -1412, -2301, -2682, -2775, -2915, -2370, -832, + -2745, -2847, -2140, -1302, 563, 3173, 5002, 6194, + -4380, -8698, -5934, -1910, 600, 1660, 1616, 1916, + -1157, -3260, -4911, -6220, -5456, -2853, -827, 1344, + 865, -668, -2850, -4570, -5349, -5459, -4917, -3603 + #endif +}; /* tables for MPVQ pulse enumeration */ @@ -4920,14 +5633,30 @@ RAM_ALIGN const UWord32 h_memN10K22[22 + 2] = {0U, RAM_ALIGN const UWord32 h_memN6K2[2 + 2] = {0U, 1U, 11U, /*U*/ 30U}; /*N=6,K=1, h_memN6K1={0U,1U, 5U,}; */ -RAM_ALIGN const UWord32 *const MPVQ_offs_ptr[M + 1] = {NULL /*0*/, NULL, NULL, NULL, NULL, NULL, - h_memN6K2, NULL, NULL, NULL, h_memN10K22, NULL, - NULL, NULL, NULL, NULL, h_memN16K12}; +#ifdef CR9_C_ADD_1p25MS_LRSNS +RAM_ALIGN const UWord32 h_memN5K8[8 + 2] = { 0U, 1U, 9U, 41U, 129U, 321U, 681U, 1289U, 2241U, /*U*/ 1824U }; +RAM_ALIGN const UWord32 h_memN8K2[2 + 2] = { 0U, 1U, 15U, /*U*/ 56U }; +RAM_ALIGN const UWord32 h_memN15K5[5 + 2] = { 0U, 1U, 29U, 421U, 4089U, 29961U, /*U*/ 88522U }; + +RAM_ALIGN const UWord32* const MPVQ_offs_ptr[M + 1] = { NULL /*0*/, NULL, NULL, NULL, NULL, h_memN5K8, + h_memN6K2, NULL, h_memN8K2, NULL, h_memN10K22, NULL, + NULL, NULL, NULL, h_memN15K5 , h_memN16K12 }; +#else +RAM_ALIGN const UWord32* const MPVQ_offs_ptr[M + 1] = { NULL /*0*/, NULL, NULL, NULL, NULL, NULL, + h_memN6K2, NULL, NULL, NULL, h_memN10K22, NULL, + NULL, NULL, NULL, NULL, h_memN16K12 }; +#endif /*maxK coefficents for MPVQ de-indexing lookup */ +#ifdef CR9_C_ADD_1p25MS_LRSNS +RAM_ALIGN const Word16 tabledKMAX[M + 1] = { + 0, 0, 0, 0, 0, 8/*N=5 LR*/, 2 /*N=6*/, 0, 2 /*N=8 LR*/, 0, 22 /*N=10*/, 0, 0, 0, 0, 5/*N==15 LR*/, 12 /*N=16*/ +}; +#else RAM_ALIGN const Word16 tabledKMAX[M + 1] = { 0, 0, 0, 0, 0, 0, 2 /*N=6*/, 0, 0, 0, 22 /*N=10*/, 0, 0, 0, 0, 0, 12 /*N=16*/ }; +#endif RAM_ALIGN const Word16 isqrt_Q16tab[1 + 64] = {/*table generated using ISqrt16 function + shift to Q16 */ 32767, 32767, 32767, 32767, 32766, 29308, 26754, 24770, 23169, 21844, @@ -4938,7 +5667,7 @@ RAM_ALIGN const Word16 isqrt_Q16tab[1 + 64] = {/*table generated using ISqrt16 f 9268, 9176, 9088, 9001, 8918, 8836, 8757, 8680, 8605, 8532, 8460, 8390, 8323, 8256, 8191}; -#ifdef ENABLE_HR_MODE +#if defined(ENABLE_HR_MODE) || defined (CR9_C_ADD_1p25MS_LRSNS) RAM_ALIGN const Word32 isqrt_Q31tab[1 + 64] = {/* 2^31 / sqrt(idx) */ 2147483647, 2147483647, 1518500249, 1239850262, 1073741824, 960383883, 876706528, 811672525, 759250124, 715827882, 679093956, 647490682, @@ -4969,3 +5698,344 @@ RAM_ALIGN const Word16 adjust_global_gain_tables[5][NUM_SAMP_FREQ] = {{80, 230, const Word16 plc_fadeout_param_maxlen[4] = {800, 400, 266, 200}; const Word16 plc_fadeout_param_maxbytes[4] = {27, 14, 9, 7}; + +#ifdef CR9_C_ADD_1p25MS_LRSNS +RAM_ALIGN const Word16 lrsns_vq_gain_lvls_fx[SNSLR_MAX_PVQ_SEARCH_CAND] = { 4,8,8 }; + +/* BASOP gains stored in Q12 to be aligned with the 38-bit SNS-VQ BASOP gain tables */ +/* Cfloat values wer Q11 quantizd */ +RAM_ALIGN const Word16 lrsns_vq_split_gainsQ12_fx[4] = { 7424 , 10240 , 13568 , 17664 }; +/* q_gains5Q11_shape0_4[4] = { +1.8125 , +2.5000 , +3.3125 , +4.3125 }; */ +RAM_ALIGN const Word16 lrsns_vq_full_gainsQ12_fx[8] = { 5888 , 7424 , 8704 , 10240 , 12032 , 14336 , 16640 , 20224 }; +/* q_gains5Q11_shape1_8[8] = { +1.4375 , +1.8125 , +2.125 , +2.500 , +2.9375 , +3.5000 , +4.0625 , +4.9375 }; */ +RAM_ALIGN const Word16 lrsns_vq_fixenv_gainsQ12_fx[8] = { 5632 , 7168 , 8192 , 9472 , 10752 , 12544 , 14592 , 18176 }; +/* q_gains5Q11_shape2_8[8] = { ++1.375, +1.75, +2.0 , +2.3125 , +2.625 , +3.0625 , +3.5625 , +4.4375 }; */ + +RAM_ALIGN const Word16 *const lrsns_vq_gainsQ12_fx[SNSLR_MAX_PVQ_SEARCH_CAND] = +{ lrsns_vq_split_gainsQ12_fx, lrsns_vq_full_gainsQ12_fx, lrsns_vq_fixenv_gainsQ12_fx }; + +RAM_ALIGN const Word16 lrsns_cbA_fx[2 * 16] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -0, + 2431, 2077, 1592, 824, 16, -540, -560, -536, + -154, 385, 927, 1129, 455, -760, -2567, -4719 +}; + +#endif + +#ifdef CR9_C_ADD_1p25MS_LRSNS + +/*LRSNS tables to construct the 170x16 st1B from legacy st1(LF,HF) tables */ +/* each index point to two vector in the split 2x32 stage 1 cb , lower 12 bits in use [1][5][1][5] */ +/* ff,fr,rf,rr , handled by counting the absoulte idx */ +RAM_ALIGN const Word16 lrsns_st1B_merged170orderSortedSegmCnt_fx[4] = { /*ff,fr,rf,rr */ + 88, 42, 24, 16 +}; +RAM_ALIGN const Word16 lrsns_st1B_merged170orderSortedSegmCum_fx[5] = { /*ff,fr,rf,rr */ + 0, 88, 130, 154, 170 +}; +RAM_ALIGN const Word16 lrsns_st1B_merged170orderSort12bitIdx_fx[170] = { /* actually 14 bit index can also be saved */ + 15, 19, 119, 162, 177, 185, 227, 296, 297, 353, 357, 369, 370, 372, 377, 416, 418, + 420, 515, 529, 561, 569, 603, 625, 627, 673, 680, 754, 756, 777, 786, 801, 809, 834, + 837, 848, 849, 850, 852, 864, 865, 866, 872, 904, 908, 913, 914, 924, 928, 978, 996, + 1041, 1082, 1088, 1089, 1090, 1139, 1651, 1751, 1982, 1999, 2066, 2120, 2194, 2247, 2391, 2495, 2579, + 2626, 2632, 2649, 2959, 3071, 3107, 3223, 3331, 3395, 3415, 3548, 3641, 3675, 3703, 3820, 3825, 3849, + 3853, 3865, 3916, 45, 107, 110, 151, 168, 169, 247, 305, 313, 323, 357, 361, 777, 785, + 841, 1096, 1123, 1347, 1427, 1498, 1555, 1617, 1643, 1646, 1651, 1774, 2051, 2087, 2265, 2296, 2371, + 2971, 3022, 3241, 3287, 3319, 3331, 3543, 3601, 3683, 3689, 3697, 122, 259, 274, 387, 401, 496, + 657, 707, 739, 850, 857, 928, 929, 932, 996, 1123, 1270, 1303, 1609, 2151, 2193, 2371, 2632, + 2633, 55, 119, 291, 299, 343, 681, 1001, 1307, 1427, 1609, 1646, 1683, 2157, 2222, 3331, 4060 +}; + +RAM_ALIGN const Word32 lrsns_st1B_enBy2TabW32_fx[2 * 32] = { + /*LF part*/ + 30234814, 48294454, 44252960, 10048319, 5798194, 24342955, 50660188, 6227077, + 3474389, 37555746, 3633757, 43938502, 8136036, 52215414, 28346960, 28744396, + 19588476, 76644956, 24786264, 18434221, 32956728, 72443234, 42151630, 19760916, + 29437456, 96801748, 19960876, 70624637, 19538794, 66641198, 56240496, 45131948, + + /*HF part*/ + 68520493, 51375963, 52197680, 2006716, 82469877, 28647435, 42830587, 15395581, + 29105630, 20211225, 34248538, 7908398, 75887420, 4137010, 15516815, 40589204, + 49172712, 8171368, 22263062, 2379007, 44354878, 11938118, 39554253, 7529063, + 41090552, 13103632, 14530709, 18529070, 47842888, 71549086, 57585190, 62886415, +}; + +const RAM_ALIGN Word16 lrsns_st1C_pitch0_mp0Q11_fx[16] = { + 2293, 2602, 1960, 1161, 880, 417, 34, -169, + -368, -541, -604, -318, -287, -958, -2341, -3759 +}; +const RAM_ALIGN Word16 lrsns_st1C_pitch1_mp1Q11_fx[16] = { + 258, 805, 789, 533, 507, 123, 183, 155, + 88, 151, 535, 1019, 1023, 58, -2013, -4211 +}; +#ifdef LRSNS_CBC_NO_LTPF_DEPENDENCY +const RAM_ALIGN Word16* lrsns_st1CTrainedMapMeans_fx[2] = { lrsns_st1C_pitch0_mp0Q11_fx ,lrsns_st1C_pitch1_mp1Q11_fx }; +#else +const RAM_ALIGN Word16 lrsns_st1C_pitch2_mp2Q11_fx[16] = { + -421, 206, 399, 323, 383, 25, 233, 263, + 240, 381, 914, 1464, 1460, 397, -1904, -4361 +}; +const RAM_ALIGN Word16* lrsns_st1CTrainedMapMeans_fx[3] = { lrsns_st1C_pitch0_mp0Q11_fx ,lrsns_st1C_pitch1_mp1Q11_fx,lrsns_st1C_pitch2_mp2Q11_fx }; +#endif +/* BE representable in Q11 after Q4*Q7 multiplcation */ +const RAM_ALIGN Word16 lrsns_st1C_Both_scaleQ4_7p4bits_fx[2] = { +-1, 86 /* exact BASOP Q4 value, used in synthesis */ }; +const RAM_ALIGN Word16 lrsns_st1C_Both_inv_scaleQ15_7p4bits_fx[2] = { +-1 , 6096 /* BASOP Q15 value, invScale used in encoder side target creation */ }; + +/* Word8 storage of ST1 codebook to save ROM in BASOP */ +const RAM_ALIGN Word8 lrsns_st1C_Both_Word8_fx[170 * 16] = { + -88, -78, -57, -39, -27, -15, -6, 3, 11, 17, 20, 23, 32, 47, 69, 88, + -86, -40, -7, 4, 1, 5, 10, 10, 0, -5, -5, 4, 9, 23, 38, 39, + -71, -69, -65, -49, -29, -5, 16, 30, 21, -8, -3, 15, 27, 40, 63, 87, + -71, -36, -10, -5, 2, 17, 15, 18, 24, 24, 13, 7, 11, 2, -6, -7, + -70, -23, 13, 12, 0, 7, 19, 14, 1, -1, 6, 3, -2, 1, 9, 13, + -68, -79, -67, -42, -26, -17, 8, 29, 38, 34, 32, 33, 32, 36, 36, 21, + -62, -66, -56, -41, -33, -13, 11, 17, 16, 17, 28, 39, 40, 41, 40, 23, + -61, -62, -51, -31, -26, -25, -23, -15, -3, 12, 24, 30, 33, 43, 68, 85, + -60, -63, -47, -28, -17, -9, 13, 30, 36, 31, 25, 24, 27, 28, 17, -6, + -57, -47, -25, -11, -17, -12, -1, -7, -4, -1, -7, 1, 23, 44, 58, 60, + -54, -59, -61, -50, -22, -1, 25, 37, 37, 31, 21, 13, 21, 31, 27, 4, + -53, -36, -14, 3, 13, 12, 14, 19, 26, 31, 30, 22, 3, -12, -21, -36, + -53, -52, -39, -24, -12, 2, 23, 34, 32, 27, 16, 8, 11, 21, 14, -9, + -45, -46, -31, -16, -8, -5, 6, 21, 31, 32, 26, 22, 18, 11, 1, -17, + -40, -11, 7, 11, 4, 13, 5, -13, -28, -20, -10, 0, 8, 19, 23, 32, + -40, -32, -18, -2, 6, 12, 8, 1, 2, 4, 9, 15, 20, 13, 3, -1, + -40, -9, 11, 7, 6, 6, 0, -13, -13, -1, 7, 12, 8, 4, 6, 9, + -39, 5, 19, 12, 13, 9, 4, 3, -2, -6, -4, 2, 3, -2, -6, -13, + -38, -13, 1, 1, 4, 17, 16, 12, 8, 0, -9, -23, -20, 0, 18, 24, + -38, -25, -13, -12, -24, -17, -6, 4, 10, 6, -17, -13, 6, 35, 51, 53, + -38, -34, -30, -24, -9, 7, 17, 18, 14, 9, 11, 14, 18, 18, 12, -3, + -38, -36, -19, 2, 20, 28, 28, 33, 31, 16, 6, 4, -4, -12, -23, -36, + -38, -46, -38, -22, -17, -22, -11, 18, 35, 34, 27, 25, 24, 22, 12, -3, + -37, 3, 34, 16, -8, -30, -54, -45, -23, -9, -3, 14, 12, 15, 42, 72, + -35, -55, -53, -38, -30, -20, -5, 6, 13, 16, 21, 25, 29, 41, 48, 36, + -35, -45, -50, -47, -48, -41, -31, -16, -1, 9, 20, 21, 29, 51, 81, 104, + -35, -46, -46, -35, -24, -11, 9, 27, 34, 33, 27, 25, 21, 17, 9, -6, + -34, -24, -20, -13, -11, -7, 2, 2, -13, -4, 23, 31, 21, 16, 16, 16, + -33, -54, -66, -58, -43, -23, -16, -10, 1, 18, 23, 18, 28, 51, 74, 89, + -31, 16, 51, 48, 30, 18, 12, 2, -7, -17, -23, -26, -29, -26, -17, -1, + -31, -20, -18, -20, -13, -8, 1, 13, 20, 2, -13, -8, 12, 27, 31, 25, + -30, -33, -40, -36, -30, -11, 3, 10, 14, 15, 24, 29, 31, 27, 20, 8, + -30, -45, -40, -20, -14, -21, -31, -23, -10, 1, 12, 15, 22, 39, 64, 83, + -29, -15, 0, 4, 8, 16, 17, 11, 5, 4, 2, 1, 11, 7, -13, -29, + -29, -29, -20, -3, 15, 27, 27, 18, 17, 29, 31, 19, -3, -19, -35, -44, + -28, -21, -26, -26, 2, 22, 30, 37, 34, 18, 8, 2, 0, -9, -18, -25, + -28, -19, -11, -7, -1, 8, 13, 17, 21, 25, 30, 23, 5, -9, -26, -42, + -27, -9, 3, 2, 3, 11, -7, -14, 9, 25, 14, -6, -4, -1, 0, 2, + -27, -27, -25, -17, -18, -10, -8, -16, -18, 1, 16, 20, 29, 35, 38, 27, + -26, -44, -8, 8, -12, -5, -6, -9, 1, 13, 17, 15, 35, 42, 6, -29, + -24, -22, -16, -13, -12, 0, 10, 15, 19, 8, 5, 13, 26, 18, -5, -21, + -24, -42, -47, -33, -31, -32, -19, 2, 13, 13, 9, 4, 16, 35, 58, 80, + -24, -16, -7, -4, -7, -6, -8, -9, -3, 5, 11, 15, 23, 22, 12, -2, + -23, -13, 1, 1, -19, -17, 7, 21, 29, 29, 20, 12, 0, -9, -15, -26, + -23, -39, -40, -26, -19, -13, -4, -10, -21, -20, 0, 18, 26, 39, 57, 73, + -22, -26, -25, -25, -28, -21, -3, 23, 35, 38, 31, 20, 10, 5, 2, -13, + -21, 3, 27, 20, -9, -8, 4, 3, -3, -10, -18, -16, -4, 8, 11, 13, + -21, -13, -5, 1, 15, 22, 23, 27, 31, 25, 13, -1, -18, -28, -33, -40, + -20, -15, 0, 10, 9, 13, 12, 0, -15, -8, 7, 9, 4, 0, -2, -6, + -20, -15, -9, -6, -2, -14, -40, -5, 34, 49, 45, 29, -7, -16, -7, -18, + -19, 13, 24, 22, 27, 17, 2, -1, -8, -17, -26, -16, 0, 1, -4, -15, + -18, -14, -7, 6, 19, 21, 20, 22, 20, 16, 17, 14, -5, -27, -39, -44, + -17, 30, 76, 76, 57, 44, 11, -23, -43, -54, -57, -58, -53, -33, 5, 40, + -17, -19, -22, -34, -39, -15, 12, 23, 21, 17, 18, 22, 20, 13, 6, -7, + -17, -12, -8, 6, 19, 4, -15, 0, 21, 32, 30, 8, -9, -15, -20, -24, + -16, 33, 77, 82, 55, 23, -2, -11, -20, -39, -58, -65, -58, -33, 0, 32, + -16, -21, -26, -21, -7, 7, 10, 8, 11, 16, 22, 20, 12, 3, -4, -16, + -15, 8, 29, 23, 11, -9, -29, -23, -14, -5, -2, -2, 4, 10, 9, 3, + -14, -17, -19, -22, -11, 2, 15, 27, 33, 27, 20, 14, 3, -10, -20, -27, + -13, -2, 6, 3, -7, -7, 4, 26, 31, 19, 13, 12, -4, -23, -29, -32, + -13, -6, 6, 18, 21, 18, 12, 7, 5, 5, 5, -1, -7, -15, -23, -33, + -12, -7, 0, 3, 5, 0, -5, 4, 18, 24, 25, 16, 1, -13, -25, -34, + -12, -3, 0, -4, -3, 10, 9, -3, -5, -6, -6, -3, 14, 20, 5, -14, + -12, -11, -15, -14, -7, 2, 12, 6, -10, -21, -4, 11, 22, 22, 15, 4, + -11, -12, -13, -5, 11, 16, 11, 6, 5, 15, 22, 20, 3, -12, -23, -33, + -11, -10, -8, -11, -3, 13, 19, 18, 11, -1, -12, -8, 6, 7, 0, -12, + -11, -17, -20, -20, -16, -9, -2, 7, 24, 32, 32, 26, 14, 0, -14, -27, + -10, -11, -11, -20, -26, -25, -7, 7, 20, 29, 19, 6, 5, 15, 9, 0, + -10, -5, -7, -9, -4, 9, 10, 0, -17, -28, -21, -7, 12, 28, 29, 22, + -8, -20, -30, -25, -28, -26, -18, -9, 7, 15, 24, 26, 30, 33, 24, 5, + -8, -17, -19, -17, -16, -7, -7, -7, 3, 4, 4, 6, 21, 28, 22, 10, + -8, 35, 62, 60, 43, 21, 6, -4, -21, -34, -37, -42, -43, -32, -12, 6, + -8, -6, -3, -1, 1, 0, -5, -5, 2, 11, 23, 21, 8, -2, -11, -24, + -7, -21, -21, -13, 1, 18, 28, 30, 30, 34, 33, 18, 0, -21, -52, -57, + -6, -31, -40, -39, -36, -27, -20, -22, -19, -4, 10, 12, 19, 38, 69, 95, + -6, -38, -48, -42, -37, -27, -13, 2, 7, 9, 17, 23, 33, 45, 46, 28, + -6, -18, -39, -58, -59, -34, -15, -6, 0, 4, 15, 22, 24, 38, 59, 71, + -4, 6, 6, 11, 15, 9, 1, -7, 2, 11, 16, 10, -5, -14, -26, -31, + -4, 2, 7, -6, -59, -49, -4, -1, 1, 15, 9, -19, -19, 11, 52, 64, + -2, 31, 53, 43, 20, 8, -2, -17, -24, -21, -22, -25, -22, -14, -8, 1, + 1, -3, -3, 4, 6, 9, -4, -31, -39, -17, -5, -1, 6, 16, 27, 34, + 1, 10, 15, 12, -5, -20, -21, -10, 12, 27, 23, 10, -4, -12, -17, -23, + 3, 13, 23, 25, 20, 14, 3, 7, 11, -4, -31, -43, -35, -21, -1, 19, + 3, -3, -9, -16, -19, -7, 1, 7, 11, -2, -5, 5, 23, 20, 2, -10, + 4, -22, -27, -23, -23, -11, 7, 14, 15, 15, 6, -3, -9, -6, 19, 44, + 5, -5, -9, -8, -9, -7, 0, 17, 29, 22, 12, 12, 6, -8, -23, -32, + 6, -31, -58, -64, -41, -12, -1, 3, 2, 0, 3, 6, 21, 37, 55, 74, + 7, 12, 10, 1, 2, 6, 2, -5, -7, -3, -2, 0, 1, 1, -6, -19, + 9, 1, 2, 12, 15, 11, -11, -33, -17, 13, 20, 9, 0, -7, -11, -13, + 10, 21, 26, 24, 18, 4, -5, -13, -14, -6, 4, 7, -7, -19, -25, -25, + 11, 1, -4, -7, -17, -28, -18, 4, 19, 27, 21, 12, 6, 2, -8, -20, + 11, 4, -17, -36, -48, -39, -18, 0, 3, 1, 3, 6, 15, 27, 39, 49, + 11, 3, -12, -26, -20, -2, 11, 16, 14, 9, 18, 19, 6, -7, -15, -25, + 12, 0, -12, -7, -5, -15, -21, -14, -5, 4, 13, 22, 22, 13, 3, -8, + 14, 17, 19, 17, 17, 16, 1, -9, -8, -5, -13, -11, -6, -7, -14, -27, + 14, 33, 52, 50, 32, 12, -1, -6, -8, -14, -23, -30, -36, -35, -26, -13, + 16, 11, 10, 15, 21, 13, 13, 10, 8, 4, 6, 6, -6, -25, -50, -52, + 17, 9, 9, 23, 23, 10, 5, 16, 20, 13, 2, -18, -35, -39, -30, -23, + 17, 31, 47, 49, 42, 32, 22, 8, -7, -21, -31, -30, -43, -53, -42, -21, + 19, 37, 50, 42, 28, 24, 15, -8, -22, -22, -19, -28, -39, -39, -26, -12, + 19, 39, 47, 31, 10, 0, 1, 1, -6, -15, -21, -23, -26, -25, -18, -13, + 19, 12, 0, -7, -3, 1, -2, -12, -19, -19, -11, -1, 9, 14, 12, 5, + 19, 33, 47, 55, 47, 23, -6, -18, -23, -24, -14, -9, -22, -34, -42, -33, + 19, 13, -1, -20, -24, -13, -6, -6, -11, -16, -21, -24, -15, 9, 45, 71, + 21, 15, 8, 4, 5, 6, 3, 4, -2, -17, -20, -8, 12, 9, -12, -28, + 22, 10, 9, 20, 18, -4, -6, 1, 5, 9, 16, 18, -1, -22, -47, -48, + 22, 22, 27, 42, 41, 33, 21, 0, -17, -27, -28, -37, -39, -32, -19, -8, + 23, 4, -28, -27, -16, -5, 9, 28, 28, 0, -52, -61, -12, 18, 35, 56, + 23, -6, -26, -22, -18, -18, -20, -28, -23, -3, 9, 3, 1, 17, 44, 66, + 23, 21, 12, 10, 6, -5, 3, 8, 4, -1, 8, 11, -2, -16, -40, -43, + 24, 11, -4, -9, -8, -10, -21, -37, -44, -26, 0, 8, 17, 29, 36, 35, + 25, 11, 3, 7, 13, 14, 9, 2, -7, -13, -17, -12, -10, -10, -7, -8, + 25, 24, 17, 12, 20, 7, -11, -10, -15, -16, -16, -5, 3, -4, -11, -21, + 27, 26, 17, 6, -5, -16, -12, 2, -1, -9, -16, -7, 3, 3, -2, -15, + 28, 15, -10, -29, -30, -17, 4, 16, 33, 29, 15, 6, -5, -18, -18, -18, + 28, 12, 4, 16, 23, 12, 6, -1, -6, -7, 2, 8, -2, -19, -38, -37, + 29, 16, -1, -15, -25, -15, -12, -9, 18, 29, 23, 12, -1, -13, -16, -20, + 29, 28, 25, 33, 32, 6, -13, -20, -8, 4, 7, 0, -14, -25, -43, -40, + 29, 25, 19, 17, 20, 8, -12, -34, -34, -19, -14, -6, 2, 4, 3, -9, + 30, 28, 22, 14, 17, 16, 15, 8, -5, -19, -13, -4, -7, -20, -40, -41, + 30, 1, -20, -4, -6, -32, -37, -28, -18, -11, -7, -3, 8, 21, 44, 63, + 30, 42, 57, 45, 22, 6, 8, 2, -10, -27, -43, -50, -45, -33, -13, 9, + 32, 25, 20, 24, 23, 6, 3, -2, -10, -8, 4, 8, -8, -27, -47, -45, + 32, 40, 44, 29, 12, 0, -10, -18, -24, -20, -18, -23, -25, -19, -5, 4, + 34, 45, 56, 51, 33, 16, 10, 6, -8, -21, -25, -42, -55, -52, -33, -16, + 34, 53, 63, 61, 58, 44, 12, -26, -62, -68, -60, -61, -47, -18, 9, 9, + 34, 28, 22, 17, 16, 16, 9, 0, -6, -12, -26, -31, -21, -13, -13, -19, + 34, 23, 10, -15, -33, -24, -17, -15, -7, 0, -5, -10, -4, 5, 23, 35, + 35, 23, 12, 0, -16, -22, -17, 0, 17, 19, 14, 7, -5, -16, -24, -27, + 35, 32, -23, -51, -12, 33, 23, 0, -10, 1, -12, -29, -13, 9, 17, 0, + 36, 69, 78, 62, 30, -9, -40, -49, -49, -44, -48, -51, -37, -10, 19, 44, + 36, 21, 8, 11, 18, 8, 9, 8, 7, 3, 2, 1, -13, -28, -46, -44, + 37, 27, 11, 6, 14, 5, -6, -1, -9, -26, -37, -18, 3, 5, 0, -11, + 39, 31, 20, 13, 12, 6, -8, -12, -16, -16, -22, -18, -9, -6, -5, -10, + 39, 33, 25, 21, 22, 18, 7, -4, -24, -33, -33, -20, -9, -8, -14, -22, + 39, 52, 61, 57, 40, 27, 9, -12, -27, -37, -46, -50, -48, -40, -23, -2, + 40, 31, 20, 18, 14, -8, -5, 4, 8, 4, -1, -2, -14, -28, -42, -38, + 40, 29, 17, 19, 15, -9, -20, -18, -7, 1, 10, 9, -5, -15, -33, -33, + 41, 33, 23, 18, 20, 2, -13, -6, -6, -9, -16, -13, -12, -18, -21, -21, + 41, 58, 71, 51, 33, 19, -13, -42, -56, -58, -65, -67, -53, -17, 32, 65, + 41, 31, 15, 10, 4, -16, -7, 5, 7, 8, 12, 8, -7, -26, -44, -40, + 43, 40, 28, 23, 23, 6, -13, -20, -26, -18, -2, 3, -2, -13, -34, -36, + 43, 23, -11, -15, 2, 3, 6, 5, 3, 4, 11, 11, -2, -17, -33, -32, + 43, 54, 61, 49, 24, -1, -8, -3, -8, -21, -32, -43, -46, -39, -21, -9, + 43, 30, 9, -8, -2, 0, -10, -12, -14, -12, -12, -2, 4, 2, -3, -14, + 43, 35, 23, 15, 12, -8, -33, -27, -16, -12, -14, -4, 5, 0, -6, -13, + 44, 31, 19, 12, 4, -5, 1, -1, -10, -14, -1, 5, -3, -15, -33, -34, + 44, 28, 8, 8, 18, 13, 7, -3, -10, -8, -3, -3, -13, -23, -33, -31, + 46, 40, 9, -22, -17, 6, 18, 19, 6, -11, -14, -5, 5, -9, -35, -35, + 47, 47, 53, 51, 27, -3, -46, -65, -46, -33, -32, -29, -28, -17, 17, 56, + 47, 43, 27, 25, 24, 2, -2, -1, -17, -19, -1, 6, -11, -33, -50, -40, + 48, 50, 47, 34, 9, -7, -10, -9, -10, -12, -17, -28, -33, -30, -19, -12, + 48, 51, 51, 41, 25, 7, -18, -39, -47, -47, -44, -36, -21, -2, 14, 17, + 48, 23, -3, 10, 21, -2, -9, -6, -4, -2, 8, 15, 0, -23, -40, -36, + 50, 25, 2, -3, 4, 16, 13, -4, -21, -30, -30, -29, -20, -2, 13, 17, + 59, 44, 18, 13, 23, 18, 8, -7, -28, -26, -8, -3, -10, -24, -42, -35, + 61, 47, 30, 22, 25, 21, 8, -2, -16, -25, -14, -5, -15, -39, -56, -43, + 62, 46, 31, 37, 38, 16, -13, -33, -25, -7, -1, -3, -20, -39, -51, -38, + 63, 47, 23, 9, 5, -2, -13, -12, -8, -7, -14, -20, -26, -25, -15, -6, + 63, 42, 20, 9, 7, 0, -10, -18, -21, -22, -24, -24, -22, -16, 0, 17, + 64, 54, 43, 22, -17, -38, -42, -38, -37, -23, -17, -20, -15, -2, 22, 42, + 64, 51, 36, 34, 35, 21, 6, -9, -34, -41, -20, -7, -18, -35, -48, -36, + 66, 66, 65, 55, 35, 8, -9, -18, -29, -35, -39, -45, -47, -39, -24, -9, + 67, 38, -11, -47, -53, -27, -14, -19, -21, -21, 0, 6, 9, 19, 31, 45, + 70, 60, 50, 45, 32, 3, -17, -33, -34, -24, -10, -9, -22, -36, -44, -30, + 75, 57, 34, 30, 34, 20, -7, -29, -42, -36, -21, -15, -19, -28, -32, -20, + 76, 61, 27, -11, -30, -32, -29, -24, -24, -22, -18, -21, -16, 1, 22, 42, + 96, 77, 40, 5, -17, -27, -30, -28, -25, -24, -22, -23, -23, -16, 1, 16, + 99, 86, 61, 28, -5, -26, -39, -35, -34, -20, -5, -15, -34, -40, -22, 2, + 127, 101, 43, -12, -35, -34, -40, -42, -40, -40, -41, -40, -31, -6, 28, 61 +}; + +const RAM_ALIGN Word16 lrsns_st1C_Both_EnBy2Tab_fx[170] = /* 2*170 words = 340 bytes st1C vector energiesBy2 for BASOP optimized st1C search */ +{ + 18337, 6464, 16528, 4442, 3325, 13879, 11473, 14799, + 8649, 8092, 10092, 5046, 6178, 4902, 2766, 2051, + 1326, 1302, 2147, 5282, 3107, 4708, 5827, 8414, + 8739, 17452, 6318, 2682, 16210, 5422, 2792, 5004, + 10256, 1519, 5041, 3956, 3440, 1079, 4168, 3788, + 2020, 9834, 1334, 2524, 8456, 4251, 1404, 4078, + 797, 4834, 2070, 3822, 17739, 3451, 2423, 16332, + 1881, 1833, 3031, 2527, 1746, 2000, 646, 1403, + 1949, 914, 3011, 2055, 2134, 3985, 1646, 9429, + 1011, 6486, 11620, 7391, 10705, 1452, 6977, 4626, + 2571, 1958, 3481, 1012, 2781, 1940, 10326, 412, + 1532, 2142, 1890, 5401, 1814, 1322, 1576, 6375, + 3799, 3481, 9205, 6809, 4090, 1001, 7829, 5257, + 1371, 3563, 6407, 7621, 5384, 2630, 4548, 1109, + 1827, 1397, 3300, 2621, 2531, 4684, 2870, 3750, + 5722, 8534, 4237, 4413, 10184, 18130, 3132, 3079, + 2704, 4383, 16988, 3762, 2559, 2501, 4264, 12450, + 3930, 3390, 3062, 19816, 3948, 4767, 2736, 9537, + 1928, 3348, 3123, 3165, 4113, 13238, 5997, 6146, + 10143, 3619, 3770, 6037, 8141, 8949, 4701, 4897, + 9675, 9684, 13828, 8352, 10983, 9836, 9009, 11364, + 15100, 23026 +}; +#endif + +#ifdef CR9_C_ADD_1p25MS_LRSNS +RAM_ALIGN const Word16 isqrt_Q15tab[1 + 6] = { + /* onepulse_search_tab based search , Q15 table generated using isqrt_Q16tab table for idx=[8(4*2),16(4*4), 20(4*5),24(4*6) ] */ + /*this slighly suboptimal inv_sqrt(x) table is used to enable optional exact use of the ROM saving BASOP ISqrt16() function */ + + 32767/*0*/, 32766/*1*/, 23169 /*2*/, 18918 /*3*/ , 16384/*4*/ , 14654 /*5*/, 13377/*6*/ + + /* i.e. value in isqrt_Q15tab[n=0..6] == isqrt_Q16tab[4*n] */ +}; + + +RAM_ALIGN const Word16 lrsns_signs_fix_fx[SNSLR_N_FIXENV] = { 12, 12, 12, 10 }; +RAM_ALIGN const Word16 long_bell_fx[M - 1 + 4] = { /* --> constants.c ROM */ + 6, 6, 7, 7, 8 , + 8, 8, 7, 7, 6 , + 6, 5, 5, 5, 5 , + 5, 5, 5, 5 }; + +RAM_ALIGN const Word16 decay_fx[M - 1] = +{ /* floor((25:-1:11 -i)/2)*/ + 12,12,11,11,10, + 10, 9, 9, 8, 8, + 7, 7, 6, 6, 5 +}; + +RAM_ALIGN const Word16 *lrsns_fix_env_fx[SNSLR_N_FIXENV] = { &(long_bell_fx[4]), decay_fx, &(long_bell_fx[2]), long_bell_fx }; + + +RAM_ALIGN const Word16 lrsns_fixenv_enQ0[SNSLR_N_FIXENV * SNSLR_N_FIXENV_SHIFTS] = /* offline pre-computed from fixenv[0..3] + shifts */ +{ 487, 448, 409, 370, 1118, 1010, 902, 806, 535, 511, 487, 448, 496, 496, 485, 461 +}; + +RAM_ALIGN const Word16 lrsns_fixenv_enNormQ19[SNSLR_N_FIXENV * SNSLR_N_FIXENV_SHIFTS] = /*Q15+4 => Q19 */ +{ /* round(2.^19 ./ sqrt(fixenv_en) , for search loop */ + 23758, 24770, 25924, 27256, /*fixenv 0*/ + 15680, 16497, 17457, 18467, /*fixenv 1*/ + 22667, 23193, 23758, 24770, /*fixenv 2*/ + 23541, 23541, 23807, 24419 /*fixenv 3*/ +}; +RAM_ALIGN const Word32 L_lrsns_fixenv_enNormQ35[SNSLR_N_FIXENV * SNSLR_N_FIXENV_SHIFTS] = /*Q15+4 +16=> Q35 */ +{ /* fixenv_enQ0= [487, 448, 409, 370, 1118, 1010, 902, 806, 535, 511, 487, 448, 496, 496, 485, 461] */ + /* int32(round(2.^35 ./ sqrt(fixenv_enQ0))), "for synthesis" */ + 1556988367L, 1623345051L, 1698979717L, 1786277740L,/*fixenv 0*/ + 1027611478L, 1081157988L, 1144054146L, 1210270165L,/*fixenv 1*/ + 1485501030L, 1519985336L, 1556988367L, 1623345051L,/*fixenv 2*/ + 1542797797L, 1542797797L, 1560195349L, 1600292558L /*fixenv 3*/ +}; + +RAM_ALIGN const Word16 lrsns_norm_factorQ_L[N_SCF_SEARCH_SHAPES_ST2_LR] = { 31, 31, 19 + 16 }; /* split, full, fixenv */ +/*maxamps = [8, 5, 12]; 8*2^11 = 2^14 =16384 , 5*2^12 = 20480, 12*2^11= 24576 */ +RAM_ALIGN const Word16 lrsns_y_up_bits[N_SCF_SEARCH_SHAPES_ST2_LR] = { 11, 12, 11 }; /* split, full, fixenv, max uphifts for normaliztion */ + +#endif diff --git a/lib_lc3plus/constants.h b/lib_lc3plus/constants.h index a367939a9..2ecc1ad24 100644 --- a/lib_lc3plus/constants.h +++ b/lib_lc3plus/constants.h @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -10,10 +10,50 @@ #ifndef CONSTANTS_H #define CONSTANTS_H +#include "options.h" +#include "wmc_auto.h" #include "defines.h" - #include "basop_util_lc3plus.h" +#ifdef LTPF_ADAPTIVE_GAIN +extern RAM_ALIGN const Word16 tilt_filter_1p25ms[5][4][11]; +extern RAM_ALIGN const Word16 adaptive_gain_step; +extern RAM_ALIGN const Word16 max_adaptive_gain[4]; +extern RAM_ALIGN const Word16 max_adaptive_gain_step[4]; +#endif + +extern RAM_ALIGN const Word16 *const lpc_pre_adapt_emphasis[NUM_SAMP_FREQ]; +extern RAM_ALIGN const Word8 *const lpc_pre_adapt_emphasis_e[NUM_SAMP_FREQ]; + +#ifdef CR9_C_ADD_1p25MS +#ifdef ENABLE_HR_MODE +extern RAM_ALIGN const Word16 LowDelayShapes_n960_len_1_25ms[6]; +#else +extern RAM_ALIGN const Word16 LowDelayShapes_n960_len_1_25ms[5]; +#endif + +#ifdef ENABLE_HR_MODE +extern RAM_ALIGN const Word32 *const LowDelayShapes_n960_1_25ms[6]; +#else +extern RAM_ALIGN const Word16 *const LowDelayShapes_n960_1_25ms[6]; +#endif + +extern RAM_ALIGN const Word16 bands_number_1_25ms[]; +extern RAM_ALIGN const Word16 *const bands_offset_1_25ms[6]; + +#ifdef ENABLE_HR_MODE +extern RAM_ALIGN const Word16 bands_number_1_25ms_HR[]; +extern RAM_ALIGN const Word16 *const bands_offset_1_25ms_HR[2]; +#endif + +extern RAM_ALIGN const Word16 bands_offset_with_one_max_1_25ms[NUM_OFFSETS]; +extern RAM_ALIGN const Word16 bands_offset_with_two_max_1_25ms[NUM_OFFSETS]; + +extern RAM_ALIGN const Word16 *const bands_offset_lin_1_25ms[NUM_SAMP_FREQ]; +extern RAM_ALIGN const Word16 bands_offset_with_one_max_lin_1_25ms[NUM_SAMP_FREQ]; +extern RAM_ALIGN const Word16 bands_offset_with_two_max_lin_1_25ms[NUM_SAMP_FREQ]; + +#endif /* CR9_C_ADD_1p25MS */ #ifdef ENABLE_HR_MODE extern RAM_ALIGN const Word16 BW_cutoff_bin_all_HR[]; @@ -137,7 +177,7 @@ extern RAM_ALIGN const UWord16 ari_spec_cumfreq[64][17]; extern RAM_ALIGN const UWord16 ari_spec_freq[64][17]; extern RAM_ALIGN const UWord16 ari_spec_bits[64][17]; -extern RAM_ALIGN const Word32 tnsAcfWindow_lc3plus[MAXLAG]; +extern RAM_ALIGN const Word32 tnsAcfWindow[MAXLAG]; extern RAM_ALIGN const Word16 ac_tns_order_bits[2][MAXLAG]; extern RAM_ALIGN const Word16 ac_tns_order_freq[2][MAXLAG]; extern RAM_ALIGN const Word16 ac_tns_order_cumfreq[2][MAXLAG]; @@ -162,6 +202,10 @@ extern RAM_ALIGN const Word16 *const lpc_warp_dee_emphasis_e[NUM_SAMP_FREQ]; extern RAM_ALIGN const Word16 *const lpc_lin_pre_emphasis_7_5ms[NUM_SAMP_FREQ]; extern RAM_ALIGN const Word16 *const lpc_lin_pre_emphasis_e_7_5ms[NUM_SAMP_FREQ]; +#ifdef FIX_PLC_CONFORM_ISSUES +extern RAM_ALIGN const Word16* const lpc_lin_pre_emphasis_1_25ms[NUM_SAMP_FREQ]; +extern RAM_ALIGN const Word16* const lpc_lin_pre_emphasis_e_1_25ms[NUM_SAMP_FREQ]; +#endif extern RAM_ALIGN const Word16 bands_nrg_scale[32]; @@ -227,6 +271,10 @@ extern RAM_ALIGN const Word32 inv_odft_twiddle_60_re[M]; extern RAM_ALIGN const Word32 inv_odft_twiddle_60_im[M]; extern RAM_ALIGN const Word32 inv_odft_twiddle_40_re[M]; extern RAM_ALIGN const Word32 inv_odft_twiddle_40_im[M]; +#ifdef FIX_PLC_CONFORM_ISSUES +extern RAM_ALIGN const Word32 inv_odft_twiddle_30_re[M]; +extern RAM_ALIGN const Word32 inv_odft_twiddle_30_im[M]; +#endif extern RAM_ALIGN const Word32 inv_odft_twiddle_20_re[M]; extern RAM_ALIGN const Word32 inv_odft_twiddle_20_im[M]; @@ -280,8 +328,39 @@ extern RAM_ALIGN const Word16 sns_gainLSBbits[4]; extern RAM_ALIGN const Word16 sns_Kval[4][2]; extern RAM_ALIGN const UWord32 sns_MPVQ_Sz[4][2]; +#ifdef CR9_C_ADD_1p25MS_LRSNS +extern RAM_ALIGN const Word16 st1SCF0_7_base5_32x8_Q11[256 * 2]; +extern RAM_ALIGN const Word16 st1SCF8_15_base5_32x8_Q11[256 * 2]; +#else extern RAM_ALIGN const Word16 st1SCF0_7_base5_32x8_Q11[256]; extern RAM_ALIGN const Word16 st1SCF8_15_base5_32x8_Q11[256]; +#endif + +#ifdef CR9_C_ADD_1p25MS_LRSNS +extern RAM_ALIGN const Word16 lrsns_ltp_bits_fx[8]; +extern RAM_ALIGN const Word16 *const lrsns_vq_gainsQ12_fx[SNSLR_MAX_PVQ_SEARCH_CAND]; +extern RAM_ALIGN const Word16 lrsns_vq_gain_lvls_fx[SNSLR_MAX_PVQ_SEARCH_CAND]; + +extern RAM_ALIGN const Word16 lrsns_cbA_fx[2 * 16]; + +/*LRSNS tables to construct st1B from legacy st1(LF,HF) Q11 tables */ +extern RAM_ALIGN const Word16 lrsns_st1B_merged170orderSortedSegmCnt_fx[4]; +extern RAM_ALIGN const Word16 lrsns_st1B_merged170orderSortedSegmCum_fx[5]; +extern RAM_ALIGN const Word16 lrsns_st1B_merged170orderSort12bitIdx_fx[170]; +extern RAM_ALIGN const Word32 lrsns_st1B_enBy2TabW32_fx[2 * 32]; + +/*LRSNS tables to construct st1C from Word8in Q7 and a Q4 scalefactor */ +#ifdef LRSNS_CBC_NO_LTPF_DEPENDENCY +extern RAM_ALIGN const Word16 * lrsns_st1CTrainedMapMeans_fx[2]; +#else +extern RAM_ALIGN const Word16 * lrsns_st1CTrainedMapMeans_fx[3]; +#endif +extern RAM_ALIGN const Word16 lrsns_st1C_Both_EnBy2Tab_fx[170]; +extern RAM_ALIGN const Word16 lrsns_st1C_Both_scaleQ4_7p4bits_fx[2]; +extern RAM_ALIGN const Word16 lrsns_st1C_Both_inv_scaleQ15_7p4bits_fx[2]; +extern RAM_ALIGN const Word8 lrsns_st1C_Both_Word8_fx[170 * 16]; + +#endif #ifdef ENABLE_HR_MODE extern RAM_ALIGN const Word32 st1SCF0_7_base5_32x8_Q27[256]; @@ -296,9 +375,27 @@ extern RAM_ALIGN const Word16 tabledKMAX[16 + 1]; extern RAM_ALIGN const UWord32 *const MPVQ_offs_ptr[16 + 1]; extern RAM_ALIGN const Word16 isqrt_Q16tab[1 + SQRT_EN_MAX_FX]; + +#ifdef CR9_C_ADD_1p25MS_LRSNS +extern RAM_ALIGN const Word16 isqrt_Q15tab[1 + 6]; +extern RAM_ALIGN const Word32 isqrt_Q31tab[1 + SQRT_EN_MAX_FX]; +#else #ifdef ENABLE_HR_MODE extern RAM_ALIGN const Word32 isqrt_Q31tab[1 + SQRT_EN_MAX_FX]; #endif +#endif + +#ifdef CR9_C_ADD_1p25MS_LRSNS +extern RAM_ALIGN const Word16 lrsns_signs_fix_fx[SNSLR_N_FIXENV]; +extern RAM_ALIGN const Word16 *lrsns_fix_env_fx[SNSLR_N_FIXENV]; + +extern RAM_ALIGN const Word16 lrsns_fixenv_enQ0[SNSLR_N_FIXENV * SNSLR_N_FIXENV_SHIFTS]; +extern RAM_ALIGN const Word16 lrsns_fixenv_enNormQ19[SNSLR_N_FIXENV * SNSLR_N_FIXENV_SHIFTS]; +extern RAM_ALIGN const Word32 L_lrsns_fixenv_enNormQ35[SNSLR_N_FIXENV * SNSLR_N_FIXENV_SHIFTS]; + +extern RAM_ALIGN const Word16 lrsns_norm_factorQ_L[N_SCF_SEARCH_SHAPES_ST2_LR]; +extern RAM_ALIGN const Word16 lrsns_y_up_bits[N_SCF_SEARCH_SHAPES_ST2_LR]; +#endif extern RAM_ALIGN const Word16 adjust_global_gain_tables[5][NUM_SAMP_FREQ]; diff --git a/lib_lc3plus/cutoff_bandwidth.c b/lib_lc3plus/cutoff_bandwidth.c index e00aa7a22..5225cd0e8 100644 --- a/lib_lc3plus/cutoff_bandwidth.c +++ b/lib_lc3plus/cutoff_bandwidth.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,11 +7,13 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "functions.h" void process_cutoff_bandwidth(Word32 d_fx[], Word16 len, Word16 bw_bin) { - Word32 i = 0; + Counter i = 0; if (len > bw_bin){ /* roll off */ for (i = -1; i < 3; i++) { diff --git a/lib_lc3plus/dct2_fx.c b/lib_lc3plus/dct2_fx.c index ec7f09c23..6d428cdc5 100644 --- a/lib_lc3plus/dct2_fx.c +++ b/lib_lc3plus/dct2_fx.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,8 +7,16 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "functions.h" +#ifdef CR9_C_ADD_1p25MS_LRSNS +#ifndef USE_LC3_OPERATORS +#include "enh40.h" +#endif +#endif + void idct16_fx(const Word16 *in, Word16 *out) { Dyn_Mem_Deluxe_In( @@ -463,3 +471,184 @@ void idct32_32_fx(const Word32 *in, Word32 *out) Dyn_Mem_Deluxe_Out(); } + +#ifdef CR9_C_ADD_1p25MS_LRSNS +void dct16_W32int_fx(const Word16 *in, + Word16 *out) /* for now same Q as input . later potetially reduce Q for output */ +{ + + +#define Mpy_32_16op(Lx,y) Mpy_32_16_lc3plus(Lx, y ) /* two-three cycle count as in existing STL */ +#define Mpy_32_16_0op(Lx,y) Mpy_32_16_0_0(Lx,y ) /* no rounding , STL shift cost still there */ + + + Dyn_Mem_Deluxe_In( + /* Counter i; */ + Word32 L_a0, L_a1, L_a2, L_a3, L_a4, L_a5, L_a6, L_a7, L_a8, L_a9, L_a10, L_a11, L_a12, L_a13, L_a14, L_a15; + Word32 L_b0, L_b1, L_b2, L_b3, L_b4, L_b5, L_b6, L_b7, L_b8, L_b9, L_b10, L_b11, L_b12, L_b13, L_b14, L_b15; + ); +#ifdef WMOPS + push_wmops("dct16_W32int_fx"); +#endif + +#define INMARGIN 0 +#if INMARGIN > 0 +#define INSCALE (1<<(15-INMARGIN) ) +#endif + +#if INMARGIN == 0 + L_a0 = L_deposit_h(add(in[15], in[0])); /* Word16 Q11 deposited 16 levels up, becomes Q27, NB add can still potentially saturate ! */ + L_a1 = L_deposit_h(add(in[14], in[1])); + L_a2 = L_deposit_h(add(in[13], in[2])); + L_a3 = L_deposit_h(add(in[12], in[3])); + L_a4 = L_deposit_h(add(in[11], in[4])); + L_a5 = L_deposit_h(add(in[10], in[5])); + L_a6 = L_deposit_h(add(in[9], in[6])); + L_a7 = L_deposit_h(add(in[8], in[7])); + + L_a10 = L_deposit_h(sub(in[5], in[10])); + L_a11 = L_deposit_h(sub(in[4], in[11])); + L_a12 = L_deposit_h(sub(in[3], in[12])); + L_a13 = L_deposit_h(sub(in[2], in[13])); +#else + /* create higher internal margin */ + /* Q11 deposited 16 levels up, becomes lower than Q27, internal L_aX, L_bx signals becomes Q26, or lower */ + L_a0 = L_mult0(add(in[15], in[0]), INSCALE); + L_a1 = L_mult0(add(in[14], in[1]), INSCALE); + L_a2 = L_mult0(add(in[13], in[2]), INSCALE); + L_a3 = L_mult0(add(in[12], in[3]), INSCALE); + L_a4 = L_mult0(add(in[11], in[4]), INSCALE); + L_a5 = L_mult0(add(in[10], in[5]), INSCALE); + L_a6 = L_mult0(add(in[9], in[6]), INSCALE); + L_a7 = L_mult0(add(in[8], in[7]), INSCALE); + + L_a10 = L_mult0(sub(in[5], in[10]), INSCALE); + L_a11 = L_mult0(sub(in[4], in[11]), INSCALE); + L_a12 = L_mult0(sub(in[3], in[12]), INSCALE); + L_a13 = L_mult0(sub(in[2], in[13]), INSCALE); +#endif + + L_b0 = L_add(L_a7, L_a0); + L_b1 = L_add(L_a6, L_a1); + L_b2 = L_add(L_a5, L_a2); + L_b3 = L_add(L_a4, L_a3); + L_b4 = L_sub(L_a3, L_a4); + L_b5 = L_sub(L_a2, L_a5); + L_b6 = L_sub(L_a1, L_a6); + L_b7 = L_sub(L_a0, L_a7); + +#if INMARGIN == 0 + L_b8 = L_deposit_h(sub(in[7], in[8])); + L_b9 = L_deposit_h(sub(in[6], in[9])); +#else + L_b8 = L_mult0(sub(in[7], in[8]), INSCALE); + L_b9 = L_mult0(sub(in[6], in[9]), INSCALE); +#endif + L_b10 = L_add(Mpy_32_16op(L_a10, -23170), Mpy_32_16op(L_a13, 23170));/* -Cπ/4 Cπ/4 */ + //L_b10 = L_add(L_b10, L_b10); /* scale up due to previous use of L_Mpy_32_16_0op() */ + + L_b11 = L_add(Mpy_32_16op(L_a11, -23170), Mpy_32_16op(L_a12, 23170)); /* -Cπ/4 Cπ/4 */ + //L_b11 = L_add(L_b11, L_b11);/* scale up due to previous use of L_Mpy_32_16_0op() */ + + L_b12 = L_add(Mpy_32_16op(L_a12, 23170), Mpy_32_16op(L_a11, 23170)); /* Cπ/4 Cπ/4 */ + //L_b12 = L_add(L_b12, L_b12);/* scale up due to previous use of L_Mpy_32_16_0op() */ + + L_b13 = L_add(Mpy_32_16op(L_a13, 23170), Mpy_32_16op(L_a10, 23170)); /* Cπ/4 Cπ/4 */ + //L_b13 = L_add(L_b13, L_b13);/* scale up due to previous use of L_Mpy_32_16_0op() */ + +#if INMARGIN == 0 + L_b14 = L_deposit_h(sub(in[1], in[14])); + L_b15 = L_deposit_h(sub(in[0], in[15])); +#else + L_b14 = L_mult0(sub(in[1], in[14]), INSCALE); + L_b15 = L_mult0(sub(in[0], in[15]), INSCALE); +#endif + + /* all inputs processed */ + L_a0 = L_add_sat(L_b3, L_b0); /*saturation was required in dct32_fx()*/ + L_a1 = L_add(L_b2, L_b1); + L_a2 = L_sub(L_b1, L_b2); + L_a3 = L_sub_sat(L_b0, L_b3); /*saturation was required in dct32_fx()*/ + + L_a4 = L_add(L_b4, 0L); + + L_a5 = L_add(Mpy_32_16op(L_b5, -23170), Mpy_32_16op(L_b6, 23170)); /* -Cπ/4 Cπ/4 */ + //L_a5 = L_add(L_a5, L_a5);/* scale up due to previous use of L_Mpy_32_16_0op() */ + L_a6 = L_add(Mpy_32_16op(L_b6, 23170), Mpy_32_16op(L_b5, 23170)); /* Cπ/4 Cπ/4 */ + //L_a6 = L_add(L_a6, L_a6);/* scale up due to previous use of L_Mpy_32_16_0op() */ + + L_a7 = L_add(L_b7, 0L); + L_a8 = L_add(L_b11, L_b8); + L_a9 = L_add(L_b10, L_b9); + + L_a10 = L_sub(L_b9, L_b10); + L_a11 = L_sub(L_b8, L_b11); + + L_a12 = L_sub(L_b15, L_b12); + L_a13 = L_sub(L_b14, L_b13); + + L_a14 = L_add(L_b13, L_b14); + L_a15 = L_add(L_b12, L_b15); + + /* upscaling done by constant doubling */ + out[0] = round_fx(L_add(Mpy_32_16_0op(L_a0, 8192 * 2), Mpy_32_16_0op(L_a1, 8192 * 2))); move16(); /* Cπ/4/√8 Cπ/4/√8 */ + out[8] = round_fx(L_add(Mpy_32_16_0op(L_a1, -8192 * 2), Mpy_32_16_0op(L_a0, 8192 * 2))); move16(); /* -Cπ/4/√8 Cπ/4/√8 */ + out[4] = round_fx(L_add(Mpy_32_16_0op(L_a2, 4433 * 2), Mpy_32_16_0op(L_a3, 10703 * 2))); move16(); /* Sπ/8/√8 Cπ/8/√8 */ + out[12] = round_fx(L_add(Mpy_32_16_0op(L_a3, 4433 * 2), Mpy_32_16_0op(L_a2, -10703 * 2))); move16(); /* C3π/8/√8 -S3π/8/√8 */ + + L_b4 = L_add(L_a5, L_a4); + L_b5 = L_sub_sat(L_a4, L_a5); /*saturation was required in dct32_fx()*/ + L_b6 = L_sub_sat(L_a7, L_a6); /*saturation was required in dct32_fx()*/ + L_b7 = L_add(L_a6, L_a7); + L_b8 = L_add(L_a8, 0L); ; + + L_b9 = L_add(Mpy_32_16op(L_a9, -30274), Mpy_32_16op(L_a14, 12540)); /* -Cπ/8 Sπ/8 */ + L_b10 = L_add(Mpy_32_16op(L_a10, -12540), Mpy_32_16op(L_a13, -30274)); /* -Sπ/8 -Cπ/8 */ + L_b11 = L_add(L_a11, 0L); + L_b12 = L_add(L_a12, 0L); + + L_b13 = L_add(Mpy_32_16op(L_a13, 12540), Mpy_32_16op(L_a10, -30274)); /* C3π/8 -S3π/8 */ + L_b14 = L_add(Mpy_32_16op(L_a14, 30274), Mpy_32_16op(L_a9, 12540)); /* S3π/8 C3π/8 */ + L_b15 = L_add(L_a15, 0L); + + + /* upscaling done by constant doubling */ + out[2] = round_fx(L_add(Mpy_32_16_0op(L_b4, 2260 * 2), Mpy_32_16_0op(L_b7, 11363 * 2))); move16(); /* Sπ/16/√8 Cπ/16/√8 */ + out[10] = round_fx(L_add(Mpy_32_16_0op(L_b5, 9633 * 2), Mpy_32_16_0op(L_b6, 6436 * 2))); move16(); /* S5π/16/√8 C5π/16/√8 */ + out[6] = round_fx(L_add(Mpy_32_16_0op(L_b6, 9633 * 2), Mpy_32_16_0op(L_b5, -6436 * 2))); move16(); /* C3π/16/√8 -S3π/16/√8 */ + out[14] = round_fx(L_add(Mpy_32_16_0op(L_b7, 2260 * 2), Mpy_32_16_0op(L_b4, -11363 * 2))); move16(); /* C7π/16/√8 -S7π/16/√8 */ + + L_a8 = L_add_sat(L_b9, L_b8); /*saturation was required in dct32_fx()*/ + L_a9 = L_sub_sat(L_b8, L_b9); + L_a10 = L_sub_sat(L_b11, L_b10); + L_a11 = L_add_sat(L_b10, L_b11); + L_a12 = L_add_sat(L_b13, L_b12); + L_a13 = L_sub_sat(L_b12, L_b13); + L_a14 = L_sub_sat(L_b15, L_b14); + L_a15 = L_add_sat(L_b14, L_b15); + + /* upscaling done by constant doubling */ + out[1] = round_fx(L_add(Mpy_32_16_0op(L_a8, 1136 * 2), Mpy_32_16_0op(L_a15, 11529 * 2))); move16(); /* Sπ/32/√8 Cπ/32/√8 */ + out[9] = round_fx(L_add(Mpy_32_16_0op(L_a9, 8956 * 2), Mpy_32_16_0op(L_a14, 7350 * 2))); move16(); /* S9π/32/√8 C9π/32/√8 */ + out[5] = round_fx(L_add(Mpy_32_16_0op(L_a10, 5461 * 2), Mpy_32_16_0op(L_a13, 10217 * 2))); move16(); /* S5π/32/√8 C5π/32/√8 */ + out[13] = round_fx(L_add(Mpy_32_16_0op(L_a11, 11086 * 2), Mpy_32_16_0op(L_a12, 3363 * 2))); move16(); /* S13π/32/√8 C13π/32/√8 */ + out[3] = round_fx(L_add(Mpy_32_16_0op(L_a12, 11086 * 2), Mpy_32_16_0op(L_a11, -3363 * 2))); move16(); /* C3π/32/√8 -S3π/32/√8 */ + out[11] = round_fx(L_add(Mpy_32_16_0op(L_a13, 5461 * 2), Mpy_32_16_0op(L_a10, -10217 * 2))); move16();/* C11π/32/√8 -S11π/32/√8 */ + out[7] = round_fx(L_add(Mpy_32_16_0op(L_a14, 8956 * 2), Mpy_32_16_0op(L_a9, -7350 * 2))); move16(); /* C7π/32/√8 -S7π/32/√8 */ + out[15] = round_fx(L_add(Mpy_32_16_0op(L_a15, 1136 * 2), Mpy_32_16_0op(L_a8, -11529 * 2))); move16(); /* C15π/32/√8 -S15/32/√8 */ + + + +#ifdef Mpy_32_16op +#undef Mpy_32_16op +#endif + +#ifdef Mpy_32_16_0op +#undef Mpy_32_16_0op +#endif +#ifdef WMOPS + pop_wmops(); +#endif + Dyn_Mem_Deluxe_Out(); +} +#endif diff --git a/lib_lc3plus/dct4_fx.c b/lib_lc3plus/dct4_fx.c index 0e5957c86..e5f1ed189 100644 --- a/lib_lc3plus/dct4_fx.c +++ b/lib_lc3plus/dct4_fx.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,6 +7,8 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "functions.h" #include "rom_basop_util_lc3plus.h" @@ -33,7 +35,7 @@ void dct_IV(Word32 *pDat, /* i/o: pointer to data buffer */ Word32 accu3; Word32 accu4; - Word32 i; + Counter i; #ifdef ENABLE_HR_MODE const PWord32 *twiddle; @@ -98,7 +100,7 @@ void dct_IV(Word32 *pDat, /* i/o: pointer to data buffer */ pDat_0 = &pDat[0]; pDat_1 = &pDat[L - 2]; - FOR (i = 0; i < M2; i += 2) + FOR (i = 0; i < M_var; i += 2) { #ifdef ENABLE_HR_MODE if (hrmode) { @@ -113,10 +115,11 @@ void dct_IV(Word32 *pDat, /* i/o: pointer to data buffer */ cplxMpy32_32_16_2(accu3, accu4, pDat_1[0], pDat_0[1], twiddle[i + 1].v.re, twiddle[i + 1].v.im); #endif - pDat_0[0] = accu2; move32(); - pDat_0[1] = accu1; move32(); + /* The order of writing the coefficients is not important unless the length is odd, as then the two pointers pDat_0 and pDat_1 would overlap. The order here should be correct as such that the incorrectly calculated coefficient is overwritten with the correctly calculated coefficient. This is happens e.g. for the FFT15, 30 Samples, 1.25 ms @ 24 kHz */ pDat_1[0] = accu4; move32(); pDat_1[1] = L_negate(accu3); move32(); + pDat_0[0] = accu2; move32(); + pDat_0[1] = accu1; move32(); pDat_0 = pDat_0 + 2; pDat_1 = pDat_1 - 2; @@ -126,7 +129,7 @@ void dct_IV(Word32 *pDat, /* i/o: pointer to data buffer */ if (hrmode) { - scale = s_max(getScaleFactor32_lc3plus(pDat, L), 0); move16(); + scale = s_max(getScaleFactor32(pDat, L), 0); move16(); FOR (i = 0; i < L; i++) { @@ -137,7 +140,7 @@ void dct_IV(Word32 *pDat, /* i/o: pointer to data buffer */ } #endif - BASOP_cfft_lc3plus(&pDat[0], &pDat[1], M_var, 2, pDat_e, workBuffer); + BASOP_cfft(&pDat[0], &pDat[1], M_var, 2, pDat_e, workBuffer); pDat_0 = &pDat[0]; pDat_1 = &pDat[L - 2]; diff --git a/lib_lc3plus/dec_entropy.c b/lib_lc3plus/dec_entropy.c index dddbc4851..a1773f92b 100644 --- a/lib_lc3plus/dec_entropy.c +++ b/lib_lc3plus/dec_entropy.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,9 +7,42 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "functions.h" -static Word16 read_indice(UWord8 *ptr, Word16 *bp, Word16 *mask, Word16 numbits); + + +#ifdef CR9_C_ADD_1p25MS_LRSNS + +static void readSNSData_fx(UWord8* ptr, + Word16* bfiPtr, + Word16* mask_side, + Word16* bp_side, + Word16* ltpf_idx_2_lrsns, + Word32* L_scf_idx, + LC3PLUS_FrameDuration frame_dms); + +#endif + +static Word16 read_indice(UWord8 *ptr, Word16 *bp, Word16 *mask, Word16 numbits) +{ + Dyn_Mem_Deluxe_In( + Word16 indice, bit; + Counter i; + ); + + indice = read_bit(ptr, bp, mask); + + FOR (i = 1; i < numbits; i++) + { + bit = read_bit(ptr, bp, mask); + indice = add(indice, lshl_pos(bit, i)); + } + + Dyn_Mem_Deluxe_Out(); + return indice; +} static Word16 ac_dec_split_st2VQ_CW( /* local BER flag */ const Word32 L_cwRx, /* max 25 bits */ @@ -20,15 +53,38 @@ void processDecoderEntropy_fx(UWord8 *bytes, Word16 *bp_side, Word16 *mask_side, Word16 L_spec, Word16 fs_idx, Word16 BW_cutoff_bits, Word16 *tns_numfilters, Word16 *lsbMode, Word16 *lastnz, Word16 *bfi, Word16 *tns_order, Word16 *fac_ns_idx, Word16 *gg_idx, Word16 *BW_cutoff_idx, Word16 *ltpf_idx, Word32 *L_scf_idx, - Word16 frame_dms) + LC3PLUS_FrameDuration frame_dms +#ifdef CR9_C_ADD_1p25MS + , Word16 rx_status[2], Word16* mem_continuation +#ifdef NEW_SIGNALLING_SCHEME_1p25 + ,Word16 *ltpfinfo_frame_cntr_fx /* set here , but also increased outside by bfi for the channel */ +#endif +#endif + + ) { +#ifdef CR9_C_ADD_1p25MS_LRSNS Dyn_Mem_Deluxe_In( - Word16 L, submodeLSB; - Word32 tmp32, tmp32lim; - Word16 gain_e, gain, submodeMSB, BER_detect; - Word32 n; - UWord8 *ptr; + Word16 L; + Word32 tmp32; + Word16 gain_e, gain; + Counter n; + UWord8 * ptr; + Word16 ltpf_idx_2_lrsns[3]; + Word16 bfiSNS; ); +#else + Dyn_Mem_Deluxe_In( + Word16 L, submodeLSB; + Word32 tmp32, tmp32lim; + Word16 gain_e, gain, submodeMSB, BER_detect; + Counter n; + UWord8 * ptr; ); +#endif + +#if !defined(LRSNS_PC_SIGNAL_FIX) && defined(CR9_C_ADD_1p25MS_LRSNS) + UNUSED(bfiSNS); +#endif ptr = bytes; *bp_side = shr_pos(sub(nbbits, 1), 3); @@ -53,17 +109,28 @@ void processDecoderEntropy_fx(UWord8 *bytes, Word16 *bp_side, Word16 *mask_side, } /* Number of TNS filters */ - IF (sub(*BW_cutoff_idx, 3) >= 0 && frame_dms >= 50) - { - *tns_numfilters = 2; move16(); - } - ELSE +#ifdef CR9_C_ADD_1p25MS + IF (frame_dms == LC3PLUS_FRAME_DURATION_1p25MS) { + *tns_numfilters = 0; + } ELSE +#ifdef CR9_C_ADD_1p25MS_LRSNS { - *tns_numfilters = 1; move16(); +#endif +#endif + IF (sub(*BW_cutoff_idx, 3) >= 0 && frame_dms >= LC3PLUS_FRAME_DURATION_5MS) + { + *tns_numfilters = 2; move16(); + } + ELSE + { + *tns_numfilters = 1; move16(); + } +#ifdef CR9_C_ADD_1p25MS_LRSNS } +#endif /* Decode number of ntuples */ - L = sub(14, norm_s(negate(L_spec))); + L = getLastNzBits_fx(L_spec); n = read_indice(ptr, bp_side, mask_side, L); n = add(n, 1); *lastnz = shl_pos(n, 1); @@ -81,7 +148,7 @@ void processDecoderEntropy_fx(UWord8 *bytes, Word16 *bp_side, Word16 *mask_side, *gg_idx = read_indice(ptr, bp_side, mask_side, 8); move16(); tmp32 = L_shl_pos(L_mult0(*gg_idx, 0x797D), 7); /* 6Q25; 0x797D -> log2(10)/28 (Q18) */ gain_e = add(extract_l(L_shr_pos(tmp32, 25)), 1); /* get exponent */ - gain = round_fx(BASOP_Util_InvLog2_lc3plus(L_or(tmp32, 0xFE000000))); + gain = round_fx(BASOP_Util_InvLog2(L_or(tmp32, 0xFE000000))); assert(gain >= 0); /* JSv, check if shr_pos(gain,1) is more appropriate) */ gain = shr_r(gain, 1); gain_e = add(gain_e, 1); @@ -94,13 +161,58 @@ void processDecoderEntropy_fx(UWord8 *bytes, Word16 *bp_side, Word16 *mask_side, } /* LTPF on/off */ -#ifdef ENABLE_HR_MODE - ltpf_idx[0] = read_bit(ptr, bp_side, mask_side); move16(); +#ifdef NEW_SIGNALLING_SCHEME_1p25 + IF(sub(frame_dms, LC3PLUS_FRAME_DURATION_1p25MS) != 0) + { + ltpf_idx[0] = read_bit(ptr, bp_side, mask_side); move16(); + } + ELSE + { /* read one of {2, 6, 7} bits into ltp/ltpf/lag variable ltpf_idx[ 0 ... 2] */ + readLtpData_fx(ptr, bfi, mask_side, bp_side, ltpf_idx, rx_status, ltpfinfo_frame_cntr_fx, mem_continuation); + } #else ltpf_idx[0] = read_indice(ptr, bp_side, mask_side, 1); move16(); #endif - /* Decode SNS VQ parameters - 1st stage (10 bits) */ + +/* Decode SNS VQ parameters - 1st stage (10 bits) */ +#ifdef CR9_C_ADD_1p25MS_LRSNS + ltpf_idx_2_lrsns[0] = ltpf_idx[0]; move16(); + ltpf_idx_2_lrsns[1] = ltpf_idx[1]; move16(); +#ifdef LRSNS_PC_SIGNAL_FIX + bfiSNS = 0; move16(); /* Local BFI flag for Errors SNS bit area */ + + readSNSData_fx(ptr, &bfiSNS, mask_side, bp_side, ltpf_idx_2_lrsns, L_scf_idx, frame_dms); + IF ( bfiSNS != 0 ) + { /* corrupt SNSbits triggers PLC through global PLC flag *bfi==1. + *bfi==2 and bfiSNS == 0 maintains bfi==2 for PC(Partial Concealmnet) + */ + *bfi = 1; + Dyn_Mem_Deluxe_Out(); + return; + } + IF ( sub(frame_dms, LC3PLUS_FRAME_DURATION_1p25MS ) == 0 ) + { /* for 1.25ms and previously detected bit errors --> handle frame as a completely corrupt bad frame */ + IF( sub(*bfi, 2) == 0) + { + *bfi = 1; + Dyn_Mem_Deluxe_Out(); + return; + } + } + +#else + readSNSData_fx(ptr, bfi, mask_side, bp_side, ltpf_idx_2_lrsns, L_scf_idx, frame_dms); + + IF(*bfi != 0) + { + *bfi = 1; + Dyn_Mem_Deluxe_Out(); + return; + } +#endif +#else + #ifdef ENABLE_HR_MODE L = read_indice(ptr, bp_side, mask_side, 5 + 5); L_scf_idx[0] = L_deposit_l(s_and(L, 0x1F)); /* stage1 LF 5 bits */ @@ -145,43 +257,114 @@ void processDecoderEntropy_fx(UWord8 *bytes, Word16 *bp_side, Word16 *mask_side, ASSERT(submodeMSB == 1); /* outlier mode shape index total 23.8536 + 19.5637 (19.5637 < (log2(2.^24 -2.^23.8537)) bits MPVQ * codeword */ - tmp32 = L_deposit_l(read_indice(ptr, bp_side, mask_side, 12)); - tmp32 = L_or(tmp32, L_shl_pos(read_indice(ptr, bp_side, mask_side, 12), 12)); - L_scf_idx[5] = tmp32; move32(); /*shape outl_near or outl_far */ - submodeLSB = 0; move16(); - BER_detect = 0; move16(); - tmp32lim = L_add(sns_MPVQ_Sz[2][0], L_shl_pos(sns_MPVQ_Sz[3][0], 1)); - IF (L_sub(tmp32, tmp32lim) >= 0) + + tmp32 = L_deposit_l( read_indice( ptr, bp_side, mask_side, 12 ) ); + tmp32 = L_or( tmp32, L_shl_pos( read_indice( ptr, bp_side, mask_side, 12 ), 12 ) ); + + L_scf_idx[5] = tmp32; + move32(); /*shape outl_near or outl_far */ + submodeLSB = 0; + move16(); + BER_detect = 0; + move16(); + tmp32lim = L_add( sns_MPVQ_Sz[2][0], L_shl_pos( sns_MPVQ_Sz[3][0], 1 ) ); + IF( L_sub( tmp32, tmp32lim ) >= 0 ) { - BER_detect = 1; move16(); + BER_detect = 1; + move16(); } ELSE { - tmp32 = L_sub(tmp32, sns_MPVQ_Sz[2][0]); /* a potential high index is computed */ - IF (tmp32 >= 0) + tmp32 = L_sub( tmp32, sns_MPVQ_Sz[2][0] ); /* a potential high index is computed */ + IF( tmp32 >= 0 ) { - submodeLSB = 1; move16(); - ASSERT(tmp32 >= 0 && tmp32 < (Word32)(2 * sns_MPVQ_Sz[3][0])); - L_scf_idx[3] = L_add(L_shl_pos(L_scf_idx[3], 1), L_and(tmp32, 0x1)); /* add LSB_gain bit to gain MSBs */ - L_scf_idx[5] = L_shr_pos(tmp32, 1); /* MPVQ index with offset and gainLSB removed */ - L_scf_idx[6] = -2L; move32(); + submodeLSB = 1; + move16(); + ASSERT( tmp32 >= 0 && tmp32 < (Word32) ( 2 * sns_MPVQ_Sz[3][0] ) ); + L_scf_idx[3] = L_add( L_shl_pos( L_scf_idx[3], 1 ), L_and( tmp32, 0x1 ) ); /* add LSB_gain bit to gain MSBs */ + L_scf_idx[5] = L_shr_pos( tmp32, 1 ); /* MPVQ index with offset and gainLSB removed */ + L_scf_idx[6] = -2L; + move32(); } ELSE { - L_scf_idx[6] = -1L; move32(); + L_scf_idx[6] = -1L; + move32(); } } } L_scf_idx[2] = - L_add(L_scf_idx[2], L_deposit_l(submodeLSB)); /* decoder internal signal shape_j = submode 0..3 to VQ */ + L_add( L_scf_idx[2], L_deposit_l( submodeLSB ) ); /* decoder internal signal shape_j = submode 0..3 to VQ */ - IF (BER_detect > 0) + IF( BER_detect > 0 ) { - *bfi = 1; move16(); + *bfi = 1; move16(); Dyn_Mem_Deluxe_Out(); return; } +#endif + +#ifdef CR9_C_ADD_1p25MS +#ifdef NEW_SIGNALLING_SCHEME_1p25 + IF( sub(frame_dms, LC3PLUS_FRAME_DURATION_1p25MS) != 0 ) + { + ltpf_idx[1] = 0; move16(); + ltpf_idx[2] = 0; move16(); + + test(); + IF( ltpf_idx[0] != 0 ) + { + L = read_indice(ptr, bp_side, mask_side, 1 + 9); + ltpf_idx[1] = s_and(L, 1); move16(); + ltpf_idx[2] = shr_pos(L, 1); move16(); + } + } +#else + IF (ltpf_idx[0] == 1) { + if (frame_dms == LC3PLUS_FRAME_DURATION_1p25MS) { + Word32 rx_current_status = read_bit(ptr, bp_side, mask_side); + IF (rx_current_status == rx_status[0]) { + IF (rx_current_status == 0) { + rx_status[0] = 1; move16(); + rx_status[1] = read_indice(ptr, bp_side, mask_side, 5); move16(); + if (*mem_continuation == 0) + { + *mem_continuation = 1; + } + } ELSE { + /* rx current status 1 */ + rx_status[0] = 0; move16(); + ltpf_idx[1] = shr_pos (rx_status[1],4); + ltpf_idx[2] = read_indice(ptr, bp_side, mask_side, 5); + ltpf_idx[2] = add(ltpf_idx[2], shl_pos(s_and(rx_status[1],15), 5)); + rx_status[1] = 0; move16(); + *mem_continuation = 0; + } + } ELSE { /* frame loss condtion */ + rx_status[0] = 0; +#ifdef FIX_PLC_CONFORM_ISSUES + rx_status[1] = read_indice( ptr, bp_side, mask_side, 5 ); +#else + rx_status[1] = 0; +#endif + } + } ELSE { + L = read_indice(ptr, bp_side, mask_side, 1+9); move16(); + ltpf_idx[1] = s_and(L, 1); move16(); + ltpf_idx[2] = shr_pos(L, 1); move16(); + } + } + ELSE + { + ltpf_idx[1] = 0; move16(); + ltpf_idx[2] = 0; move16(); + rx_status[0] = 0; + rx_status[1] = 0; + *mem_continuation = 0; + } +#endif +#else /* CR9_C_ADD_1p25MS */ /* LTPF data */ IF (ltpf_idx[0] != 0) { @@ -197,191 +380,619 @@ void processDecoderEntropy_fx(UWord8 *bytes, Word16 *bp_side, Word16 *mask_side, } ELSE { - ltpf_idx[1] = 0; move16(); - ltpf_idx[2] = 0; move16(); + ltpf_idx[1] = 0; move16(); + ltpf_idx[2] = 0; move16(); } +#endif /* new signalling */ /* Decode noise-fac */ - *fac_ns_idx = read_indice(ptr, bp_side, mask_side, 3); move16(); + *fac_ns_idx = read_indice( ptr, bp_side, mask_side, 3 ); move16(); Dyn_Mem_Deluxe_Out(); } + #ifdef ENABLE_PADDING -int paddingDec_fx(UWord8 *bytes, Word16 nbbits, Word16 L_spec, Word16 BW_cutoff_bits, Word16 ep_enabled, - Word16 *total_padding, Word16 *np_zero) +Word32 paddingDec_fx( UWord8* bytes, Word16 nbbits, Word16 L_spec, Word16 BW_cutoff_bits, Word16 ep_enabled, Word16* total_padding, Word16* np_zero ) { Word16 lastnz_threshold; Word16 padding_len_bits, padding_len; Word16 bp_side; - Word16 nbbytes = shr(nbbits,3); + Word16 nbbytes = shr( nbbits, 3 ); - Word16 mask_side; - UWord8 *ptr = bytes; + Word16 mask_side; + UWord8* ptr = bytes; Word16 lastnz; - Word16 nbits = sub(14, norm_s(negate(L_spec))); - if (sub(nbbits, nbits) < 0) + Word16 nbits = getLastNzBits_fx( L_spec ); + if ( sub( nbbits, nbits ) < 0 ) { return 1; } - *np_zero = 0; + *np_zero = 0; *total_padding = 0; - bp_side = shr_pos(sub(nbbits, 1), 3); - mask_side = shl(1, sub(8, sub(nbbits, shl_pos(bp_side, 3)))); + bp_side = shr_pos( sub( nbbits, 1 ), 3 ); + mask_side = shl( 1, sub( 8, sub( nbbits, shl_pos( bp_side, 3 ) ) ) ); test(); - IF (sub(bp_side, 19) < 0 || sub(bp_side, LC3PLUS_MAX_BYTES ) >= 0) { + IF( sub( bp_side, 19 ) < 0 || sub( bp_side, LC3PLUS_MAX_BYTES ) >= 0 ) + { return 1; } ptr = bytes; - IF (BW_cutoff_bits > 0) + IF( BW_cutoff_bits > 0 ) { - read_indice(ptr, &bp_side, &mask_side, BW_cutoff_bits); + read_indice( ptr, &bp_side, &mask_side, BW_cutoff_bits ); move16(); } - lastnz = read_indice(ptr, &bp_side, &mask_side, nbits); + lastnz = read_indice( ptr, &bp_side, &mask_side, nbits ); move16(); - lastnz_threshold = sub(shl(1, nbits), 2); + lastnz_threshold = sub( shl( 1, nbits ), 2 ); - WHILE (lastnz == lastnz_threshold) + WHILE( lastnz == lastnz_threshold ) { - padding_len_bits = sub(sub(12, nbits), BW_cutoff_bits); + padding_len_bits = sub( sub( 12, nbits ), BW_cutoff_bits ); /*Read padding length*/ - padding_len = read_indice(ptr, &bp_side, &mask_side, padding_len_bits); + padding_len = read_indice( ptr, &bp_side, &mask_side, padding_len_bits ); move16(); /* Read 4 reserved bits */ - read_indice(ptr, &bp_side, &mask_side, 4); + read_indice( ptr, &bp_side, &mask_side, 4 ); move16(); - IF (ep_enabled == 0) + IF( ep_enabled == 0 ) { /* Discard padding length bytes */ - bp_side = sub(bp_side, padding_len); - *total_padding = add(add(*total_padding, padding_len), 2); move16(); + bp_side = sub( bp_side, padding_len ); + *total_padding = add( add( *total_padding, padding_len ), 2 ); + move16(); } ELSE { - *total_padding = add(*total_padding, 2); move16(); - *np_zero = add(*np_zero, padding_len); move16(); + *total_padding = add( *total_padding, 2 ); + move16(); + *np_zero = add( *np_zero, padding_len ); + move16(); } - + /* test if we have less than 20 bytes left; if so frame is broken */ - IF (sub(sub(nbbytes,add(*total_padding,*np_zero)),20) < 0) { + IF( sub( sub( nbbytes, add( *total_padding, *np_zero ) ), 20 ) < 0 ) + { return 1; } /* Read bandwidth bits */ - IF (BW_cutoff_bits > 0) + IF( BW_cutoff_bits > 0 ) { - read_indice(ptr, &bp_side, &mask_side, BW_cutoff_bits); + read_indice( ptr, &bp_side, &mask_side, BW_cutoff_bits ); move16(); } - lastnz = read_indice(ptr, &bp_side, &mask_side, nbits); + lastnz = read_indice( ptr, &bp_side, &mask_side, nbits ); move16(); } - IF (ep_enabled != 0) + IF( ep_enabled != 0 ) { - *total_padding = add(*total_padding, *np_zero); move16(); + *total_padding = add( *total_padding, *np_zero ); + move16(); } return 0; } #endif -static __forceinline Word16 read_indice(UWord8 *ptr, Word16 *bp, Word16 *mask, Word16 numbits) -{ - Dyn_Mem_Deluxe_In( - Word16 indice, bit; - Counter i; - ); - - indice = read_bit(ptr, bp, mask); - - FOR (i = 1; i < numbits; i++) - { - bit = read_bit(ptr, bp, mask); - indice = add(indice, lshl_pos(bit, i)); - } - - Dyn_Mem_Deluxe_Out(); - return indice; -} - -static __forceinline Word16 ac_dec_split_st2VQ_CW( /* local BER flag */ - const Word32 L_cwRx, /* max 25 bits */ - const Word32 L_szA, const Word32 L_szB, Word32 *L_cwA, Word32 *L_cwB, - Word16 *submodeLSB) +static Word16 ac_dec_split_st2VQ_CW( /* local BER flag */ + const Word32 L_cwRx, /* max 25 bits */ + const Word32 L_szA, + const Word32 L_szB, + Word32* L_cwA, + Word32* L_cwB, + Word16* submodeLSB ) { /* demultiplex: L_cwRx = L_cwB(21.z bits) * L_szA(3.y bits) + L_cwA(21.x bits)); */ - Word16 start, fin, ind; - Word32 L_tmp, L_max_size; + Word16 start, fin, ind; + Word32 L_tmp, L_max_size; Counter i; - L_max_size = (Word32)UL_Mpy_32_32((UWord32)L_szB, (UWord32)L_szA); /* may be tabled */ + L_max_size = (Word32) UL_Mpy_32_32( (UWord32) L_szB, (UWord32) L_szA ); /* may be tabled */ /* section B ind larger than 13 out of the possible 14 = 0..13 */ - IF (L_sub(L_cwRx, L_max_size) >= 0) + IF( L_sub( L_cwRx, L_max_size ) >= 0 ) { - *L_cwA = L_deposit_l(0); - *L_cwB = L_deposit_l(0); - *submodeLSB = 0; move16(); - return (Word16)1; /* set berFlag and exit */ + *L_cwA = L_deposit_l( 0 ); + *L_cwB = L_deposit_l( 0 ); + *submodeLSB = 0; + move16(); + return (Word16) 1; /* set berFlag and exit */ } /*initial binary split of cw, select top or low half */ - start = 0; move16(); + start = 0; + move16(); - ASSERT((L_szB & 0x1L) == 0); /* this middle split only works if L_szB is even */ - if (L_sub(L_cwRx, L_shr_pos(L_max_size, 1)) >= 0) + ASSERT( ( L_szB & 0x1L ) == 0 ); /* this middle split only works if L_szB is even */ + if ( L_sub( L_cwRx, L_shr_pos( L_max_size, 1 ) ) >= 0 ) { - start = L_shr_pos(L_szB, 1); /* top half start index */ + start = L_shr_pos( L_szB, 1 ); /* top half start index */ } /*linear loop over a low or a high section */ - ind = start; move16(); - L_tmp = L_negate(L_cwRx); /* search from negative side */ + ind = start; + move16(); + L_tmp = L_negate( L_cwRx ); /* search from negative side */ - L_tmp = L_add(L_tmp, (Word32)UL_Mpy_32_32(UL_deposit_l((UWord16)start), (UWord32)L_szA)); + L_tmp = L_add( L_tmp, (Word32) UL_Mpy_32_32( UL_deposit_l( (UWord16) start ), (UWord32) L_szA ) ); /* start is 0 or 7 */ /*non-fractional mult is (int)start * L_szA */ /* a short linear run over ceil(szB/2) = 7 values */ - fin = add(start, shr_pos(L_szB, 1)); - FOR (i = start; i < fin; i++) + fin = add( start, shr_pos( L_szB, 1 ) ); + FOR( i = start; i < fin; i++ ) { - ind = add(ind, 1); - L_tmp = L_add(L_tmp, L_szA); - if (L_tmp > 0) + ind = add( ind, 1 ); + L_tmp = L_add( L_tmp, L_szA ); + if ( L_tmp > 0 ) { - ind = sub(ind, 1); /* passed criteria point, keep index */ + ind = sub( ind, 1 ); /* passed criteria point, keep index */ } } - *L_cwB = L_deposit_l(ind); - *L_cwA = L_sub(L_cwRx, (Word32)UL_Mpy_32_32(UL_deposit_l((UWord16)ind), - (UWord32)L_szA)); /* non-fractional mult; (int)ind * L_szA */ + *L_cwB = L_deposit_l( ind ); + *L_cwA = L_sub( L_cwRx, (Word32) UL_Mpy_32_32( UL_deposit_l( (UWord16) ind ), + (UWord32) L_szA ) ); /* non-fractional mult; (int)ind * L_szA */ - ASSERT(*L_cwA >= 0 && *L_cwA < L_szA); - ASSERT(*L_cwB >= 0 && *L_cwB < L_szB); + ASSERT( *L_cwA >= 0 && *L_cwA < L_szA ); + ASSERT( *L_cwB >= 0 && *L_cwB < L_szB ); *submodeLSB = 0; - *L_cwB = L_sub(*L_cwB, 2); - if (*L_cwB < 0) + *L_cwB = L_sub( *L_cwB, 2 ); + if ( *L_cwB < 0 ) { - *submodeLSB = 1; move16(); + *submodeLSB = 1; + move16(); } - *L_cwB = L_mac0(*L_cwB, 2, *submodeLSB); /* add back gain ind if needed */ + *L_cwB = L_mac0( *L_cwB, 2, *submodeLSB ); /* add back gain ind if needed */ return 0; /* no BER */ } + +#ifdef CR9_C_ADD_1p25MS_LRSNS + +void readSNSData_fx(UWord8* ptr, + Word16* bfiPtr, + Word16* mask_side, + Word16* bp_side, + Word16* ltpf_idx_2_lrsns, + Word32* L_scf_idx, + LC3PLUS_FrameDuration frame_dms) +{ + Dyn_Mem_Deluxe_In( + Word32 i, tmp32, tmp32lim; + Word16 submodeMSB, submodeLSB; + Word16 L, BER_detect; + Word16 read_legacy_sns_vq_bits_fx; + Word16 shape_idx, gain_idx, aux_idx, tmp_shape, stop_bit; + Word16 plc_trigger_SNS1, plc_trigger_SNS2; + + ); + + BER_detect = 0; move16(); + plc_trigger_SNS1 = 1; move16(); +#ifdef LRSNS_10MS_BFISIGNAL_FIX + plc_trigger_SNS2 = 1; move16(); +#else + plc_trigger_SNS2 = 2; move16(); +#endif + read_legacy_sns_vq_bits_fx = 1; move16(); + IF(sub(frame_dms, LC3PLUS_FRAME_DURATION_1p25MS) == 0) + { + read_legacy_sns_vq_bits_fx = 0; move16(); /* decode 9, 10, or 29/30 bits */ + } + + IF(read_legacy_sns_vq_bits_fx != 0) + { + /* Decode SNS VQ parameters - 1st stage (10 bits) */ + L = read_indice(ptr, bp_side, mask_side, 5 + 5); + L_scf_idx[0] = L_deposit_l(s_and(L, 0x1F)); /* stage1 LF 5 bits */ + L_scf_idx[1] = L_deposit_l(shr_pos(L, 5)); /* stage1 HF 5 bits */ + + + /* Decode SNS VQ parameters - 2nd stage side-info (3-4 bits) */ + submodeMSB = read_bit(ptr, bp_side, mask_side); /* submodeMSB 1 bit */ + L_scf_idx[2] = L_deposit_l(shl_pos(submodeMSB, 1)); + ASSERT(sns_gainMSBbits[L_scf_idx[2]] > 0); + L_scf_idx[3] = L_deposit_l( + read_indice(ptr, bp_side, mask_side, sns_gainMSBbits[L_scf_idx[2]])); /* gains or gain MSBs 1-2 bits */ + L_scf_idx[4] = read_bit(ptr, bp_side, mask_side); /* shape LS 1 bit */ + + /* Decode SNS VQ parameters - 2nd stage data (24-25 bits) */ + IF(submodeMSB == 0) + { /* shape_j = 0, or 1 */ + /* regular mode A,B indexes integer multiplexed, total 24.x bits MPVQ codeword section A and codeword for + * section B */ + /* regular mode mode shape index total 24.9999 bits MPVQ codeword */ + + tmp32 = L_deposit_l(read_indice(ptr, bp_side, mask_side, 13)); + tmp32 = L_or(tmp32, L_shl_pos(read_indice(ptr, bp_side, mask_side, 12), 13)); + move16(); /*for ber state */ + BER_detect = + ac_dec_split_st2VQ_CW( /* local BER flag */ + tmp32, /* L_cwRx max 25 bits */ + sns_MPVQ_Sz[0][0], UL_addNsD(sns_MPVQ_Sz[0][1], sns_MPVQ_Sz[1][1]), /* 12+2 = 14 */ + (&L_scf_idx[5]), /* shape A */ + (&L_scf_idx[6]), /* shape B or gain LSB */ + &submodeLSB /* total submode update below */ + ); + IF(submodeLSB != 0) + { /* add gainLSB bit */ + L_scf_idx[3] = L_add(L_shl_pos(L_scf_idx[3], 1), L_scf_idx[6]); + L_scf_idx[6] = -2L; + } + } + ELSE + { /* shape_j = 2 or 3 */ + ASSERT(submodeMSB == 1); + /* outlier mode shape index total 23.8536 + 19.5637 (19.5637 < (log2(2.^24 -2.^23.8537)) bits MPVQ + * codeword */ + tmp32 = L_deposit_l(read_indice(ptr, bp_side, mask_side, 12)); + tmp32 = L_or(tmp32, L_shl_pos(read_indice(ptr, bp_side, mask_side, 12), 12)); + + L_scf_idx[5] = tmp32; move32(); /*shape outl_near or outl_far */ + submodeLSB = 0; move16(); + BER_detect = 0; move16(); + tmp32lim = L_add(sns_MPVQ_Sz[2][0], L_shl_pos(sns_MPVQ_Sz[3][0], 1)); + + IF (L_sub(tmp32, tmp32lim) >= 0) + { + BER_detect = 1; move16(); + } + ELSE + { + tmp32 = L_sub(tmp32, sns_MPVQ_Sz[2][0]); /* a potential high index is computed */ + IF (tmp32 >= 0) + { + submodeLSB = 1; move16(); + ASSERT(tmp32 >= 0 && tmp32 < (Word32)(2 * sns_MPVQ_Sz[3][0])); + L_scf_idx[3] = L_add(L_shl_pos(L_scf_idx[3], 1), L_and(tmp32, 0x1)); /* add LSB_gain bit to gain MSBs */ + L_scf_idx[5] = L_shr_pos(tmp32, 1); /* MPVQ index with offset and gainLSB removed */ + L_scf_idx[6] = -2L; move32(); + } + ELSE + { + L_scf_idx[6] = -1L; move32(); + } + } + } + L_scf_idx[2] = + L_add(L_scf_idx[2], L_deposit_l(submodeLSB)); /* decoder internal signal shape_j = submode 0..3 to VQ */ + + +#ifdef LRSNS_10MS_BFISIGNAL_FIX + IF( BER_detect > 0) + { + *bfiPtr = 1; move16(); + Dyn_Mem_Deluxe_Out(); + return; + } +#else + *bfiPtr = BER_detect; move16(); + IF(*bfiPtr != 0) + { + Dyn_Mem_Deluxe_Out(); + return; + } +#endif + } + ELSE + { + ASSERT(read_legacy_sns_vq_bits_fx == 0 ); + /* lrsns 9/10/29/30 */ + /* init auxiliary demuxing variabls */ + shape_idx = -1; move16(); + gain_idx = -1; move16(); + aux_idx = -1; move16(); + tmp_shape = -1; move16(); + stop_bit = -1; move16(); + + FOR(i = 0; i < SCF_MAX_PARAM; i++) + { + L_scf_idx[i] = L_sub(-32000, i); move32(); /* init parameters to be fwded to LRSNS VQ demultiplexor */ + } + + /* start actual Q-mode and fractional bits demultiplexing */ + + /* SNS-VQ 1st stage , 3 sections of 7.4 bits is stored in the first 9 bits */ + L_scf_idx[0] = L_deposit_l(read_indice(ptr, bp_side, mask_side, 9)); + + IF(L_sub(L_scf_idx[0], 510) >= 0) + { + ASSERT(L_scf_idx[0] < 512); + L_scf_idx[0] -= 510; move32(); /* sent only idx 0,1 */ + shape_idx = -9; move16(); + L_scf_idx[2] = shape_idx; move32(); /* actual signal to LRSNS decoder vector reconstruction */ + } + ELSE + { + /* read stop bit, 10th bit */ + stop_bit = read_indice(ptr, bp_side, mask_side, 1); + + test(); test(); + IF((L_sub(L_scf_idx[0] , (2 * 170)) < 0) && (stop_bit != 0)) + { + /*keep values 0...339 in sns_vq_idx[0] , so that B vs C can be determined later in DecLR_fx function */ + L_scf_idx[2] = -10L; move32(); + L_scf_idx[3] = L_deposit_l(ltpf_idx_2_lrsns[0]); /*LTP active flag */ + L_scf_idx[4] = L_deposit_l(ltpf_idx_2_lrsns[1]); /*LTPF active flag */ + } + ELSE + { /* stage1B* + stage2*/ + /*0...169 in sns_vq_idx[0]*/ + test(); test(); + IF((L_sub(L_scf_idx[0], (2 * 170)) < 0) && (stop_bit == 0)) + { + aux_idx = 0; move16(); /* typically a leading or first sign is stored in aux_idx */ + + IF(L_sub(L_scf_idx[0], 170) >= 0) + { + aux_idx = 1; move16(); + L_scf_idx[0] = L_sub(L_scf_idx[0], 170); move32(); + } + L_scf_idx[1] = aux_idx; move32(); /* forward aux bit for , LR_Split_LF, 29 bits */ + + shape_idx = 0; move16(); /* point to splitLF parsing */ + L_scf_idx[2] = L_deposit_l(shape_idx); move32(); + + gain_idx = read_indice(ptr, bp_side, mask_side, 2); + L_scf_idx[3] = L_deposit_l(gain_idx); move32(); + + /* stage2 shape demux for LR_splitLF */ + + L_scf_idx[4] = L_deposit_l(read_indice(ptr, bp_side, mask_side, 10));/* 10bits mPVQ(N=5,K=6) */ + + IF(L_sub(L_scf_idx[4] , (SNSLR_NPVQ_L5K6 >> 1) + (1 << 5)) >= 0) /* some limited bit error detection possible here */ + { + *bfiPtr = plc_trigger_SNS1; move16(); + IF(*bfiPtr != 0) + { +#ifdef LRSNS_10MS_BFISIGNAL_FIX + ASSERT(*bfiPtr == 1); +#endif + Dyn_Mem_Deluxe_Out(); + return; + } + } + + /* determine section of splitLF mpvq(5,6)+P(8,2)+P(2,0) or mpvq(5,8)+P(10,0) */ + IF(L_sub(L_scf_idx[4] , (SNSLR_NPVQ_L5K6 >> 1)) < 0) + { + tmp_shape = read_indice(ptr, bp_side, mask_side, 1);/* LS (8,2) */ + L_scf_idx[5] = L_deposit_l(read_indice(ptr, bp_side, mask_side, 6)); move32(); /* mPVQ(8,2) */ + L_scf_idx[5] = L_mac0(L_shl_pos(L_scf_idx[5], 1), 1, tmp_shape); move32(); /* P(8,2) LS put as lsb */ + } + ELSE + { + L_scf_idx[4] = L_sub(L_scf_idx[4], (SNSLR_NPVQ_L5K6 >> 1)); move32(); /* 5 lsbs of mpvq (5,8) */ + + L_scf_idx[5] = L_deposit_l(read_indice(ptr, bp_side, mask_side, 7)); move32();/* 7 msbs of mPVQ(5,8) */ + + L_scf_idx[4] = L_or(L_shl_pos(L_scf_idx[5], 5), L_scf_idx[4]); move32(); /* binary merge MSB's and LSBs */ + L_scf_idx[5] = -8L; move32(); /* signal to sns_decoder split_LF subshape to decode 8 lf pulses, and no hf pulses */ + + IF(L_sub(L_scf_idx[4] , (SNSLR_NPVQ_L5K8 >> 1)) >= 0) + { + *bfiPtr = plc_trigger_SNS2; move16(); + IF( *bfiPtr != 0 ) + { +#ifdef LRSNS_10MS_BFISIGNAL_FIX + ASSERT(*bfiPtr == 1); +#endif + Dyn_Mem_Deluxe_Out(); + return; + } + } + } + } + ELSE IF(L_sub(L_scf_idx[0], 2 * 170) >= 0) + { + aux_idx = stop_bit; move16(); + L_scf_idx[0] = L_sub(L_scf_idx[0], 2 * 170); move32(); + L_scf_idx[1] = L_deposit_l(aux_idx); move32(); + + + shape_idx = 1; move16();/* point to full parsing */ + L_scf_idx[2] = shape_idx; move32();/* LR_full , 30 bits */ + + gain_idx = read_indice(ptr, bp_side, mask_side, 3); + L_scf_idx[3] = gain_idx; move32(); + + /* stage2 shape demux for LR_full */ + tmp32 = L_deposit_l(read_indice(ptr, bp_side, mask_side, 10)); /* 10 LSBs. total 16.666 bits mPVQ(N=15,K=5) */ + tmp32 = L_or(tmp32, L_shl_pos(read_indice(ptr, bp_side, mask_side, 7), 10)); /*7 MSBs */ + L_scf_idx[4] = tmp32; move32(); + IF(L_sub(L_scf_idx[4], (SNSLR_NPVQ_L15K5 >> 1)) >= 0) + { /* fixenv shapes demultiplexing */ + L_scf_idx[5] = L_sub(L_scf_idx[4], (SNSLR_NPVQ_L15K5 >> 1)); move32(); + + IF(L_sub(L_scf_idx[5] , 3 * (1 << 13)) < 0) + { /*fix_env's "0,1,2" with 2 shiftbits and 11 remaining sign bits s1..s11 */ + L_scf_idx[4] = 0L; move32(); + WHILE(L_sub(L_scf_idx[5], (1 << 13)) >= 0) + { + L_scf_idx[5] = L_mac0(L_scf_idx[5], -1, (1 << 13)); move32(); + L_scf_idx[4] = L_add(L_scf_idx[4], 1); move32(); + } + assert(L_scf_idx[4] >= 0 && L_scf_idx[4] <= 3); + assert(L_scf_idx[5] >= 0 && L_scf_idx[5] < (1 << 13)); + } + ELSE IF(L_sub(L_scf_idx[5], 3 * (1 << 13) + (1 << 11)) < 0) + { + L_scf_idx[4] = 3L; move32(); /*smaller fix_env "3" with 2 shiftbits and 9 remaining sign bits s1..s9 */ + L_scf_idx[5] = L_mac0(L_scf_idx[5] , -1, 3 * (1 << 13)); move32(); + assert(L_scf_idx[5] >= 0 && L_scf_idx[5] < (1 << 11)); + } + ELSE + { + /* unused section indicate bit error */ + *bfiPtr = plc_trigger_SNS2; move16(); + test(); + IF( *bfiPtr != 0 ) + { + Dyn_Mem_Deluxe_Out(); + return; + } + } + shape_idx = add(extract_l(L_scf_idx[4]), 2); move32(); + L_scf_idx[2] = L_deposit_l(shape_idx); move32(); + } /* fixenv */ + } /*full*/ + } /*stage1B* + stage2 */ + } /*10+ bits*/ + } +#ifdef LRSNS_PC_SIGNAL_FIX + assert(*bfiPtr == 0 || *bfiPtr == 1); /* local SNS BFI-flag output check */ +#endif + Dyn_Mem_Deluxe_Out(); +} /*read SNS*/ +#endif /* LRSNS */ + + + +#ifdef NEW_SIGNALLING_SCHEME_1p25 + +void readLtpData_fx( + UWord8* ptr, + Word16* bfiPtr, + Word16* mask_side, + Word16* bp_side, + Word16* ltpf_idx, + Word16* rx_status, + Word16* ltpfinfo_frame_cntr_fx, + Word16* mem_continuation +) +{ + Word16 rx_current_status = -1; + Word16 tmp, MSBs, LSBs; + + ltpf_idx[2] = -1; move16(); /* -1 indicates incomplete lag, conditionally decoded if phase is B , and consecutive A/B has arrived */ + + tmp = read_indice(ptr, bp_side, mask_side, 2); + + test(); + IF(tmp == 0) + { + ltpf_idx[0] = 0; move16(); /* ltp ltpf/lag was not transmitted */ + ltpf_idx[1] = 0; move16(); /* ltpf activation bit zeroed */ + + /* *ltp_bits_fx = 2; */ /* note: ltpbits bitbudget not really used in decoder */ + + rx_status[0] = -32768; move16(); /* set unknown phase A , due to rxLTP==0 */ + rx_status[1] = -1; move16(); /* set unknown phase A MSBs content */ + *ltpfinfo_frame_cntr_fx = -32768; move16(); + ASSERT(ltpf_idx[2] < 0); /* ltpf_idx[2] = -1; , no ready lag available */ +#ifdef FIX_LTPF_1p25 + *mem_continuation = 0; move16(); /* also kill lag continuation state */ +#endif + } + ELSE IF(sub(tmp, 1) == 0) + { + ltpf_idx[0] = 1; + ltpf_idx[1] = 0; /* LTP=1, LTPF=0, inactive ltpf */ + rx_current_status = read_bit(ptr, bp_side, mask_side); + + test(); + IF(rx_current_status == 0) + { + rx_status[0] = 0; move16(); /* phaseA */ + rx_status[1] = read_indice(ptr, bp_side, mask_side, 4); /* read four MSBs, and store in rx_status[1] */ +#ifdef FIX_LTPF_1p25 + test(); + if (*mem_continuation == 0) + { + *mem_continuation = 1; + } +#endif + *ltpfinfo_frame_cntr_fx = 0; /* handle longer loss bursts */ + } + ELSE + { /* LSB part of delta coded lag information */ + ASSERT(rx_current_status == 1); + LSBs = shl(read_indice(ptr, bp_side, mask_side, 4), 1); /* NB LSB is on purpose always zero, truncation on encoder side */ + IF ( rx_status[1] < 0 ) + { + *bfiPtr = 1; move16(); + return; + } + ltpf_idx[2] = s_or(shl(rx_status[1], 5), LSBs); + + /* check frame cntr info to not combine oldA with a newB */ + IF(sub(*ltpfinfo_frame_cntr_fx, 1) != 0) + { + ltpf_idx[1] = 0; move16(); /*turn of LTPF, even number of bfi frames may have happened */ + ltpf_idx[2] = -1; move16(); /* indicate bfi burst and corrupt lagLSBs to PLC and ltpf_decoder_fx */ + } +#ifdef FIX_LTPF_MEM_CONTINUATION + else + { + *mem_continuation = 0; move16(); + } + # endif + rx_status[0] = -32768; move16(); + *ltpfinfo_frame_cntr_fx = -32678; move16(); + } + } + ELSE + { /*2 or 3*/ + ltpf_idx[0] = 1; move16(); + ltpf_idx[1] = 1; move16(); /* active ltpf */ + + IF(sub(tmp, 2) == 0) + { + /* phaseA */ + MSBs = read_indice(ptr, bp_side, mask_side, 4); + rx_status[0] = 0; move16(); + rx_status[1] = MSBs; move16();/* remember the four MSBs */ +#ifdef FIX_LTPF_1p25 + test(); + if (*mem_continuation == 0) + { + *mem_continuation = 1; move16(); + } +#endif + *ltpfinfo_frame_cntr_fx = 0; move16(); + } + ELSE + { + ASSERT(tmp == 3); /* phaseB */ + LSBs = read_indice(ptr, bp_side, mask_side, 5); /* all 5 LSBs available*/ + IF ( rx_status[1] < 0 ) + { + *bfiPtr = 1; move16(); + return; + } + ltpf_idx[2] = s_or(shl(rx_status[1], 5), LSBs); + + /* check frame cntr info to not combine oldA MSBs with a newB LSBs */ + IF(sub(*ltpfinfo_frame_cntr_fx, 1) != 0) + { + ltpf_idx[1] = 0; move16(); /* turn off LTPF activation, ltpf_idx[2] is not read */ + ltpf_idx[2] = -1; move16(); /* indicate bfi burst and corrupt lagLSBs to PLC and ltpf_decoder_fx */ + } + *ltpfinfo_frame_cntr_fx = -32678; move16(); /*cntr init in phaseA*/ + rx_status[0] = -32768; move16(); /* phase init in phaseA*/ + +#ifdef FIX_LTPF_MEM_CONTINUATION + *mem_continuation = 0; move16(); +#endif + } + } +} + +#endif diff --git a/lib_lc3plus/dec_lc3.c b/lib_lc3plus/dec_lc3plus.c similarity index 81% rename from lib_lc3plus/dec_lc3.c rename to lib_lc3plus/dec_lc3plus.c index fc01373d5..525edc74f 100644 --- a/lib_lc3plus/dec_lc3.c +++ b/lib_lc3plus/dec_lc3plus.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,6 +7,8 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "functions.h" static int Dec_LC3PLUS_Channel(LC3PLUS_Dec *decoder, int channel, int bits_per_sample, UWord8 *bs_in, void *s_out, Word16 bfi, @@ -22,13 +24,14 @@ static int Dec_LC3PLUS_Channel(LC3PLUS_Dec *decoder, int channel, int bits_per_s #ifdef ENABLE_RFRAME Word16 rframe = 0; #endif - Word16 ltpf_idx[3]; + Word16 ltpf_idx[3] = {0}; Word16 spec_inv_idx = 0; Counter i; /* Buffers */ Word16 *int_scf_fx_exp, tns_order[TNS_NUMFILTERS_MAX]; UWord8 *resBitBuf; + Word16 resBitBufLen; #ifdef ENABLE_HR_MODE Word32 *sqQdec; #else @@ -41,11 +44,26 @@ static int Dec_LC3PLUS_Channel(LC3PLUS_Dec *decoder, int channel, int bits_per_s Word32 * q_d_fx; Word8 * currentScratch; DecSetup *h_DecSetup = decoder->channel_setup[channel]; + +#ifdef CR9_C_ADD_1p25MS_LRSNS + Word16 pitch_rx_fx; + Word16 ltpf_rx_fx; +#endif + +#ifdef CR9_C_ADD_1p25MS_LRSNS + Word32 scf_q_ip[M]; +#ifdef ENABLE_HR_MODE + //Counter i; + Word32* x_fx_ip; + Word32 *int_scf_fx_ip; +#endif +#else #ifdef ENABLE_HR_MODE Word32 *x_fx_ip; Word32 *int_scf_fx_ip; Word32 scf_q_ip[M]; #endif +#endif /* CR9_C_ADD_1p25MS_LRSNS */ #ifdef DYNMEM_COUNT struct _dynmem @@ -73,6 +91,7 @@ static int Dec_LC3PLUS_Channel(LC3PLUS_Dec *decoder, int channel, int bits_per_s Word16 *sqQdec; #endif Word16 *int_scf_fx, *x_fx, *indexes; + Word16 resBitBufLen; Word32 *L_scf_idx; Word32 *q_d_fx; Word8 * currentScratch; @@ -91,12 +110,35 @@ static int Dec_LC3PLUS_Channel(LC3PLUS_Dec *decoder, int channel, int bits_per_s /* BUFFER INITIALISATION. Some buffers may overlap since they are not used in the whole decoding process */ q_d_fx = scratchAlign(scratchBuffer, 0); /* Size = 4 * MAX_LEN bytes */ + +#ifdef CR9_C_ADD_1p25MS + IF (decoder->frame_dms==LC3PLUS_FRAME_DURATION_1p25MS) + { + resBitBufLen = 3; + } + ELSE { +#endif + resBitBufLen = 2; +#ifdef CR9_C_ADD_1p25MS + } +#endif + #ifdef ENABLE_HR_MODE /* allocate memory for residual bits */ if (decoder->hrmode) { - resBitBuf = scratchAlign(q_d_fx, sizeof(*q_d_fx) * +#ifdef CR9_C_ADD_1p25MS + IF (decoder->frame_dms==LC3PLUS_FRAME_DURATION_1p25MS) + { + resBitBuf = scratchAlign(q_d_fx, sizeof(*q_d_fx) * + decoder->frame_length * 3); + } + ELSE +#endif + { + resBitBuf = scratchAlign(q_d_fx, sizeof(*q_d_fx) * decoder->frame_length); + } basop_memset(resBitBuf, 0, sizeof(*resBitBuf) * MAX_RESBITS_LEN); } else @@ -105,13 +147,14 @@ static int Dec_LC3PLUS_Channel(LC3PLUS_Dec *decoder, int channel, int bits_per_s resBitBuf = scratchAlign(q_d_fx, sizeof(*q_d_fx) * decoder->frame_length); /* Size = 2 * NPRM_RESQ = 2 * MAX_LEN bytes for normal case and 2*MAX_RESBITS_LEN for hrmode */ - basop_memset(resBitBuf, 0, sizeof(*resBitBuf) * 2 * decoder->frame_length); + + basop_memset(resBitBuf, 0, sizeof(*resBitBuf) * resBitBufLen * decoder->frame_length); } - + #ifdef ENABLE_HR_MODE indexes = scratchAlign(resBitBuf, sizeof(*resBitBuf) * MAX_RESBITS_LEN); #else - indexes = scratchAlign(resBitBuf, sizeof(*resBitBuf) * 2 * decoder->frame_length); + indexes = scratchAlign(resBitBuf, sizeof(*resBitBuf) * resBitBufLen * decoder->frame_length); #endif memset(indexes, 0, sizeof(*indexes) * TNS_NUMFILTERS_MAX * MAXLAG); @@ -134,11 +177,11 @@ static int Dec_LC3PLUS_Channel(LC3PLUS_Dec *decoder, int channel, int bits_per_s scratchAlign(q_d_fx, sizeof(*q_d_fx) * decoder->frame_length); /* Size = 2 * (MAX_LEN + MDCT_MEM_LEN_MAX) = 2 * MAX_LEN + 1.25 * MAX_LEN = 3.25 * MAX_LEN */ #endif - + #ifdef ENABLE_HR_MODE x_fx_ip = scratchAlign(x_fx, sizeof(*x_fx) * (decoder->frame_length + decoder->stDec_ola_mem_fx_len)); int_scf_fx_ip = scratchAlign(x_fx_ip, sizeof(*x_fx_ip) * (decoder->frame_length + decoder->stDec_ola_mem_fx_len)); - + currentScratch = scratchAlign(int_scf_fx_ip, sizeof(*int_scf_fx_ip) * 2 * MAX_BANDS_NUMBER); /* Size = 4 * MAX_LEN */ #else currentScratch = scratchAlign(x_fx, sizeof(*x_fx) * 4 * MAX_LEN); /* Size = 4 * MAX_LEN */ @@ -178,11 +221,29 @@ static int Dec_LC3PLUS_Channel(LC3PLUS_Dec *decoder, int channel, int bits_per_s #ifdef WMOPS push_wmops("Entropy dec"); #endif +#ifdef NEW_SIGNALLING_SCHEME_1p25 + h_DecSetup->ltpfinfo_frame_cntr_fx = add_sat(h_DecSetup->ltpfinfo_frame_cntr_fx, 1); + /*ltpfinfo_frame_cntr_fx increased always, also for bfi=1 */ /* set or reset inside dec_entropy_fx() */ +#endif + IF (sub(bfi, 1) != 0) { processDecoderEntropy_fx(bs_in, &bp_side, &mask_side, h_DecSetup->total_bits, decoder->yLen, decoder->fs_idx, decoder->BW_cutoff_bits, &tns_numfilters, &lsbMode, &lastnz, &bfi, tns_order, - &fac_ns_idx, &gg_idx, &BW_cutoff_idx, ltpf_idx, L_scf_idx, decoder->frame_dms); + &fac_ns_idx, &gg_idx, &BW_cutoff_idx, ltpf_idx, L_scf_idx, decoder->frame_dms +#ifdef CR9_C_ADD_1p25MS +#ifdef FIX_TX_RX_STRUCT_STEREO + , h_DecSetup->ltpf_rx_status, &h_DecSetup->ltpf_mem_continuation +#else + , decoder->ltpf_rx_status, &decoder->ltpf_mem_continuation +#endif +#ifdef NEW_SIGNALLING_SCHEME_1p25 + , + &h_DecSetup->ltpfinfo_frame_cntr_fx +#endif +#endif + ); + BW_cutoff_idx_nf = BW_cutoff_idx; move16(); } @@ -204,7 +265,7 @@ static int Dec_LC3PLUS_Channel(LC3PLUS_Dec *decoder, int channel, int bits_per_s , decoder->hrmode #endif ); - + #ifdef ENABLE_RFRAME test();test(); IF (sub(rframe, 1) == 0 && zero_frame == 0 && sub(bfi, 1) != 0) @@ -214,24 +275,31 @@ static int Dec_LC3PLUS_Channel(LC3PLUS_Dec *decoder, int channel, int bits_per_s Word16 max_bw_stopband = BW_cutoff_bin_all[BW_cutoff_idx]; SWITCH (decoder->frame_dms) { - case 25: - max_bw_stopband = shr_pos(max_bw_stopband, 2); - BREAK; - case 50: - max_bw_stopband = shr_pos(max_bw_stopband, 1); - BREAK; - case 75: - max_bw_stopband = add(shr_pos(max_bw_stopband, 2), add(shr_pos(max_bw_stopband, 2), shr_pos(max_bw_stopband, 2))); - BREAK; - case 100: - BREAK; +#ifdef CR9_C_ADD_1p25MS + case LC3PLUS_FRAME_DURATION_1p25MS: + max_bw_stopband = shr_pos(max_bw_stopband, 3); + BREAK; +#endif + case LC3PLUS_FRAME_DURATION_2p5MS: + max_bw_stopband = shr_pos(max_bw_stopband, 2); + BREAK; + case LC3PLUS_FRAME_DURATION_5MS: + max_bw_stopband = shr_pos(max_bw_stopband, 1); + BREAK; + case LC3PLUS_FRAME_DURATION_7p5MS: + max_bw_stopband = add(shr_pos(max_bw_stopband, 2), add(shr_pos(max_bw_stopband, 2), shr_pos(max_bw_stopband, 2))); + BREAK; + case LC3PLUS_FRAME_DURATION_10MS: + BREAK; + case LC3PLUS_FRAME_DURATION_UNDEFINED: + assert(0); } - + spec_inv_idx = s_max(lastnz, max_bw_stopband); move16(); } #endif - + IF (bfi == 0) { processAriDecoderScaling_fx(sqQdec, decoder->yLen, q_d_fx, &q_fx_exp); @@ -244,8 +312,27 @@ static int Dec_LC3PLUS_Channel(LC3PLUS_Dec *decoder, int channel, int bits_per_s #ifdef WMOPS push_wmops("SnsQuantScfDec"); #endif + IF (sub(bfi, 1) != 0) +#ifdef CR9_C_ADD_1p25MS_LRSNS { + IF(sub(decoder->frame_dms, LC3PLUS_FRAME_DURATION_1p25MS) == 0) + { + pitch_rx_fx = ltpf_idx[0]; move16(); + +#ifdef LRSNS_CBC_NO_LTPF_DEPENDENCY + ltpf_rx_fx = 0; move16(); /* CB_C with binary means , not dependent on LTPF activation */ +#else + ltpf_rx_fx = ltpf_idx[1]; move16();/* CB_C, with ternary means dependent on LTPF activation */ +#endif + snsQuantScfDecLR_fx(L_scf_idx, scf_q_ip, scf_q, pitch_rx_fx, ltpf_rx_fx, currentScratch); /* 9,12,29,30, bits decoding and 2 pitch info bits */ +#ifdef ENABLE_HR_MODE + downshift_w32_arr(scf_q_ip /* Q26 */, scf_q/* Q11 */, 26 - 11, M); /* W16Q11 version required for PLC */ +#endif + } + ELSE +#endif /* CR9_C_ADD_1p25MS_LRSNS */ + { /* currentScratch Size = 96 bytes */ #ifdef ENABLE_HR_MODE processSnsQuantizeScfDecoder_fx(L_scf_idx, scf_q_ip, currentScratch); @@ -254,6 +341,9 @@ static int Dec_LC3PLUS_Channel(LC3PLUS_Dec *decoder, int channel, int bits_per_s processSnsQuantizeScfDecoder_fx(L_scf_idx, scf_q, currentScratch); #endif } +#ifdef CR9_C_ADD_1p25MS_LRSNS +} +#endif #ifdef WMOPS pop_wmops(); #endif @@ -293,6 +383,22 @@ static int Dec_LC3PLUS_Channel(LC3PLUS_Dec *decoder, int channel, int bits_per_s pop_wmops(); #endif +#ifdef FIX_PLC_CONFORM_ISSUES +#ifdef CR9_C_ADD_1p25MS + IF( sub( bfi, 1 ) == 0 ) + { +#ifdef FIX_TX_RX_STRUCT_STEREO + h_DecSetup->ltpf_rx_status[0] = 0; + h_DecSetup->ltpf_rx_status[1] = 0; +#else + decoder->ltpf_rx_status[0] = 0; + decoder->ltpf_rx_status[1] = 0; +#endif + } +#endif +#endif + + IF (sub(bfi, 1) != 0) { #ifdef WMOPS @@ -301,6 +407,9 @@ static int Dec_LC3PLUS_Channel(LC3PLUS_Dec *decoder, int channel, int bits_per_s processResidualDecoding_fx(q_d_fx, q_fx_exp, decoder->yLen, resBitBuf, fill_bits #ifdef ENABLE_HR_MODE , decoder->hrmode +#endif +#if defined (CR9_C_ADD_1p25MS) + , decoder->frame_dms #endif ); #ifdef WMOPS @@ -311,11 +420,15 @@ static int Dec_LC3PLUS_Channel(LC3PLUS_Dec *decoder, int channel, int bits_per_s push_wmops("Noisefill"); #endif /* currentScratch Size = 2 * MAX_LEN bytes */ +#ifdef CR9_C_ADD_1p25MS IF (zero_frame == 0) +#else + IF (zero_frame == 0) +#endif { processNoiseFilling_fx(q_d_fx, nf_seed, q_fx_exp, fac_ns_idx, BW_cutoff_idx_nf, decoder->frame_dms, h_DecSetup->prev_fac_ns_fx, spec_inv_idx, currentScratch -#ifdef ENABLE_HR_MODE +#ifdef ENABLE_HR_MODE , decoder->hrmode #endif ); @@ -332,6 +445,9 @@ static int Dec_LC3PLUS_Channel(LC3PLUS_Dec *decoder, int channel, int bits_per_s pop_wmops(); #endif +#ifdef CR9_C_ADD_1p25MS + if (tns_numfilters > 0) { +#endif #ifdef WMOPS push_wmops("Tns_dec"); #endif @@ -345,6 +461,9 @@ static int Dec_LC3PLUS_Channel(LC3PLUS_Dec *decoder, int channel, int bits_per_s #ifdef WMOPS pop_wmops(); #endif +#ifdef CR9_C_ADD_1p25MS + } +#endif #ifdef ENABLE_HR_MODE #ifdef WMOPS @@ -386,7 +505,7 @@ static int Dec_LC3PLUS_Channel(LC3PLUS_Dec *decoder, int channel, int bits_per_s /* end int_scf_fx */ #endif /* ENABLE_HR_MODE */ } - + /* x_fx_ip will be used to store h_DecSetup->stDec_ola_mem_fx returned by PLCmain_fx*/ /* This will be upshifted to 32 bit overlap buffer outside of the PLCmain function */ #ifdef ENABLE_HR_MODE @@ -425,7 +544,7 @@ static int Dec_LC3PLUS_Channel(LC3PLUS_Dec *decoder, int channel, int bits_per_s #ifdef WMOPS pop_wmops(); #endif - + #ifdef ENABLE_HR_MODE IF(sub(bfi, 1) == 0) { @@ -447,7 +566,7 @@ static int Dec_LC3PLUS_Channel(LC3PLUS_Dec *decoder, int channel, int bits_per_s h_DecSetup->ltpf_mem_pitch_int, ltpf_idx[0], q_d_fx, &q_fx_exp, h_DecSetup->q_old_d_fx, &h_DecSetup->q_old_fx_exp, decoder->yLen, h_DecSetup->plcAd->stab_fac, decoder->frame_dms, &h_DecSetup->plcAd->cum_fading_slow, &h_DecSetup->plcAd->cum_fading_fast, spec_inv_idx - , h_DecSetup->plcAd->plc_fadeout_type + , h_DecSetup->plcAd->plc_fadeout_type ); } #ifdef WMOPS @@ -472,7 +591,7 @@ static int Dec_LC3PLUS_Channel(LC3PLUS_Dec *decoder, int channel, int bits_per_s , decoder->hrmode #endif ); - + #ifdef ENABLE_HR_MODE IF(sub(bfi, 1) != 0 || sub(h_DecSetup->concealMethod, LC3_CON_TEC_NS_STD) == 0 || sub(h_DecSetup->concealMethod, LC3_CON_TEC_NS_ADV) == 0 || sub(h_DecSetup->concealMethod, LC3_CON_TEC_FREQ_MUTING) == 0) { @@ -516,13 +635,25 @@ static int Dec_LC3PLUS_Channel(LC3PLUS_Dec *decoder, int channel, int bits_per_s &h_DecSetup->ltpf_mem_pitch_int, &h_DecSetup->ltpf_mem_pitch_fr, &h_DecSetup->ltpf_mem_gain, &h_DecSetup->ltpf_mem_active, h_DecSetup->ltpf_scale_fac_idx, bfi, h_DecSetup->concealMethod, - h_DecSetup->plc_damping, &h_DecSetup->ltpf_mem_scale_fac_idx, + h_DecSetup->plc_damping, &h_DecSetup->ltpf_mem_scale_fac_idx, &h_DecSetup->rel_pitch_change, decoder->hrmode, decoder->frame_dms, - currentScratch); + currentScratch +#ifdef CR9_C_ADD_1p25MS +#ifdef FIX_TX_RX_STRUCT_STEREO + ,&h_DecSetup->ltpf_mem_continuation, &h_DecSetup->ltpf_mem_pitch_int_prev, + &h_DecSetup->ltpf_mem_pitch_fr_prev, &h_DecSetup->ltpf_mem_beta_idx_prev, &h_DecSetup->ltpf_mem_gain_prev, + &h_DecSetup->ltpf_mem_active_prev, &h_DecSetup->ltpf_pitch_stability_counter +#else + , &decoder->ltpf_mem_continuation, &decoder->ltpf_mem_pitch_int_prev, + &decoder->ltpf_mem_pitch_fr_prev, &decoder->ltpf_mem_beta_idx_prev, &decoder->ltpf_mem_gain_prev, + &decoder->ltpf_mem_active_prev, &decoder->ltpf_pitch_stability_counter +#endif +#endif + ); #ifdef WMOPS pop_wmops(); #endif - + #ifdef ENABLE_HR_MODE IF (!(decoder->hrmode)) { @@ -532,7 +663,7 @@ static int Dec_LC3PLUS_Channel(LC3PLUS_Dec *decoder, int channel, int bits_per_s } } #endif - + #ifdef WMOPS push_wmops("Output scaling"); #endif @@ -652,6 +783,7 @@ LC3PLUS_Error Dec_LC3PLUS(LC3PLUS_Dec *decoder, UWord8 *input, int num_bytes, vo { decoder->epmr = 12; out_bfi = 0; + decoder->error_report = 0; for (ch = 0; ch < decoder->channels; ch++) { @@ -663,10 +795,16 @@ LC3PLUS_Error Dec_LC3PLUS(LC3PLUS_Dec *decoder, UWord8 *input, int num_bytes, vo channel_bfi = bfi; - decoder->error_report = + Word32 chan_error_report = fec_decoder(input, fec_num_bytes, &lc3_num_bytes, &channel_epmr, decoder->combined_channel_coding, &decoder->n_pccw, &channel_bfi, &decoder->be_bp_left, &decoder->be_bp_right, &decoder->n_pc, &decoder->m_fec, scratch); + + if (chan_error_report < 0 || decoder->error_report < 0) { + decoder->error_report = -1; move16(); + } else { + decoder->error_report = add(decoder->error_report, chan_error_report); + } #ifdef WMOPS pop_wmops(); diff --git a/lib_lc3plus/defines.h b/lib_lc3plus/defines.h index f21d5cf37..24da69b87 100644 --- a/lib_lc3plus/defines.h +++ b/lib_lc3plus/defines.h @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -90,9 +90,129 @@ #ifndef NO_POST_REL_CHANGES /* Post-release non-bitexact changes */ +#define CR13_B_FIX_PC_BINS +#define CR13_C_RESET_CLASSIFIER_AFTER_BAD_FRAMES + +#define CR12_B_STOP_DC_RINGING +#define CR12_D_FIX_BITRATE_LIMITS + +#define CR9_C_ADD_1p25MS + +#ifdef CR9_C_ADD_1p25MS + +#define CR9_C_ADD_1p25MS_LRSNS +#define ENABLE_12p5_DMS_MODE +#define NOISEFILLWIDTH_1_25MS 1 +#define NOISEFILLSTART_1_25MS 6 + +#define CR9_C_ADD_1p25MS_NOISEFILLING +#define CR9_1p25MS_SNS_TILT +#define CR9_1p25MS_SNS_TILT_FIX_DELTA_AD_LINE + +#define PLC34_ATTEN_FAC_125_FX 32752 + +#define LTPF_ADAPTIVE_GAIN + +#ifdef LTPF_ADAPTIVE_GAIN +#define LTPF_PITCH_STABILITY_THRESHOLD 5 /* Number of frames for which the pitch must be constant for adaptive gain and pitch correction to be applied */ +#define LTPF_ADAPTIVE_GAIN_RATE 20 /* Number of frames it must take to reach maximum beta from the default value, provided the pitch remains constant */ + +#define LTPF_ADAPTIVE_GAIN_WITH_NORM_CORR +#endif + +/* master integration fixes for 1p25 */ +#ifdef CR9_C_ADD_1p25MS +#define FIX_BASOP_ENC_QUANTIZE_1P25MS_512KBPS /* add two last MDCT coeffs into the last quadruple for global_gain _xmax_ and energy analysis */ + + +#define FIX_BOTH_1p25_WB_GLOBGAINOFFSET_NONBE /* 1p25 curve tilt calulation corrected and made into BASOP, WB had a loss of of HF in the range 211-260 kbps */ +#define FIX_BOTH_1p25_WB_GLOBGAINOFFSET_LOWLIM_NONBE -135 /* 1p25 curve tilt calulation limited to value -135 kbps */ + +#define FIX_BOTH_1p25_TEST_NEW_GG_EST2 /* GG_EST2_will use bands with two coeffs in each instead of four, for 1p25 WB and 1p25 SSWB , note only active for regular, hrmode==0 */ + +#ifdef FIX_BOTH_1p25_TEST_NEW_GG_EST2 +#define FIX_BASOP_1p25_NEW_GG_EST3 /* GG_EST3 , GG_EST2 with optimized code for better BASOP code reuse , less changes to non 1p25ms */ +#define FIX_BOTH_1p25_GG_EST_SWB_FB /* 1.25ms GG_EST update for SWB/FB, better RD curve float and BASOP , active for hrmode==0 */ +#endif + +/* defines to activate 2 or 3 tuple 1.25ms loops for WB,SSWB,SWB,FB */ +#define FIX_1p25_GG_EST_TUPLES /* 1.25 ms GG_EST2_will use 2,3 or 4 , note only active for regular, hrmode==0 */ +#ifdef FIX_1p25_GG_EST_TUPLES +#define GG_1p25_WB_TUPLES 2 +#define GG_1p25_SSWB_TUPLES 2 +#define GG_1p25_SWB_TUPLES 2 +#define GG_1p25_FB_TUPLES 3 +#define GG_1p25_MAX_TUPLES MAX(MAX(GG_1p25_WB_TUPLES ,GG_1p25_SSWB_TUPLES ), MAX(GG_1p25_SWB_TUPLES ,GG_1p25_FB_TUPLES)) /* used to control common energy loop */ +#define FIX_1p25_32kHz_CLANG_WARNING_EST_GAIN + +#ifndef FIX_BOTH_1p25_ALLOC_SPECTRUM +#define FIX_BOTH_1p25_ALLOC_SPECTRUM +#endif + +#define FIX_1p25_FLEX_ITER_TUPLE_LOOP /* energy loop part optimized BASOP only */ +#define LOG2_LC_APPROX /* log2_LC(energy) call BASOP only */ /* only applied to 1p25 ms global gain estimation loop */ +#define FIX_1p25_FLEX_BISECT_LOOP /* bisect optimization BASOP only !! */ + +#endif + +#define FIX_LTPFDEC_BASOP /* added saturation and apply L_max() */ + +/* all 1p25ms precision optimizations */ + +#define FIX_BASOP_ENC_LRSNS_CBC_MSE /* recalculate CB_C MSE to better match CFL cbC vs st2 decision */ +#define FIX_BASOP_ENC_LRSNS_ST2FULL_PROJ /* less optimistic pre-projection for Y_FULL , better match CFL */ + +#define FIX_BASOP_LT_NORMCORR_AR1 /* better exact representation of 0.8 LT normcorr limit */ +#define FIX_BASOP_PREEMPH_CALC /* only1p25ms higher precision in adaptive preemphasis addition , average increase by ~6dB, minSNR increased by ~1dB */ + +#define FIX_SNS_BASOP_MEAN64_CALC /* norm for all energy bands to reduce SCF target variations before log2 domain */ +#ifdef FIX_SNS_BASOP_MEAN64_CALC +#define FIX_SNS_BASOP_NF_APPL /* apply noisefill 1/10000 in the W32*exp energy domain, not in the inexact 1/9998 W16Q9 log2 domain */ +#endif +#define FIX_SNS_BASOP_MEAN16_APPLY /* norm for all 16 scg log2 bands to reduce SCF target variations */ + +#endif + +#ifdef CR9_C_ADD_1p25MS_LRSNS + /*NB CR9_C_ADD_1p25MS_LRSNS requires NEW_SIGNALLING_SCHEME_1p25 */ +#define LRSNS_PC_SIGNAL_FIX /*correct handling of incoming bfi==2 to DEC_ENTROPY for conformance */ +/* #define USE_LC3_OPERATORS */ + +#define LRSNS_10MS_BFISIGNAL_FIX /* correct signaling of detected BER in both 10ms SNS/and in 1.25ms LRSNS */ + +#define LRSNS_ALLZERO_FIX /* BASOP_Util_InvLog2_pos(), incorrect exponent for 2^0, became appearant for an all zero vector in LRSNS CB_A */ +#define LRSNS_MORE_SCRATCH /* set BASOP SCRATCH to max values */ +/* #define LRSNS_CBC_NO_LTPF_DEPENDENCY */ /* turn off LRSNS CB_C dependency on LTPF activation flag */ + +#define SNSLR_N_FIXENV 4 /* 4 fix envelopes multiplexed inside the full codeword */ +#define SNSLR_N_FIXENV_SHIFTS 4 /* 2 bits */ +#define SNSLR_MAX_PVQ_CAND 6 /* splitLF(0), full(1), fixed_env 2+{0,1,2,3 }, */ +#define SNSLR_MAX_PVQ_SEARCH_CAND (SNSLR_MAX_PVQ_CAND-SNSLR_N_FIXENV+1) /* 3 = splitLF(0), full(1), fixed_envs(2), */ +#define SNS_IDX_SHAPEJ 2 /* shape index location */ + +#endif + + +#define FIX_LTPF_PITCH_1p25 +#define FIX_LTPF_MEM_CONTINUATION +#define FIX_LTPF_PITCH_MEM_LEN +#define FIX_PLC_CONFORM_ISSUES +#define FIX_TDC_BURST_ERROR +#define FIX_LTPF_DEC_FLFX_MISMATCH +#define FIX_TX_RX_STRUCT_STEREO +#define NEW_SIGNALLING_SCHEME_1p25 +#define FIX_LTPF_1p25 + +#endif /* CR9_C_ADD_1p25MS */ #endif /* NO_POST_REL_CHANGES Post-release changes */ +#ifdef CR9_C_ADD_1p25MS +#define LEN_MEM_NORMCORR 5 +#else +#define LEN_MEM_NORMCORR 2 +#endif + #define THRESH_100_DMS_TDC_CNT 9 #define THRESH_100_DMS_NS_CNT 7 #define THRESH_100_DMS_TDC_NS_CNT 73 @@ -129,14 +249,14 @@ #define G192_ONE 0x0081 #define READ_G192FER /* allow C executable to also read G192 formatted FER files */ -#ifdef DEBUG +#ifdef DEBUG #ifdef READ_G192FER -#define READ_G192_FER_BYTE /* Allow C executable to also read G192 byte formatted FER files 0x20=BAD , 0x21=Good */ -#endif -#endif +#define READ_G192_FER_BYTE /* Allow C executable to also read G192 byte formatted FER files 0x20=BAD , 0x21=Good */ +#endif +#endif -// #define DYNMEM_COUNT +// #define DYNMEM_COUNT /* conflicts with WMC tool */ #define STAMEM_COUNT @@ -181,6 +301,11 @@ do not change __forceinline for mex compilation using gcc6.3.0 or larger #define MAX_BR_100DMS_SSWB 314400 /* for 100ms at 24kHz */ #endif +#ifdef CR9_C_ADD_1p25MS +#define MIN_BR_0125DMS 128000 /* 20 * 800 * 100/ 12.5 */ +#define MAX_BR_0125DMS 512000 +#endif + #define MIN_BR_075DMS_48KHZ_HR ((int)124800/ 800/2)* 800 #define MIN_BR_075DMS_96KHZ_HR ((int)149600/ 800/2)* 800 #define MIN_BR_075DMS 21334 /* ceil( 20 * 800 * 100/ 75) */ @@ -220,7 +345,7 @@ do not change __forceinline for mex compilation using gcc6.3.0 or larger #else /* ENABLE_HR_MODE */ #define MAX_RESBITS MAX_LEN #endif /* ENABLE_HR_MODE */ - + /* BW Cutoff-Detection */ #define MAX_BW_BANDS_NUMBER 5 @@ -258,6 +383,18 @@ do not change __forceinline for mex compilation using gcc6.3.0 or larger #define MAX_BW_BIN 400 #define FEC_SLOT_BYTES_MIN 40 #define FEC_SLOT_BYTES_MAX 400 +#ifdef CR12_D_FIX_BITRATE_LIMITS +#ifdef ENABLE_HR_MODE +#define FEC_SLOT_BYTES_MIN_025DMS_48KHZ_HR 54 +#define FEC_SLOT_BYTES_MIN_025DMS_96KHZ_HR 61 +#define FEC_SLOT_BYTES_MIN_050DMS_48KHZ_HR 87 +#define FEC_SLOT_BYTES_MIN_050DMS_96KHZ_HR 101 +#define FEC_SLOT_BYTES_MIN_075DMS_48KHZ_HR 110 +#define FEC_SLOT_BYTES_MIN_075DMS_96KHZ_HR 126 +#define FEC_SLOT_BYTES_MIN_100DMS_48KHZ_HR 140 +#define FEC_SLOT_BYTES_MIN_100DMS_96KHZ_HR 164 +#endif +#endif #if MAX_BW_BIN > MAX_LEN #define MAX_BW MAX_LEN #else @@ -289,6 +426,37 @@ do not change __forceinline for mex compilation using gcc6.3.0 or larger #define SNS_DAMPING_HRMODE_UB_2_5MS 4915 /* 0.15 in Q15 */ #endif +#ifdef CR9_C_ADD_1p25MS_LRSNS +#define N_SCF_SEARCH_SHAPES_ST2_LR SNSLR_MAX_PVQ_SEARCH_CAND /* {split, full, fix} */ +#define NA_LR 5 +#define NB_LR 8 +#define NC_LR 2 /* the 2 remaining positions also coded by full*/ +#define NFULL_LR (NA_LR+NB_LR+NC_LR) + +#define PULSES_SPLIT_A_LR 6 +#define PULSES_SPLIT_B_LR 2 +#define PULSES_FULL_LR 5 /* 'full'== ABC region */ + +#define N_CANDS_FIX_LR SNSLR_N_FIXENV +#define NSIGNS_FIX_012 12 /* 15-4+1 */ +#define N_SHIFT_FIX SNSLR_N_FIXENV_SHIFTS +#define NSIGNS_FIX_3 (NSIGNS_FIX_012 -2) +#define N_SHIFT_FIX_3 SNSLR_N_FIXENV_SHIFTS + + + +#define SNSLR_NST1 170 /*, 3*170 + 2 = 512 */ +#define SNSLR_NPVQ_L5K6 1970 /* mux into 11 bits 2048 pos , 78 slots remaining, 6 whole bits */ +#define SNSLR_NPVQ_L5K8 5890 /* additional split LF part muxed into 13 bits, log2(5980)= 12.5241 */ +#define SNSLR_NPVQ_L8K2 128 /* 1+6 = 7 bits */ +#define SNSLR_NPVQ_L15K5 207006L /* 1+ 16.6593 bits , */ + +#define SNSLR_A_CNST_WEIGHT 28672 /* 0.875 */ + +#define SNS_VQ_MAX_IDX 8 + +#endif /* CR9_C_ADD_LRSNS */ + /* PVQ VQ setup */ #define VQMODES26 \ ((0 << 4) + (1 << 3) + (1 << 2) + (1 << 1) + \ @@ -355,14 +523,14 @@ do not change __forceinline for mex compilation using gcc6.3.0 or larger /* PLC */ #define PLC_FADEOUT_TYPE_1_IN_MS 200 -#define PLC_FADEOUT_IN_MS 60 /* fade-out to zero in ms for TD-PLC and NS, minimum value is 20 */ +#define PLC_FADEOUT_IN_MS 60 /* fade-out to zero in ms for TD-PLC and NS, minimum value is 20 */ /* table settings */ #define PLC2_FADEOUT_IN_MS_MIN 30 /* table min */ #define PLC2_FADEOUT_IN_MS_MAX 140 /* table max */ #define PLC2_FADEOUT_RES 10 /* 10 ms steps used in fade tables */ /* current settings */ -#define PLC2_FADEOUT_LONG_IN_MS 120 +#define PLC2_FADEOUT_LONG_IN_MS 120 #define PLC2_FADEOUT_IN_MS 30 /* 0 uses original constants for PLC2 -1 uses TDC::PLC_FADEOUT_IN_MS as basis for a PLC2 macro-re-calculation 30..140 will use a separate settings for PLC2 fadeout @@ -655,35 +823,58 @@ do not change __forceinline for mex compilation using gcc6.3.0 or larger #define scratchAlign(ptr, offset) (void *)(((uintptr_t)(ptr) + (offset) + 0x3) & ~0x3) + /* some configurations leave empty translation units. */ extern int fix_empty_translation_unit_warning; #define FIX_IVAS_LC3PLUS_DUPLICATES #ifdef FIX_IVAS_LC3PLUS_DUPLICATES -#define Tab_esc_nb Tab_esc_nb_lc3plus -#define POW_ATT_TABLE0 POW_ATT_TABLE0_lc3plus -#define POW_ATT_TABLE1 POW_ATT_TABLE1_lc3plus -#define InvIntTable InvIntTable_lc3plus -#define SineTable320 SineTable320_lc3plus -#define RotVector_320 RotVector_320_lc3plus -#define RotVector_480 RotVector_480_lc3plus -#define SineWindow20 SineWindow20_lc3plus -#define SineWindow40 SineWindow40_lc3plus -#define SineWindow60 SineWindow60_lc3plus -#define SineWindow80 SineWindow80_lc3plus -#define SineWindow120 SineWindow120_lc3plus -#define SineWindow160 SineWindow160_lc3plus -#define SineWindow180 SineWindow180_lc3plus -#define SineWindow320 SineWindow320_lc3plus -#define BASOP_getTables BASOP_getTables_lc3plus -#define ISqrt16 ISqrt16_lc3plus -#define getScaleFactor16 getScaleFactor16_lc3plus -#define Norm32Norm Norm32Norm_lc3plus -#define Scale_sig Scale_sig_lc3plus -#define Copy_Scale_sig Copy_Scale_sig_lc3plus -#define get_size_mpvq_calc_offset_fx get_size_mpvq_calc_offset_fx_lc3plus -#endif - -#define FIX_IVAS_LC3PLUS_WARNINGS - -#endif +#define abs_s_sat abs_s +#define BASOP_cfft BASOP_cfft_lc3plus +#define BASOP_getTables BASOP_getTables_lc3plus +#define BASOP_Util_Add_Mant32Exp BASOP_Util_Add_Mant32Exp_lc3plus +#define BASOP_Util_Cmp_Mant32Exp BASOP_Util_Cmp_Mant32Exp_lc3plus +#define BASOP_Util_Divide1616_Scale BASOP_Util_Divide1616_Scale_lc3plus +#define BASOP_Util_Divide3216_Scale BASOP_Util_Divide3216_Scale_lc3plus +#define BASOP_Util_InvLog2 BASOP_Util_InvLog2_lc3plus +#define BASOP_Util_Log2 BASOP_Util_Log2_lc3plus +#define Copy_Scale_sig Copy_Scale_sig_lc3plus +#define exp2_tab_long exp2_tab_long_lc3plus +#define exp2w_tab_long exp2w_tab_long_lc3plus +#define exp2x_tab_long exp2x_tab_long_lc3plus +#define get_size_mpvq_calc_offset_fx get_size_mpvq_calc_offset_fx_lc3plus +#define getScaleFactor16 getScaleFactor16_lc3plus +#define getScaleFactor32 getScaleFactor32_lc3plus +#define i_mult DEPR_i_mult +#define Inv16 Inv16_lc3plus +#define InvDiffTable InvDiffTable_lc3plus +#define InvIntTable InvIntTable_lc3plus +#define InvTable InvTable_lc3plus +#define ISqrt16 ISqrt16_lc3plus +#define ISqrtDiffTable ISqrtDiffTable_lc3plus +#define ISqrtTable ISqrtTable_lc3plus +#define L_abs_sat L_abs +#define ldCoeff ldCoeff_lc3plus +#define Norm32Norm Norm32Norm_lc3plus +#define POW_ATT_TABLE0 POW_ATT_TABLE0_lc3plus +#define POW_ATT_TABLE1 POW_ATT_TABLE1_lc3plus +#define RotVector_320 RotVector_320_lc3plus +#define RotVector_480 RotVector_480_lc3plus +#define Scale_sig Scale_sig_lc3plus +#define SineTable320 SineTable320_lc3plus +#define SineWindow120 SineWindow120_lc3plus +#define SineWindow160 SineWindow160_lc3plus +#define SineWindow180 SineWindow180_lc3plus +#define SineWindow20 SineWindow20_lc3plus +#define SineWindow30 SineWindow30_lc3plus +#define SineWindow320 SineWindow320_lc3plus +#define SineWindow40 SineWindow40_lc3plus +#define SineWindow60 SineWindow60_lc3plus +#define SineWindow80 SineWindow80_lc3plus +#define Sqrt16 Sqrt16_lc3plus +#define SqrtDiffTable SqrtDiffTable_lc3plus +#define SqrtTable SqrtTable_lc3plus +#define Tab_esc_nb Tab_esc_nb_lc3plus +#define tnsAcfWindow tnsAcfWindow_lc3plus +#endif /* FIX_IVAS_LC3PLUS_DUPLICATES */ +#endif /* DEFINES_H */ diff --git a/lib_lc3plus/detect_cutoff_warped_fx.c b/lib_lc3plus/detect_cutoff_warped_fx.c index a329a48f6..e57723f7b 100644 --- a/lib_lc3plus/detect_cutoff_warped_fx.c +++ b/lib_lc3plus/detect_cutoff_warped_fx.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,10 +7,12 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "functions.h" #include "rom_basop_util_lc3plus.h" -void processDetectCutoffWarped_fx(Word16 *bw_idx, Word32 *d2_fx, Word16 d2_fx_exp, Word16 fs_idx, Word16 frame_dms) +void processDetectCutoffWarped_fx(Word16 *bw_idx, Word32 *d2_fx, Word16 d2_fx_exp, Word16 fs_idx, LC3PLUS_FrameDuration frame_dms) { Dyn_Mem_Deluxe_In( @@ -28,28 +30,39 @@ void processDetectCutoffWarped_fx(Word16 *bw_idx, Word32 *d2_fx, Word16 d2_fx_ex const Word16 *warp_idx_start, *warp_idx_stop, *bw_brickwall_dist; ); + warp_idx_start = 0; + warp_idx_stop = 0; + bw_brickwall_dist = 0; + SWITCH (frame_dms) { - case 25: +#ifdef CR9_C_ADD_1p25MS + case LC3PLUS_FRAME_DURATION_1p25MS: + *bw_idx = fs_idx; move16(); + Dyn_Mem_Deluxe_Out(); + return; +#endif + case LC3PLUS_FRAME_DURATION_2p5MS: warp_idx_start = BW_warp_idx_start_all_2_5ms[fs_idx - 1]; move16(); warp_idx_stop = BW_warp_idx_stop_all_2_5ms[fs_idx - 1]; move16(); bw_brickwall_dist = BW_brickwall_dist_2_5ms; BREAK; - case 50: + case LC3PLUS_FRAME_DURATION_5MS: warp_idx_start = BW_warp_idx_start_all_5ms[fs_idx - 1]; move16(); warp_idx_stop = BW_warp_idx_stop_all_5ms[fs_idx - 1]; move16(); bw_brickwall_dist = BW_brickwall_dist_5ms; BREAK; - case 75: + case LC3PLUS_FRAME_DURATION_7p5MS: warp_idx_start = BW_warp_idx_start_all_7_5ms[fs_idx - 1]; move16(); warp_idx_stop = BW_warp_idx_stop_all_7_5ms[fs_idx - 1]; move16(); bw_brickwall_dist = BW_brickwall_dist_7_5ms; BREAK; - default: /* 100 */ + case LC3PLUS_FRAME_DURATION_10MS: warp_idx_start = BW_warp_idx_start_all[fs_idx - 1]; move16(); warp_idx_stop = BW_warp_idx_stop_all[fs_idx - 1]; move16(); bw_brickwall_dist = BW_brickwall_dist; BREAK; + case LC3PLUS_FRAME_DURATION_UNDEFINED: assert(0); } counter = fs_idx; @@ -75,14 +88,14 @@ void processDetectCutoffWarped_fx(Word16 *bw_idx, Word32 *d2_fx, Word16 d2_fx_ex iBand++; FOR (; iBand <= warp_idx_stop[counter]; iBand++) { - d2_fx_sum = BASOP_Util_Add_Mant32Exp_lc3plus(d2_fx[iBand], d2_fx_exp, d2_fx_sum, d2_fx_sum_exp, &d2_fx_sum_exp); + d2_fx_sum = BASOP_Util_Add_Mant32Exp(d2_fx[iBand], d2_fx_exp, d2_fx_sum, d2_fx_sum_exp, &d2_fx_sum_exp); } /* Energy-sum */ d2_fx_mean = Mpy_32_16_lc3plus(d2_fx_sum, InvIntTable[add(sub(warp_idx_stop[counter], warp_idx_start[counter]), 1)]); d2_fx_mean_exp = d2_fx_sum_exp; move16(); /* check if above threshold */ - nrg_below_thresh = BASOP_Util_Cmp_Mant32Exp_lc3plus(BW_thresh_quiet[counter], BW_thresh_quiet_exp, d2_fx_mean, + nrg_below_thresh = BASOP_Util_Cmp_Mant32Exp(BW_thresh_quiet[counter], BW_thresh_quiet_exp, d2_fx_mean, d2_fx_mean_exp); /* true if firstNumber > secondNumber */ } WHILE (nrg_below_thresh > 0) diff --git a/lib_lc3plus/dynmem.c b/lib_lc3plus/dynmem.c index 9756b123b..9cdac738d 100644 --- a/lib_lc3plus/dynmem.c +++ b/lib_lc3plus/dynmem.c @@ -19,6 +19,8 @@ #define _CRT_SECURE_NO_WARNINGS #endif +#include "options.h" +#include "wmc_auto.h" #include #include #include diff --git a/lib_lc3plus/enc_entropy.c b/lib_lc3plus/enc_entropy.c index c4930fd16..4afac13a4 100644 --- a/lib_lc3plus/enc_entropy.c +++ b/lib_lc3plus/enc_entropy.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,6 +7,8 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "functions.h" static Word32 ac_enc_mux_st2VQ_cws( /* o: max 25 bits total codeword */ @@ -17,7 +19,11 @@ static Word32 ac_enc_mux_st2VQ_cws( /* o: max 25 bits total void processEncoderEntropy(UWord8 *bytes, Word16 *bp_side, Word16 *mask_side, Word16 nbbits, Word16 targetBytes, Word16 L_spec, Word16 BW_cutoff_bits, Word16 tns_numfilters, Word16 lsbMode, Word16 lastnz, Word16 *tns_order, Word16 fac_ns_idx, Word16 gg_idx, - Word16 BW_cutoff_idx, Word16 *ltpf_idx, Word32 *L_scf_idx, Word16 bfi_ext, Word16 fs_idx) + Word16 BW_cutoff_idx, Word16 *ltpf_idx, Word32 *L_scf_idx, Word16 bfi_ext, Word16 fs_idx +#ifdef CR9_C_ADD_1p25MS + , LC3PLUS_FrameDuration frame_dms, Word16* Tx_ltpf +#endif + ) { Word16 tmp; Word32 L_tmp; @@ -42,6 +48,8 @@ void processEncoderEntropy(UWord8 *bytes, Word16 *bp_side, Word16 *mask_side, Wo Dyn_Mem_In("processEncoderEntropy", sizeof(struct _dynmem)); #endif + UNUSED(L_gain_LSB); UNUSED(gain_MSBs); UNUSED(submode_MSB); UNUSED(submode_LSB); UNUSED(L_tmp); + /* Init */ *bp_side = shr_pos(sub(nbbits, 1), 3); *mask_side = shl(1, sub(8, sub(nbbits, shl_pos(*bp_side, 3)))); @@ -56,7 +64,7 @@ void processEncoderEntropy(UWord8 *bytes, Word16 *bp_side, Word16 *mask_side, Wo } /* Encode last non-zero tuple */ - tmp = sub(14, norm_s(negate(L_spec))); + tmp = getLastNzBits_fx(L_spec); IF (sub(bfi_ext, 1) == 0) { @@ -80,8 +88,25 @@ void processEncoderEntropy(UWord8 *bytes, Word16 *bp_side, Word16 *mask_side, Wo } /* LTPF on/off*/ +#ifdef CR9_C_ADD_1p25MS +#ifdef NEW_SIGNALLING_SCHEME_1p25 + IF( sub(frame_dms, LC3PLUS_FRAME_DURATION_1p25MS) == 0 ) + { + writeLtpData_fx(ptr, bp_side, mask_side, ltpf_idx, Tx_ltpf); /* LTP-flag and LTPFflag and interleaved lag */ + } + ELSE + { + write_bit_backward(ptr, bp_side, mask_side, ltpf_idx[0]); /* LTP-flag only */ + } +#endif +#else write_indice_backward(ptr, bp_side, mask_side, ltpf_idx[0], 1); +#endif +#ifdef CR9_C_ADD_1p25MS_LRSNS + /* Encode SCF VQ parameters */ + writeSNSData_fx(bytes, bp_side, mask_side, frame_dms, L_scf_idx); +#else /* Encode SCF VQ parameters - 1st stage (10 bits) */ write_indice_backward(ptr, bp_side, mask_side, extract_l(L_scf_idx[0]), 5); /* stage1 LF 5 bits */ write_indice_backward(ptr, bp_side, mask_side, extract_l(L_scf_idx[1]), 5); /* stage1 HF 5 bits */ @@ -135,14 +160,22 @@ void processEncoderEntropy(UWord8 *bytes, Word16 *bp_side, Word16 *mask_side, Wo write_indice_backward(ptr, bp_side, mask_side, extract_l(L_tmp), 12); /* multiplex 12 bits LSB*/ write_indice_backward(ptr, bp_side, mask_side, extract_l(L_shr(L_tmp, 12)), 12); /* multiplex 12 bits MSBs */ } +#endif /* LTPF data */ - IF (ltpf_idx[0] != 0) +#ifdef NEW_SIGNALLING_SCHEME_1p25 + test(); test(); + IF( (sub(frame_dms, LC3PLUS_FRAME_DURATION_1p25MS) != 0) && (ltpf_idx[0] != 0) ) +#else + test(); + IF( ltpf_idx[0] != 0 ) +#endif { - write_indice_backward(ptr, bp_side, mask_side, ltpf_idx[1], 1); - write_indice_backward(ptr, bp_side, mask_side, ltpf_idx[2], 9); + write_indice_backward(ptr, bp_side, mask_side, ltpf_idx[1], 1); + write_indice_backward(ptr, bp_side, mask_side, ltpf_idx[2], 9); } + /* Encoder noise-fac */ write_indice_backward(ptr, bp_side, mask_side, fac_ns_idx, 3); @@ -171,3 +204,335 @@ ac_enc_mux_st2VQ_cws( /* o: max 25 bits total codeword */ return L_cwTx; } + +#ifdef NEW_SIGNALLING_SCHEME_1p25 +void writeLtpData_fx( + UWord8 *ptr, + Word16 *bp_side, + Word16 *mask_side, + Word16* ltpf_idx, + Word16* Tx_ltpf +) +{ + Dyn_Mem_Deluxe_In( + Word16 tmp; + Word16 bitsTx;); + + tmp = s_min(*Tx_ltpf, 1); /*phaseA==0, phaseB==1*/ + test(); + IF(ltpf_idx[0] == 0) + { + write_indice_backward(ptr, bp_side, mask_side, 0, 2); /* "00" */ + + *Tx_ltpf = 0; + /* *Tx_ltpf A/B state forced to zero or kept at zero */ + /* decoder will discard any sofar in phase received phaseA MSB bits */ + } + ELSE IF(ltpf_idx[1] == 0) + { + /* no current LTPF activation, + lag transmitted for PLC, or for next frame LTPF activation */ + ASSERT(ltpf_idx[0] != 0); + + /* A "010" 3 bits Hdr transmitted */ + /* B "011" 3 bits Hdr transmitted*/ + + write_indice_backward(ptr, bp_side, mask_side, 1, 2); /* "01"*/ + write_indice_backward(ptr, bp_side, mask_side, tmp, 1); /* phase A or phaseB */ + + test(); + IF(*Tx_ltpf == 0) + { /* phase A transmission */ + ASSERT(tmp == 0); + ASSERT((ltpf_idx[2] & ~(0x01ff)) == 0); /* only 9 bits info allowed within ltpf_idx[2] */ + tmp = shr_pos(ltpf_idx[2], 5); /* shift_out LSBS, send 4 MSBs */ + *Tx_ltpf = s_or(0x200, ltpf_idx[2]); move16(); /* remember full lag, as phaseB sentinel in bit 10, */ + } + ELSE + { /* phase B */ + ASSERT(tmp == 1); + ASSERT(*Tx_ltpf > 511); /*sentinel in b10 should have been set in previous phaseA frame */ + tmp = shr_pos(s_and(*Tx_ltpf, 0x001f), 1); /* B send 4* LSBs, 1 bit truncated */ + *Tx_ltpf = 0; move16(); /* clear sentinel in b10 and the old remebered lag value */ + } + write_indice_backward(ptr, bp_side, mask_side, tmp, 4); /* 4 bits lag info Tx, when LTPF is deactivated */ + } + ELSE + { /* LTPF activated */ + /* A "10" 2 bits Hdr */ + /* B "11" 2 bits Hdr */ + ASSERT(ltpf_idx[0] != 0 && ltpf_idx[1] != 0); + + tmp = s_or(0x02, tmp); + write_indice_backward(ptr, bp_side, mask_side, tmp, 2); + test(); + IF(*Tx_ltpf == 0) + { + bitsTx = 4; move16(); + ASSERT((ltpf_idx[2] & ~(0x01ff)) == 0); /* only 9 bits info allowed within ltpf_idx[2] */ + tmp = shr_pos(ltpf_idx[2], 5); /* shift away 5 LBS, LTPF active, send phaseA 4 MSBs */ + + *Tx_ltpf = s_or(0x0200, ltpf_idx[2]); /* remember full lag in state *Tx_ltpf, add phaseB Tx state sentinel in bit 10 */ + } + ELSE + { + bitsTx = 5; move16(); + tmp = s_and(*Tx_ltpf, 0x001f); /* LTPF active B send 5 LSBs , full regular resolution */ + *Tx_ltpf = 0; move16(); /* clear sentinel in b10 and also the old remebered lag value */ + } + + write_indice_backward(ptr, bp_side, mask_side, tmp, bitsTx); /* ltp==1 , ltpf==1, 4(A,MSBs) or 5(b, LSBs) bits */ + } + Dyn_Mem_Deluxe_Out(); +} + + +void writeSNSData_fx(UWord8 *bytes, Word16 *bp_side, Word16 *mask_side, LC3PLUS_FrameDuration frame_dms, Word32* L_scf_idx) +{ + Dyn_Mem_Deluxe_In( + Word16 submode_LSB, submode_MSB, gain_MSBs; + Word32 L_gain_LSB; + Word16 write_legacy_sns_vq_bits; + Word16 tmp; + Word32 L_tmp; + Word16 aux_idx; /* aux value: location the LS, or the s0 sign bit */ + Word16 shape_idx; /* st2 shape 0 .. 5 , where [2.3.4.5] are fixed FESS shapes */ + Word16 fixenv_shape_idx; + Word16 gain_idx; /* idx of 2-3 bits valued gains */ + Word16 n5k; /* number of unit pulses k for the width N=5 LF region of splitLF */ + ); + + write_legacy_sns_vq_bits = 1; + if (sub(frame_dms, LC3PLUS_FRAME_DURATION_1p25MS) == 0) /* 9,10,29/30 */ + { + write_legacy_sns_vq_bits = 0; + } + + test(); + IF(write_legacy_sns_vq_bits != 0) /* 10 bits (5+5) for stage1 + a total of 28 bits for stage2 */ + { + /* Encode SCF VQ parameters - 1st stage (10 bits) */ + write_indice_backward(bytes, bp_side, mask_side, extract_l(L_scf_idx[0]), 5); /* stage1 LF 5 bits */ + write_indice_backward(bytes, bp_side, mask_side, extract_l(L_scf_idx[1]), 5); /* stage1 HF 5 bits */ + + /* Encode SCF VQ parameters - 2nd stage side-info (3-4 bits) */ + submode_MSB = shr_pos(extract_l(L_scf_idx[2]), 1); /* explicit tx */ + write_bit_backward(bytes, bp_side, mask_side, submode_MSB); /* submode MSB 1 explicit bit */ + submode_LSB = s_and(extract_l(L_scf_idx[2]), 0x1); /* for joint coding with shapeCw */ + gain_MSBs = extract_l(L_scf_idx[3]); /* all gain bits */ + L_gain_LSB = L_and(L_scf_idx[3], 0x1L); + gain_MSBs = shr(gain_MSBs, sns_gainLSBbits[L_scf_idx[2]]); + + ASSERT(gain_MSBs >= 0 && gain_MSBs < (1 << sns_gainMSBbits[L_scf_idx[2]])); /* ASSERT max 2 MSB(s) in gain bits */ + + write_indice_backward(bytes, bp_side, mask_side, gain_MSBs, + sns_gainMSBbits[L_scf_idx[2]]); /* adjgain or MSBs of adjGains 1-2 bits */ + write_bit_backward(bytes, bp_side, mask_side, extract_l(L_scf_idx[4])); /* shape LS 1 bit */ + + /* Encode SCF VQ parameters - 2nd stage data (24-25 bits) */ + test(); + IF(submode_MSB == 0) + { /* regular,regular_lf*/ + ASSERT(submode_MSB == 0); + + L_tmp = L_add(L_gain_LSB, 0); /* gain-LSB 0,1 for regular_lf, offset is 0 */ + if (submode_LSB == 0) + { + L_tmp = L_add(L_scf_idx[6], + sns_MPVQ_Sz[1][1]); /* shape B pos offset is 2 , upshifted two positions , 0..11 -> 2..13 */ + } + /* regular mode A,B indexes multiplexed, total 24.x bits MPVQ codeword section A + codeword for section B */ + L_tmp = ac_enc_mux_st2VQ_cws(sns_MPVQ_Sz[0][0], /* max 21.3 bits*/ + UL_addNsD(sns_MPVQ_Sz[0][1], sns_MPVQ_Sz[1][1]), /* max log2(14) bits */ + L_scf_idx[5] /* shapeA */, L_tmp /* shapeB joint with adjGainLSB */); + /* regular mode mode shape index total 1+23.9999 bits MPVQ codeword */ + ASSERT(L_tmp < (1L << 25)); + write_indice_backward(bytes, bp_side, mask_side, extract_l(L_tmp), 13); /* multiplex 13 bits */ + write_indice_backward(bytes, bp_side, mask_side, extract_l(L_shr_pos(L_tmp, 13)), 12); /* multiplex 12 bits */ + } + ELSE + { /* outlier near, outlier far */ + ASSERT(submode_MSB == 1); + L_tmp = L_scf_idx[5]; + move32(); /* outlier near section assumed */ + if (submode_LSB != 0) + { /* outl_far */ + L_tmp = L_add(L_shl_pos(L_tmp, 1), L_gain_LSB); /* add lsb bit of Gain */ + L_tmp = L_add(L_tmp, sns_MPVQ_Sz[2][0]); /* outlier far section offset added */ + } + + ASSERT(L_tmp < (1L << 24)); + /* outlier mode shape index total 23.8536 ( + ~.14 ) bits as MPVQ codeword */ + write_indice_backward(bytes, bp_side, mask_side, extract_l(L_tmp), 12); /* multiplex 12 bits LSB*/ + write_indice_backward(bytes, bp_side, mask_side, extract_l(L_shr(L_tmp, 12)), 12); /* multiplex 12 bits MSBs */ + } + } + + test(); + IF(write_legacy_sns_vq_bits == 0) /* 9 or 10 bits for stage1, 19-20 bits for stage2 */ + { + /* SNS-VQ 1st stage is jointly multiplexed into 9 bits or 10 bits */ + /* input scf_idx[0], has the stage1 index for one of BCA , if B+stage 1 only */ + tmp = extract_l(L_scf_idx[0]); + aux_idx = extract_l(L_scf_idx[1]); /* aux value: we have the LS, or the s0 sign bit */ + shape_idx = extract_l(L_scf_idx[2]); /* st2 shape 0 .. 5 , where [2.3.4.5] are fixed FESS shapes */ + gain_idx = extract_l(L_scf_idx[3]); /* idx of 2-3 bits valued gains */ + +#ifdef DEBUG + if (shape_idx == 0 && L_scf_idx[0] >= 0) + { /*aux==2 --> split mode st1B (aux==2), + a 2 bit gain + P(5,6)10.96b + P(8,2)7b */ + ASSERT(shape_idx == 0 && gain_idx < 4); + } + if ((shape_idx == 1) && L_scf_idx[0] >= 0) + { /* regular mode st1B , + a 3 bit gain + P(15,5) */ + ASSERT(shape_idx == 1 && gain_idx >= 0 && gain_idx < 8); + } + + if ((shape_idx >= 2) && L_scf_idx[0] >= 0) + { /* regular mode st1B , + a 3 bit gain + fixenv */ + ASSERT(shape_idx >= 2 && shape_idx <= 5 && gain_idx >= 0 && gain_idx < 8); + } +#endif + /* b0-b8 b9 + segm , idx9b , stop bit, comment use + -----+--------+--------- + A | 510,511| n/a, 2 entries, 9 bit total + ------+--------+-------- + B | 0--169 | 1 , 170 entries, 10 bit total + ------+--------+-------- + C | 170-339| 1 , 170 entries, 10 bit total + ------+--------+--------+------------*/ + + test(); test(); test(); test(); + IF(L_sub(L_scf_idx[0], 510) >= 0) + { /* stage1A */ + ASSERT(L_scf_idx[0] < (1 << 9)); + write_indice_backward(bytes, bp_side, mask_side, tmp, 9); /* writes values 510 or 511 */ + shape_idx = -9; move16(); /* use only the coarse stage 1A , no more bits to send */ + } + ELSE IF((sub(tmp, 2 * 170) < 0) && (shape_idx < 0)) + { + write_indice_backward(bytes, bp_side, mask_side, tmp, 9); /* 1B [ 0..169] or 1C [ 170 ... 339 ] */ + + /* write the stop bit sentinel value "1", so that the demux dec_entropy_fx) can stop already at (9+1)=10 bits */ + write_indice_backward(bytes, bp_side, mask_side, 1, 1); /* dec_entropy_fx() will read this a 1 "stop" bit */ + shape_idx = -10; move16(); + } + ELSE IF(shape_idx == 0) { + /* aux info as a part of (9+1) 10 initial bits */ + /* b0-b8 b9 + segm , idx9b , stop bit, comment use + -----+--------+--------- + B* | 0--169 | 0 , --> aux=0, 170, 2b+17b for stage2 'LR_SplitLF', 29 bit total + ------+--------+--------+------- + B* | 170-339| 0 , --> aux=1, 170, 2b+17b for stage2 'LR_SplitLF', 29 bit total + ------+--------+--------+------- + */ + /* 29 bit total LR_splitLF */ +#ifdef DEBUG + ASSERT(L_scf_idx[0] >= 0 && L_scf_idx[0] < 170); /* st1B range */ + ASSERT(aux_idx >= 0 && aux_idx <= 1); /* aux_bit can only be 1 or 0 */ +#endif + write_indice_backward(bytes, bp_side, mask_side, extract_l(L_mac0(L_scf_idx[0], aux_idx, 170)), 9); /* aux_bit defined by region 0.169 or 170..339 in decoder */ + write_indice_backward(bytes, bp_side, mask_side, 0, 1); /* "stop" bit. always zero for 'LR_splitLF' path */ + + write_indice_backward(bytes, bp_side, mask_side, gain_idx, 2); /* always 2bits == 4 gain levels for the splitLF mode */ + + n5k = 6; move16(); + test(); + if (L_scf_idx[5] < 0) + { + ASSERT(L_scf_idx[5] == -8); + n5k = 8; move16(); /* 8 LF pulses , no HF pulses */ + } + + test(); + IF(sub(n5k, 6) == 0) + { /* multiplex remaining 10 + 1+6 bit */ + write_indice_backward(bytes, bp_side, mask_side, extract_l(L_scf_idx[4]), 10); /* P(5,6)=10.94 in LS+10 bits, */ + write_indice_backward(bytes, bp_side, mask_side, extract_l(L_and(L_scf_idx[5], 0x1)), 1); /* LS for P(8,2)=7 */ + write_indice_backward(bytes, bp_side, mask_side, extract_l(L_shr_pos(L_scf_idx[5], 1)), 6); /* mPVQ(8,2) in 6 */ + } + ELSE + { /* LF is PVQ(N=5,K=8), HF is all zero , multiplexed as top section in stage2 10b , + 7b */ + /* scf_idx[4] is in the range [0 ... (SNSLR_NPVQ_L5K8 >>1)[, [0 .. 2945[ , 11.52 bits */ + /* 985 - 1024 = 39 entries where we now use 32 (5 bits) */ + /* index_to_send = (SNSLR_NPVQ_L5K6 >> 1) + (scf_idx[4] & 0x001f) , range [985 .. 1017[ , i.e. 7 values are not sent:[1018 ... 1023] */ + ASSERT(L_scf_idx[4] < (SNSLR_NPVQ_L5K8 >> 1)); + write_indice_backward(bytes, bp_side, mask_side, extract_l(L_add((SNSLR_NPVQ_L5K6 >> 1), L_and(L_scf_idx[4], 0x001f))), 10); /* 5 lsb's as top in the 10b block*/ + ASSERT((L_scf_idx[4] >> 5) < (1 << 7)); + write_indice_backward(bytes, bp_side, mask_side, extract_l(L_shr_pos(L_scf_idx[4], 5)), 7); /* 7 msb's of mpvq(5,8)*/ + /* unused region of 7*2^7 = 1792= 10.8 bits may be used for BER detection */ + } + } + ELSE IF(shape_idx == 1) + { + /* b0-b8 b9 + segm , idx9b , stop bit, comment/use + ------+--------+--------+------------ + B* | 340-509| 1 --> aux=1, 170, 3b+17b for stage2 'LR_full', 30 bit total + ------+--------+--------+------- + B* | 340-509| 0 --> aux=0, 170, 3b+17b for stage2 'LR_full', 30 bit total + ------+--------+--------+------- + */ + ASSERT(L_scf_idx[0] >= 0 && L_scf_idx[0] < 170); /* validate st1B* range */ + + write_indice_backward(bytes, bp_side, mask_side, add(tmp, 2 * 170), 9); /* stage1B* signal */ + write_indice_backward(bytes, bp_side, mask_side, aux_idx, 1); /* auxbit value transmitted in the stop bit location */ + + write_indice_backward(bytes, bp_side, mask_side, gain_idx, 3); /* 30b always 8 gain levels in 3 bits for the full mode */ + /* the next 17 bit index is used to decode submode 1==full or one of submode 2,3,4,5 == fix */ + ASSERT(L_scf_idx[4] >= 0 && L_scf_idx[4] < ((SNSLR_NPVQ_L15K5 >> 1))); + + L_tmp = L_scf_idx[4]; move32(); /* full 17 bit index */ + /* typically P(15,5) without the leading sign, 16.6593 bits, written */ + /* subset of 7 lsb's written first to match Cflt writing of all 17 bits at once */ + write_indice_backward(bytes, bp_side, mask_side, extract_l(L_tmp), 17 - 10); + write_indice_backward(bytes, bp_side, mask_side, extract_l(L_shr_pos(L_tmp, 7)), 10); + } + ELSE + { /* Fixed shapes 2(fixenv0) and 3(fixenv1) , 4(fixenv2), 5(fixenv3) */ + ASSERT(shape_idx >= 2 && shape_idx <= 5); + /* fixenv 0,1,2, : s0(in aux) + shift(2bits)+ 11 signs , section size 8192 + fixenv 3 : s0(in aux) + shift(2bits)+ 9 signs , section size 2048 + */ + fixenv_shape_idx = extract_l(L_scf_idx[4]); + ASSERT(fixenv_shape_idx == (shape_idx - 2)); /* scf_idx[4] has the fixed env index*/ + ASSERT(L_scf_idx[0] >= 0 && L_scf_idx[0] < 170); /* validate st1B* range */ + + write_indice_backward(bytes, bp_side, mask_side, add(tmp, 2 * 170), 9); /* stage1B* signal */ + write_indice_backward(bytes, bp_side, mask_side, aux_idx, 1); /* auxbit transmitted in the stop bit location */ + + write_indice_backward(bytes, bp_side, mask_side, gain_idx, 3); /* for this 30bit path it is always 3 gain bits */ + + IF(sub(shape_idx, 5) < 0) /* 2,3,4 */ + { + ASSERT(L_scf_idx[5] >= 0 && L_scf_idx[5] < (1 << 13)); + ASSERT((SNSLR_NPVQ_L15K5 >> 1) + fixenv_shape_idx * (1 << 13) + L_scf_idx[5] < (1 << 17)); + /* offset is PVQ(15,5) without leading sign */ + /* int32_t tmp_idx = (SNSLR_NPVQ_L15K5 >> 1) + env_shape_idx * (1 << 13) + scf_idx[5]; */ + L_tmp = L_add(L_mac0((SNSLR_NPVQ_L15K5 >> 1), fixenv_shape_idx, 1 << 13), L_scf_idx[5]); /* full 17 bits*/ + } + ELSE + { + ASSERT(shape_idx == 5); /* 5*/ + ASSERT(fixenv_shape_idx == 3); + ASSERT(L_scf_idx[5] < (1 << 11)); + ASSERT(((SNSLR_NPVQ_L15K5 >> 1) + 3 * (1 << 13) + L_scf_idx[5]) < (1 << 17)); + /* offset is PVQ(15,5) without leading sign */ + L_tmp = L_add((SNSLR_NPVQ_L15K5 >> 1) + 3 * (1 << 13), L_scf_idx[5]); /* full 17 bits*/ + } + /* subset of 7 lsb's written first to match Cflt writing of all 17 bits at once */ + write_indice_backward(bytes, bp_side, mask_side, extract_l(L_tmp), 17 - 10); + write_indice_backward(bytes, bp_side, mask_side, extract_l(L_shr_pos(L_tmp, 7)), 10); + } + } + Dyn_Mem_Deluxe_Out(); +} +#endif /* CR9_C_ADD_1p25MS_LRSNS */ + + + +#ifdef __cplusplus +} /* NAMESPACE_VERSION */ +#endif diff --git a/lib_lc3plus/enc_lc3.c b/lib_lc3plus/enc_lc3plus.c similarity index 76% rename from lib_lc3plus/enc_lc3.c rename to lib_lc3plus/enc_lc3plus.c index a5b8fabfd..2658ac6bb 100644 --- a/lib_lc3plus/enc_lc3.c +++ b/lib_lc3plus/enc_lc3plus.c @@ -1,14 +1,15 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * * Rights Policy, 3rd April 2019. No patent licence is granted by implication, * * estoppel or otherwise. * ******************************************************************************/ - +#include "options.h" +#include "wmc_auto.h" +#include #include "functions.h" -#include // ToDo: probably to be removed static void Enc_LC3PLUS_Channel(LC3PLUS_Enc *encoder, int channel, int bits_per_sample, Word32 *s_in, UWord8 *bytes, Word8 *scratchBuffer, int bfi_ext) @@ -36,7 +37,7 @@ static void Enc_LC3PLUS_Channel(LC3PLUS_Enc *encoder, int channel, int bits_per_ Word32 * s_in_scaled; Word16 * s_in_scaled_lp; UWord8 * resBits; - Word16 ltpf_idx[3]; + Word16 ltpf_idx[3]; EncSetup * h_EncSetup; Word8 * currentScratch; Word16 hrmode; @@ -52,13 +53,54 @@ static void Enc_LC3PLUS_Channel(LC3PLUS_Enc *encoder, int channel, int bits_per_ Word16 * scf, *scf_q; Word16 * codingdata; Word16 * s_in_scaled; UWord8 * resBits; Word8 * currentScratch; Word16 ltpf_idx[3]; EncSetup * h_EncSetup;); #endif /* ENABLE_HR_MODE */ - + +#ifdef CR9_C_ADD_1p25MS_LRSNS + Word16 envelope_bits_fx; + Word16 pitch_rx_fx; + Word16 ltpf_rx_fx; + Word16 lrsns_st1C_in_use ; + Word16 ltptx_lowest_bit_lim; +#endif + +#ifdef CR9_C_ADD_1p25MS_LRSNS + envelope_bits_fx = -1; /*later move up to Dynmem() struct area */ +#endif h_EncSetup = encoder->channel_setup[channel]; - -#ifdef ENABLE_HR_MODE + +#ifdef ENABLE_HR_MODE hrmode = encoder->hrmode; #endif + +#ifndef FIX_1p25_GG_EST_TUPLES + +#if defined (FIX_BASOP_ENC_QUANTIZE_1P25MS_512KBPS) + /* make sure the initial allocated d_fx buffer size is a multiple of 4 */ + /* ms_mode Fs frame_length frame_ylen misc */ + /* 1.25ms 16 kHz 20/2=10 same 2-tuples */ + /* 1.25ms 24kHz 30/2=15 same 2-tuples action in estimate_global_gain() */ + /* 1.25ms 32kHz 40/2=10 same 2-tuples */ + /* 1.25ms 48kHz 60/3=20 50/3=16.66 3-tuples, 60/3 =15 allocated , separate action in estimate_global_gain(), 50==60*40/48 */ + /* 2.5 ms 8 kHz 20/4=5 same 4-tuples */ + + Word16 lg_4 = shr(encoder->frame_length, 2); + Word16 rem_4 = sub(encoder->frame_length, shl(lg_4, 2)); + if (rem_4 != 0 && sub(encoder->frame_length, encoder->yLen) == 0) + { + lg_4 = add(lg_4, 1); /* add one quadruple */ + ASSERT(encoder->frame_dms == LC3PLUS_FRAME_DURATION_1p25MS); + ASSERT(MAX_LEN >= lg_4 * 4 ); /* "en" size in estimate_global_gain_fx() */ + } +#ifdef FIX_BASOP_1p25_NEW_GG_EST3 + if(encoder->frame_dms == LC3PLUS_FRAME_DURATION_1p25MS && (sub(encoder->frame_length, 30) <= 0)) /* WB and SSWB */ + { + ASSERT(MAX_LEN >= 2 + lg_4 * 4); /*make sure that there are 2 extra tail coeffs in d_fx*/ + } +#endif +#endif +#endif + + #ifdef WMOPS push_wmops("Encoder"); #endif @@ -67,6 +109,14 @@ static void Enc_LC3PLUS_Channel(LC3PLUS_Enc *encoder, int channel, int bits_per_ d_fx = scratchAlign(scratchBuffer, 0); /* Size = 4 * MAX_LEN bytes */ L_scf_idx = scratchAlign( d_fx, sizeof(*d_fx) * s_max(80, encoder->frame_length)); /* Size = 4 * SCF_MAX_PARAM -> aligned to 32 bytes */ + +#ifdef FIX_1p25_GG_EST_TUPLES + if (encoder->frame_dms == LC3PLUS_FRAME_DURATION_1p25MS) + { + ASSERT(MAX(80, encoder->frame_length) >= ((GG_1p25_MAX_TUPLES - 1) + encoder->yLen)); + /*make sure that there are extra tail coeffs in d_fx for Global gain estimation routine */ + } +#endif indexes = scratchAlign(L_scf_idx, sizeof(*L_scf_idx) * SCF_MAX_PARAM); /* Size = 2 * TNS_NUMFILTERS_MAX * MAXLAG = 32 bytes */ @@ -75,7 +125,7 @@ static void Enc_LC3PLUS_Channel(LC3PLUS_Enc *encoder, int channel, int bits_per_ #else q_d_fx16 = scratchAlign(indexes, sizeof(*indexes) * (TNS_NUMFILTERS_MAX * MAXLAG)); /* Size = 2 * MAX_LEN bytes */ #endif /* ENABLE_HR_MODE */ - + #ifdef ENABLE_HR_MODE codingdata = scratchAlign(q_d_fx24, sizeof(*q_d_fx24) * s_max(80, encoder->frame_length)); /* Size = 3 * MAX_LEN bytes */ @@ -83,7 +133,7 @@ static void Enc_LC3PLUS_Channel(LC3PLUS_Enc *encoder, int channel, int bits_per_ codingdata = scratchAlign(q_d_fx16, sizeof(*q_d_fx16) * s_max(80, encoder->frame_length)); /* Size = 3 * MAX_LEN bytes */ #endif - + #ifdef ENABLE_HR_MODE ener_fx = scratchAlign(q_d_fx24, 0); /* Size = 4 * MAX_BANDS_NUMBER = 256 bytes */ s_in_scaled = scratchAlign(q_d_fx24, 0); /* Size = 2 * MAX_LEN bytes */ @@ -91,7 +141,7 @@ static void Enc_LC3PLUS_Channel(LC3PLUS_Enc *encoder, int channel, int bits_per_ ener_fx = scratchAlign(q_d_fx16, 0); /* Size = 4 * MAX_BANDS_NUMBER = 256 bytes */ s_in_scaled = scratchAlign(q_d_fx16, 0); /* Size = 2 * MAX_LEN bytes */ #endif - + #ifdef ENABLE_HR_MODE s_in_scaled_lp = (Word16 *)s_in_scaled; #endif @@ -166,7 +216,7 @@ static void Enc_LC3PLUS_Channel(LC3PLUS_Enc *encoder, int channel, int bits_per_ /* currentScratch Size = 4 * MAX_LEN */ processMdct_fx(s_in_scaled, h_EncSetup->x_exp, encoder->frame_length, #ifdef ENABLE_HR_MODE - hrmode, + hrmode, #endif encoder->W_fx, encoder->W_size, h_EncSetup->stEnc_mdct_mem, encoder->stEnc_mdct_mem_len, d_fx, &d_fx_exp, currentScratch); @@ -181,7 +231,7 @@ static void Enc_LC3PLUS_Channel(LC3PLUS_Enc *encoder, int channel, int bits_per_ /* currentScratch Size = 2.25 * MAX_LEN bytes */ #ifdef ENABLE_HR_MODE downshift_w32_arr(s_in_scaled, s_in_scaled_lp, 16, encoder->frame_length); /* s_in_scaled is no longer required */ - + process_resamp12k8_fx(s_in_scaled_lp, encoder->frame_length, h_EncSetup->r12k8_mem_in, encoder->r12k8_mem_in_len, h_EncSetup->r12k8_mem_50, h_EncSetup->r12k8_mem_out, encoder->r12k8_mem_out_len, s_12k8, &s_12k8_len, encoder->fs_idx, encoder->frame_dms, currentScratch @@ -203,7 +253,7 @@ static void Enc_LC3PLUS_Channel(LC3PLUS_Enc *encoder, int channel, int bits_per_ #endif /* currentScratch Size = 392 bytes */ process_olpa_fx(&h_EncSetup->olpa_mem_s6k4_exp, h_EncSetup->olpa_mem_s12k8, h_EncSetup->olpa_mem_s6k4, &pitch, - s_12k8, s_12k8_len, &normcorr, &h_EncSetup->olpa_mem_pitch, + s_12k8, s_12k8_len, &normcorr, &h_EncSetup->olpa_mem_pitch, &h_EncSetup->pitch_flag, h_EncSetup->resamp_exp, encoder->frame_dms, currentScratch); #ifdef WMOPS @@ -216,10 +266,22 @@ static void Enc_LC3PLUS_Channel(LC3PLUS_Enc *encoder, int channel, int bits_per_ /* currentScratch Size = 512 bytes */ process_ltpf_coder_fx(<pf_bits, pitch, h_EncSetup->ltpf_enable, &h_EncSetup->ltpf_mem_in_exp, h_EncSetup->ltpf_mem_in, encoder->ltpf_mem_in_len, ltpf_idx, s_12k8, s_12k8_len, - &h_EncSetup->ltpf_mem_normcorr, &h_EncSetup->ltpf_mem_mem_normcorr, normcorr, + h_EncSetup->ltpf_mem_normcorr, &h_EncSetup->ltpf_mem_mem_normcorr, normcorr, &h_EncSetup->ltpf_mem_ltpf_on, &h_EncSetup->ltpf_mem_pitch, h_EncSetup->resamp_exp, - encoder->frame_dms, currentScratch, - encoder->hrmode + encoder->frame_dms, currentScratch + , encoder->hrmode + +#ifdef CR9_C_ADD_1p25MS +#ifdef FIX_TX_RX_STRUCT_STEREO +#ifdef NEW_SIGNALLING_SCHEME_1p25 + ,&h_EncSetup->Tx_ltpf +#else + ,h_EncSetup->Tx_ltpf +#endif +#else + , encoder->Tx_ltpf +#endif +#endif ); #ifdef WMOPS pop_wmops(); @@ -238,7 +300,7 @@ static void Enc_LC3PLUS_Channel(LC3PLUS_Enc *encoder, int channel, int bits_per_ #ifdef WMOPS pop_wmops(); #endif - + /* begin ener_fx */ #ifdef WMOPS push_wmops("PerBandEnergy"); @@ -311,20 +373,57 @@ static void Enc_LC3PLUS_Channel(LC3PLUS_Enc *encoder, int channel, int bits_per_ /* currentScratch Size = 512 bytes */ processSnsComputeScf_fx(ener_fx, ener_fx_exp, encoder->fs_idx, encoder->bands_number, scf, h_EncSetup->attdec_detected, encoder->attdec_damping, currentScratch, encoder->sns_damping +#ifdef CR9_C_ADD_1p25MS + , encoder->frame_dms, normcorr, &encoder->LT_normcorr +#endif ); + #ifdef WMOPS pop_wmops(); #endif + +#ifdef CR9_C_ADD_1p25MS_LRSNS + IF(sub(encoder->frame_dms, LC3PLUS_FRAME_DURATION_1p25MS) == 0) + { + pitch_rx_fx = ltpf_idx[0]; /* pitch_rx status flag */ + ltpf_rx_fx = ltpf_idx[1]; /* ltpf_activation used in snslr_st1C mode */ + + +#ifdef WMOPS + push_wmops("EncLC3_SnsQuantScfEncLR_fx"); +#endif + envelope_bits_fx = snsQuantScfEncLR_fx( + scf, /* input scf is always Word16 Q11 (both for ENABLE_HR and DISABLE_HR) */ + L_scf_idx, /* output: to send to enc_entropy_fx() */ + scf_q, /* output: Word32(for ENABLE_HR) or Word16 (for DISABLE_HR ) */ + pitch_rx_fx, ltpf_rx_fx, /* input: pitch information to st1C */ + currentScratch); +#ifdef WMOPS + pop_wmops(); +#endif + + } + ELSE + { +#ifdef WMOPS + push_wmops("SnsQuantScfEnc38bit"); +#endif + processSnsQuantizeScfEncoder_fx(scf, L_scf_idx, scf_q, currentScratch); +#ifdef WMOPS + pop_wmops(); +#endif + } +#else #ifdef WMOPS push_wmops("SnsQuantScfEnc"); #endif /* currentScratch Size = 500 bytes */ - processSnsQuantizeScfEncoder_fx(scf, L_scf_idx, scf_q, currentScratch); #ifdef WMOPS pop_wmops(); #endif +#endif /* CR9_C_ADD_1p25MS_LRSNS */ #ifdef WMOPS push_wmops("SnsInterpScfEnc"); @@ -360,7 +459,11 @@ static void Enc_LC3PLUS_Channel(LC3PLUS_Enc *encoder, int channel, int bits_per_ #endif /* currentScratch Size = 2 * MAX_LEN + 220 */ +#ifdef CR9_C_ADD_1p25MS + IF (h_EncSetup->lfe == 0 && encoder->frame_dms > LC3PLUS_FRAME_DURATION_1p25MS) +#else IF (h_EncSetup->lfe == 0) +#endif { processTnsCoder_fx(&(h_EncSetup->tns_bits), indexes, d_fx, BW_cutoff_idx, tns_order, &tns_numfilters, h_EncSetup->enable_lpc_weighting, encoder->nSubdivisions, encoder->frame_dms, @@ -368,13 +471,18 @@ static void Enc_LC3PLUS_Channel(LC3PLUS_Enc *encoder, int channel, int bits_per_ #ifdef ENABLE_HR_MODE , encoder->hrmode #endif - , encoder->near_nyquist_flag + , encoder->near_nyquist_flag ); } ELSE { tns_numfilters = 1; move16(); +#ifdef CR9_C_ADD_1p25MS + IF (encoder->frame_dms == LC3PLUS_FRAME_DURATION_1p25MS) { + tns_numfilters = 0; move16(); + } +#endif tns_order[0] = 0; move16(); h_EncSetup->tns_bits = tns_numfilters; @@ -390,20 +498,59 @@ static void Enc_LC3PLUS_Channel(LC3PLUS_Enc *encoder, int channel, int bits_per_ /* currentScratch Size = 4 * MAX_LEN bytes */ h_EncSetup->targetBitsQuant = sub(h_EncSetup->targetBitsInit, add(h_EncSetup->tns_bits, ltpf_bits)); +#ifdef CR9_C_ADD_1p25MS_LRSNS + IF( sub(encoder->frame_dms, LC3PLUS_FRAME_DURATION_1p25MS) == 0 ) + { /* adjust(==reduce) target bits based on the selected LRSNS-VQ bitrate */ + + h_EncSetup->targetBitsQuant = add(h_EncSetup->targetBitsQuant, 38); /* legacy 38bits was already pre-subtracted in h_EncSetup->targetBitsInit setup */ + ASSERT(envelope_bits_fx >= 9 && envelope_bits_fx <= 30); + h_EncSetup->targetBitsQuant = sub(h_EncSetup->targetBitsQuant, envelope_bits_fx); /* 9,10, 29,30, subtract actual LRSNS bitrate */ + } +#endif + test(); +#ifdef CR9_C_ADD_1p25MS_LRSNS + /* incoming (state based) ltpf_bits for tranmission set in function ltpf_coder_fx() */ + test(); test(); + lrsns_st1C_in_use = 0; move16(); + /* LRSNS stage1C use 10 bits and ltp/ltpf active flags , i.e. one can thus not always disable/steal the ltp/ltpf flags */ + if ( (sub(encoder->frame_dms, LC3PLUS_FRAME_DURATION_1p25MS) == 0) && (sub(envelope_bits_fx, 10) == 0) && (L_sub(L_scf_idx[0], 170L) > 0) ) + { + ASSERT(L_scf_idx[0] < (2 * 170) && (L_scf_idx[1] != 0) ); + lrsns_st1C_in_use = 1; move16(); + } + + ltptx_lowest_bit_lim = 1; move16(); + if ( sub(encoder->frame_dms, LC3PLUS_FRAME_DURATION_1p25MS) == 0 ) + { + ltptx_lowest_bit_lim = lrsns_ltp_bits_fx[0]; move16(); + } + test(); test(); test(); test(); + + /* allow cut away of LTP-active, ltpf-active, lag-index (including phase A, B) info when possible and not actually in use by LRSNS-VQ */ + + IF((h_EncSetup->targetBitsQuant < 0) && (sub(ltpf_bits, ltptx_lowest_bit_lim) > 0) && (lrsns_st1C_in_use == 0)) +#else IF (h_EncSetup->targetBitsQuant < 0 && sub(ltpf_bits, 1) > 0) +#endif { /* Disable LTPF */ h_EncSetup->ltpf_mem_ltpf_on = 0; move16(); ltpf_idx[1] = 0; move16(); +#ifdef CR9_C_ADD_1p25MS_LRSNS + ASSERT( (ltpf_bits-ltptx_lowest_bit_lim) > 0 ); + h_EncSetup->targetBitsQuant = add(h_EncSetup->targetBitsQuant, sub(ltpf_bits, ltptx_lowest_bit_lim)); move16(); /* subtract saving */ + ltpf_bits = ltptx_lowest_bit_lim; move16(); +#else ltpf_bits = 1; move16(); h_EncSetup->targetBitsQuant = sub(h_EncSetup->targetBitsInit, add(h_EncSetup->tns_bits, ltpf_bits)); +#endif } - + #ifdef ENABLE_HR_MODE Word32 gain32; #endif - + processEstimateGlobalGain_fx(d_fx, d_fx_exp, encoder->yLen, h_EncSetup->targetBitsQuant, #ifdef ENABLE_HR_MODE &gain32, @@ -416,13 +563,17 @@ static void Enc_LC3PLUS_Channel(LC3PLUS_Enc *encoder, int channel, int bits_per_ currentScratch #ifdef ENABLE_HR_MODE , encoder->hrmode, h_EncSetup->regBits, encoder->frame_dms +#else +#if defined(FIX_BOTH_1p25_TEST_NEW_GG_EST2) || defined (FIX_1p25_GG_EST_TUPLES) + , encoder->frame_dms +#endif #endif ); #ifdef WMOPS pop_wmops(); #endif /* begin q_d_fx16 */ - + #ifdef WMOPS push_wmops("Quant. 1"); #endif @@ -430,7 +581,7 @@ static void Enc_LC3PLUS_Channel(LC3PLUS_Enc *encoder, int channel, int bits_per_ processQuantizeSpec_fx(d_fx, d_fx_exp, gain32, gain_e, q_d_fx24, encoder->yLen, h_EncSetup->targetBitsQuant, h_EncSetup->targetBitsAri, &h_EncSetup->mem_specBits, &nBits, encoder->fs_idx, &lastnz, codingdata, &lsbMode, -1, encoder->hrmode); - + #else processQuantizeSpec_fx(d_fx, d_fx_exp, gain, gain_e, q_d_fx16, encoder->yLen, h_EncSetup->targetBitsQuant, h_EncSetup->targetBitsAri, &h_EncSetup->mem_specBits, &nBits, encoder->fs_idx, &lastnz, @@ -496,6 +647,9 @@ static void Enc_LC3PLUS_Channel(LC3PLUS_Enc *encoder, int channel, int bits_per_ gain_e, encoder->yLen, h_EncSetup->targetBitsQuant, nBits, resBits, &numResBits #ifdef ENABLE_HR_MODE , encoder->hrmode +#endif +#if defined (CR9_C_ADD_1p25MS) + , encoder->frame_dms #endif ); } @@ -534,13 +688,21 @@ static void Enc_LC3PLUS_Channel(LC3PLUS_Enc *encoder, int channel, int bits_per_ #ifdef WMOPS pop_wmops(); #endif - + #ifdef WMOPS push_wmops("Entropy cod"); #endif processEncoderEntropy(bytes, &bp_side, &mask_side, h_EncSetup->targetBitsAri, h_EncSetup->targetBytes, encoder->yLen, encoder->BW_cutoff_bits, tns_numfilters, lsbMode, lastnz, tns_order, - fac_ns_idx, quantizedGain, BW_cutoff_idx, ltpf_idx, L_scf_idx, bfi_ext, encoder->fs_idx); + fac_ns_idx, quantizedGain, BW_cutoff_idx, ltpf_idx, L_scf_idx, bfi_ext, encoder->fs_idx +#ifdef CR9_C_ADD_1p25MS +#ifdef FIX_TX_RX_STRUCT_STEREO + , encoder->frame_dms, &h_EncSetup->Tx_ltpf +#else + , encoder->frame_dms, &encoder->Tx_ltpf +#endif +#endif + ); #ifdef WMOPS pop_wmops(); #endif @@ -569,31 +731,31 @@ static void Enc_LC3PLUS_Channel(LC3PLUS_Enc *encoder, int channel, int bits_per_ #ifdef WMOPS push_wmops("Reorder Ari dec"); #endif - + #ifdef ENABLE_HR_MODE Word32 *xbuf = (Word32 *) scratchAlign(scratchBuffer, 0); - + processAriDecoder_fx(bytes, &bp_side, &mask_side, h_EncSetup->total_bits, encoder->yLen, encoder->fs_idx, h_EncSetup->enable_lpc_weighting, tns_numfilters, lsbMode, lastnz, &gain, tns_order, fac_ns_idx, quantizedGain, encoder->frame_dms, h_EncSetup->n_pc, 0, shr_pos(h_EncSetup->total_bits, 3), 1, &gain, &b_left, &gain, xbuf, - &gain, resBits, indexes, &gain, + &gain, resBits, indexes, &gain, currentScratch , encoder->hrmode ); #else - + processAriDecoder_fx(bytes, &bp_side, &mask_side, h_EncSetup->total_bits, encoder->yLen, encoder->fs_idx, h_EncSetup->enable_lpc_weighting, tns_numfilters, lsbMode, lastnz, &gain, tns_order, fac_ns_idx, quantizedGain, encoder->frame_dms, h_EncSetup->n_pc, 0, shr_pos(h_EncSetup->total_bits, 3), 1, &gain, &b_left, &gain, codingdata, - &gain, resBits, indexes, &gain, + &gain, resBits, indexes, &gain, currentScratch ); #endif - + #ifdef WMOPS pop_wmops(); /* Ari dec */ #endif @@ -665,4 +827,3 @@ int Enc_LC3PLUS(LC3PLUS_Enc *encoder, void **input, int bits_per_sample, UWord8 return output_size; } - diff --git a/lib_lc3plus/estimate_global_gain_fx.c b/lib_lc3plus/estimate_global_gain_fx.c index 8d0c54ded..ec4e8cd1a 100644 --- a/lib_lc3plus/estimate_global_gain_fx.c +++ b/lib_lc3plus/estimate_global_gain_fx.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,6 +7,8 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "functions.h" void processEstimateGlobalGain_fx(Word32 x[], Word16 x_e, Word16 lg, Word16 nbitsSQ, @@ -20,7 +22,11 @@ void processEstimateGlobalGain_fx(Word32 x[], Word16 x_e, Word16 lg, Word16 nbit Word32 *targetBitsOff, Word16 *old_targetBits, Word16 old_specBits, Word8 *scratchBuffer #ifdef ENABLE_HR_MODE - , Word16 hrmode, Word16 regBits, Word16 frame_dms + , Word16 hrmode, Word16 regBits, LC3PLUS_FrameDuration frame_dms +#else +#if defined(FIX_BOTH_1p25_TEST_NEW_GG_EST2) ||defined (FIX_1p25_GG_EST_TUPLES) + , LC3PLUS_FrameDuration frame_dms +#endif #endif ) { @@ -35,7 +41,31 @@ void processEstimateGlobalGain_fx(Word32 x[], Word16 x_e, Word16 lg, Word16 nbit Word16 *en_exp = NULL; Word32 M0, M1; #endif - +#ifdef FIX_1p25_GG_EST_TUPLES + /* NB (-1) WB(20), SSWB(30), SWB(40), FB(50) */ + Word16 nCoeffTab1p25[5] = { -1/*NB*/, GG_1p25_WB_TUPLES, GG_1p25_SSWB_TUPLES, GG_1p25_SWB_TUPLES, GG_1p25_FB_TUPLES }; + Word16 bwIdx; + Word16 divTabQ15[5] = { 0, -32768, 16384, 10923, 8192 }; +#endif +#ifdef FIX_BOTH_1p25_TEST_NEW_GG_EST2 + Word16 nCoeffPerBand = 4; /* 4 coeff per band */ + Word16 twoCoeffFlag = 0; /* boolean */ +#endif +#if defined( FIX_1p25_FLEX_ITER_TUPLE_LOOP ) || defined( FIX_1p25_FLEX_BISECT_LOOP ) + Word16 twoCoeffOutShiftA; + Word16 twoCoeffOutShiftB; + Word32 L_twoCoeffSuppressMaskA; + Word32 L_twoCoeffSuppressMaskB; + Word32 L_dB_scale_offset, L_dB_scale_offset2, L_dB_scale_offset3; + + Word16 twoCoeffOutShift; + Word32 L_twoCoeffSuppressMask; + +#elif defined( FIX_BASOP_1p25_NEW_GG_EST3) + Word16 twoCoeffOutShift; + Word32 L_twoCoeffSuppressMask; + Word32 L_dB_scale_offset, L_dB_scale_offset2, L_dB_scale_offset3; +#endif #ifdef DYNMEM_COUNT Dyn_Mem_In("processEstimateGlobalGain_fx", sizeof(struct { Word16 lg_4, s, tmp16, iszero; @@ -46,9 +76,95 @@ void processEstimateGlobalGain_fx(Word32 x[], Word16 x_e, Word16 lg, Word16 nbit Word32 diff, diff2; })); #endif + UNUSED(iszero); + +#ifdef FIX_1p25_FLEX_ITER_TUPLE_LOOP + UNUSED(twoCoeffOutShift); + UNUSED(L_twoCoeffSuppressMask); +#endif +#ifdef FIX_1p25_FLEX_BISECT_LOOP + UNUSED(twoCoeffOutShiftA); + UNUSED(L_twoCoeffSuppressMaskA); + UNUSED(twoCoeffOutShiftB); + UNUSED(L_twoCoeffSuppressMaskB); +#endif + +#ifdef FIX_1p25_FLEX_ITER_TUPLE_LOOP + UNUSED(twoCoeffOutShiftA); + UNUSED(L_twoCoeffSuppressMaskA); + UNUSED(twoCoeffOutShiftB); + UNUSED(L_twoCoeffSuppressMaskB); +#endif + +#ifndef FIX_1p25_GG_EST_TUPLES +#ifdef FIX_BOTH_1p25_TEST_NEW_GG_EST2 + IF(frame_dms == LC3PLUS_FRAME_DURATION_1p25MS && (sub(lg, 30) <= 0)) /* WB and SSWB */ + { + nCoeffPerBand = 2; move16(); /* 2 coeff per band */ + twoCoeffFlag = 1; move16(); + } +#endif +#endif + + +#ifdef FIX_1p25_GG_EST_TUPLES + twoCoeffFlag = 0; move16(); + nCoeffPerBand = 4; move16(); /* default assume 4 coeff per band(4-tuples block) */ + lg_4 = shr_pos_pos(lg, 2); + + test(); + IF(frame_dms == LC3PLUS_FRAME_DURATION_1p25MS) + { + bwIdx = mult(lg, 3276); + assert(bwIdx == ((lg - 1) / 10)); + nCoeffPerBand = nCoeffTab1p25[bwIdx]; move16(); + + if (sub(nCoeffPerBand, 2) == 0) + { + twoCoeffFlag = 1; move16(); + } + s = mult(add(lg, sub(nCoeffPerBand, 1)), divTabQ15[nCoeffPerBand]); + + tmp16 = i_mult(s, nCoeffPerBand); + +#ifdef FIX_1p25_32kHz_CLANG_WARNING_EST_GAIN + /* common 2,3,4 tuple energy loop may access tail values in blocks of GG_1p25_MAX_TUPLES */ + /* even if they are actually unused as values and shifted out, they should not be accessed uninitialized */ + tmp16 = add(tmp16, sub(GG_1p25_MAX_TUPLES,nCoeffPerBand)); +#endif + + FOR(i = lg; i < tmp16; i++) + { + x[i] = L_deposit_l(0); /* zero the top virtual MDCT lines in the spectrum signal x */ + } + assert(MAX_LEN >= s); + lg_4 = s; /* lg_4 also used for 3_tuples, 2 tuples*/ + } + +#elif defined( FIX_BASOP_ENC_QUANTIZE_1P25MS_512KBPS) + /* handle non-eaxactly quadruple lengths, in case frame_length is (e.g 1p25ms 24kHz --> 30 = 7*4 + 2 ) */ + /* e.g 1p25ms 48kHz --> 50 = 12*4 + 2 ) */ + /* quadruple extension is needed provide a correct x_max analysis as req. for scaling analysis */ + lg_4 = shr_pos(lg, 2); /*1/4*/ + + IF(frame_dms == LC3PLUS_FRAME_DURATION_1p25MS) + { + tmp16 = sub(lg, shl_pos(lg_4, 2)); + test(); + if (tmp16 != 0) + { + lg_4 = add(lg_4, 1); + } + FOR(i = lg; i < lg_4 * 4; i++) + { + x[i] = L_deposit_l(0); /* zero these top virtual MDCT lines */ + } + } +#endif + + + en = (Word32 *)scratchAlign(scratchBuffer, 0); /* Size = MAX_LEN bytes */ - en = (Word32 *)scratchAlign(scratchBuffer, - 0); /* Size = MAX_LEN bytes */ #ifdef ENABLE_HR_MODE if (hrmode) @@ -71,13 +187,14 @@ void processEstimateGlobalGain_fx(Word32 x[], Word16 x_e, Word16 lg, Word16 nbit move16(); } - *old_targetBits = nbitsSQ; - move16(); + *old_targetBits = nbitsSQ; move16(); nbitsSQ = add(nbitsSQ, round_fx(*targetBitsOff)); +#ifndef FIX_BASOP_ENC_QUANTIZE_1P25MS_512KBPS lg_4 = shr_pos(lg, 2); - x_max = 0; - move32(); +#endif + + x_max = 0; move32(); /* energy of quadruples with 9dB offset */ #ifdef ENABLE_HR_MODE @@ -155,7 +272,7 @@ void processEstimateGlobalGain_fx(Word32 x[], Word16 x_e, Word16 lg, Word16 nbit ELSE { /* log */ - tmp32 = L_add(BASOP_Util_Log2_lc3plus(ener), L_shl_pos(L_deposit_l(s), 25)); /* log2, 6Q25 */ + tmp32 = L_add(BASOP_Util_Log2(ener), L_shl_pos(L_deposit_l(s), 25)); /* log2, 6Q25 */ tmp32 = L_add(L_shr_pos(Mpy_32_16_lc3plus(tmp32, 0x436E), 7), 0x4E666); /* -> (28/20)*(7+10*tmp32/log2(10)), 16Q15 */ en[i] = tmp32; @@ -167,23 +284,179 @@ void processEstimateGlobalGain_fx(Word32 x[], Word16 x_e, Word16 lg, Word16 nbit } ELSE #endif - { + { /* regular hrmode==0 */ +#if defined ( FIX_1p25_FLEX_ITER_TUPLE_LOOP ) + if (frame_dms == LC3PLUS_FRAME_DURATION_1p25MS) + { + /* 4 or 2 tuples */ + L_dB_scale_offset = L_shr_pos(0x9CCCD, twoCoeffFlag); /* S15Q16 7.5(4 tuples) or 3.75(2_tuples) offset */ + L_dB_scale_offset2 = L_shr_pos(0x460000, twoCoeffFlag); + L_dB_scale_offset3 = L_shr_pos(0x3C7AE, twoCoeffFlag); + + /* set up constants for blocks of 4 (or block of 3 or 2)*/ + + /*init for 2-tuples energy loop */ + twoCoeffOutShiftA = 31; move16(); /* shift out */ + twoCoeffOutShiftB = 31; move16(); /* shift out */ + L_twoCoeffSuppressMaskA = 0; move32(); /* suppress value*/ + L_twoCoeffSuppressMaskB = 0; move32(); /* suppress value*/ + + +#if GG_1p25_MAX_TUPLES>=3 + IF(sub(nCoeffPerBand, 3) == 0) + { + L_dB_scale_offset = L_add(Mpy_32_16_lc3plus(0x9CCCD, 24576), 1L); /* S15Q16/ round(7.5 * 3/4), 481689.75 -> 481690 */ + L_dB_scale_offset2 = Mpy_32_16_lc3plus(0x460000, 24576); /*3440640.0 */ + L_dB_scale_offset3 = Mpy_32_16_lc3plus(0x3C7AE, 24576); /* 185794.5*/ + + twoCoeffOutShiftA = 0; move16(); /* do not shift out */ + L_twoCoeffSuppressMaskA = -1L; move32(); /* all ones, do not suppress*/ + twoCoeffOutShiftB = 31; move16(); /* shift out x[3] */ + L_twoCoeffSuppressMaskB = 0; move32(); /* suppress value*/ + } +#endif + +#if GG_1p25_MAX_TUPLES>=4 + IF(sub(nCoeffPerBand, 4) == 0) + { + twoCoeffOutShiftA = 0; move16(); /* do not shift out */ + twoCoeffOutShiftB = 0; move16(); /* do not shift out */ + L_twoCoeffSuppressMaskA = -1L; move32(); /* all ones, do not suppress*/ + L_twoCoeffSuppressMaskB = -1L; move32(); /* all ones, do not suppress*/ + } +#endif +#endif + +#ifdef FIX_1p25_FLEX_ITER_TUPLE_LOOP + + FOR(i = 0; i < lg_4; i++) /* 1.25 ms energy loop used for all N/4 , (N)/3 and N/2 */ + { + /* normalization */ + s = 31; move16(); + + tmp32 = L_abs(x[0]); + tmp32 = L_max(tmp32, L_abs(x[1])); + + /* 0 or 31 shift, 0 for blocks of 4, 31 to accumulate a 0 value (for block #2,#3) for blocks of 2 or blocks of 3 */ +#if GG_1p25_MAX_TUPLES>=3 + tmp32 = L_max(tmp32, L_shr_pos_pos(L_abs(x[2]), twoCoeffOutShiftA)); +#endif +#if GG_1p25_MAX_TUPLES>=4 + tmp32 = L_max(tmp32, L_shr_pos_pos(L_abs(x[3]), twoCoeffOutShiftB)); +#endif + x_max = L_max(x_max, tmp32); /* global x_max */ + + + if (tmp32 != 0) + { + s = norm_l(tmp32); + } + + s = sub(s, 2); /* 2 bits headroom . for up to four values accumulation */ + /* NB only 1 bit headroom needed with L_mac0 */ + /* NB only 2tuples will only need 1 bit even with L_mac */ + /* calc quadruple or , triple or tuple energy */ + ener = L_deposit_l(1); + + + tmp16 = round_fx(L_shl(x[0], s)); /* s is in range [29...-2], i.e. can become a downshift of two */ + ener = L_mac(ener, tmp16, tmp16); + + tmp16 = round_fx(L_shl(x[1], s)); + ener = L_mac(ener, tmp16, tmp16); + +#if GG_1p25_MAX_TUPLES >= 3 + tmp32 = L_and(x[2], L_twoCoeffSuppressMaskA); /* mask is 0 for 2blocks, all ones for 3 or 4 blocks */ + tmp16 = round_fx(L_shl(tmp32, s)); + ener = L_mac(ener, tmp16, tmp16); +#endif + +#if GG_1p25_MAX_TUPLES >= 4 + tmp32 = L_and(x[3], L_twoCoeffSuppressMaskB); /* 0 for 2 or 3 blocks, all ones for 4 blocks */ + tmp16 = round_fx(L_shl(tmp32, s)); + ener = L_mac(ener, tmp16, tmp16); +#endif + s = shl_pos(sub(x_e, s), 1); + +#ifdef NONBE_GAIN_EST_FIX + test(); test(); + if ((L_sub(ener, 1L) == 0) && (s < 0)) + { + s = 0; move16(); + } +#endif + +#ifndef LOG2_LC_APPROX + /* log2 */ + tmp32 = L_add_sat(BASOP_Util_Log2(ener), L_shl_sat(L_deposit_l(s), 25)); /* log2, 6Q25 */ +#endif +#ifdef LOG2_LC_APPROX + tmp32 = L_add_sat(BASOP_Util_Log2_LC(ener), L_shl_sat(L_deposit_l(s), 25)); /* log2LC , 6Q25 */ +#endif + tmp32 = L_add(L_shr_pos(Mpy_32_16_lc3plus(tmp32, 0x436E), 6), L_dB_scale_offset); /* -> (28/20)*( (7or5.25or3.5 ) + 10*tmp32/log2(10)), 15Q16 */ + + en[i] = tmp32; move32(); + + x += nCoeffPerBand; + /* N/4 or N/3 or N/2 */ + } /* for loop*/ + } /* end of IF 1p25 */ + else + { /* 4 or 2 merged loop for non-1p25ms */ +#endif + +#ifndef FIX_1p25_GG_EST_TUPLES + # ifdef FIX_BOTH_1p25_TEST_NEW_GG_EST2 + test(); + if (twoCoeffFlag != 0) + { + lg_4 = add(lg_4, lg_4); /*lg_4(extended) for N/4 doubled and used as "lg_2" for N/2 */ + } +#endif +#endif + + #ifdef FIX_BASOP_1p25_NEW_GG_EST3 + /*set up constants for blocks of two (or block of 4)*/ + L_dB_scale_offset = L_shr_pos(0x9CCCD, twoCoeffFlag); /* S15Q16/ 7.5 or 3.5 offset */ +#ifdef FIX_1p25_FLEX_ITER_TUPLE_LOOP + Word16 twoCoeffOutShift; + Word32 L_twoCoeffSuppressMask; +#endif + twoCoeffOutShift = 0; move16(); /* do not shift out */ + L_twoCoeffSuppressMask = -1L; move32(); /* all ones-mask, do not suppress*/ + + IF(twoCoeffFlag != 0) + { + twoCoeffOutShift = 31; move16(); + L_twoCoeffSuppressMask = 0; move16();/* supress value*/ + x[lg_4 * 2] = 0; move32(); /*make sure extra two coeffs at tail are zeroed */ + x[lg_4 * 2 + 1] = 0; move32(); + }; +#endif + FOR (i = 0; i < lg_4; i++) { /* normalization */ - s = 31; - move16(); + s = 31; move16(); tmp32 = L_abs(x[0]); tmp32 = L_max(tmp32, L_abs(x[1])); +#ifdef FIX_BOTH_1p25_TEST_NEW_GG_EST2 +#ifdef FIX_BASOP_1p25_NEW_GG_EST3 + /* 0 or 31 shift, 0 for blocks of 4, 31 to accumulate a 0 value (for block #2,#3) for blocks of 2 */ + tmp32 = L_max(tmp32, L_shr_pos(L_abs(x[2]), twoCoeffOutShift)); + tmp32 = L_max(tmp32, L_shr_pos(L_abs(x[3]), twoCoeffOutShift)); +#endif +#else tmp32 = L_max(tmp32, L_abs(x[2])); tmp32 = L_max(tmp32, L_abs(x[3])); +#endif x_max = L_max(x_max, tmp32); - if (tmp32 != 0) + if (tmp32 != 0) { s = norm_l(tmp32); - - s = sub(s, 2); /* 2 bits headroom */ + } + s = sub(s, 2); /* 2 bits headroom */ /* note: slightly suboptimal 2 bit headroom kept for pairs */ /* calc quadruple energy */ ener = L_deposit_l(1); @@ -194,34 +467,55 @@ void processEstimateGlobalGain_fx(Word32 x[], Word16 x_e, Word16 lg, Word16 nbit tmp16 = round_fx(L_shl(x[1], s)); ener = L_mac(ener, tmp16, tmp16); +#ifdef FIX_BOTH_1p25_TEST_NEW_GG_EST2 +#ifdef FIX_BASOP_1p25_NEW_GG_EST3 + tmp32 = L_and(x[2], L_twoCoeffSuppressMask); /* 0 for 2blocks, all ones for 4 blocks */ + tmp16 = round_fx(L_shl(tmp32, s)); + ener = L_mac(ener, tmp16, tmp16); + + tmp32 = L_and(x[3], L_twoCoeffSuppressMask); /* 0 for 2blocks, all ones for 4 blocks */ + tmp16 = round_fx(L_shl(tmp32, s)); + ener = L_mac(ener, tmp16, tmp16); +#endif +#else tmp16 = round_fx(L_shl(x[2], s)); ener = L_mac(ener, tmp16, tmp16); tmp16 = round_fx(L_shl(x[3], s)); ener = L_mac(ener, tmp16, tmp16); - +#endif s = shl_pos(sub(x_e, s), 1); - if (ener == 1 && s < 0) + if (ener == 1 && s < 0) { s = 0; + } /* log */ - tmp32 = L_add_sat(BASOP_Util_Log2_lc3plus(ener), L_shl_sat(L_deposit_l(s), 25)); /* log2, 6Q25 */ - tmp32 = - L_add(L_shr_pos(Mpy_32_16_lc3plus(tmp32, 0x436E), 6), 0x9CCCD); /* -> (28/20)*(7+10*tmp32/log2(10)), 15Q16 */ - en[i] = tmp32; - move32(); + tmp32 = L_add_sat(BASOP_Util_Log2(ener), L_shl_sat(L_deposit_l(s), 25)); /* log2, 6Q25 */ +#ifdef FIX_BOTH_1p25_TEST_NEW_GG_EST2 +#ifdef FIX_BASOP_1p25_NEW_GG_EST3 + tmp32 = L_add(L_shr_pos(Mpy_32_16_lc3plus(tmp32, 0x436E), 6), L_dB_scale_offset); /* -> (28/20)*( (7or3.5) + 10*tmp32/log2(10)), 15Q16 */ +#endif +#else + tmp32 = L_add(L_shr_pos(Mpy_32_16_lc3plus(tmp32, 0x436E), 6), 0x9CCCD); /* -> (28/20)*(7+10*tmp32/log2(10)), 15Q16 */ +#endif + en[i] = tmp32; move32(); + +#ifdef FIX_BOTH_1p25_TEST_NEW_GG_EST2 + x += nCoeffPerBand; +#else x += 4; - } - } +#endif + } /* N/4 or N/2 energy loop */ +#ifdef FIX_1p25_FLEX_ITER_TUPLE_LOOP + } /* end of non-1.25ms 4 or 2 tuple energy loop */ +#endif + }/* hrmode==0 */ IF (x_max == 0) { - *quantizedGainMin = quantizedGainOff; - move16(); - *quantizedGain = 0; - move16(); - *old_targetBits = -1; - move16(); + *quantizedGainMin = quantizedGainOff; move16(); + *quantizedGain = 0; move16(); + *old_targetBits = -1; move16(); } ELSE { @@ -244,7 +538,7 @@ void processEstimateGlobalGain_fx(Word32 x[], Word16 x_e, Word16 lg, Word16 nbit if (M0 <= 0x7fff) { - Word16 inv_M0 = Inv16_lc3plus(M0, &ratio_exp); /* Inverse in Q(15 - ratio_exp) */ + Word16 inv_M0 = Inv16(M0, &ratio_exp); /* Inverse in Q(15 - ratio_exp) */ ratio = L_shr(Mpy_32_16_lc3plus(M1, inv_M0), 15 - ratio_exp); /* Integer ratio */ } else @@ -252,7 +546,7 @@ void processEstimateGlobalGain_fx(Word32 x[], Word16 x_e, Word16 lg, Word16 nbit Word16 M0_h = L_shr(M0, 15); Word32 M1_h = L_shr(M1, 15); - Word16 inv_M0 = Inv16_lc3plus(M0_h, &ratio_exp); /* Inverse in Q(15 - ratio_exp) */ + Word16 inv_M0 = Inv16(M0_h, &ratio_exp); /* Inverse in Q(15 - ratio_exp) */ ratio = extract_l(L_shr(Mpy_32_16_lc3plus(M1_h, inv_M0), 15 - ratio_exp)); /* Integer ratio */ } @@ -264,16 +558,33 @@ void processEstimateGlobalGain_fx(Word32 x[], Word16 x_e, Word16 lg, Word16 nbit ratio_prod = L_mult(ratio, 5); - if (ratio_prod < frame_dms) + int frame_dms_val = 0; + SWITCH (frame_dms) /* 1 / frame_dms in Q15 */ + { +#ifdef CR9_C_ADD_1p25MS + case LC3PLUS_FRAME_DURATION_1p25MS: assert(0); frame_dms_val = 13; BREAK; +#endif + case LC3PLUS_FRAME_DURATION_2p5MS: frame_dms_val = 25; BREAK; + case LC3PLUS_FRAME_DURATION_5MS: frame_dms_val = 50; BREAK; + case LC3PLUS_FRAME_DURATION_7p5MS: frame_dms_val = 75; BREAK; + case LC3PLUS_FRAME_DURATION_10MS: frame_dms_val = 100; BREAK; + case LC3PLUS_FRAME_DURATION_UNDEFINED: assert(0); + } + + if (ratio_prod < frame_dms_val) { Word16 mult_factor = 0; SWITCH (frame_dms) /* 1 / frame_dms in Q15 */ { - case 25: mult_factor = 1311; break; - case 50: mult_factor = 655; break; - case 75: mult_factor = 437; break; - case 100: mult_factor = 328; break; +#ifdef CR9_C_ADD_1p25MS + case LC3PLUS_FRAME_DURATION_1p25MS: mult_factor = 15721; BREAK; +#endif + case LC3PLUS_FRAME_DURATION_2p5MS: mult_factor = 1311; BREAK; + case LC3PLUS_FRAME_DURATION_5MS: mult_factor = 655; BREAK; + case LC3PLUS_FRAME_DURATION_7p5MS: mult_factor = 437; BREAK; + case LC3PLUS_FRAME_DURATION_10MS: mult_factor = 328; BREAK; + case LC3PLUS_FRAME_DURATION_UNDEFINED: assert(0); } /* ratio_prod < frame_dms. Hence Word16 can be used */ @@ -294,7 +605,7 @@ void processEstimateGlobalGain_fx(Word32 x[], Word16 x_e, Word16 lg, Word16 nbit IF(rB_offset > 0) { Word32 reg_exp = L_negate(L_add(L_shl(regBits, 25), L_shr(rB_offset, 3))); - reg_val = Mpy_32_32_lc3plus(x_max, BASOP_Util_InvLog2_lc3plus(reg_exp)); /* Product is in Q31 */ + reg_val = Mpy_32_32_lc3plus(x_max, BASOP_Util_InvLog2(reg_exp)); /* Product is in Q31 */ /* reg_val is in Q(31-x_e) */ } ELSE @@ -303,8 +614,7 @@ void processEstimateGlobalGain_fx(Word32 x[], Word16 x_e, Word16 lg, Word16 nbit reg_val_e = sub(x_e, regBits); } - sub_val = 0x183BA045; - move16(); + sub_val = 0x183BA045; move16(); /*28 * log10(32768*256 - 2) in Q21 */ /* @@ -320,10 +630,8 @@ void processEstimateGlobalGain_fx(Word32 x[], Word16 x_e, Word16 lg, Word16 nbit FOR (i = 0; i < lg_4; i++) { - ener = en[i]; - move16(); - s = en_exp[i]; - move16(); + ener = en[i]; move16(); + s = en_exp[i]; move16(); Word16 shift_val = sub(reg_val_e, s); @@ -347,21 +655,20 @@ void processEstimateGlobalGain_fx(Word32 x[], Word16 x_e, Word16 lg, Word16 nbit s = reg_val_e; } - tmp32 = L_add(BASOP_Util_Log2_lc3plus(ener), L_shl_pos(L_deposit_l(s), 25)); /* log2, 6Q25 */ + tmp32 = L_add(BASOP_Util_Log2(ener), L_shl_pos(L_deposit_l(s), 25)); /* log2, 6Q25 */ tmp32 = L_add(L_shr_pos(Mpy_32_32_lc3plus(tmp32, 0x436E439A), 7), 0x4E666); /* -> (28/20)*(7+10*tmp32/log2(10)), 15Q16 */ - en[i] = tmp32; - move32(); + en[i] = tmp32; move32(); } } #endif - x_max = BASOP_Util_Log2_lc3plus(x_max); + x_max = BASOP_Util_Log2(x_max); /* Minimum gain */ x_max = L_add(x_max, L_shl_pos(L_deposit_l(x_e), 25)); /* log2(x_max) in 6Q25 */ x_max = L_sub( Mpy_32_32_lc3plus(x_max, 0x436E439A), sub_val); /* 28*log10(x_max/(32768-0.375)) = log2(x_max)*(28/log2(10))-28*log10(32768-0.375) in 10Q21 */ /* 28/log1(10) is in Q27 - Mpy_32_32_lc3plus : Q25(x_max) + Q27 + Q1(Mpy_32_32_ss) - Q32 = Q21 */ + Mpy_32_32 : Q25(x_max) + Q27 + Q1(Mpy_32_32_ss) - Q32 = Q21 */ *quantizedGainMin = extract_l(L_shr_pos(L_add(x_max, (1 << 21) + (1 << 11)), 21)); move16(); ASSERT(*quantizedGainMin <= 255 + quantizedGainOff); @@ -401,8 +708,7 @@ void processEstimateGlobalGain_fx(Word32 x[], Word16 x_e, Word16 lg, Word16 nbit else { ener = L_add(ener, tmp32); - iszero = 0; - move16(); + iszero = 0; move16(); diff2 = L_sub(tmp32, 0x118000); /* 0x230000 -> (28/20)*(50) */ if (diff2 >= 0) @@ -422,79 +728,208 @@ void processEstimateGlobalGain_fx(Word32 x[], Word16 x_e, Word16 lg, Word16 nbit tmp16 = extract_h(L_shl(offset, 2)); } ELSE -#endif +#endif + /* regular mode */ + /* SQ scale: 4 bits / 6 dB per quadruple */ { - /* SQ scale: 4 bits / 6 dB per quadruple */ + + #ifndef FIX_1p25_FLEX_BISECT_LOOP +#ifdef FIX_BASOP_1p25_NEW_GG_EST3 + /*these limits were constant for blocks of 4 , now we adaptively adjust them for blocks of two */ + L_dB_scale_offset = L_shr_pos(0x9CCCD, twoCoeffFlag); + L_dB_scale_offset2 = L_shr_pos(0x460000, twoCoeffFlag); + L_dB_scale_offset3 = L_shr_pos(0x3C7AE, twoCoeffFlag); +#endif +#endif target = L_shl_pos(L_mult(0x7D71, nbitsSQ), 1); /* -> (28/20) * (1.4) * nbitsSQ */ fac = L_add(0x1000000, 0); /* -> 256 */ - /* find offset (0 to 127) */ - FOR (iter = 0; iter < 8; iter++) +#ifdef FIX_1p25_FLEX_BISECT_LOOP + + /* 1p25 iteration code, for 4-tuples 3-tuples and 2 tuples */ + test(); + IF((frame_dms == LC3PLUS_FRAME_DURATION_1p25MS) && (sub(nCoeffPerBand, 4) <= 0)) { - fac = L_shr_pos(fac, 1); - offset = L_sub(offset, fac); + Word16 idx; /* 0, 1, 2 , section index */ + Word32 L_tmp32; + Word32 L_offset2; - ener = L_deposit_l(0); - iszero = 1; - move16(); - FOR (i = lg_4 - 1; i >= 0; i--) + Word16 shiftl_fac[3] = { -31, 0, 1 }; /* ROM float mult_fact[3] = { 0.0, 1.0, 2.0 }; */ /* -31 shifts out all energy in an signed Word32 */ + + /* 4 or 2 tuples */ + L_dB_scale_offset = L_shr_pos(0x9CCCD, twoCoeffFlag); /* S15Q16 7.5(4 tuples) or 3.75(2_tuples) offset */ + L_dB_scale_offset2 = L_shr_pos(0x460000, twoCoeffFlag); + L_dB_scale_offset3 = L_shr_pos(0x3C7AE, twoCoeffFlag); + + /* set up constants for blocks of 4 (or block of 3 or 2)*/ +#if GG_1p25_MAX_TUPLES>=3 + IF(sub(nCoeffPerBand, 3) == 0) { - tmp32 = L_sub(en[i], offset); - diff = L_sub(tmp32, 0x9CCCD); /* 0x9CCCD -> (28/20)*(7) in Q16 */ - if (diff < 0) + L_dB_scale_offset = L_add(Mpy_32_16_lc3plus(0x9CCCD, 24576), 1L); /* S15Q16/ round(7.5 * 3/4), 481689.75 -> 481690 */ + L_dB_scale_offset2 = Mpy_32_16_lc3plus(0x460000, 24576); /*3440640.0 */ + L_dB_scale_offset3 = Mpy_32_16_lc3plus(0x3C7AE, 24576); /* 185794.5*/ + } +#endif + /* tuple-size dynamic constant tables, treated as registers */ + Word32 L_en_lim[2]; + Word32 L_add_fac[3]; + + L_en_lim[0] = L_add(L_dB_scale_offset, 0); /*28/20*7.0*/; + L_en_lim[1] = L_add(L_dB_scale_offset2, 0); /*28/20*50.0*/ + + L_add_fac[0] = L_add(L_dB_scale_offset3, 0); + L_add_fac[1] = L_add(0, 0); + L_add_fac[2] = L_negate(L_dB_scale_offset2); + + + /* find offset (0 to 255) */ + FOR(iter = 0; iter < 8; iter++) + { + fac = L_shr_pos_pos(fac, 1); + offset = L_sub(offset, fac); + iszero = 1; move16(); + ener = L_deposit_l(0); + /* skip iszero section, go to first band with enough energy */ + /* find first index where we start summing up adding bits. */ + + L_offset2 = L_add(offset, L_dB_scale_offset); + FOR(i = sub(lg_4, 1); i >= 0; i--) { - if (iszero == 0) + L_tmp32 = L_sub(en[i], L_offset2); + IF(L_tmp32 > 0) { - ener = L_add_sat(ener, 0x3C7AE); /* 0x3C7AE -> (28/20)*(2.7) in Q16 */ + iszero = 0; move16(); /* now also allow upward update */ + BREAK; } } - else + /* exiting counter value "i" is remembered , for the next FOR loop initialization */ + + + /* Equations realized acc = { 0*d_en + 2.7 , 1*dEn + 0.0, 2*dEn + (-50.0) }; */ + FOR(; i >= 0; i--) { - ener = L_add_sat(ener, tmp32); - iszero = 0; - move16(); + L_tmp32 = L_sub(en[i], offset); - diff2 = L_sub(tmp32, 0x460000); /* 0x460000 -> (28/20)*(50) in Q16 */ - if (diff2 >= 0) + /* pre_quantize energy "L_tmp32" into a idx 0, 1, 2; to address tabled acc. values */ + idx = 0; move16(); /* "ptr" init to low section */ + if (L_sub(L_tmp32, L_en_lim[0]) > 0) { - ener = L_add_sat(ener, diff2); + idx = add(idx, 1); /* single op */ /* middle section */ } + + if (L_sub(L_tmp32, L_en_lim[1]) > 0) + { + idx = add(idx, 1); /* single op */ /* high section*/ + } + + ener = L_add_sat(ener, L_shl_sat(L_tmp32, shiftl_fac[idx])); /* *0.0, *1.0, *2.0 */ /* NB! this shifts L_tmp32, (the ener contribution) both up and down */ + ener = L_add_sat(ener, L_add_fac[idx]); /* 2.7, 0, -50 */ } - - } + - /* if ener is above target -> increase offset */ - test(); - if (L_sub(ener, target) > 0 && iszero == 0) - { - offset = L_add(offset, fac); - } + /* if ener is above target -> increase offset */ + /* if only low level signal , iszero was never set to 0 --> offset not moved */ + assert(target > 0); + test(); test(); + if (L_sub(ener, target) > 0 && iszero == 0) + { + offset = L_add(offset, fac); + } + } /* iter 1--8 ,1p25 loop */ } + /* if 1p25 */ + ELSE + { + #endif /* FLEX BISECT*/ + /* find offset (0 to 127) */ +#ifdef FIX_BASOP_1p25_NEW_GG_EST3 + /* 4 ,or 2 tuples */ + L_dB_scale_offset = L_shr_pos(0x9CCCD, twoCoeffFlag); + /* S15Q16 7.5(4 tuples) or 3.75(2_tuples) offset */ + L_dB_scale_offset2 = L_shr_pos(0x460000, twoCoeffFlag); + L_dB_scale_offset3 = L_shr_pos(0x3C7AE, twoCoeffFlag); +#endif + FOR(iter = 0; iter < 8; iter++) + { + fac = L_shr_pos(fac, 1); + offset = L_sub(offset, fac); + + ener = L_deposit_l(0); + iszero = 1; move16(); + + + FOR(i = lg_4 - 1; i >= 0; i--) + { + tmp32 = L_sub(en[i], offset); +#ifdef FIX_BOTH_1p25_TEST_NEW_GG_EST2 +#ifdef FIX_BASOP_1p25_NEW_GG_EST3 + diff = L_sub(tmp32, L_dB_scale_offset); /* 0x9CCCD -> (28/20)*( 7or3.5) in Q16 */ +#endif +#else + diff = L_sub(tmp32, 0x9CCCD); /* 0x9CCCD -> (28/20)*(7) in Q16 */ +#endif + if (diff < 0) + { + if (iszero == 0) + { +#ifdef FIX_BOTH_1p25_TEST_NEW_GG_EST2 +#ifdef FIX_BASOP_1p25_NEW_GG_EST3 + ener = L_add_sat(ener, L_dB_scale_offset3); /* 0x3C7AE -> (28/20)*(2.7or 3.5) in Q16 */ +#endif +#else + ener = L_add_sat(ener, 0x3C7AE); /* 0x3C7AE -> (28/20)*(2.7) in Q16 */ +#endif + } + } + else + { + ener = L_add_sat(ener, tmp32); + iszero = 0; move16(); +#ifdef FIX_BOTH_1p25_TEST_NEW_GG_EST2 +#ifdef FIX_BASOP_1p25_NEW_GG_EST3 + diff2 = L_sub(tmp32, L_dB_scale_offset2); /* 0x460000 -> (28/20)*(50or25) in Q16 */ +#endif +#else + diff2 = L_sub(tmp32, 0x460000); /* 0x460000 -> (28/20)*(50) in Q16 */ +#endif + if (diff2 >= 0) + { + ener = L_add_sat(ener, diff2); + } + } + + } + + /* if ener is above target -> increase offset */ + test(); + if (L_sub(ener, target) > 0 && iszero == 0) + { + offset = L_add(offset, fac); + } + } /* legacy 1-8 iter loop , FOR */ +#ifdef FIX_1p25_FLEX_BISECT_LOOP + } /* 1p25, non 1p25*/ +#endif tmp16 = extract_h(offset); - } - if (sub(tmp16, *quantizedGainMin) < 0) - { - *old_targetBits = -1; - move16(); - } - *quantizedGain = sub(s_max(*quantizedGainMin, tmp16), quantizedGainOff); - move16(); + if (sub(tmp16, *quantizedGainMin) < 0) + { + *old_targetBits = -1; move16(); + } + *quantizedGain = sub(s_max(*quantizedGainMin, tmp16), quantizedGainOff); move16(); } #ifdef ENABLE_HR_MODE - tmp32 = - Mpy_32_16_lc3plus(0x797CD707, L_shl_pos(add(*quantizedGain, quantizedGainOff), 6)); + tmp32 = Mpy_32_16_lc3plus(0x797CD707, L_shl_pos(add(*quantizedGain, quantizedGainOff), 6)); #else - tmp32 = - L_shl_pos(L_mult0(add(*quantizedGain, quantizedGainOff), 0x797D), 7); /* 6Q25; 0x797D -> log2(10)/28 (Q18) */ + tmp32 = L_shl_pos(L_mult0(add(*quantizedGain, quantizedGainOff), 0x797D), 7); /* 6Q25; 0x797D -> log2(10)/28 (Q18) */ #endif *gain_e = add(extract_l(L_shr_pos(tmp32, 25)), 1); /* get exponent */ #ifdef ENABLE_HR_MODE - *gain = BASOP_Util_InvLog2_lc3plus(L_or(tmp32, (Word32)0xFE000000)); + *gain = BASOP_Util_InvLog2(L_or(tmp32, (Word32)0xFE000000)); #else - *gain = round_fx(BASOP_Util_InvLog2_lc3plus(L_or(tmp32,(Word32) 0xFE000000))); + *gain = round_fx(BASOP_Util_InvLog2(L_or(tmp32,(Word32) 0xFE000000))); #endif #ifdef DYNMEM_COUNT diff --git a/lib_lc3plus/fft_lc3plus.c b/lib_lc3plus/fft_lc3plus.c index 56dd33156..e7a71d5b1 100644 --- a/lib_lc3plus/fft_lc3plus.c +++ b/lib_lc3plus/fft_lc3plus.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,6 +7,8 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "functions.h" #include "rom_basop_util_lc3plus.h" @@ -27,9 +29,9 @@ #define SCALEFACTOR32_2 1 #ifdef ENABLE_HR_MODE -#define Mpy_32_xx Mpy_32_32_lc3plus +#define Mpy_32_xx Mpy_32_32 #else -#define Mpy_32_xx Mpy_32_16_lc3plus +#define Mpy_32_xx Mpy_32_16 #endif #define SCALEFACTOR6 4 @@ -3649,7 +3651,7 @@ static void fftN2(Word32 *re, Word32 *im, #ifdef ENABLE_FFT_RESCALE IF (scale) { - *scale = s_max(sub(getScaleFactor32_lc3plus(x, dim1 * dim2 * 2), FFT_RESCALE_HR), 0); move16(); + *scale = s_max(sub(getScaleFactor32(x, dim1 * dim2 * 2), FFT_RESCALE_HR), 0); move16(); #if defined(FUNCTION_scaleValues_32) scaleValues_32(x, dim1 * dim2, *scale); @@ -3987,7 +3989,7 @@ static void fftN2(Word32 *re, Word32 *im, /* x is the scratch buffer */ -void BASOP_cfft_lc3plus(Word32 *re, Word32 *im, Word16 length, Word16 s, Word16 *scale, Word32 *x) +void BASOP_cfft(Word32 *re, Word32 *im, Word16 length, Word16 s, Word16 *scale, Word32 *x) { #if (defined ENABLE_FFT_RESCALE) && ((defined LC3_FFT30) || (defined ENABLE_HR_MODE)) Word16 fftN2scale = 0; @@ -4007,6 +4009,13 @@ void BASOP_cfft_lc3plus(Word32 *re, Word32 *im, Word16 length, Word16 s, Word16 *scale = add(*scale, SCALEFACTOR10); move16(); BREAK; +#ifdef CR9_C_ADD_1p25MS + case 15: + fft15(re, im, s); + *scale = add(*scale, SCALEFACTOR15); + move16(); + BREAK; +#endif case 16: fft16(re, im, s); *scale = add(*scale, SCALEFACTOR16); @@ -4250,7 +4259,7 @@ void BASOP_rfftN(Word32 *x, Word16 sizeOfFft, Word16 *scale, Word8 *scratchBuffe sizeOfFft4 = shr_pos(sizeOfFft, 2); sizeOfFft8 = shr_pos(sizeOfFft, 3); - BASOP_cfft_lc3plus(&x[0], &x[1], sizeOfFft2, 2, scale, workBuffer); + BASOP_cfft(&x[0], &x[1], sizeOfFft2, 2, scale, workBuffer); xb0 = L_shr_pos(x[0], 1); xb1 = L_shr_pos(x[1], 1); @@ -4351,7 +4360,7 @@ void BASOP_irfftN(Word32 *x, Word16 sizeOfFft, Word16 *scale, Word8 *scratchBuff x[sizeOfFft - 2 * i + 1] = L_shr_pos(x[2 * i + 1], 1); move32(); - BASOP_cfft_lc3plus(&x[0], &x[1], sizeOfFft2, 2, scale, workBuffer); + BASOP_cfft(&x[0], &x[1], sizeOfFft2, 2, scale, workBuffer); /* If you want BASOP_irfft to be inverse to BASOP_rfft then the result needs * to be normalised by sizeOfFft */ diff --git a/lib_lc3plus/functions.h b/lib_lc3plus/functions.h index b557ca38f..5146ca05c 100644 --- a/lib_lc3plus/functions.h +++ b/lib_lc3plus/functions.h @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -10,6 +10,8 @@ #ifndef FUNCTIONS_H #define FUNCTIONS_H +#include "options.h" +#include "wmc_auto.h" #include "defines.h" #include "stl.h" @@ -18,11 +20,10 @@ #endif #include "basop_util_lc3plus.h" -#include "basop32.h" #include "constants.h" -#include "lc3.h" -#include "setup_dec_lc3.h" /* for decoder state handle ptr */ -#include "setup_enc_lc3.h" /* for encoder state handle ptr */ +#include "lc3plus.h" +#include "setup_dec_lc3plus.h" /* for decoder state handle ptr */ +#include "setup_enc_lc3plus.h" /* for encoder state handle ptr */ #include "basop_mpy_lc3plus.h" #include @@ -54,15 +55,18 @@ void WarnMsg(char *msg); void ExitMsg(char *msg); void AssertMsg(int true_flag, char *msg); +Word16 getLastNzBits_fx (Word16 N); +void dct16_W32int_fx(const Word16 *in, Word16 *out); + void processTnsDecoder_fx(Word16 rc_idx[], Word32 x[], Word16 xLen, Word16 order[], Word16 *x_e, Word16 BW_stopband_idx, - Word16 frame_dms, Word8 *scratchBuffer + LC3PLUS_FrameDuration frame_dms, Word8 *scratchBuffer #ifdef ENABLE_HR_MODE , Word16 hrmode #endif ); void processTnsCoder_fx(Word16 *bits, Word16 indexes[], Word32 x[], Word16 BW_cutoff_idx, Word16 order[], - Word16 *numfilters, Word16 enable_lpc_weighting, Word16 nSubdivisions, Word16 frame_dms, + Word16 *numfilters, Word16 enable_lpc_weighting, Word16 nSubdivisions, LC3PLUS_FrameDuration frame_dms, Word16 max_len, Word8 *scratchBuffer #ifdef ENABLE_HR_MODE , Word16 hrmode @@ -77,12 +81,15 @@ void processResidualDecoding_fx(Word32 spectrum[], Word16 spectrum_e, Word16 L_s #ifdef ENABLE_HR_MODE , Word16 hrmode #endif +#ifdef CR9_C_ADD_1p25MS + , LC3PLUS_FrameDuration frame_dms +#endif ); void processPreemph_fx(Word16 *x, Word16 len, Word16 mem[], Word16 memLen, Word16 out[], Word16 *outLen, Word16 mu); void processNoiseFilling_fx(Word32 xq[], Word16 nfseed, Word16 xq_e, Word16 fac_ns_idx, Word16 BW_cutoff_idx, - Word16 frame_dms, Word16 fac_ns_pc, Word16 spec_inv_idx, Word8 *scratchBuffer + LC3PLUS_FrameDuration frame_dms, Word16 fac_ns_pc, Word16 spec_inv_idx, Word8 *scratchBuffer #ifdef ENABLE_HR_MODE , Word16 hrmode #endif @@ -94,7 +101,7 @@ void processNoiseFactor_fx(Word16 *fac_ns_idx, Word16 x_e, Word32 x[], #else Word16 xq[], #endif - Word16 gg, Word16 gg_e, Word16 BW_cutoff_idx, Word16 frame_dms, Word16 target_bytes, + Word16 gg, Word16 gg_e, Word16 BW_cutoff_idx, LC3PLUS_FrameDuration frame_dms, Word16 target_bytes, Word8 *scratchBuffer #ifdef ENABLE_HR_MODE , Word16 hrmode @@ -103,7 +110,7 @@ void processNoiseFactor_fx(Word16 *fac_ns_idx, Word16 x_e, Word32 x[], void processMdctShaping_fx(Word32 x[], #ifdef ENABLE_HR_MODE - Word32 scf[], + Word32 scf[], #else Word16 scf[], #endif @@ -154,7 +161,7 @@ void ProcessingIMDCT(Word32 y[], Word16 *y_e, Word16 x[], /* o: time signal out */ #endif Word16 wLen, - Word16 N, Word16 memLen, Word16 frame_dms, + Word16 N, Word16 memLen, LC3PLUS_FrameDuration frame_dms, Word16 concealMethod, Word16 bfi, Word16 prev_bfi, Word16 nbLostFramesInRow, AplcSetup *plcAd, Word8 *scratchBuffer #ifdef ENABLE_HR_MODE @@ -206,7 +213,7 @@ void pvq_dec_en1_norm_fx( /* */ Word32 * xq, /* o: en1 normalized decoded vector (Q14) */ #else Word16 * xq, /* o: en1 normalized decoded vector (Q14) */ -#endif +#endif const Word16 *y, /* i: decoded vector (non-scaled int) */ const Word16 kval_max, /* i: max possible K in Q0 kO or kA */ const Word16 dim, /* i: Length of vector */ @@ -237,6 +244,118 @@ void pvq_dec_scale_vec_fx(const Word32 *inQ29, Word16 adjGainQ13, Word32 *outQ); void pvq_dec_scale_vec_fx(const Word16 *inQ14, Word16 adjGainQ13, Word16 *outQ14); #endif +#ifdef CR9_C_ADD_1p25MS_LRSNS + +/* LRSNS functions needed in both encoder and decoder */ +Word16 snslr_remove_st1_DC_fQ11_fx( /* o : dc in Q11 */ + Word16 *scfq, /* i/o: b vector in Q11 */ + Word16 len /* i : length Q0*/); + +void lrsns_pvq_dec_scale_W16vec_fx( + const Word16 *inQ14, Word16 adjGainQ12, Word16 *inoutQ11 +); + +void snslr_st1B_vector_dec_fx( + Word16 idx, const Word16* LFCB, const Word16 *HFCB, const Word16* seg_cnt_cum, const Word16* idx12b_cb, Word16 *st1B_vectorQ11 +); +void snslr_st1C_vector_dec_fx( + Word16 idx, const Word8* CBW8, Word16 scaleQ4, Word16 inv_scaleQ15, Word16 v_len, Word16 cb_len, Word16 *st1C_vector +); + +#ifdef ENABLE_HR_MODE +void lrsns_pvq_dec_scale_W32vec_fx( + const Word32 *inQ27, Word16 adjGainQ12, Word32 *inQ27outQ26, Word16 *outQ11 +); +#endif /* ENABLE_HR_MODE*/ + +/* enc_dec common lrsns PVQ_FESS function */ +void pvq_fess_dec_en1_normQ30andQ14_fx( + const Word16 *y /*Q0*/, + Word16 y_up_bits, /*constant max upshift for each Q0 shape 0,1, 2(3,4,5) */ + Word32 L_norm_factor, + Word16 norm_factorQ, /*Q of L_norm_factor */ + Word16 len, + Word32* L_y_norm, /* Q30 */ + Word16 *y_norm); /* Q14 */ + + +void FESSdeenum_fx(Word16 dim_in_fx, /* i : dimension of vec_out typically (M-1 == 15) */ + Word16 n_env_fx, /* i : number of envelopes */ + Word16 n_shift_fx, /* i : number shifts */ + Word16 n_signs_fx, /* i : number signs */ + Word16 env_ind_fx, /* i:indx */ + Word16 shift_ind_fx, /* i:indx */ + Word16 sign_ind_fx, /* i:indx */ + Word16* vec_out_fx /* o : FESS integer pulse train , with signs applied */ +); + +Word16 snsQuantScfDecLR_fx( /* BER_flag */ + Word32* L_sns_vq_idx_fx, + Word32* L_scf_q_fx, + Word16* scf_q_fx, + Word16 pitch_rx_fx, + Word16 ltpf_rx_fx, + Word8 * scratch); + + +Word16 MSEsearchCbBIdxMap_fx( + const Word16 *scf, const Word16 *LFCB, const Word16 *HFCB, const Word16 *seg_cnt_cum, const Word16* idx12b_cb, Word16 v_len, Word16 cb_len, Word32* min_mse +); +Word16 MSEsearchGenericScaledW8_fx( + Word16 *scf, const Word8 *sns_CBW8, Word16 scaleQ4, Word16 inv_scaleQ15, Word16 v_len, Word16 cb_len, Word32* L_min_mse +); +Word16 MSEsearchGeneric_fx( + Word16 *scf, const Word16 *sns_CB, Word16 v_len, Word16 cb_len, Word32* L_min_mse +); + +void pvq_fess_enc_search_fx( + const Word16 *x_in, /* i: target vector to quantize Qin 0...M-1 */ + Word16 * y_Q0, /* o: raw integer pulses (non-scaled short) Q0 , length 3*M */ + Word16 * y_normQ14, /* o: normlized integer pulses (non-scaled short) Q14 , length 3*M */ + Word32 * L_y_normQ30, + Word16 * s_idx, /* o: quantized shape index, 0,1,2 */ + Word16 * g_idx, /* o: quantized gain index, 0..3, or 0..7 */ + Word16 * g_valQ12Ptr, /* o: quantized gain value, in Q12 -32767 == 7.99975 for best shape */ + Word16 * fixShapeNb, /* o: idx for the selected fix shape y_fix 0...3, relevant in the case s_idx==2 */ + Word16 * fixShiftIdxPtr, + Word32 * L_MSEQ22Ptr, /* o: 1 Q11+Q0+1 --> Q22 */ + Word8 * scratch +); + +Word32 snsQuantScfEncLRSt1ABC_fx(Word16* env, Word32* L_index, Word32 *L_min_mse_saveBCA_ptr_fx, + Word16* ind_saveB_ptr, Word16* st1_vectors, + Word16 pitch_rx, Word16 ltpf_rx, Word8* scratch); + +Word16 snsQuantScfEncLR_fx( /* o: bits spent on LRSNS-VQ envelope */ + Word16 scf_fx[], /* i: input scf M W16Q11 */ + Word32 *L_index_fx, /* o: SNS indeces . */ +#ifdef ENABLE_HR_MODE + Word32 *L_scf_q_fx, /* o: quantizefl_env scf M W16Q11 */ +#else + Word16 *scf_q_fx, /* o: quantizefl_env scf M W16Q11 */ +#endif + Word16 pitch_rx_fx, /*i: 0 or 1 */ + Word16 ltpf_rx_fx, /*i: 0 or 1 */ + Word8 * scratch); + + + +void dct16_fx(const Word16 *in, Word16 *out); +void dct16_updated_fx(const Word16 *in, Word16 *out); +void dct16_W32int_fx(const Word16 *in, Word16 *out); + +void writeSNSData_fx(UWord8 *bytes, Word16 *bp_side, Word16 *mask_side, LC3PLUS_FrameDuration frame_dms, Word32* L_scf_idx); + +#endif /* CR9_C_ADD_1p25MS_LRSNS */ + + +#ifdef NEW_SIGNALLING_SCHEME_1p25 +void writeLtpData_fx(UWord8 *ptr, Word16 *bp_side, Word16 *mask_side, Word16* ltpf_idx, Word16* Tx_ltpf); +#endif + + + + Word16 processAriEncoder_fx(UWord8 *bytes, Word16 bp_side, Word16 mask_side, Word16 nbbits, #ifdef ENABLE_HR_MODE Word32 xq[], @@ -250,7 +369,7 @@ Word16 processAriEncoder_fx(UWord8 *bytes, Word16 bp_side, Word16 mask_side, Wor void processAriDecoder_fx(UWord8 *bytes, Word16 *bp_side, Word16 *mask_side, Word16 nbbits, Word16 L_spec, Word16 fs_idx, Word16 enable_lpc_weighting, Word16 tns_numfilters, Word16 lsbMode, Word16 lastnz, Word16 *bfi, Word16 *tns_order, Word16 fac_ns_idx, Word16 gg_idx, - Word16 frame_dms, + LC3PLUS_FrameDuration frame_dms, Word16 n_pc, Word16 be_bp_left, Word16 be_bp_right, Word16 mode, Word16 *spec_inv_idx, Word16 *b_left, Word16 *resBits, @@ -276,7 +395,7 @@ void processAriDecoderScaling_fx( void processApplyGlobalGain_fx(Word32 x[], Word16 *x_e, Word16 xLen, Word16 global_gain_idx, Word16 global_gain_off); void processPerBandEnergy_fx(Word32 *d2_fx, Word16 *d2_fx_exp, Word32 *d_fx, Word16 d_fx_exp, - const Word16 *band_offsets, Word16 fs_idx, Word16 n_bands, Word16 linear, Word16 frame_dms, + const Word16 *band_offsets, Word16 fs_idx, Word16 n_bands, Word16 linear, LC3PLUS_FrameDuration frame_dms, Word8 *scratchBuffer #ifdef ENABLE_HR_MODE , Word16 hrmode @@ -286,28 +405,35 @@ void processPerBandEnergy_fx(Word32 *d2_fx, Word16 *d2_fx_exp, Word32 *d_fx, Wor void processNearNyquistdetector_fx(Word16 *near_nyquist_flag, const Word16 fs_idx, const Word16 near_nyquist_index, const Word16 bands_number, const Word32 *ener_fx, const Word16 ener_fx_exp #ifdef ENABLE_HR_MODE - , Word16 frame_dms , Word16 hrmode); -#else - ); + , LC3PLUS_FrameDuration frame_dms , Word16 hrmode #endif -void processDetectCutoffWarped_fx(Word16 *bw_idx, Word32 *d2_fx, Word16 d2_fx_exp, Word16 fs_idx, Word16 frame_dms); + ); + +void processDetectCutoffWarped_fx(Word16 *bw_idx, Word32 *d2_fx, Word16 d2_fx_exp, Word16 fs_idx, LC3PLUS_FrameDuration frame_dms); void process_resamp12k8_fx(Word16 x[], Word16 x_len, Word16 mem_in[], Word16 mem_in_len, Word32 mem_50[], Word16 mem_out[], Word16 mem_out_len, Word16 y[], Word16 *y_len, Word16 fs_idx, - Word16 frame_dms, Word8 *scratchBuffer + LC3PLUS_FrameDuration frame_dms, Word8 *scratchBuffer , Word16 bps ); void process_olpa_fx(Word16 *mem_s6k4_exp, Word16 mem_s12k8[], Word16 mem_s6k4[], Word16 *pitch, Word16 *s12k8, - Word16 len, Word16 *normcorr, Word16 *mem_pitch, + Word16 len, Word16 *normcorr, Word16 *mem_pitch, Word16 *pitch_flag, - Word16 s12k8_exp, Word16 frame_dms, Word8 *scratchBuffer); + Word16 s12k8_exp, LC3PLUS_FrameDuration frame_dms, Word8 *scratchBuffer); void process_ltpf_coder_fx(Word16 *bits, Word16 ol_pitch, Word16 ltpf_enable, Word16 *old_wsp_exp, Word16 *old_wsp, Word16 old_wsplen, Word16 *param, Word16 *wsp, Word16 len, Word16 *mem_normcorr, Word16 *mem_mem_normcorr, Word16 ol_normcorr, Word16 *mem_ltpf_on, Word16 *mem_ltpf_pitch, - Word16 wsp_exp, Word16 frame_dms, Word8 *scratchBuffer - , Word16 hrmode + Word16 wsp_exp, LC3PLUS_FrameDuration frame_dms, Word8 *scratchBuffer + , Word16 hrmode +#ifdef CR9_C_ADD_1p25MS +#ifdef NEW_SIGNALLING_SCHEME_1p25 + , Word16* Tx_ltpf +#else + , Word16 Tx_ltpf +#endif +#endif ); void process_ltpf_decoder_fx(Word16 *x_e, Word16 L_frame, Word16 old_x_len, Word16 fs_idx, Word16 old_y_len, @@ -315,14 +441,22 @@ void process_ltpf_decoder_fx(Word16 *x_e, Word16 L_frame, Word16 old_x_len, Word Word16 ltpf_active, Word16 pitch_index, Word16 *old_pitch_int, Word16 *old_pitch_fr, Word16 *old_gain, Word16 *mem_ltpf_active, Word16 scale_fac_idx, Word16 bfi, Word16 concealMethod, - Word16 damping, Word16 *old_scale_fac_idx, - Word32 *rel_pitch_change, Word16 hrmode, Word16 frame_dms, - Word8 *scratchBuffer); + Word16 damping, Word16 *old_scale_fac_idx, + Word32 *rel_pitch_change, Word16 hrmode, LC3PLUS_FrameDuration frame_dms, + Word8 *scratchBuffer +#ifdef CR9_C_ADD_1p25MS + , Word16* mem_continuation, Word16* mem_pitch_int_prev, + Word16* mem_pitch_fr_prev, Word16* mem_beta_idx_prev, Word16* mem_gain_prev, Word16 *mem_ltpf_active_prev, Word16* pitch_stability_counter +#endif + ); void attack_detector_fx(LC3PLUS_Enc *enc, EncSetup *setup, Word16 *input, Word16 input_scaling, void *scratch); void processSnsComputeScf_fx(Word32 *d2_fx, Word16 d2_fx_exp, Word16 fs_idx, Word16 n_bands, Word16 *scf, Word16 scf_smoothing_enabled, Word16 attdec_damping_factor, Word8 *scratchBuffer, Word16 sns_damping +#ifdef CR9_C_ADD_1p25MS + , LC3PLUS_FrameDuration frame_dms, Word16 norm_corr, Word16 *LT_normcorr +#endif ); void processSnsQuantizeScfEncoder_fx(Word16 scf[], /* i: input scf M */ @@ -338,7 +472,7 @@ Word16 processSnsQuantizeScfDecoder_fx( /* Word32 *L_prm_idx, /* i: indeces */ #ifdef ENABLE_HR_MODE Word32 scf_q[], -#else +#else Word16 scf_q[], #endif Word8 *scratchBuffer); /* o: M */ @@ -366,7 +500,7 @@ void processPLCmain_fx(Word16 plcMeth, Word16 *concealMethod, Word16 *nbLostFram Word16 *ola_mem_exp, Word16 q_old_d_fx[], Word16 *q_old_fx_exp, Word32 q_d_fx[], Word16 *q_fx_exp, Word16 yLen, Word16 fs_idx, const Word16 *band_offsets, Word16 bands_number, Word16 *damping, Word16 old_pitch_int, Word16 old_pitch_fr, Word16 *ns_cum_alpha, Word16 *ns_seed, - AplcSetup *plcAd, Word16 frame_dms, Word8 *scratchBuffer, Word16 *pc_nbLostFramesInRow + AplcSetup *plcAd, LC3PLUS_FrameDuration frame_dms, Word8 *scratchBuffer, Word16 *pc_nbLostFramesInRow #ifdef ENABLE_HR_MODE , Word16 hrmode #endif @@ -395,7 +529,7 @@ void processPLCUpdateAfterIMDCT_fx(Word16 x_fx[], Word16 q_fx_exp, Word16 concea Word16 scf_q[], Word16 *ns_cum_alpha, AplcSetup *plcAd); void processPLCclassify_fx(Word16 plcMeth, Word16 *concealMethod, Word16 *nbLostFramesInRow, Word16 bfi, - Word16 ltpf_mem_pitch_int, Word16 frame_length, Word16 frame_dms, Word16 fs_idx, Word16 yLen, + Word16 ltpf_mem_pitch_int, Word16 frame_length, LC3PLUS_FrameDuration frame_dms, Word16 fs_idx, Word16 yLen, Word16 q_old_d_fx[], const Word16 *band_offsets, Word16 bands_number, AplcSetup *plcAd, Word8 *scratchBuffer #ifdef ENABLE_HR_MODE , Word16 hrmode @@ -403,7 +537,7 @@ void processPLCclassify_fx(Word16 plcMeth, Word16 *concealMethod, Word16 *nbLost ); void processPLCapply_fx( - Word16 *concealMethod, + Word16 *concealMethod, Word16 nbLostFramesInRow, Word16 bfi, Word16 prev_bfi, Word16 frame_length, Word16 la_zeroes, #ifdef ENABLE_HR_MODE @@ -414,7 +548,7 @@ void processPLCapply_fx( Word16 x_fx[], Word16 ola_mem[], Word16 *ola_mem_exp, Word16 q_old_d_fx[], Word16 *q_old_fx_exp, Word32 q_d_fx[], Word16 *q_fx_exp, Word16 yLen, Word16 fs_idx, Word16 *damping, Word16 old_pitch_int, - Word16 old_pitch_fr, Word16 *ns_cum_alpha, Word16 *ns_seed, Word16 frame_dms, AplcSetup *plcAd, + Word16 old_pitch_fr, Word16 *ns_cum_alpha, Word16 *ns_seed, LC3PLUS_FrameDuration frame_dms, AplcSetup *plcAd, Word8 *scratchBuffer #ifdef ENABLE_HR_MODE , Word16 hrmode @@ -427,15 +561,15 @@ void processPLCNoiseSubstitution_fx(Word32 spec[], Word16 spec_prev[], Word16 L_ void processPLCDampingScrambling_main_fx(Word16 bfi, Word16 concealMethod, Word16 ns_nbLostFramesInRow, Word16 *cum_fflcAtten, Word16 pc_nbLostFramesInRow, Word16 *ns_seed, Word16 *pc_seed, Word16 pitch_present_bfi1, Word16 pitch_present_bfi2, Word32 spec[], Word16 *q_fx_exp, Word16 *q_old_d_fx, - Word16 *q_old_fx_exp, Word16 L_spec, Word16 stabFac, Word16 frame_dms, + Word16 *q_old_fx_exp, Word16 L_spec, Word16 stabFac, LC3PLUS_FrameDuration frame_dms, Word16 *cum_fading_slow, Word16 *cum_fading_fast, Word16 spec_inv_idx - , UWord8 plc_fadeout_type + , UWord8 plc_fadeout_type ); void processPLCDampingScrambling_fx(Word32 spec[], Word16 L_spec, Word16 nbLostFramesInRow, Word16 stabFac, Word16 processDampScramb, - Word16 *cum_fflcAtten, Word16 pitch_present, Word16 frame_dms, Word16 *cum_fading_slow, + Word16 *cum_fflcAtten, Word16 pitch_present, LC3PLUS_FrameDuration frame_dms, Word16 *cum_fading_slow, Word16 *cum_fading_fast, Word16 *seed, Word16 spec_inv_idx - , UWord8 plc_fadeout_type + , UWord8 plc_fadeout_type ); void processLagwin_fx(Word32 r[], const Word32 w[], Word16 m); @@ -443,7 +577,7 @@ void processLagwin_fx(Word32 r[], const Word32 w[], Word16 m); void processInverseODFT_fx(Word32 *r_fx, Word16 *r_fx_exp, Word32 *d2_fx, Word16 d2_fx_exp, Word16 n_bands, Word16 lpc_order, Word8 *scratchBuffer); -void processPreEmphasis_fx(Word32 *d2_fx, Word16 *d2_fx_exp, Word16 fs_idx, Word16 n_bands, Word16 frame_dms, +void processPreEmphasis_fx(Word32 *d2_fx, Word16 *d2_fx_exp, Word16 fs_idx, Word16 n_bands, LC3PLUS_FrameDuration frame_dms, Word8 *scratchBuffer); void processPLCLpcScaling_fx(Word32 tdc_A_32[], Word16 tdc_A_16[], Word16 m); @@ -451,24 +585,24 @@ void processPLCLpcScaling_fx(Word32 tdc_A_32[], Word16 tdc_A_16[], Word16 m); void processPLCcomputeStabFac_main(Word16 scf_q[], Word16 old_scf_q[], Word16 old_old_scf_q[], Word16 bfi, Word16 prev_bfi, Word16 prev_prev_bfi, Word16 *stab_fac); -void processPLCUpdateXFP_w_E_hist_fx(Word16 prev_bfi, Word16 bfi, - Word16 *xfp_fx, Word16 xfp_exp_fx,Word16 margin_xfp, - Word16 fs_idx, - Word32 *L_oold_xfp_w_E_fx, Word16 *oold_xfp_w_E_exp_fx, - Word32 *L_old_xfp_w_E_fx, Word16 *old_xfp_w_E_exp_fx, - Word16 *oold_Ltot_exp_fx, Word16 *old_Ltot_exp_fx); +void processPLCUpdateXFP_w_E_hist_fx(Word16 prev_bfi, Word16 bfi, + Word16 *xfp_fx, Word16 xfp_exp_fx,Word16 margin_xfp, + Word16 fs_idx, + Word32 *L_oold_xfp_w_E_fx, Word16 *oold_xfp_w_E_exp_fx, + Word32 *L_old_xfp_w_E_fx, Word16 *old_xfp_w_E_exp_fx, + Word16 *oold_Ltot_exp_fx, Word16 *old_Ltot_exp_fx); void processTimeDomainConcealment_Apply_fx(const Word16 pitch_int, const Word16 preemphFac_fx, const Word16 *A_fx, const Word16 lpc_order, const Word16 *pcmbufHist_fx, - const Word16 frame_length, const Word16 frame_dms, const Word16 fs_idx, + const Word16 frame_length, const LC3PLUS_FrameDuration frame_dms, const Word16 fs_idx, const Word16 nbLostFramesInRow, const Word16 overlap, - const Word16 stabFac_fx, Word16 *fract, Word16 *seed_fx, + const Word16 stabFac_fx, Word16 *fract, Word16 *seed_fx, Word32 *gain_c_fx, Word16 *synth_fx, Word16 *Q_syn, Word16 *alpha, Word16 max_len_pcm_plc, Word16 harmonicBuf_fx[MAX_PITCH], Word16 synthHist_fx[M], Word16 *const harmonicBuf_Q, Word8 *scratchBuffer , UWord8 plc_fadeout_type - , Word16 *alpha_type_2_table + ,Word16 *alpha_type_2_table ); void processTdac_fx(Word16 *ola_mem, Word16 *ola_mem_exp, const Word16 *synth, const Word16 synth_exp, @@ -530,8 +664,8 @@ void trans_burst_ana_fx(const Word16 *xfp, /* i : Input signal Word16 * Xavg, /* o : Frequency group average gain to fade to */ Word16 Q_spec, Word32 L_oold_xfp_w_E_fx, Word16 oold_xfp_w_E_exp_fx, Word16 oold_Ltot_exp_fx, Word16 *oold_grp_shape_fx, Word32 L_old_xfp_w_E_fx, Word16 old_xfp_w_E_exp_fx, - Word16 old_Ltot_exp_fx, Word16 *old_grp_shape_fx, - Word16 fadeout, + Word16 old_Ltot_exp_fx, Word16 *old_grp_shape_fx, + Word16 fadeout, Word32 *L_Xavg, /* full scale average band amplitudes */ Word8 *scratchBuffer); @@ -540,9 +674,9 @@ void spec_ana_fx(Word16 *xfp, Word16 *, Word32 *, Word16 *, Word16 *, const Word void subst_spec_fx(const Word16 *, const Word32 *, Word16 *, const Word16, Word16 *, const Word16 *, const Word16, const Word16 *, const Word16, Word16 *, const Word16 *, const Word16 *, const Word16 *, const Word16 - ,const Word16, + ,const Word16, Word16*, - const Word32 * + const Word32 * ); void rec_frame_fx(Word16 * X, /* i : FFT spectrum */ @@ -595,8 +729,8 @@ void hq_phase_ecu_fx(const Word16 *prevsynth, /* i : buffer of previously synth Word8 *scratchBuffer /* Size = 2 * MAX_LGW + 8 * MAX_LPROT + 12 * MAX_L_FRAME */ ); -Word16 -plc_xcorr_lc_fx(/* o: quantized output xcorr in Q15 [ 0 ..32767 ] = [0. 1.0[ */ + +Word16 plc_xcorr_lc_fx(/* o: quantized output xcorr in Q15 [ 0 ..32767 ] = [0. 1.0[ */ Word16 * pcmbuf_fx, /* NB should be an already dynamically upscaled buffer with about 0...1 bits margin */ Word16 max_len_pcm_plc, /* Q0 size of pcmbuf_fx */ @@ -614,7 +748,7 @@ Word16 initQV(Word16 SR_idx, Word32 BR); void processEstimateGlobalGain_fx(Word32 x[], Word16 x_e, Word16 lg, Word16 sqTargetBits, #ifdef ENABLE_HR_MODE Word32 *gain, -#else +#else Word16 *gain, #endif Word16 *gain_e, @@ -622,7 +756,11 @@ void processEstimateGlobalGain_fx(Word32 x[], Word16 x_e, Word16 lg, Word16 sqTa Word32 *targetBitsOff, Word16 *old_targetBits, Word16 old_specBits, Word8 *scratchBuffer #ifdef ENABLE_HR_MODE - , Word16 hrmode, Word16 regBits, Word16 frame_dms + , Word16 hrmode, Word16 regBits, LC3PLUS_FrameDuration frame_dms +#else +#ifdef FIX_BOTH_1p25_TEST_NEW_GG_EST2 + , LC3PLUS_FrameDuration frame_dms +#endif #endif ); @@ -635,7 +773,7 @@ void processAdjustGlobalGain_fx(Word16 *gg_idx, Word16 gg_idx_min, Word16 gg_idx Word16 *gain_e, Word16 target, Word16 nBits, Word16 *gainChange, Word16 fs_idx #ifdef ENABLE_HR_MODE - , Word16 hrmode, Word16 frame_dms + , Word16 hrmode, LC3PLUS_FrameDuration frame_dms #endif ); @@ -645,8 +783,8 @@ void processScalarQuant_fx(Word32 x[], Word16 x_e, Word16 xq[], Word16 L_frame, void processQuantizeSpec_fx(Word32 x[], Word16 x_e, Word32 gain, Word16 gain_e, Word32 xq[], Word16 nt, Word16 target, Word16 totalBits, Word16 *nBits, Word16 *nBits2, Word16 fs_idx, Word16 *lastnz, Word16 *codingdata, Word16 *lsbMode, Word16 mode, Word16 hrmode); -#else -void processQuantizeSpec_fx(Word32 x[], Word16 x_e, Word16 gain, Word16 gain_e, Word16 xq[], Word16 nt, +#else +void processQuantizeSpec_fx(Word32 x[], Word16 x_e, Word16 gain, Word16 gain_e, Word16 xq[], Word16 nt, Word16 target, Word16 totalBits, Word16 *nBits, Word16 *nBits2, Word16 fs_idx, Word16 *lastnz, Word16 *codingdata, Word16 *lsbMode, Word16 mode); @@ -664,6 +802,9 @@ void processResidualCoding_fx(Word16 x_e, Word32 x[], #ifdef ENABLE_HR_MODE , Word16 hrmode #endif +#if defined (CR9_C_ADD_1p25MS) + , LC3PLUS_FrameDuration frame_dms +#endif ); void scale_signal24_fx(Word32 x[], /* i: time input signal */ @@ -696,8 +837,8 @@ void fec_encoder(Word16 mode, Word16 epmr, UWord8 *iobuf, Word16 data_bytes, Wor int fec_decoder(UWord8 *iobuf, Word16 slot_bytes, int *data_bytes, Word16 *epmr, Word16 ccc_flag, Word16 *n_pccw, int *bfi, Word16 *be_bp_left, Word16 *be_bp_right, Word16 *n_pc, Word16 *m_fec, void *scratch); -void processPCmain_fx(Word16 rframe, Word16 *bfi, Word16 yLen, Word16 frame_dms, Word16 q_old_res_fx[], - Word16 *q_old_res_fx_exp, +void processPCmain_fx(Word16 rframe, Word16 *bfi, Word16 yLen, LC3PLUS_FrameDuration frame_dms, Word16 q_old_res_fx[], + Word16 *q_old_res_fx_exp, #ifdef ENABLE_HR_MODE Word32 q_res_fx[], #else @@ -707,7 +848,7 @@ void processPCmain_fx(Word16 rframe, Word16 *bfi, Word16 yLen, Word16 frame_dms, Word16 pitch_present, Word16 stab_fac, Word32 q_d_fx[], Word16 *q_fx_exp, Word16 gg_idx, Word16 gg_idx_off, Word16 *prev_gg, Word16 *prev_gg_e, Word16 *BW_cutoff_idx_nf, Word16 *prev_BW_cutoff_idx_nf, Word16 fac_ns_idx, Word16 *prev_fac_ns_fx, Word16 *pc_nbLostFramesInRow); -void processPCclassify_fx(Word16 pitch_present, Word16 frame_dms, Word16 q_old_d_fx[], Word16 q_old_res_fx[], +void processPCclassify_fx(Word16 pitch_present, LC3PLUS_FrameDuration frame_dms, Word16 q_old_d_fx[], Word16 q_old_res_fx[], Word16 yLen, Word16 spec_inv_idx, Word16 stab_fac, Word16 *bfi); void processPCapply_fx(Word16 yLen, Word16 q_old_res_fx[], Word16 *q_old_res_fx_exp, #ifdef ENABLE_HR_MODE @@ -745,12 +886,28 @@ void write_indice_backward(UWord8 *ptr, Word16 *bp, Word16 *mask, Word16 indice, void processEncoderEntropy(UWord8 *bytes, Word16 *bp_side, Word16 *mask_side, Word16 nbbits, Word16 targetBytes, Word16 L_spec, Word16 BW_cutoff_bits, Word16 tns_numfilters, Word16 lsbMode, Word16 lastnz, Word16 *tns_order, Word16 fac_ns_idx, Word16 gg_idx, Word16 BW_cutoff_idx, Word16 *ltpf_idx, - Word32 *L_scf_idx, Word16 bfi_ext, Word16 fs_idx); + Word32 *L_scf_idx, Word16 bfi_ext, Word16 fs_idx +#ifdef CR9_C_ADD_1p25MS + , LC3PLUS_FrameDuration frame_dms, Word16* Tx_ltpf +#endif + ); void processDecoderEntropy_fx(UWord8 *bytes, Word16 *bp_side, Word16 *mask_side, Word16 nbbits, Word16 L_spec, Word16 fs_idx, Word16 BW_cutoff_bits, Word16 *tns_numfilters, Word16 *lsbMode, Word16 *lastnz, Word16 *bfi, Word16 *tns_order, Word16 *fac_ns_idx, Word16 *gg_idx, - Word16 *BW_cutoff_idx, Word16 *ltpf_idx, Word32 *L_scf_idx, Word16 frame_dms); + Word16 *BW_cutoff_idx, Word16 *ltpf_idx, Word32 *L_scf_idx, LC3PLUS_FrameDuration frame_dms +#ifdef CR9_C_ADD_1p25MS + , Word16 rx_status[2], Word16* mem_continuation +#ifdef NEW_SIGNALLING_SCHEME_1p25 + , Word16 *ltpfinfo_frame_cntr_fx +#endif +#endif + ); + +#ifdef NEW_SIGNALLING_SCHEME_1p25 +void readLtpData_fx(UWord8* ptr, Word16* bfiPtr, Word16* mask_side, Word16* bp_side, Word16* ltpf_idx, Word16* rx_status, + Word16* ltpfinfo_frame_cntr_fx, Word16* mem_continuation); +#endif #ifdef ENABLE_PADDING int paddingDec_fx(UWord8 *bytes, Word16 nbbits, Word16 L_spec, Word16 BW_cutoff_bits, Word16 ep_enabled, @@ -759,7 +916,7 @@ int paddingDec_fx(UWord8 *bytes, Word16 nbbits, Word16 L_spec, Word16 BW_cuto Word16 read_bit(UWord8 *ptr, Word16 *bp, Word16 *mask); -/* setup_enc_lc3.c */ +/* setup_enc_lc3plus.c */ int alloc_encoder(LC3PLUS_Enc *encoder, int samplerate, int channels); void set_enc_frame_params(LC3PLUS_Enc *encoder); LC3PLUS_Error update_enc_bitrate(LC3PLUS_Enc *encoder, int bitrate); @@ -770,7 +927,7 @@ LC3PLUS_Error FillEncSetup(LC3PLUS_Enc *encoder, int samplerate, int channels , int32_t lfe_channel_array[] ); -/* setup_dec_lc3.c */ +/* setup_dec_lc3plus.c */ int alloc_decoder(LC3PLUS_Dec *decoder, int samplerate, int channels); void set_dec_frame_params(LC3PLUS_Dec *decoder); LC3PLUS_Error update_dec_bitrate(LC3PLUS_Dec *decoder, int ch, Word16 nBytes); @@ -786,6 +943,10 @@ LC3PLUS_Error Dec_LC3PLUS(LC3PLUS_Dec *decoder, UWord8 *input, int input_bytes, void *balloc(void *base, size_t *base_size, size_t size); -Word16 type_2_fadeout_fx(Word16 nbLostFramesInRow, Word16 frame_dms); +#ifdef FIX_BOTH_1p25_WB_GLOBGAINOFFSET_NONBE +Word16 calc_GGainOffset_1p25_fx(Word16 total_bits, Word16 fs_idx); +#endif -#endif +Word16 type_2_fadeout_fx(Word16 nbLostFramesInRow, LC3PLUS_FrameDuration frame_dms); + +#endif /* FUNCTIONS_H */ diff --git a/lib_lc3plus/imdct_fx.c b/lib_lc3plus/imdct_fx.c index 8fdf06671..70e76c8c5 100644 --- a/lib_lc3plus/imdct_fx.c +++ b/lib_lc3plus/imdct_fx.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,6 +7,8 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "functions.h" void ProcessingIMDCT( @@ -28,7 +30,7 @@ void ProcessingIMDCT( Word16 wLen, /* i: window length */ Word16 N, /* i: block size */ Word16 memLen, /* i: overlap add buffer size */ - Word16 frame_dms, /* i: frame size in ms */ + LC3PLUS_FrameDuration frame_dms, /* i: frame size in ms */ Word16 concealMethod, /* i: concealment method */ Word16 bfi, /* i: bad frame indicator */ Word16 prev_bfi, /* i: previous bad frame indicator */ @@ -82,18 +84,24 @@ void ProcessingIMDCT( { SWITCH (frame_dms) { - case 25: +#ifdef CR9_C_ADD_1p25MS + case LC3PLUS_FRAME_DURATION_1p25MS: + max_bw = MAX_BW >> 3; move16(); + BREAK; +#endif + case LC3PLUS_FRAME_DURATION_2p5MS: max_bw = MAX_BW >> 2; move16(); BREAK; - case 50: + case LC3PLUS_FRAME_DURATION_5MS: max_bw = MAX_BW >> 1; move16(); BREAK; - case 75: + case LC3PLUS_FRAME_DURATION_7p5MS: max_bw = (MAX_BW >> 2) * 3; move16(); BREAK; - case 100: + case LC3PLUS_FRAME_DURATION_10MS: max_bw = MAX_BW; move16(); BREAK; + case LC3PLUS_FRAME_DURATION_UNDEFINED: assert(0); } } @@ -116,11 +124,11 @@ void ProcessingIMDCT( #else dct_IV(y, y_e, N, workBuffer); #endif - y_s = getScaleFactor32_lc3plus(y, N); + y_s = getScaleFactor32(y, N); y_s = sub(y_s, 1); *y_e = sub(*y_e, y_s + 3); /* mdct window is scaled by pow(2,x) */ /* N<=20 only happens for 2.5ms frames in NB */ - if (sub(N, 20) <= 0) + if (sub(N, 30) <= 0) { *y_e = add(*y_e, 2); } @@ -300,7 +308,7 @@ void Processing_ITDA_WIN_OLA( L_y = L_x_tda; /* use same variables naming as in IMDCT for DCT-IV output signal y */ - y_s = getScaleFactor32_lc3plus(L_y, N); + y_s = getScaleFactor32(L_y, N); y_s = sub(y_s, 1); /* add 1 bit margin , y_s is now initial tda upscaling factor */ diff --git a/lib_lc3plus/lc3.c b/lib_lc3plus/lc3plus.c similarity index 88% rename from lib_lc3plus/lc3.c rename to lib_lc3plus/lc3plus.c index e8a73aec8..aed8e029b 100644 --- a/lib_lc3plus/lc3.c +++ b/lib_lc3plus/lc3plus.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,35 +7,35 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "defines.h" #include "functions.h" -#include "lc3.h" -#include "setup_dec_lc3.h" -#include "setup_enc_lc3.h" +#include "lc3plus.h" +#include "setup_dec_lc3plus.h" +#include "setup_enc_lc3plus.h" #define RETURN_IF(cond, error) \ if (cond) \ return (error) -#ifndef FIX_IVAS_LC3PLUS_WARNINGS #ifdef SUBSET_NB -#pragma message("- SUBSET_NB") +// #pragma message("- SUBSET_NB") #endif #ifdef SUBSET_WB -#pragma message("- SUBSET_WB") +// #pragma message("- SUBSET_WB") #endif #ifdef SUBSET_SSWB -#pragma message("- SUBSET_SSWB") +// #pragma message("- SUBSET_SSWB") #endif #ifdef SUBSET_SWB -#pragma message("- SUBSET_SWB") +// #pragma message("- SUBSET_SWB") #endif #ifdef SUBSET_FB -#pragma message("- SUBSET_FB") +// #pragma message("- SUBSET_FB") #endif #ifdef SUBSET_UB -#pragma message("- SUBSET_UB") -#endif +// #pragma message("- SUBSET_UB") #endif /* ensure api header constants are up to date */ @@ -86,6 +86,7 @@ int lc3plus_samplerate_supported(int samplerate) #endif default: return 0; } + return 0; } static int lc3plus_plc_mode_supported(LC3PLUS_PlcMode plc_mode) @@ -96,19 +97,24 @@ static int lc3plus_plc_mode_supported(LC3PLUS_PlcMode plc_mode) return 1; default: return 0; } + return 0; } -static int lc3plus_frame_size_supported(int frame_dms) +static int lc3plus_frame_size_supported(LC3PLUS_FrameDuration frame_dms) { switch (frame_dms) { - case 25: /* fallthru */ - case 50: /* fallthru */ - case 75: /* fallthru */ - case 100: +#ifdef CR9_C_ADD_1p25MS + case LC3PLUS_FRAME_DURATION_1p25MS: /* fallthru */ +#endif + case LC3PLUS_FRAME_DURATION_2p5MS: /* fallthru */ + case LC3PLUS_FRAME_DURATION_5MS: /* fallthru */ + case LC3PLUS_FRAME_DURATION_7p5MS: /* fallthru */ + case LC3PLUS_FRAME_DURATION_10MS: return 1; default: return 0; } + return 0; } static int null_in_list(void **list, int n) @@ -121,9 +127,9 @@ static int null_in_list(void **list, int n) /* return pointer to aligned base + base_size, *base_size += size + 4 bytes align */ void *balloc(void *base, size_t *base_size, size_t size) { - uintptr_t ptr = ((uintptr_t)base + *base_size + 3) & (uintptr_t)(~3); + uintptr_t ptr = ((uintptr_t)base + *base_size + 3) & ~3; assert((uintptr_t)base % 4 == 0); /* base must be 4-byte aligned */ - *base_size = (*base_size + size + 3) & (uintptr_t)(~3); + *base_size = (*base_size + size + 3) & ~3; return (void *)ptr; } @@ -213,9 +219,13 @@ int lc3plus_enc_get_real_bitrate(const LC3PLUS_Enc *encoder) { totalBytes += encoder->channel_setup[ch]->targetBytes; } - +#ifdef CR9_C_ADD_1p25MS + int frame_ns = (int)(1250L*(encoder->frame_dms)); + int bitrate = (long long int)((totalBytes * 8L) * 1000000L + (frame_ns - 1L)) / (frame_ns); +#else int bitrate = (totalBytes * 80000.0 + encoder->frame_dms - 1) / encoder->frame_dms; - +#endif + if (encoder->fs_in == 44100) { int rem = bitrate % 480; @@ -254,11 +264,15 @@ LC3PLUS_Error lc3plus_enc_set_ep_mode_request(LC3PLUS_Enc *encoder, LC3PLUS_EpMo return LC3PLUS_OK; } -LC3PLUS_Error lc3plus_enc_set_frame_dms(LC3PLUS_Enc *encoder, int frame_dms) +LC3PLUS_Error lc3plus_enc_set_frame_dms(LC3PLUS_Enc *encoder, LC3PLUS_FrameDuration frame_dms) { RETURN_IF(encoder == NULL, LC3PLUS_NULL_ERROR); RETURN_IF(!lc3plus_frame_size_supported(frame_dms), LC3PLUS_FRAMEMS_ERROR); RETURN_IF(encoder->lc3_br_set, LC3PLUS_BITRATE_SET_ERROR); +#ifdef CR9_C_ADD_1p25MS + RETURN_IF(encoder->fs == 8000 && frame_dms == LC3PLUS_FRAME_DURATION_1p25MS, LC3PLUS_SAMPLERATE_ERROR); +#endif + encoder->frame_dms = frame_dms; set_enc_frame_params(encoder); return LC3PLUS_OK; @@ -385,12 +399,15 @@ LC3PLUS_EpModeRequest lc3plus_dec_get_ep_mode_request(const LC3PLUS_Dec *decoder return (LC3PLUS_EpModeRequest)decoder->epmr; } -LC3PLUS_Error lc3plus_dec_set_frame_dms(LC3PLUS_Dec *decoder, int frame_dms) +LC3PLUS_Error lc3plus_dec_set_frame_dms(LC3PLUS_Dec *decoder, LC3PLUS_FrameDuration frame_dms) { RETURN_IF(decoder == NULL, LC3PLUS_NULL_ERROR); RETURN_IF(!lc3plus_frame_size_supported(frame_dms), LC3PLUS_FRAMEMS_ERROR); - RETURN_IF(decoder->plcMeth == 2 && frame_dms != 100, LC3PLUS_FRAMEMS_ERROR); - + RETURN_IF(decoder->plcMeth == 2 && frame_dms != LC3PLUS_FRAME_DURATION_10MS, LC3PLUS_FRAMEMS_ERROR); +#ifdef CR9_C_ADD_1p25MS + RETURN_IF(decoder->fs == 8000 && frame_dms == LC3PLUS_FRAME_DURATION_1p25MS, LC3PLUS_SAMPLERATE_ERROR); +#endif + decoder->frame_dms = frame_dms; set_dec_frame_params(decoder); return LC3PLUS_OK; diff --git a/lib_lc3plus/lc3.h b/lib_lc3plus/lc3plus.h similarity index 95% rename from lib_lc3plus/lc3.h rename to lib_lc3plus/lc3plus.h index 1021afa14..2ac69c9a9 100644 --- a/lib_lc3plus/lc3.h +++ b/lib_lc3plus/lc3plus.h @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,7 +7,7 @@ * estoppel or otherwise. * ******************************************************************************/ -/*! \file lc3.h +/*! \file lc3plus.h * This header provides the API for LC3plus. * * This library is targeting devices with extreme memory limitations, so memory management @@ -23,11 +23,12 @@ */ #ifndef LC3PLUS_H -#define LC3PLUS_H - +#define LC3PLUS_H #define ENABLE_HR_MODE #ifndef _MSC_VER +#include "options.h" +#include "wmc_auto.h" #include #else typedef __int16 int16_t; @@ -38,7 +39,7 @@ typedef __int32 int32_t; #define LC3PLUS_VERSION_INT(major, minor, micro) (((major) << 16) | ((minor) << 8) | (micro)) /*! Version number to ensure header and binary are matching. */ -#define LC3PLUS_VERSION LC3PLUS_VERSION_INT(1, 7, 4) +#define LC3PLUS_VERSION LC3PLUS_VERSION_INT(1, 8, 0) /*! Maximum number of supported channels. The actual binary might support * less, use lc3plus_channels_supported() to check. */ @@ -58,6 +59,9 @@ typedef __int32 int32_t; #define LC3PLUS_MAX_BYTES 870 #endif + + + /*! Maximum size needed to store encoder state. */ #ifdef ENABLE_HR_MODE #define LC3PLUS_ENC_MAX_SIZE 12628 @@ -72,6 +76,18 @@ typedef __int32 int32_t; #define LC3PLUS_DEC_MAX_SIZE 28446 #endif +#ifdef LRSNS_MORE_SCRATCH + +#ifdef ENABLE_HR_MODE +#define LC3PLUS_ENC_MAX_SCRATCH_SIZE (2*32767) +#define LC3PLUS_DEC_MAX_SCRATCH_SIZE (2*32767) +#else +#define LC3PLUS_ENC_MAX_SCRATCH_SIZE (2*32767) +#define LC3PLUS_DEC_MAX_SCRATCH_SIZE (2*32767) +#endif + +#else + /*! Maximum scratch size needed by lc3plus_enc16() or lc3plus_enc24().*/ #ifdef ENABLE_HR_MODE #define LC3PLUS_ENC_MAX_SCRATCH_SIZE 45624 @@ -85,6 +101,20 @@ typedef __int32 int32_t; #else #define LC3PLUS_DEC_MAX_SCRATCH_SIZE 27474 #endif + +#endif + +typedef enum { + LC3PLUS_FRAME_DURATION_UNDEFINED = 0, /* Invalid */ +#ifdef CR9_C_ADD_1p25MS + LC3PLUS_FRAME_DURATION_1p25MS = 1, /* 1.25 ms */ +#endif + LC3PLUS_FRAME_DURATION_2p5MS = 2, /* 2.5 ms */ + LC3PLUS_FRAME_DURATION_5MS = 4, /* 5 ms */ + LC3PLUS_FRAME_DURATION_7p5MS = 6, /* 7.5 ms */ + LC3PLUS_FRAME_DURATION_10MS = 8, /* 10 ms */ +} LC3PLUS_FrameDuration; + /*! Decoder packet loss concealment mode */ typedef enum { @@ -321,7 +351,7 @@ int lc3plus_enc_get_delay(const LC3PLUS_Enc *encoder); * \param[in] frame_ms Frame length in ms. * \return LC3PLUS_OK on success or appropriate error code. */ -LC3PLUS_Error lc3plus_enc_set_frame_dms(LC3PLUS_Enc *encoder, int frame_ms); +LC3PLUS_Error lc3plus_enc_set_frame_dms(LC3PLUS_Enc *encoder, LC3PLUS_FrameDuration frame_ms); /*! Set error protection mode. The default is LC3PLUS_EP_OFF. It is possible to switch between * different modees during encoding. Dynamic switching is only allowed between LC3PLUS_EP_ZERO, @@ -465,7 +495,7 @@ int lc3plus_dec_get_delay(const LC3PLUS_Dec *decoder); * \param[in] frame_ms Frame length in ms. * \return LC3PLUS_OK on success or appropriate error code. */ -LC3PLUS_Error lc3plus_dec_set_frame_dms(LC3PLUS_Dec *decoder, int frame_ms); +LC3PLUS_Error lc3plus_dec_set_frame_dms(LC3PLUS_Dec *decoder, LC3PLUS_FrameDuration frame_ms); /*! Enable or disable error protection. Default value is 0 (disabled). If error protection is * enabled, the decoder expects that the frames were encoded with error protection mode @@ -519,4 +549,4 @@ int lc3plus_dec_get_error_report(const LC3PLUS_Dec *decoder); int lc3plus_dec_get_epok_flags(const LC3PLUS_Dec *decoder); /*! \} */ -#endif /* LC3plus */ +#endif /* LC3PLUS_H */ diff --git a/lib_lc3plus/levinson_fx.c b/lib_lc3plus/levinson_fx.c index 0aa4b2e2c..3cb547439 100644 --- a/lib_lc3plus/levinson_fx.c +++ b/lib_lc3plus/levinson_fx.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,6 +7,8 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "functions.h" void processLevinson_fx(Word32 *lpc, Word32 *ac, Word16 N, Word16 *rc, Word32 *pred_err, Word8 *scratchBuffer) diff --git a/lib_lc3plus/license.h b/lib_lc3plus/license.h index 684166bf4..a692e0ed4 100644 --- a/lib_lc3plus/license.h +++ b/lib_lc3plus/license.h @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,13 +7,15 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "defines.h" static const char *const LICENSE = "*******************************************************************************\n" - "* ETSI TS 103 634 V1.5.1 *\n" + "* ETSI TS 103 634 V1.6.1 *\n" "* Low Complexity Communication Codec Plus (LC3plus) *\n" - "* Fixed Point Software V%i.%i.%iETSI, " __DATE__ " *\n" + "* Fixed Point Software V%i.%i.%iETSI, " __DATE__ " *\n" "* Copyright licence is solely granted through ETSI Intellectual Property *\n" "* Rights Policy, 3rd April 2019. No patent licence is granted by implication, *\n" "* estoppel or otherwise. *\n" diff --git a/lib_lc3plus/ltpf_coder_fx.c b/lib_lc3plus/ltpf_coder_fx.c index e5ae9c5f2..bf2ea18ab 100644 --- a/lib_lc3plus/ltpf_coder_fx.c +++ b/lib_lc3plus/ltpf_coder_fx.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,16 +7,29 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "functions.h" +#ifdef CR9_C_ADD_1p25MS_LRSNS +#include "constants.h" +#endif + /*************************************************************************/ void process_ltpf_coder_fx(Word16 *bits, Word16 ol_pitch, Word16 ltpf_enable, Word16 *mem_in_exp, Word16 mem_in[], Word16 mem_in_len, Word16 param[], Word16 *xin, Word16 len, Word16 *mem_normcorr, Word16 *mem_mem_normcorr, Word16 ol_normcorr, Word16 *mem_ltpf_on, Word16 *mem_ltpf_pitch, - Word16 xin_exp, Word16 frame_dms, Word8 *scratchBuffer - , Word16 hrmode + Word16 xin_exp, LC3PLUS_FrameDuration frame_dms, Word8 *scratchBuffer + , Word16 hrmode +#ifdef CR9_C_ADD_1p25MS +#ifdef NEW_SIGNALLING_SCHEME_1p25 + , Word16* Tx_ltpf +#else + , Word16 Tx_ltpf +#endif +#endif ) { Word16 pitch_index, scale0, scale1, scale2, *x, x_exp, shift, prod_exp, ltpf_pitch; @@ -27,6 +40,9 @@ void process_ltpf_coder_fx(Word16 *bits, Word16 ol_pitch, Word16 ltpf_enable, Wo Word16 pitch, pitch_res, min_pitch_fr, pitch_int, pitch_fr, norm_corr, ltpf_active; Counter n, m, fr; Word16 tmp, acflen; +#if defined (CR9_C_ADD_1p25MS) + Word16 activation_due_to_past_corr, activation_due_to_stable_pitch, activation; +#endif #ifdef DYNMEM_COUNT Dyn_Mem_In("process_ltpf_coder_fx", sizeof(struct { @@ -41,7 +57,7 @@ void process_ltpf_coder_fx(Word16 *bits, Word16 ol_pitch, Word16 ltpf_enable, Wo })); #endif - + UNUSED(mem_mem_normcorr); ac32 = (Word32 *)scratchAlign(scratchBuffer, 0); /* Size = 4 * 17 = 68 bytes; */ ac = (Word16 *)scratchAlign(ac32, sizeof(*ac32) * 17); /* Size = 2 * 17 = 34 bytes */ @@ -78,7 +94,7 @@ void process_ltpf_coder_fx(Word16 *bits, Word16 ol_pitch, Word16 ltpf_enable, Wo *mem_in_exp = x_exp; move16(); } - Word32 normCorrTh = 0; + Word32 normCorrTh = 0; if (hrmode) { normCorrTh = 13107; } else { @@ -95,12 +111,38 @@ void process_ltpf_coder_fx(Word16 *bits, Word16 ol_pitch, Word16 ltpf_enable, Wo ac_min_pitch = sub(min_pitch, 4); ac_max_pitch = add(max_pitch, 4); acflen = len; move16(); - if (sub(frame_dms, 25) == 0) + +#ifndef FIX_LTPF_PITCH_MEM_LEN + IF ( sub( frame_dms, LC3PLUS_FRAME_DURATION_2p5MS ) == 0 ) { - acflen = shl(len, 1); - x = x - len; + acflen = shl( len, 1 ); + x = x - len; } +#ifdef CR9_C_ADD_1p25MS + IF ( sub( frame_dms, LC3PLUS_FRAME_DURATION_1p25MS ) == 0 ) + { + acflen = shl( len, 2 ); + x = x - 80; + } +#endif +#else + if (sub(frame_dms, LC3PLUS_FRAME_DURATION_5MS) == 0) + { + acflen = shl(len, 1); + } + if (sub(frame_dms, LC3PLUS_FRAME_DURATION_2p5MS) == 0) + { + acflen = shl(len, 2); + } +#ifdef CR9_C_ADD_1p25MS + if (sub(frame_dms, LC3PLUS_FRAME_DURATION_1p25MS) == 0) + { + acflen = shl(len, 3); + } +#endif + x = x - (mem_in_len - LTPF_MEMIN_LEN); +#endif /* Compute norm */ sum1 = L_mac0(1, x[0], x[0]); sum2 = L_mac0(1, x[-ac_min_pitch], x[-ac_min_pitch]); @@ -150,9 +192,11 @@ void process_ltpf_coder_fx(Word16 *bits, Word16 ol_pitch, Word16 ltpf_enable, Wo /* Find maximum */ ac_max = ac[min_pitch - ac_min_pitch]; move16(); pitch = min_pitch; move16(); + FOR (n = min_pitch + 1; n <= max_pitch; n++) { tmp = sub_sat(ac[n - ac_min_pitch], ac_max); + if (tmp > 0) { pitch = n; move16(); @@ -272,11 +316,34 @@ void process_ltpf_coder_fx(Word16 *bits, Word16 ol_pitch, Word16 ltpf_enable, Wo { test(); test(); test(); test(); /* Decision if lptf active */ - IF ((*mem_ltpf_on == 0 && sub(*mem_normcorr, 30802) > 0 && sub(norm_corr, 30802) > 0 && - (sub(frame_dms, 100) == 0 || sub(*mem_mem_normcorr, 30802) > 0)) || - (sub(*mem_ltpf_on, 1) == 0 && sub(norm_corr, 29491) > 0) || - (sub(*mem_ltpf_on, 1) == 0 && sub(abs_s(sub(ltpf_pitch, *mem_ltpf_pitch)), 8) < 0 && - add(sub(norm_corr, *mem_normcorr), 3277) > 0 && sub(norm_corr, 27525) > 0)) +#if defined (CR9_C_ADD_1p25MS) + activation_due_to_past_corr = sub(mem_normcorr[1], 30802) > 0; + activation_due_to_stable_pitch = 1; + IF (frame_dms == LC3PLUS_FRAME_DURATION_1p25MS) + { + activation_due_to_past_corr &= sub(mem_normcorr[2], 30802) > 0; + activation_due_to_past_corr &= sub(mem_normcorr[3], 30802) > 0; + activation_due_to_past_corr &= sub(mem_normcorr[4], 30802) > 0; + + /* 0.7 * max(pitch,mem.pitch(1)) < min(pitch,mem.pitch(1)); */ + Word16 tmp_max = s_max(ltpf_pitch, *mem_ltpf_pitch); + Word16 tmp_min = s_min(ltpf_pitch, *mem_ltpf_pitch); + activation_due_to_stable_pitch = shr(mult(shl(tmp_max,5),22938),5) < tmp_min; + } + activation = activation_due_to_past_corr && activation_due_to_stable_pitch; + + IF( ( *mem_ltpf_on == 0 && sub( *mem_normcorr, 30802 ) > 0 && sub( norm_corr, 30802 ) > 0 && + ( sub( frame_dms, LC3PLUS_FRAME_DURATION_10MS ) == 0 || activation ) ) || + ( sub( *mem_ltpf_on, 1 ) == 0 && sub( norm_corr, 29491 ) > 0 ) & activation_due_to_stable_pitch || + ( sub( *mem_ltpf_on, 1 ) == 0 && sub( abs_s( sub( ltpf_pitch, *mem_ltpf_pitch ) ), 8 ) < 0 && + add( sub( norm_corr, *mem_normcorr ), 3277 ) > 0 && sub( norm_corr, 27525 ) > 0 ) ) +#else + IF( ( *mem_ltpf_on == 0 && sub( mem_normcorr[0], 30802 ) > 0 && sub( norm_corr, 30802 ) > 0 && + ( sub( frame_dms, LC3PLUS_FRAME_DURATION_10MS ) == 0 || sub( mem_normcorr[1], 30802 ) > 0 ) ) || + ( sub( *mem_ltpf_on, 1 ) == 0 && sub( norm_corr, 29491 ) > 0 ) || + ( sub( *mem_ltpf_on, 1 ) == 0 && sub( abs_s( sub( ltpf_pitch, *mem_ltpf_pitch ) ), 8 ) < 0 && + add( sub( norm_corr, mem_normcorr[0] ), 3277 ) > 0 && sub( norm_corr, 27525 ) > 0 ) ) +#endif { ltpf_active = 1; move16(); } @@ -285,7 +352,7 @@ void process_ltpf_coder_fx(Word16 *bits, Word16 ol_pitch, Word16 ltpf_enable, Wo param[0] = 1; move16(); param[1] = ltpf_active; move16(); param[2] = pitch_index; move16(); - *bits = 11; move16(); + *bits = 11; move16(); } ELSE { @@ -297,13 +364,62 @@ void process_ltpf_coder_fx(Word16 *bits, Word16 ol_pitch, Word16 ltpf_enable, Wo ltpf_pitch = 0; move16(); } +#ifdef CR9_C_ADD_1p25MS + if ( sub(frame_dms, LC3PLUS_FRAME_DURATION_1p25MS) == 0 ) + { +#ifdef NEW_SIGNALLING_SCHEME_1p25 + tmp = s_min(*Tx_ltpf, 1); /* tmp == 0 == phaseA, tmp==1==PhaseB ) */ + test(); test(); test(); + if (param[0] == 0 && tmp != 0) + { + /* pitch correlation dropped from high(ltpf_active) to low(no ltp info at all ), + we select to NOT send the remaining phaseB laginfo for use in a possible low corr PLC frame */ + *Tx_ltpf = 0; move16(); /* kill the lag transmission state at encoder side */ + } + + /* 00 (ltp=0, ltpf=0, no Phase, 2b), + 010yyyy (ltp=1, ltpf=0, phaseA, 7b), + 011zzzz (ltp=1, ltpf=0, phaseB , 7b), "zzzz=lowered lag res for PLC use" + 10yyyy (ltp=1, ltpf=1) phaseA 6b) + 11ZZZZZ (ltp=1, ltpf=1) phaseB 7b) "ZZZZZ= full lag resolution for LTPF use" + */ + test(); + IF(param[0] != 0) + { + test(); + IF(param[1] == 0) + { /* ltpf inactive */ + tmp = s_or(shl(param[0], 1), tmp); /* LTP in b1 phase in LSB b0 , tmp becomes 2 or 3 */ + ASSERT(tmp==2 || tmp == 3 ); + } + ELSE + { /* ltpf active */ + ASSERT(param[2] >= 0 && param[2] <= 511); + tmp = s_or(0x04, shl(tmp, 1)); /* LTPF in b2, phase b1, always zero in b0 , tmp becomes 4 or 6 */ + ASSERT(tmp == 4 || tmp == 6); + } + } + *bits = lrsns_ltp_bits_fx[tmp]; move16(); /* one of { 2,2, 7,7 , 6,6, 7,7} */ + /* tmp as idx is 0,1 2,3 4,5, 6,7 */ + ASSERT(*bits >= 2 && *bits <= 7); +#else + ASSERT(*bits == 1 || *bits == 11 ); +#endif + } +#else + ASSERT(*bits == 1 || *bits == 11 ); +#endif /* CR9_C_ADD_1p25MS */ + /* Update memory */ FOR (n = 0; n < mem_in_len; n++) { mem_in[n] = mem_in[n + len]; move16(); } - *mem_mem_normcorr = *mem_normcorr; move16(); + FOR (n = LEN_MEM_NORMCORR-2; n>=0; n--) { + mem_normcorr[n+1] = mem_normcorr[n]; move16(); + } + *mem_normcorr = norm_corr; move16(); *mem_ltpf_on = ltpf_active; move16(); *mem_ltpf_pitch = ltpf_pitch; move16(); @@ -312,4 +428,3 @@ void process_ltpf_coder_fx(Word16 *bits, Word16 ol_pitch, Word16 ltpf_enable, Wo Dyn_Mem_Out(); #endif } - diff --git a/lib_lc3plus/ltpf_decoder_fx.c b/lib_lc3plus/ltpf_decoder_fx.c index 31da1dbbb..084b7738b 100644 --- a/lib_lc3plus/ltpf_decoder_fx.c +++ b/lib_lc3plus/ltpf_decoder_fx.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,14 +7,156 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "functions.h" static void ltpf_synth_filter(Word16 *synth_ltp, Word16 *synth, Word16 length, Word16 pitch_int, Word16 pitch_fr, Word16 gain, Word16 scale_fac_idx, Word16 fs_idx, - Word16 fade /* 0=normal, +1=fade-in, -1=fade-out */); + Word16 fade /* 0=normal, +1=fade-in, -1=fade-out */ + , Word16 continuation, Word16 splitFading +#ifdef LTPF_ADAPTIVE_GAIN + , LC3PLUS_FrameDuration frame_dms +#endif + ); + /*************************************************************************/ +#ifdef CR9_C_ADD_1p25MS +static void get_continuation (Word16 fading_case, LC3PLUS_FrameDuration frame_dms, Word16 *continuation) +{ + if (frame_dms != LC3PLUS_FRAME_DURATION_1p25MS) { + *continuation = 0; + } + else + { + if ( *continuation > 0 ) + { + *continuation = 0; + } + else + { + *continuation = fading_case; + } + } +} +#endif + +#ifdef LTPF_ADAPTIVE_GAIN_WITH_NORM_CORR +static Word16 compare_normalized_corrs(Word16 *sig, Word16 len, Word16 pitch_int, Word16 old_pitch_int) +{ + Word32 sum0, sum1, sum2, prod, inv; + Word32 sum0_prev, sum2_prev, prod_prev; + Word16 scale0, scale1, scale2, shift, prod_exp, prod_exp_prev; + Word32 norm_corr, norm_corr_prev; + + sum0 = L_mult0( sig[0], sig[-pitch_int] ); + sum1 = L_mac0( 1, sig[0], sig[0] ); + sum2 = L_mac0( 1, sig[-pitch_int], sig[-pitch_int] ); + + sum0_prev = L_mult0( sig[0], sig[-old_pitch_int] ); + sum2_prev = L_mac0( 1, sig[-old_pitch_int], sig[-old_pitch_int] ); + + FOR (int i=1; i < len; i++) + { + sum0 = L_mac0( sum0, sig[i], sig[i - pitch_int] ); + sum1 = L_mac0( sum1, sig[i], sig[i] ); + sum2 = L_mac0( sum2, sig[i - pitch_int], sig[i - pitch_int] ); + + sum0_prev = L_mac0( sum0_prev, sig[i], sig[i - old_pitch_int] ); + sum2_prev = L_mac0( sum2_prev, sig[i - old_pitch_int], sig[i - old_pitch_int] ); + } + + scale1 = norm_l( sum1 ); + scale2 = norm_l( sum2 ); + sum1 = L_shl_pos( sum1, scale1 ); + sum2 = L_shl_pos( sum2, scale2 ); + prod = Mpy_32_32_lc3plus( sum1, sum2 ); + shift = norm_l( prod ); + prod = L_shl_pos( prod, shift ); + prod_exp = sub( 62, add( add( scale1, scale2 ), shift ) ); + inv = Isqrt_lc3plus( prod, &prod_exp ); + scale0 = norm_l( sum0 ); + sum0 = L_shl_pos( sum0, scale0 ); + prod = Mpy_32_32_lc3plus( sum0, inv ); + prod_exp = add( sub( 31, scale0 ), prod_exp ); + +#ifdef FIX_LTPFDEC_BASOP + norm_corr = INT_MAX; move32(); + test(); + if(prod == 0 || sub(norm_l(prod), prod_exp) >= 0) + { + norm_corr = L_shl_sat(prod, prod_exp); + } + norm_corr = L_max(0, norm_corr); +#else + test(); + IF( prod == 0 || sub( norm_l( prod ), prod_exp ) >= 0 ) + { + norm_corr = L_max( 0, L_shl_sat( prod, prod_exp ) ); + } + ELSE + { + norm_corr = 2147483647; move32(); + } + + if ( norm_corr < 0 ) + { + norm_corr = 0; move32(); + } +#endif + + + scale2 = norm_l( sum2_prev ); + sum2_prev = L_shl_pos( sum2_prev, scale2 ); + prod_prev = Mpy_32_32_lc3plus( sum1, sum2_prev ); + shift = norm_l( prod_prev ); + prod_prev = L_shl_pos( prod_prev, shift ); + prod_exp_prev = sub( 62, add( add( scale1, scale2 ), shift ) ); + inv = Isqrt_lc3plus( prod_prev, &prod_exp_prev ); + scale0 = norm_l( sum0_prev ); + sum0_prev = L_shl_pos( sum0_prev, scale0 ); + prod_prev = Mpy_32_32_lc3plus( sum0_prev, inv ); + prod_exp_prev = add( sub( 31, scale0 ), prod_exp_prev ); + +#ifdef FIX_LTPFDEC_BASOP + norm_corr_prev = INT_MAX; move32(); + test(); + if( prod_prev == 0 || sub( norm_l( prod_prev ), prod_exp_prev ) >= 0 ) + { + norm_corr_prev = L_shl_sat( prod_prev, prod_exp_prev ); + } + norm_corr_prev = L_max( 0L, norm_corr_prev); +#else + test(); + IF( prod_prev == 0 || sub(norm_l(prod_prev), prod_exp_prev) >= 0) + { + norm_corr_prev = L_max(0, L_shl_sat(prod_prev, prod_exp_prev)); move32(); + } + ELSE + { + norm_corr_prev = 2147483647; move32(); + } + + IF(norm_corr_prev < 0) + { + norm_corr_prev = 0; + } +#endif + +#ifdef FIX_LTPFDEC_BASOP + IF(L_sub_sat(L_sub(norm_corr_prev, norm_corr), 1073742L) > 0) +#else + IF( L_sub(L_sub(norm_corr_prev, norm_corr), 1073742L ) > 0) +#endif + { + return 1; + } + + return 0; +} +#endif void process_ltpf_decoder_fx(Word16 *x_e, Word16 L_frame, Word16 old_x_len, Word16 fs_idx, Word16 old_y_len, Word16 *old_e, Word16 *x_in, Word16 *old_x, Word16 *y_out, Word16 *old_y, Word16 ltpf, @@ -22,27 +164,76 @@ void process_ltpf_decoder_fx(Word16 *x_e, Word16 L_frame, Word16 old_x_len, Word Word16 *old_gain, Word16 *mem_ltpf_active, Word16 scale_fac_idx, Word16 bfi, Word16 concealMethod, Word16 damping, Word16 *old_scale_fac_idx, - Word32 *rel_pitch_change, Word16 hrmode, Word16 frame_dms, - Word8 *scratchBuffer) + Word32 *rel_pitch_change, Word16 hrmode, LC3PLUS_FrameDuration frame_dms, + Word8 *scratchBuffer +#ifdef CR9_C_ADD_1p25MS + , Word16* mem_continuation, Word16* mem_pitch_int_prev, + Word16* mem_pitch_fr_prev, Word16* mem_beta_idx_prev, Word16* mem_gain_prev, Word16 *ltpf_mem_active_prev, Word16* pitch_stability_counter +#endif + ) { Counter i; - Word16 gain, s, s0, s1, pitch, pitch_int, pitch_fr, N4, N34; + Word16 gain, s, s0, s1, pitch, pitch_int, pitch_fr, N4, N34, fading_case, split_fading; Word16 *x, *y; - Word16 *z; + Word16* z; Word32 tmp32, pitch_delta; + +#ifdef LTPF_ADAPTIVE_GAIN + Word16 bkp_ltpf_active = 0; + Word16 bkp_pitch_int = 0, bkp_pitch_fr = 0; + Word16 bkp_gain = 0; +#endif + #ifdef DYNMEM_COUNT +#ifndef CR9_N_SHORT_FADE_FOR_UNSTABLE_PITCH + Dyn_Mem_In( "process_ltpf_decoder_fx", sizeof( struct { + Counter i; + Word16 gain, s, s0, s1, pitch, pitch_int, pitch_fr, N4, N34; + Word16 *x, *y; + Word16* z; + } ) ); +#else Dyn_Mem_In("process_ltpf_decoder_fx", sizeof(struct { - Counter i; - Word16 gain, s, s0, s1, pitch, pitch_int, pitch_fr, N4, N34; - Word16 *x, *y; - Word16 *z; - Word32 tmp32, pitch_delta; - })); + Counter i; + Word16 gain, s, s0, s1, pitch, pitch_int, pitch_fr, N4, N34; + Word16 *x, *y; + Word16* z; + Word32 tmp32, pitch_delta; + })); +#endif + #endif z = (Word16 *)scratchAlign(scratchBuffer, 0); /* Size = MAX_LEN / 4 + 10 */ +#ifdef CR9_C_ADD_1p25MS + UNUSED( frame_dms ); + UNUSED( mem_continuation ); + UNUSED( mem_pitch_int_prev ); + UNUSED( mem_pitch_fr_prev ); + UNUSED( mem_beta_idx_prev ); + UNUSED( mem_gain_prev ); +#else + Word16 mem_cont = 0; + Word16* mem_continuation = &mem_cont; +#ifndef FIX_LTPF_MEM_CONTINUATION + fading_case = 0; +#endif + UNUSED( mem_continuation ); +#endif + +#ifdef FIX_LTPF_MEM_CONTINUATION + fading_case = 0; +#endif + + split_fading = 0; +#ifdef CR9_C_ADD_1p25MS + if ( frame_dms == LC3PLUS_FRAME_DURATION_1p25MS ) + { + split_fading = 1; + } +#endif test(); IF ((sub(bfi, 1) == 0) && (sub(concealMethod, LC3_CON_TEC_NS_STD) == 0)) { @@ -53,6 +244,13 @@ void process_ltpf_decoder_fx(Word16 *x_e, Word16 L_frame, Word16 old_x_len, Word gain = 0; move16(); } +#ifdef FIX_LTPF_1p25 + IF (pitch_index == -1) { + ltpf = 0; + ltpf_active = 0; + } +#endif + /* Filter parameters */ IF (sub(bfi, 1) != 0) { @@ -110,7 +308,12 @@ void process_ltpf_decoder_fx(Word16 *x_e, Word16 L_frame, Word16 old_x_len, Word gain = gain_scale_fac[scale_fac_idx]; move16(); } } +#ifdef CR9_C_ADD_1p25MS + ELSE IF ( (sub(concealMethod, LC3_CON_TEC_NS_STD) != 0) + && (*mem_continuation == 0) ) +#else ELSE IF (sub(concealMethod, LC3_CON_TEC_NS_STD) != 0) +#endif { /* fix to avoid not initialized filtering for concelament might be necessary in case of bit errors or rate switching */ @@ -120,7 +323,7 @@ void process_ltpf_decoder_fx(Word16 *x_e, Word16 L_frame, Word16 old_x_len, Word scale_fac_idx = *old_scale_fac_idx; } } - + ltpf_active = *mem_ltpf_active; move16(); if ((sub(concealMethod, LC3_CON_TEC_PHASE_ECU) == 0)) @@ -133,13 +336,189 @@ void process_ltpf_decoder_fx(Word16 *x_e, Word16 L_frame, Word16 old_x_len, Word pitch_fr = *old_pitch_fr; gain = mult_r(*old_gain, damping); } + +#ifdef CR9_C_ADD_1p25MS + IF (*mem_continuation > 0) + { +#ifdef LTPF_ADAPTIVE_GAIN + /* Backup LTPF parameters */ + bkp_ltpf_active = ltpf_active; + bkp_pitch_int = pitch_int; + bkp_pitch_fr = pitch_fr; + bkp_gain = gain; +#endif - test(); test(); - IF (ltpf_active == 0 && *mem_ltpf_active == 0) + fading_case = *mem_continuation; + ltpf_active = *mem_ltpf_active; + pitch_int = *old_pitch_int; + pitch_fr = *old_pitch_fr; + gain = *old_gain; +#ifdef FIX_LTPF_1p25 + scale_fac_idx = *old_scale_fac_idx; +#endif + *mem_ltpf_active = *ltpf_mem_active_prev; + *old_pitch_int = *mem_pitch_int_prev; + *old_pitch_fr = *mem_pitch_fr_prev; + *old_gain = *mem_gain_prev; +#ifdef FIX_LTPF_1p25 + *old_scale_fac_idx = *mem_beta_idx_prev; +#endif + } +#endif + +#ifdef LTPF_ADAPTIVE_GAIN + IF (frame_dms == LC3PLUS_FRAME_DURATION_1p25MS) { - /* LTPF inactive */ +#ifdef FIX_LTPF_DEC_FLFX_MISMATCH + /* Control variables */ + Word8 ltpf_active_ctrl = ltpf_active; + Word8 ltpf_active_prev_ctrl = *mem_ltpf_active; +#endif + Word8 pitch_changed = !( ( pitch_int == *old_pitch_int ) && ( pitch_fr == *old_pitch_fr ) ); + Word8 pitch_was_stable = ( ( *pitch_stability_counter >= LTPF_PITCH_STABILITY_THRESHOLD ) ); + +#ifdef CR9_C_ADD_1p25MS + IF ( *mem_continuation == 0 ) + { +#endif + +#ifdef LTPF_ADAPTIVE_GAIN_WITH_NORM_CORR + Word16 tmp_y[LTPF_MEM_Y_LEN] = {0}; + basop_memmove( tmp_y, old_y, ( old_y_len ) * sizeof( Word16 ) ); + basop_memmove( tmp_y + old_y_len, x_in, ( L_frame ) * sizeof( Word16 ) ); + + Word16 scale1 = sub( getScaleFactor16_0( tmp_y, old_y_len + L_frame ), 3 ); + Scale_sig( tmp_y, old_y_len + L_frame, scale1 ); + + IF ( !pitch_was_stable && pitch_changed && pitch_int != 0 && *old_pitch_int != 0 ) + { + pitch_was_stable = compare_normalized_corrs(tmp_y + old_y_len, L_frame, pitch_int, *old_pitch_int); + } +#endif + +#ifdef FIX_LTPF_DEC_FLFX_MISMATCH + IF ( ltpf_active_ctrl && !pitch_changed ) +#else + IF ( ltpf_active && !pitch_changed ) +#endif + { + /* increment gain and increment pitch stability counter */ + gain = pitch_was_stable ? MIN( max_adaptive_gain[scale_fac_idx], MAX( gain, *old_gain ) + adaptive_gain_step ) : MAX( gain, *old_gain ); + (*pitch_stability_counter)++; + } +#ifdef FIX_LTPF_DEC_FLFX_MISMATCH + ELSE IF ( ltpf_active_ctrl && pitch_changed && !pitch_was_stable ) +#else + ELSE IF ( ltpf_active && pitch_changed && !pitch_was_stable ) +#endif + { + /* decrement gain and reset pitch stability counter */ + gain = ( *old_gain > gain) ? MAX( gain, *old_gain - max_adaptive_gain_step[scale_fac_idx] ) : gain; + *pitch_stability_counter = 0; + } +#ifdef FIX_LTPF_DEC_FLFX_MISMATCH + ELSE IF ( !ltpf_active_ctrl && !pitch_was_stable && ltpf_active_prev_ctrl && pitch_changed ) +#else + ELSE IF ( !ltpf_active && !pitch_was_stable && *mem_ltpf_active && pitch_changed ) +#endif + { + /* decrement gain, use previous pitch and reset pitch stability counter */ + gain = *old_gain - adaptive_gain_step; + + if (scale_fac_idx>=0 && (gain-gain_scale_fac[scale_fac_idx]) > -20) + { + ltpf_active = *mem_ltpf_active; + pitch_int = *old_pitch_int; + pitch_fr = *old_pitch_fr; + } + else + { + gain = 0; + } + *pitch_stability_counter = 0; + } +#ifdef FIX_LTPF_DEC_FLFX_MISMATCH + ELSE IF ( ( ltpf_active_ctrl && pitch_changed && pitch_was_stable ) || ( !ltpf_active_ctrl && pitch_was_stable ) || ( !ltpf_active_ctrl && !pitch_was_stable && ltpf_active_prev_ctrl && !pitch_changed ) ) +#else + ELSE IF ( ( ltpf_active && pitch_changed && pitch_was_stable ) || ( !ltpf_active && pitch_was_stable ) || ( !ltpf_active && !pitch_was_stable && *mem_ltpf_active && !pitch_changed ) ) +#endif + { + /* use previous pitch and gain and reset pitch stability counter */ + ltpf_active = *mem_ltpf_active; + pitch_int = *old_pitch_int; + pitch_fr = *old_pitch_fr; + gain = *old_gain; + *pitch_stability_counter = 0; + } +#ifdef CR9_C_ADD_1p25MS /* This preprocessor is added here for the future when adaptive gain will be enabled for other frame sizes. */ + } +#ifdef FIX_PLC_CONFORM_ISSUES + ELSE IF ( *mem_continuation != 0 && bkp_ltpf_active == 1 && bfi == 0 ) +#else + ELSE IF ( *mem_continuation != 0 && bkp_ltpf_active == 1 ) +#endif + { + /* Code enters this block if LTPF is reenabled when adaptive gain is being applied. */ + /* In this case, use new LTPF parameters but with a smaller gain than in the prev frame. */ + fading_case = 0; + *mem_continuation = 0; + + *ltpf_mem_active_prev = *mem_ltpf_active; + *mem_pitch_int_prev = *old_pitch_int; + *mem_pitch_fr_prev = *old_pitch_fr; + *mem_gain_prev = *old_gain; + + *mem_ltpf_active = ltpf_active; + *old_pitch_int = pitch_int; + *old_pitch_fr = pitch_fr; + *old_gain = gain; + + ltpf_active = bkp_ltpf_active; + pitch_int = bkp_pitch_int; + pitch_fr = bkp_pitch_fr; + gain = bkp_gain; + + /* if prev gain > curr gain, then decrease gain slowly.*/ + gain = ( *old_gain > gain) ? MAX( gain, *old_gain - max_adaptive_gain_step[scale_fac_idx] ) : gain; + + *pitch_stability_counter = 0; + } +#endif + } +#endif /* LTPF_ADAPTIVE_GAIN */ + +#ifdef FIX_LTPF_1p25 + if ( *mem_ltpf_active && *old_scale_fac_idx < 0 ) + { + *mem_ltpf_active = 0; + } + + if ( ltpf_active && scale_fac_idx < 0 ) + { + ltpf_active = 0; + } +#endif + + IF( sub( fs_idx, 5 ) < 0 ) + { + test(); + test(); + +#ifdef FIX_LTPF_MEM_CONTINUATION + IF( ( ltpf_active == 0 && *mem_ltpf_active == 0 ) || fading_case == 1 ) +#else + IF( ltpf_active == 0 && *mem_ltpf_active == 0 && *mem_continuation == 0 ) +#endif + { + /* LTPF inactive */ + basop_memmove( y_out, x_in, L_frame * sizeof( Word16 ) ); +#ifdef FIX_LTPF_MEM_CONTINUATION +#ifdef CR9_C_ADD_1p25MS + fading_case = 1; + get_continuation( fading_case, frame_dms, mem_continuation ); +#endif +#endif - basop_memmove(y_out, x_in, L_frame * sizeof(Word16)); /* Update */ s = sub(*old_e, *x_e); @@ -183,32 +562,31 @@ void process_ltpf_decoder_fx(Word16 *x_e, Word16 L_frame, Word16 old_x_len, Word basop_memmove(old_x, &x_in[L_frame - old_x_len], (old_x_len) * sizeof(Word16)); - *old_e = *x_e; move16(); + *old_e = *x_e; + move16(); + } + *old_gain = 0; + move16(); + *mem_ltpf_active = 0; + move16(); } + ELSE + { + /* Input/Output buffers */ + x = old_x + old_x_len; + y = old_y + old_y_len; - if (bfi == 0 && sub(hrmode,1) == 0 && (sub(frame_dms,50) == 0 || sub(frame_dms,25) == 0)){ - pitch_delta = abs_s(add(sub(*old_pitch_int,pitch_int) , shr_pos(sub(*old_pitch_fr, pitch_fr),2))); //int_old -int_new + (fr_old-fr_new) / 4.0)); - tmp32 = BASOP_Util_Divide3216_Scale_lc3plus(pitch_delta, MAX(add(*old_pitch_int, shr_pos(*old_pitch_fr,2)), 1),&s0);// = pitch_delta *2^15 / MAX(pitch_fl_c_old, 1); - *rel_pitch_change = L_shl_pos(tmp32,s0+16); - } - - *old_pitch_int = pitch_int; move16(); - *old_pitch_fr = pitch_fr; move16(); - *old_gain = 0; move16(); - *mem_ltpf_active = 0; move16(); - } - ELSE - { - /* Input/Output buffers */ - x = old_x + old_x_len; - y = old_y + old_y_len; - #ifdef ENABLE_HR_MODE - assert(fs_idx < 5 && "Ltpf not supported for 96kHz!\n"); + assert( fs_idx < 5 && "Ltpf not supported for 96kHz!\n" ); #endif - - N4 = ltpf_overlap_len[fs_idx]; move16(); - N34 = sub(L_frame, N4); move16(); + + N4 = ltpf_overlap_len[fs_idx]; + move16(); +#ifdef CR9_C_ADD_1p25MS + N4 = N4 >> split_fading; +#endif + N34 = sub( L_frame, N4 ); + move16(); /* Input */ basop_memmove(x, x_in, (L_frame) * sizeof(Word16)); @@ -234,53 +612,179 @@ void process_ltpf_decoder_fx(Word16 *x_e, Word16 L_frame, Word16 old_x_len, Word *old_e = *x_e; move16(); } - /* Filtering */ - IF (ltpf_active == 0) - { - ltpf_synth_filter(y, x, N4, *old_pitch_int, *old_pitch_fr, *old_gain, *old_scale_fac_idx, fs_idx, - -1); - } - ELSE IF (*mem_ltpf_active == 0) - { - ltpf_synth_filter(y, x, N4, pitch_int, pitch_fr, gain, scale_fac_idx, fs_idx, 1); + test(); +#ifndef FIX_LTPF_1p25 + IF (sub(*mem_ltpf_active, 1) == 0 && *old_scale_fac_idx < 0) + { + *mem_ltpf_active = 0; + } +#endif +#ifdef CR9_C_ADD_1p25MS + IF (*mem_continuation == 0) + { +#endif + /* fading case */ + IF (ltpf_active == 0) + { + fading_case = 3; + } + ELSE IF (*mem_ltpf_active == 0) + { + fading_case = 2; + } + ELSE IF (sub(pitch_int, *old_pitch_int) == 0 && sub(*old_pitch_fr, pitch_fr) == 0) + { + fading_case = 4; + } + ELSE + { + fading_case = 5; + } +#ifdef CR9_C_ADD_1p25MS + } +#endif + + /* Filtering */ + IF( sub( fading_case, 3 ) == 0 ) + { + ltpf_synth_filter( y, x, N4, *old_pitch_int, *old_pitch_fr, *old_gain, *old_scale_fac_idx, fs_idx, -1, *mem_continuation, split_fading +#ifdef LTPF_ADAPTIVE_GAIN + , + frame_dms +#endif + ); + } + ELSE IF( sub( fading_case, 2 ) == 0 ) + { + ltpf_synth_filter( y, x, N4, pitch_int, pitch_fr, gain, scale_fac_idx, fs_idx, 1, *mem_continuation, split_fading +#ifdef LTPF_ADAPTIVE_GAIN + , + frame_dms +#endif + ); + } + ELSE IF( sub( fading_case, 4 ) == 0 ) + { + ltpf_synth_filter( y, x, N4, pitch_int, pitch_fr, gain, scale_fac_idx, fs_idx, 0, *mem_continuation, split_fading +#ifdef LTPF_ADAPTIVE_GAIN + , + frame_dms +#endif + ); + } + ELSE + { + ltpf_synth_filter( y, x, N4, *old_pitch_int, *old_pitch_fr, *old_gain, *old_scale_fac_idx, fs_idx, + -1, *mem_continuation, split_fading +#ifdef LTPF_ADAPTIVE_GAIN + , + frame_dms +#endif + ); + + basop_memmove( z, y - tilt_filter_len[fs_idx], ( N4 + tilt_filter_len[fs_idx] ) * sizeof( Word16 ) ); + + ltpf_synth_filter( y, z + tilt_filter_len[fs_idx], N4, pitch_int, pitch_fr, gain, scale_fac_idx, + fs_idx, 1, *mem_continuation, split_fading +#ifdef LTPF_ADAPTIVE_GAIN + , + frame_dms +#endif + ); + } +#ifdef CR9_C_ADD_1p25MS + IF( sub( fading_case, 1 ) > 0 ) + { + get_continuation( fading_case, frame_dms, mem_continuation ); + } +#endif + +#ifdef CR9_C_ADD_1p25MS + IF( ltpf_active > 0 && frame_dms > LC3PLUS_FRAME_DURATION_1p25MS ) +#else + IF( ltpf_active > 0 ) +#endif + { + ltpf_synth_filter( y + N4, x + N4, N34, pitch_int, pitch_fr, gain, + scale_fac_idx, fs_idx, 0, 0, 0 +#ifdef LTPF_ADAPTIVE_GAIN + , + frame_dms +#endif + ); + } + ELSE + { + basop_memmove( &y[N4], &x[N4], N34 * sizeof( Word16 ) ); + } + + /* Output */ + basop_memmove( y_out, y, ( L_frame ) * sizeof( Word16 ) ); + + /* Update */ + basop_memmove( old_x, &old_x[L_frame], ( old_x_len ) * sizeof( Word16 ) ); + basop_memmove( old_y, &old_y[L_frame], ( old_y_len ) * sizeof( Word16 ) ); + +#ifndef FIX_LTPF_DEC_FLFX_MISMATCH +#ifdef CR9_C_ADD_1p25MS + if ( frame_dms == LC3PLUS_FRAME_DURATION_1p25MS ) + { + *mem_pitch_int_prev = *old_pitch_int; + *mem_pitch_fr_prev = *old_pitch_fr; + *mem_gain_prev = *old_gain; + *ltpf_mem_active_prev = *mem_ltpf_active; + } +#endif + + *old_gain = gain; + move16(); + *mem_ltpf_active = ltpf_active; + move16(); +#endif } - ELSE IF (sub(pitch_int, *old_pitch_int) == 0 && sub(*old_pitch_fr, pitch_fr) == 0) + } + + + + + IF( bfi == 0 && sub( hrmode, 1 ) == 0 && ( sub( frame_dms, LC3PLUS_FRAME_DURATION_5MS ) == 0 || sub( frame_dms, LC3PLUS_FRAME_DURATION_2p5MS ) == 0 ) ) + { + pitch_delta = abs_s( add( sub( *old_pitch_int, pitch_int ), shr_pos( sub( *old_pitch_fr, pitch_fr ), 2 ) ) ); + tmp32 = BASOP_Util_Divide3216_Scale( pitch_delta, MAX( add( *old_pitch_int, shr_pos( *old_pitch_fr, 2 ) ), 1 ), &s0 ); + IF( s0 + 16 < 0 ) { - ltpf_synth_filter(y, x, N4, pitch_int, pitch_fr, gain, scale_fac_idx, fs_idx, 0); + *rel_pitch_change = L_shr_pos( tmp32, -( s0 + 16 ) ); } ELSE { - ltpf_synth_filter(y, x, N4, *old_pitch_int, *old_pitch_fr, *old_gain, *old_scale_fac_idx, fs_idx, - -1); - basop_memmove(z, y - tilt_filter_len[fs_idx], (N4 + tilt_filter_len[fs_idx]) * sizeof(Word16)); - ltpf_synth_filter(y, z + tilt_filter_len[fs_idx], N4, pitch_int, pitch_fr, gain, scale_fac_idx, - fs_idx, 1); - } - IF (ltpf_active > 0) - { - ltpf_synth_filter(y + N4, x + N4, N34, pitch_int, pitch_fr, gain, - scale_fac_idx, fs_idx, 0); + *rel_pitch_change = L_shl_pos( tmp32, s0 + 16 ); } - ELSE + } + +#ifdef FIX_LTPF_DEC_FLFX_MISMATCH +#ifdef CR9_C_ADD_1p25MS + if ( frame_dms == LC3PLUS_FRAME_DURATION_1p25MS ) { - basop_memmove(&y[N4], &x[N4], N34 * sizeof(Word16)); + *mem_pitch_int_prev = *old_pitch_int; + *mem_pitch_fr_prev = *old_pitch_fr; + *mem_gain_prev = *old_gain; + *ltpf_mem_active_prev = *mem_ltpf_active; + *mem_beta_idx_prev = *old_scale_fac_idx; } +#endif - /* Output */ - basop_memmove(y_out, y, (L_frame) * sizeof(Word16)); - - /* Update */ - basop_memmove(old_x, &old_x[L_frame], (old_x_len) * sizeof(Word16)); - - basop_memmove(old_y, &old_y[L_frame], (old_y_len) * sizeof(Word16)); - - *old_pitch_int = pitch_int; move16(); - *old_pitch_fr = pitch_fr; move16(); - *old_gain = gain; move16(); - *mem_ltpf_active = ltpf_active; move16(); - } + *old_gain = gain; + move16(); + *mem_ltpf_active = ltpf_active; + move16(); +#endif - *old_scale_fac_idx = scale_fac_idx; move16(); + *old_pitch_int = pitch_int; + move16(); + *old_pitch_fr = pitch_fr; + move16(); + *old_scale_fac_idx = scale_fac_idx; + move16(); #ifdef DYNMEM_COUNT Dyn_Mem_Out(); @@ -290,7 +794,12 @@ void process_ltpf_decoder_fx(Word16 *x_e, Word16 L_frame, Word16 old_x_len, Word static void ltpf_synth_filter(Word16 *synth_ltp, Word16 *synth, Word16 length, Word16 pitch_int, Word16 pitch_fr, Word16 gain, Word16 scale_fac_idx, Word16 fs_idx, - Word16 fade /* 0=normal, +1=fade-in, -1=fade-out */) + Word16 fade /* 0=normal, +1=fade-in, -1=fade-out */ + ,Word16 continuation, Word16 splitFading +#ifdef LTPF_ADAPTIVE_GAIN + , LC3PLUS_FrameDuration frame_dms +#endif + ) { Word16 *x0; Word16 *y0; @@ -318,18 +827,26 @@ static void ltpf_synth_filter(Word16 *synth_ltp, Word16 *synth, Word16 length, W y0 = synth; alpha = 0; move16(); + IF (fade != 0) { if (fade < 0) { alpha = 0x7FFF; move16(); } + if (continuation > 0) { + alpha = shr(0x7FFF,1); + } /* step = 1.f/(float)(length); */ if (sub(length, 20) == 0) { step = 1638 /*1.f/20.f Q15*/; move16(); } + if (sub(length, 30) == 0) + { + step = 1092 /*1.f/30.f Q15*/; move16(); + } if (sub(length, 40) == 0) { step = 819 /*1.f/40.f Q15*/; move16(); @@ -349,21 +866,32 @@ static void ltpf_synth_filter(Word16 *synth_ltp, Word16 *synth, Word16 length, W if (fade < 0) step = negate(step); + + if (splitFading != 0) + step = shr(step,1); } FOR (j = 0; j < length; j++) { - s = L_mult(x0[0], inter_filter[fs_idx][pitch_fr][0]); - FOR (l = 1; l < inter_filter_len[fs_idx]; l++) + const Word16* tilt_filter_ptr = tilt_filter[fs_idx][scale_fac_idx]; +#ifdef LTPF_ADAPTIVE_GAIN + IF ( frame_dms == LC3PLUS_FRAME_DURATION_1p25MS ) + { + tilt_filter_ptr = tilt_filter_1p25ms[fs_idx][scale_fac_idx]; + } +#endif + + s = L_mult( x0[0], inter_filter[fs_idx][pitch_fr][0] ); + FOR( l = 1; l < inter_filter_len[fs_idx]; l++ ) { s = L_mac(s, x0[-l], inter_filter[fs_idx][pitch_fr][l]); } FOR (l = 0; l < tilt_filter_len[fs_idx]; l++) { - s = L_msu(s, y0[-l], tilt_filter[fs_idx][scale_fac_idx][l]); + s = L_msu( s, y0[-l], tilt_filter_ptr[l] ); } - i = msu_r(s, y0[-l], tilt_filter[fs_idx][scale_fac_idx][l]); + i = msu_r( s, y0[-l], tilt_filter_ptr[l] ); k = mult_r(gain, i); diff --git a/lib_lc3plus/makefile b/lib_lc3plus/makefile deleted file mode 100644 index ccf8514af..000000000 --- a/lib_lc3plus/makefile +++ /dev/null @@ -1,180 +0,0 @@ -#****************************************************************************** -# ETSI TS 103 634 V1.5.1 * -# Low Complexity Communication Codec Plus (LC3plus) * -# * -# Copyright licence is solely granted through ETSI Intellectual Property * -# Rights Policy, 3rd April 2019. No patent licence is granted by implication, * -# estoppel or otherwise. * -#*****************************************************************************/ - -# Options -AFL = 0 -GCOV = 0 -NO_POST_REL_CHANGES_TEST = 0 -OPTIM = 0 -SUBSET = ALL -WMOPS = 1 -HR = 1 -CLANG = 0 -SHORT_PLC_FADEOUT = 0 - -# Paths -VPATH = . basic_op -BUILD = build -CC = gcc -LINK = $(CC) - -# Binary Name -NAME_LC3 = LC3plus -# Shared Library Name -LIB_LC3 = libLC3plus.so - -# Default tool settings -RM = rm -f - -ifndef VERBOSE -QUIET_CC = @echo ' ' Compiling $<; -QUIET_LINK= @echo ' ' Linking $@; -QUIET = @ -endif - -# C compiler flags -# Preprocessor(-I/-D) / Compiler / Linker flags -CPPFLAGS += -Ibasic_op -DSUBSET_$(SUBSET) -CFLAGS += -std=c99 -fPIC \ - -pedantic -Wcast-qual -Wall -W -Wextra -Wno-long-long \ - -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes \ - -Werror-implicit-function-declaration - -ifneq "$(DEBUG)" "0" -CFLAGS += -g3 -LDFLAGS += -g3 -endif - -ifeq "$(HR)" "0" -CFLAGS += -DDISABLE_HR_MODE -endif - -ifeq "$(SHORT_PLC_FADEOUT)" "1" -CFLAGS += -DPLC_TUNING_SHORT_FADEOUT -endif - -# memory sanitizer, find use of uninitialized memory -ifeq "$(CLANG)" "1" - CC = clang - CFLAGS += -fsanitize=memory -fsanitize-memory-track-origins -fno-omit-frame-pointer - LDFLAGS += -fsanitize=memory -fsanitize-memory-track-origins -fno-omit-frame-pointer - OPTIM = 2 -endif - -# address sanitizer, find buffer overflows -ifeq "$(CLANG)" "2" - CC = clang - CFLAGS += -fsanitize=address -fno-omit-frame-pointer - LDFLAGS += -fsanitize=address -fno-omit-frame-pointer - OPTIM = 2 -endif - -# undefined behavior sanitizer, find bugs like integer overflows -ifeq "$(CLANG)" "3" - CC = clang - CFLAGS += -fsanitize=undefined - LDFLAGS += -fsanitize=undefined - OPTIM = 2 -endif - -LDFLAGS += -lm - -DEPFLAGS = -MT $@ -MMD -MP -MF $(BUILD)/$*.Td - -ifeq "$(GCOV)" "1" -CFLAGS += -fprofile-arcs -ftest-coverage -LDFLAGS += -fprofile-arcs -ftest-coverage -endif - -OPTIM ?= 0 -CFLAGS += -O$(OPTIM) - -CFLAGS += $(foreach DIR,$(SRC_DIRS),-I$(DIR)) - -ifeq "$(NO_POST_REL_CHANGES_TEST)" "1" -CFLAGS += -DNO_POST_REL_CHANGES -endif - -# disable wmops instrumentation -ifeq "$(WMOPS)" "0" - CPPFLAGS += -DWMOPS=0 -DDONT_COUNT_MEM -endif - -# dependency magic -CC_FLAGS = '$(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS)' -POSTCOMPILE = mv -f $(BUILD)/$*.Td $(BUILD)/$*.d && touch $@ - -############################################################################### - -SRCS := $(notdir $(foreach DIR, $(VPATH), $(wildcard $(DIR)/*.c))) - -EXCL := ccConvert.c -SRCS := $(notdir $(foreach DIR, $(VPATH), $(wildcard $(DIR)/*.c))) -SRCS := $(filter-out $(EXCL), $(SRCS)) - -EXCL_CCC := $(BUILD)/codec_exe.o -OBJS_CCC_UNF := $(addprefix $(BUILD)/, $(SRCS:.c=.o)) -OBJS_CCC := $(filter-out $(EXCL_CCC), $(OBJS_CCC_UNF)) - -OBJS := $(addprefix $(BUILD)/, $(SRCS:.c=.o)) - -LIBSRCS := $(filter-out $(DIR)/ccConvert.c $(DIR)/codec_exe.c, $(SRCS)) -LIBOBJS := $(addprefix $(BUILD)/, $(LIBSRCS:.c=.o)) - -############################################################################### - -.PHONY: all clean help force - -all: $(NAME_LC3) - -help: - @echo 'Targets:' - @echo ' $(NAME_LC3) (default)' - @echo ' $(LIB_LC3)' - @echo ' ccConvert' - @echo 'Syntax: make [OPTION=VALUE ...]' - @echo 'Build options:' - @echo ' NO_POST_REL_CHANGES_TEST $(NO_POST_REL_CHANGES_TEST) [0,1]' - @echo ' OPTIM $(OPTIM) [0-3]' - @echo ' SUBSET $(SUBSET) [NB,WB,SSWB,SWB,FB,UB,ALL]' - @echo ' WMOPS $(WMOPS) [0,1]' - @echo ' SHORT_PLC_FADEOUT $(SHORT_PLC_FADEOUT) [0,1]' - @echo 'Debug options:' - @echo ' AFL $(AFL) [0,1]' - @echo ' CLANG $(CLANG) [0-3]' - @echo ' GCOV $(GCOV) [0,1]' - -$(NAME_LC3): $(OBJS) - @echo 'Linking' $@ - $(QUIET) $(LINK) $(OBJS) -o $@ $(LDFLAGS) - -$(LIB_LC3): $(LIBOBJS) - @echo 'Linking' $@ - $(QUIET) $(LINK) --shared $(OBJS) -o $@ $(LDFLAGS) - -ccConvert: $(BUILD)/ccConvert.o $(OBJS_CCC) - @echo 'Linking' $@ - $(QUIET) $(LINK) $? -o $@ $(LDFLAGS) - -clean: - $(QUIET) rm -rf $(NAME_LC3) $(LIB_LC3) $(BUILD) ccConvert - -$(BUILD)/%.o : %.c $(BUILD)/cc_flags - @echo 'Compiling' $< - $(QUIET) $(CC) $(DEPFLAGS) $(CFLAGS) $(CPPFLAGS) -c -o $@ $< - $(QUIET) $(POSTCOMPILE) - -# force rebuild if compilation flags changed -$(BUILD)/cc_flags: force - $(QUIET) mkdir -p $(BUILD) - $(QUIET) echo $(CC_FLAGS) | cmp -s - $@ || echo $(CC_FLAGS) > $@ - -# force rebuild if include dependency changed -$(BUILD)/%.d: ; -include $(wildcard $(patsubst %, $(BUILD)/%.d, $(basename $(SRCS)))) diff --git a/lib_lc3plus/mdct_fx.c b/lib_lc3plus/mdct_fx.c index 1953b6d68..b2cde56ab 100644 --- a/lib_lc3plus/mdct_fx.c +++ b/lib_lc3plus/mdct_fx.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,6 +7,8 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "functions.h" /* Union holding buffers to conserve stack memory. */ @@ -134,7 +136,7 @@ void processMdct_fx( } #endif - s = s_max(0, getScaleFactor32_lc3plus(y, N)); + s = s_max(0, getScaleFactor32(y, N)); FOR (i = 0; i < N; i++) { y[i] = L_shl(y[i], s); move32(); @@ -144,7 +146,7 @@ void processMdct_fx( /* N=20 only for 2.5ms possible */ /* maybe implement this a pre init of shift */ - if (sub(N, 20) <= 0) + if (sub(N, 30) <= 0) { *y_e = add(*y_e, 2); } diff --git a/lib_lc3plus/mdct_shaping_fx.c b/lib_lc3plus/mdct_shaping_fx.c index 1637a5275..90e29aa36 100644 --- a/lib_lc3plus/mdct_shaping_fx.c +++ b/lib_lc3plus/mdct_shaping_fx.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,6 +7,8 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "functions.h" void processMdctShaping_fx(Word32 x[], diff --git a/lib_lc3plus/near_nyquist_detector_fx.c b/lib_lc3plus/near_nyquist_detector_fx.c index 595ff435c..c88a7fc9f 100644 --- a/lib_lc3plus/near_nyquist_detector_fx.c +++ b/lib_lc3plus/near_nyquist_detector_fx.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,15 +7,16 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "functions.h" void processNearNyquistdetector_fx(Word16 *near_nyquist_flag, const Word16 fs_idx, const Word16 near_nyquist_index, const Word16 bands_number, const Word32 *ener_fx, const Word16 ener_fx_exp #ifdef ENABLE_HR_MODE - , Word16 frame_dms, Word16 hrmode) -#else - ) + ,LC3PLUS_FrameDuration frame_dms, Word16 hrmode #endif + ) { *near_nyquist_flag = 0; #ifdef ENABLE_HR_MODE @@ -38,20 +39,20 @@ void processNearNyquistdetector_fx(Word16 *near_nyquist_flag, const Word16 fs_id ener_low_exp = 0; move16(); FOR (i = 0; i < near_nyquist_index; i++) { - ener_low = BASOP_Util_Add_Mant32Exp_lc3plus(ener_fx[i], ener_fx_exp, ener_low, ener_low_exp, &ener_low_exp); + ener_low = BASOP_Util_Add_Mant32Exp(ener_fx[i], ener_fx_exp, ener_low, ener_low_exp, &ener_low_exp); } ener_high = 0; move32(); ener_high_exp = 0; move16(); FOR (i = near_nyquist_index; i < bands_number; i++) { - ener_high = BASOP_Util_Add_Mant32Exp_lc3plus(ener_fx[i], ener_fx_exp, ener_high, ener_high_exp, &ener_high_exp); + ener_high = BASOP_Util_Add_Mant32Exp(ener_fx[i], ener_fx_exp, ener_high, ener_high_exp, &ener_high_exp); } - comp_energy = Mpy_32_16_lc3plus(ener_low, NN_thresh); /* Mpy_32_16_lc3plus -> 32Q15 */ + comp_energy = Mpy_32_16_lc3plus(ener_low, NN_thresh); /* Mpy_32_16 -> 32Q15 */ comp_energy_exp = add(add(ener_low_exp, NN_thresh_exp),15); - nrg_above_thresh = BASOP_Util_Cmp_Mant32Exp_lc3plus(ener_high, ener_high_exp, comp_energy, comp_energy_exp); /* 1 if firstNumber > secondNumber */ + nrg_above_thresh = BASOP_Util_Cmp_Mant32Exp(ener_high, ener_high_exp, comp_energy, comp_energy_exp); /* 1 if firstNumber > secondNumber */ if (sub(nrg_above_thresh, 1) == 0) { @@ -62,25 +63,31 @@ void processNearNyquistdetector_fx(Word16 *near_nyquist_flag, const Word16 fs_id } #ifdef ENABLE_HR_MODE } - ELSE // hrmode == 1 + ELSE /* hrmode == 1 */ { - // inverse spectral flatness = mean(energy) ./ 2^(mean(log2(energy))); - Word32 td_thresh; + /* inverse spectral flatness = mean(energy) ./ 2^(mean(log2(energy))); */ + Word32 td_thresh = 0; SWITCH (frame_dms) { - case 25: +#ifdef CR9_C_ADD_1p25MS + case LC3PLUS_FRAME_DURATION_1p25MS: + assert(0); + BREAK; +#endif + case LC3PLUS_FRAME_DURATION_2p5MS: td_thresh = TD_HR_thresh_2_5ms; BREAK; - case 50: + case LC3PLUS_FRAME_DURATION_5MS: td_thresh = TD_HR_thresh_5ms; BREAK; - case 75: + case LC3PLUS_FRAME_DURATION_7p5MS: td_thresh = TD_HR_thresh_7_5ms; BREAK; - default: /* 100 */ + case LC3PLUS_FRAME_DURATION_10MS: td_thresh = TD_HR_thresh_10ms; BREAK; + case LC3PLUS_FRAME_DURATION_UNDEFINED: assert(0); } Word16 mean_ener_exp = 0; @@ -89,15 +96,15 @@ void processNearNyquistdetector_fx(Word16 *near_nyquist_flag, const Word16 fs_id Word16 sum_ener_exp = 0; move16(); FOR (Word16 i = 0; i < bands_number; i++) { - sum_ener = BASOP_Util_Add_Mant32Exp_lc3plus(ener_fx[i], ener_fx_exp, sum_ener, sum_ener_exp, &sum_ener_exp); + sum_ener = BASOP_Util_Add_Mant32Exp(ener_fx[i], ener_fx_exp, sum_ener, sum_ener_exp, &sum_ener_exp); } Word16 denom = sub(14,norm_s(bands_number)); - IF (sub(frame_dms, 50) == 0){ + IF (sub(frame_dms, LC3PLUS_FRAME_DURATION_5MS) == 0){ denom = sub(15,norm_s(bands_number)); move16(); } - Word32 mean_ener = L_shr(sum_ener, denom); move32(); // = sum_ener / bands_number + Word32 mean_ener = L_shr(sum_ener, denom); move32(); mean_ener_exp = sum_ener_exp; move16(); Word32 sum_ener_log2 = 0;move32(); @@ -107,10 +114,10 @@ void processNearNyquistdetector_fx(Word16 *near_nyquist_flag, const Word16 fs_id FOR (Word16 i = 0; i < bands_number; i++) { IF (ener_fx[i] != 0) { - Word32 log2Value = L_add(BASOP_Util_Log2_lc3plus(ener_fx[i]), L_shl_pos(L_deposit_l(ener_fx_exp), 25)); + Word32 log2Value = L_add(BASOP_Util_Log2(ener_fx[i]), L_shl_pos(L_deposit_l(ener_fx_exp), 25)); /* input argument is in Q7.25 , returns pow(2,(x/64) floatingpoint value log2_fl = log2Value/pow(2,31-6) */ - sum_ener_log2 = BASOP_Util_Add_Mant32Exp_lc3plus(log2Value, 6, sum_ener_log2, sum_ener_log2_exp, &sum_ener_log2_exp); move32(); + sum_ener_log2 = BASOP_Util_Add_Mant32Exp(log2Value, 6, sum_ener_log2, sum_ener_log2_exp, &sum_ener_log2_exp); move32(); } } mean_ener_log2 = L_shr(sum_ener_log2, denom); move32(); //mean_ener_log2 = sum_ener_log2 / bands_number @@ -127,5 +134,5 @@ void processNearNyquistdetector_fx(Word16 *near_nyquist_flag, const Word16 fs_id *near_nyquist_flag = 1; move16(); } } - #endif // ENABLE_HR_MODE + #endif /* ENABLE_HR_MODE */ } diff --git a/lib_lc3plus/noise_factor_fx.c b/lib_lc3plus/noise_factor_fx.c index c6b5aa87b..c73eef56e 100644 --- a/lib_lc3plus/noise_factor_fx.c +++ b/lib_lc3plus/noise_factor_fx.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,6 +7,8 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "functions.h" @@ -16,7 +18,7 @@ void processNoiseFactor_fx(Word16 *fac_ns_idx, Word16 x_e, Word32 x[], #else Word16 xq[], #endif - Word16 gg, Word16 gg_e, Word16 BW_cutoff_idx, Word16 frame_dms, Word16 target_bytes, + Word16 gg, Word16 gg_e, Word16 BW_cutoff_idx, LC3PLUS_FrameDuration frame_dms, Word16 target_bytes, Word8 *scratchBuffer #ifdef ENABLE_HR_MODE ,Word16 hrmode @@ -50,25 +52,33 @@ void processNoiseFactor_fx(Word16 *fac_ns_idx, Word16 x_e, Word32 x[], SWITCH (frame_dms) { - case 25: +#ifdef CR9_C_ADD_1p25MS + case LC3PLUS_FRAME_DURATION_1p25MS: + N = shr_pos(N, 3); + noisefillwidth = NOISEFILLWIDTH_1_25MS; + noisefillstart = NOISEFILLSTART_1_25MS; + BREAK; +#endif + case LC3PLUS_FRAME_DURATION_2p5MS: N = shr_pos(N, 2); noisefillwidth = NOISEFILLWIDTH_2_5MS; noisefillstart = NOISEFILLSTART_2_5MS; BREAK; - case 50: + case LC3PLUS_FRAME_DURATION_5MS: N = shr_pos(N, 1); noisefillwidth = NOISEFILLWIDTH_5MS; noisefillstart = NOISEFILLSTART_5MS; BREAK; - case 75: + case LC3PLUS_FRAME_DURATION_7p5MS: N = add(shr_pos(N, 2), add(shr_pos(N, 2), shr_pos(N, 2))); noisefillwidth = NOISEFILLWIDTH_7_5MS; noisefillstart = NOISEFILLSTART_7_5MS; BREAK; - case 100: + case LC3PLUS_FRAME_DURATION_10MS: noisefillwidth = NOISEFILLWIDTH; noisefillstart = NOISEFILLSTART; BREAK; + case LC3PLUS_FRAME_DURATION_UNDEFINED: assert(0); } nzeros = -2 * noisefillwidth - 1; @@ -123,7 +133,7 @@ void processNoiseFactor_fx(Word16 *fac_ns_idx, Word16 x_e, Word32 x[], ELSE { - IF (target_bytes <= 20 && frame_dms == 100) + IF (target_bytes <= 20 && frame_dms == LC3PLUS_FRAME_DURATION_10MS) { Word32 ind_sum; Word16 mean_ind; @@ -138,7 +148,7 @@ void processNoiseFactor_fx(Word16 *fac_ns_idx, Word16 x_e, Word32 x[], ind_sum = L_add(ind_sum, ind[k]); } - mean_ind = BASOP_Util_Divide3216_Scale_lc3plus(ind_sum, c, &s2); + mean_ind = BASOP_Util_Divide3216_Scale(ind_sum, c, &s2); mean_ind = shl(mean_ind, s2 + 1); assert(0 <= mean_ind && mean_ind <= ind[c - 1]); @@ -148,7 +158,7 @@ void processNoiseFactor_fx(Word16 *fac_ns_idx, Word16 x_e, Word32 x[], if (sub(mean_ind, ind[0]) > 0) { /* calculate scale to ensure that Lsum does not overflow */ - s2 = s_max(sub(sub(14, norm_s(c)), getScaleFactor32_lc3plus(&x[ind[0]], sub(mean_ind, ind[0]))), 0); + s2 = s_max(sub(sub(14, norm_s(c)), getScaleFactor32(&x[ind[0]], sub(mean_ind, ind[0]))), 0); } Lsum = L_shr_pos_pos(L_abs(x[ind[0]]), s2); @@ -157,10 +167,10 @@ void processNoiseFactor_fx(Word16 *fac_ns_idx, Word16 x_e, Word32 x[], /* scale before adding to Lsum */ Lsum = L_add(Lsum, L_shr_pos_pos(L_abs(x[ind[k]]), s2)); } - fac_unq1 = BASOP_Util_Divide3216_Scale_lc3plus(Lsum, k, &s1); + fac_unq1 = BASOP_Util_Divide3216_Scale(Lsum, k, &s1); /* add scale applied during summing */ s1 = add(s1, s2); - fac_unq1 = BASOP_Util_Divide1616_Scale_lc3plus(fac_unq1, gg, &s2); + fac_unq1 = BASOP_Util_Divide1616_Scale(fac_unq1, gg, &s2); s3 = sub(15, add(x_e, add(s1, sub(s2, gg_e)))); s2 = norm_s(fac_unq1); test(); @@ -183,8 +193,8 @@ void processNoiseFactor_fx(Word16 *fac_ns_idx, Word16 x_e, Word32 x[], { Lsum = L_add(Lsum, L_abs(x[ind[k]])); } - fac_unq2 = BASOP_Util_Divide3216_Scale_lc3plus(Lsum, idx, &s1); - fac_unq2 = BASOP_Util_Divide1616_Scale_lc3plus(fac_unq2, gg, &s2); + fac_unq2 = BASOP_Util_Divide3216_Scale(Lsum, idx, &s1); + fac_unq2 = BASOP_Util_Divide1616_Scale(fac_unq2, gg, &s2); s3 = sub(15, add(x_e, add(s1, sub(s2, gg_e)))); s2 = norm_s(fac_unq1); test(); @@ -205,17 +215,17 @@ void processNoiseFactor_fx(Word16 *fac_ns_idx, Word16 x_e, Word32 x[], ELSE { /* calculate scale to ensure that Lsum does not overflow */ - s2 = s_max(sub(sub(14, norm_s(c)), getScaleFactor32_lc3plus(&x[ind[0]], sub(N,ind[0]))), 0); + s2 = s_max(sub(sub(14, norm_s(c)), getScaleFactor32(&x[ind[0]], sub(N,ind[0]))), 0); Lsum = L_abs(x[ind[0]]); FOR (k = 1; k < c; k++) { /* scale before adding to Lsum */ Lsum = L_add(Lsum, L_shr_pos_pos(L_abs(x[ind[k]]), s2)); } - fac_unq = BASOP_Util_Divide3216_Scale_lc3plus(Lsum, c, &s1); + fac_unq = BASOP_Util_Divide3216_Scale(Lsum, c, &s1); /* add scale applied during summing */ s1 = add(s1, s2); - fac_unq = BASOP_Util_Divide1616_Scale_lc3plus(fac_unq, gg, &s2); + fac_unq = BASOP_Util_Divide1616_Scale(fac_unq, gg, &s2); s3 = sub(15, add(x_e, add(s1, sub(s2, gg_e)))); s2 = norm_s(fac_unq); test(); diff --git a/lib_lc3plus/noise_filling_fx.c b/lib_lc3plus/noise_filling_fx.c index 5b22983d8..0be080f6f 100644 --- a/lib_lc3plus/noise_filling_fx.c +++ b/lib_lc3plus/noise_filling_fx.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,6 +7,8 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "functions.h" /*************************************************************************/ @@ -14,7 +16,7 @@ void processNoiseFilling_fx(Word32 xq[], Word16 nfseed, Word16 xq_e, Word16 fac_ns_idx, Word16 BW_cutoff_idx, - Word16 frame_dms, Word16 fac_ns_pc, Word16 spec_inv_idx, Word8 *scratchBuffer + LC3PLUS_FrameDuration frame_dms, Word16 fac_ns_pc, Word16 spec_inv_idx, Word8 *scratchBuffer #ifdef ENABLE_HR_MODE , Word16 hrmode #endif @@ -27,6 +29,8 @@ void processNoiseFilling_fx(Word32 xq[], Word16 nfseed, Word16 xq_e, Word16 fac_ Word32 L_tmp, L_tmp_neg, L_tmp_pc, L_tmp_neg_pc; ); + noisefillwidth = 0; move16(); + noisefillstart = 0; move16(); ind = (Word16 *)scratchAlign(scratchBuffer, 0); /* Size = 2 * MAX_LEN bytes */ c = 0; move16(); @@ -46,25 +50,33 @@ void processNoiseFilling_fx(Word32 xq[], Word16 nfseed, Word16 xq_e, Word16 fac_ SWITCH (frame_dms) { - case 25: +#ifdef CR9_C_ADD_1p25MS + case LC3PLUS_FRAME_DURATION_1p25MS: + N = shr_pos(N, 3); + noisefillwidth = NOISEFILLWIDTH_1_25MS; + noisefillstart = NOISEFILLSTART_1_25MS; + BREAK; +#endif + case LC3PLUS_FRAME_DURATION_2p5MS: N = shr_pos(N, 2); noisefillwidth = NOISEFILLWIDTH_2_5MS; noisefillstart = NOISEFILLSTART_2_5MS; BREAK; - case 50: + case LC3PLUS_FRAME_DURATION_5MS: N = shr_pos(N, 1); noisefillwidth = NOISEFILLWIDTH_5MS; noisefillstart = NOISEFILLSTART_5MS; BREAK; - case 75: + case LC3PLUS_FRAME_DURATION_7p5MS: N = add(shr_pos(N, 2), add(shr_pos(N, 2), shr_pos(N, 2))); noisefillwidth = NOISEFILLWIDTH_7_5MS; noisefillstart = NOISEFILLSTART_7_5MS; BREAK; - default: /* 100 */ + case LC3PLUS_FRAME_DURATION_10MS: noisefillwidth = NOISEFILLWIDTH; noisefillstart = NOISEFILLSTART; BREAK; + case LC3PLUS_FRAME_DURATION_UNDEFINED: assert(0); } nzeros = -2 * noisefillwidth - 1; move16(); diff --git a/lib_lc3plus/olpa_fx.c b/lib_lc3plus/olpa_fx.c index 53f15ca9b..813182609 100644 --- a/lib_lc3plus/olpa_fx.c +++ b/lib_lc3plus/olpa_fx.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,6 +7,8 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "functions.h" /*************************************************************************/ @@ -15,7 +17,7 @@ void process_olpa_fx(Word16 *mem_s6k4_exp, Word16 mem_s12k8[], Word16 mem_s6k4[], Word16 *pitch, Word16 *s12k8, Word16 len, Word16 *normcorr, Word16 *mem_pitch, Word16 *pitch_flag, - Word16 s12k8_exp, Word16 frame_dms, Word8 *scratchBuffer) + Word16 s12k8_exp, LC3PLUS_FrameDuration frame_dms, Word8 *scratchBuffer) { Word32 sum, sum0, sum1, sum2, prod, inv; Word16 shift, s6k4_exp, prod_exp, min_pitch, max_pitch; @@ -54,15 +56,24 @@ void process_olpa_fx(Word16 *mem_s6k4_exp, Word16 mem_s12k8[], Word16 mem_s6k4[] SWITCH(frame_dms) { - case 50: + case LC3PLUS_FRAME_DURATION_10MS: break; + case LC3PLUS_FRAME_DURATION_7p5MS: break; + case LC3PLUS_FRAME_DURATION_5MS: mem_in_len = add(mem_in_len, 32); acflen = add(acflen, 32); break; - case 25: + case LC3PLUS_FRAME_DURATION_2p5MS: mem_in_len = add(mem_in_len, 48); acflen = add(acflen, 48); break; + case LC3PLUS_FRAME_DURATION_UNDEFINED: assert(0); +#ifdef CR9_C_ADD_1p25MS + case LC3PLUS_FRAME_DURATION_1p25MS: + mem_in_len = add(mem_in_len, 56); + acflen = add(acflen, 56); + break; +#endif } s6k4 = mem_s6k4 + mem_in_len; @@ -103,13 +114,21 @@ void process_olpa_fx(Word16 *mem_s6k4_exp, Word16 mem_s12k8[], Word16 mem_s6k4[] SWITCH(frame_dms) { - case 50: + case LC3PLUS_FRAME_DURATION_10MS: break; + case LC3PLUS_FRAME_DURATION_7p5MS: break; + case LC3PLUS_FRAME_DURATION_5MS: s6k4 = s6k4 - 32; break; - case 25: + case LC3PLUS_FRAME_DURATION_2p5MS: s6k4 = s6k4 - 48; break; +#ifdef CR9_C_ADD_1p25MS + case LC3PLUS_FRAME_DURATION_1p25MS: + s6k4 = s6k4 - 56; + break; +#endif + case LC3PLUS_FRAME_DURATION_UNDEFINED: assert(0); } Scale_sig(mem_s6k4, mem_in_len, shift); @@ -229,7 +248,7 @@ void process_olpa_fx(Word16 *mem_s6k4_exp, Word16 mem_s12k8[], Word16 mem_s6k4[] SWITCH(frame_dms) { - case 50: + case LC3PLUS_FRAME_DURATION_5MS: if(*pitch_flag == 1) { *mem_pitch = *pitch; move16(); *pitch_flag = 0; @@ -239,7 +258,7 @@ void process_olpa_fx(Word16 *mem_s6k4_exp, Word16 mem_s12k8[], Word16 mem_s6k4[] } break; - case 25: + case LC3PLUS_FRAME_DURATION_2p5MS: if (*pitch_flag == 3) { *mem_pitch = *pitch; move16(); *pitch_flag = 0; @@ -248,6 +267,17 @@ void process_olpa_fx(Word16 *mem_s6k4_exp, Word16 mem_s12k8[], Word16 mem_s6k4[] *pitch_flag += 1; } break; +#ifdef CR9_C_ADD_1p25MS + case LC3PLUS_FRAME_DURATION_1p25MS: + if (*pitch_flag == 7) { + *mem_pitch = *pitch; move16(); + *pitch_flag = 0; + } + else { + *pitch_flag += 1; + } + break; +#endif default: diff --git a/lib_lc3plus/pc_apply_fx.c b/lib_lc3plus/pc_apply_fx.c index cac9e1735..c34c83e14 100644 --- a/lib_lc3plus/pc_apply_fx.c +++ b/lib_lc3plus/pc_apply_fx.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,6 +7,8 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "defines.h" #include "constants.h" #include "functions.h" @@ -54,7 +56,7 @@ void processPCapply_fx(Word16 yLen, Word16 q_old_res_fx[], Word16 *q_old_res_fx_ tmp32 = L_shl_pos(L_mult0(add(gg_idx, gg_idx_off), 0x797D), 7); global_gain_e = add(extract_l(L_shr_pos(tmp32, 25)), 1); - global_gain = round_fx(BASOP_Util_InvLog2_lc3plus(L_or(tmp32, 0xFE000000))); + global_gain = round_fx(BASOP_Util_InvLog2(L_or(tmp32, 0xFE000000))); /** Calculate rescaling factor **/ @@ -103,7 +105,7 @@ void processPCapply_fx(Word16 yLen, Word16 q_old_res_fx[], Word16 *q_old_res_fx_ move32(); #ifdef ENABLE_HR_MODE - s2 = getScaleFactor32_lc3plus(q_res_fx, spec_inv_idx); + s2 = getScaleFactor32(q_res_fx, spec_inv_idx); FOR (i = 0; i < spec_inv_idx; i++) { tmp16 = extract_h(L_shl_sat(q_res_fx[i], sub(s2, 4))); @@ -132,8 +134,8 @@ void processPCapply_fx(Word16 yLen, Word16 q_old_res_fx[], Word16 *q_old_res_fx_ IF ( ener_prev > 0 ) { /* fac = sqrt(ener_curr/ener_prev); */ - s = getScaleFactor32_lc3plus(&ener_prev, 1); - s2 = getScaleFactor32_lc3plus(&ener_curr, 1); + s = getScaleFactor32(&ener_prev, 1); + s2 = getScaleFactor32(&ener_curr, 1); s3 = s_min(s, s2); tmp16 = extract_h(L_shl_sat(ener_curr, s3)); tmp16_2 = extract_h(L_shl_sat(ener_prev, s3)); @@ -143,14 +145,14 @@ void processPCapply_fx(Word16 yLen, Word16 q_old_res_fx[], Word16 *q_old_res_fx_ tmp16_2 = 32767; move16(); *fac_e = 15; move16(); } else { - tmp16_2 = Inv16_lc3plus(tmp16_2, fac_e); + tmp16_2 = Inv16(tmp16_2, fac_e); } *fac = mult(tmp16, tmp16_2); IF (sub(*fac, 32767) < 0) { - *fac = Sqrt16_lc3plus(*fac, fac_e); move16(); + *fac = Sqrt16(*fac, fac_e); move16(); } } @@ -177,7 +179,7 @@ void processPCapply_fx(Word16 yLen, Word16 q_old_res_fx[], Word16 *q_old_res_fx_ { /* fac = prev_gg/gg; */ s = global_gain_e; move16(); - inv_gain = Inv16_lc3plus(global_gain, &s); + inv_gain = Inv16(global_gain, &s); fac_local = mult(prev_gg, inv_gain); fac_local_e = add(s, prev_gg_e); } diff --git a/lib_lc3plus/pc_classify_fx.c b/lib_lc3plus/pc_classify_fx.c index 97d62d9f9..a9736b9b9 100644 --- a/lib_lc3plus/pc_classify_fx.c +++ b/lib_lc3plus/pc_classify_fx.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,6 +7,8 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "defines.h" #include "constants.h" #include "functions.h" @@ -17,7 +19,7 @@ void peakDetector_fx(Word16 in_sig[], Word16 yLen, Word16 *xover); -void processPCclassify_fx(Word16 pitch_present, Word16 frame_dms, Word16 q_old_d_fx[], Word16 q_old_res_fx[], +void processPCclassify_fx(Word16 pitch_present, LC3PLUS_FrameDuration frame_dms, Word16 q_old_d_fx[], Word16 q_old_res_fx[], Word16 yLen, Word16 spec_inv_idx, Word16 stab_fac, Word16 *bfi) { Dyn_Mem_Deluxe_In( @@ -26,9 +28,28 @@ void processPCclassify_fx(Word16 pitch_present, Word16 frame_dms, Word16 q_old_d Word16 s, tmp16, full_nrg16, part_nrg16; Word32 full_nrg, part_nrg; ); + + int frame_dms_val = 0; + SWITCH (frame_dms) + { +#ifdef CR9_C_ADD_1p25MS + case LC3PLUS_FRAME_DURATION_1p25MS: + assert(0); frame_dms_val = 125; BREAK; +#endif + case LC3PLUS_FRAME_DURATION_2p5MS: + frame_dms_val = 250; BREAK; + case LC3PLUS_FRAME_DURATION_5MS: + frame_dms_val = 500; BREAK; + case LC3PLUS_FRAME_DURATION_7p5MS: + frame_dms_val = 750; BREAK; + case LC3PLUS_FRAME_DURATION_10MS: + frame_dms_val = 1000; BREAK; + case LC3PLUS_FRAME_DURATION_UNDEFINED: + assert(0); + } /* Apply classifier only if lower than 2kHz signal */ - IF (sub(DEPR_i_mult(spec_inv_idx, 10), shl_pos(frame_dms, 2)) < 0 ) + IF (sub(i_mult(spec_inv_idx, 10), shl_pos(frame_dms_val/10, 2)) < 0 ) { IF (sub(stab_fac, 16384 /* 0.5 */) < 0) { @@ -37,7 +58,7 @@ void processPCclassify_fx(Word16 pitch_present, Word16 frame_dms, Word16 q_old_d ELSE IF (sub(pitch_present, 1) == 0) { maxPitchBin = 8; move16(); - IF (sub(frame_dms, 50) == 0) + IF (sub(frame_dms, LC3PLUS_FRAME_DURATION_5MS) == 0) { maxPitchBin = 4; move16(); } @@ -68,7 +89,7 @@ void processPCclassify_fx(Word16 pitch_present, Word16 frame_dms, Word16 q_old_d full_nrg = L_mac0(full_nrg, tmp16, tmp16); /* exp = 2s - 8 */ } - s = getScaleFactor32_lc3plus(&full_nrg, 1); + s = getScaleFactor32(&full_nrg, 1); full_nrg16 = extract_h(L_shl(full_nrg, s)); part_nrg16 = extract_h(L_shl(part_nrg, s)); @@ -114,7 +135,7 @@ void peakDetector_fx(Word16 in_sig[], Word16 yLen, Word16 *xover) c = sub(yLen, 2 * BLOCK_SIZE); test(); - IF (abs_s(in_sig[0]) >= abs_s(in_sig[1])) + IF (abs_s_sat(in_sig[0]) >= abs_s_sat(in_sig[1])) { block_cent = 0; move32(); FOR (j = 0; j <= 1; j++) @@ -126,12 +147,12 @@ void peakDetector_fx(Word16 in_sig[], Word16 yLen, Word16 *xover) IF (L_sub(block_cent, mean_block_nrg) > 0) { - cur_max = abs_s(in_sig[0]); - cur_max = MAX(abs_s(in_sig[1]), cur_max); + cur_max = abs_s_sat(in_sig[0]); + cur_max = MAX(abs_s_sat(in_sig[1]), cur_max); - next_max = abs_s(in_sig[-1 + BLOCK_SIZE]); - next_max = MAX(abs_s(in_sig[-1 + BLOCK_SIZE + 1]), next_max); - next_max = MAX(abs_s(in_sig[-1 + BLOCK_SIZE + 2]), next_max); + next_max = abs_s_sat(in_sig[-1 + BLOCK_SIZE]); + next_max = MAX(abs_s_sat(in_sig[-1 + BLOCK_SIZE + 1]), next_max); + next_max = MAX(abs_s_sat(in_sig[-1 + BLOCK_SIZE + 2]), next_max); IF (sub(cur_max, next_max) > 0) { @@ -144,7 +165,7 @@ void peakDetector_fx(Word16 in_sig[], Word16 yLen, Word16 *xover) FOR (i = 0; i < BLOCK_SIZE; i++) { test(); - IF (abs_s(in_sig[i + 1]) >= abs_s(in_sig[i]) && abs_s(in_sig[i + 1]) >= abs_s(in_sig[i + 2])) + IF (abs_s_sat(in_sig[i + 1]) >= abs_s_sat(in_sig[i]) && abs_s_sat(in_sig[i + 1]) >= abs_s_sat(in_sig[i + 2])) { block_cent = 0; move32(); FOR (j = 0; j < BLOCK_SIZE; j++) @@ -156,22 +177,22 @@ void peakDetector_fx(Word16 in_sig[], Word16 yLen, Word16 *xover) IF (L_sub(block_cent, mean_block_nrg) > 0) { - cur_max = abs_s(in_sig[i]); - cur_max = MAX(abs_s(in_sig[i + 1]), cur_max); - cur_max = MAX(abs_s(in_sig[i + 2]), cur_max); + cur_max = abs_s_sat(in_sig[i]); + cur_max = MAX(abs_s_sat(in_sig[i + 1]), cur_max); + cur_max = MAX(abs_s_sat(in_sig[i + 2]), cur_max); prev_max = 0; move16(); FOR (j = i - BLOCK_SIZE; j <= i - 1; j++) { IF (j > 0) { - prev_max = MAX(abs_s(in_sig[j]), prev_max); + prev_max = MAX(abs_s_sat(in_sig[j]), prev_max); } } - next_max = abs_s(in_sig[i + BLOCK_SIZE]); - next_max = MAX(abs_s(in_sig[i + BLOCK_SIZE + 1]), next_max); - next_max = MAX(abs_s(in_sig[i + BLOCK_SIZE + 2]), next_max); + next_max = abs_s_sat(in_sig[i + BLOCK_SIZE]); + next_max = MAX(abs_s_sat(in_sig[i + BLOCK_SIZE + 1]), next_max); + next_max = MAX(abs_s_sat(in_sig[i + BLOCK_SIZE + 2]), next_max); test(); IF (sub(cur_max, prev_max) >= 0 && sub(cur_max, next_max) > 0) @@ -203,7 +224,7 @@ void peakDetector_fx(Word16 in_sig[], Word16 yLen, Word16 *xover) FOR (i = BLOCK_SIZE; i <= c; i++) { test(); - IF (abs_s(in_sig[i + 1]) >= abs_s(in_sig[i]) && abs_s(in_sig[i + 1]) >= abs_s(in_sig[i + 2])) + IF (abs_s_sat(in_sig[i + 1]) >= abs_s_sat(in_sig[i]) && abs_s_sat(in_sig[i + 1]) >= abs_s_sat(in_sig[i + 2])) { block_cent = 0; move32(); FOR (j = 0; j < BLOCK_SIZE; j++) @@ -215,17 +236,17 @@ void peakDetector_fx(Word16 in_sig[], Word16 yLen, Word16 *xover) IF (L_sub(block_cent, mean_block_nrg) > 0) { - cur_max = abs_s(in_sig[i]); - cur_max = MAX(abs_s(in_sig[i + 1]), cur_max); - cur_max = MAX(abs_s(in_sig[i + 2]), cur_max); + cur_max = abs_s_sat(in_sig[i]); + cur_max = MAX(abs_s_sat(in_sig[i + 1]), cur_max); + cur_max = MAX(abs_s_sat(in_sig[i + 2]), cur_max); - prev_max = abs_s(in_sig[i - BLOCK_SIZE]); - prev_max = MAX(abs_s(in_sig[i - BLOCK_SIZE + 1]), prev_max); - prev_max = MAX(abs_s(in_sig[i - BLOCK_SIZE + 2]), prev_max); + prev_max = abs_s_sat(in_sig[i - BLOCK_SIZE]); + prev_max = MAX(abs_s_sat(in_sig[i - BLOCK_SIZE + 1]), prev_max); + prev_max = MAX(abs_s_sat(in_sig[i - BLOCK_SIZE + 2]), prev_max); - next_max = abs_s(in_sig[i + BLOCK_SIZE]); - next_max = MAX(abs_s(in_sig[i + BLOCK_SIZE + 1]), next_max); - next_max = MAX(abs_s(in_sig[i + BLOCK_SIZE + 2]), next_max); + next_max = abs_s_sat(in_sig[i + BLOCK_SIZE]); + next_max = MAX(abs_s_sat(in_sig[i + BLOCK_SIZE + 1]), next_max); + next_max = MAX(abs_s_sat(in_sig[i + BLOCK_SIZE + 2]), next_max); test(); IF (sub(cur_max, prev_max) >= 0 && sub(cur_max, next_max) > 0) diff --git a/lib_lc3plus/pc_main_fx.c b/lib_lc3plus/pc_main_fx.c index de598b4d8..3e159b301 100644 --- a/lib_lc3plus/pc_main_fx.c +++ b/lib_lc3plus/pc_main_fx.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,11 +7,13 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "defines.h" #include "constants.h" #include "functions.h" -void processPCmain_fx(Word16 rframe, Word16 *bfi, Word16 yLen, Word16 frame_dms, Word16 q_old_res_fx[], +void processPCmain_fx(Word16 rframe, Word16 *bfi, Word16 yLen, LC3PLUS_FrameDuration frame_dms, Word16 q_old_res_fx[], Word16 *q_old_res_fx_exp, #ifdef ENABLE_HR_MODE Word32 q_res_fx[], diff --git a/lib_lc3plus/pc_update_fx.c b/lib_lc3plus/pc_update_fx.c index e17dc1186..6823a320f 100644 --- a/lib_lc3plus/pc_update_fx.c +++ b/lib_lc3plus/pc_update_fx.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,6 +7,8 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "defines.h" #include "constants.h" #include "functions.h" @@ -67,13 +69,13 @@ void processPCupdate_fx(Word16 bfi, Word16 yLen, Word16 q_old_res_fx[], Word16 * tmp32 = L_shl_pos(L_mult0(add(gg_idx, gg_idx_off), 0x797D), 7); global_gain_e = add(extract_l(L_shr_pos(tmp32, 25)), 1); - global_gain = round_fx(BASOP_Util_InvLog2_lc3plus(L_or(tmp32, 0xFE000000))); + global_gain = round_fx(BASOP_Util_InvLog2(L_or(tmp32, 0xFE000000))); *prev_gg = global_gain; move16(); *prev_gg_e = global_gain_e; move16(); #ifdef ENABLE_HR_MODE - s = getScaleFactor32_lc3plus(q_res_fx, spec_inv_idx); /* exp = 0 */ + s = getScaleFactor32(q_res_fx, spec_inv_idx); /* exp = 0 */ #else s = getScaleFactor16(q_res_fx, spec_inv_idx); /* exp = 0 */ #endif @@ -91,7 +93,7 @@ void processPCupdate_fx(Word16 bfi, Word16 yLen, Word16 q_old_res_fx[], Word16 * ELSE { #ifdef ENABLE_HR_MODE - s2 = getScaleFactor32_lc3plus(&q_res_fx[spec_inv_idx], sub(yLen, spec_inv_idx)); /* exp = q_old_res_fx_exp */ + s2 = getScaleFactor32(&q_res_fx[spec_inv_idx], sub(yLen, spec_inv_idx)); /* exp = q_old_res_fx_exp */ IF (s2 == 0) s2 = 16; s3 = add(s, *q_old_res_fx_exp); diff --git a/lib_lc3plus/per_band_energy_fx.c b/lib_lc3plus/per_band_energy_fx.c index a8b9bcac9..86c848c01 100644 --- a/lib_lc3plus/per_band_energy_fx.c +++ b/lib_lc3plus/per_band_energy_fx.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,11 +7,13 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "functions.h" #include "rom_basop_util_lc3plus.h" void processPerBandEnergy_fx(Word32 *d2_fx, Word16 *d2_fx_exp, Word32 *d_fx, Word16 d_fx_exp, - const Word16 *band_offsets, Word16 fs_idx, Word16 n_bands, Word16 linear, Word16 frame_dms, + const Word16 *band_offsets, Word16 fs_idx, Word16 n_bands, Word16 linear, LC3PLUS_FrameDuration frame_dms, Word8 *scratchBuffer #ifdef ENABLE_HR_MODE , Word16 hrmode @@ -24,6 +26,8 @@ void processPerBandEnergy_fx(Word32 *d2_fx, Word16 *d2_fx_exp, Word32 *d_fx, Wor d2_band_fx_exp = (Word16 *)scratchAlign(scratchBuffer, 0); /* Size = 2 * MAX_BANDS_NUMBER_PLC bytes */ + bandsOffsetOne = 0; move16(); + bandsOffsetTwo = 0; move16(); #ifdef ENABLE_HR_MODE if (hrmode) @@ -41,7 +45,17 @@ void processPerBandEnergy_fx(Word32 *d2_fx, Word16 *d2_fx_exp, Word32 *d_fx, Wor SWITCH (frame_dms) { - case 25: maxBwBin = maxBwBin >> 2; move16(); +#ifdef CR9_C_ADD_1p25MS + case LC3PLUS_FRAME_DURATION_1p25MS: maxBwBin = maxBwBin >> 3; move16(); + { + bandsOffsetOne = bands_offset_with_one_max_1_25ms[fs_idx]; + move16(); + bandsOffsetTwo = bands_offset_with_two_max_1_25ms[fs_idx]; + move16(); + } + BREAK; +#endif + case LC3PLUS_FRAME_DURATION_2p5MS: maxBwBin = maxBwBin >> 2; move16(); { bandsOffsetOne = bands_offset_with_one_max_2_5ms[fs_idx]; move16(); @@ -49,7 +63,7 @@ void processPerBandEnergy_fx(Word32 *d2_fx, Word16 *d2_fx_exp, Word32 *d_fx, Wor move16(); } BREAK; - case 50: maxBwBin = maxBwBin >> 1; move16(); + case LC3PLUS_FRAME_DURATION_5MS: maxBwBin = maxBwBin >> 1; move16(); { bandsOffsetOne = bands_offset_with_one_max_5ms[fs_idx]; move16(); @@ -57,14 +71,14 @@ void processPerBandEnergy_fx(Word32 *d2_fx, Word16 *d2_fx_exp, Word32 *d_fx, Wor move16(); } BREAK; - case 75: + case LC3PLUS_FRAME_DURATION_7p5MS: maxBwBin = (maxBwBin >> 2) * 3; move16(); bandsOffsetOne = bands_offset_with_one_max_7_5ms[fs_idx]; move16(); bandsOffsetTwo = bands_offset_with_two_max_7_5ms[fs_idx]; move16(); BREAK; - default: /* 100 */ + case LC3PLUS_FRAME_DURATION_10MS: { bandsOffsetOne = bands_offset_with_one_max[fs_idx]; move16(); @@ -72,6 +86,7 @@ void processPerBandEnergy_fx(Word32 *d2_fx, Word16 *d2_fx_exp, Word32 *d_fx, Wor move16(); } BREAK; + case LC3PLUS_FRAME_DURATION_UNDEFINED: assert(0); } IF (sub(linear, 1) == 0) @@ -86,30 +101,39 @@ void processPerBandEnergy_fx(Word32 *d2_fx, Word16 *d2_fx_exp, Word32 *d_fx, Wor SWITCH (frame_dms) { - case 25: +#ifdef CR9_C_ADD_1p25MS + case LC3PLUS_FRAME_DURATION_1p25MS: + bandsOffsetOne = bands_offset_with_one_max_lin_1_25ms[fs_idx]; + move16(); + bandsOffsetTwo = bands_offset_with_two_max_lin_1_25ms[fs_idx]; + move16(); + BREAK; +#endif + case LC3PLUS_FRAME_DURATION_2p5MS: bandsOffsetOne = bands_offset_with_one_max_lin_2_5ms[fs_idx]; move16(); bandsOffsetTwo = bands_offset_with_two_max_lin_2_5ms[fs_idx]; move16(); BREAK; - case 50: + case LC3PLUS_FRAME_DURATION_5MS: bandsOffsetOne = bands_offset_with_one_max_lin_5ms[fs_idx]; move16(); bandsOffsetTwo = bands_offset_with_two_max_lin_5ms[fs_idx]; move16(); BREAK; - case 75: + case LC3PLUS_FRAME_DURATION_7p5MS: bandsOffsetOne = bands_offset_with_one_max_lin_7_5ms[fs_idx]; move16(); bandsOffsetTwo = bands_offset_with_two_max_lin_7_5ms[fs_idx]; move16(); BREAK; - case 100: + case LC3PLUS_FRAME_DURATION_10MS: bandsOffsetOne = bands_offset_with_one_max_lin[fs_idx]; move16(); bandsOffsetTwo = bands_offset_with_two_max_lin[fs_idx]; move16(); BREAK; + case LC3PLUS_FRAME_DURATION_UNDEFINED: assert(0); } } diff --git a/lib_lc3plus/plc_apply_fx.c b/lib_lc3plus/plc_apply_fx.c index d08957fda..ca07b5d81 100644 --- a/lib_lc3plus/plc_apply_fx.c +++ b/lib_lc3plus/plc_apply_fx.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,6 +7,8 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "defines.h" #include "constants.h" #include "functions.h" @@ -23,7 +25,7 @@ void processPLCapply_fx( Word16 x_fx[], Word16 ola_mem[], Word16 *ola_mem_exp, Word16 q_old_d_fx[], Word16 *q_old_fx_exp, Word32 q_d_fx[], Word16 *q_fx_exp, Word16 yLen, Word16 fs_idx, Word16 *damping, Word16 old_pitch_int, - Word16 old_pitch_fr, Word16 *ns_cum_alpha, Word16 *ns_seed, Word16 frame_dms, AplcSetup *plcAd, + Word16 old_pitch_fr, Word16 *ns_cum_alpha, Word16 *ns_seed, LC3PLUS_FrameDuration frame_dms, AplcSetup *plcAd, Word8 *scratchBuffer #ifdef ENABLE_HR_MODE , Word16 hrmode @@ -58,9 +60,9 @@ void processPLCapply_fx( UNUSED(rel_pitch_change); #endif - Word16 thresh_tdc_cnt; - Word16 thresh_ns_cnt; - Word16 thresh_tdc_ns_cnt; + Word16 thresh_tdc_cnt = 0; + Word16 thresh_ns_cnt = 0; + Word16 thresh_tdc_ns_cnt = 0; band_offsets = NULL; @@ -91,23 +93,31 @@ void processPLCapply_fx( { SWITCH(frame_dms) { - case 25: +#ifdef CR9_C_ADD_1p25MS + case LC3PLUS_FRAME_DURATION_1p25MS: + consecutiveLostThreshold = 32; + thresh_tdc_cnt = THRESH_025_DMS_TDC_CNT; + thresh_ns_cnt = THRESH_025_DMS_NS_CNT; + thresh_tdc_ns_cnt = THRESH_025_DMS_TDC_NS_CNT; + BREAK; +#endif + case LC3PLUS_FRAME_DURATION_2p5MS: consecutiveLostThreshold = 16; thresh_tdc_cnt = THRESH_025_DMS_TDC_CNT; thresh_ns_cnt = THRESH_025_DMS_NS_CNT; thresh_tdc_ns_cnt = THRESH_025_DMS_TDC_NS_CNT; break; - case 50: consecutiveLostThreshold = 8; + case LC3PLUS_FRAME_DURATION_5MS: consecutiveLostThreshold = 8; thresh_tdc_cnt = THRESH_050_DMS_TDC_CNT; thresh_ns_cnt = THRESH_050_DMS_NS_CNT; thresh_tdc_ns_cnt = THRESH_050_DMS_TDC_NS_CNT; break; - case 75: consecutiveLostThreshold = 6; + case LC3PLUS_FRAME_DURATION_7p5MS: consecutiveLostThreshold = 6; thresh_tdc_cnt = THRESH_075_DMS_TDC_CNT; thresh_ns_cnt = THRESH_075_DMS_NS_CNT; thresh_tdc_ns_cnt = THRESH_075_DMS_TDC_NS_CNT; break; - case 100: consecutiveLostThreshold = 4; + case LC3PLUS_FRAME_DURATION_10MS: consecutiveLostThreshold = 4; thresh_tdc_cnt = THRESH_100_DMS_TDC_CNT; thresh_ns_cnt = THRESH_100_DMS_NS_CNT; thresh_tdc_ns_cnt = THRESH_100_DMS_TDC_NS_CNT; @@ -135,8 +145,9 @@ void processPLCapply_fx( { plcAd->plc_fadeout_type = 0; } + #ifdef ENABLE_HR_MODE - IF (L_sub(rel_pitch_change,REL_PITCH_THRESH) > 0 && sub(hrmode,1) == 0 && (sub(frame_dms,50) == 0 || sub(frame_dms,25) == 0)){ + IF (L_sub(rel_pitch_change,REL_PITCH_THRESH) > 0 && sub(hrmode,1) == 0 && (sub(frame_dms, LC3PLUS_FRAME_DURATION_5MS) == 0 || sub(frame_dms, LC3PLUS_FRAME_DURATION_2p5MS) == 0)){ plcAd->plc_fadeout_type = 2;move16(); } ELSE #endif @@ -151,7 +162,7 @@ void processPLCapply_fx( SWITCH (*concealMethod) { case LC3_CON_TEC_PHASE_ECU: - ASSERT(frame_dms == 100); + ASSERT(frame_dms == LC3PLUS_FRAME_DURATION_10MS); /* call phaseEcu */ env_stab = 32767; move16(); /* 1.0=stable , 0.0=dynamic Q15*/ tmp_is_trans[0] = plcAd->PhECU_short_flag_prev; move16(); @@ -254,21 +265,32 @@ void processPLCapply_fx( n_bands = s_min(frame_length, MAX_BANDS_NUMBER_PLC); SWITCH (frame_dms) { - case 25: +#ifdef CR9_C_ADD_1p25MS + case LC3PLUS_FRAME_DURATION_1p25MS: +#ifdef FIX_PLC_CONFORM_ISSUES + band_offsets = bands_offset_lin_1_25ms[fs_idx]; move16(); +#endif + IF (sub(fs_idx, 4) == 0) + { + n_bands = 60; move16(); + } + BREAK; +#endif + case LC3PLUS_FRAME_DURATION_2p5MS: band_offsets = bands_offset_lin_2_5ms[fs_idx]; move16(); IF (sub(fs_idx, 4) == 0) { n_bands = 60; move16(); } BREAK; - case 50: + case LC3PLUS_FRAME_DURATION_5MS: band_offsets = bands_offset_lin_5ms[fs_idx]; move16(); IF (sub(fs_idx, 2) == 0) { n_bands = 40; move16(); } BREAK; - case 75: + case LC3PLUS_FRAME_DURATION_7p5MS: band_offsets = bands_offset_lin_7_5ms[fs_idx]; move16(); #ifdef ENABLE_HR_MODE IF (sub(fs_idx, 5) != 0) @@ -282,9 +304,10 @@ void processPLCapply_fx( } #endif BREAK; - case 100: + case LC3PLUS_FRAME_DURATION_10MS: band_offsets = bands_offset_lin[fs_idx]; move16(); BREAK; + case LC3PLUS_FRAME_DURATION_UNDEFINED: assert(0); } FOR (i = 0; i < yLen; i++) diff --git a/lib_lc3plus/plc_classify_fx.c b/lib_lc3plus/plc_classify_fx.c index 24775f6f5..6779ca925 100644 --- a/lib_lc3plus/plc_classify_fx.c +++ b/lib_lc3plus/plc_classify_fx.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,6 +7,8 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "defines.h" #include "functions.h" @@ -104,7 +106,7 @@ static Word16 spectral_centroid_fx_lc(Word16 old_scf_q[], const Word16 *band_off ); void processPLCclassify_fx(Word16 plcMeth, Word16 *concealMethod, Word16 *nbLostFramesInRow, Word16 bfi, - Word16 ltpf_mem_pitch_int, Word16 frame_length, Word16 frame_dms, Word16 fs_idx, Word16 yLen, + Word16 ltpf_mem_pitch_int, Word16 frame_length, LC3PLUS_FrameDuration frame_dms, Word16 fs_idx, Word16 yLen, Word16 q_old_d_fx[], const Word16 *band_offsets, Word16 bands_number, AplcSetup *plcAd, Word8 *scratchBuffer #ifdef ENABLE_HR_MODE , Word16 hrmode @@ -128,6 +130,40 @@ void processPLCclassify_fx(Word16 plcMeth, Word16 *concealMethod, Word16 *nbLost plcAd->norm_corrQ15_fx = 0; move16(); } +#ifdef CR13_C_RESET_CLASSIFIER_AFTER_BAD_FRAMES + Word16 resetClassifierThreshold = 0; + Word16 updateStatistics = 0; + + SWITCH (frame_dms) + { +#ifdef CR9_C_ADD_1p25MS + case LC3PLUS_FRAME_DURATION_1p25MS: + resetClassifierThreshold = 16; + BREAK; +#endif + case LC3PLUS_FRAME_DURATION_2p5MS: + resetClassifierThreshold = 8; + BREAK; + case LC3PLUS_FRAME_DURATION_5MS: + resetClassifierThreshold = 4; + BREAK; + case LC3PLUS_FRAME_DURATION_7p5MS: + resetClassifierThreshold = 3; + BREAK; + case LC3PLUS_FRAME_DURATION_10MS: + resetClassifierThreshold = 2; + BREAK; + case LC3PLUS_FRAME_DURATION_UNDEFINED: assert(0); + } + + IF (sub(plcAd->numberOfGoodFrames, resetClassifierThreshold) > 0) + { + updateStatistics = 1; + } ELSE { + updateStatistics = 0; + } +#endif + /* assert(bfi != 2 && "Error bfi flag value, state of fadeout cntr is affected by PartialConcealment here "); */ /* Save statistics for 24 kHz, 48 kHz and 96 kHz */ IF((sub(bfi, 1) == 0) || (((bfi >= 0) && (sub(bfi, 2) <= 0)) && ((sub(fs_idx, 2) == 0) || (sub(fs_idx, 4) == 0) || (sub(fs_idx, 5) == 0)))) /* note for PC bfi==2 is possible */ @@ -167,39 +203,75 @@ void processPLCclassify_fx(Word16 plcMeth, Word16 *concealMethod, Word16 *nbLost IF(class <= 0) { #ifdef ENABLE_HR_MODE - IF((frame_dms == 100) && (hrmode == 0)) + IF((frame_dms == LC3PLUS_FRAME_DURATION_10MS) && (hrmode == 0)) #else - IF(frame_dms == 100) + IF(frame_dms == LC3PLUS_FRAME_DURATION_10MS) #endif { *concealMethod = LC3_CON_TEC_PHASE_ECU; move16(); /* Phase ECU selected */ - array_insert_and_shift(plcAd->plc_longterm_advc_tdc, 0, plcAd->longterm_analysis_counter_max, &plcAd->overall_counter, &plcAd->longterm_counter_byte_position, &plcAd->longterm_counter_bit_position); - array_insert_and_shift(plcAd->plc_longterm_advc_ns, 0, plcAd->longterm_analysis_counter_max, NULL, &plcAd->longterm_counter_byte_position, &plcAd->longterm_counter_bit_position); + +#ifdef CR13_C_RESET_CLASSIFIER_AFTER_BAD_FRAMES + IF (sub(updateStatistics, 1) == 0) +#endif + { + array_insert_and_shift(plcAd->plc_longterm_advc_tdc, 0, plcAd->longterm_analysis_counter_max, &plcAd->overall_counter, &plcAd->longterm_counter_byte_position, &plcAd->longterm_counter_bit_position); + array_insert_and_shift(plcAd->plc_longterm_advc_ns, 0, plcAd->longterm_analysis_counter_max, NULL, &plcAd->longterm_counter_byte_position, &plcAd->longterm_counter_bit_position); + } } ELSE { - array_insert_and_shift(plcAd->plc_longterm_advc_tdc, 0, plcAd->longterm_analysis_counter_max, &plcAd->overall_counter, &plcAd->longterm_counter_byte_position, &plcAd->longterm_counter_bit_position); - array_insert_and_shift(plcAd->plc_longterm_advc_ns, 0, plcAd->longterm_analysis_counter_max, NULL, &plcAd->longterm_counter_byte_position, &plcAd->longterm_counter_bit_position); +#ifdef CR13_C_RESET_CLASSIFIER_AFTER_BAD_FRAMES + IF (sub(updateStatistics, 1) == 0) +#endif + { + array_insert_and_shift(plcAd->plc_longterm_advc_tdc, 0, plcAd->longterm_analysis_counter_max, &plcAd->overall_counter, &plcAd->longterm_counter_byte_position, &plcAd->longterm_counter_bit_position); + array_insert_and_shift(plcAd->plc_longterm_advc_ns, 0, plcAd->longterm_analysis_counter_max, NULL, &plcAd->longterm_counter_byte_position, &plcAd->longterm_counter_bit_position); + } } } ELSE { - array_insert_and_shift(plcAd->plc_longterm_advc_tdc, 1, plcAd->longterm_analysis_counter_max, &plcAd->overall_counter, &plcAd->longterm_counter_byte_position, &plcAd->longterm_counter_bit_position); - array_insert_and_shift(plcAd->plc_longterm_advc_ns, 0, plcAd->longterm_analysis_counter_max, NULL, &plcAd->longterm_counter_byte_position, &plcAd->longterm_counter_bit_position); +#ifdef CR13_C_RESET_CLASSIFIER_AFTER_BAD_FRAMES + IF (sub(updateStatistics, 1) == 0) +#endif + { + array_insert_and_shift(plcAd->plc_longterm_advc_tdc, 1, plcAd->longterm_analysis_counter_max, &plcAd->overall_counter, &plcAd->longterm_counter_byte_position, &plcAd->longterm_counter_bit_position); + array_insert_and_shift(plcAd->plc_longterm_advc_ns, 0, plcAd->longterm_analysis_counter_max, NULL, &plcAd->longterm_counter_byte_position, &plcAd->longterm_counter_bit_position); + } } } ELSE { *concealMethod = LC3_CON_TEC_NS_ADV; move16(); /* Noise Substitution */ - array_insert_and_shift(plcAd->plc_longterm_advc_tdc, 0, plcAd->longterm_analysis_counter_max, &plcAd->overall_counter, &plcAd->longterm_counter_byte_position, &plcAd->longterm_counter_bit_position); - array_insert_and_shift(plcAd->plc_longterm_advc_ns, 1, plcAd->longterm_analysis_counter_max, NULL, &plcAd->longterm_counter_byte_position, &plcAd->longterm_counter_bit_position); + +#ifdef CR13_C_RESET_CLASSIFIER_AFTER_BAD_FRAMES + IF (sub(updateStatistics, 1) == 0) +#endif + { + array_insert_and_shift(plcAd->plc_longterm_advc_tdc, 0, plcAd->longterm_analysis_counter_max, &plcAd->overall_counter, &plcAd->longterm_counter_byte_position, &plcAd->longterm_counter_bit_position); + array_insert_and_shift(plcAd->plc_longterm_advc_ns, 1, plcAd->longterm_analysis_counter_max, NULL, &plcAd->longterm_counter_byte_position, &plcAd->longterm_counter_bit_position); + } } - array_calculate(plcAd->plc_longterm_advc_tdc, plcAd->plc_longterm_advc_ns, plcAd->longterm_analysis_counter_max_bytebuffer, &plcAd->longterm_counter_plcTdc, &plcAd->longterm_counter_plcNsAdv, plcAd->longterm_analysis_counter_max); - update_bit_and_byte_positions(plcAd->longterm_analysis_counter_max_bytebuffer, &plcAd->longterm_counter_byte_position, &plcAd->longterm_counter_bit_position); +#ifdef CR13_C_RESET_CLASSIFIER_AFTER_BAD_FRAMES + IF (sub(updateStatistics, 1) == 0) +#endif + { + array_calculate(plcAd->plc_longterm_advc_tdc, plcAd->plc_longterm_advc_ns, plcAd->longterm_analysis_counter_max_bytebuffer, &plcAd->longterm_counter_plcTdc, &plcAd->longterm_counter_plcNsAdv, plcAd->longterm_analysis_counter_max); + update_bit_and_byte_positions(plcAd->longterm_analysis_counter_max_bytebuffer, &plcAd->longterm_counter_byte_position, &plcAd->longterm_counter_bit_position); + } } } } + +#ifdef CR13_C_RESET_CLASSIFIER_AFTER_BAD_FRAMES + IF (sub(bfi, 1) == 0) + { + plcAd->numberOfGoodFrames = 0; + } ELSE { + plcAd->numberOfGoodFrames = add(plcAd->numberOfGoodFrames, 1); + } +#endif Dyn_Mem_Deluxe_Out(); #ifdef WMOPS @@ -207,7 +279,6 @@ void processPLCclassify_fx(Word16 plcMeth, Word16 *concealMethod, Word16 *nbLost #endif } - Word16 spectral_centroid_fx_lc(Word16 old_scf_q[], const Word16 *band_offsets, Word16 bands_number, Word16 frame_length, Word16 fs_idx, Word8 *scratchBuffer #ifdef ENABLE_HR_MODE diff --git a/lib_lc3plus/plc_damping_scrambling_fx.c b/lib_lc3plus/plc_damping_scrambling_fx.c index ea56ead1d..89c079202 100644 --- a/lib_lc3plus/plc_damping_scrambling_fx.c +++ b/lib_lc3plus/plc_damping_scrambling_fx.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,13 +7,15 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "defines.h" #include "functions.h" void processPLCDampingScrambling_main_fx(Word16 bfi, Word16 concealMethod, Word16 ns_nbLostFramesInRow, Word16 *cum_fflcAtten, Word16 pc_nbLostFramesInRow, Word16 *ns_seed, Word16 *pc_seed, Word16 pitch_present_bfi1, Word16 pitch_present_bfi2, Word32 spec[], Word16 *q_fx_exp, Word16 *q_old_d_fx, - Word16 *q_old_fx_exp, Word16 L_spec, Word16 stabFac, Word16 frame_dms, + Word16 *q_old_fx_exp, Word16 L_spec, Word16 stabFac, LC3PLUS_FrameDuration frame_dms, Word16 *cum_fading_slow, Word16 *cum_fading_fast, Word16 spec_inv_idx , UWord8 plc_fadeout_type ) @@ -63,15 +65,15 @@ void processPLCDampingScrambling_main_fx(Word16 bfi, Word16 concealMethod, Word1 } void processPLCDampingScrambling_fx(Word32 spec[], Word16 L_spec, Word16 nbLostFramesInRow, Word16 stabFac, Word16 processDampScramb, - Word16 *cum_fflcAtten, Word16 pitch_present, Word16 frame_dms, Word16 *cum_fading_slow, + Word16 *cum_fflcAtten, Word16 pitch_present, LC3PLUS_FrameDuration frame_dms, Word16 *cum_fading_slow, Word16 *cum_fading_fast, Word16 *seed, Word16 spec_inv_idx , UWord8 plc_fadeout_type ) { Counter i; Word16 lossDuration_dms, slow, fast, tmp16; - Word16 plc_start_inFrames, plc_end_inFrames, plc_duration_inFrames, linFuncStartStop; - Word16 randThreshold, ad_threshFac, energThreshold, s, s2, s3, mean_energy16; + Word16 plc_start_inFrames = 0, plc_end_inFrames = 0, plc_duration_inFrames, linFuncStartStop; + Word16 randThreshold = 0, ad_threshFac, energThreshold, s, s2, s3, mean_energy16; Word32 frame_energy, mean_nrg, fac; Word16 fflcAtten, cum_fading_slow_local, cum_fading_fast_local; @@ -96,47 +98,76 @@ void processPLCDampingScrambling_fx(Word32 spec[], Word16 L_spec, Word16 nbLostF SWITCH (frame_dms) { - case 25: +#ifdef CR9_C_ADD_1p25MS + case LC3PLUS_FRAME_DURATION_1p25MS: +#ifdef FIX_PLC_CONFORM_ISSUES + for ( i = 0; i < 3; i++ ) +#else + for ( i = 0; i < 8; i++ ) +#endif + { + IF (sub(slow, 32767) < 0) + { + tmp16 = 0; + slow = Sqrt16(slow, &tmp16); move16(); + slow = shl(slow, tmp16); + } + } +#ifdef FIX_PLC_CONFORM_ISSUES + for ( i = 0; i < 3; i++ ) + { + IF( sub( fast, 32767 ) < 0 ) + { + tmp16 = 0; + fast = Sqrt16( fast, &tmp16 ); + move16(); + fast = shl( fast, tmp16 ); + } + } +#endif + BREAK; +#endif + case LC3PLUS_FRAME_DURATION_2p5MS: IF (sub(slow, 32767) < 0) { tmp16 = 0; - slow = Sqrt16_lc3plus(slow, &tmp16); move16(); + slow = Sqrt16(slow, &tmp16); move16(); slow = shl(slow, tmp16); } IF (sub(slow, 32767) < 0) { tmp16 = 0; - slow = Sqrt16_lc3plus(slow, &tmp16); move16(); + slow = Sqrt16(slow, &tmp16); move16(); slow = shl(slow, tmp16); } IF (sub(fast, 32767) < 0) { tmp16 = 0; - fast = Sqrt16_lc3plus(fast, &tmp16); move16(); + fast = Sqrt16(fast, &tmp16); move16(); fast = shl(fast, tmp16); } IF (sub(fast, 32767) < 0) { tmp16 = 0; - fast = Sqrt16_lc3plus(fast, &tmp16); move16(); + fast = Sqrt16(fast, &tmp16); move16(); fast = shl(fast, tmp16); } BREAK; - case 50: + case LC3PLUS_FRAME_DURATION_5MS: IF (sub(slow, 32767) < 0) { tmp16 = 0; - slow = Sqrt16_lc3plus(slow, &tmp16); move16(); + slow = Sqrt16(slow, &tmp16); move16(); slow = shl(slow, tmp16); } IF (sub(fast, 32767) < 0) { tmp16 = 0; - fast = Sqrt16_lc3plus(fast, &tmp16); move16(); + fast = Sqrt16(fast, &tmp16); move16(); fast = shl(fast, tmp16); } BREAK; - case 75: + case LC3PLUS_FRAME_DURATION_7p5MS: IF (sub(slow, 32767) < 0) { slow = mult(slow, mult(slow, slow)); @@ -144,13 +175,13 @@ void processPLCDampingScrambling_fx(Word32 spec[], Word16 L_spec, Word16 nbLostF IF (sub(slow, 32767) < 0) { tmp16 = 0; - slow = Sqrt16_lc3plus(slow, &tmp16); move16(); + slow = Sqrt16(slow, &tmp16); move16(); slow = shl(slow, tmp16); } IF (sub(slow, 32767) < 0) { tmp16 = 0; - slow = Sqrt16_lc3plus(slow, &tmp16); move16(); + slow = Sqrt16(slow, &tmp16); move16(); slow = shl(slow, tmp16); } IF (sub(fast, 32767) < 0) @@ -160,16 +191,18 @@ void processPLCDampingScrambling_fx(Word32 spec[], Word16 L_spec, Word16 nbLostF IF (sub(fast, 32767) < 0) { tmp16 = 0; - fast = Sqrt16_lc3plus(fast, &tmp16); move16(); + fast = Sqrt16(fast, &tmp16); move16(); fast = shl(fast, tmp16); } IF (sub(fast, 32767) < 0) { tmp16 = 0; - fast = Sqrt16_lc3plus(fast, &tmp16); move16(); + fast = Sqrt16(fast, &tmp16); move16(); fast = shl(fast, tmp16); } BREAK; + case LC3PLUS_FRAME_DURATION_10MS: BREAK; + case LC3PLUS_FRAME_DURATION_UNDEFINED: assert(0); } if (plc_fadeout_type == 0) @@ -187,17 +220,26 @@ void processPLCDampingScrambling_fx(Word32 spec[], Word16 L_spec, Word16 nbLostF SWITCH (frame_dms) { - case 25: +#ifdef CR9_C_ADD_1p25MS + case LC3PLUS_FRAME_DURATION_1p25MS: + lost_frame_thr1 = 32; + lost_frame_thr2 = 64; + BREAK; +#endif + case LC3PLUS_FRAME_DURATION_2p5MS: lost_frame_thr1 = 16; lost_frame_thr2 = 32; BREAK; - case 50: + case LC3PLUS_FRAME_DURATION_5MS: lost_frame_thr1 = 8; lost_frame_thr2 = 16; BREAK; - case 75: + case LC3PLUS_FRAME_DURATION_7p5MS: lost_frame_thr1 = 6; lost_frame_thr2 = 11; + BREAK; + case LC3PLUS_FRAME_DURATION_10MS: BREAK; + case LC3PLUS_FRAME_DURATION_UNDEFINED: assert(0); } IF (sub(nbLostFramesInRow, lost_frame_thr1) < 0) { @@ -222,7 +264,20 @@ void processPLCDampingScrambling_fx(Word32 spec[], Word16 L_spec, Word16 nbLostF IF (spec_inv_idx == 0) { - lossDuration_dms = DEPR_i_mult(nbLostFramesInRow, frame_dms); + int frame_dms_val = 0; + SWITCH (frame_dms) /* 1 / frame_dms in Q15 */ + { +#ifdef CR9_C_ADD_1p25MS + case LC3PLUS_FRAME_DURATION_1p25MS: frame_dms_val = 125; BREAK; +#endif + case LC3PLUS_FRAME_DURATION_2p5MS: frame_dms_val = 250; BREAK; + case LC3PLUS_FRAME_DURATION_5MS: frame_dms_val = 500; BREAK; + case LC3PLUS_FRAME_DURATION_7p5MS: frame_dms_val = 750; BREAK; + case LC3PLUS_FRAME_DURATION_10MS: frame_dms_val = 1000; BREAK; + case LC3PLUS_FRAME_DURATION_UNDEFINED: assert(0); + } + + lossDuration_dms = i_mult(nbLostFramesInRow, frame_dms_val/10); IF (sub(lossDuration_dms, PLC_FADEOUT_IN_MS*10) > 0) { *cum_fflcAtten = 0; move16(); @@ -232,10 +287,14 @@ void processPLCDampingScrambling_fx(Word32 spec[], Word16 L_spec, Word16 nbLostF { SWITCH (frame_dms) { - case 25: fflcAtten = PLC34_ATTEN_FAC_025_FX; BREAK; - case 50: fflcAtten = PLC34_ATTEN_FAC_050_FX; BREAK; - case 75: fflcAtten = PLC34_ATTEN_FAC_075_FX; BREAK; - case 100: fflcAtten = PLC34_ATTEN_FAC_100_FX; BREAK; +#ifdef CR9_C_ADD_1p25MS + case LC3PLUS_FRAME_DURATION_1p25MS: fflcAtten = PLC34_ATTEN_FAC_125_FX; BREAK; +#endif + case LC3PLUS_FRAME_DURATION_2p5MS: fflcAtten = PLC34_ATTEN_FAC_025_FX; BREAK; + case LC3PLUS_FRAME_DURATION_5MS: fflcAtten = PLC34_ATTEN_FAC_050_FX; BREAK; + case LC3PLUS_FRAME_DURATION_7p5MS: fflcAtten = PLC34_ATTEN_FAC_075_FX; BREAK; + case LC3PLUS_FRAME_DURATION_10MS: fflcAtten = PLC34_ATTEN_FAC_100_FX; BREAK; + case LC3PLUS_FRAME_DURATION_UNDEFINED: assert(0); } } IF ( sub(fflcAtten, 32767) < 0 ) @@ -251,21 +310,29 @@ void processPLCDampingScrambling_fx(Word32 spec[], Word16 L_spec, Word16 nbLostF plc_end_inFrames; decreasing linearly in between */ SWITCH (frame_dms) { - case 25: +#ifdef CR9_C_ADD_1p25MS + case LC3PLUS_FRAME_DURATION_1p25MS: + plc_start_inFrames = (100 * PLC4_TRANSIT_START_IN_MS) / 125; move16(); + plc_end_inFrames = (100 * PLC4_TRANSIT_END_IN_MS) / 125; move16(); + BREAK; +#endif + case LC3PLUS_FRAME_DURATION_2p5MS: plc_start_inFrames = (10*PLC4_TRANSIT_START_IN_MS) / 25; move16(); plc_end_inFrames = (10*PLC4_TRANSIT_END_IN_MS) / 25; move16(); BREAK; - case 50: + case LC3PLUS_FRAME_DURATION_5MS: plc_start_inFrames = (10*PLC4_TRANSIT_START_IN_MS) / 50; move16(); plc_end_inFrames = (10*PLC4_TRANSIT_END_IN_MS) / 50; move16(); BREAK; - case 75: + case LC3PLUS_FRAME_DURATION_7p5MS: plc_start_inFrames = (10*PLC4_TRANSIT_START_IN_MS) / 75; move16(); plc_end_inFrames = (10*PLC4_TRANSIT_END_IN_MS) / 75; move16(); BREAK; - default: + case LC3PLUS_FRAME_DURATION_10MS: plc_start_inFrames = (10*PLC4_TRANSIT_START_IN_MS) / 100; move16(); plc_end_inFrames = (10*PLC4_TRANSIT_END_IN_MS) / 100; move16(); + BREAK; + case LC3PLUS_FRAME_DURATION_UNDEFINED: assert(0); } if (pitch_present == 0) @@ -320,21 +387,21 @@ void processPLCDampingScrambling_fx(Word32 spec[], Word16 L_spec, Word16 nbLostF tmp16 = mult(18022 /* 10 - 1.2 */, linFuncStartStop); ad_threshFac = add(shr(tmp16, 1), 1228 /* 1.2 >> 1 */); /* exp = 5 */ - s = getScaleFactor32_lc3plus(&spec[spec_inv_idx], sub(L_spec, spec_inv_idx)); + s = getScaleFactor32(&spec[spec_inv_idx], sub(L_spec, spec_inv_idx)); frame_energy = 0; move32(); FOR (i = spec_inv_idx; i < L_spec; i++) { tmp16 = extract_h(L_shl_sat(spec[i], sub(s, 4))); frame_energy = L_mac0(frame_energy, tmp16, tmp16); /* exp = -(2*(s-16) - 8) */ } - mean_energy16 = BASOP_Util_Divide3216_Scale_lc3plus(frame_energy, sub(L_spec, spec_inv_idx), &s2); /* exp = -(2*(s-16) - 8) + 16 - (15-s2) */ + mean_energy16 = BASOP_Util_Divide3216_Scale(frame_energy, sub(L_spec, spec_inv_idx), &s2); /* exp = -(2*(s-16) - 8) + 16 - (15-s2) */ energThreshold = mult(ad_threshFac, mean_energy16); /* exp = -(2*(s-16) - 8) + 16 - (15-s2) + 5 */ s3 = add(sub(29, shl(sub(s, 16), 1)), s2); IF (sub(energThreshold, 32767) < 0) { - energThreshold = Sqrt16_lc3plus(energThreshold, &s3); + energThreshold = Sqrt16(energThreshold, &s3); } s3 = sub(s3, 15); @@ -345,7 +412,7 @@ void processPLCDampingScrambling_fx(Word32 spec[], Word16 L_spec, Word16 nbLostF FOR (i = spec_inv_idx; i < L_spec; i++) { - if ( ( plc_fadeout_type != 0 ) || (L_sub(L_abs(spec[i]), mean_nrg) < 0) ) + if ( ( plc_fadeout_type != 0 ) || (L_sub(L_abs_sat(spec[i]), mean_nrg) < 0) ) { spec[i] = Mpy_32_16_lc3plus(spec[i], cum_fading_slow_local); } diff --git a/lib_lc3plus/plc_lpc_scaling_fx.c b/lib_lc3plus/plc_lpc_scaling_fx.c index 15d753342..945f583a1 100644 --- a/lib_lc3plus/plc_lpc_scaling_fx.c +++ b/lib_lc3plus/plc_lpc_scaling_fx.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,6 +7,8 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "defines.h" #include "functions.h" @@ -22,7 +24,7 @@ void processPLCLpcScaling_fx(Word32 tdc_A_32[], Word16 tdc_A_16[], Word16 m) })); #endif - s = getScaleFactor32_lc3plus(tdc_A_32, m); + s = getScaleFactor32(tdc_A_32, m); FOR (i = 0; i < m; i++) { tdc_A_16[i] = round_fx_sat(L_shl_sat(tdc_A_32[i], s)); move16(); diff --git a/lib_lc3plus/plc_main_fx.c b/lib_lc3plus/plc_main_fx.c index 87cfb59d4..9f12d15a0 100644 --- a/lib_lc3plus/plc_main_fx.c +++ b/lib_lc3plus/plc_main_fx.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,6 +7,8 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "defines.h" #include "functions.h" @@ -21,7 +23,7 @@ void processPLCmain_fx(Word16 plcMeth, Word16 *concealMethod, Word16 *nbLostFram Word16 *ola_mem_exp, Word16 q_old_d_fx[], Word16 *q_old_fx_exp, Word32 q_d_fx[], Word16 *q_fx_exp, Word16 yLen, Word16 fs_idx, const Word16 *band_offsets, Word16 bands_number, Word16 *damping, Word16 old_pitch_int, Word16 old_pitch_fr, Word16 *ns_cum_alpha, Word16 *ns_seed, - AplcSetup *plcAd, Word16 frame_dms, Word8 *scratchBuffer, Word16 *pc_nbLostFramesInRow + AplcSetup *plcAd, LC3PLUS_FrameDuration frame_dms, Word8 *scratchBuffer, Word16 *pc_nbLostFramesInRow #ifdef ENABLE_HR_MODE , Word16 hrmode #endif diff --git a/lib_lc3plus/plc_noise_substitution_fx.c b/lib_lc3plus/plc_noise_substitution_fx.c index 0b227edae..5bf71258a 100644 --- a/lib_lc3plus/plc_noise_substitution_fx.c +++ b/lib_lc3plus/plc_noise_substitution_fx.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,6 +7,8 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "defines.h" #include "functions.h" diff --git a/lib_lc3plus/plc_phecu_f0_refine_first_fx.c b/lib_lc3plus/plc_phecu_f0_refine_first_fx.c index 5a37b4149..4c4f26b00 100644 --- a/lib_lc3plus/plc_phecu_f0_refine_first_fx.c +++ b/lib_lc3plus/plc_phecu_f0_refine_first_fx.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,6 +7,8 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "defines.h" #include "functions.h" diff --git a/lib_lc3plus/plc_phecu_fec_hq_fx.c b/lib_lc3plus/plc_phecu_fec_hq_fx.c index 5686920de..37711a6bc 100644 --- a/lib_lc3plus/plc_phecu_fec_hq_fx.c +++ b/lib_lc3plus/plc_phecu_fec_hq_fx.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,6 +7,8 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "defines.h" #include "functions.h" #include "math.h" /*dbg*/ @@ -558,7 +560,7 @@ void trans_burst_ana_fx( /* beta[k] = beta_pre[k]* *beta_mute;*/ /* (1.0-alpha.^2), in exp 1 due to L_mult0; */ - L_acc = L_sub((INT32_MAX >> 1) + 1, L_mult0(alpha[k], alpha[k])); + L_acc = L_sub((INT_MAX >> 1) + 1, L_mult0(alpha[k], alpha[k])); { /* use lower complex(WMOPS/ROM) 2nd-order sqrt approximation */ @@ -862,7 +864,7 @@ static Word16 imax_fx( /* o: The location, relative to the Lprot = LprotSzPtr[bwidth_fx]; move16(); - hamm_len2 = DEPR_i_mult(3, mult(output_frame, (Word16)(3277) /* divBy10 + floor */)); /* 3 ms */ + hamm_len2 = i_mult(3, mult(output_frame, (Word16)(3277) /* divBy10 + floor */)); /* 3 ms */ fft_scale = PhEcuFftScale[bwidth_fx]; move16(); /* 32,16,8 kHz all have fft scale 0, 24 has 8, 48 has 4 */ Lprot2 = shr_pos(Lprot, 1); @@ -1873,7 +1875,6 @@ static Word16 imax_fx( /* o: The location, relative to the Word16 prevsynth_man_upshift; Word16 Q_prevsynthMinus1; Word8 *buffer; - // ToDO Word32 L_Xavg[MAX_LGW]; })); #endif @@ -2922,7 +2923,7 @@ static Word16 imax_fx( /* o: The location, relative to the /* log2(Upshifted Word32) */ /* maximize precision in BASOP Log2 function */ - L_XavgL2_fx[i] = BASOP_Util_Log2_lc3plus(L_tmp); /* L_input 1.0 or lower --> output always negative */ + L_XavgL2_fx[i] = BASOP_Util_Log2(L_tmp); /* L_input 1.0 or lower --> output always negative */ /* add 31.0 to store as fractional bits of an upscaled positive Word32 integer input ) */ L_XavgL2_fx[i] = L_add(31L << 25, L_XavgL2_fx[i]); /* only diffs added so 31.0 is cancelled out later , in total only values between +/- 2^6 = [-64 ... -64[ are possible */ } /* band i for L_Xavg calc*/ diff --git a/lib_lc3plus/plc_phecu_lf_peak_analysis_fx.c b/lib_lc3plus/plc_phecu_lf_peak_analysis_fx.c index b32c61b66..cdd082c31 100644 --- a/lib_lc3plus/plc_phecu_lf_peak_analysis_fx.c +++ b/lib_lc3plus/plc_phecu_lf_peak_analysis_fx.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,6 +7,8 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "defines.h" #include "functions.h" diff --git a/lib_lc3plus/plc_phecu_peak_locator_fx.c b/lib_lc3plus/plc_phecu_peak_locator_fx.c index ddb348666..e1342a486 100644 --- a/lib_lc3plus/plc_phecu_peak_locator_fx.c +++ b/lib_lc3plus/plc_phecu_peak_locator_fx.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,6 +7,8 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "defines.h" #include "functions.h" diff --git a/lib_lc3plus/plc_phecu_setf0hz_fx.c b/lib_lc3plus/plc_phecu_setf0hz_fx.c index 6b2322f00..b21488af4 100644 --- a/lib_lc3plus/plc_phecu_setf0hz_fx.c +++ b/lib_lc3plus/plc_phecu_setf0hz_fx.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,6 +7,8 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "defines.h" #include "functions.h" diff --git a/lib_lc3plus/plc_phecu_tools_fx.c b/lib_lc3plus/plc_phecu_tools_fx.c index c37d6ba32..c9eb49e02 100644 --- a/lib_lc3plus/plc_phecu_tools_fx.c +++ b/lib_lc3plus/plc_phecu_tools_fx.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,6 +7,8 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "defines.h" #include "functions.h" @@ -171,7 +173,7 @@ Word32 winEnCalc( /* o: output summed energy Ltot */ push_wmops("PhECU::winEnCalc"); #endif - L_tot = INT32_MAX; move32(); /*acc is on negative side , but as all accumulation is positive, we make use of one extra bit */ + L_tot = INT_MAX; move32(); /*acc is on negative side , but as all accumulation is positive, we make use of one extra bit */ pX = x; pW = win; @@ -210,7 +212,7 @@ Word32 winEnCalc( /* o: output summed energy Ltot */ /* handle wrap on zero point */ IF( L_tot >= 0 ) { /* L_tot positive --> less than 32 bits needed, */ - L_tot = L_add(L_tot,(INT32_MIN+1)); + L_tot = L_add(L_tot,(INT_MIN+1)); if( L_tot == 0 ) { *exp = LTOT_MIN_EXP; /* WC is actually (-(15+4)*2 + 1 +1 -31) */ ; move16(); @@ -221,12 +223,12 @@ Word32 winEnCalc( /* o: output summed energy Ltot */ { /* L_tot negative --> more than 31 bits needed for sum , scale 32 bit sum within 31 bits and adjust exp */ L_tot = L_shr_pos(L_add(L_tot,1),1); /* rnd by adding 1, then use 50% contribution from negative side */ - L_tot = L_add(L_tot, INT32_MIN>>1); /* add 50% contribution from positive side */ + L_tot = L_add(L_tot, INT_MIN>>1); /* add 50% contribution from positive side */ *exp = add(*exp, 1); move16(); } - L_tot = L_max( -(INT32_MAX), L_tot); /* guard against max accumulation on the negative side , should only occur for rectangle windows */ + L_tot = L_max( -(INT_MAX), L_tot); /* guard against max accumulation on the negative side , should only occur for rectangle windows */ L_tot = L_negate(L_tot); /* no saturation here */ /* activate when xfp_exp is not used any longer */ diff --git a/lib_lc3plus/plc_tdac_fx.c b/lib_lc3plus/plc_tdac_fx.c index e419abfe6..43b85be6d 100644 --- a/lib_lc3plus/plc_tdac_fx.c +++ b/lib_lc3plus/plc_tdac_fx.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,6 +7,8 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "defines.h" #include "functions.h" @@ -118,6 +120,12 @@ void processTdac_fx(Word16 *ola_mem, Word16 *ola_mem_exp, const Word16 *synth_in { INV_NORM_E = add(INV_NORM_E, 2); } +#ifdef FIX_PLC_CONFORM_ISSUES + if (sub(frame_len, 30) == 0) + { + INV_NORM_E = add(INV_NORM_E, 2); + } +#endif } /* Scale input */ diff --git a/lib_lc3plus/plc_tdc_inverse_odft_fx.c b/lib_lc3plus/plc_tdc_inverse_odft_fx.c index 753268489..3eb4cdc6a 100644 --- a/lib_lc3plus/plc_tdc_inverse_odft_fx.c +++ b/lib_lc3plus/plc_tdc_inverse_odft_fx.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,6 +7,8 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "defines.h" #include "functions.h" @@ -39,12 +41,20 @@ void processInverseODFT_fx(Word32 *r_fx, Word16 *r_fx_exp, Word32 *d2_fx, Word16 buffer_BASOP_rfftN = scratchAlign(x, sizeof(*x) * (MAX_BANDS_NUMBER_PLC + MAX_BANDS_NUMBER_PLC/2)); /* Size = 480 bytes */ ASSERT(lpc_order <= M); +#ifdef FIX_PLC_CONFORM_ISSUES + ASSERT(n_bands == 80 || n_bands == 60 || n_bands == 40 || n_bands == 30 || n_bands == 20); +#else ASSERT(n_bands == 80 || n_bands == 60 || n_bands == 40 || n_bands == 20); +#endif n_bands2 = shr_pos_pos(n_bands, 1); test(); - IF (sub(n_bands, 20) == 0 || sub(n_bands, 60) == 0) +#ifdef FIX_PLC_CONFORM_ISSUES + IF( sub(n_bands, 20) == 0 || sub( n_bands, 30) == 0 || sub( n_bands, 60) == 0 ) +#else + IF( sub(n_bands, 20) == 0 || sub( n_bands, 60) == 0 ) +#endif { /* sort input samples */ FOR (i = 0; i < n_bands2; i++) @@ -54,7 +64,7 @@ void processInverseODFT_fx(Word32 *r_fx, Word16 *r_fx_exp, Word32 *d2_fx, Word16 x[n_bands + 2*i] = d2_fx[n_bands - 1 - 2 * i]; move32(); x[n_bands + 2*i + 1] = 0; move32(); } - BASOP_cfft_lc3plus(&x[0], &x[1], n_bands, 2, &d2_fx_exp, (Word32*)buffer_BASOP_rfftN); + BASOP_cfft(&x[0], &x[1], n_bands, 2, &d2_fx_exp, (Word32*)buffer_BASOP_rfftN); } ELSE { @@ -75,6 +85,13 @@ void processInverseODFT_fx(Word32 *r_fx, Word16 *r_fx_exp, Word32 *d2_fx, Word16 inv_odft_twiddle_re = inv_odft_twiddle_20_re; inv_odft_twiddle_im = inv_odft_twiddle_20_im; } +#ifdef FIX_PLC_CONFORM_ISSUES + ELSE IF(sub(n_bands, 30) == 0 ) + { + inv_odft_twiddle_re = inv_odft_twiddle_30_re; + inv_odft_twiddle_im = inv_odft_twiddle_30_im; + } +#endif ELSE IF (sub(n_bands, 40) == 0) { inv_odft_twiddle_re = inv_odft_twiddle_40_re; diff --git a/lib_lc3plus/plc_tdc_lagwin_fx.c b/lib_lc3plus/plc_tdc_lagwin_fx.c index 4fb8cd6c5..2de348eb2 100644 --- a/lib_lc3plus/plc_tdc_lagwin_fx.c +++ b/lib_lc3plus/plc_tdc_lagwin_fx.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,6 +7,8 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "defines.h" #include "functions.h" diff --git a/lib_lc3plus/plc_tdc_main_fx.c b/lib_lc3plus/plc_tdc_main_fx.c index 4867342cd..56e62f21b 100644 --- a/lib_lc3plus/plc_tdc_main_fx.c +++ b/lib_lc3plus/plc_tdc_main_fx.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,6 +7,8 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "defines.h" #include "functions.h" @@ -17,7 +19,7 @@ static Word32 TDC_L_Dot_product(const Word16 x[], const Word16 y[], const Word16 static void TDC_highPassFiltering_fx(const Word16 L_buffer, Word16 exc2[], const Word16 l_fir_fer, const Word16 *hp_filt); static Word32 TDC_calcGainp(Word16 x[], Word16 y[], Word16 lg); -static void TDC_calcGainc(Word16 *exc, Word16 Q_exc, Word16 old_fpitch, Word16 lg, Word16 frame_dms, Word16 lp_gainp, Word32 *lp_gainc); +static void TDC_calcGainc(Word16 *exc, Word16 Q_exc, Word16 old_fpitch, Word16 lg, LC3PLUS_FrameDuration frame_dms, Word16 lp_gainp, Word32 *lp_gainc); static void TDC_random_fx(Word16 *seed, Word16 lg, Word16 *y); static Word16 TDC_preemph(Word16 *x, const Word16 fac, const Word16 lg); static void TDC_LPC_residu_fx(const Word16 *a, Word16 *x, Word16 *y, Word16 lg, Word16 m); @@ -25,7 +27,23 @@ static void TDC_deemph_fx(const Word16 *x, Word16 *y, const Word16 fac, const static void TDC_LPC_synthesis_fx(const Word16 sh, const Word16 a[], const Word16 x[], Word16 y[], const Word16 lg, const Word16 m); static void TDC_normalize_energy_fx(Word16 *gain, Word16 *gain_exp, const Word16 *x, const Word16 lg); - + +#ifdef FIX_TDC_BURST_ERROR +const Word16 beforeNextIncArray_fx[5][8] = { + { 0, 0, 0, 0, 0, 0, 0, 1 }, + { 0, 0, 0, 1, 0, 0, 0, 1 }, + { 0, 1, 0, 1, 0, 1, 0, 1 }, + { 0, 1, 1, 1, 0, 1, 1, 1 }, + { 1, 1, 1, 1, 1, 1, 1, 1 } +}; +const Word16 nextIncArray_fx[5][8] = { + { 1, 0, 0, 0, 0, 0, 0, 0 }, + { 1, 0, 0, 0, 1, 0, 0, 0 }, + { 1, 0, 1, 0, 1, 0, 1, 0 }, + { 1, 0, 1, 1, 1, 0, 1, 1 }, + { 1, 1, 1, 1, 1, 1, 1, 1 } +}; +#else const Word16 beforeNextIncArray_fx[4][4] = {{0,0,0,1}, {0,1,0,1}, {0,1,1,1}, @@ -34,7 +52,9 @@ const Word16 nextIncArray_fx[4][4] = {{1,0,0,0}, {1,0,1,0}, {1,0,1,1}, {1,1,1,1}}; -static Word16 type_2_alpha_long(Word16 nbLostFramesInRow, Word16 frame_dms); +#endif + +static Word16 type_2_alpha_long(Word16 nbLostFramesInRow, LC3PLUS_FrameDuration frame_dms); static Word16 powWord16rest(Word16 base, Word16 exp, Word16 rest); /*****************************************************************************/ @@ -70,14 +90,14 @@ static Word16 powWord16rest(Word16 base, Word16 exp, Word16 rest); */ void processTimeDomainConcealment_Apply_fx(const Word16 pitch_int, const Word16 preemphFac_fx, const Word16 *A_fx, const Word16 lpc_order, const Word16 *pcmbufHist_fx, const Word16 frame_length, - const Word16 frame_dms, const Word16 fs_idx, const Word16 nbLostFramesInRow, + const LC3PLUS_FrameDuration frame_dms, const Word16 fs_idx, const Word16 nbLostFramesInRow, const Word16 overlap, const Word16 stabFac_fx, Word16 *fract, Word16 *seed_fx, Word32 *gain_c_fx, Word16 *synth_fx, Word16 *Q_syn, Word16 *alpha, Word16 max_len_pcm_plc, Word16 harmonicBuf_fx[MAX_PITCH], Word16 synthHist_fx[M], Word16 *const harmonicBuf_Q, Word8 *scratchBuffer , UWord8 plc_fadeout_type - , Word16 * alpha_type_2_table + ,Word16 * alpha_type_2_table ) { Counter i; @@ -126,14 +146,54 @@ void processTimeDomainConcealment_Apply_fx(const Word16 pitch_int, const Word16 /* len of output signal */ len = add(frame_length, overlap); + + int frame_dms_val = 0; + SWITCH (frame_dms) + { +#ifdef FIX_TDC_BURST_ERROR +#ifdef CR9_C_ADD_1p25MS + case LC3PLUS_FRAME_DURATION_1p25MS: frame_dms_val = 1; break; +#endif + case LC3PLUS_FRAME_DURATION_2p5MS: frame_dms_val = 2; break; + case LC3PLUS_FRAME_DURATION_5MS: frame_dms_val = 4; break; + case LC3PLUS_FRAME_DURATION_7p5MS: frame_dms_val = 6; break; + case LC3PLUS_FRAME_DURATION_10MS: frame_dms_val = 8; break; + case LC3PLUS_FRAME_DURATION_UNDEFINED: assert(0); + default: assert( 0 ); +#else +#ifdef CR9_C_ADD_1p25MS + case LC3PLUS_FRAME_DURATION_1p25MS: frame_dms_val = 125; break; +#endif + case LC3PLUS_FRAME_DURATION_2p5MS: frame_dms_val = 250; break; + case LC3PLUS_FRAME_DURATION_5MS: frame_dms_val = 500; break; + case LC3PLUS_FRAME_DURATION_7p5MS: frame_dms_val = 750; break; + case LC3PLUS_FRAME_DURATION_10MS: frame_dms_val = 1000; break; + case LC3PLUS_FRAME_DURATION_UNDEFINED: assert(0); +#endif + } +#ifdef FIX_TDC_BURST_ERROR + nbLostFramesInRow_mod = sub( nbLostFramesInRow, 1 ) & 0x0007; + nbLostCmpt_loc = L_add(L_shr(L_mult0(frame_dms_val, sub(nbLostFramesInRow, 1)), 3), 1); + if (sub(frame_dms_val, 1) == 0) + { + frame_dms_idx = 0; + } + else + { + frame_dms_idx = shr(frame_dms, 1); + } + beforeNextInc = beforeNextIncArray_fx[frame_dms_idx][nbLostFramesInRow_mod]; + nextInc = nextIncArray_fx[frame_dms_idx][nbLostFramesInRow_mod]; +#else nbLostFramesInRow_mod = sub(nbLostFramesInRow, 1) & 0x0003; - frame_dms_idx = mult(frame_dms, 0x051F); + frame_dms_idx = mult(frame_dms_val/10, 0x051F); nbLostCmpt_loc = add(shr(L_mult0(frame_dms_idx, sub(nbLostFramesInRow, 1)), 2), 1); frame_dms_idx = sub(frame_dms_idx, 1); beforeNextInc = beforeNextIncArray_fx[frame_dms_idx][nbLostFramesInRow_mod]; move16(); nextInc = nextIncArray_fx [frame_dms_idx][nbLostFramesInRow_mod]; move16(); +#endif IF (sub(nbLostCmpt_loc, plc_fadeout_len / 10) > 0) { @@ -281,7 +341,7 @@ void processTimeDomainConcealment_Apply_fx(const Word16 pitch_int, const Word16 ELSE { exp_scale = 0; - *alpha = Sqrt16_lc3plus(gain_p_fx, &exp_scale); move16(); + *alpha = Sqrt16(gain_p_fx, &exp_scale); move16(); *alpha = shl(*alpha, exp_scale); } } @@ -327,10 +387,14 @@ void processTimeDomainConcealment_Apply_fx(const Word16 pitch_int, const Word16 { SWITCH (frame_dms) { - case 25: *alpha = mult(*alpha, PLC34_ATTEN_FAC_025_FX); BREAK; - case 50: *alpha = mult(*alpha, PLC34_ATTEN_FAC_025_FX); BREAK; - case 75: *alpha = mult(*alpha, PLC34_ATTEN_FAC_075_FX); BREAK; - case 100: *alpha = mult(*alpha, PLC34_ATTEN_FAC_100_FX); BREAK; +#ifdef CR9_C_ADD_1p25MS + case LC3PLUS_FRAME_DURATION_1p25MS: *alpha = mult(*alpha, PLC34_ATTEN_FAC_125_FX); BREAK; +#endif + case LC3PLUS_FRAME_DURATION_2p5MS: *alpha = mult(*alpha, PLC34_ATTEN_FAC_025_FX); BREAK; + case LC3PLUS_FRAME_DURATION_5MS: *alpha = mult(*alpha, PLC34_ATTEN_FAC_025_FX); BREAK; + case LC3PLUS_FRAME_DURATION_7p5MS: *alpha = mult(*alpha, PLC34_ATTEN_FAC_075_FX); BREAK; + case LC3PLUS_FRAME_DURATION_10MS: *alpha = mult(*alpha, PLC34_ATTEN_FAC_100_FX); BREAK; + case LC3PLUS_FRAME_DURATION_UNDEFINED: assert(0); } } if (sub(nbLostCmpt_loc, 5) > 0) @@ -423,9 +487,9 @@ void processTimeDomainConcealment_Apply_fx(const Word16 pitch_int, const Word16 /* update steps */ if (frame_length == 720) { - ilen = BASOP_Util_Divide1616_Scale_lc3plus((Word16)1, 960, &ilen_exp); + ilen = BASOP_Util_Divide1616_Scale((Word16)1, 960, &ilen_exp); } else { - ilen = BASOP_Util_Divide1616_Scale_lc3plus((Word16)1, frame_length, &ilen_exp); + ilen = BASOP_Util_Divide1616_Scale((Word16)1, frame_length, &ilen_exp); } step_fx = round_fx(L_shl(L_mult(sub(gain_h_fx, *alpha), ilen), ilen_exp)); @@ -500,6 +564,15 @@ void processTimeDomainConcealment_Apply_fx(const Word16 pitch_int, const Word16 mem_deemph = shl_sat(pcmbufHist_fx[max_len_pcm_plc - 1], *Q_syn); TDC_deemph_fx(synth_tmp_fx, synth_fx, preemphFac_fx, len, mem_deemph); +#ifdef CR12_B_STOP_DC_RINGING_NO + if ((gain_h_fx == 0) && (g_fx == 0)) + { + for (i = 0; i < len; i++) + { + synth_fx[i] = 0; + } + } +#endif /*----------------------------------------------------------* * Fade to zero * *----------------------------------------------------------*/ @@ -666,7 +739,7 @@ static void TDC_highPassFiltering_fx(const Word16 L_buffer, Word16 exc2[], const * Returns: * void */ -static void TDC_calcGainc(Word16 *exc, Word16 Q_exc, Word16 old_fpitch, Word16 lg, Word16 frame_dms, Word16 lp_gainp, Word32 *lp_gainc) +static void TDC_calcGainc(Word16 *exc, Word16 Q_exc, Word16 old_fpitch, Word16 lg, LC3PLUS_FrameDuration frame_dms, Word16 lp_gainp, Word32 *lp_gainc) { Dyn_Mem_Deluxe_In( Word16 tmp16, tmp_e, tmp2_e; @@ -683,7 +756,7 @@ static void TDC_calcGainc(Word16 *exc, Word16 Q_exc, Word16 old_fpitch, Word16 l L_tmp = L_mac0_sat(L_tmp, tmp16, tmp16); /*Q3*/ } - IF (sub(frame_dms, 100) < 0) + IF (sub(frame_dms, LC3PLUS_FRAME_DURATION_10MS) < 0) { L_tmp_max = L_deposit_l(0); FOR (i = 0; i < lg; i++) @@ -696,12 +769,12 @@ static void TDC_calcGainc(Word16 *exc, Word16 Q_exc, Word16 old_fpitch, Word16 l tmp_e = norm_l(L_tmp); L_tmp = L_shl(L_tmp, tmp_e); tmp_e = sub(sub(31, shl_pos(Q_exc, 1)), tmp_e); /*L_tmp is Q31, now*/ - tmp16 = BASOP_Util_Divide3216_Scale_lc3plus(L_tmp /*Q31,norm,tmp_e*/, lg /*Q15,15*/, &tmp2_e) /*Q15,tmp2_e+tmp_e-15*/; + tmp16 = BASOP_Util_Divide3216_Scale(L_tmp /*Q31,norm,tmp_e*/, lg /*Q15,15*/, &tmp2_e) /*Q15,tmp2_e+tmp_e-15*/; tmp_e = sub(add(tmp2_e, tmp_e), 15); IF (tmp16 != 0) { - tmp16 = Sqrt16_lc3plus(tmp16, &tmp_e); /*Q15,norm,tmp_e*/ + tmp16 = Sqrt16(tmp16, &tmp_e); /*Q15,norm,tmp_e*/ tmp_e = L_min(tmp_e, 15); *lp_gainc = L_shl_pos(L_deposit_l(tmp16), add(tmp_e, 1)); /*15Q16*/ move32(); @@ -743,7 +816,14 @@ static Word32 TDC_calcGainp(Word16 x[], Word16 y[], Word16 lg) FOR (i = 0; i < lg; i += 2) { L_tmp1 = L_mac0_sat(L_tmp1, x[i], y[i]); +#ifdef FIX_PLC_CONFORM_ISSUES + IF (i + 1 < lg) + { +#endif L_tmp2 = L_mac0_sat(L_tmp2, x[i + 1], y[i + 1]); +#ifdef FIX_PLC_CONFORM_ISSUES + } +#endif } tcorr = L_add(L_shr_pos(L_tmp1, 1), L_shr_pos(L_tmp2, 1)); Q_corr = norm_l(tcorr); @@ -755,7 +835,14 @@ static Word32 TDC_calcGainp(Word16 x[], Word16 y[], Word16 lg) FOR (i = 0; i < lg; i += 2) { L_tmp1 = L_mac0_sat(L_tmp1, y[i], y[i]); +#ifdef FIX_PLC_CONFORM_ISSUES + IF (i + 1 < lg) + { +#endif L_tmp2 = L_mac0_sat(L_tmp2, y[i + 1], y[i + 1]); +#ifdef FIX_PLC_CONFORM_ISSUES + } +#endif } tener = L_add(L_shr_pos(L_tmp1, 1), L_shr_pos(L_tmp2, 1)); Q_ener = norm_l(tener); @@ -768,7 +855,7 @@ static Word32 TDC_calcGainp(Word16 x[], Word16 y[], Word16 lg) { negative = 1; move16(); } - tcorr = L_abs(tcorr); + tcorr = L_abs_sat(tcorr); m_corr = extract_h(tcorr); @@ -1072,7 +1159,7 @@ static void TDC_normalize_energy_fx(Word16 *gain, Word16 *gain_exp, const Word16 e = norm_l(tmp); tmp = L_shl_pos(tmp, e); e1 = sub(sub(30, e), -8); move16(); - tmp16 = BASOP_Util_Divide3216_Scale_lc3plus(tmp, lg, &e2); + tmp16 = BASOP_Util_Divide3216_Scale(tmp, lg, &e2); e = 0; move16(); if (tmp16 != 0) @@ -1101,40 +1188,40 @@ static void TDC_normalize_energy_fx(Word16 *gain, Word16 *gain_exp, const Word16 tmp16 = add(shr_pos(tmp16, e2), shr_pos(c, e2)); e = add(e, e2); - tmp16 = Sqrt16_lc3plus(tmp16, &e); + tmp16 = Sqrt16(tmp16, &e); - *gain = BASOP_Util_Divide1616_Scale_lc3plus((Word16)0x7FFF, tmp16, &e1); move16(); + *gain = BASOP_Util_Divide1616_Scale((Word16)0x7FFF, tmp16, &e1); move16(); *gain_exp = sub(e1, e); move16(); Dyn_Mem_Deluxe_Out(); } -static Word16 type_2_alpha_long(Word16 nbLostFramesInRow, Word16 frame_dms) +static Word16 type_2_alpha_long(Word16 nbLostFramesInRow, LC3PLUS_FrameDuration frame_dms) { Word16 n_help; Word32 n_shift; - if (nbLostFramesInRow <= 3*(100.0/frame_dms)){ - n_help = (nbLostFramesInRow + (100/frame_dms) - 1) * frame_dms; + if (nbLostFramesInRow <= 3*(100.0/(frame_dms*1.25*10))){ + n_help = (nbLostFramesInRow + (100/(frame_dms*1.25*10)) - 1) * (frame_dms*1.25*10); return powWord16rest(31129,n_help/100,n_help%100); } else { - n_shift = (nbLostFramesInRow - 3*(100/frame_dms)) * 50/frame_dms; - n_help = (n_shift + (100/frame_dms) - 1) * frame_dms; + n_shift = (nbLostFramesInRow - 3*(100/(frame_dms*1.25*10))) * 50/(frame_dms*1.25*10); + n_help = (n_shift + (100/(frame_dms*1.25*10)) - 1) * (frame_dms*1.25*10); return powWord16rest(22937,n_help/100,n_help%100); } } -Word16 type_2_fadeout_fx(Word16 nbLostFramesInRow, Word16 frame_dms) +Word16 type_2_fadeout_fx(Word16 nbLostFramesInRow, LC3PLUS_FrameDuration frame_dms) { Word16 n_help; - Word16 selector = PLC_FADEOUT_TYPE_2_SELECTOR * 2 * (100/frame_dms); + Word16 selector = PLC_FADEOUT_TYPE_2_SELECTOR * 2 * (100/(frame_dms*1.25*10)); if (selector >= nbLostFramesInRow){ return type_2_alpha_long(nbLostFramesInRow, frame_dms); } else { - n_help = (nbLostFramesInRow + (100/frame_dms) - 1) * frame_dms; + n_help = (nbLostFramesInRow + (100/(frame_dms*1.25*10)) - 1) * (frame_dms*1.25*10); return powWord16rest(16383,n_help/100, n_help%100); } } @@ -1154,23 +1241,23 @@ static Word16 powWord16rest(Word16 base, Word16 exp, Word16 rest) { SWITCH (rest) { case 50: - root = Sqrt16_lc3plus(base, &exp2); + root = Sqrt16(base, &exp2); shr(root,exp2); exp_result = L_shr(exp_result * root,15); /* 0.5^1.5 = 0.5^(3/2) = 0.5^3*sqrt(0.5) */ BREAK; case 25: - root = Sqrt16_lc3plus(base, &exp2); + root = Sqrt16(base, &exp2); shr(root,exp2); exp2 = 0; - root = Sqrt16_lc3plus(root, &exp2); + root = Sqrt16(root, &exp2); shr(root,exp2); exp_result = L_shr(exp_result * root,15); /* 0.5^(1/4) = 0.5^sqrt(sqrt(0.5)) */ BREAK; case 75: - root = Sqrt16_lc3plus(base, &exp2); + root = Sqrt16(base, &exp2); shr(root,exp2); exp2 = 0; - root = Sqrt16_lc3plus(root, &exp2); + root = Sqrt16(root, &exp2); shr(root,exp2); tmp_result = powWord16rest(root, 3, 0); exp_result = L_shr( exp_result * tmp_result,15); diff --git a/lib_lc3plus/plc_tdc_pre_emphasis_fx.c b/lib_lc3plus/plc_tdc_pre_emphasis_fx.c index bd587d088..401bb061b 100644 --- a/lib_lc3plus/plc_tdc_pre_emphasis_fx.c +++ b/lib_lc3plus/plc_tdc_pre_emphasis_fx.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,10 +7,12 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "defines.h" #include "functions.h" -void processPreEmphasis_fx(Word32 *d2_fx, Word16 *d2_fx_exp, Word16 fs_idx, Word16 n_bands, Word16 frame_dms, Word8 *scratchBuffer) +void processPreEmphasis_fx(Word32 *d2_fx, Word16 *d2_fx_exp, Word16 fs_idx, Word16 n_bands, LC3PLUS_FrameDuration frame_dms, Word8 *scratchBuffer) { Word16 s; Word32 nrg; @@ -38,21 +40,36 @@ void processPreEmphasis_fx(Word32 *d2_fx, Word16 *d2_fx_exp, Word16 fs_idx, Word pre_emph_e = lpc_lin_pre_emphasis_e[fs_idx]; SWITCH (frame_dms) { - case 25: +#ifdef CR9_C_ADD_1p25MS + case LC3PLUS_FRAME_DURATION_1p25MS: +#ifdef FIX_PLC_CONFORM_ISSUES + pre_emph = lpc_lin_pre_emphasis_1_25ms[fs_idx]; + pre_emph_e = lpc_lin_pre_emphasis_e_1_25ms[fs_idx]; +#endif + BREAK; +#endif + case LC3PLUS_FRAME_DURATION_2p5MS: pre_emph = lpc_lin_pre_emphasis_2_5ms[fs_idx]; pre_emph_e = lpc_lin_pre_emphasis_e_2_5ms[fs_idx]; BREAK; - case 50: + case LC3PLUS_FRAME_DURATION_5MS: pre_emph = lpc_lin_pre_emphasis_5ms[fs_idx]; pre_emph_e = lpc_lin_pre_emphasis_e_5ms[fs_idx]; BREAK; - case 75: + case LC3PLUS_FRAME_DURATION_7p5MS: pre_emph = lpc_lin_pre_emphasis_7_5ms[fs_idx]; pre_emph_e = lpc_lin_pre_emphasis_e_7_5ms[fs_idx]; BREAK; + case LC3PLUS_FRAME_DURATION_10MS: + BREAK; + case LC3PLUS_FRAME_DURATION_UNDEFINED: assert(0); } - ASSERT(n_bands==20 || n_bands==40 || n_bands==60 || n_bands ==80); +#ifdef FIX_PLC_CONFORM_ISSUES + ASSERT(n_bands == 20 || n_bands == 30 || n_bands == 40 || n_bands == 60 || n_bands == 80); +#else + ASSERT(n_bands == 20 || n_bands == 40 || n_bands == 60 || n_bands == 80); +#endif /* start processing */ smax = -31; move16(); diff --git a/lib_lc3plus/plc_update_aft_imdct_fx.c b/lib_lc3plus/plc_update_aft_imdct_fx.c index e1653f3af..18685f5b4 100644 --- a/lib_lc3plus/plc_update_aft_imdct_fx.c +++ b/lib_lc3plus/plc_update_aft_imdct_fx.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,6 +7,8 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "defines.h" #include "functions.h" diff --git a/lib_lc3plus/plc_update_fx.c b/lib_lc3plus/plc_update_fx.c index ad0fbcf95..9cb2b02e4 100644 --- a/lib_lc3plus/plc_update_fx.c +++ b/lib_lc3plus/plc_update_fx.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,6 +7,8 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "defines.h" #include "functions.h" @@ -44,7 +46,7 @@ void processPLCupdateSpec_fx(Word16 q_old_d_fx[], Word16 *q_old_fx_exp, Word32 q ); /* save spectrum and the corresponding exponent */ - s = getScaleFactor32_lc3plus(q_d_fx, yLen); + s = getScaleFactor32(q_d_fx, yLen); *q_old_fx_exp = sub(*q_fx_exp, s); @@ -163,7 +165,7 @@ void processPLCspec2shape_fx(Word16 prev_bfi, Word16 bfi, Word16 q_old_d_fx[], W L_tot = L_add(L_tot, L_acc); /* two negative numbers added */ - L_tot = L_max( -(INT32_MAX), L_tot); /* conditionally add 1 to negative side, to avoid possible saturation in L_negate */ + L_tot = L_max( -(INT_MAX), L_tot); /* conditionally add 1 to negative side, to avoid possible saturation in L_negate */ L_tot = L_negate(L_tot); /* no saturation here as L_tot is != INT_MIN */ diff --git a/lib_lc3plus/plc_xcorr_fx.c b/lib_lc3plus/plc_xcorr_fx.c index 360fb8d3f..0c3dbb0cf 100644 --- a/lib_lc3plus/plc_xcorr_fx.c +++ b/lib_lc3plus/plc_xcorr_fx.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,6 +7,8 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "defines.h" #include "functions.h" diff --git a/lib_lc3plus/pvq_dec_fx.c b/lib_lc3plus/pvq_dec_fx.c index ce2cff9cd..2eb1a76a4 100644 --- a/lib_lc3plus/pvq_dec_fx.c +++ b/lib_lc3plus/pvq_dec_fx.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,6 +7,8 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "functions.h" Word16 pvq_dec_deidx_fx( /* out BER detected 1 , ok==0 */ @@ -71,6 +73,138 @@ void pvq_dec_scale_vec_fx(const Word16 *inQ14, Word16 adjGainQ13, Word16 *outQ14 Dyn_Mem_Deluxe_Out(); } +#ifdef CR9_C_ADD_1p25MS_LRSNS +void lrsns_pvq_dec_scale_W16vec_fx( + const Word16 *inQ14, + Word16 adjGainQ12, + Word16 *inQ11outQ11 +) +{ + Dyn_Mem_Deluxe_In( + Counter i; + ); + FOR(i = 0; i < M; i++) + { /* Q12*Q14 +1 -16 => Q11 */ + inQ11outQ11[i] = add(inQ11outQ11[i], mult_r(adjGainQ12, inQ14[i])); move16(); + /* Q11 = Q11 + adjGainQ12 *inQ14 +1-16 , note 12+14+1-16=11 */ + } + Dyn_Mem_Deluxe_Out(); +} + +#ifdef ENABLE_HR_MODE +void lrsns_pvq_dec_scale_W32vec_fx( + const Word32 *inQ30, + Word16 adjGainQ12, + Word32 *inQ27outQ26, + Word16 *outQ11 +) +{ + Dyn_Mem_Deluxe_In( + Counter i; + Word32 L_tmp; + ); + FOR(i = 0; i < M; i++) + { + L_tmp = L_shr_pos(L_add(inQ27outQ26[i], Mpy_32_16_lc3plus(inQ30[i], adjGainQ12)), 1); + /* Q26 = ( Q27 + inQ30*adjGainQ12 * +1-16 ) >>1 , note 30+12+1-16 =43-16 = 27 */ + inQ27outQ26[i] = L_tmp; move32(); + L_tmp = L_add(L_tmp, 1 << 14); /* manual round + 0.5*2^15 */ + L_tmp = L_min(16383L << 16, L_tmp); /* pre_saturate, to not exceed 32767 , for extract_l() below */ + L_tmp = L_max(-(16384L << 16), L_tmp); /* pre_saturate, to not exceed -32768. for extract_l() below */ + outQ11[i] = extract_h(L_shl_pos(L_tmp, 1)); move16(); /*26-16 +1= 26-15 = 11 --> Q26 to Q11*/ + + /* the effect of this Word32 to Word16 rounding does not result in exactly the same W16Q11 vector as DISABLE_HR */ + } + Dyn_Mem_Deluxe_Out(); +} +#endif /* ENABLE_HR_MODE */ + +void pvq_fess_dec_en1_normQ30andQ14_fx( + const Word16 *y /*Q0*/, + Word16 y_up_bits, + Word32 L_norm_factor, + Word16 norm_factorQ, + Word16 len, + Word32* L_y_norm, + Word16 *y_norm) +{ + Dyn_Mem_Deluxe_In( + Counter i; + Word32 L_tmp; + Word16 shift_tot; + ); + +#ifdef WMOPS + push_wmops("pvq_fess_dec_en1_normQ30andQ14_fx"); +#endif + + /* lrsns_norm_factorQ_L[N_SCF_SEARCH_SHAPES_ST2_LR] = { 31, 31, 19 + 16 }; */ /* 0_split, 1_full, 2_fixenv */ + /* maxamps = [8, 5, 12 ]; 8*2^11 = 2^14 =16384 , 5*2^12 = 20480, 12*2^11= 24576 */ + /* lrsns_y_up_bits[N_SCF_SEARCH_SHAPES_ST2_LR] = { 11, 12, 11 };*/ + + shift_tot = sub((30 + 16), add(norm_factorQ, y_up_bits)); + /* 0: lf_split (30+16) - (31+11) = 4 */ + /* 1: full (30+16) - (31+12) = 3 */ + /* 2: fixenv (30+16) - (35+11) = 0 */ + ASSERT(shift_tot >= 0); + FOR(i = 0; i < len; i++) + { + L_tmp = Mpy_32_16_0_0(L_norm_factor, shl_pos(y[i], y_up_bits)); /* Qfactor*Q_y_up => Qfactor*Qyup + 0 - 16 . e.g. Q31*Q11-16 = Q26 */ + L_y_norm[i] = L_shl_pos(L_tmp, shift_tot); move32(); /* shift up the target to Q30 */ + + y_norm[i] = round_fx(L_y_norm[i]); move16(); /* 30-16=> Q14, used in enc side gainQ loop, and for DISABLE_HR synthesis */ + + } +#ifdef WMOPS + pop_wmops(); /* pvq_fess_dec_en1_normQ30andQ14_fx*/ +#endif + Dyn_Mem_Deluxe_Out(); +} + +void FESSdeenum_fx(Word16 dim_in_fx, /* i : dimension of vec_out typically (M-1 == 15) */ + Word16 n_env_fx, /* i : number of envelopes */ + Word16 n_shift_fx, /* i : number shifts */ + Word16 n_signs_fx, /* i : number signs */ + Word16 env_ind_fx, /* i:indx */ + Word16 shift_ind_fx, /* i:indx */ + Word16 sign_ind_fx, /* i:indx */ + Word16* vec_out_fx /* o : FESS integer pulse train , with signs applied */) +{ + Dyn_Mem_Deluxe_In( + Counter i; + Word16 sign_val_fx; + ); + assert(n_env_fx >= 1 && n_env_fx <= 4); + assert(env_ind_fx >= 0 && env_ind_fx < n_env_fx); + assert(shift_ind_fx >= 0 && shift_ind_fx < n_shift_fx); + + UNUSED(n_env_fx); + UNUSED(n_shift_fx); + +#ifdef WMOPS + push_wmops("FESSdeenum_fx"); +#endif + + basop_memset(vec_out_fx, 0, sizeof(*vec_out_fx)*dim_in_fx); + + FOR(i = (shift_ind_fx + n_signs_fx - 1); i >= shift_ind_fx; i--) + { + /* low numbered coeff signs are in the msb's */ + /* high numbered coeff signs are in the lsb's */ + ASSERT(i < dim_in_fx); + + sign_val_fx = sub(1, shl_pos(s_and(sign_ind_fx, 0x01), 1)); /* 1 - 2*signbit_value */ + sign_ind_fx = shr_pos_pos(sign_ind_fx, 1); + + vec_out_fx[i] = extract_l(L_mult0(sign_val_fx, lrsns_fix_env_fx[env_ind_fx][i])); + } + +#ifdef WMOPS + pop_wmops(); /* */ +#endif + Dyn_Mem_Deluxe_Out(); +} +#endif void pvq_dec_en1_normQ14_fx(/* Have to be used EXACTLY the same way in both both encoder and decoder */ #ifdef ENABLE_HR_MODE diff --git a/lib_lc3plus/pvq_enc_fx.c b/lib_lc3plus/pvq_enc_fx.c index 87bc3009f..9351cbcc2 100644 --- a/lib_lc3plus/pvq_enc_fx.c +++ b/lib_lc3plus/pvq_enc_fx.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,8 +7,118 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" +#include "defines.h" #include "functions.h" +#ifdef CR9_C_ADD_1p25MS_LRSNS + static void pvq_pyr_project_lrsns_adv(const Word16 dim_proj, /* vector dimension */ + const Word16 *xabs, /* absolute vector values */ + Word32 L_xsum, /* absolute vector sum over dim_proj */ + Word16 num, /* start/safe target number of pulses for projection to a pyramid e.g. KMAX-1 */ + Word16 num_max, /* max number of pulses allowed , typically K_MAX */ + Word16 * y, /* projected integer output vector */ + Word16 *pulse_tot_ptr, Word32 *L_xy_ptr, /* accumulated correlation Q(in+0+1) = Qin+1 */ + Word32 *L_yy_ptr, /* accumulated energy Q0 */ + Word8 * scratch + ) + { + Dyn_Mem_Deluxe_In( + Counter i; + Word32 L_tmp, L_num; + Word16 den, shift_num, shift_den, shift_delta, proj_fac; + Word16 *y_r, *y_r_soft; + Word16 pulse_tot_r, pulse_tot_r_soft; + ); + +#ifdef FIX_BASOP_ENC_LRSNS_ST2FULL_PROJ + Word16 skip_rnd_flag = 0; +#endif + + y_r = (Word16 *)scratchAlign(scratch, 0); + y_r_soft = (Word16 *)scratchAlign(y_r, M * sizeof(*y_r)); /* y_r = M */ + /* y_r_soft = M */ + + *pulse_tot_ptr = 0; move16(); + pulse_tot_r = 0; move16(); + pulse_tot_r_soft = 0; move16(); + + shift_den = norm_l(L_xsum); /* x_sum input Qin */ + den = extract_h(L_shl_pos(L_xsum, shift_den)); /* now in Qin+shift_den */ + +#ifdef FIX_BASOP_ENC_LRSNS_ST2FULL_PROJ + IF(num_max == 0 ) { + num_max = num; move16(); /* use projection value num as num_max limit*/ + skip_rnd_flag = 1; move16(); + } +#endif + + L_num = L_deposit_l(num); + shift_num = sub(norm_l(L_num), 1); + L_num = L_shl_pos(L_num, shift_num); /* now in Q0 +shift_num -1 */ + + proj_fac = div_l(L_num, den); /* L_num always has to be less than den<<16 , norm_l-1 makes that happen */ + + shift_delta = sub(shift_num, shift_den); + + /* we are here using a single proj factor, but different rounding offsets 0(==trunc=safe), .25(soft), .5(==round=risky) */ + + FOR(i = 0; i < dim_proj; i++) + { + L_tmp = L_mult(proj_fac, xabs[i]); /* Q shift_delta + PVQ_SEARCH_QIN */ + L_tmp = L_shr(L_tmp, shift_delta); + + y[i] = extract_h(L_tmp); move16(); /* to Q0 with floor */ + *pulse_tot_ptr = add(*pulse_tot_ptr, y[i]); /* Q0 */ + + y_r[i] = extract_h(L_add(L_tmp, (Word32)0x00008000L)); /* regular round i.e. +.5 and truncate */ + pulse_tot_r = add(pulse_tot_r, y_r[i]); /* Q0 */ + + y_r_soft[i] = extract_h(L_add(L_tmp, (Word32)0x00004000L)); /* softer round i.e. +.25 and truncate */ + pulse_tot_r_soft = add(pulse_tot_r_soft, y_r_soft[i]); /* Q0 */ + } + + /* now analyze which rounding is valid and closest to num_max */ + +#ifdef FIX_BASOP_ENC_LRSNS_ST2FULL_PROJ + IF (skip_rnd_flag != 0 ) + { + pulse_tot_r = 32767; /*disable most optimistic rounding */ + pulse_tot_r_soft = 32767; /*disable soft optimistic rounding */ + } +#endif + + /* if y_r is successful and does not overshoot, let us use that */ + IF(sub(pulse_tot_r, num_max) <= 0) + { + basop_memcpy(y, y_r, dim_proj * sizeof(*y)); + *pulse_tot_ptr = pulse_tot_r; + pulse_tot_r_soft = 32767; /* exclude r_soft */ + } + + /* if y_r_soft is successful and does not overshoot, use that */ + IF(sub(pulse_tot_r_soft, num_max) <= 0) + { + basop_memcpy(y, y_r_soft, dim_proj * sizeof(*y)); + *pulse_tot_ptr = pulse_tot_r_soft; + pulse_tot_r = 32767; + } + + /*sum up correlation and energy */ + *L_xy_ptr = L_deposit_l(0); + *L_yy_ptr = L_deposit_l(0); + FOR(i = 0; i < dim_proj; i++) + { + *L_yy_ptr = L_mac0(*L_yy_ptr, y[i], y[i]); /* Energy, Q0 */ + *L_xy_ptr = L_mac(*L_xy_ptr, xabs[i], y[i]); /* Corr, Q11*Q0 +1 --> Q12 */ + } + ASSERT(*pulse_tot_ptr <= num_max); + + Dyn_Mem_Deluxe_Out(); + } +#endif + static void pvq_pyr_project(const Word16 dim_proj, /* end vector dimension+1 */ const Word16 *xabs, /* absolute vector values */ Word32 L_xsum, /* absolute vector sum over dim */ @@ -112,6 +222,69 @@ static __forceinline Word16 one_pulse_search(const Word16 dim_start, /* start v return imax; } +#ifdef CR9_C_ADD_1p25MS_LRSNS + +/* evaluate corr/sqrt(en) = corr*inv_sqrt_tab[en], as CorrSq/en ratio cross-multiplication may cost more */ + +static __forceinline Word16 one_pulse_search_tab_isqrt( + const Word16 dim_start, /* start vector dimension */ + const Word16 dim_end, /* end vector dimension+1 */ + const Word16 *x_abs, /* absolute vector values */ + Word16 * y, /* output vector */ + Word16 * pulse_tot_ptr, + Word32 * L_xy_ptr, /* accumulated correlation Q(12+0+1) = Q13 */ + Word32 * L_yy_ptr, /* accumulated energy Q0 */ + Word16 max_xabs) /* current max amplitude for target */ +{ + Dyn_Mem_Deluxe_In( + Counter i; + + Word32 L_cand_en_lc, L_cand_corr; + Word16 corr_up_shift, imax; + Word32 L_cand_norm_ratio, L_max_norm_ratio; + ); + + /* maximize correlation precision, prior to every unit pulse addition in the vector */ + corr_up_shift = norm_l(L_mac0(*L_xy_ptr, 2, max_xabs)); /* pre analyze worst case L_xy update in the dim loop */ + imax = -1; /* init not needed for this search, only added to avoid MSVC compiler warning */ + + /* select isqrt table for this pulse addition loop , based on current energy */ + const Word16* isqrt_QxTab = isqrt_Q16tab; move32(); /* Q16 table valid for energies 4...64 */ + if (L_sub(*L_yy_ptr, 3L) <= 0) /* +1 for the inloop value of L_yy was preadded outside to *L_yy_ptr */ + { + isqrt_QxTab = isqrt_Q15tab; move32(); /* energies: 1...6 */ + } + + { + L_max_norm_ratio = L_deposit_l(-1); /* req. to force a 1st update for n==dim_start */ + + FOR(i = dim_start; i < dim_end; i++) + { + L_cand_corr = L_shl_pos(L_mac0(*L_xy_ptr, 2, x_abs[i]), corr_up_shift); /* actual in-loop target value */ + L_cand_en_lc = L_mac0(*L_yy_ptr, 2, y[i]); /*Q0 y^2+ 2y +1, "+1" added once before loop outside */ + + L_cand_norm_ratio = Mpy_32_16_0_0(L_cand_corr, isqrt_QxTab[L_cand_en_lc]); /* energy normalized ratio, non-saturating operation */ + + /* 32 bit comparison WC (1 +1 +1 = 2 */ + if (L_sub(L_cand_norm_ratio, L_max_norm_ratio) >= 0) + { + imax = i; move16(); /* conditional move single basop */ + } + L_max_norm_ratio = L_max(L_max_norm_ratio, L_cand_norm_ratio); /* always update */ + } /* dim */ + } + + /* finally add found unit pulse contribution to past L_xy, L_yy, for next pulse loop */ + *L_xy_ptr = L_mac0(*L_xy_ptr, x_abs[imax], 2); /* Qin*Q0+1 */ + *L_yy_ptr = L_mac0(*L_yy_ptr, 2, y[imax]); /* en = en + 2*y + 1 , 1 was preadded outside */ + + y[imax] = add(y[imax], 1); move16(); /* Q0 added pulse */ + (*pulse_tot_ptr) = add((*pulse_tot_ptr), 1); /* increment total pulse sum */ + + Dyn_Mem_Deluxe_Out(); + return imax; +} +#endif void pvq_enc_search_fx( const Word16 *x, /* i: target vector to quantize Qin */ @@ -367,3 +540,546 @@ void pvq_enc_search_fx( #endif } +#ifdef CR9_C_ADD_1p25MS_LRSNS + +/* 29/30 bits optimized search functions for PVQ and FESS */ +/* stage 2 submode shape 0: "splitLF" (N=5,K=6)(N=8,K=2)(N=2,K=0), or (N=5,K=8)(N=10,K=0) , 4 gains */ +/* stage 2 submode shape 1: "full" FB (N=15,K=5), , 8 gains */ +/* stage 2 submode shape 2-5: "fixed env " (N=13-15,K=10-12), 4xfixed , 8 gains */ + +#define SC 1 /* starting coeff for LRSNS VQ searches, as DC is zero in the DCT-II domain target */ +void pvq_fess_enc_search_fx( + const Word16 *x_in, /* i: target vector to quantize Qin (=Q11) 0...M-1 */ + + Word16 * y_Q0, /* o: raw integer pulses (non-scaled short) Q0 , length 3*M */ + Word16 * y_normQ14, /* o: normalized integer pulses (non-scaled short) Q14 , length 3*M */ + Word32 * L_y_normQ30, /* o: normalized integer pulses (non-scaled short) Q30 , length 3*M */ + Word16 * s_idxPtr, /* o: quantized shape index, 0,1,2 */ + Word16 * g_idxPtr, /* o: quantized gain index, 0..3, or 0..7 */ + Word16 * g_qvalQ12Ptr, /* o: quantized gain value, in Q12 -32767 == 7.99975 for best shape */ + Word16 * fixShapeNbPtr, /* o: idx for the selected fix shape y_fix 0...3, only relevant in the case s_idx==2 */ + Word16 * fixShiftIdxPtr, /* o: idx for the selected fix shift 0...3, only relevant in the case s_idx==2 */ + Word32 * L_MSEQ22Ptr, /* o: 1 Q11+Q0+1 --> Q22 */ + Word8 * scratch +) +{ + + Dyn_Mem_Deluxe_In( + Counter i, k, n; + Word16 pulse_tot; + Word16 max_xabs, max_xabsA, max_xabsB, max_xabsAB, max_xabsC; + Word32 L_xsum, L_xsumA, L_xsumB, L_xsumAB; + Word32 L_yy, L_xy; + + Word16 imax; + Word16 *y_split, *y_full, *y_fix; + Word16 *y_splitAB; + + Word16 *y_splitA0; + Word16 best_env_ind; + Word16 best_shift_ind; + Word32 L_targetEnNeg; + + Word16 shift_ind, fix_ind; + Word16* xabs1; + const Word16* envPtr; + Word32 L_corr; + + + Word16 *y, *y_norm, tmp; + Word32 *L_y_norm; + Word32 L_tmp; + Word32 L_min_mse_opt; + + Word16 gain_idx_opt, shape_idx_opt; + Word16 best_ind; + Word16 gidx; + Word32 L_g_q_tmp; + const Word16 *gTabPtr; + Word32 L_mse; + Word32 L_xy_a6_mem; + Word32 L_MSEQ22_recalc; + Word32 L_normcorrQy; + Word16 norm_factors[N_SCF_SEARCH_SHAPES_ST2_LR]; + Word32 L_norm_factors[N_SCF_SEARCH_SHAPES_ST2_LR]; + + Word32 *L_search_corr; + Word32 *L_search_en; + Word16 *xabs; + Word8* scratch_top_proj; + Word32 *L_corr_fixenv; + Word32 *L_normcorr_fixenv; + Word16 *gain_idx_opt_save; + Word32 *L_min_mse_opt_save; + ); + UNUSED(imax); /* avoid gcc compiler warning */ + UNUSED(tmp); + + L_search_corr = (Word32 *)scratchAlign(scratch, 0); + L_search_en = (Word32 *)scratchAlign(L_search_corr , N_SCF_SEARCH_SHAPES_ST2_LR * sizeof(*L_search_corr)); + xabs = (Word16 *)scratchAlign(L_search_en , N_SCF_SEARCH_SHAPES_ST2_LR * sizeof(*L_search_en)); + scratch_top_proj = (Word8 *)scratchAlign(xabs, PVQ_MAX_VEC_SIZE * sizeof(*xabs) ); + + L_corr_fixenv = (Word32 *)scratch_top_proj ; + L_normcorr_fixenv = (Word32 *)scratchAlign(L_corr_fixenv , SNSLR_N_FIXENV*SNSLR_N_FIXENV_SHIFTS * sizeof(*L_corr_fixenv)); + gain_idx_opt_save = (Word16 *)scratchAlign(L_normcorr_fixenv, SNSLR_N_FIXENV*SNSLR_N_FIXENV_SHIFTS * sizeof(*L_normcorr_fixenv)); + L_min_mse_opt_save = (Word32 *)scratchAlign(gain_idx_opt_save, N_SCF_SEARCH_SHAPES_ST2_LR * sizeof(*gain_idx_opt_save)); + /* scratch_top = (Word8 *)scratchAlign(L_min_mse_opt_save, N_SCF_SEARCH_SHAPES_ST2_LR *sizeof(L_min_mse_opt_save)); */ + +#ifdef WMOPS + push_wmops("pvq_fess_enc_search_fx"); +#endif + + best_env_ind = -1; + best_shift_ind = -1; + gain_idx_opt = 0; + + y_split = &(y_Q0[0]); move32(); + y_full = &(y_Q0[1 * M]); move32(); + y_fix = &(y_Q0[2 * M]); move32(); + + + /* init */ + basop_memset(L_search_corr, 0, N_SCF_SEARCH_SHAPES_ST2_LR * sizeof(Word32)); + basop_memset(L_search_en, 0, N_SCF_SEARCH_SHAPES_ST2_LR * sizeof(Word32)); + + max_xabs = -1; move16(); + max_xabsC = -1; move16(); + + basop_memset(y_split, 0, PVQ_MAX_VEC_SIZE * sizeof(Word16)); + basop_memset(y_full, 0, PVQ_MAX_VEC_SIZE * sizeof(Word16)); + basop_memset(y_fix, 0, PVQ_MAX_VEC_SIZE * sizeof(Word16)); + + y_splitAB = y_split; /* ptr init */ + y_splitA0 = y_fix; /* ptr init */ /* y_fix temporarlily used for splitA0 */ + + xabs[0] = 0; move16(); /* always no DC in LRSNS scheme */ + FOR(i = SC; i < PVQ_MAX_VEC_SIZE; i++) + { + xabs[i] = abs_s(x_in[i]); move16(); /* input Qx */ + } + + /* A section */ + max_xabsA = -1; move16(); + L_xsumA = L_deposit_h(0); + FOR(i = SC; i < SC + NA_LR; i++) + { + max_xabsA = s_max(max_xabsA, xabs[i]); /* max value used for near optimal search correlation scaling */ + L_xsumA = L_mac0(L_xsumA, 1, xabs[i]); /* stay in Qx */ + } + /* B section */ + max_xabsB = -1; move16(); + L_xsumB = L_deposit_h(0); + FOR(i = SC + NA_LR; i < SC + NA_LR + NB_LR; i++) + { + max_xabsB = s_max(max_xabsB, xabs[i]); /* later used for near optimal search correlation scaling */ + L_xsumB = L_mac0(L_xsumB, 1, xabs[i]); /* stay in Qx */ + } + L_xsumAB = L_add(L_xsumA, L_xsumB); + + /* "C" section, 2 coeffs, not coded by split shapes {A,B}, {A,0} , but potentially coded by full and fix shapes */ + max_xabsC = s_max(xabs[PVQ_MAX_VEC_SIZE - 2], xabs[PVQ_MAX_VEC_SIZE - 1]); + L_xsum = L_mac0(L_xsumAB, 1, xabs[PVQ_MAX_VEC_SIZE - 2]); + L_xsum = L_mac0(L_xsum, 1, xabs[PVQ_MAX_VEC_SIZE - 1]); + + /*globalMax abs , for split and full search and projection */ + max_xabsAB = s_max(max_xabsA, max_xabsB); + max_xabs = s_max(max_xabsAB, max_xabsC); /* global max abs value over all M-1 coeffs */ + + L_targetEnNeg = L_deposit_l(0); + FOR(i = SC; i < PVQ_MAX_VEC_SIZE; i++) + { + /*target MSE part for final winning stage 2 MSE shape */ + L_targetEnNeg = L_msu0(L_targetEnNeg, x_in[i], x_in[i]); /* for final MSE output calculation */ + } + + IF(L_xsum == 0) + { /* no shape in any section, projection, A, AB, ABC not possible:: --> search is meaningless */ + y_split[SC] = PULSES_SPLIT_A_LR; move16(); + y_split[SC + NA_LR] = PULSES_SPLIT_B_LR; move16(); + + y_full[SC] = PULSES_FULL_LR; move16(); + + FOR(i = SC; i < SC + NSIGNS_FIX_3; i++) + { + y_fix[i] = 1; move16(); + } + *fixShapeNbPtr = 3; move16(); + + /* L_search_corr[], [0,1,2] all stays zero valued */ + ASSERT(L_search_corr[0] == 0 && L_search_corr[1] == 0 && L_search_corr[2] == 0); + L_search_en[0] = PULSES_SPLIT_A_LR * PULSES_SPLIT_A_LR + PULSES_SPLIT_B_LR * PULSES_SPLIT_B_LR; move32(); + L_search_en[1] = PULSES_FULL_LR * PULSES_FULL_LR; move32(); + L_search_en[2] = NSIGNS_FIX_3; move32(); /* read from table as shape is not all ones */ + } + ELSE + { /* projection, to a valid pyramid or sub-pyramid */ + /* use the most optimistic projection */ +#ifdef FIX_BASOP_ENC_LRSNS_ST2FULL_PROJ + /* always use at least one loop of single pulse optimization */ + pvq_pyr_project_lrsns_adv(SC + NFULL_LR, xabs, L_xsum, (PULSES_FULL_LR - 1), 0, y_full, &pulse_tot, &L_xy, &L_yy, scratch_top_proj); /* 0 --> old floor( 1/( K-1) ) */ +#else + pvq_pyr_project_lrsns_adv(SC + NFULL_LR, xabs, L_xsum, (PULSES_FULL_LR), PULSES_FULL_LR, y_full, &pulse_tot, &L_xy, &L_yy, scratch_top_proj); +#endif + + FOR(k = pulse_tot; k < PULSES_FULL_LR; k++) + { + L_yy = L_add(L_yy, 1); /* pre add 1 in Q0 in L_yyQ0 = (x^2 + 2*x + 1) */ + imax = one_pulse_search_tab_isqrt(SC, PVQ_MAX_VEC_SIZE, xabs, y_full, &pulse_tot, &L_xy, &L_yy, max_xabs); + } + ASSERT(pulse_tot == PULSES_FULL_LR); + + /* full subshape result vector in y_full[0...15] */ + /* L_mac result from splitAB search loop */ + L_search_corr[1] = L_shr_pos(L_xy,1); /* Q11*Q0 */ + L_search_en[1] = L_yy; move32(); /*Q0*/ + + + IF( L_xsumA == 0 ) + { /* no shape in A section, search is meaningless */ + y_split[SC] = PULSES_SPLIT_A_LR; move16(); /*splitAB A-shape set */ + y_split[SC + NA_LR] = PULSES_SPLIT_B_LR; move16(); /*splitAB B-shape set */ + L_search_corr[0] = L_deposit_h(0); + L_search_en[0] = (PULSES_SPLIT_A_LR*PULSES_SPLIT_A_LR + PULSES_SPLIT_B_LR + PULSES_SPLIT_B_LR); move32(); /*Q0*/ + } + ELSE + { /* recalculate A section from the partially available full result ( to remove section B pulses influence in corr^2/en ) */ + pulse_tot = 0; move16(); + L_xy = L_deposit_l(0); + L_yy = L_deposit_l(0); + + basop_memmove(y_splitAB, y_full, (SC + NA_LR) * sizeof(Word16)); /* copy full(15) -> y_splitAB(5+8) (5 first here only) */ + + FOR(i = SC; i < (SC + NA_LR); i++) + { + pulse_tot = add(pulse_tot, y_splitAB[i]); /* Q0 */ + L_xy = L_mac(L_xy, xabs[i], y_splitAB[i]); /* Corr, Q0*Qx +1 --> Qx+1 */ + L_yy = L_mac0(L_yy, y_splitAB[i], y_splitAB[i]); /* Energy, Q(0+0)+1)= Q0 */ + } + + /* search any remaining unit pulses in section A */ + /* (continue up to 6 LF section A pulses) */ + + FOR(k = pulse_tot; k < PULSES_SPLIT_A_LR; k++) + { + L_yy = L_add(L_yy, 1); /* 1 added in Q0 */ + imax = one_pulse_search_tab_isqrt(SC, SC + NA_LR, xabs, y_splitAB, &pulse_tot, &L_xy, &L_yy, max_xabsA); + } + + /* L_mac result from splitAB search loop */ + L_xy_a6_mem = L_xy; move32(); + L_search_corr[0] = L_shr_pos(L_xy,1); /* A-part of AB temporarily saved */ + L_search_en[0] = L_yy; move32(); /* A-part of AB temporarily saved */ + + ASSERT(pulse_tot == PULSES_SPLIT_A_LR); + + basop_memmove(y_splitA0, y_splitAB, (SC + NA_LR) * sizeof(Word16)); /* copy_splitAB(5 first) -> y_splitA (5) */ + + /* search any remaining unit pulses in sectionA for the PVQ(n=5,k=8)+PVQ(n=9,k=0) alternative */ + /* (i.e. add 2 LF pulses, up to 8) */ + + FOR(k = pulse_tot; k < (PULSES_SPLIT_A_LR + PULSES_SPLIT_B_LR); k++) + { + L_yy = L_add(L_yy, 1); /* 1 added in Q0 */ + imax = one_pulse_search_tab_isqrt(SC, SC + NA_LR, xabs, y_splitA0, &pulse_tot, &L_xy, &L_yy, max_xabsA); + } + + + /* note: a local temporary use of the fixed env location "2" for corr and energy memory*/ + L_search_corr[2] = L_xy; move32(); /* A-part of A,0 saved temporarily */ + L_search_en[2] = L_yy; move32(); /* A-part of A,0 saved */ + + /* search B section of splitAB (add 2 HF pulses) */ + L_xy = L_xy_a6_mem; move32(); + L_yy = L_search_en[0]; move32(); + pulse_tot = PULSES_SPLIT_A_LR; move16(); + + IF(L_xsumB != 0) + { + FOR(k = 0; k < PULSES_SPLIT_B_LR; k++) + { + L_yy = L_add(L_yy, 1); /* 1 added in Q0 */ + imax = one_pulse_search_tab_isqrt(SC + NA_LR, SC + NA_LR + NB_LR, xabs, y_splitAB, &pulse_tot, &L_xy, &L_yy, max_xabsB); + } + } + ELSE + { + y_splitAB[SC + NA_LR] = PULSES_SPLIT_B_LR; /* correlation L_xy not increased as x is zero */ + L_yy = L_add(L_yy, PULSES_SPLIT_B_LR * PULSES_SPLIT_B_LR); /* y_splitAB energy increased by 2^2 */ + } + + /* compare the best split shape out of (splitAB), vs (splitA,0) */ + /* if corrAB^2/enAB > corrA^2/enA, then choose AB else A,0 */ + /* energy in L_yy can at most be 64 , and low value is 8 */ + /* however as energy can only take on ~64 values [8 ... 64] */ + /* we use :. if corrAB*sqrt(1/enAB) > corrA* sqrt(1/enA), then choose AB else A,0 */ + { + Word32 L_tmpA0, L_tmpAB; + Word16 tmp_shift; + + /* maximize precision in corr values */ + tmp_shift = s_min(norm_l(L_search_corr[2]), norm_l(L_xy)); + + ASSERT(tmp_shift >= 0); + + ASSERT(L_yy >= 4 && L_search_en[2] > 4 && "isqrt_Q16tab requires energy >=4 "); + L_tmpA0 = Mpy_32_16_0_0(L_shl_pos(L_search_corr[2], tmp_shift), isqrt_Q16tab[L_search_en[2]]); /* nonsaturating Mpy32_16_0_0 used for ARM-SMULWB reuse */ + L_tmpAB = Mpy_32_16_0_0(L_shl_pos(L_xy, tmp_shift), isqrt_Q16tab[L_yy]); + + L_search_corr[0] = L_shr_pos_pos(L_xy, 1); /* assume AB corr as winner */ + L_search_en[0] = L_yy; move32(); /* assume AB energy as winner */ + + IF(L_sub(L_tmpA0, L_tmpAB) > 0) + { + basop_memcpy(y_split, y_splitA0, M * sizeof(Word16)); /* cpy complete LFonly A,0 as the final splitLF output */ + L_search_corr[0] = L_shr_pos_pos(L_search_corr[2], 1); /* set A,0 as winner */ + L_search_en[0] = L_search_en[2]; move32(); /* set A,0 as winner */ + } + } + } /* L_xsumA!=0 */ + } /* L_xsum != 0 */ + + { + /* Fixed envelope signband coding, including sign coding of a shifted block */ + /* subshape idx 2,3,4 , "1"/env 1(s0)+ 2(shift)+ 11bits(s1..s11) + always a 3 bits gain */ + /* subshape idx 5 , "1"/env 1(s0)+ 2(shift)+ 9bits(s1..s9) + always a 3 bits gain */ + /* + 2, init_bell_12signs , [ 8,8,8, 7,7 ... ] + 3, decaying envelope 12 signs, [ 12,12,11,11, ... ] + 4, start_bell_12signs , [ 7,7,8,8,8, 7,... ] + 5, early_bell_10signs, [ 6,6, 7,7,8,8,8,7,... ]*/ + + /* find the minimum shape error across all possible 4 envelopes and all 4 shifts */ + /* maximise normalized cross correlation target*y /sqrt(en(y)) to minimize shape error */ + + basop_memset(y_fix, 0, PVQ_MAX_VEC_SIZE * sizeof(Word16)); /* y_fix buffer was used for y_splitA0 above, reset needed */ + + FOR(fix_ind = 0; fix_ind < SNSLR_N_FIXENV; fix_ind++) + { + FOR(shift_ind = 0; shift_ind < SNSLR_N_FIXENV_SHIFTS; shift_ind++) + { + L_corr = L_deposit_l(0); + envPtr = &(lrsns_fix_env_fx[fix_ind][shift_ind]); /* ptr init to start of the selected Q0 unit pulses */ + xabs1 = &(xabs[SC + shift_ind]); /* ptr init */ + FOR(n = 0; n < lrsns_signs_fix_fx[fix_ind]; n++) + { + ASSERT(envPtr[n] >= 0 && xabs1[n] >= 0); + L_corr = L_mac0(L_corr, xabs1[n], envPtr[n]); /* runtime first octant correlation calc */ + } + + tmp = add(shl_pos(fix_ind, 2), shift_ind); /* fix_ind * 4 + shift_ind */ + L_corr_fixenv[tmp] = L_corr; move32(); + L_corr = L_shl_pos(L_corr, 9); /* always 100% safe to shift up by 9 , tested with input M* 32767*/ + /* energy normalize, for the specific shift and env, + otherwise it is not possible to compare among the fixed shape envelopes */ + L_normcorr_fixenv[tmp] = Mpy_32_16_0_0(L_corr, lrsns_fixenv_enNormQ19[tmp]); + } + } + + /* now actually pick the fixenv[0,1,2,3] and env shift[0,1,2,3] option which maximizes the normcorr + . (also minimizes shape MSE as all fixed envelopes later use the very same 8 level gain quantizer) */ + + Word32 *pL = &(L_normcorr_fixenv[0]); /* ptr init */ + + best_ind = 0; move16(); + FOR(n = 1; n < (SNSLR_N_FIXENV * SNSLR_N_FIXENV_SHIFTS); n++) + { + if (L_sub(pL[n], pL[best_ind]) > 0) + { + best_ind = n; move16(); /* conditional move single BASOP */ + } + } + + /* decompose index */ + best_env_ind = shr_pos_pos(best_ind, 2); + best_shift_ind = sub(best_ind, i_mult(best_env_ind, 4)); + + ASSERT(best_env_ind >= 0 && best_env_ind < SNSLR_N_FIXENV); + ASSERT(best_shift_ind >= 0 && best_shift_ind < SNSLR_N_FIXENV_SHIFTS); + + + *fixShapeNbPtr = best_env_ind; move16(); + *fixShiftIdxPtr = best_shift_ind; move16(); + + basop_memcpy(&(y_fix[add(SC, best_shift_ind)]), &(lrsns_fix_env_fx[best_env_ind][best_shift_ind]), lrsns_signs_fix_fx[best_env_ind] * sizeof(Word16)); /* cpy complete fixed envelope to output */ + + tmp = add(shl_pos(best_env_ind, 2), best_shift_ind); + L_search_corr[2] = L_corr_fixenv[tmp]; move32(); /* L_mac0 result from fixenv normcorr search loop*/ + L_search_en[2] = L_deposit_l(lrsns_fixenv_enQ0[tmp]); /* tabled energy */ + } + + /* sign application for all three shape options */ + /* apply sign of (x_in) to first orthant result in Q0 */ + + FOR(i = SC; i < (SC + NA_LR + NB_LR); i++) + { + if (x_in[i] < 0) + { + y_split[i] = negate(y_split[i]); move16(); /* apply sign for split (AB or A0) */ + } + } + + FOR(i = SC; i < (SC + NFULL_LR); i++) + { + if (x_in[i] < 0) + { + y_full[i] = negate(y_full[i]); move16(); /* apply sign for full */ + } + } + + FOR(i = SC; i < (SC + NFULL_LR); i++) + { + if (x_in[i] < 0) + { + y_fix[i] = negate(y_fix[i]); move16(); /* apply sign for fixed env */ + } + } + + /* prepare Q14 normalized values and run the gain quantization with all remaining 3 shape options */ + /* and prepare Q30 normalized values for HR mode */ + { + + /* calculate each normalized envelope y_Q0[0...M-1]/sqrt(en) and provide result in Q14 */ + + /* make sure Word16 inv_sqrt table lookup is ok */ + ASSERT(L_search_en[0] <= SQRT_EN_MAX_FX && L_search_en[1] <= SQRT_EN_MAX_FX); + ASSERT(L_search_en[0] > 4 && L_search_en[1] > 4); /* inv_sqrt table only valid from energy value 5 */ + + + norm_factors[0] = isqrt_Q16tab[L_search_en[0]]; move16(); move16(); /* Q16 */ + norm_factors[1] = isqrt_Q16tab[L_search_en[1]]; move16(); move16(); /* Q16 */ + tmp = add(shl_pos(best_env_ind, 2), best_shift_ind); + norm_factors[2] = lrsns_fixenv_enNormQ19[tmp]; move16(); /* Q19 */ + + L_norm_factors[0] = isqrt_Q31tab[L_search_en[0]]; move32(); move32(); /* Q31 */ + L_norm_factors[1] = isqrt_Q31tab[L_search_en[1]]; move32(); move32(); /* Q31 */ + L_norm_factors[2] = L_lrsns_fixenv_enNormQ35[tmp]; move32(); + + FOR(n = 0; n < (N_SCF_SEARCH_SHAPES_ST2_LR); n++) + { + /* PVQ and FESS unit energy normalization */ + /* some precomputed norm factor and pre-known normalization shift */ + y = &(y_Q0[n*M]); /* ptr init */ + L_y_norm = &(L_y_normQ30[n*M]); /* ptr init */ + y_norm = &(y_normQ14[n*M]); /* ptr init to signed seq Q14 */ + + ASSERT(y[0] == 0); + pvq_fess_dec_en1_normQ30andQ14_fx( + y /*Q0*/, + lrsns_y_up_bits[n], + L_norm_factors[n], + lrsns_norm_factorQ_L[n], + M, /*M==16 always used to enable simple unroll into 4 */ + L_y_norm, /* for MSEQ22 estimation, and for ENABLE_HR */ + y_norm); /* for gain Q*/ + ASSERT(L_y_norm[0] == 0 && y_norm[0] == 0); + + L_y_norm[0] = 0; move32(); /* DC is always zero in LRSNS stage2 */ + y_norm[0] = 0; move16(); + + + /* establish normalized correlation to target */ + + Word32 L_normcorr_pre_fx = Mpy_32_16_lc3plus(L_search_corr[n], norm_factors[n]); + /* no need to recalc correlation, simply scale with factor */ + /*here Mpy_32_16 shifts left by 1 and maintains maximum precision */ + /*For ARM the somewhat better/native 32_16_0_0() without saturation, however not used here */ + + Word16 g_shiftright_opt[3] = { 0 , 0 , 3 }; /* down_shift(right) to get result as "g_opt*2" in Q11 */ + Word32 L_normcorrX2_opt_fx = L_shr_pos_pos(L_normcorr_pre_fx, g_shiftright_opt[n]); /* -2*g_opt for MSE calc , in Q11 */ + + /* MSE= t_2 + g^2*1.0 -(2*g_opt)*g , with g_opt = corr(t_2,x_n) */ + + gTabPtr = (const Word16 *)lrsns_vq_gainsQ12_fx[n]; move32(); /* q gains in Q12, n-adaptive ptr init */ + L_mse = L_deposit_l(0); + L_min_mse_opt = L_add(MAX_32, 0); /* min_MSE w/o target energy gain loop */ + + FOR(gidx = 0; gidx < lrsns_vq_gain_lvls_fx[n]; gidx++) + { + /* adding at the same Q required, we use Q22 in search loop for now */ + /* g_q*(g_q - 2*g_opt)/ */ + /* (-2*g_opt)*g_q + g_q*g_q = g_q*(g_q-2*g_opt) , Q11*Q11->Q22 */ + + L_g_q_tmp = L_shr_pos(L_deposit_h(gTabPtr[gidx]), 2); /* from Q12 to 12+16-2-> Q26 */ + L_tmp = L_shl_pos(L_normcorrX2_opt_fx, 15); /*11+15 -> 26 */ + ASSERT(L_normcorrX2_opt_fx <= 32767 && "L_normcorrX2_opt_fx <= 32767 "); /* should fit in Word16 */ + + L_tmp = L_sub(L_g_q_tmp, L_tmp); /* Q26-Q26 --> Q26 */ + + L_mse = Mpy_32_16_0_0(L_tmp, gTabPtr[gidx]); /* Q26+Q12 - 16 => 22 */ + + L_min_mse_opt = L_min(L_min_mse_opt, L_mse); + if (L_sub(L_mse, L_min_mse_opt) == 0) + { + gain_idx_opt = gidx; move16(); /* single BASOP, conditional move */ + } + } + gain_idx_opt_save[n] = gain_idx_opt; move16(); + L_min_mse_opt_save[n] = L_min_mse_opt; move32(); + + } /* shape n */ + + /* get the best min(MSE) among the 3 shapes */ + shape_idx_opt = 0; move16(); + L_min_mse_opt = L_min_mse_opt_save[shape_idx_opt]; move32(); + FOR(n = 1; n < (N_SCF_SEARCH_SHAPES_ST2_LR); n++) + { + L_min_mse_opt = L_min(L_min_mse_opt_save[n], L_min_mse_opt); + if (L_sub(L_min_mse_opt, L_min_mse_opt_save[n]) == 0) + { + shape_idx_opt = n; move16(); /* single basop */ + } + } + /* provide function output */ + *s_idxPtr = shape_idx_opt; move16(); + *g_idxPtr = gain_idx_opt_save[*s_idxPtr]; move16(); + *L_MSEQ22Ptr = L_sub(L_min_mse_opt, L_targetEnNeg); /* search based MSE, add target energy to gain part of MSE (sum t*2) */ + *g_qvalQ12Ptr = lrsns_vq_gainsQ12_fx[*s_idxPtr][*g_idxPtr]; + + ASSERT(L_min_mse_opt == L_min_mse_opt_save[*s_idxPtr]); + + + + /** Recalculate winning stage2 MSE with high precision **/ + L_MSEQ22_recalc = 0; + L_normcorrQy = 0; /* INT32_MIN; */ + + /* shift up input signal to the max with a margin of 4 bits. */ + Word16 x_in_upshift = norm_s(max_xabs); + + /* accumulate 15 values, would typically require ~4 bits margin , however we know only 12 can have a non-zero value */ + x_in_upshift = s_max(sub(x_in_upshift, 4), 0); + + FOR(i = 1; i < M; i++) + { + L_tmp = Mpy_32_16_0_0(L_y_normQ30[*s_idxPtr*M + i], shl_pos(x_in[i], x_in_upshift)); /* signed*signed */ + L_normcorrQy = L_add(L_normcorrQy, L_tmp); + } + L_normcorrQy = L_shr_pos(L_normcorrQy, x_in_upshift); /* back to Q25 */ + + + /* x_in^2 + gq^2*1 - 2*gq*gopt */ + L_MSEQ22_recalc = L_negate(L_targetEnNeg); + L_tmp = L_shr_pos(L_mult0(*g_qvalQ12Ptr, *g_qvalQ12Ptr), 2); + L_MSEQ22_recalc = L_add(L_MSEQ22_recalc, L_tmp); + L_tmp = L_shl_pos(Mpy_32_16_0_0(L_normcorrQy, *g_qvalQ12Ptr), (26 + 1) - 25); /* Qy+12-16+lshift = 22, --> lshift = 26-Qy , 2.0 factor -> add 1 leftshift*/ + + L_MSEQ22_recalc = L_sub(L_MSEQ22_recalc, L_tmp); + + *L_MSEQ22Ptr = L_max(L_MSEQ22_recalc, 0L); move32(); /*use high precision result recalculated MSE for winner */ + + + + ASSERT(*L_MSEQ22Ptr >= 0 && " warning negative total MSE "); + + + } /* shape norm and gain calc , and shape decision */ + +#ifdef WMOPS + pop_wmops(); +#endif + + Dyn_Mem_Deluxe_Out(); +} +#endif + diff --git a/lib_lc3plus/pvq_index_fx.c b/lib_lc3plus/pvq_index_fx.c index 948d85233..5d216df5e 100644 --- a/lib_lc3plus/pvq_index_fx.c +++ b/lib_lc3plus/pvq_index_fx.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,6 +7,8 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "functions.h" #define SIGNBIT_FX 0x80000000u diff --git a/lib_lc3plus/quantize_spec_fx.c b/lib_lc3plus/quantize_spec_fx.c index 3b080db08..147000186 100644 --- a/lib_lc3plus/quantize_spec_fx.c +++ b/lib_lc3plus/quantize_spec_fx.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,6 +7,8 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "functions.h" #ifdef ENABLE_HR_MODE @@ -107,22 +109,22 @@ void processQuantizeSpec_fx(Word32 x[], Word16 x_e, Word32 gain, Word16 gain_e, #else FOR (i = 0; i < nt; i++) { - offs32 = Mpy_32_32_lc3plus(L_abs(x[i]), gain); /* multiply */ - offs32 = L_shl(offs32, s); /* convert to 15Q16 */ - tmp16 = mac_r(offs32, -4096, 1); /* add offset and truncate */ - if (x[i] < 0) - tmp16 = negate(tmp16); /* restore sign */ + offs32 = Mpy_32_32_lc3plus(L_abs(x[i]), gain); /* multiply */ + offs32 = L_shl( offs32, s ); /* convert to 15Q16 */ + tmp16 = mac_r(offs32, -4096, 1); /* add offset and truncate */ + if (x[i] < 0) + tmp16 = negate(tmp16); /* restore sign */ - /* Normal quantization: xq[i] = x[i] / gg + sign(x[i]) * 0.375 - quant_offset is -0.125 in Q15 and round adds 0.5 in Q16. Hence - mac_r results in abs(x[i])/gain - 0.125 + 0.5 = abs(x[i])/gain + 0.375. - Due to the abs and negate combination this achieves the same result - as spec. - */ + /* Normal quantization: xq[i] = x[i] / gg + sign(x[i]) * 0.375 + quant_offset is -0.125 in Q15 and round adds 0.5 in Q16. Hence + mac_r results in abs(x[i])/gain - 0.125 + 0.5 = abs(x[i])/gain + 0.375. + Due to the abs and negate combination this achieves the same result + as spec. + */ - xq[i] = tmp16; - move16(); + xq[i] = tmp16; + move16(); } #endif /* FUNCTION_quantizeSpec_func1 */ } @@ -131,7 +133,7 @@ void processQuantizeSpec_fx(Word32 x[], Word16 x_e, Word32 gain, Word16 gain_e, move16(); if (fs_idx != 5) { - if (sub(totalBits, add(160, DEPR_i_mult(fs_idx, 160))) > 0) + if (sub(totalBits, add(160, i_mult(fs_idx, 160))) > 0) { rateFlag = 2 << NBITS_CONTEXT; move16(); @@ -157,7 +159,7 @@ void processQuantizeSpec_fx(Word32 x[], Word16 x_e, Word32 gain, Word16 gain_e, if (fs_idx != 5) { - IF (mode == 0 && sub(totalBits, add(480, DEPR_i_mult(fs_idx, 160))) >= 0) + IF (mode == 0 && sub(totalBits, add(480, i_mult(fs_idx, 160))) >= 0) { mode = 1; move16(); @@ -667,7 +669,7 @@ void processQuantizeSpec_fx(Word32 x[], Word16 x_e, Word16 gain, Word16 gain_e, #endif /* Quantization */ - gain = Inv16_lc3plus(gain, &gain_e); + gain = Inv16(gain, &gain_e); s = sub(add(x_e, gain_e), 15); s = s_max(s_min(s, 15), -15); @@ -688,7 +690,7 @@ void processQuantizeSpec_fx(Word32 x[], Word16 x_e, Word16 gain, Word16 gain_e, /* Rate flag */ rateFlag = 0; move16(); - if (sub(totalBits, add(160, DEPR_i_mult(fs_idx, 160))) > 0) + if (sub(totalBits, add(160, i_mult(fs_idx, 160))) > 0) { rateFlag = 2 << NBITS_CONTEXT; move16(); @@ -710,7 +712,7 @@ void processQuantizeSpec_fx(Word32 x[], Word16 x_e, Word16 gain, Word16 gain_e, move32(); nbits_lsb = 0; move16(); - IF (mode == 0 && sub(totalBits, add(480, DEPR_i_mult(fs_idx, 160))) >= 0) + IF (mode == 0 && sub(totalBits, add(480, i_mult(fs_idx, 160))) >= 0) { mode = 1; move16(); diff --git a/lib_lc3plus/reorder_bitstream_fx.c b/lib_lc3plus/reorder_bitstream_fx.c index 949fdc8f8..657abffc1 100644 --- a/lib_lc3plus/reorder_bitstream_fx.c +++ b/lib_lc3plus/reorder_bitstream_fx.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,6 +7,8 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "defines.h" #include "constants.h" diff --git a/lib_lc3plus/resamp12k8_fx.c b/lib_lc3plus/resamp12k8_fx.c index d59f11ec1..ebfa42502 100644 --- a/lib_lc3plus/resamp12k8_fx.c +++ b/lib_lc3plus/resamp12k8_fx.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,11 +7,13 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "functions.h" void process_resamp12k8_fx(Word16 x[], Word16 x_len, Word16 mem_in[], Word16 mem_in_len, Word32 mem_50[], Word16 mem_out[], Word16 mem_out_len, Word16 y[], Word16 *y_len, Word16 fs_idx, - Word16 frame_dms, Word8 *scratchBuffer + LC3PLUS_FrameDuration frame_dms, Word8 *scratchBuffer , Word16 bps ) { @@ -28,7 +30,8 @@ void process_resamp12k8_fx(Word16 x[], Word16 x_len, Word16 mem_in[], Word16 mem ); buf = (Word16 *)scratchAlign(scratchBuffer, 0); /* Size = 2 * (MAX_LEN + MAX_LEN / 8) bytes */ - + len_12k8 = 0; + /* resamp parameters : {upsample-factor, 120 / upsample-factor, down_sample_int_part, down_sample_frac_part } upsample is to 384 kHz. upsample-facor = 192000 / samp-freq Fractional downsample parameters are calculated from : downsample samp-freq to 128000 @@ -44,8 +47,19 @@ void process_resamp12k8_fx(Word16 x[], Word16 x_len, Word16 mem_in[], Word16 mem resamp_off_int = resamp_params[fs_idx][2]; move16(); resamp_off_frac = resamp_params[fs_idx][3]; move16(); resamp_filt = resamp_filts[fs_idx]; move16(); - - len_12k8 = LEN_12K8 / 4 * (frame_dms / 25); move16(); + + SWITCH (frame_dms) + { +#ifdef CR9_C_ADD_1p25MS + case LC3PLUS_FRAME_DURATION_1p25MS: len_12k8 = 16; BREAK; +#endif + case LC3PLUS_FRAME_DURATION_2p5MS: len_12k8 = 32; BREAK; + case LC3PLUS_FRAME_DURATION_5MS: len_12k8 = 64; BREAK; + case LC3PLUS_FRAME_DURATION_7p5MS: len_12k8 = 96; BREAK; + case LC3PLUS_FRAME_DURATION_10MS: len_12k8 = 128; BREAK; + case LC3PLUS_FRAME_DURATION_UNDEFINED: assert(0); + } + *y_len = len_12k8; move16(); /* Init Input Buffer */ diff --git a/lib_lc3plus/residual_coding_fx.c b/lib_lc3plus/residual_coding_fx.c index 2787f06c4..bec0636b7 100644 --- a/lib_lc3plus/residual_coding_fx.c +++ b/lib_lc3plus/residual_coding_fx.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,6 +7,8 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "functions.h" #ifdef ENABLE_HR_MODE @@ -16,13 +18,18 @@ void processResidualCoding_fx(Word16 x_e, Word32 x[], Word16 gain_e, Word16 L_spec, Word16 targetBits, Word16 nBits, UWord8 *resBits, Word16 *numResBits , Word16 hrmode +#if defined (CR9_C_ADD_1p25MS) + , LC3PLUS_FrameDuration frame_dms +#endif ) { Counter i; Word16 s, n, m; Word32 L_tmp; +#if defined (CR9_C_ADD_1p25MS) || defined (ENABLE_HR_MODE) Word16 iter = 0; +#endif Counter idx; Word16 N_nz = 0; Word16 n1, n2; @@ -143,6 +150,18 @@ void processResidualCoding_fx(Word16 x_e, Word32 x[], s = add(s, 16); gain = round_fx(gain); +#if defined (CR9_C_ADD_1p25MS) + Word16 iter_exit, exit_iter = 0; + IF (sub(frame_dms, LC3PLUS_FRAME_DURATION_1p25MS) == 0) + { + iter_exit = 3; move16(); + } ELSE { + iter_exit = 1; move16(); + } + + FOR (iter = 0; iter < iter_exit; iter++) + { +#endif FOR (i = 0; i < L_spec; i++) { IF (xq[i] != 0) @@ -158,10 +177,20 @@ void processResidualCoding_fx(Word16 x_e, Word32 x[], n = add(n, 1); IF (sub(n, m) == 0) { +#if defined (CR9_C_ADD_1p25MS) + exit_iter = 1; +#endif BREAK; } } } +#if defined (CR9_C_ADD_1p25MS) + IF (exit_iter) + { + BREAK; + } + } +#endif } *numResBits = n; move16(); @@ -177,6 +206,9 @@ void processResidualCoding_fx(Word16 x_e, Word32 x[], Word16 xq[], Word16 gain, Word16 gain_e, Word16 L_spec, Word16 targetBits, Word16 nBits, UWord8 *resBits, Word16 *numResBits +#if defined (CR9_C_ADD_1p25MS) + , LC3PLUS_FrameDuration frame_dms +#endif ) { @@ -204,6 +236,18 @@ void processResidualCoding_fx(Word16 x_e, Word32 x[], s = sub(add(15, gain_e), x_e); { +#if defined (CR9_C_ADD_1p25MS) + Word16 iter_exit, exit_iter = 0, iter = 0; + IF (sub(frame_dms, LC3PLUS_FRAME_DURATION_1p25MS) == 0) + { + iter_exit = 3; move16(); + } ELSE { + iter_exit = 1; move16(); + } + + FOR (iter = 0; iter < iter_exit; iter++) + { +#endif FOR (i = 0; i < L_spec; i++) { IF (xq[i] != 0) @@ -222,10 +266,20 @@ void processResidualCoding_fx(Word16 x_e, Word32 x[], n = add(n, 1); IF (sub(n, m) == 0) { +#if defined (CR9_C_ADD_1p25MS) + exit_iter = 1; +#endif BREAK; } } } +#if defined (CR9_C_ADD_1p25MS) + IF (exit_iter) + { + BREAK; + } + } +#endif } *numResBits = n; move16(); diff --git a/lib_lc3plus/residual_decoding_fx.c b/lib_lc3plus/residual_decoding_fx.c index 243f7baba..158c5f454 100644 --- a/lib_lc3plus/residual_decoding_fx.c +++ b/lib_lc3plus/residual_decoding_fx.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,6 +7,8 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "functions.h" #ifdef ENABLE_HR_MODE /* HRMODE enables packing of residual bits */ @@ -15,6 +17,9 @@ void processResidualDecoding_fx(Word32 x[], Word16 x_e, Word16 L_spec, UWord8 pr #ifdef ENABLE_HR_MODE , Word16 hrmode #endif +#ifdef CR9_C_ADD_1p25MS + , LC3PLUS_FrameDuration frame_dms +#endif ) { @@ -24,7 +29,11 @@ void processResidualDecoding_fx(Word32 x[], Word16 x_e, Word16 L_spec, UWord8 pr Word32 tmp; Counter idx; Word16 N_nz = 0; - Word16 iter; +#if defined (CR9_C_ADD_1p25MS) || defined (ENABLE_HR_MODE) + Word16 iter = 0; move16(); + Word16 maxIter = 1; move16(); + UNUSED(maxIter); +#endif Word32 fac_hr; #ifdef DYNMEM_COUNT @@ -52,6 +61,13 @@ void processResidualDecoding_fx(Word32 x[], Word16 x_e, Word16 L_spec, UWord8 pr { fac_m = L_shr(0xC000000, s); /* 0.1875 in 1Q30 */ fac_p = L_shr(0x14000000, s); /* 0.3125 in 1Q30 */ + +#if defined (CR9_C_ADD_1p25MS) + IF (sub(frame_dms, LC3PLUS_FRAME_DURATION_1p25MS) == 0) + { + maxIter = 3; + } +#endif } bits = 0; @@ -100,6 +116,10 @@ void processResidualDecoding_fx(Word32 x[], Word16 x_e, Word16 L_spec, UWord8 pr } } ELSE + { + #if defined (CR9_C_ADD_1p25MS) + WHILE (iter < maxIter) + #endif { FOR (i = 0; i < L_spec; i++) { @@ -129,6 +149,12 @@ void processResidualDecoding_fx(Word32 x[], Word16 x_e, Word16 L_spec, UWord8 pr bits = add(bits, 1); } } + #if defined (CR9_C_ADD_1p25MS) + iter++; + fac_p = L_shr(fac_p, 1); + fac_m = L_shr(fac_m, 1); + #endif + } } #ifdef DYNMEM_COUNT @@ -139,6 +165,9 @@ void processResidualDecoding_fx(Word32 x[], Word16 x_e, Word16 L_spec, UWord8 pr #else void processResidualDecoding_fx(Word32 x[], Word16 x_e, Word16 L_spec, UWord8 prm[], Word16 resQBits +#ifdef CR9_C_ADD_1p25MS + , LC3PLUS_FrameDuration frame_dms +#endif ) { @@ -156,6 +185,12 @@ void processResidualDecoding_fx(Word32 x[], Word16 x_e, Word16 L_spec, UWord8 pr })); #endif +#if defined (CR9_C_ADD_1p25MS) + Word16 iter = 0; move16(); + Word16 maxIter = 1; move16(); + UNUSED(maxIter); +#endif + tmp = 0; s = sub(x_e, 1); s = s_min(s, 31); @@ -164,10 +199,20 @@ void processResidualDecoding_fx(Word32 x[], Word16 x_e, Word16 L_spec, UWord8 pr fac_m = L_shr(0xC000000, s); /* 0.1875 in 1Q30 */ fac_p = L_shr(0x14000000, s); /* 0.3125 in 1Q30 */ } + +#if defined (CR9_C_ADD_1p25MS) + IF (sub(frame_dms, LC3PLUS_FRAME_DURATION_1p25MS) == 0) + { + maxIter = 3; + } +#endif bits = 0; move16(); - + + #if defined (CR9_C_ADD_1p25MS) + WHILE (iter < maxIter) + #endif { FOR (i = 0; i < L_spec; i++) { @@ -197,6 +242,11 @@ void processResidualDecoding_fx(Word32 x[], Word16 x_e, Word16 L_spec, UWord8 pr bits = add(bits, 1); } } + #if defined (CR9_C_ADD_1p25MS) + iter++; + fac_p = L_shr(fac_p, 1); + fac_m = L_shr(fac_m, 1); + #endif } #ifdef DYNMEM_COUNT diff --git a/lib_lc3plus/rom_basop_util_lc3plus.c b/lib_lc3plus/rom_basop_util_lc3plus.c old mode 100755 new mode 100644 index 6e53895e1..f47c818f6 --- a/lib_lc3plus/rom_basop_util_lc3plus.c +++ b/lib_lc3plus/rom_basop_util_lc3plus.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,6 +7,8 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "rom_basop_util_lc3plus.h" #include "basop_util_lc3plus.h" #include "functions.h" @@ -29,7 +31,7 @@ /** * \brief Lookup-Table for binary logarithm */ -RAM_ALIGN const Word16 ldCoeff_lc3plus[7] = {-32768, -16384, -10923, -8192, -6554, -5461, -4681}; +RAM_ALIGN const Word16 ldCoeff[7] = {-32768, -16384, -10923, -8192, -6554, -5461, -4681}; /** \brief Lookup-Table for binary power algorithm @@ -37,7 +39,7 @@ RAM_ALIGN const Word16 ldCoeff_lc3plus[7] = {-32768, -16384, -10923, -8192, -655 This table is used for lookup 2^x with x in range [0...1.0[ in steps of 1/32 */ -const UWord32 exp2_tab_long_lc3plus[32] = { +const UWord32 exp2_tab_long[32] = { 0x40000000, 0x4166C34C, 0x42D561B4, 0x444C0740, 0x45CAE0F2, 0x47521CC6, 0x48E1E9BA, 0x4A7A77D4, 0x4C1BF829, 0x4DC69CDD, 0x4F7A9930, 0x51382182, 0x52FF6B55, 0x54D0AD5A, 0x56AC1F75, 0x5891FAC1, 0x5A82799A, 0x5C7DD7A4, 0x5E8451D0, 0x60962665, 0x62B39509, 0x64DCDEC3, 0x6712460B, 0x69540EC9, @@ -50,7 +52,7 @@ const UWord32 exp2_tab_long_lc3plus[32] = { This table is used for lookup 2^x with x in range [0...1/32[ in steps of 1/1024 */ -const UWord32 exp2w_tab_long_lc3plus[32] = { +const UWord32 exp2w_tab_long[32] = { 0x40000000, 0x400B1818, 0x4016321B, 0x40214E0C, 0x402C6BE9, 0x40378BB4, 0x4042AD6D, 0x404DD113, 0x4058F6A8, 0x40641E2B, 0x406F479E, 0x407A7300, 0x4085A051, 0x4090CF92, 0x409C00C4, 0x40A733E6, 0x40B268FA, 0x40BD9FFF, 0x40C8D8F5, 0x40D413DD, 0x40DF50B8, 0x40EA8F86, 0x40F5D046, 0x410112FA, @@ -63,7 +65,7 @@ const UWord32 exp2w_tab_long_lc3plus[32] = { This table is used for lookup 2^x with x in range [0...1/1024[ in steps of 1/32768 */ -const UWord32 exp2x_tab_long_lc3plus[32] = { +const UWord32 exp2x_tab_long[32] = { 0x40000000, 0x400058B9, 0x4000B173, 0x40010A2D, 0x400162E8, 0x4001BBA3, 0x4002145F, 0x40026D1B, 0x4002C5D8, 0x40031E95, 0x40037752, 0x4003D011, 0x400428CF, 0x4004818E, 0x4004DA4E, 0x4005330E, 0x40058BCE, 0x4005E48F, 0x40063D51, 0x40069613, 0x4006EED5, 0x40074798, 0x4007A05B, 0x4007F91F, @@ -71,7 +73,7 @@ const UWord32 exp2x_tab_long_lc3plus[32] = { }; /* square root tables */ -const Word32 SqrtTable_lc3plus[32] = { +const Word32 SqrtTable[32] = { /* Q31 */ 0x5A82D429, 0x5BEA10FE, 0x5D4BE6E5, 0x5EA89270, 0x60004BE2, 0x615347A1, 0x62A1B68C, 0x63EBC651, 0x6531A1B5, 0x667370D4, 0x67B1595F, 0x68EB7EC8, 0x6A220277, 0x6B5503F0, 0x6C84A0F9, 0x6DB0F5BD, @@ -79,14 +81,14 @@ const Word32 SqrtTable_lc3plus[32] = { 0x77BBCF60, 0x78CC4545, 0x79DA5A00, 0x7AE61D3E, 0x7BEF9E07, 0x7CF6EAC2, 0x7DFC113F, 0x7EFF1EC0, }; -const Word16 SqrtDiffTable_lc3plus[32] = { +const Word16 SqrtDiffTable[32] = { /* Q21 */ 0x59CF, 0x5875, 0x572B, 0x55EE, 0x54BF, 0x539C, 0x5284, 0x5177, 0x5074, 0x4F7A, 0x4E89, 0x4DA1, 0x4CC0, 0x4BE7, 0x4B15, 0x4A4A, 0x4985, 0x48C6, 0x480C, 0x4758, 0x46AA, 0x4600, 0x455B, 0x44BA, 0x441D, 0x4385, 0x42F1, 0x4260, 0x41D3, 0x414A, 0x40C3, 0x4040, }; -const Word32 ISqrtTable_lc3plus[32] = { +const Word32 ISqrtTable[32] = { /* Q31 */ 0x7FFE7F85, 0x7E0A4E25, 0x7C2C56C7, 0x7A63002C, 0x78ACD922, 0x7708939D, 0x75750088, 0x73F10C2D, 0x727BBB1A, 0x71142774, 0x6FB97EA5, 0x6E6AFF54, 0x6D27F79D, 0x6BEFC388, 0x6AC1CBA4, 0x699D83DA, @@ -94,7 +96,7 @@ const Word32 ISqrtTable_lc3plus[32] = { 0x60C1E8C8, 0x5FE7AE45, 0x5F131EBE, 0x5E43FC76, 0x5D7A0D4F, 0x5CB51A81, 0x5BF4F061, 0x5B395E26, }; -const Word16 ISqrtDiffTable_lc3plus[32] = { +const Word16 ISqrtDiffTable[32] = { /* Q21 */ 0x7D0C, 0x777E, 0x7256, 0x6D8A, 0x6911, 0x64E5, 0x60FD, 0x5D54, 0x59E5, 0x56AA, 0x53A0, 0x50C2, 0x4E0D, 0x4B7E, 0x4912, 0x46C6, 0x4499, 0x4288, 0x4090, 0x3EB1, 0x3CE9, 0x3B36, @@ -102,7 +104,7 @@ const Word16 ISqrtDiffTable_lc3plus[32] = { }; /* 1/x tables */ -const Word32 InvTable_lc3plus[32] = { +const Word32 InvTable[32] = { /* Q31 */ 0x7FFBFE40, 0x7C1B608E, 0x78752176, 0x750440BA, 0x71C44C49, 0x6EB14D0A, 0x6BC7B6B4, 0x69045A19, 0x6664598A, 0x63E51EE2, 0x61845308, 0x5F3FD698, 0x5D15BB8E, 0x5B043FD0, 0x5909C861, 0x5724DD3C, @@ -126,7 +128,7 @@ const Word16 InvIntTable[32] = { }; #endif -const Word16 InvDiffTable_lc3plus[32] = { +const Word16 InvDiffTable[32] = { /* Q20 */ 0x7C14, 0x74C8, 0x6E1C, 0x67FF, 0x6260, 0x5D33, 0x586C, 0x5400, 0x4FE7, 0x4C19, 0x4890, 0x4543, 0x422F, 0x3F4F, 0x3C9D, 0x3A17, 0x37B8, 0x357E, 0x3365, 0x316B, 0x2F8D, 0x2DCB, @@ -659,6 +661,20 @@ const PWord16 SineWindow20[10] = { WTCP(0x6fadf2fb, 0x3e8b240e), WTCP(0x6a6d98a3, 0x471cece6), WTCP(0x648543e3, 0x4f3e7874), WTCP(0x5dfe47ad, 0x56e2f15d), }; + +#if (defined CR9_C_ADD_1p25MS) +#ifdef ENABLE_HR_MODE +const PWord32 SineWindow30[] = { +#else +const PWord16 SineWindow30[] = { +#endif + WTCP(0x7ff4c56f, 0x0359c428), WTCP(0x7f9afcb9, 0x0a0af299), WTCP(0x7ee7aa4c, 0x10b5150f), WTCP(0x7ddb4bfc, 0x17537e63), + WTCP(0x7c769e18, 0x1de189a6), WTCP(0x7aba9ae6, 0x245a9d65), WTCP(0x78a879f4, 0x2aba2ee4), WTCP(0x7641af3d, 0x30fbc54d), + WTCP(0x7387ea23, 0x371afcd5), WTCP(0x707d1443, 0x3d1389cb), WTCP(0x6d23501b, 0x42e13ba4), WTCP(0x697cf78a, 0x487fffe4), + WTCP(0x658c9a2d, 0x4debe4fe), WTCP(0x6154fb91, 0x53211d18), WTCP(0x5cd91140, 0x581c00b3), WTCP(0x5cd91140, 0x581c00b3), + +}; +#endif #ifdef ENABLE_HR_MODE const PWord32 SineWindow40[20] = { @@ -1360,13 +1376,14 @@ const PWord32 SineWindow960[480] = { }; #endif -// fs 48 32 24 16 8 -// ms +-------------------- -// 10.0 | 480 320 240 160 80 -// 7.5 | 360 240 180 120 60 -// 5.0 | 240 160 120 80 40 -// 2.5 | 120 80 60 40 20 - +/* + fs 48 32 24 16 8 + ms +-------------------- + 10.0 | 480 320 240 160 80 + 7.5 | 360 240 180 120 60 + 5.0 | 240 160 120 80 40 + 2.5 | 120 80 60 40 20 +*/ void BASOP_getTables( #ifdef ENABLE_HR_MODE const PWord32 **twiddle, const PWord32 **sin, @@ -1385,6 +1402,17 @@ void BASOP_getTables( *twiddle = SineWindow20; move16(); BREAK; +#ifdef CR9_C_ADD_1p25MS + /* 24 kHz 1.25 ms */ + case 30: + *sin = SineTable360; + move16(); + *sin_step = 24; + move16(); + *twiddle = SineWindow30; + move16(); + BREAK; +#endif case 40: *sin = SineTable320; move16(); @@ -2782,7 +2810,7 @@ const Word16 RotVector_32_12[2 * (384 - 32)] = { Implicit exponent is 1 - Example: 0x5A82799A = Isqrt(0x40000000), exponent=1 + Example: 0x5A82799A = Isqrt_lc3plus(0x40000000), exponent=1 */ const Word32 isqrt_table[128 + 2] = { 0x5A827999, 0x5A287E03, 0x59CF8CBC, 0x5977A0AC, 0x5920B4DF, 0x58CAC480, 0x5875CADE, 0x5821C364, 0x57CEA99D, diff --git a/lib_lc3plus/rom_basop_util_lc3plus.h b/lib_lc3plus/rom_basop_util_lc3plus.h index b75637bc5..bde04fad3 100644 --- a/lib_lc3plus/rom_basop_util_lc3plus.h +++ b/lib_lc3plus/rom_basop_util_lc3plus.h @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,9 +7,11 @@ * estoppel or otherwise. * ******************************************************************************/ -#ifndef __ROM_BASOP_UTIL_LC3PLUS_H__ -#define __ROM_BASOP_UTIL_LC3PLUS_H__ +#ifndef __BASOP_UTIL_ROM_LC3PLUS_H__ +#define __BASOP_UTIL_ROM_LC3PLUS_H__ +#include "options.h" +#include "wmc_auto.h" #include "basop_util_lc3plus.h" #include "functions.h" @@ -33,22 +35,22 @@ /** * \brief Lookup-Table for binary logarithm */ -extern const Word16 ldCoeff_lc3plus[7]; +extern const Word16 ldCoeff[7]; /** \brief Lookup-Table for binary power algorithm */ -extern const UWord32 exp2_tab_long_lc3plus[32]; +extern const UWord32 exp2_tab_long[32]; /** \brief Lookup-Table for binary power algorithm */ -extern const UWord32 exp2w_tab_long_lc3plus[32]; +extern const UWord32 exp2w_tab_long[32]; /** \brief Lookup-Table for binary power algorithm */ -extern const UWord32 exp2x_tab_long_lc3plus[32]; +extern const UWord32 exp2x_tab_long[32]; /** * \brief 1/x, x=[0,1,2,3...] table @@ -167,4 +169,4 @@ extern const UWord16 rs16_elp_deg3_table[256]; extern const Word32 invSqrtTab[(128 + 2)]; #endif -#endif +#endif /* __BASOP_UTIL_ROM_LC3PLUS_H__ */ diff --git a/lib_lc3plus/scale_signal24_fx.c b/lib_lc3plus/scale_signal24_fx.c index e22b7c3f2..1cabd2bbf 100644 --- a/lib_lc3plus/scale_signal24_fx.c +++ b/lib_lc3plus/scale_signal24_fx.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,6 +7,8 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "functions.h" void scale_signal24_fx(Word32 x[], /* i: time input signal */ diff --git a/lib_lc3plus/setup_com_lc3plus.c b/lib_lc3plus/setup_com_lc3plus.c new file mode 100644 index 000000000..ce8a9ac66 --- /dev/null +++ b/lib_lc3plus/setup_com_lc3plus.c @@ -0,0 +1,39 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.6.1 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "options.h" +#include "wmc_auto.h" +#include "functions.h" + +#ifdef FIX_BOTH_1p25_WB_GLOBGAINOFFSET_NONBE +/* tilt factor in gainOffset quantized and adjusted for low Fs and 1p25ms framing */ +Word16 calc_GGainOffset_1p25_fx(Word16 total_bits, Word16 fs_idx) +{ + Word16 gain_off_tilt_1p25_Q19[6] = { 20480, 17408, 17476, 13107, 10486, 8738 }; /* vector for NB to UB */ + /* Corresponding FLT = gain_off_tilt_1p25 = {0.039062500000000 0.033203125000000 0.033333333333333 0.025000000000000 0.020000000000000 0.016666666666667 }*/ + + Word16 tmp1 = extract_h(L_shr_pos(L_mult0(total_bits, gain_off_tilt_1p25_Q19[fs_idx]), 3)); /* extract bits in Q0 , no rounding for interop*/ + Word16 tmp2 = extract_l(L_mac0(105L, 5, add(fs_idx, 1))); + + tmp2 = negate(add(s_min(115, tmp1), tmp2)); move16(); + + +#ifdef FIX_BOTH_1p25_WB_GLOBGAINOFFSET_LOWLIM_NONBE + if (sub(fs_idx, 1) <= 0) + { /* only NB and WB additionally limited to -135 */ + tmp2 = s_max(tmp2, FIX_BOTH_1p25_WB_GLOBGAINOFFSET_LOWLIM_NONBE); + } +#endif + + + return tmp2; +} +#endif + + diff --git a/lib_lc3plus/setup_dec_lc3.c b/lib_lc3plus/setup_dec_lc3plus.c similarity index 76% rename from lib_lc3plus/setup_dec_lc3.c rename to lib_lc3plus/setup_dec_lc3plus.c index 0435da50a..43512a4ea 100644 --- a/lib_lc3plus/setup_dec_lc3.c +++ b/lib_lc3plus/setup_dec_lc3plus.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,8 +7,10 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "functions.h" -#include "setup_dec_lc3.h" +#include "setup_dec_lc3plus.h" /* if decoder is null only size is reported */ /*assume 10ms for memory allocation for now */ @@ -78,14 +80,7 @@ int alloc_decoder(LC3PLUS_Dec *decoder, int samplerate, int channels) #else q_old_res_fx = balloc(decoder, &size, sizeof(*setup->q_old_res_fx) * MIN(max_len, MAX_BW)); #endif - -/* longterm_analysis_counter_max = PLC_LONGTERM_ANALYSIS_MS * (100.0f / 25.0f);*/ -/* assert(longterm_analysis_counter_max == (PLC_LONGTERM_ANALYSIS_MS * (100 /25))); */ /* test integer division for compatibility */ -/* longterm_analysis_counter_max_bytebuffer = floor(longterm_analysis_counter_max / 30.0); */ -/* assert(longterm_analysis_counter_max_bytebuffer == (longterm_analysis_counter_max / 30)); */ /* test integer division for compatibility */ -/* longterm_analysis_counter_max = (longterm_analysis_counter_max_bytebuffer+1) * 30; */ - longterm_analysis_counter_max = plc_fadeout_param_maxlen[0]; longterm_analysis_counter_max_bytebuffer = plc_fadeout_param_maxbytes[0]; @@ -151,7 +146,7 @@ LC3PLUS_Error FillDecSetup(LC3PLUS_Dec *decoder, int samplerate, int channels, L decoder->fs_out = samplerate; decoder->fs_idx = FS2FS_IDX(decoder->fs); decoder->channels = channels; - decoder->frame_dms = 100; + decoder->frame_dms = LC3PLUS_FRAME_DURATION_10MS; decoder->plcMeth = plc_mode; { decoder->BW_cutoff_bits = BW_cutoff_bits_all[decoder->fs_idx]; @@ -168,11 +163,32 @@ LC3PLUS_Error FillDecSetup(LC3PLUS_Dec *decoder, int samplerate, int channels, L setup->plc_damping = 32767; setup->ltpf_mem_scale_fac_idx = -1; move16(); + +#ifdef CR9_C_ADD_1p25MS +#ifdef CR9_C_ADD_1p25MS_LRSNS + setup->ltpfinfo_frame_cntr_fx = -32768; move16(); +#endif +#endif + + # ifdef CR9_C_ADD_1p25MS + # if 0 + /* @FhG @alex ToAddhere channel dependent :: setup->ltpf_mem_continuation = 0; */ + # endif + # ifdef CR9_C_ADD_1p25MS_LRSNS + setup->ltpfinfo_frame_cntr_fx = -32768; move16(); + # endif + # endif setup->pc_seed = 24607; setup->ns_seed = 24607; setup->ns_cum_alpha = 32767; +#ifdef CR9_C_ADD_1p25MS +#ifdef NEW_SIGNALLING_SCHEME_1p25 + setup->ltpfinfo_frame_cntr_fx = -32768; move16(); +#endif +#endif + int i = 0; /* 0 = 0kHz 1= 8kHz, 2= 16 kHz 3= 24 , 4 = 32 5=40 6=48kHz */ #if (PHECU_XFP_LA == 0) @@ -194,13 +210,12 @@ LC3PLUS_Error FillDecSetup(LC3PLUS_Dec *decoder, int samplerate, int channels, L mult(decoder->frame_length, (Word16)(32768.0 / 99.0)); /* truncation needed , i.e no rounding can be applied here */ /* idx=frame/80, 0=8kHZ, 1=16kHz, 2=24 kHz, 3=32 kHz 5=*, 4=48 */ - setup->plcAd->max_len_pcm_plc = DYN_MAX_LEN_PCM_PLC(decoder->fs); if ((decoder->hrmode == 0) && (samplerate <= 48000)) { setup->plcAd->PhECU_frame_ms = (Word16)( - decoder->frame_dms * 0.1); /* needed in PLCUpdate and PLC main functions, adjusted in first frame */ + decoder->frame_dms * 1.25 * 10 * 0.1); /* needed in PLCUpdate and PLC main functions, adjusted in first frame */ setup->plcAd->PhECU_seed_fx = 21845; setup->plcAd->PhECU_LprotOrg_fx = shl_pos(oneMsTab[setup->plcAd->PhECU_fs_idx_fx], 4); /* 16 *1ms = 1.6 *framelength */ @@ -250,6 +265,15 @@ void set_dec_frame_params(LC3PLUS_Dec *decoder) { Word16 tmp = 0; Word16 n; + +#ifndef FIX_TX_RX_STRUCT_STEREO +#ifdef CR9_C_ADD_1p25MS + decoder->ltpf_rx_status[0] = 0; + decoder->ltpf_rx_status[1] = 0; + decoder->ltpf_mem_continuation = 0; + decoder->ltpf_mem_active_prev = 0; +#endif +#endif decoder->frame_length = extract_l(L_shr_pos(Mpy_32_16_lc3plus(decoder->fs, 20972), 6)); /* fs * 0.01*2^6 */ @@ -262,7 +286,61 @@ void set_dec_frame_params(LC3PLUS_Dec *decoder) SWITCH (decoder->frame_dms) { - case 25: +#ifdef CR9_C_ADD_1p25MS + case LC3PLUS_FRAME_DURATION_1p25MS: + decoder->frame_length = shr_pos(decoder->frame_length, 3); + decoder->la_zeroes = 0; + decoder->stDec_ola_mem_fx_len = sub(decoder->frame_length, decoder->la_zeroes); + decoder->BW_cutoff_bits = 0; +#ifdef ENABLE_HR_MODE + if (decoder->hrmode) + { + assert(0); + } + else +#endif + { + decoder->bands_number = bands_number_1_25ms[decoder->fs_idx]; + decoder->bands_offset = bands_offset_1_25ms[decoder->fs_idx]; + decoder->W_fx = LowDelayShapes_n960_1_25ms[decoder->fs_idx]; + decoder->W_size = LowDelayShapes_n960_len_1_25ms[decoder->fs_idx]; + decoder->yLen = s_min(MAX_BW >> 3, decoder->frame_length); + } + +#ifdef ENABLE_HR_MODE + if (decoder->hrmode) + { + assert(0); + } + else +#endif + { + decoder->bands_number = bands_number_1_25ms[decoder->fs_idx]; + decoder->bands_offset = bands_offset_1_25ms[decoder->fs_idx]; + decoder->W_fx = LowDelayShapes_n960_1_25ms[decoder->fs_idx]; + decoder->W_size = LowDelayShapes_n960_len_1_25ms[decoder->fs_idx]; + decoder->yLen = s_min(MAX_BW >> 3, decoder->frame_length); + decoder->BW_cutoff_bits = -1; + } +#ifdef FIX_PLC_CONFORM_ISSUES + if (decoder->fs_idx == 0 || decoder->frame_length <= 20) +#else + if (decoder->fs_idx == 0) +#endif + { + int ch; + for (ch = 0; ch < decoder->channels; ch++) + { + DecSetup *setup = decoder->channel_setup[ch]; + if (setup->plcAd != NULL) + { + setup->plcAd->tdc_lpc_order = 8; + } + } + } + BREAK; +#endif + case LC3PLUS_FRAME_DURATION_2p5MS: decoder->frame_length = shr_pos(decoder->frame_length, 2); decoder->la_zeroes = LowDelayShapes_n960_la_zeroes_2_5ms[decoder->fs_idx]; decoder->stDec_ola_mem_fx_len = sub(decoder->frame_length, decoder->la_zeroes); @@ -286,7 +364,11 @@ void set_dec_frame_params(LC3PLUS_Dec *decoder) decoder->yLen = s_min(MAX_BW >> 2, decoder->frame_length); } +#ifdef FIX_PLC_CONFORM_ISSUES + if (decoder->fs_idx == 0 || decoder->frame_length <= 20) +#else if (decoder->fs_idx == 0) +#endif { int ch; for (ch = 0; ch < decoder->channels; ch++) @@ -299,7 +381,7 @@ void set_dec_frame_params(LC3PLUS_Dec *decoder) } } BREAK; - case 50: + case LC3PLUS_FRAME_DURATION_5MS: decoder->frame_length = shr_pos(decoder->frame_length, 1); decoder->la_zeroes = LowDelayShapes_n960_la_zeroes_5ms[decoder->fs_idx]; decoder->stDec_ola_mem_fx_len = sub(decoder->frame_length, decoder->la_zeroes); @@ -324,7 +406,7 @@ void set_dec_frame_params(LC3PLUS_Dec *decoder) } BREAK; - case 75: + case LC3PLUS_FRAME_DURATION_7p5MS: tmp = shr_pos(decoder->frame_length, 2); decoder->frame_length = add(tmp, add(tmp, tmp)); decoder->la_zeroes = LowDelayShapes_n960_la_zeroes_7_5ms[decoder->fs_idx]; @@ -349,7 +431,7 @@ void set_dec_frame_params(LC3PLUS_Dec *decoder) } BREAK; - case 100: + case LC3PLUS_FRAME_DURATION_10MS: decoder->la_zeroes = LowDelayShapes_n960_la_zeroes[decoder->fs_idx]; decoder->stDec_ola_mem_fx_len = sub(decoder->frame_length, decoder->la_zeroes); decoder->bands_number = 64; @@ -371,6 +453,8 @@ void set_dec_frame_params(LC3PLUS_Dec *decoder) decoder->yLen = s_min(MAX_BW, decoder->frame_length); } BREAK; + case LC3PLUS_FRAME_DURATION_UNDEFINED: + assert(0); } { @@ -380,15 +464,17 @@ void set_dec_frame_params(LC3PLUS_Dec *decoder) DecSetup *setup = decoder->channel_setup[ch]; if (setup->plcAd != NULL) { /*only set if plcAd was actually allocated */ - setup->plcAd->longterm_analysis_counter_max = plc_fadeout_param_maxlen[(decoder->frame_dms / 25) - 1]; - setup->plcAd->longterm_analysis_counter_max_bytebuffer = plc_fadeout_param_maxbytes[(decoder->frame_dms / 25) - 1]; + int idx = (decoder->frame_dms * 1.25 * 10 / 25) - 1; + setup->plcAd->longterm_analysis_counter_max = plc_fadeout_param_maxlen[idx]; + setup->plcAd->longterm_analysis_counter_max_bytebuffer = plc_fadeout_param_maxbytes[idx]; + setup->plcAd->PhECU_frame_ms = (Word16)( - decoder->frame_dms * + decoder->frame_dms * 1.25 * 10 * 0.1); /* needed in processPLCupdate_fx(), now set properly set in first frame /second time */ } } } - FOR (n=0; n < PLC_FADEOUT_TYPE_1_IN_MS*10/decoder->frame_dms;n++){ + FOR (n=0; n < PLC_FADEOUT_TYPE_1_IN_MS*10/(decoder->frame_dms*1.25*10);n++){ decoder->alpha_type_2_table[n] = type_2_fadeout_fx(n, decoder->frame_dms); } } @@ -397,7 +483,7 @@ LC3PLUS_Error update_dec_bitrate(LC3PLUS_Dec *decoder, int ch, Word16 nBytes) { int tmp = 0, totalBits = 0; int channel_bytes = 0; - int minBytes, maxBytes; + int minBytes = 0, maxBytes = 0; DecSetup *setup = decoder->channel_setup[ch]; channel_bytes = nBytes; @@ -407,23 +493,29 @@ LC3PLUS_Error update_dec_bitrate(LC3PLUS_Dec *decoder, int ch, Word16 nBytes) { SWITCH (decoder->frame_dms) { - case 25: - maxBytes = 210; - minBytes = MIN_NBYTES; - BREAK; - case 50: - maxBytes = 375; - minBytes = MIN_NBYTES; - BREAK; - case 75: - maxBytes = 625; - minBytes = MIN_NBYTES; - BREAK; - case 100: - maxBytes = 625; - minBytes = MIN_NBYTES; - BREAK; - default: return LC3PLUS_HRMODE_ERROR; +#ifdef CR9_C_ADD_1p25MS + case LC3PLUS_FRAME_DURATION_1p25MS: + maxBytes = 210; + minBytes = MIN_NBYTES; + BREAK; +#endif + case LC3PLUS_FRAME_DURATION_2p5MS: + maxBytes = 210; + minBytes = MIN_NBYTES; + BREAK; + case LC3PLUS_FRAME_DURATION_5MS: + maxBytes = 375; + minBytes = MIN_NBYTES; + BREAK; + case LC3PLUS_FRAME_DURATION_7p5MS: + maxBytes = 625; + minBytes = MIN_NBYTES; + BREAK; + case LC3PLUS_FRAME_DURATION_10MS: + maxBytes = 625; + minBytes = MIN_NBYTES; + BREAK; + case LC3PLUS_FRAME_DURATION_UNDEFINED: return LC3PLUS_HRMODE_ERROR; } } else @@ -442,9 +534,24 @@ LC3PLUS_Error update_dec_bitrate(LC3PLUS_Dec *decoder, int ch, Word16 nBytes) move16(); setup->total_bits = shl(setup->targetBytes, 3); setup->enable_lpc_weighting = (setup->total_bits < 480); + + +#ifdef FIX_BOTH_1p25_WB_GLOBGAINOFFSET_NONBE + IF(decoder->frame_dms == LC3PLUS_FRAME_DURATION_1p25MS) + { + setup->quantizedGainOff = calc_GGainOffset_1p25_fx(setup->total_bits, decoder->fs_idx); /* enc/dec common function */ + } + ELSE + { + setup->quantizedGainOff = + -(s_min(115, setup->total_bits / (10 * (decoder->fs_idx + 1))) + 105 + 5 * (decoder->fs_idx + 1)); + } +#else setup->quantizedGainOff = -(s_min(115, setup->total_bits / (10 * (decoder->fs_idx + 1))) + 105 + 5 * (decoder->fs_idx + 1)); - tmp = DEPR_i_mult(80, decoder->fs_idx); +#endif + + #ifdef ENABLE_HR_MODE if (decoder->hrmode && decoder->fs_idx == 5) @@ -452,30 +559,39 @@ LC3PLUS_Error update_dec_bitrate(LC3PLUS_Dec *decoder, int ch, Word16 nBytes) setup->quantizedGainOff = MAX(setup->quantizedGainOff, -181); } #endif - - totalBits = setup->total_bits; + tmp = i_mult(80, decoder->fs_idx); + + totalBits = setup->total_bits; SWITCH (decoder->frame_dms) { - case 25: - setup->enable_lpc_weighting = 0; - /* total_bits * 2.4 */ - totalBits = extract_l(L_shr(L_mult0(19661, setup->total_bits), 13)); - BREAK; - case 50: - setup->enable_lpc_weighting = setup->total_bits < 240; - totalBits = sub(DEPR_i_mult(setup->total_bits, 2), 160); - BREAK; - case 75: - setup->enable_lpc_weighting = setup->total_bits < 360; - totalBits = L_shr(L_mult0(10923, setup->total_bits), 13); - BREAK; - case 100: - BREAK; +#ifdef CR9_C_ADD_1p25MS + case LC3PLUS_FRAME_DURATION_1p25MS: + setup->enable_lpc_weighting = 0; + /* total_bits * 3.36 */ + totalBits = extract_l(L_shr(L_mult0(27526, setup->total_bits), 13)); + BREAK; +#endif + case LC3PLUS_FRAME_DURATION_2p5MS: + setup->enable_lpc_weighting = 0; + /* total_bits * 2.4 */ + totalBits = extract_l(L_shr(L_mult0(19661, setup->total_bits), 13)); + BREAK; + case LC3PLUS_FRAME_DURATION_5MS: + setup->enable_lpc_weighting = setup->total_bits < 240; + totalBits = sub(i_mult(setup->total_bits, 2), 160); + BREAK; + case LC3PLUS_FRAME_DURATION_7p5MS: + setup->enable_lpc_weighting = setup->total_bits < 360; + totalBits = L_shr(L_mult0(10923, setup->total_bits), 13); + BREAK; + case LC3PLUS_FRAME_DURATION_10MS: + BREAK; + case LC3PLUS_FRAME_DURATION_UNDEFINED: + assert(0); } - if (sub(totalBits, add(320, tmp)) < 0) { setup->ltpf_scale_fac_idx = 0; diff --git a/lib_lc3plus/setup_dec_lc3.h b/lib_lc3plus/setup_dec_lc3plus.h similarity index 79% rename from lib_lc3plus/setup_dec_lc3.h rename to lib_lc3plus/setup_dec_lc3plus.h index c1c556f5d..e2c35ec45 100644 --- a/lib_lc3plus/setup_dec_lc3.h +++ b/lib_lc3plus/setup_dec_lc3plus.h @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -10,6 +10,8 @@ #ifndef SETUP_DEC_LC3_H #define SETUP_DEC_LC3_H +#include "options.h" +#include "wmc_auto.h" #include "constants.h" typedef struct @@ -36,7 +38,7 @@ typedef struct Word16 PhECU_LprotOrg_fx; /* needed to change the Prot size adaptively */ Word16 PhECU_Lprot_fx; Word16 PhECU_fs_idx_fx; - Word16 PhECU_frame_ms; /* needed in PLC_Update and PLCMain functons*/ + Word16 PhECU_frame_ms; /* needed in PLC_Update and PLCMain functons*/ Word16 PhECU_seed_fx; Word16 PhECU_xfp_exp_fx; Word16 PhECU_time_offs; @@ -55,17 +57,17 @@ typedef struct Word16 max_len_pcm_plc; Word16 max_lprot; Word16 max_plocs; - - /* Word32 L_tot W_energy sum exponent */ - Word16 PhECU_oold_Ltot_exp_fx; + + /* Word32 L_tot W_energy sum exponent */ + Word16 PhECU_oold_Ltot_exp_fx; Word16 PhECU_old_Ltot_exp_fx; Word32 PhECU_L_oold_xfp_w_E_fx; Word32 PhECU_L_old_xfp_w_E_fx; Word16 PhECU_oold_xfp_w_E_exp_fx; /* input Word16 xfp exponnet */ - Word16 PhECU_old_xfp_w_E_exp_fx; + Word16 PhECU_old_xfp_w_E_exp_fx; Word16 PhECU_oold_grp_shape_fx[MAX_LGW]; Word16 PhECU_old_grp_shape_fx[MAX_LGW]; - Word16 PhECU_margin_xfp; + Word16 PhECU_margin_xfp; Word16 PhECU_nonpure_tone_flag; /* non-pure single tone indicator state */ Word16 PhECU_mag_chg_1st[MAX_LGW]; Word16 PhECU_Xavg[MAX_LGW]; @@ -73,7 +75,7 @@ typedef struct Word16 old_old_scf_q[M]; Word16 tdc_A[M + 1]; /* for now 20 ms saved Q14 or ptr to a combined ifft win and MDCT preTDA synthesis window 16 ms */ - + Word16 longterm_counter_plcTdc; Word16 longterm_counter_plcNsAdv; Word16 longterm_analysis_counter_max; /* Maximum longterm frames number */ @@ -84,6 +86,9 @@ typedef struct Word16 overall_counter; Word8 longterm_counter_byte_position; Word8 longterm_counter_bit_position; +#ifdef CR13_C_RESET_CLASSIFIER_AFTER_BAD_FRAMES + Word16 numberOfGoodFrames; +#endif } AplcSetup; /* Channel state and bitrate-derived values go in this struct */ @@ -128,6 +133,21 @@ typedef struct Word16 plc_damping; Word16 last_size; Word32 rel_pitch_change; +#ifdef CR9_C_ADD_1p25MS +#ifdef FIX_TX_RX_STRUCT_STEREO + Word16 ltpf_rx_status[2]; +#endif + Word16 ltpf_mem_continuation; + Word16 ltpf_mem_active_prev; + Word16 ltpf_mem_pitch_int_prev; + Word16 ltpf_mem_pitch_fr_prev; + Word16 ltpf_mem_beta_idx_prev; + Word16 ltpf_mem_gain_prev; + Word16 ltpf_pitch_stability_counter; +#ifdef NEW_SIGNALLING_SCHEME_1p25 + Word16 ltpfinfo_frame_cntr_fx; /* individual cntr for each channel*/ +#endif +#endif } DecSetup; /* Constants and sampling rate derived values go in this struct */ @@ -146,7 +166,7 @@ struct LC3PLUS_Dec Word16 frame_length; /* sampling rate index */ Word16 channels; /* number of channels */ Word16 plcMeth; /* PLC method for all channels */ - Word16 frame_dms; /* frame length in dms (decimilliseconds, 10^-4)*/ + LC3PLUS_FrameDuration frame_dms; /* frame length in dms (decimilliseconds, 10^-4)*/ Word16 last_size; /* size of last frame, without error protection */ Word16 ep_enabled; /* error protection enabled */ Word16 error_report; /* corrected errors in last frame or -1 on error */ @@ -168,7 +188,19 @@ struct LC3PLUS_Dec Word16 ltpf_mem_y_len; Word16 BW_cutoff_bits; Word16 hrmode; - Word16 alpha_type_2_table[80];/* PLC_FADEOUT_TYPE_1_IN_MS*10/25 */ + Word16 alpha_type_2_table[160];/* PLC_FADEOUT_TYPE_1_IN_MS*100/125 */ +#ifndef FIX_TX_RX_STRUCT_STEREO +#ifdef CR9_C_ADD_1p25MS + Word16 ltpf_rx_status[2]; + Word16 ltpf_mem_continuation; + Word16 ltpf_mem_active_prev; + Word16 ltpf_mem_pitch_int_prev; + Word16 ltpf_mem_pitch_fr_prev; + Word16 ltpf_mem_beta_idx_prev; + Word16 ltpf_mem_gain_prev; + Word16 ltpf_pitch_stability_counter; +#endif +#endif }; -#endif +#endif /* SETUP_DEC_LC3_H */ diff --git a/lib_lc3plus/setup_enc_lc3.c b/lib_lc3plus/setup_enc_lc3plus.c similarity index 67% rename from lib_lc3plus/setup_enc_lc3.c rename to lib_lc3plus/setup_enc_lc3plus.c index 563734358..92c668912 100644 --- a/lib_lc3plus/setup_enc_lc3.c +++ b/lib_lc3plus/setup_enc_lc3plus.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,8 +7,10 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "functions.h" -#include "setup_enc_lc3.h" +#include "setup_enc_lc3plus.h" /* if encoder is null only size is reported */ int alloc_encoder(LC3PLUS_Enc *encoder, int samplerate, int channels) @@ -58,8 +60,11 @@ LC3PLUS_Error FillEncSetup(LC3PLUS_Enc *encoder, int samplerate, int channels #endif encoder->channels = channels; - encoder->frame_dms = 100; + encoder->frame_dms = LC3PLUS_FRAME_DURATION_10MS; encoder->envelope_bits = 38; + #ifdef CR9_C_ADD_1p25MS_LRSNS + /* "38" SNS bit constant kept here, final LR-SNS bitrate adjusted in enc_lc3() after LR-SNSVQ */ +#endif /* CR9_C_ADD_1p25MS_LRSNS */ encoder->global_gain_bits = 8; encoder->noise_fac_bits = 3; encoder->r12k8_mem_in_len = extract_l(L_shr_pos(Mpy_32_16_lc3plus(encoder->fs, 20972), 9)); @@ -92,6 +97,12 @@ LC3PLUS_Error FillEncSetup(LC3PLUS_Enc *encoder, int samplerate, int channels void set_enc_frame_params(LC3PLUS_Enc *encoder) { Word16 tmp; +#ifdef CR9_C_ADD_1p25MS +#ifndef FIX_TX_RX_STRUCT_STEREO + encoder->Tx_ltpf = 0; +#endif + encoder->LT_normcorr = 0xFFFF >> 2; +#endif encoder->frame_length = extract_l(L_shr_pos(Mpy_32_16_lc3plus(encoder->fs, 20972), 6)); /* fs * 0.01*2^6 */ @@ -108,12 +119,50 @@ void set_enc_frame_params(LC3PLUS_Enc *encoder) SWITCH (encoder->frame_dms) { - case 25: +#ifdef CR9_C_ADD_1p25MS + case LC3PLUS_FRAME_DURATION_1p25MS: + encoder->BW_cutoff_bits = 0; + encoder->frame_length = shr_pos(encoder->frame_length, 3); + encoder->la_zeroes = 0; + encoder->stEnc_mdct_mem_len = sub(encoder->frame_length, encoder->la_zeroes); + encoder->nSubdivisions = 0; +#ifdef FIX_LTPF_PITCH_MEM_LEN + encoder->ltpf_mem_in_len = LTPF_MEMIN_LEN + 112; +#else + encoder->ltpf_mem_in_len = LTPF_MEMIN_LEN + ( LEN_12K8 >> 1 ) + 16; +#endif + encoder->r12k8_mem_out_len = 8; +#ifndef CR9_C_ADD_1p25MS_NOISEFILLING + encoder->noise_fac_bits = 0; +#endif +#ifdef ENABLE_HR_MODE + if (encoder->hrmode) + { + assert(0); + } + else +#endif + { + encoder->yLen = s_min(MAX_BW >> 3, encoder->frame_length); + encoder->W_fx = LowDelayShapes_n960_1_25ms[encoder->fs_idx]; + encoder->W_size = LowDelayShapes_n960_len_1_25ms[encoder->fs_idx]; + encoder->bands_number = bands_number_1_25ms[encoder->fs_idx]; + encoder->bands_offset = bands_offset_1_25ms[encoder->fs_idx]; + encoder->near_nyquist_index = encoder->bands_number - 2; + encoder->near_nyquist_flag = 0; + } + BREAK; +#endif + case LC3PLUS_FRAME_DURATION_2p5MS: encoder->frame_length = shr_pos(encoder->frame_length, 2); encoder->la_zeroes = LowDelayShapes_n960_la_zeroes_2_5ms[encoder->fs_idx]; encoder->stEnc_mdct_mem_len = sub(encoder->frame_length, encoder->la_zeroes); encoder->nSubdivisions = 2; - encoder->ltpf_mem_in_len = LTPF_MEMIN_LEN + (LEN_12K8 >> 2); +#ifdef FIX_LTPF_PITCH_MEM_LEN + encoder->ltpf_mem_in_len = LTPF_MEMIN_LEN + 96; +#else + encoder->ltpf_mem_in_len = LTPF_MEMIN_LEN + ( LEN_12K8 >> 2 ); +#endif #ifdef ENABLE_HR_MODE if (encoder->hrmode) @@ -137,12 +186,16 @@ void set_enc_frame_params(LC3PLUS_Enc *encoder) } BREAK; - case 50: + case LC3PLUS_FRAME_DURATION_5MS: encoder->frame_length = shr_pos(encoder->frame_length, 1); encoder->la_zeroes = LowDelayShapes_n960_la_zeroes_5ms[encoder->fs_idx]; encoder->stEnc_mdct_mem_len = sub(encoder->frame_length, encoder->la_zeroes); encoder->nSubdivisions = 2; - encoder->ltpf_mem_in_len = LTPF_MEMIN_LEN + (LEN_12K8 >> 1); +#ifdef FIX_LTPF_PITCH_MEM_LEN + encoder->ltpf_mem_in_len = LTPF_MEMIN_LEN + 64; +#else + encoder->ltpf_mem_in_len = LTPF_MEMIN_LEN + ( LEN_12K8 >> 1 ); +#endif #ifdef ENABLE_HR_MODE if (encoder->hrmode) @@ -164,10 +217,9 @@ void set_enc_frame_params(LC3PLUS_Enc *encoder) encoder->near_nyquist_index = encoder->bands_number - 3; encoder->near_nyquist_flag = 0; } - encoder->ltpf_mem_in_len = LTPF_MEMIN_LEN; BREAK; - case 75: + case LC3PLUS_FRAME_DURATION_7p5MS: tmp = shr_pos(encoder->frame_length, 2); encoder->frame_length = add(tmp, add(tmp, tmp)); encoder->la_zeroes = LowDelayShapes_n960_la_zeroes_7_5ms[encoder->fs_idx]; @@ -201,7 +253,7 @@ void set_enc_frame_params(LC3PLUS_Enc *encoder) } BREAK; - case 100: + case LC3PLUS_FRAME_DURATION_10MS: encoder->la_zeroes = LowDelayShapes_n960_la_zeroes[encoder->fs_idx]; encoder->stEnc_mdct_mem_len = sub(encoder->frame_length, encoder->la_zeroes); encoder->bands_number = 64; @@ -230,6 +282,8 @@ void set_enc_frame_params(LC3PLUS_Enc *encoder) encoder->bands_offset = bands_offset[encoder->fs_idx]; } BREAK; + case LC3PLUS_FRAME_DURATION_UNDEFINED: + assert(0); } } @@ -240,12 +294,17 @@ LC3PLUS_Error update_enc_bitrate(LC3PLUS_Enc *encoder, int bitrate) int totalBytes = 0, maxBR = 0, minBR = 0, max_bytes = 0; int channel_bytes = 0; +#ifdef CR12_D_FIX_BITRATE_LIMITS + int fec_slot_bytes_min = 0, check_bytes = 0; +#endif #ifdef ENABLE_HR_MODE if (encoder->hrmode) { - switch (encoder->frame_dms) + SWITCH (encoder->frame_dms) { - case 25: +#ifdef CR9_C_ADD_1p25MS + case LC3PLUS_FRAME_DURATION_1p25MS: + assert(0); maxBR = 672000; if (encoder->fs == 48000) { @@ -260,7 +319,23 @@ LC3PLUS_Error update_enc_bitrate(LC3PLUS_Enc *encoder, int bitrate) return LC3PLUS_HRMODE_ERROR; } break; - case 50: +#endif + case LC3PLUS_FRAME_DURATION_2p5MS: + maxBR = 672000; + if (encoder->fs == 48000) + { + minBR = MIN_BR_25MS_48KHZ_HR; + } + else if (encoder->fs == 96000) + { + minBR = MIN_BR_25MS_96KHZ_HR; + } + else + { + return LC3PLUS_HRMODE_ERROR; + } + break; + case LC3PLUS_FRAME_DURATION_5MS: maxBR = 600000; if (encoder->fs == 48000) { @@ -275,13 +350,13 @@ LC3PLUS_Error update_enc_bitrate(LC3PLUS_Enc *encoder, int bitrate) return LC3PLUS_HRMODE_ERROR; } break; - case 75: + case LC3PLUS_FRAME_DURATION_7p5MS: maxBR = 500000; if (encoder->fs == 48000) {minBR = MIN_BR_075DMS_48KHZ_HR;} else if (encoder->fs == 96000) {minBR = MIN_BR_075DMS_96KHZ_HR;} else {return LC3PLUS_HRMODE_ERROR;} BREAK; - case 100: + case LC3PLUS_FRAME_DURATION_10MS: maxBR = 500000; if (encoder->fs == 48000) { @@ -296,7 +371,7 @@ LC3PLUS_Error update_enc_bitrate(LC3PLUS_Enc *encoder, int bitrate) return LC3PLUS_HRMODE_ERROR; } break; - default: return LC3PLUS_HRMODE_ERROR; + case LC3PLUS_FRAME_DURATION_UNDEFINED: return LC3PLUS_HRMODE_ERROR; } } else @@ -304,13 +379,19 @@ LC3PLUS_Error update_enc_bitrate(LC3PLUS_Enc *encoder, int bitrate) minBR = (MIN_NBYTES << 3); maxBR = MAX_BR; - switch (encoder->frame_dms) + SWITCH (encoder->frame_dms) { - case 25: +#ifdef CR9_C_ADD_1p25MS + case LC3PLUS_FRAME_DURATION_1p25MS: + minBR = MIN_BR_0125DMS; + maxBR = MAX_BR_0125DMS; + BREAK; +#endif + case LC3PLUS_FRAME_DURATION_2p5MS: minBR = MIN_BR_025DMS; maxBR = MAX_BR; BREAK; - case 50: + case LC3PLUS_FRAME_DURATION_5MS: minBR = MIN_BR_050DMS; maxBR = MAX_BR; /* have additional limitations for 5.0ms */ @@ -322,7 +403,7 @@ LC3PLUS_Error update_enc_bitrate(LC3PLUS_Enc *encoder, int bitrate) default: BREAK; } BREAK; - case 75: + case LC3PLUS_FRAME_DURATION_7p5MS: minBR = MIN_BR_075DMS; maxBR = MAX_BR_075DMS; // special value for maxBR @ 7.5ms /* have additional limitations for 7.5ms */ @@ -340,7 +421,7 @@ LC3PLUS_Error update_enc_bitrate(LC3PLUS_Enc *encoder, int bitrate) default: BREAK; } BREAK; - case 100: + case LC3PLUS_FRAME_DURATION_10MS: /* have additional limitations for 10ms */ minBR = MIN_BR_100DMS; maxBR = MAX_BR; @@ -358,7 +439,7 @@ LC3PLUS_Error update_enc_bitrate(LC3PLUS_Enc *encoder, int bitrate) default: maxBR = MAX_BR; BREAK; } BREAK; - default: return LC3PLUS_FRAMEMS_ERROR; + case LC3PLUS_FRAME_DURATION_UNDEFINED: return LC3PLUS_FRAMEMS_ERROR; } /* 441/480 in Q31 and 1000/75 in Q23 */ @@ -372,13 +453,19 @@ LC3PLUS_Error update_enc_bitrate(LC3PLUS_Enc *encoder, int bitrate) minBR = (MIN_NBYTES << 3); maxBR = MAX_BR; - switch (encoder->frame_dms) + SWITCH (encoder->frame_dms) { - case 25: +#ifdef CR9_C_ADD_1p25MS + case LC3PLUS_FRAME_DURATION_1p25MS: + minBR = MIN_BR_0125DMS; + maxBR = MAX_BR_0125DMS; + BREAK; +#endif + case LC3PLUS_FRAME_DURATION_2p5MS: minBR = MIN_BR_025DMS; maxBR = MAX_BR; BREAK; - case 50: + case LC3PLUS_FRAME_DURATION_5MS: minBR = MIN_BR_050DMS; maxBR = MAX_BR; /* have additional limitations for 5.0ms */ @@ -390,7 +477,7 @@ LC3PLUS_Error update_enc_bitrate(LC3PLUS_Enc *encoder, int bitrate) default: BREAK; } BREAK; - case 75: + case LC3PLUS_FRAME_DURATION_7p5MS: minBR = MIN_BR_075DMS; maxBR = MAX_BR_075DMS; // special value for maxBR @ 7.5ms /* have additional limitations for 7.5ms */ @@ -408,7 +495,7 @@ LC3PLUS_Error update_enc_bitrate(LC3PLUS_Enc *encoder, int bitrate) default: BREAK; } BREAK; - case 100: + case LC3PLUS_FRAME_DURATION_10MS: /* have additional limitations for 10ms */ minBR = MIN_BR_100DMS; maxBR = MAX_BR; @@ -426,7 +513,7 @@ LC3PLUS_Error update_enc_bitrate(LC3PLUS_Enc *encoder, int bitrate) default: maxBR = MAX_BR; BREAK; } BREAK; - default: return LC3PLUS_FRAMEMS_ERROR; + case LC3PLUS_FRAME_DURATION_UNDEFINED: return LC3PLUS_FRAMEMS_ERROR; } /* 441/480 in Q31 and 1000/75 in Q23 */ @@ -461,9 +548,56 @@ LC3PLUS_Error update_enc_bitrate(LC3PLUS_Enc *encoder, int bitrate) if (encoder->epmode > 0) { - max_bytes = bitrate * encoder->frame_length / (8 * encoder->fs_in * encoder->channels); +#ifdef CR12_D_FIX_BITRATE_LIMITS +#ifdef ENABLE_HR_MODE + if (encoder->hrmode){ + SWITCH( encoder->frame_dms ) + { + case LC3PLUS_FRAME_DURATION_2p5MS: + IF( encoder->fs_in == 48000){ + fec_slot_bytes_min = FEC_SLOT_BYTES_MIN_025DMS_48KHZ_HR; + } ELSE { + fec_slot_bytes_min = FEC_SLOT_BYTES_MIN_025DMS_96KHZ_HR; + } + BREAK; + case LC3PLUS_FRAME_DURATION_5MS: + IF( encoder->fs_in == 48000){ + fec_slot_bytes_min = FEC_SLOT_BYTES_MIN_050DMS_48KHZ_HR; + } ELSE { + fec_slot_bytes_min = FEC_SLOT_BYTES_MIN_050DMS_96KHZ_HR; + } + BREAK; + case LC3PLUS_FRAME_DURATION_7p5MS: + IF( encoder->fs_in == 48000){ + fec_slot_bytes_min = FEC_SLOT_BYTES_MIN_075DMS_48KHZ_HR; + } ELSE { + fec_slot_bytes_min = FEC_SLOT_BYTES_MIN_075DMS_96KHZ_HR; + } + BREAK; + case LC3PLUS_FRAME_DURATION_10MS: + IF( encoder->fs_in == 48000){ + fec_slot_bytes_min = FEC_SLOT_BYTES_MIN_100DMS_48KHZ_HR; + } ELSE { + fec_slot_bytes_min = FEC_SLOT_BYTES_MIN_100DMS_96KHZ_HR; + } + BREAK; + default: + return LC3PLUS_FRAMEMS_ERROR; + } + } + else +#endif + { + fec_slot_bytes_min = FEC_SLOT_BYTES_MIN; + } + check_bytes = bitrate * encoder->frame_length / ( 8 * encoder->fs_in * encoder->channels ); + maxBR = FEC_SLOT_BYTES_MAX * ( 8 * encoder->fs_in * encoder->channels ) / encoder->frame_length; + if ( check_bytes < fec_slot_bytes_min || bitrate > maxBR ) +#else + max_bytes = bitrate * encoder->frame_length / (8 * encoder->fs_in * encoder->channels); if (max_bytes < FEC_SLOT_BYTES_MIN || max_bytes > FEC_SLOT_BYTES_MAX) +#endif /* CR12_D_FIX_BITRATE_LIMITS */ { return LC3PLUS_BITRATE_ERROR; } @@ -502,7 +636,7 @@ LC3PLUS_Error update_enc_bitrate(LC3PLUS_Enc *encoder, int bitrate) setup->n_pc = fec_get_n_pc(encoder->epmode, setup->n_pccw, channel_bytes); } /* reduce bandwith to 12kHz if bitrate is low */ - if (sub(encoder->frame_dms, 100) == 0 && + if (sub(encoder->frame_dms, LC3PLUS_FRAME_DURATION_10MS) == 0 && ((sub(setup->targetBytes, 40) < 0 && L_sub(encoder->fs, 48000) == 0) || (sub(setup->targetBytes, 36) < 0 && L_sub(encoder->fs, 32000) == 0))) { @@ -516,26 +650,34 @@ LC3PLUS_Error update_enc_bitrate(LC3PLUS_Enc *encoder, int bitrate) } { - Word16 tmp; + Word16 tmp = 0; SWITCH(encoder->frame_dms) { - case 25: tmp = 1; BREAK; - case 50: tmp = 2; BREAK; - case 75: tmp = 3; BREAK; - default : tmp = 4; BREAK; +#ifdef CR9_C_ADD_1p25MS + case LC3PLUS_FRAME_DURATION_1p25MS: tmp = 1; BREAK; +#endif + case LC3PLUS_FRAME_DURATION_2p5MS: tmp = 2; BREAK; + case LC3PLUS_FRAME_DURATION_5MS: tmp = 4; BREAK; + case LC3PLUS_FRAME_DURATION_7p5MS: tmp = 6; BREAK; + case LC3PLUS_FRAME_DURATION_10MS: tmp = 8; BREAK; + case LC3PLUS_FRAME_DURATION_UNDEFINED: assert(0); } - encoder->bw_ctrl_cutoff_bin = L_mult0(Mpy_32_32_lc3plus(encoder->bandwidth, 10737419), tmp); /* bandwidth * frame_dms / 5000 */ + encoder->bw_ctrl_cutoff_bin = L_mult0(Mpy_32_32_lc3plus(encoder->bandwidth, 10737420>>1), tmp); /* bandwidth * frame_dms / 5000 */ } encoder->bw_index = sub( Mpy_32_32_lc3plus(encoder->bandwidth, 536871), 1); /* (bandwidth / 4000 ) - 1 */ - switch (encoder->frame_dms) + SWITCH (encoder->frame_dms) { - case 25: max_bytes = MAX_NBYTES_025; break; - case 50: max_bytes = MAX_NBYTES_050; break; - case 75: max_bytes = MAX_NBYTES_075; BREAK; - case 100: max_bytes = MAX_NBYTES_100; break; +#ifdef CR9_C_ADD_1p25MS + case LC3PLUS_FRAME_DURATION_1p25MS: max_bytes = MAX_NBYTES_025; break; +#endif + case LC3PLUS_FRAME_DURATION_2p5MS: max_bytes = MAX_NBYTES_025; break; + case LC3PLUS_FRAME_DURATION_5MS: max_bytes = MAX_NBYTES_050; break; + case LC3PLUS_FRAME_DURATION_7p5MS: max_bytes = MAX_NBYTES_075; BREAK; + case LC3PLUS_FRAME_DURATION_10MS: max_bytes = MAX_NBYTES_100; break; + case LC3PLUS_FRAME_DURATION_UNDEFINED: assert(0); } #ifdef ENABLE_HR_MODE if (encoder->hrmode) @@ -553,7 +695,7 @@ LC3PLUS_Error update_enc_bitrate(LC3PLUS_Enc *encoder, int bitrate) sub(setup->total_bits, add(encoder->envelope_bits, add(encoder->global_gain_bits, add(encoder->noise_fac_bits, encoder->BW_cutoff_bits)))); - setup->targetBitsInit = sub(setup->targetBitsInit, sub(17, norm_s(sub(encoder->yLen, 1)))); + setup->targetBitsInit = sub(setup->targetBitsInit, getLastNzBits_fx (encoder->frame_length) + 3); if (setup->total_bits > 1280) { setup->targetBitsInit = sub(setup->targetBitsInit, 1); @@ -574,29 +716,52 @@ LC3PLUS_Error update_enc_bitrate(LC3PLUS_Enc *encoder, int bitrate) SWITCH (encoder->frame_dms) { - case 25: - /* 9830 = 2.4 * 2^12 */ - setup->ltpf_enable = - sub(extract_l(L_shr(L_mult0(9830, setup->total_bits), 12)), add(560, DEPR_i_mult(80, encoder->fs_idx))) < 0; - setup->enable_lpc_weighting = 0; - BREAK; - case 50: - setup->ltpf_enable = sub(sub(DEPR_i_mult(setup->total_bits, 2), 160), add(560, DEPR_i_mult(80, encoder->fs_idx))) < 0; - setup->enable_lpc_weighting = setup->total_bits < 240; - BREAK; - case 75: - setup->ltpf_enable = sub(L_shr(L_mult0(10923, setup->total_bits), 13), add(560, DEPR_i_mult(80, encoder->fs_idx))) < 0; - setup->enable_lpc_weighting = setup->total_bits < 360; - BREAK; - case 100: - setup->enable_lpc_weighting = setup->total_bits < 480; - setup->ltpf_enable = sub(setup->total_bits, add(560, DEPR_i_mult(80, encoder->fs_idx))) < 0; - BREAK; - } +#ifdef CR9_C_ADD_1p25MS + case LC3PLUS_FRAME_DURATION_1p25MS: + /* 13763 = 3.36 * 2^12 */ + setup->ltpf_enable = + sub(extract_l(L_shr(L_mult0(13763, setup->total_bits), 12)), add(560, i_mult(80, encoder->fs_idx))) < 0; + setup->enable_lpc_weighting = 0; + BREAK; +#endif + case LC3PLUS_FRAME_DURATION_2p5MS: + /* 9830 = 2.4 * 2^12 */ + setup->ltpf_enable = + sub(extract_l(L_shr(L_mult0(9830, setup->total_bits), 12)), add(560, i_mult(80, encoder->fs_idx))) < 0; + setup->enable_lpc_weighting = 0; + BREAK; + case LC3PLUS_FRAME_DURATION_5MS: + setup->ltpf_enable = sub(sub(i_mult(setup->total_bits, 2), 160), add(560, i_mult(80, encoder->fs_idx))) < 0; + setup->enable_lpc_weighting = setup->total_bits < 240; + BREAK; + case LC3PLUS_FRAME_DURATION_7p5MS: + setup->ltpf_enable = sub(L_shr(L_mult0(10923, setup->total_bits), 13), add(560, i_mult(80, encoder->fs_idx))) < 0; + setup->enable_lpc_weighting = setup->total_bits < 360; + BREAK; + case LC3PLUS_FRAME_DURATION_10MS: + setup->enable_lpc_weighting = setup->total_bits < 480; + setup->ltpf_enable = sub(setup->total_bits, add(560, i_mult(80, encoder->fs_idx))) < 0; + BREAK; + case LC3PLUS_FRAME_DURATION_UNDEFINED: + assert(0); + } + +#ifdef FIX_BOTH_1p25_WB_GLOBGAINOFFSET_NONBE + IF(encoder->frame_dms == LC3PLUS_FRAME_DURATION_1p25MS) + { + setup->quantizedGainOff = calc_GGainOffset_1p25_fx(setup->total_bits, encoder->fs_idx); /* enc/dec common function */ + } + ELSE + { + setup->quantizedGainOff = + -(s_min(115, setup->total_bits / (10 * (encoder->fs_idx + 1))) + 105 + 5 * (encoder->fs_idx + 1)); + } +#else setup->quantizedGainOff = -(s_min(115, setup->total_bits / (10 * (encoder->fs_idx + 1))) + 105 + 5 * (encoder->fs_idx + 1)); - +#endif + #ifdef ENABLE_HR_MODE if (encoder->hrmode && encoder->fs_idx == 5) { @@ -605,13 +770,13 @@ LC3PLUS_Error update_enc_bitrate(LC3PLUS_Enc *encoder, int bitrate) #endif #ifdef ENABLE_HR_MODE - if (encoder->frame_dms == 100 && + if (encoder->frame_dms == LC3PLUS_FRAME_DURATION_10MS && ((encoder->fs_in >= 44100 && setup->targetBytes >= 100) || (encoder->fs_in == 32000 && setup->targetBytes >= 81)) && setup->targetBytes < 340 && (encoder->hrmode == 0)) #else - if (encoder->frame_dms == 100 && + if (encoder->frame_dms == LC3PLUS_FRAME_DURATION_10MS && ((encoder->fs_in >= 44100 && setup->targetBytes >= 100) || (encoder->fs_in == 32000 && setup->targetBytes >= 81)) && setup->targetBytes < 340 @@ -620,7 +785,7 @@ LC3PLUS_Error update_enc_bitrate(LC3PLUS_Enc *encoder, int bitrate) { setup->attack_handling = 1; } - else if (encoder->frame_dms == 75 && ((encoder->fs_in >= 44100 && setup->targetBytes >= 75) || + else if (encoder->frame_dms == LC3PLUS_FRAME_DURATION_7p5MS && ((encoder->fs_in >= 44100 && setup->targetBytes >= 75) || (encoder->fs_in == 32000 && setup->targetBytes >= 61)) && setup->targetBytes < 150 #ifdef ENABLE_HR_MODE && encoder->hrmode == 0 @@ -655,19 +820,19 @@ LC3PLUS_Error update_enc_bitrate(LC3PLUS_Enc *encoder, int bitrate) encoder->sns_damping = SNS_DAMPING_HRMODE; IF (encoder->fs_idx >= 4) { - IF ((encoder->frame_dms == 100) & (setup->total_bits > 4400)) + IF ((encoder->frame_dms == LC3PLUS_FRAME_DURATION_10MS) & (setup->total_bits > 4400)) { encoder->sns_damping = SNS_DAMPING_HRMODE_UB_10MS; } - IF ((encoder->frame_dms == 75) & (setup->total_bits > 3300)) + IF ((encoder->frame_dms == LC3PLUS_FRAME_DURATION_7p5MS) & (setup->total_bits > 3300)) { encoder->sns_damping = SNS_DAMPING_HRMODE_UB_7_5MS; } - IF ((encoder->frame_dms == 50) & (setup->total_bits > 2300)) + IF ((encoder->frame_dms == LC3PLUS_FRAME_DURATION_5MS) & (setup->total_bits > 2300)) { encoder->sns_damping = SNS_DAMPING_HRMODE_UB_5MS; } - IF ((encoder->frame_dms == 25) & (setup->total_bits > 1150)) + IF ((encoder->frame_dms == LC3PLUS_FRAME_DURATION_2p5MS) & (setup->total_bits > 1150)) { encoder->sns_damping = SNS_DAMPING_HRMODE_UB_2_5MS; } @@ -676,39 +841,39 @@ LC3PLUS_Error update_enc_bitrate(LC3PLUS_Enc *encoder, int bitrate) if (encoder->hrmode && encoder->fs_idx >= 4) { - int real_rate = setup->targetBytes * 8 * 10000 / encoder->frame_dms; + int real_rate = setup->targetBytes * 8 * 10000 / (encoder->frame_dms * 1.25 * 10); setup->regBits = real_rate / 12500; if (encoder->fs_idx == 5) { - if (encoder->frame_dms == 100) + if (encoder->frame_dms == LC3PLUS_FRAME_DURATION_10MS) { setup->regBits += 2; } - if (encoder->frame_dms == 75) + if (encoder->frame_dms == LC3PLUS_FRAME_DURATION_7p5MS) { setup->regBits +=1; } - if (encoder->frame_dms == 25) + if (encoder->frame_dms == LC3PLUS_FRAME_DURATION_2p5MS) { setup->regBits -= 6; } } else { - if (encoder->frame_dms == 25) + if (encoder->frame_dms == LC3PLUS_FRAME_DURATION_2p5MS) { setup->regBits -= 6; } - else if (encoder->frame_dms == 50) + else if (encoder->frame_dms == LC3PLUS_FRAME_DURATION_5MS) { setup->regBits += 0; } - if (encoder->frame_dms == 75) + if (encoder->frame_dms == LC3PLUS_FRAME_DURATION_7p5MS) { setup->regBits +=2; } - if (encoder->frame_dms == 100) + if (encoder->frame_dms == LC3PLUS_FRAME_DURATION_10MS) { setup->regBits += 5; } diff --git a/lib_lc3plus/setup_enc_lc3.h b/lib_lc3plus/setup_enc_lc3plus.h similarity index 89% rename from lib_lc3plus/setup_enc_lc3.h rename to lib_lc3plus/setup_enc_lc3plus.h index c9a1076a3..6fa08039d 100644 --- a/lib_lc3plus/setup_enc_lc3.h +++ b/lib_lc3plus/setup_enc_lc3plus.h @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -10,6 +10,8 @@ #ifndef SETUP_ENC_LC3_H #define SETUP_ENC_LC3_H +#include "options.h" +#include "wmc_auto.h" #include "constants.h" /* Channel state and bitrate-derived values go in this struct */ @@ -35,10 +37,13 @@ typedef struct Word16 olpa_mem_pitch; Word16 pitch_flag; Word16 ltpf_mem_in_exp; - Word16 ltpf_mem_normcorr; + Word16 ltpf_mem_normcorr[LEN_MEM_NORMCORR]; Word16 ltpf_mem_mem_normcorr; Word16 ltpf_mem_ltpf_on; Word16 ltpf_mem_pitch; +#ifdef FIX_TX_RX_STRUCT_STEREO + Word16 Tx_ltpf; +#endif Word16 mem_targetBits; Word16 mem_specBits; Word16 x_exp; @@ -89,7 +94,7 @@ struct LC3PLUS_Enc Word16 frame_length; /* audio samples / frame */ Word16 channels; /* number of channels */ Word16 epmode; /* error protection mode */ - Word16 frame_dms; /* frame length in dms (decimilliseconds, 10^-4)*/ + LC3PLUS_FrameDuration frame_dms; /* enum for frame length in steps of 12.5 dms */ Word8 lc3_br_set; /* indicate if bitrate has been set */ Word16 yLen; @@ -120,6 +125,12 @@ struct LC3PLUS_Enc Word16 attdec_hangover_thresh; Word16 hrmode; Word16 sns_damping; +#ifdef CR9_C_ADD_1p25MS +#ifndef FIX_TX_RX_STRUCT_STEREO + Word16 Tx_ltpf; +#endif + Word16 LT_normcorr; +#endif }; -#endif +#endif /* SETUP_ENC_LC3_H */ diff --git a/lib_lc3plus/sns_compute_scf_fx.c b/lib_lc3plus/sns_compute_scf_fx.c index cc3338b77..8acfe52bb 100644 --- a/lib_lc3plus/sns_compute_scf_fx.c +++ b/lib_lc3plus/sns_compute_scf_fx.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,10 +7,88 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "functions.h" +#ifdef CR9_C_ADD_1p25MS +static Word32 limitShaping (Word32* d3_fx) { + Word32 score = L_shl_pos(L_sub(d3_fx[0], d3_fx[1]), 1); + score = L_add(score, L_sub(d3_fx[0], d3_fx[2])); + score = L_shr_pos(score, 1); + + score = L_max(L_min(score, 536870912), 335544320); /* 5*2^26 and 8*2^26 */ + + score = L_sub(536870912, score); /* 8 - score */ + + score = L_shr_pos(Mpy_32_16_lc3plus(score, 7646), 0); /* 7646 = 0.7/3 * 2^15 */ + + score = L_add(score, 20132660); /* +0.3*2^26 */ + + score = L_shl_sat(score, 5); /* Bring score into Q31 Format for Mpy32_16() */ + /* Alex: Changed from L_shl_pos to L_shl_sat */ + + return score; +} +#endif + + +#ifdef FIX_SNS_BASOP_MEAN64_CALC +/*improved precision in mean64 accumulation will increase min SNR by 15 dB */ +/* output is max energy band location [0 ... 63] */ +static Word16 sns_compute_mean64_ip(Word32 *en_fx_m, Word16 * en_fx_exp, Word32 *L_mean64_fx, Word16* mean64_fx_exp, Word32* L_en_upd_fx, Word16* en_upd_fx_exp ) +{ + Word32 i,L_tmp; + Word16 tmp, max_exp; + + /* maximize all exponents and mantissas , except for zero mantissas */ + max_exp = -128; move16(); + FOR (i = 0; i < 64; i++) + { + tmp = norm_l(en_fx_m[i]); + + L_en_upd_fx[i] = L_shl_pos(en_fx_m[i], tmp); /* factor 1/64 __NOT__ applied here */ + en_upd_fx_exp[i] = sub(en_fx_exp[i], tmp); + + if (L_en_upd_fx[i] == 0) + { + en_upd_fx_exp[i] = 0; move16();/* all zero mantissa --> correct max_exp */ + } + + max_exp = s_max(max_exp, en_upd_fx_exp[i]); + + } + + L_tmp = L_deposit_l(0); + + /* sum up at max_exp + 6 for 1/64 */ + Word16 glob_shift = add(max_exp, 6); /* add div by 64 , as margin */ + + glob_shift = s_max(glob_shift, -31); + + for (i = 0; i < 64; i++) + { + tmp = s_min(31, sub(glob_shift, en_upd_fx_exp[i])); /* right shift including 1/64 can become larger than 31 */ + L_tmp = L_add(L_tmp, L_shr(L_en_upd_fx[i], tmp)); + } + + //double mean64_m = round(mean64 * pow(2.0, 31.0-(double)max_exp)); /* dbg */ + //double mean64_new = (double)L_tmp * pow(2.0, (double)max_exp - 31.0); + + *L_mean64_fx = L_tmp; + *mean64_fx_exp = max_exp; + + return -1; + +} +#endif + + void processSnsComputeScf_fx(Word32 *d2_fx, Word16 d2_fx_exp, Word16 fs_idx, Word16 n_bands, Word16 *scf, Word16 scf_smoothing_enabled, Word16 attdec_damping_factor, Word8 *scratchBuffer, Word16 sns_damping +#ifdef CR9_C_ADD_1p25MS + , LC3PLUS_FrameDuration frame_dms, Word16 norm_corr, Word16 *LT_normcorr +#endif ) { Dyn_Mem_Deluxe_In( @@ -28,6 +106,26 @@ void processSnsComputeScf_fx(Word32 *d2_fx, Word16 d2_fx_exp, Word16 fs_idx, Wor d3_fx_exp = scratchAlign(d3_fx, sizeof(*d3_fx) * MAX_BANDS_NUMBER); /* Size = 2 * MAX_BANDS_NUMBER = 128 bytes */ d4_fx = scratchAlign(d3_fx_exp, sizeof(*d3_fx_exp) * MAX_BANDS_NUMBER); /* Size = 2 * MAX_BANDS_NUMBER = 128bytes */ scf_smooth = scratchAlign(d4_fx, sizeof(*d4_fx) * MAX_BANDS_NUMBER); /* Size = 2 * 16 */ + + const Word16 *preemp; + const Word16 *preemp_e; +#ifdef CR9_C_ADD_1p25MS + Word16 *pre_em_buf; + Word16 *pre_em_buf_e; + + if (frame_dms == LC3PLUS_FRAME_DURATION_1p25MS) { + pre_em_buf = scratchAlign(scf_smooth, sizeof(*pre_em_buf) * MAX_BANDS_NUMBER); + pre_em_buf_e = scratchAlign(pre_em_buf, sizeof(*pre_em_buf_e) * MAX_BANDS_NUMBER); + } + + Word32 limiterGain = 0x7FFFFFFF; /* 1.0f */ + Word16 ncorr_fac = 0; + +#ifdef FIX_SNS_BASOP_MEAN64_CALC + Word32 L_d5_fx[64], L_mean_ip = 1; + Word16 d5_fx_exp[64], mean_ip_exp = 0; +#endif +#endif /* Smoothing and Pre-emphasis */ IF (sub(n_bands, 32) < 0) @@ -63,18 +161,96 @@ void processSnsComputeScf_fx(Word32 *d2_fx, Word16 d2_fx_exp, Word16 fs_idx, Wor n_bands = 64; move16(); } +#ifdef CR9_C_ADD_1p25MS + /* calc long termn normcorr */ + if (frame_dms == LC3PLUS_FRAME_DURATION_1p25MS && lpc_pre_adapt_emphasis[fs_idx] != NULL) { +#ifdef FIX_BASOP_LT_NORMCORR_AR1 + #ifdef ER_DEBUG + Word16 LT_normcorr_mem = *LT_normcorr; + #endif + L_tmp = L_mult0(1, norm_corr); /* 1/8 */ + L_tmp = L_mac0(L_tmp, 7, *LT_normcorr); /* 7/8 */ + *LT_normcorr = round_fx(L_shl_pos(L_tmp, 16 - 3) ); + assert(*LT_normcorr >= 0); + + /* ncorr_fac = max(*LT_normcorr - 0.8, 0) * 5 */ + /* improved precision of n_corr_fac esp. close to the 0.8 border */ + L_tmp = L_mult0(*LT_normcorr, 5 * (1L << (15 - 3))); /* work in the 5 * upscaled domain from start */ + L_tmp = L_sub(L_tmp, 4 * (1L << ((15 - 3) + 15))); /* sub by 0.8 , limit now exactly 0.8 */ + L_tmp = L_max(L_tmp, 0L); + ncorr_fac = round_fx(L_shl(L_tmp, 4)); /* extract in Q15 */ + + #ifdef ER_DEBUG + LT_normcorr_mem = add(mult(LT_normcorr_mem, 28672), mult(norm_corr, 4096)); + Word16 ncorr_fac_orig = i_mult(s_max(sub(LT_normcorr_mem, 26214), 0), 5); + UNUSED(ncorr_fac_orig); + #endif +#else + /* LT_normcorr * (1-0.125) + normcorr * 0.125 */ + *LT_normcorr = add(mult(*LT_normcorr,28672), mult(norm_corr,4096)); + /* ncorr_fac = max(LT_normcorr - 0.8, 0) * 5 */ + ncorr_fac = i_mult(s_max(sub(*LT_normcorr, 26214), 0), 5); +#endif + + if (ncorr_fac == 0) + { + preemp = lpc_pre_emphasis[fs_idx]; + preemp_e = lpc_pre_emphasis_e[fs_idx]; + } else { + FOR (i = 0; i < n_bands; i++) { + assert (lpc_pre_adapt_emphasis_e[fs_idx][i]>= lpc_pre_emphasis_e[fs_idx][i]); + assert((((Word16)lpc_pre_adapt_emphasis_e[fs_idx][i]) + 1) <= 255); /*check Word8 storage */ + assert((((Word16)lpc_pre_adapt_emphasis_e[fs_idx][i]) + 1) >= -256); /*check Word8 storage */ +#ifdef FIX_BASOP_PREEMPH_CALC + /* FLT sns_preemph_new[i] = (sns_preemph[i] + fac * sns_preemph_adapt[i]); */ + /* BASOP MantNew[i]*2^expNew[i] = (Mant16A[i]*2^expA[i] + facQ15 * Mant16B^expB[i]); */ + /*determine downscaling factor for the base part */ + Word16 tmp_shift = sub(lpc_pre_adapt_emphasis_e[fs_idx][i], lpc_pre_emphasis_e[fs_idx][i]); + Word16 shift_factor = shr_pos(-32768, tmp_shift); /* mantissa downshift impl. as multiplication on the negative side */ + + /*Add scaled mantissas in the same Q but 1 bit rightshifted(for 1 bit WC addition margin) */ + L_tmp = L_mult0(lpc_pre_adapt_emphasis[fs_idx][i], ncorr_fac); /* Qx*Q15 --> Qx, 1 additional bit margin created with Mult0 */ + L_tmp = L_msu0(L_tmp, lpc_pre_emphasis[fs_idx][i], shift_factor ); /* shift_dactor is negative, Msu0 will lead to addition */ + + tmp = norm_l(L_tmp); + pre_em_buf[i] = round_fx_sat(L_shl_pos(L_tmp, tmp)); /* maximize mantissa and apply round */ /* sat needed due to warning due to RND additio of 0.5 */ + + tmp = sub(tmp, add(tmp_shift, 1)); ; + pre_em_buf_e[i] = sub(lpc_pre_emphasis_e[fs_idx][i], tmp); /* adjust final exponent due to mantissa upshift and addition margin */ + + /* sum ~10 ops, but increased precision, and a maintained maximized mantissa */ + +#else + pre_em_buf_e[i] = lpc_pre_adapt_emphasis_e[fs_idx][i] + 1; + Word16 tmp_s = lpc_pre_adapt_emphasis_e[fs_idx][i] - lpc_pre_emphasis_e[fs_idx][i]; + Word16 tmp_v = mult(lpc_pre_adapt_emphasis[fs_idx][i], ncorr_fac); + pre_em_buf[i] = add(shr(lpc_pre_emphasis[fs_idx][i], (tmp_s+1)), shr(tmp_v,1)); +#endif + } + preemp = pre_em_buf; + preemp_e = pre_em_buf_e; + } + } else { + preemp = lpc_pre_emphasis[fs_idx]; + preemp_e = lpc_pre_emphasis_e[fs_idx]; + } +#else + preemp = lpc_pre_emphasis[fs_idx]; + preemp_e = lpc_pre_emphasis_e[fs_idx]; +#endif + L_tmp = L_add(Mpy_32_16_lc3plus(d2_fx[0], 24576), L_shr_pos(d2_fx[1], 2)); - d3_fx[0] = Mpy_32_16_lc3plus(L_tmp, lpc_pre_emphasis[fs_idx][0]); move32(); - d3_fx_exp[0] = add(d2_fx_exp, lpc_pre_emphasis_e[fs_idx][0]); move16(); + d3_fx[0] = Mpy_32_16_lc3plus(L_tmp, preemp[0]); move32(); + d3_fx_exp[0] = add(d2_fx_exp, preemp_e[0]); move16(); FOR (i = 1; i < n_bands - 1; i++) { L_tmp = L_add(L_shr_pos(d2_fx[i], 1), L_add(L_shr_pos(d2_fx[i - 1], 2), L_shr_pos(d2_fx[i + 1], 2))); - d3_fx[i] = Mpy_32_16_lc3plus(L_tmp, lpc_pre_emphasis[fs_idx][i]); move32(); - d3_fx_exp[i] = add(d2_fx_exp, lpc_pre_emphasis_e[fs_idx][i]); move16(); + d3_fx[i] = Mpy_32_16_lc3plus(L_tmp, preemp[i]); move32(); + d3_fx_exp[i] = add(d2_fx_exp, preemp_e[i]); move16(); } L_tmp = L_add(Mpy_32_16_lc3plus(d2_fx[n_bands - 1], 24576), L_shr_pos(d2_fx[n_bands - 2], 2)); - d3_fx[n_bands - 1] = Mpy_32_16_lc3plus(L_tmp, lpc_pre_emphasis[fs_idx][n_bands - 1]); move32(); - d3_fx_exp[n_bands - 1] = add(d2_fx_exp, lpc_pre_emphasis_e[fs_idx][n_bands - 1]); move16(); + d3_fx[n_bands - 1] = Mpy_32_16_lc3plus(L_tmp, preemp[n_bands - 1]); move32(); + d3_fx_exp[n_bands - 1] = add(d2_fx_exp, preemp_e[n_bands - 1]); move16(); /* Mean */ s = d3_fx_exp[MAX_BANDS_NUMBER - 1]; @@ -86,9 +262,161 @@ void processSnsComputeScf_fx(Word32 *d2_fx, Word16 d2_fx_exp, Word16 fs_idx, Wor L_mean = L_add(L_mean, L_shr(d3_fx[i], sub(s2, d3_fx_exp[i]))); } - /* Noise floor at -40dB */ +#ifdef FIX_SNS_BASOP_MEAN64_CALC + IF(frame_dms == LC3PLUS_FRAME_DURATION_1p25MS) + { + /* improved precision in mean64 accumulation will increase minimum SNR vs FLT by 15 dB */ + Word16 max_loc = sns_compute_mean64_ip(&d3_fx[0], &d3_fx_exp[0], &L_mean_ip, &mean_ip_exp, &L_d5_fx[0], &d5_fx_exp[0]); /*ToDo::inplace update d3_fx, d3_fx_exp */ + /* high precision accumluation , divides all entries in d_fx by 1/64 */ + UNUSED(max_loc); + +#ifdef ER_DEBUG + //float mean64new_fx_fl = (((double)L_mean_ip))*pow(2.0, (double)mean_ip_exp - 31); + Word16 d3_max_log2 = BASOP_Util_Log2_16(d3_fx[max_loc], d3_fx_exp[max_loc]); + double d3_maxlog2_dbl = (double)d3_max_log2 / 512.0; + UNUSED(d3_maxlog2_dbl); +#endif + +#ifdef ER_DEBUG + if (d3_fx[max_loc] != 0) /* max_loc is -1 when not debugging */ +#endif + { /* maximize the q in the coming log2 function call */ + + basop_memcpy(d3_fx, L_d5_fx, 64 * sizeof(Word32)); /* use upscaled mantissa values */ + + basop_memcpy(d3_fx_exp, d5_fx_exp, 64 * sizeof(Word16)); /* use corresponding exponents values */ + +#ifdef ER_DEBUG + /* s,s2 are no longer valid in relation to the previous d3_fx */ + s = d3_fx_exp[max_loc]; + s2 = add(s, 6); /* div by 64 */ + + /* debug:: redo L_mean calc using new s, s2 and upscaled mantissa parameters */ + tmp = s_min(31, sub(s2, d3_fx_exp[0])); + L_mean = L_shr_pos(d3_fx[0], tmp); + FOR(i = 1; i < MAX_BANDS_NUMBER; i++) + { + tmp = s_min(31, sub(s2, d3_fx_exp[i])); + L_mean = L_add(L_mean, L_shr_pos(d3_fx[i], tmp)); + } +#endif + } + } +#endif + +#ifdef ER_DEBUG + if ((dbgflag("r") || dbgflag("ru")) && scratch->max_scratch_calculation_only == 0) + { + double sns64_fx_fl_all[64]; + double sns64_fx_fl_all_log2[64]; /* find range of smoothed input signal */ + + double sns64_fx_fl_opt_all[64]; + double sns64_fx_fl_opt_all_log2[64]; /* find range of smoothed input signal */ + + Word32 d3_opt_fx[64]; + Word16 d3_opt_fx_exp[64]; + float fl_mean64, fl_mean64_m, fl_mean64_e; + float L_mean_fx_fl; + float fl_mean64_recalc; + + UNUSED(sns64_fx_fl_opt_all); + UNUSED(sns64_fx_fl_opt_all_log2); + UNUSED(sns64_fx_fl_all_log2); + UNUSED(sns64_fx_fl_all); + + + UNUSED(fl_mean64_m); + UNUSED(fl_mean64_e); + + dbgread(&fl_mean64, sizeof(fl_mean64), 1, "..//..//..//fl_x_mean64.float.1.dat"); + +#ifdef FIX_SNS_BASOP_MEAN64_CALC + float mean64new_fx_fl = (((double)L_mean_ip))*pow(2.0, (double)mean_ip_exp - 31); + + snr_diff(&mean64new_fx_fl, &fl_mean64, 1, 0, "SNRc4b_x_mean64ip_FXvsFL"); + +#endif + + fl_mean64_e = s; + fl_mean64_m = fl_mean64 * pow(2.0, 31.0 -(double)fl_mean64_e ); + + + fl_mean64_recalc = 0.0; + for (int i = 0; i < 64; i++) + { + sns64_fx_fl_all[i] = (double)d3_fx[i] * pow(2.0, (double)d3_fx_exp[i] - 31.0); + sns64_fx_fl_all_log2[i] = log2(sns64_fx_fl_all[i]); + fl_mean64_recalc += sns64_fx_fl_all[i]; + + int tmp_up = norm_l(d3_fx[i]); + d3_opt_fx[i] = L_shl_pos(d3_fx[i], tmp_up); + d3_opt_fx_exp[i] = sub(d3_fx_exp[i], tmp_up); + + sns64_fx_fl_opt_all[i] = (double)d3_opt_fx[i] * pow(2.0, (double)d3_opt_fx_exp[i] - 31.0); + sns64_fx_fl_opt_all_log2[i] = log2(sns64_fx_fl_all[i]); + } + + + + fl_mean64_recalc /= 64.0; /* downscaling by 1/64 already applied */ + + L_mean_fx_fl = (((double)L_mean))*pow(2.0, (double)s - 31.0); + snr_diff(&L_mean_fx_fl, &fl_mean64, 1, 0, "SNRc4b_x_mean64_FXvsFL"); + + snr_diff(&fl_mean64_recalc, &fl_mean64, 1, 0, "SNRc4b_x_mean64recalc_FXvsFL"); /* 15 dB better !! */ + + + if (dbgflag("ru")) + { +#ifdef FIX_SNS_BASOP_MEAN64_CALC + L_mean = round(fl_mean64*pow(2.0, 31 - mean_ip_exp)); + assert(fabs(fl_mean64*pow(2.0, 31 - mean_ip_exp)) <= (double)INT32_MAX); +#else + L_mean = round(fl_mean64*pow(2.0, 31 - s)); + assert(fabs(fl_mean64*pow(2.0, 31 - s)) <= (double)INT32_MAX); +#endif + + } + } +#endif + +#ifdef FIX_SNS_BASOP_NF_APPL + IF(frame_dms == LC3PLUS_FRAME_DURATION_1p25MS) + { +#ifdef ER_DEBUG + Word16 nf_post = BASOP_Util_Log2_16(L_mean_ip, mean_ip_exp); + nf_post = sub(s_max(nf_post, -25965), 6803); /* log2(-25965)- log2(6803) --> -50.7 -13.28 => -64.00 in Q9 */ + /*if nf > -50.7 nf is applied by subtracting 2^-13.28 9996 */ +#endif + + /* calulate the nf level in W32 before going to the less exact log2() W16 domain */ + Word16 tmp_nf = norm_l(L_mean_ip); + Word32 L_nf_fx = L_shl_pos(L_mean_ip, tmp_nf); /* shift up 1/64 to maximize mantissa */ + + L_nf_fx = Mpy_32_16_lc3plus(L_nf_fx, 26844); /* 26844=round(2^13/10000) */ + Word16 nf_fx_exp = sub(mean_ip_exp, add(13, tmp_nf)); /* division by 10000.0 as L_mant = L_mant*(2^13/10000), nf_exp=mean_exp-13 */ + + nf = BASOP_Util_Log2_16(L_nf_fx, nf_fx_exp); /* log2_16 function ouput is in Q9 , range is values [-64.xxx to 63.xxxx] */ + +#ifdef ER_DEBUG + /* all zero input will get nf of -32768 */ + if (L_mean_ip == 0) + { + assert(nf == -32768); + } +#endif + + } + ELSE + { /* 2.5ms ... 10ms (nf is at approximated at 1/9998 below mean) */ + nf = BASOP_Util_Log2_16(L_mean, s); + nf = sub(s_max(nf, -25965), 6803); + } +#else nf = BASOP_Util_Log2_16(L_mean, s); nf = sub(s_max(nf, -25965), 6803); +#endif + /* Log-domain */ FOR (i = 0; i < MAX_BANDS_NUMBER; i++) @@ -116,6 +444,13 @@ void processSnsComputeScf_fx(Word32 *d2_fx, Word16 d2_fx_exp, Word16 fs_idx, Wor L_tmp = L_mac(L_tmp, d4_fx[61], 8192); L_tmp = L_mac(L_tmp, d4_fx[62], 8192); d3_fx[M - 1] = L_mac(L_tmp, d4_fx[63], 8192); move32(); + +#if defined (CR9_C_ADD_1p25MS) + /* limit shaping */ + IF (frame_dms == LC3PLUS_FRAME_DURATION_1p25MS) { + limiterGain = limitShaping(d3_fx); + } +#endif /* Remove mean and scaling */ L_mean = L_shr_pos(d3_fx[0], 4); @@ -124,15 +459,99 @@ void processSnsComputeScf_fx(Word32 *d2_fx, Word16 d2_fx_exp, Word16 fs_idx, Wor L_mean = L_add(L_mean, L_shr_pos(d3_fx[i], 4)); } +#ifdef FIX_SNS_BASOP_MEAN16_APPLY + Word16 limGainDamping = 0; + Word16 up_shift = 0, dn_shift = 0; + + IF(frame_dms == LC3PLUS_FRAME_DURATION_1p25MS) + { + up_shift = 31; move16(); + + FOR(i = 0; i < M; i++) + { + L_tmp = L_sub(d3_fx[i], L_mean); + up_shift = s_min(norm_l(L_tmp), up_shift); + d3_fx[i + M] = L_tmp; move32(); /* store mean removed variable */ + } + dn_shift = s_max(0, sub(up_shift, 1)); /* conditional downshift from q10 to Q11, to maintain precision */ + + limGainDamping = round_fx(Mpy_32_16_lc3plus(limiterGain, sns_damping)); + } +#endif + FOR (i = 0; i < M; i++) { +#if defined (CR9_C_ADD_1p25MS) + if (frame_dms == LC3PLUS_FRAME_DURATION_1p25MS) + { +#ifdef FIX_SNS_BASOP_MEAN16_APPLY + /* maximize precision */ + L_tmp = Mpy_32_16_lc3plus(L_shl_pos(d3_fx[i + M], up_shift), limGainDamping ); + scf[i] = round_fx(L_shr_pos(L_tmp, dn_shift)); +#else + scf[i] = mult_r(extract_h(Mpy_32_16_lc3plus(limiterGain, sns_damping)), round_fx(L_shl_pos(L_sub(d3_fx[i], L_mean), 1))); +#endif + move16(); + } else { + scf[i] = mult_r(sns_damping, round_fx(L_shl_pos(L_sub(d3_fx[i], L_mean), 1))); + move16(); + } +#else scf[i] = mult_r(sns_damping, round_fx(L_shl_pos(L_sub(d3_fx[i], L_mean), 1))); move16(); +#endif } /* scale factor smoothing */ + #ifdef CR9_C_ADD_1p25MS_LRSNS + test(); test(); + IF( (scf_smoothing_enabled != 0 ) || (sub(frame_dms, LC3PLUS_FRAME_DURATION_1p25MS) == 0) ) + #else IF (scf_smoothing_enabled) + #endif { + #ifdef CR9_C_ADD_1p25MS_LRSNS + IF(sub(frame_dms, LC3PLUS_FRAME_DURATION_1p25MS) == 0) + { + +#define A0Q15 6144 /* 0.1875 */ +#define A1Q15 (32768 - 2 * A0Q15) /* 0.675 */ +#define A2Q15 A0Q15 /* 0.1875 */ + + L_tmp = L_mult0(scf[0], A0Q15 >> 1); + L_tmp = L_mac0(L_tmp, scf[1], A0Q15 >> 1);/*incl a mult by 0.5)*/ /* a virtual scf[-1]*.1875 created */ + L_tmp = L_mac0(L_tmp, scf[0], A1Q15); /*scf[0] * .675 */ + L_tmp = L_mac0(L_tmp, scf[1], A2Q15); /*scf[1] * .1875 */ + L_tmp = L_add(L_tmp, L_tmp); /* added to realize one upshift due to margin created by mac0 */ + + scf_smooth[0] = round_fx(L_tmp); + L_mean = L_deposit_l(scf_smooth[0]); + + FOR(i = 1; i < M - 1; i++) + { /* normal unity gain three tap FIR filter */ + L_tmp = L_mult0(scf[i - 1], A0Q15); /*Q(11+16+1) Q26 */ + L_tmp = L_mac0(L_tmp, scf[i], A1Q15); + L_tmp = L_mac0(L_tmp, scf[i + 1], A2Q15); + L_tmp = L_add(L_tmp, L_tmp); /* added to realize one upshift due to margin created by mac0 */ + scf_smooth[i] = round_fx(L_tmp); /* back to Q11 */ + L_mean = L_add(L_mean, L_deposit_l(scf_smooth[i])); /* mean accumulated on the low side */ + } + + /* final coeff */ + L_tmp = L_mult0(scf[M - 2], A2Q15); /* .1875*/ + L_tmp = L_mac0(L_tmp, scf[M - 1], A1Q15); /* .675 */ + L_tmp = L_mac0(L_tmp, scf[M - 2], A0Q15 >> 1); /* now the final virtual scf[M]*.1875 */ + L_tmp = L_mac0(L_tmp, scf[M - 1], A0Q15 >> 1); + L_tmp = L_add(L_tmp, L_tmp); /* added to realize one upshift due to margin created by mac0 */ + scf_smooth[M - 1] = round_fx(L_tmp); + + L_mean = L_add(L_mean, L_deposit_l(scf_smooth[M - 1])); + + L_mean = L_shr(L_add(L_mean, 1L << (4 - 1)), 4); /* excplicit rounding in the 1/M = 0.1625 application */ + } + ELSE IF(sub(scf_smoothing_enabled, 1) == 0) + { /* legacy smoothing logic */ +#endif scf_smooth[0] = L_shr(L_mult0(L_add(L_add(scf[0], scf[1]), scf[2]), 10923), 15); L_mean = scf_smooth[0]; move16(); scf_smooth[1] = L_shr(L_add(L_add(L_add(scf[0], scf[1]), scf[2]), scf[3]), 2); @@ -154,11 +573,35 @@ void processSnsComputeScf_fx(Word32 *d2_fx, Word16 d2_fx_exp, Word16 fs_idx, Wor L_mean = L_add(L_mean, scf_smooth[M - 1]); L_mean = L_shr(L_mean, 4); + + #ifdef CR9_C_ADD_1p25MS_LRSNS + } + #endif + + #ifdef CR9_C_ADD_1p25MS_LRSNS + IF(sub(frame_dms, LC3PLUS_FRAME_DURATION_1p25MS) == 0) + { + ASSERT(L_mean <= 32767L && L_mean >= -32768L); + Word16 mean = extract_l(L_mean); + FOR(i = 0; i < M; i++) + { + scf[i] = sub(scf_smooth[i], mean); /* only mean subtraction required, no damping/scaling */ + } + } + ELSE + { + FOR(i = 0; i < M; i++) + { + scf[i] = mult_r(attdec_damping_factor, sub(scf_smooth[i], L_mean)); + } + } +#else FOR (i = 0; i < M; i++) { scf[i] = mult_r(attdec_damping_factor, sub(scf_smooth[i], L_mean)); } + #endif } Dyn_Mem_Deluxe_Out(); diff --git a/lib_lc3plus/sns_interpolate_scf_fx.c b/lib_lc3plus/sns_interpolate_scf_fx.c index 65e4b1c16..89718af52 100644 --- a/lib_lc3plus/sns_interpolate_scf_fx.c +++ b/lib_lc3plus/sns_interpolate_scf_fx.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,6 +7,8 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "functions.h" void processSnsInterpolateScf_fx( diff --git a/lib_lc3plus/sns_quantize_scf_fx.c b/lib_lc3plus/sns_quantize_scf_fx.c index baa33a1c1..d16a90b34 100644 --- a/lib_lc3plus/sns_quantize_scf_fx.c +++ b/lib_lc3plus/sns_quantize_scf_fx.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,7 +7,14 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" +#include "defines.h" #include "functions.h" +#ifdef CR9_C_ADD_1p25MS_LRSNS +#include "constants.h" +#include /* req for INT32_MAX in msvc */ +#endif static Word16 stage1_base( /* o : idx */ const Word16 *t, /* i : target SCFs */ @@ -361,7 +368,7 @@ static void pvq_enc_find_best_submode_pre_post_fx( /* start actual search loop */ /* basic raw MSE loop, */ - L_mse_min = INT32_MAX; move32(); + L_mse_min = INT_MAX; move32(); L_idx = L_deposit_l(-1); /* section in low 2 bits* gain idx above */ FOR (L_section = 0; L_section < N_SCF_SHAPES_ST2; L_section++) @@ -832,3 +839,1229 @@ Word16 processSnsQuantizeScfDecoder_fx( /* return BER_flag; } +#ifdef CR9_C_ADD_1p25MS_LRSNS +Word16 snsQuantScfDecLR_fx(Word32* L_sns_vq_idx_fx, + Word32* L_scf_q_fx, /* o: Q26 */ + Word16* scf_q_fx, /* o: Q11 */ + Word16 pitch_rx_fx, Word16 ltpf_rx_fx, Word8 * scratch) +{ + + + + Dyn_Mem_Deluxe_In( + Counter i; + Word32 L_mPVQ_ind_fx; /* can be up to 17 bits */ + Word16 shape_idx_fx, gain_idx_fx, cb_idx_fx, aux_idx_fx, LS_ind_fx; + Word16 env_ind_fx, shift_ind_fx, sign_ind_fx, n_signs_fx; + + Word16 *Y_shape_j_fx; /* Q0 */ + Word16 *Xq_shape_j_fx; /* Q14 */ + Word32 *L_Xq_shape_j_fx; + const Word16 *cb_fx; + Word16 * st1_scf_q_fx; + Word16 CBCmeanp_ind_fx; + const Word16 *gainTab_fx; + Word16 gainValQ12_fx; + Word16 BER_dec; + Word32 L_y_en, L_norm_factor; + Word16 norm_factorQ, y_upshift; + ); + + st1_scf_q_fx = (Word16*)scratchAlign(scratch, 0); + Y_shape_j_fx = (Word16*)scratchAlign(st1_scf_q_fx, sizeof(*st1_scf_q_fx) * M); /*1*16*/ + L_Xq_shape_j_fx = (Word32*)scratchAlign(Y_shape_j_fx, sizeof(*Y_shape_j_fx) * M); /*1*16*/ + Xq_shape_j_fx = (Word16*)scratchAlign(L_Xq_shape_j_fx, sizeof(*L_Xq_shape_j_fx) * M); /*1*16*/ + /*1*16*/ + +#ifdef LRSNS_CBC_NO_LTPF_DEPENDENCY + UNUSED(ltpf_rx_fx); +#endif + BER_dec = 0; /* no BER detected in PVQ indeces */ + basop_memset(Y_shape_j_fx, 0, sizeof(Word16) * M); + + gainTab_fx = lrsns_vq_gainsQ12_fx[0]; move16(); /* gcc warning init */ + gain_idx_fx = 0; move16();/* gcc warning init */ + shift_ind_fx = 0; move16(); + env_ind_fx = 0; move16(); + + /* get indices from dec_entropy_dx */ + cb_idx_fx = extract_l(L_sns_vq_idx_fx[0]); move16(); /* stage1 idx */ + aux_idx_fx = extract_l(L_sns_vq_idx_fx[1]); move16(); /* mPVQ LS-bit or the FESS s0 bit */ + shape_idx_fx = extract_l(L_sns_vq_idx_fx[2]); move16(); /* analysis order shape idx -9,-10 0,1, 2,3,4,5 */ + gain_idx_fx = extract_l(L_sns_vq_idx_fx[3]); move16(); /* stage 2 gain index */ + + /* Stage1 cand */ + IF(sub(shape_idx_fx, -9) == 0) + { + /* minimal 2*16 SNS codebook, no DC */ + cb_fx = lrsns_cbA_fx; /* ptr init */ + basop_memcpy(scf_q_fx, &(cb_fx[shl_pos(cb_idx_fx, 4)]), sizeof(Word16) * M); /* cb_idx_fx * M */ + } + ELSE IF(sub(shape_idx_fx, -10) == 0) + { /* 0..339 */ /* stage 1B or 1C only, transmitted in 9+1= 10 bits */ + IF(sub(cb_idx_fx, 170) < 0) + { /* Stage 1B */ + snslr_st1B_vector_dec_fx(cb_idx_fx, st1SCF0_7_base5_32x8_Q11, st1SCF8_15_base5_32x8_Q11, + lrsns_st1B_merged170orderSortedSegmCum_fx, lrsns_st1B_merged170orderSort12bitIdx_fx, scf_q_fx); + + snslr_remove_st1_DC_fQ11_fx(scf_q_fx, M); + } + ELSE + { + cb_idx_fx = sub(cb_idx_fx, 170); + /* Stage 1C harmonic outlier CB with pitch dependent mean vector */ + /* Q11 values , so that BASOP and float is always BE in synthesis*/ + ASSERT(cb_idx_fx >= 0 && cb_idx_fx < 170); + + snslr_st1C_vector_dec_fx(cb_idx_fx, lrsns_st1C_Both_Word8_fx, lrsns_st1C_Both_scaleQ4_7p4bits_fx[1], + lrsns_st1C_Both_inv_scaleQ15_7p4bits_fx[1], M, 170, scf_q_fx); + /* add harmonic mean , based on pitch_info availability */ + + pitch_rx_fx = extract_l(L_sns_vq_idx_fx[3]); /* LTP active flag directly from dec_entropy */ +#ifdef LRSNS_CBC_NO_LTPF_DEPENDENCY + ltpf_rx_fx = 0; /* CB_C has no dependency on LTPF active flag */ +#else + ltpf_rx_fx = extract_l(L_sns_vq_idx_fx[4]); /* LTPF active flag directly from dec_entropy */ +#endif + CBCmeanp_ind_fx = pitch_rx_fx; move16(); /* 0 or 1 */ +#ifndef LRSNS_CBC_NO_LTPF_DEPENDENCY + test(); test(); test(); + if (pitch_rx_fx != 0 && ltpf_rx_fx != 0) + { + CBCmeanp_ind_fx = add(CBCmeanp_ind_fx, 1); /* high corr ltpf_rx is also active */ + } +#endif + const Word16 *mean_cb_fx = lrsns_st1CTrainedMapMeans_fx[CBCmeanp_ind_fx]; /* point to pitch dependent mean */ + for (i = 0; i < M; i++) + { + scf_q_fx[i] = add(scf_q_fx[i], mean_cb_fx[i]); + } + /* remove_DC() call is not required for section C */ + } + } + ELSE + { /* 0..169 */ /* st1B* used with a stage 2 shape submode */ + ASSERT(shape_idx_fx >= 0 && shape_idx_fx <= 5); + snslr_st1B_vector_dec_fx(cb_idx_fx, st1SCF0_7_base5_32x8_Q11, st1SCF8_15_base5_32x8_Q11, lrsns_st1B_merged170orderSortedSegmCum_fx, lrsns_st1B_merged170orderSort12bitIdx_fx, scf_q_fx); + snslr_remove_st1_DC_fQ11_fx(scf_q_fx, M); /* inplace */ /* DC needs removal for st1 part B */ + } + + basop_memcpy(st1_scf_q_fx, scf_q_fx, sizeof(Word16) * M); /* keep track of stage1 (A,B or C) contribution */ + + IF(shape_idx_fx >= 0) /* stage 2 shapes 0,1, 2,3,4,5 ( negative idx used for stage1 only */ + { + /* stage 2 SNS VQ decoding */ + /* Decode shape_j */ + Y_shape_j_fx[0] = 0; /* no DCT-II DC-coeff decoded */ + + SWITCH(shape_idx_fx) + { + case 0: /* splitLF 29 bits total */ + LS_ind_fx = aux_idx_fx; move16(); + L_mPVQ_ind_fx = L_sns_vq_idx_fx[4]; move32(); /* mPVQ(5,6) or mPVQ(5,8) */ + + test(); + IF(L_sns_vq_idx_fx[5] >= 0) + { + /* CFLT: MPVQdeenum_fx(5, 6, LS_ind_fx, L_mPVQ_ind_fx, &Y_shape_j_fx[1]); */ + BER_dec = pvq_dec_deidx_fx(&Y_shape_j_fx[1], PULSES_SPLIT_A_LR, NA_LR, LS_ind_fx, (UWord32)L_mPVQ_ind_fx); + + LS_ind_fx = extract_l(L_and(L_sns_vq_idx_fx[5], 0x1)); + L_mPVQ_ind_fx = L_shr_pos(L_sns_vq_idx_fx[5], 1); + + /* CFLT: MPVQdeenum_fx(8, 2, LS_ind_fx, L_mPVQ_ind_fx, &Y_shape_j_fx[1 + 5]); */ + BER_dec = s_or(BER_dec, pvq_dec_deidx_fx(&Y_shape_j_fx[1 + NA_LR], PULSES_SPLIT_B_LR, NB_LR, LS_ind_fx, (UWord32)L_mPVQ_ind_fx)); + } + ELSE + { + /* CFLT: MPVQdeenum_fx(5, 8, LS_ind_fx, L_mPVQ_ind_fx, &Y_shape_j_fx[1]); */ + BER_dec = pvq_dec_deidx_fx(&Y_shape_j_fx[1], (PULSES_SPLIT_A_LR + PULSES_SPLIT_B_LR), NA_LR, LS_ind_fx, (UWord32)L_mPVQ_ind_fx); + } + gainTab_fx = lrsns_vq_gainsQ12_fx[0]; move32(); /* 4 levels in 2 bits */ + break; + case 1: /* full (N=15,K=5) 30 bits total */ + LS_ind_fx = aux_idx_fx; move16(); + L_mPVQ_ind_fx = L_sns_vq_idx_fx[4]; move32(); + + /* CFLT: MPVQdeenum_fx(15, 5, LS_ind_fx, L_mPVQ_ind_fx, &Y_shape_j_fx[1]); */ + BER_dec = pvq_dec_deidx_fx(&Y_shape_j_fx[1], PULSES_FULL_LR, NFULL_LR, LS_ind_fx, (UWord32)L_mPVQ_ind_fx); + gainTab_fx = lrsns_vq_gainsQ12_fx[1]; move16(); /* 8 levels in 3 bits */ + + break; + case 2: /* fix env 0 , init_bell 12 signs */ + case 3: /* fix env 1 , decay 12-->6 12 signs */ + case 4: /* fix env 2 , start bell 12 signs */ + case 5: /* fix env 3 , early bell 10 signs */ + LS_ind_fx = aux_idx_fx; /* s0 */ move16(); + env_ind_fx = extract_l(L_sns_vq_idx_fx[4]); move16(); + ASSERT(env_ind_fx == (shape_idx_fx - 2)); + Word16 sign_mask_fx = 0x07ff; move16(); /* mask for 11 remaining signs */ + n_signs_fx = NSIGNS_FIX_012; move16(); /* number of signs including s0 */ + if (sub(env_ind_fx, 3) == 0) + { + n_signs_fx = NSIGNS_FIX_3; move16(); + } + sign_mask_fx = shr_pos_pos(sign_mask_fx, sub(NSIGNS_FIX_012, n_signs_fx)); + + shift_ind_fx = extract_l(L_shr_pos(L_sns_vq_idx_fx[5], sub(n_signs_fx, 1))); + sign_ind_fx = s_and(extract_l(L_sns_vq_idx_fx[5]), sign_mask_fx); + + /* put sign s0 , right next to s1 , to make the subsequent sign decoding loop straight fwd */ + sign_ind_fx = add(shl_pos(LS_ind_fx, sub(n_signs_fx, 1)), sign_ind_fx); /* s0 put as MSB at 12th position */ + + /*FixEnvShiftedSigns deenumeration */ + /* part of 30b total, 4xenv,4xshifts, 10 or12 signs , spread over 15 positions,*/ + FESSdeenum_fx(NFULL_LR, N_CANDS_FIX_LR, N_SHIFT_FIX, n_signs_fx, env_ind_fx, shift_ind_fx, sign_ind_fx, &Y_shape_j_fx[1]); + + gainTab_fx = lrsns_vq_gainsQ12_fx[2]; move16(); /* 8 levels in 3 bits */ + /* fix_envshift_nb_fx = env_ind_fx * 4 + shift_ind_fx; */ /* index for fast normalization lookup */ + break; + default: + ASSERT(0 && " LRSNS stage2 demux bad shape shape_idx_fx received from dec_entropy_fx "); + break; + } + + gainValQ12_fx = gainTab_fx[gain_idx_fx]; + + + /* enc/dec common Word32Q30 and Word16Q14 Unit energy normalization of the received shapes mPVQ or FESS */ + IF(sub(shape_idx_fx, 2) < 0) + { /* 0,1,2 :: PVQ(N,K) shape with up to 8 unit pulses */ + L_y_en = L_deposit_l(0); + FOR(i = 1; i < M; i++) + { + L_y_en = L_mac0(L_y_en, Y_shape_j_fx[i], Y_shape_j_fx[i]); + } + L_norm_factor = isqrt_Q31tab[L_y_en]; move32(); /* Q31 inv_sqrt value */ + norm_factorQ = lrsns_norm_factorQ_L[shape_idx_fx]; move16(); + y_upshift = lrsns_y_up_bits[shape_idx_fx]; move16(); + } + ELSE + { /* 2,3,4,5 :: FESS shapes with up to unit pulses */ + /* no energy calc required, only 16 different energies are possible */ + L_norm_factor = L_lrsns_fixenv_enNormQ35[add(shl_pos(env_ind_fx , 2), shift_ind_fx)]; move32(); /* Q19+16=Q35 */ + norm_factorQ = lrsns_norm_factorQ_L[2]; move16(); + y_upshift = lrsns_y_up_bits[2]; move16(); + } + + /* reuse common encoder/decoder unit energy normalization routine */ + ASSERT(Y_shape_j_fx[0] == 0); + pvq_fess_dec_en1_normQ30andQ14_fx(Y_shape_j_fx, y_upshift, L_norm_factor, norm_factorQ, M, L_Xq_shape_j_fx, Xq_shape_j_fx); + ASSERT(L_Xq_shape_j_fx[0] == 0 && Xq_shape_j_fx[0] == 0); + + /* Reconstruction of the quantized SNS scale factors */ +#ifdef ENABLE_HR_MODE + L_Xq_shape_j_fx[0] = 0; move32(); /* enforce no DC */ + idct32_32_fx(L_Xq_shape_j_fx, L_Xq_shape_j_fx); /* inplace idct */ + + /* move stage1 W16Q11 to W32Q27 */ + FOR(i = 0; i < M; i++) + { + L_scf_q_fx[i] = L_deposit_h(st1_scf_q_fx[i]); move32();/* stage1 W16Q11 to W32Q27 */ + } + lrsns_pvq_dec_scale_W32vec_fx(L_Xq_shape_j_fx, gainValQ12_fx, L_scf_q_fx /* W32Q27 in, W32Q26 out */, scf_q_fx /* out Q11*/); + +#else + /* DISABLE_HR */ + Xq_shape_j_fx[0] = 0; move16(); /* no DC */ + idct16_fx(Xq_shape_j_fx, Xq_shape_j_fx); /* inplace idct */ /* fwd in unscaled unit energy domain */ + + /* move stage1B into a W16 vector for accumulation in Q11 */ + basop_memcpy(scf_q_fx, st1_scf_q_fx, sizeof(*scf_q_fx)*M); + + /* scf_q_fx contains stage1 in Q11 */ + lrsns_pvq_dec_scale_W16vec_fx(Xq_shape_j_fx/* Q14 */, gainValQ12_fx, scf_q_fx /* Q11in, Q11out */); + + /* scf_q_fx is the final result incl. stage2 in Q11 */ +#endif /* DISABLE_HR */ + + } + ELSE + { /* -9, -10 */ + /* LRSNS stage 1 A,B,C */ + basop_memcpy(scf_q_fx, st1_scf_q_fx, sizeof(Word16) * M); /* Q11*/ + + FOR(i = 0; i < M; i++) + { + L_scf_q_fx[i] = L_shr_pos(L_deposit_h(scf_q_fx[i]), 1); /* 11+16-1 => Q26 */ + } + } + Dyn_Mem_Deluxe_Out(); + + return BER_dec; +} + +/* split out of LRSNS stage 1 functionality */ +Word32 snsQuantScfEncLRSt1ABC_fx(Word16* env, Word32* L_index, Word32 *L_min_mse_saveBCA_ptr_fx, + Word16* ind_saveB_ptr, Word16* st1_vectors, + Word16 pitch_rx, Word16 ltpf_rx, Word8 * scratch) +{ + + Dyn_Mem_Deluxe_In( + Counter i; + Word16 *st1_vector_fx, *st1_vectorA_fx, *st1_vectorB_fx, *st1_vectorC_fx, *target_fx; + Word32 L_min_mse_saveA_fx, L_min_mse_saveB_fx, L_min_mse_saveC_fx, L_min_mse_saveBC_fx; + Word16 ind_saveA_fx, ind_saveC_fx; + Word16 meanC_ind; + Word16 stage1_mode; /*0=A, 1=B, 2=C. -1==fail*/ + Word32 L_min_mse_saveB_fxlike_fx; + Word16 ind_saveB_fxlike_fx; + Word16 dc_fx; + Word32 L_tmp; + Word16 *st1_vectorB_idx_fx; + ); + + stage1_mode = -1; /* output */ + + st1_vectorB_idx_fx = scratchAlign(scratch, 0); + target_fx = scratchAlign(scratch, sizeof(*st1_vectorB_idx_fx) * M); + +#ifdef LRSNS_CBC_NO_LTPF_DEPENDENCY + UNUSED(ltpf_rx); +#endif + st1_vectorA_fx = &(st1_vectors[0]); + st1_vectorB_fx = &(st1_vectors[1 * M]); + st1_vectorC_fx = &(st1_vectors[2 * M]); + st1_vector_fx = &(st1_vectors[3 * M]); /*selected winner */ + +#ifdef WMOPS + push_wmops("snsQuantScfEncLRSt1ABC_fx"); +#endif + + /* snslr stage1 B(170) and C(170), A(2) evaluation */ + /* + segm idx9b + + ------+--------+--------+------- + B | 0--169 | aux==0 , 170 entries + ------+--------+-------- + C | 170-339| aux==1 , 170 entries, + ------+--------+--------+ + * | 341-509| aux==2 , 170 entries (later decided to be B + aux bit) + ------+--------+--------- + A | 510,511| 2 entries, 9 bit total + ------+--------+-------- + */ +#ifdef WMOPS + push_wmops("MSEsearchCbA_fx"); +#endif + + + { /* stage 1 section A(2), a very small 2xM entry cb */ + /* two crude vector MSE_calculations needed */ + + basop_memcpy(target_fx, env, sizeof(Word16)*M); + + ind_saveA_fx = MSEsearchGeneric_fx(target_fx, lrsns_cbA_fx, M, 2, &L_min_mse_saveA_fx); + + basop_memcpy(st1_vectorA_fx, &(lrsns_cbA_fx[ind_saveA_fx*M]), sizeof(Word16)*M); + } +#ifdef WMOPS + pop_wmops(); +#endif + + +#ifdef WMOPS + push_wmops("MSEsearchCbB_fx"); +#endif + { /* stage1 section B(170) MSE analysis */ + basop_memcpy(target_fx, env, sizeof(Word16)*M); + *ind_saveB_ptr = -1; move16(); + + ind_saveB_fxlike_fx = MSEsearchCbBIdxMap_fx(target_fx, st1SCF0_7_base5_32x8_Q11, st1SCF8_15_base5_32x8_Q11, + lrsns_st1B_merged170orderSortedSegmCum_fx, lrsns_st1B_merged170orderSort12bitIdx_fx, M, 170, &L_min_mse_saveB_fxlike_fx); /*st1B LF,HF idx lookup search 170 ,170 Word16s , 0.34kB ROM */ + + snslr_st1B_vector_dec_fx(ind_saveB_fxlike_fx, st1SCF0_7_base5_32x8_Q11, st1SCF8_15_base5_32x8_Q11, lrsns_st1B_merged170orderSortedSegmCum_fx, lrsns_st1B_merged170orderSort12bitIdx_fx, + st1_vectorB_idx_fx); + + *ind_saveB_ptr = ind_saveB_fxlike_fx; move16(); + L_min_mse_saveB_fx = L_min_mse_saveB_fxlike_fx; move32(); + basop_memcpy(st1_vectorB_fx, st1_vectorB_idx_fx, sizeof(Word16)*M); /*use low ROM version */ + + { + /* remove the DC that can remain in the LF,HF index stored stage cbB structure */ + /* a very slight off-line decrease in perf 0.001 dB in AveSD when searching with DC above, + but it allows much better stage1 ROM-reuse performance */ + + dc_fx = snslr_remove_st1_DC_fQ11_fx(st1_vectorB_fx, M); /* in-place removal of dc in st1_vectorB */ + + ASSERT(L_min_mse_saveB_fx >= 0L); + + dc_fx = shl_pos(dc_fx, 2); /* mult dc_fx with sqrt(M) */ + L_tmp = L_msu0(L_min_mse_saveB_fx, dc_fx, dc_fx); + + /* force the MSE B to be zero or larger*/ + /* may happen due to imperfect(truncation) DC removal */ + L_min_mse_saveB_fx = L_max(L_tmp, 0L); + } + } /* end of stage 1 section B , search */ +#ifdef WMOPS + pop_wmops(); +#endif + +#ifdef WMOPS + push_wmops("MSEsearchCbC_fx"); +#endif + meanC_ind = pitch_rx; move16(); +#ifndef LRSNS_CBC_NO_LTPF_DEPENDENCY + if (ltpf_rx != 0) + { + meanC_ind = add(meanC_ind, 1); + } +#else + /* CbC only dependent on LTP transmission on/off */ +#endif + Word32 L_mse_tmpQ22 = L_min(Mpy_32_16_lc3plus(L_min_mse_saveA_fx, SNSLR_A_CNST_WEIGHT), L_min_mse_saveB_fx); + + /* apply skipC threshold of 3.97 in Q22 */ + IF(L_sub(L_mse_tmpQ22, 16651387L) < 0) /* to skip C search if SD is already low enough < 1.5dB (msesum=3.97)) to save average WMOPS */ + { + /* search stage1C */ /* made adaptive on stage1 BA MSE sofar */ + L_min_mse_saveC_fx = (23404216L << 1); move32();/* disable C selection in consecutive logic */ + ind_saveC_fx = 0; move16();/* a valid index that will not be used */ + } + ELSE + { + /* search another set (pitch dependent section C) of 170 mean residual vectors */ + /* pitch_info rx used to selects a mean and then a trained residual 1x170W8 based harmonic outlier table */ + /* float means were based on Word16 S16Q11 values, so that BASOP and float always may become BE in synthesis*/ + FOR(i = 0; i < M; i++) { + target_fx[i] = sub(env[i], lrsns_st1CTrainedMapMeans_fx[meanC_ind][i]); + } + + + Word32 ind_saveC_ScaledW8_fx; + Word32 L_min_mse_saveC_ScaledW8_fx; + + ind_saveC_ScaledW8_fx = MSEsearchGenericScaledW8_fx(target_fx, lrsns_st1C_Both_Word8_fx, + lrsns_st1C_Both_scaleQ4_7p4bits_fx[1], lrsns_st1C_Both_inv_scaleQ15_7p4bits_fx[1], + M, 170, &(L_min_mse_saveC_ScaledW8_fx)); + + snslr_st1C_vector_dec_fx(ind_saveC_ScaledW8_fx, lrsns_st1C_Both_Word8_fx, lrsns_st1C_Both_scaleQ4_7p4bits_fx[1], lrsns_st1C_Both_inv_scaleQ15_7p4bits_fx[1], + M, 170, + st1_vectorC_fx + ); + + ind_saveC_fx = ind_saveC_ScaledW8_fx; + L_min_mse_saveC_fx = L_min_mse_saveC_ScaledW8_fx; + + FOR(i = 0; i < M; i++) + { + st1_vectorC_fx[i] = add(st1_vectorC_fx[i], lrsns_st1CTrainedMapMeans_fx[meanC_ind][i]); /* Q11 means*/ + } + +#ifdef FIX_BASOP_ENC_LRSNS_CBC_MSE + /* CB_C MSE search loop in BASOP is using lower resolution, than and the best possible calculation */ + /* recalc CB_C MSE with Q22 precision for a best possible CB decision */ + MSEsearchGeneric_fx(env, st1_vectorC_fx, M, 1, &L_min_mse_saveC_fx); /* reuse of search to get MSE for 1 vector */ +#endif + + } +#ifdef WMOPS + pop_wmops(); +#endif + + + /* BC stage1 comparison */ + /* initially assume B as stage 1 winner */ + L_min_mse_saveBC_fx = L_min_mse_saveB_fx; move32(); + L_index[0] = L_deposit_l(*ind_saveB_ptr); /* 0...169 */ + + basop_memcpy(st1_vector_fx, st1_vectorB_fx, sizeof(Word16)*M); /* stage 1 segmentB result without DC copied as base for st2 */ + + { + IF(L_sub(L_min_mse_saveC_fx, L_min_mse_saveBC_fx) < 0) + { /* C better than B */ + L_min_mse_saveBC_fx = L_min_mse_saveC_fx; move32(); + L_index[0] = L_add(170L, L_deposit_l(ind_saveC_fx)); /* [2x 170] (9+3)b [ 0..169], [170-339] , ">=170" is a signal to multiplexor */ + basop_memcpy(st1_vector_fx, st1_vectorC_fx, sizeof(Word16)*M); + } + L_index[1] = -10; move32(); + ASSERT(L_min_mse_saveBC_fx >= 0.0); + + /* (9(A)<->10(BC) bit weighted comparison */ + *L_min_mse_saveBCA_ptr_fx = L_min_mse_saveBC_fx; move32(); + IF(L_sub(Mpy_32_16_lc3plus(L_min_mse_saveA_fx, SNSLR_A_CNST_WEIGHT), L_min_mse_saveBC_fx) < 0) /* a minor favouring of the 9b vector results sqrt(0.875) => approx 0.6dB level domain */ + { + L_index[0] = L_add(510L, L_deposit_l(ind_saveA_fx)); /* only [510,511] possible */ + L_index[1] = -9; + + basop_memcpy(st1_vectorA_fx, &(lrsns_cbA_fx[ind_saveA_fx*M]), sizeof(Word16)*M); + basop_memcpy(st1_vector_fx, st1_vectorA_fx, sizeof(Word16)*M); + + *L_min_mse_saveBCA_ptr_fx = Mpy_32_16_lc3plus(L_min_mse_saveA_fx, SNSLR_A_CNST_WEIGHT); /* Q22 */ + } + } + + /* index0_saveBCA = index[0];*/ /* 0...511 */ + /* index1_saveBCA = index[1];*/ /* -9 or -10 */ + + stage1_mode = 2; move16(); /* cbC */ + if (L_sub(L_index[0], 510L) >= 0) { + stage1_mode = 0; move16(); /* cbA */ + } + if (L_sub(L_index[0], 169L) <= 0) { + stage1_mode = 1; move16();/* cbB */ + } + +#ifdef WMOPS + pop_wmops(); +#endif + + Dyn_Mem_Deluxe_Out(); + + return stage1_mode; /* return best mode */ +} + +/* top level lrsns BASOP code calling both st1 and st2 */ +Word16 snsQuantScfEncLR_fx( /* o: bits spent on LRSNS-VQ envelope */ + Word16 scf_fx[], /* i: input scf M W16Q11 */ + Word32 *L_index_fx, /* o: SNS indeces . */ +#ifdef ENABLE_HR_MODE + Word32 *L_scf_q_fx, /* o: quantizefl_env scf M ? W32Q11 or W32Q27 */ +#else + Word16 *scf_q_fx, /* o: quantizefl_env scf M W16Q11 */ +#endif + Word16 pitch_rx_fx, /*i: 0 or 1 */ + Word16 ltpf_rx_fx, /*i: o or 1 */ + Word8 * scratch) +{ + + Dyn_Mem_Deluxe_In( + Counter col; + + Word16 *st1_vectorA_fx, *st1_vectorB_fx, *st1_vectorC_fx, *st1_vector_fx; + Word16 ind_saveB_fx; + Word16 st1_mode_fx; + Word16 envelope_bits_fx; /* output */ + Word32 L_min_mse_saveBCA_Q22_fx; + + Word16 gain_idx_fx; /* gain index 0..3, 0..7, 0..7 */ + Word16 s_idx_fx; /* shape index 0 =split, 1 = full, 2= fix*/ + Word16 shape_idx_fx; /* expanded shape index 0 ..5 */ + Word32 L_mse_st1B_st2_Q22_fx; + Word16 *y_split_fx, *y_full_fx, *y_fix_fx; + Word16 gainValQ12_fx; /* output from PVQ search */ + Word16 fixShapeNb; + Word16 fixShiftIdx; + + /* scratch ptrs */ + Word16 *st1_vectors_fx; + Word16 *target_st2_fx; + Word8 *scratch_ABC_fx; + Word32 *L_target_st2_fx; /* req. for dct32 use */ + Word16 *pvq_target_fx; + Word32 *L_pvq_target_fx; + Word16 *y_Q0; + Word16 *y_normQ14_fx; + Word32 *L_y_normQ30_fx; + Word8 *scratch_pvq_fess_fx; + ); + + +#ifdef ENABLE_HR_MODE + Word16 scf_q_fx[M]; /* W16Q11 always in use also for HR_MODE */ + UNUSED(scf_q_fx); +#endif + UNUSED(st1_mode_fx); + UNUSED(st1_vectorA_fx); + UNUSED(st1_vectorC_fx); + + st1_mode_fx = -1; move16(); + envelope_bits_fx = -1; move16(); /* output information */ + shape_idx_fx = 0; move16(); + + st1_vectors_fx = (Word16*)scratchAlign(scratch, 0); + scratch_ABC_fx = (Word8*)scratchAlign(st1_vectors_fx, sizeof(*st1_vector_fx) * M * 4); + target_st2_fx = (Word16*)scratch_ABC_fx; + L_target_st2_fx = (Word32*)scratchAlign(target_st2_fx, sizeof(*target_st2_fx) * M); + + pvq_target_fx = (Word16*)scratchAlign(L_target_st2_fx, sizeof(*L_target_st2_fx) * M); + L_pvq_target_fx = (Word32*)scratchAlign(pvq_target_fx, sizeof(*pvq_target_fx) * M); + y_Q0 = (Word16*)scratchAlign(L_pvq_target_fx, sizeof(*L_pvq_target_fx) * M); + y_normQ14_fx = (Word16*)scratchAlign(y_Q0, sizeof(*y_Q0) *SNSLR_MAX_PVQ_SEARCH_CAND*M); + L_y_normQ30_fx = (Word32*)scratchAlign(y_normQ14_fx, sizeof(*y_normQ14_fx) *SNSLR_MAX_PVQ_SEARCH_CAND*M); + scratch_pvq_fess_fx = (Word8*)scratchAlign(L_y_normQ30_fx, sizeof(*L_y_normQ30_fx) * SNSLR_MAX_PVQ_SEARCH_CAND * M ); + + y_split_fx = &(y_Q0[0 * M]); /* ptr init */ + y_full_fx = &(y_Q0[1 * M]); /* ptr init */ + y_fix_fx = &(y_Q0[2 * M]); /* ptr init */ + + st1_vectorA_fx = &(st1_vectors_fx[0]); /* ptr init */ + st1_vectorB_fx = &(st1_vectors_fx[1 * M]); + st1_vectorC_fx = &(st1_vectors_fx[2 * M]); + st1_vector_fx = &(st1_vectors_fx[3 * M]); /* best vector */ + + FOR(col = 0; col < SCF_MAX_PARAM; col++) + { + L_index_fx[col] = L_sub(-32000, col); move32(); /* safety init parameters to be fwd'ed to LRSNS VQ multiplexor */ + } + + /* Stage 1 Cb's A,B,C */ + ind_saveB_fx = -1; + L_min_mse_saveBCA_Q22_fx = M * 32 * 32; move32(); + + st1_mode_fx = snsQuantScfEncLRSt1ABC_fx( + scf_fx, L_index_fx, &L_min_mse_saveBCA_Q22_fx, &ind_saveB_fx, st1_vectors_fx, + pitch_rx_fx, ltpf_rx_fx, scratch_ABC_fx); + + Word32 L_mse_lim_smooth_Q22_fx = 22691185L; /* round(5.41*pow(2.0, 22.0))*//* 1.75 dB */ + + /* mse_st1B_st2_fl = 2.0* min_mse_saveBCA + 1.0;*/ /* safety indicate that st1B+st2 is not used by setting a higher MSE than st1BCA */ + L_mse_st1B_st2_Q22_fx = L_add(L_shl_pos(L_min_mse_saveBCA_Q22_fx, 1), (1L << 22)); /* set st1B+st2 to a safety bad MSE value */ + + + IF((L_sub(L_min_mse_saveBCA_Q22_fx, L_mse_lim_smooth_Q22_fx) > 0)) + { /* stage 2 analysis */ + /* prepare stage2 W16 target */ + FOR(col = 0; col < M; col++) + { + target_st2_fx[col] = sub(scf_fx[col], st1_vectorB_fx[col]); /* Q11 */ + } + + /* both ENABLE_HR and DISABLE_HR runs the same analysis DCT-II(16) */ + /* for analysis use 16 bit i/o Word16 constants, but Word32 internal states in DCT-II(M=16) */ + basop_memcpy(pvq_target_fx, target_st2_fx, M * sizeof(*pvq_target_fx)); + + dct16_W32int_fx(pvq_target_fx, pvq_target_fx); /* Q11 to Q11, enc-side analysis with W16 i/o internally W32 precision */ + + pvq_target_fx[0] = 0; move16(); + + /* PVQ FESS search, include norm , shape search and Q gain search */ + /* NB IDCT-II __not__ run in stage2 shape and gain search */ + pvq_fess_enc_search_fx( + pvq_target_fx, + y_Q0, + y_normQ14_fx, /* normally calculated for DISABLE_HR_MODE */ + L_y_normQ30_fx, /* calculated for both DISABLE_HR_MODE and ENABLE_HR_MODE */ + &s_idx_fx/*[0,1,2]*/, + &gain_idx_fx/* [0...7]*/, + &gainValQ12_fx, + &fixShapeNb, /* 0,1,2,3, [-1] */ + &fixShiftIdx, /* 0,1,2,3, [-1] */ + &L_mse_st1B_st2_Q22_fx, + scratch_pvq_fess_fx); + + + /* update to shape idx to one of 0...5 ] */ + shape_idx_fx = s_idx_fx; move16(); + if (sub(shape_idx_fx, 2) == 0) + { + shape_idx_fx = add(shape_idx_fx, fixShapeNb); /* [0..5] */ + } + } + ELSE + { /* indicate complete skipping of stage2 search, stage1 is good enough */ + L_mse_st1B_st2_Q22_fx = INT32_MAX; move32(); + /*copy of best stage 1 to proper output , done below */ + } + + IF(L_sub(L_mse_st1B_st2_Q22_fx, L_min_mse_saveBCA_Q22_fx) > 0) + { + /* skip IDCT, as stage2 will not be used */ + //L_mse_st1B_st2_Q22_fx = L_mse_st1B_st2_Q22_fx; /* dummy op */ + } + ELSE + { +#ifdef ENABLE_HR_MODE + /* apply IDCT-II on the Q30 unit energy normalized vector */ + Word32 L_tmp_vec_fx[M]; + Word32* L_y_norm_fx = &(L_y_normQ30_fx[s_idx_fx*M]); move32(); + + ASSERT(L_y_norm_fx[0] == 0); + /* 32x32 bit dec IDCT-II analysis, with W32 internal constants */ + idct32_32_fx(L_y_norm_fx, L_tmp_vec_fx); /* currently Q30 to Q30 , can also be inplace */ + /* idct32_32_fx:: 162.712 dBSegSNR, minSNR = 157.979, WMOPS 0.26 */ +#else + Word16 tmp_vec_fx[M]; + /* apply IDCT-II on the Q14 unit energy normalized vector */ + + Word16* y_norm_fx = &(y_normQ14_fx[s_idx_fx*M]); move32(); + ASSERT(y_norm_fx[0] == 0); + idct16_fx(y_norm_fx, tmp_vec_fx); /* idct16_fx:: segsnr 73.7 /minsnr 67.65 , 0.118 WMOPS using mult_r) */ +#endif /* HR_MODE*/ + +#ifdef ENABLE_HR_MODE + /* move stage1 W16Q11 to W32Q27 */ + FOR(col = 0; col < M; col++) + { + L_scf_q_fx[col] = L_deposit_h(st1_vectorB_fx[col]); /* W16Q11 to W32Q27 */ + } + lrsns_pvq_dec_scale_W32vec_fx(L_tmp_vec_fx, gainValQ12_fx, L_scf_q_fx /* W32Q27 in, W32Q26 out */, scf_q_fx /* W16Q11 out */); +#else + /* non HR */ + /* move stage1B into a W16 vector for accumulation in Q11 */ + basop_memcpy(scf_q_fx, st1_vectorB_fx, sizeof(*scf_q_fx)*M); + + /* scf_q_fx contains stage1 in Q11*/ + lrsns_pvq_dec_scale_W16vec_fx(tmp_vec_fx/*Q14*/, gainValQ12_fx, scf_q_fx /* Q11 */); /* scf_q_fx is the final result incl. stage2 in Q11 */ + +#endif /* ENABLE_HR_MODE */ + } + + + /* post-evaluate if one of (st1B, st1C, st1A) was actually better than st1B+stage2 */ + + IF(L_sub(L_mse_st1B_st2_Q22_fx, L_min_mse_saveBCA_Q22_fx) <= 0) + { + /* use stage1B + st2 at 29b or 30b bits total cost */ + L_index_fx[0] = L_deposit_l(ind_saveB_fx); move32(); + L_index_fx[1] = L_deposit_l(2930); move32(); /* later stage2 aux value LS_splitLF or LS_full or s0, put here as a 0 or 1 */ + L_index_fx[2] = L_deposit_l(shape_idx_fx); move32(); /* 0=splitLF, 1=full, ( 2=fixEnv0, 3=fixEnv1, 4: fixEnv2, 5: fixEnv3 ) */ + L_index_fx[3] = L_deposit_l(gain_idx_fx); move32(); /* gain idx with a shape dependent number of levels (4 or 8 levels ) */ + + basop_memcpy(st1_vector_fx, st1_vectorB_fx, sizeof(*st1_vectorB_fx)*M); + /* final result st1 in combination with stage 2, kept now for verification at decoder */ + + envelope_bits_fx = 29; move16(); /* 'LR_splitLF' bitrate */ + test(); + if (shape_idx_fx > 0) { + envelope_bits_fx = add(envelope_bits_fx, 1); /*30 'LR_full/LR_fixenv' */ + } + + { + /* DBG check values */ + ASSERT(shape_idx_fx >= 0); + ASSERT(envelope_bits_fx >= 29); + ASSERT(L_index_fx[0] <= 170); /*only B allowed */ + ASSERT(L_index_fx[1] >= 0); + + ASSERT(gain_idx_fx >= 0); /*gain index*/ + ASSERT(gainValQ12_fx > 0); /* gain value */ + } + } + ELSE + { /*stick to stage1(best of BCA) at 9 or 10 bits */ + ASSERT(L_index_fx[1] < 0 && L_index_fx[0] >= 0 && L_index_fx[0] < 512); + envelope_bits_fx = ((L_index_fx[0] >= 510) ? 9 : 10); + shape_idx_fx = -envelope_bits_fx; /* signal an invalid stage2 shape number to enc-entropy */ +#ifdef ENABLE_HR_MODE + FOR(col = 0; col < M; col++) + { + L_scf_q_fx[col] = L_shl_pos(st1_vector_fx[col], 16 - 1); move32(); /* W16Q11 to W32Q26 */ + } +#else + basop_memcpy(scf_q_fx, st1_vector_fx, M * sizeof(*scf_q_fx)); /* output */ +#endif + + gainValQ12_fx = 0; move16(); + + gain_idx_fx = -1; move16(); /* L_index sentinel */ + L_index_fx[2] = shape_idx_fx; move32(); + } + + /******************************************************************/ + /* signal to enc_entropy_fx for LRSNS semi-fractional multiplexing */ + /******************************************************************/ + /* integer multiplexing 29/30 bit modes into intermediate unmuxed integer indeces 0...7 */ + /* a bit of fractional multiplexing for the L_index_fx 0...7 is done later, in function enc_entropy_fx() */ + test(); + IF(shape_idx_fx >= 0) + { /* stage 2 multiplexing manipulations */ + Word16 fix_end_sign_fx; + + PvqEntry_fx enc_PVQ_A, enc_PVQ_B; + + test(); + IF(shape_idx_fx == 0) + { /* splitLF shape */ + Word16 n5k = 0; + FOR(col = 1; col < 6; col++) + { + n5k += abs_s(y_split_fx[col]); + } + + IF(sub(n5k, PULSES_SPLIT_A_LR) == 0) + { + /* this (6+2) pulses over NA+NB=5+8, is expected to be more frequent than 8 pulses over NA=5 */ + enc_PVQ_A = mpvq_index_fx(&(y_split_fx[1]), NA_LR, PULSES_SPLIT_A_LR); /* P(N=5,K=6) (10)=10 bit L_index */ + L_index_fx[4] = (Word32)enc_PVQ_A.index; move32(); + L_index_fx[1] = L_deposit_l(enc_PVQ_A.lead_sign_ind); /* aux bit for the splitLF path , we plant the first LS there */ + + enc_PVQ_B = mpvq_index_fx(&(y_split_fx[1 + NA_LR]), NB_LR, PULSES_SPLIT_B_LR); + L_index_fx[5] = L_mac0(L_shl_pos((Word32)enc_PVQ_B.index, 1), 1, enc_PVQ_B.lead_sign_ind); move32(); /* A full PVQ 7 bit index for the P(N=8,K=2) B config*/ + + assert(L_index_fx[5] >= 0); + } + ELSE + { + ASSERT(n5k == (PULSES_SPLIT_A_LR + PULSES_SPLIT_B_LR));/* PVQ(N=5,K=8) (12.x in total, i.e. LS+ 11.x ) */ + enc_PVQ_A = mpvq_index_fx(&(y_split_fx[1]), NA_LR, PULSES_SPLIT_A_LR + PULSES_SPLIT_B_LR); + L_index_fx[4] = (Word32)enc_PVQ_A.index; + L_index_fx[1] = L_deposit_l(enc_PVQ_A.lead_sign_ind); /* aux bit for the splitLF path , we plant the first LS there */ + L_index_fx[5] = L_deposit_l(-8); /* signal LF PVQ(5,k=8) and zeroed HF(10,0) apart */ + } + } + IF(sub(shape_idx_fx, 1) == 0) + { /* full (15,5), LS kept separated */ + enc_PVQ_A = mpvq_index_fx(&(y_full_fx[1]), NFULL_LR, PULSES_FULL_LR);/* mPVQ 16.66 bits in index[4], and LS 1 bit in index[1] */ + L_index_fx[4] = (Word32)enc_PVQ_A.index; move32(); + L_index_fx[1] = L_deposit_l(enc_PVQ_A.lead_sign_ind); + } + + IF(sub(shape_idx_fx, 2) >= 0) + { /* fixEnv0, fixEnv1, fixEnv2, fixEnv3 */ + ASSERT(shape_idx_fx <= 5); + /* send the fixed env subshape mode to enc_entropy */ + L_index_fx[4] = L_deposit_l(sub(shape_idx_fx, 2)); /* env shape, 0-->"1" , 1--> "env1" */ /* L_index[2] has original shape 0...5 */ + + ASSERT(fixShapeNb == L_index_fx[4]); + ASSERT(fixShiftIdx < (1 << 2)); + + Word16 tmp1 = add(1, fixShiftIdx); + + /* aux_bit : 0 (or 1) , will indicate the s0 sign in the FESS fix shape */ + L_index_fx[1] = 0L; move32(); /* s0 positive */ + test(); + if (y_fix_fx[tmp1] < 0) + { + L_index_fx[1] = 1L; move32(); /* s0 negative*/ + } + + fix_end_sign_fx = 12; move16(); + if (sub(shape_idx_fx, 5) == 0) + { + ASSERT(L_index_fx[4] == 3L); /* final fix_envelope only has 10 signs */ + fix_end_sign_fx = 10; move16(); /* shape 5 has 2 bits shift and a total of 10 signs =2^10*2^2 = 2^12 = 4096 */ + } + + Word16 tmp = fixShiftIdx; move16(); /* the two shift bits will be pushed up to b11,b12, for 11 signs s1-s11 */ + + /* sign loop */ + FOR(int sign_ind_fx = 1; sign_ind_fx < fix_end_sign_fx; sign_ind_fx++) /* push the remaining sequential signs s1-s11(or s1-s9), into a single idx */ + { /* s1 is in the MSB, and s11 is in the LSB*/ + tmp = shl_pos(tmp, 1); /* shift in a zero */ + test(); + if (y_fix_fx[add(tmp1, sign_ind_fx)] < 0) /* "1" indicates negative, "0" means positive */ + { + tmp = add(tmp, 1); + } + } + L_index_fx[5] = L_deposit_l(tmp); + + ASSERT(L_index_fx[5] >= 0 && L_index_fx[5] < (1 << (2 + (fix_end_sign_fx - 1)))); + } + } /* end of stage2 premultiplexing , fractional packing aspects done within enc_entropy_fx() */ + + ASSERT(envelope_bits_fx == 9 || envelope_bits_fx == 10 || envelope_bits_fx == 29 || envelope_bits_fx == 30); + + Dyn_Mem_Deluxe_Out(); + return envelope_bits_fx; +} + +/* LRSNS function needed in both encoder and decoder */ +Word16 snslr_remove_st1_DC_fQ11_fx( /* o : dc in Q11 */ + Word16 *scfq, /* i/o: stage1B vector in Q11 */ + Word16 len /* i : length Q0 */ +) +{ + Dyn_Mem_Deluxe_In( + Counter i; + Word32 L_dcQ11; + Word16 dcQ11; + ); + assert(len == 16); +#ifdef WMOPS + push_wmops("snslr_remove_st1_DC_fQ11_fx"); +#endif + + L_dcQ11 = 0; move32(); + + for (i = 0; i < len; i++) { + L_dcQ11 = L_mac0(L_dcQ11, scfq[i], 2048); + } + dcQ11 = extract_h(L_shl_pos(L_dcQ11, 1)); /*NB ! same truncation needed in both CFL and in basop */ + + for (i = 0; i < len; i++) + { + scfq[i] = sub(scfq[i], dcQ11); move16(); /* result update */ + } + +#ifdef WMOPS + pop_wmops(); +#endif + Dyn_Mem_Deluxe_Out(); + + return dcQ11; /* output used for encoder side mse update*/ +} + + +void snslr_st1B_vector_dec_fx(Word16 idx, const Word16* LFCB, const Word16 *HFCB, const Word16* seg_cnt_cum, const Word16* idx12b_cb, Word16 *st1B_vectorQ11) +{ + /* decompose the received 0... 169 index , into the correct integer and float st1B vector */ + Dyn_Mem_Deluxe_In( + Counter i; + const Word16 *lf_cb, *hf_cb; + + Word16 seg_fx; + Word16 idx_12b_fx, lf_sign_fx; + Word16 hf_sign_fx; + Word16 idx_HF_fx; + Word16 idx_LF_fx; + Word16 st1B_W16Q11_fx[M]; + Word16 buf[M]; + ); + +#ifdef WMOPS + push_wmops("snslr_st1B_vector_dec_fx"); +#endif + assert(idx >= 0 && idx < 170); + + + seg_fx = 0; move16(); + WHILE(sub(seg_cnt_cum[add(seg_fx, 1)], idx) <= 0) + { + seg_fx = add(seg_fx, 1); + } + + assert(seg_fx >= 0 && seg_fx < 4); + + idx_12b_fx = idx12b_cb[idx]; /* indirect lookup from sequential value to a coded 12b index*/ + + lf_sign_fx = 1; move16(); /* assume a 0 bit -> "+" */ + if (s_and(0x0800, idx_12b_fx) != 0) { + lf_sign_fx = -1; move16(); /* assume a 1 bit -> " -" */ + } + + hf_sign_fx = 1; move16(); /* assume a 0 bit -> "+" */ + if ((s_and(0x0400, idx_12b_fx)) != 0) { + hf_sign_fx = -1; move16(); /* assume a 1 bit -> "-" */ + } + idx_LF_fx = shr_pos(s_and(0x03e0, idx_12b_fx), 5); + idx_HF_fx = s_and(0x001f, idx_12b_fx); + + /* extseg0 f,f */ + lf_cb = &(LFCB[idx_LF_fx*(M / 2)]); L_mult(0, 0); /* mult and pointer init */ + hf_cb = &(HFCB[idx_HF_fx*(M / 2)]); L_mult(0, 0); /* mult and pointer init */ + + FOR(i = 0; i < (M / 2); i++) + { + st1B_W16Q11_fx[i] = i_mult(lf_sign_fx, lf_cb[i]); /* imult() to switch sign without changing dynamics*/ + st1B_W16Q11_fx[M / 2 + i] = i_mult(hf_sign_fx, hf_cb[i]); + } + + basop_memcpy(buf, st1B_W16Q11_fx, sizeof(*buf)*M); /* buffer cpy needed for reversal sections */ + + IF(s_and(seg_fx, 0x0002) != 0) + { /* r,* */ /* flip LF */ + FOR(i = 0; i < (M / 2); i++) + { + st1B_W16Q11_fx[i] = buf[(M / 2 - 1) - i]; move16(); + } + } + + IF(s_and(seg_fx, 0x0001) != 0) + { /* *,r */ /* flip HF */ + FOR(i = 0; i < (M / 2); i++) + { + st1B_W16Q11_fx[(M / 2) + i] = buf[(M - 1) - i]; move16(); + } + } + + basop_memcpy(st1B_vectorQ11, st1B_W16Q11_fx, M * sizeof(*st1B_vectorQ11)); + +#ifdef WMOPS + pop_wmops(); +#endif + Dyn_Mem_Deluxe_Out(); +} + +Word16 MSEsearchCbBIdxMap_fx(const Word16 *scf, const Word16 *LFCB, const Word16 *HFCB, const Word16 *seg_cnt_cum, const Word16* idx12b_cb, Word16 v_len, Word16 cb_len, Word32* min_mse) +{ + Dyn_Mem_Deluxe_In( + + Counter seg, i, j; /*counters */ + + Word16 scfLF_Q11[M]; + + Word16* scfHF_Q11; + const Word16 *lf_cb, *hf_cb; + Word16 idx_12b, signbitLF, signbitHF, idx_LF, idx_HF; + Word32 L_mse_best_fx; + Word16 best_ind; + ); + UNUSED(v_len); + UNUSED(cb_len); + Word32 L_tEnBy2; + Word32 L_cbEnBy2; + Word32 L_mseBy2; /* sum( t_i^2 + cbB_i^2 - 2*t_i*cbB_i )/2 */ + + + + + /* MSE separated into targetEn + vectorB_en - 2 *correlation t*cbB */ + /* vectorBenergy is obtained from addition of two Word32 lookup tables LFen and HFen */ + + +#ifdef WMOPS + push_wmops("MSEsearchCbBIdxMap_fx"); +#endif + + L_mse_best_fx = INT_MAX; move32(); + best_ind = -1; /*for debug*/ + + assert(v_len == M); + + L_tEnBy2 = L_mult0(scf[0], scf[0]); + FOR(i = 1; i < M; i++) + { + L_tEnBy2 = L_mac0(L_tEnBy2, scf[i], scf[i]); /* calc target Energy part of MSE */ + } + L_tEnBy2 = L_shr_pos_pos(L_tEnBy2, 1); + + + scfHF_Q11 = (&scfLF_Q11[M / 2]); /* ptr init */ + + FOR(seg = 0; seg < 4; seg++) + { + basop_memcpy(scfLF_Q11, scf, M * sizeof(*scfLF_Q11)); + /*seg==0: fwd, fwd *//*seg==1: fwd, rev *//*seg==2: fwd, fwd */ /*seg==3: rev, rev */ + + IF(s_and(seg, 0x0002) != 0) + { /* {r,*} */ /* flip LF */ + FOR(i = 0; i < (M / 2); i++) + { + scfLF_Q11[i] = scf[(M / 2 - 1) - i]; move16(); + } + } + IF(s_and(seg, 0x0001) != 0) + { /* {*,r} */ /* flip HF */ + FOR(i = 0; i < (M / 2); i++) + { + scfHF_Q11[i] = scf[(M - 1) - i]; move16(); + } + } + + FOR(i = seg_cnt_cum[seg]; i < seg_cnt_cum[add(seg, 1)]; i++) + { + /* Note: these 4 subindex extractions can be in parallel */ + idx_12b = idx12b_cb[i]; /* tmp variable, indirect adressing lookup of 12b index pointing to LF and HF + individual sign swaps */ + + idx_LF = shr_pos_pos(s_and(0x03e0, idx_12b), 5); /* b9...b5 */ + idx_HF = s_and(0x001f, idx_12b); /* b4...b0 lowest 5 bits */ + + L_cbEnBy2 = L_add(lrsns_st1B_enBy2TabW32_fx[idx_LF], lrsns_st1B_enBy2TabW32_fx[32 + idx_HF]); /* ptr init to HF tab*/ + + signbitLF = s_and(0x0800, idx_12b); /* b11 logical 0 or 2048 */ + signbitHF = s_and(0x0400, idx_12b); /* b10 logical 0 or 1024 */ + + /* conditional update of signed section offsets */ + if (signbitLF != 0) + { + idx_LF = add(idx_LF, 32); /* point to negated part of lf_cb */ + } + if (signbitHF != 0) + { + idx_HF = add(idx_HF, 32); /* point to negated part of hf_cb */ + } + + lf_cb = &(LFCB[idx_LF * M / 2]); /* adaptive ptr init */ + hf_cb = &(HFCB[idx_HF * M / 2]); /* adaptive ptr init */ + + L_mseBy2 = L_add(L_tEnBy2, L_cbEnBy2); /* in ARM one op per cbB idx [0..169] can likely be saved by adding targetEnergyBy2 last */ + + /* mse/2 = tEn^2/2 + cbEn^2/2 - corr(target_v, (sign)*cb_v ) */ + FOR(j = 0; j < (M / 2); j++) + { + /* cycles saved by extending the LF and HF tables with negated versions */ + L_mseBy2 = L_msu0(L_mseBy2, scfLF_Q11[j], lf_cb[j]); /* acc with -1 * t*c , cb sign set by lf_cb */ + L_mseBy2 = L_msu0(L_mseBy2, scfHF_Q11[j], hf_cb[j]); /* acc -1* t*c with cb sign set by hf_cb ptr */ + } + ASSERT(L_mseBy2 >= 0); + /* always update best case */ + L_mse_best_fx = L_min(L_mseBy2, L_mse_best_fx); /* 1 cycle BASOP update */ + + if (L_sub(L_mseBy2, L_mse_best_fx) == 0) + { + best_ind = ((Word16)i); move16(); /* update winner, cond move , single BASOP */ + } + } /* one segment seg*/ + } /* all segms */ + + *min_mse = L_add(L_mse_best_fx, L_mse_best_fx); /* multiply halved MSEby2 to get final MSE */ + + assert(best_ind >= 0 && best_ind < cb_len); + +#ifdef WMOPS + pop_wmops(); /* func */ +#endif + Dyn_Mem_Deluxe_Out(); + + return best_ind; +} + +void snslr_st1C_vector_dec_fx(Word16 idx, const Word8* CBW8, Word16 scaleQ4, Word16 inv_scaleQ15, Word16 v_len, Word16 cb_len, Word16 *st1C_vector) +{ + /* decompose the received 0... 169 index , into the correct (integer and) float st1C vector */ + /* even in C-float the st1C coeffs are put into a S16Q11 final integers domain */ + /* Enables BE compatibility between {BASOP, float, double} arithmetic implmentations */ + Dyn_Mem_Deluxe_In( + Counter i; + const Word8 *cb; + Word32 L_tmp; + Word16 s_tmp; + ); + UNUSED(v_len); + UNUSED(cb_len); + UNUSED(inv_scaleQ15); /* req for debugging only */ + +#ifdef WMOPS + push_wmops("snslr_st1C_vector_dec_fx"); +#endif + + assert(idx >= 0 && idx < cb_len); + assert(v_len == M); + + cb = &(CBW8[idx*M]); move16(); /* pointer init */ + FOR(i = 0; i < M; i++) + { + L_tmp = L_mult0((Word16)cb[i], scaleQ4); /*S8Q7 * S15Q4 */ /*sign+7bit, sign+4 bits --> sign+11bit .lt sign+23 bits*/ + s_tmp = extract_l(L_tmp); + assert(L_tmp >= -32768L && L_tmp <= 32767L); /* INT16 domain check*/ + st1C_vector[i] = s_tmp; + } + +#ifdef WMOPS + pop_wmops(); +#endif + Dyn_Mem_Deluxe_Out(); +} + +Word16 MSEsearchGenericScaledW8_fx(Word16 *scf, const Word8 *sns_CBW8, Word16 scaleQ4, Word16 inv_scaleQ15, Word16 v_len, Word16 cb_len, Word32* L_min_mse) +{ + /* scf float input values are typically in the range +12.0 to -12.0. + rom table stored in Word8 [+127,-128], format corresponding to ]+1.0 .. -1.0 ] + inv_scaleQ15, [downscaling value in Q15] applied before search + scaleQ12 upscaling value quantized in Q12, used in the mse calulation and in the common float and BASOP synthesis routines + + */ + Dyn_Mem_Deluxe_In( + Counter i, n; + Word32 best_ind; + Word32 L_mse, L_mse_best; + Word16 targetW16[M]; + const Word8 * cbW8; + Word16 shift_mse; + Word16 tmp; + ); + +#ifdef WMOPS + push_wmops("MSEsearchGenericScaledW8_fx"); +#endif + FOR(i = 0; i < v_len; i++) + { + targetW16[i] = shr_pos(mult(scf[i], inv_scaleQ15), 4); /* target from W16Q11 to W8Q7 domain , and floor */ + }; + + best_ind = -1; /* needed to avoid compiler warning */ + + /* use use S1.15 wise multiplication operations QSUB16 for two coeffs correlation */ + /* L_msu0 can use 16 bit input only e.g. SMLSLD */ + + /* MSE_i = sum(i=0,15, (t_i-c_i)*(t_i-c_i) ) = sum(i=0,15, (t_i)^2 + c_i^2 - 2*(t_i*c_i) ) */ + /* store EnC_i = sum(1,16) c_i^2 , in a Word32 ROM entry , 170 entries , or potentially in Word16 */ + /* calculate MSE_i = EnT+EnC - sum (2*t_i*c_i) */ + /* or even calculate MSE_i/2 = enT/2 + EnC/2 - sum( t_i*c_i) , as an approximation of MSE */ + + /* commmon target contribution to MSE */ + + Word32 L_targetEn = 0; move32(); + if (v_len > 0) { + L_targetEn = L_mult0(targetW16[0], targetW16[0]); + FOR (i = 1; i < v_len; i++) + { + L_targetEn = L_mac0(L_targetEn, targetW16[i], targetW16[i]); + } + } + L_mse_best = INT32_MAX; move32(); /* largest possible positive number in INT32 */ + + FOR(i = 0; i < cb_len; i++) + { + cbW8 = &(sns_CBW8[i*M]); /* ptr init += i*16 */ + assert(v_len == M); + + L_mse = L_deposit_l(lrsns_st1C_Both_EnBy2Tab_fx[i]); /* scaled down CB energy by 2 from ROM to allow use of L_msu0 for best ARM ops */ + L_mse = L_add(L_mse, L_shr_pos_pos(L_targetEn, 1)); /* scale down target energy by 2 to allow use of L_msu0 for best ARM ops */ + + FOR(n = 0; n < v_len; n++) + { /* correlate is fast in most ARM cases, as SIMD or as blocks of 4 */ + L_mse = L_msu0(L_mse, targetW16[n], (Word16)(cbW8[n])); /* no upscaling included in L_msu0() */ + } + + assert(L_mse >= 0); /* check that error is always positive, otherwise we might get overflow in the subtraction below */ + if (L_sub(L_mse, L_mse_best) <= 0) + { + best_ind = i; move16(); /* single BASOP, conditional move, for best_ind update */ + } + L_mse_best = L_min(L_mse, L_mse_best); /* always update best MSE using L_min() in the idx loop, reduces WC WMOPS */ + } + L_mse_best = L_add(L_mse_best, L_mse_best); /* scale up by two from the BASOP/ARM optimized search mse domain */ + + + assert(best_ind >= 0 && best_ind < cb_len); + + *L_min_mse = L_mse_best; move32(); + + tmp = i_mult(scaleQ4, scaleQ4); /* non fractional square --> Q4 to Q8 */ + tmp = shl_pos(tmp, 2); /* a Q10 const */ + + shift_mse = norm_l(*L_min_mse); + + *L_min_mse = L_shl(*L_min_mse, shift_mse); + *L_min_mse = Mpy_32_16_lc3plus(*L_min_mse, tmp); /* still use max upshifting Mpy_32_16, here for this final Word32 L_mse output calculation */ + *L_min_mse = L_shr(*L_min_mse, add(shift_mse, 2 - 15)); + +#ifdef WMOPS + pop_wmops(); +#endif + Dyn_Mem_Deluxe_Out(); + + return best_ind; +} + +Word16 MSEsearchGeneric_fx(Word16 *scf, const Word16 *sns_CB, Word16 v_len, Word16 cb_len, Word32* L_min_mse) +{ + Dyn_Mem_Deluxe_In( + Counter i, n; + Word16 ind; + Word32 L_mse_best_fx, L_mse_fx; + Word16 tmp; + Word16 const *cb_ptr; + Word16 const *scf_ptr; + ); + +#ifdef WMOPS + push_wmops("MSEsearchGeneric_fx"); +#endif + ind = -1; /* avoid compiler warning */ + L_mse_best_fx = INT_MAX; move32(); + + FOR(i = 0; i < cb_len; i++) + { + L_mse_fx = L_deposit_l(0); + cb_ptr = &(sns_CB[i*v_len]); /* pointer init */ + scf_ptr = &(scf[0]); /* pointer init */ + FOR(n = 0; n < v_len; n++) + { + tmp = sub(*scf_ptr++, *cb_ptr++); + L_mse_fx = L_mac0(L_mse_fx, tmp, tmp); + } + + L_mse_best_fx = L_min(L_mse_fx, L_mse_best_fx); + if (L_sub(L_mse_fx, L_mse_best_fx) == 0) + { + ind = i; move16(); + } + } + + *L_min_mse = L_mse_best_fx; move32(); + + assert(ind >= 0 && ind < cb_len); +#ifdef WMOPS + pop_wmops(); +#endif + Dyn_Mem_Deluxe_Out(); + return ind; +} + +#endif diff --git a/lib_lc3plus/tinywavein_c.h b/lib_lc3plus/tinywavein_c.h deleted file mode 100644 index ff7e17ca4..000000000 --- a/lib_lc3plus/tinywavein_c.h +++ /dev/null @@ -1,603 +0,0 @@ -/****************************************************************************** -* ETSI TS 103 634 V1.5.1 * -* Low Complexity Communication Codec Plus (LC3plus) * -* * -* Copyright licence is solely granted through ETSI Intellectual Property * -* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * -* estoppel or otherwise. * -******************************************************************************/ - -#ifndef __TINYWAVEIN_C_H__ -#define __TINYWAVEIN_C_H__ - -/*#define SUPPORT_BWF*/ - -#include -#include -#include - -#if defined(__i386__) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64) || defined(__arm__) || \ - defined(__aarch64__) -#define __TWI_LE /* _T_iny _W_ave _I_n _L_ittle _E_ndian */ -#endif - -#if defined(__POWERPC__) -#define __TWI_BE /* _T_iny _W_ave _I_n _B_ig _E_ndian */ -#endif - -#if !defined(__TWI_LE) && !defined(__TWI_BE) -#error unknown processor -#endif - -#define __TWI_SUCCESS (0) -#define __TWI_ERROR (-1) - -#ifdef SUPPORT_BWF -typedef struct -{ - float loudnessVal; - float loudnessRange; - float maxTruePeakLevel; - float maxMomentaryLoudnes; - float maxShortTermLoudness; -} WAVEIN_LOUDNESSINFO; -#endif - -typedef struct __tinyWaveInHandle -{ - FILE * theFile; - fpos_t dataChunkPos; - unsigned int position; - unsigned int length; - unsigned int bps; -#ifdef SUPPORT_BWF - WAVEIN_LOUDNESSINFO *loudnessInfo; -#endif -} __tinyWaveInHandle, WAVEFILEIN; - -typedef struct -{ - short compressionCode; - short numberOfChannels; - unsigned int sampleRate; - unsigned int averageBytesPerSecond; - short blockAlign; - short bitsPerSample; - /* short extraFormatBytes ; */ -} SWavInfo; - -#ifdef SUPPORT_BWF -typedef struct -{ - unsigned char description[256]; - unsigned char originator[32]; - unsigned char originatorReference[32]; - unsigned char originatorDate[10]; /* ASCII: <> */ - unsigned char originationTime[8]; /* ASCII: <> */ - unsigned int timeReferenceLow; - unsigned int timeReferenceHigh; - unsigned short version; - unsigned char UMID[64]; /* Binary Bytes of SMPTE UMID */ - - signed short loudnessVal; - signed short loudnessRange; - signed short maxTruePeakLevel; - signed short maxMomentaryLoudnes; - signed short maxShortTermLoudness; - - unsigned char Reserved[180]; - - unsigned char codingHistory; /* ASCII: <> */ -} SBwfWav; -#endif - -typedef struct -{ - char chunkID[4]; - unsigned int chunkSize; - /* long dataOffset ; */ /* never used */ -} SChunk; - -/* local wrapper, always returns correct endian */ -static size_t fread_LE(void *ptr, size_t size, size_t nmemb, FILE *stream); - -#ifdef __TWI_BE -static short BigEndian16(short v); -static int BigEndian32(int v); -#endif - -/*! - * \brief Read header from a WAVEfile. Host endianess is handled accordingly. - * \fp filepointer of type FILE*. - * \wavinfo SWavInfo struct where the decoded header info is stored into. - * \return 0 on success and non-zero on failure. - * - */ -static WAVEFILEIN *OpenWav(const char *filename, unsigned int *samplerate, short *channels, unsigned int *samplesInFile, - short *bps) -{ - WAVEFILEIN *self; - - SChunk fmt_chunk, data_chunk; - int offset; - unsigned int tmpSize; - char tmpFormat[4]; - SWavInfo wavinfo = {0, 0, 0, 0, 0, 0}; - - self = (WAVEFILEIN *)calloc(1, sizeof(WAVEFILEIN)); - if (!self) - goto bail; /* return NULL; */ - - if (!filename) - goto bail; - if (!samplerate) - goto bail; - if (!channels) - goto bail; - if (!samplesInFile) - goto bail; - if (!bps) - goto bail; - - self->theFile = fopen(filename, "rb"); - if (!self->theFile) - goto bail; - - /* read RIFF-chunk */ - if (fread(tmpFormat, 1, 4, self->theFile) != 4) - { - goto bail; - } - - if (strncmp("RIFF", tmpFormat, 4)) - { - goto bail; - } - - /* Read RIFF size. Ignored. */ - fread_LE(&tmpSize, 4, 1, self->theFile); - - /* read WAVE-chunk */ - if (fread(tmpFormat, 1, 4, self->theFile) != 4) - { - goto bail; - } - - if (strncmp("WAVE", tmpFormat, 4)) - { - goto bail; - } - - /* read format/bext-chunk */ - if (fread(fmt_chunk.chunkID, 1, 4, self->theFile) != 4) - { - goto bail; - } - -#ifdef SUPPORT_BWF - /* test for bext-chunk */ - if (!strncmp("bext", fmt_chunk.chunkID, 4)) - { - /*unsigned int i;*/ - unsigned int bextSize = 0; - - if (fread_LE(&bextSize, 1, 4, self->theFile) != 4) - { - goto bail; - } - - self->loudnessInfo = (WAVEIN_LOUDNESSINFO *)calloc(1, sizeof(WAVEIN_LOUDNESSINFO)); - - if (bextSize >= 602) - { /* minimum size bext-data, w/o 'CodingHistory' */ - int i; - signed short readBuf = 0; - signed int nulbuf = 0; - - /* first skip all descriptive data */ - for (i = 0; i < 412; i++) - { - if (fread_LE(&nulbuf, 1, 1, self->theFile) != 1) - { - goto bail; - } - bextSize -= 1; - } - /* second, read loudness data */ - fread_LE(&readBuf, 2, 1, self->theFile); - bextSize -= 2; - self->loudnessInfo->loudnessVal = (float)readBuf * 0.01f; - - fread_LE(&readBuf, 2, 1, self->theFile); - bextSize -= 2; - self->loudnessInfo->loudnessRange = (float)readBuf * 0.01f; - - fread_LE(&readBuf, 2, 1, self->theFile); - bextSize -= 2; - self->loudnessInfo->maxTruePeakLevel = (float)readBuf * 0.01f; - - fread_LE(&readBuf, 2, 1, self->theFile); - bextSize -= 2; - self->loudnessInfo->maxMomentaryLoudnes = (float)readBuf * 0.01f; - - fread_LE(&readBuf, 2, 1, self->theFile); - bextSize -= 2; - self->loudnessInfo->maxShortTermLoudness = (float)readBuf * 0.01f; - - /* skip reserved data */ - for (i = 0; i < 180; i++) - { - if (fread_LE(&nulbuf, 1, 1, self->theFile) != 1) - { - goto bail; - } - bextSize -= 1; - } - } - - /* skip remaining data */ - while (bextSize) - { - int nulbuf; - if (fread_LE(&nulbuf, 1, 1, self->theFile) != 1) - { - goto bail; - } - bextSize -= 1; - } - - /* read next chunk header */ - if (fread(fmt_chunk.chunkID, 1, 4, self->theFile) != 4) - { - goto bail; - } - } -#endif - - /* skip some potential chunks up to fmt chunk */ - - while (strncmp("fmt ", fmt_chunk.chunkID, 4) != 0) - { - unsigned int chunkSize = 0; - - if (fread_LE(&chunkSize, 1, 4, self->theFile) != 4) - { - goto bail; - } - - /* skip chunk data */ - while (chunkSize) - { - int nulbuf; - if (fread_LE(&nulbuf, 1, 1, self->theFile) != 1) - { - goto bail; - } - chunkSize -= 1; - } - - /* read next chunk header */ - if (fread(fmt_chunk.chunkID, 1, 4, self->theFile) != 4) - { - goto bail; - } - } - - /* go on with fmt-chunk */ - if (strncmp("fmt ", fmt_chunk.chunkID, 4)) - { - goto bail; - } - - if (fread_LE(&fmt_chunk.chunkSize, 4, 1, self->theFile) != 1) - { /* should be 16 for PCM-format (uncompressed) */ - goto bail; - } - - - /* read info */ - fread_LE(&(wavinfo.compressionCode), 2, 1, self->theFile); - fread_LE(&(wavinfo.numberOfChannels), 2, 1, self->theFile); - fread_LE(&(wavinfo.sampleRate), 4, 1, self->theFile); - fread_LE(&(wavinfo.averageBytesPerSecond), 4, 1, self->theFile); - fread_LE(&(wavinfo.blockAlign), 2, 1, self->theFile); - fread_LE(&(wavinfo.bitsPerSample), 2, 1, self->theFile); - - if (wavinfo.compressionCode == -2) - { - fseek(self->theFile, 8, SEEK_CUR); // skip channel mask - fread_LE(&(wavinfo.compressionCode), 2, 1, self->theFile); // part of GUID - fseek(self->theFile, 14, SEEK_CUR); // skip rest of GUID - offset = fmt_chunk.chunkSize - 40; - } - else - offset = fmt_chunk.chunkSize - 16; - - if (wavinfo.compressionCode == 0x01) - { - if ((wavinfo.bitsPerSample != 16) && (wavinfo.bitsPerSample != 24) && (wavinfo.bitsPerSample != 32)) - /* we do only support 16,24 and 32 bit PCM audio */ - goto bail; - } - else - { - /* if(wavinfo.bitsPerSample != 32) */ - printf("compressioncode: %02x\n", wavinfo.compressionCode); - puts("Error! We only support 16,24 and 32 bit PCM audio"); - exit(1); - goto bail; - } - - /* Skip rest of fmt header if any. */ - for (; offset > 0; offset--) - { - fread(&tmpSize, 1, 1, self->theFile); - } - - do - { - - /* Read data chunk ID */ - if (fread(data_chunk.chunkID, 1, 4, self->theFile) != 4) - { - goto bail; - } - - /* Read chunk length. */ - - if (fread_LE(&offset, 4, 1, self->theFile) != 1) - { - goto bail; - } - - /* Check for data chunk signature. */ - if (strncmp("data", data_chunk.chunkID, 4) == 0) - { - data_chunk.chunkSize = offset; - break; - } - - /* unused 1 byte present, if size is odd */ - /* see https://www.daubnet.com/en/file-format-riff */ - if (offset % 2) - { - offset++; - } - - /* Jump over non data chunk. */ - for (; offset > 0; offset--) - { - fread(&tmpSize, 1, 1, self->theFile); - } - - } while (!feof(self->theFile)); - - /* success so far */ - *samplerate = wavinfo.sampleRate; - *channels = wavinfo.numberOfChannels; - *samplesInFile = data_chunk.chunkSize / wavinfo.numberOfChannels; - *samplesInFile /= ((wavinfo.bitsPerSample + 7) / 8); - *bps = wavinfo.bitsPerSample; - - self->position = 0; - self->bps = wavinfo.bitsPerSample; - self->length = *samplesInFile * wavinfo.numberOfChannels; - - fgetpos(self->theFile, &self->dataChunkPos); - - return self; - -bail: - free(self); - return NULL; -} - -#ifdef SUPPORT_BWF -static void ReadBWF(WAVEFILEIN *self, WAVEIN_LOUDNESSINFO **wavInLoudness) -{ - *wavInLoudness = self->loudnessInfo; -} -#endif - -static int __ReadSample16(WAVEFILEIN *self, int *sample) -{ - size_t cnt; - short v = 0; - - cnt = fread(&v, 2, 1, self->theFile); - - if (cnt != 1) - { - return __TWI_ERROR; - } - - self->position += 1; - -#ifdef __TWI_BE - v = BigEndian16(v); -#endif - *sample = v; - return __TWI_SUCCESS; -} - -static int __ReadSample24(WAVEFILEIN *self, int *sample) -{ - size_t cnt; - int v = 0; - - cnt = fread(&v, 3, 1, self->theFile); - - if (cnt != 1) - { - return __TWI_ERROR; - } - - self->position += 1; - -#ifdef __TWI_BE - v = BigEndian32(v); -#endif - - if (v >= 0x800000) - { - v |= 0xff000000; - } - - *sample = v; - - return __TWI_SUCCESS; -} - -static int __ReadSample32(WAVEFILEIN *self, int *sample) -{ - size_t cnt; - int v = 0; - - cnt = fread(&v, 4, 1, self->theFile); - - if (cnt != 1) - { - return __TWI_ERROR; - } - - self->position += 1; - -#ifdef __TWI_BE - v = BigEndian32(v); -#endif - - *sample = v >> 8; - - return __TWI_SUCCESS; -} - -static int __ReadSampleInternal(WAVEFILEIN *self, int *sample, int scale) -{ - int err; - - if (!self) - { - return __TWI_ERROR; - } - - switch (scale) - { - - case 16: err = __ReadSample16(self, sample); break; - - case 24: err = __ReadSample24(self, sample); break; - - case 32: err = __ReadSample32(self, sample); break; - - default: err = __TWI_ERROR; break; - } - - return err; -} - -/* this function returns normalized values in the range +8388607..-8388608 */ -static int ReadWavInt(WAVEFILEIN *self, int sampleBuffer[], unsigned int nSamplesToRead, unsigned int *nSamplesRead) -{ - unsigned int i; - int err = __TWI_SUCCESS; - *nSamplesRead = 0; - - if (!sampleBuffer) - { - return __TWI_ERROR; - } - - /* check if we have enough samples left, if not, - set nSamplesToRead to number of samples left. */ - if (self->position + nSamplesToRead > self->length) - { - nSamplesToRead = self->length - self->position; - } - - for (i = 0; i < nSamplesToRead; i++) - { - - int tmp; - err = __ReadSampleInternal(self, &tmp, self->bps); - if (err != __TWI_SUCCESS) - { - return err; - } - sampleBuffer[i] = tmp; - *nSamplesRead += 1; - } - - return __TWI_SUCCESS; -} - -static int CloseWavIn(WAVEFILEIN *self) -{ - if (self) - { - if (self->theFile) - { - fclose(self->theFile); - } - } - free(self); - - return __TWI_SUCCESS; -} -/* -static int ResetWavIn(WAVEFILEIN* self) -{ - if (self) { - if (self->theFile) { - fsetpos(self->theFile, &self->dataChunkPos); - self->position = 0; - } - } - return __TWI_SUCCESS; -} -*/ -/*------------- local subs ----------------*/ - -static size_t fread_LE(void *ptr, size_t size, size_t nmemb, FILE *stream) -{ -#ifdef __TWI_LE - return fread(ptr, size, nmemb, stream); -#endif -#ifdef __TWI_BE - - unsigned char x[sizeof(int)]; - unsigned char *y = (unsigned char *)ptr; - int i; - int len; - - len = fread(x, size, nmemb, stream); - - for (i = 0; i < size * nmemb; i++) - { - *y++ = x[size * nmemb - i - 1]; - } - - return len; -#endif -} - -#ifdef __TWI_BE -static short BigEndian16(short v) -{ - short a = (v & 0x0ff); - short b = (v & 0x0ff00) >> 8; - - return a << 8 | b; -} - -static int BigEndian32(int v) -{ - int a = (v & 0x0ff); - int b = (v & 0x0ff00) >> 8; - int c = (v & 0x0ff0000) >> 16; - int d = (v & 0xff000000) >> 24; - - return a << 24 | b << 16 | c << 8 | d; -} -#endif - -#endif /* __TINYWAVEIN_C_H__ */ diff --git a/lib_lc3plus/tinywaveout_c.h b/lib_lc3plus/tinywaveout_c.h deleted file mode 100644 index 2f64a659f..000000000 --- a/lib_lc3plus/tinywaveout_c.h +++ /dev/null @@ -1,889 +0,0 @@ -/****************************************************************************** -* ETSI TS 103 634 V1.5.1 * -* Low Complexity Communication Codec Plus (LC3plus) * -* * -* Copyright licence is solely granted through ETSI Intellectual Property * -* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * -* estoppel or otherwise. * -******************************************************************************/ - -#ifndef __TINYWAVEOUT_C_H__ -#define __TINYWAVEOUT_C_H__ - -/*#define TWO_SUPPORT_BWF*/ - -#include -#include -#include -#include -#ifdef TWO_SUPPORT_BWF -#include -#endif - -/***** Interface *********************************************************/ - -#ifndef TWO_UINT64 - #if !(defined(WIN32)) - #include - #define TWO_UINT64 uint64_t - #else - #define TWO_UINT64 unsigned __int64 - #endif -#endif - -typedef struct WAVEFILEOUT WAVEFILEOUT; -#ifdef TWO_SUPPORT_BWF -typedef struct WAVEOUT_LOUDNESSINFO WAVEOUT_LOUDNESSINFO; -#endif - -#define __TWO_SUCCESS (0) -#define __TWO_ERROR (-1) - -static WAVEFILEOUT* CreateWav( - const char *fileName, - const unsigned int sampleRate, - const unsigned int numChannels, - const unsigned int bps - ); - -#ifdef TWO_SUPPORT_BWF -static WAVEFILEOUT* CreateWavBWF( - const char *fileName, - const unsigned int sampleRate, - const unsigned int numChannels, - const unsigned int bps, - const WAVEOUT_LOUDNESSINFO *hBwfData - ); -#endif - -/* this function expects values in the 16 bit range +32767..-32768 */ -static int WriteWavShort( - WAVEFILEOUT* self, - short sampleBuffer[], - unsigned int nSamples - ); - -/* this function expects values in the 24 bit range +8388607..-8388608 */ -static int WriteWavLong( - WAVEFILEOUT* self, - int sampleBuffer[], - unsigned int nSamples - ); - -/* this function expects normalized values in the range +-1.0f */ -static int WriteWavFloat( - WAVEFILEOUT* self, - float sampleBuffer[], - unsigned int nSamples - ); - -static int CloseWav(WAVEFILEOUT* self); -#ifdef TWO_SUPPORT_BWF -static int CloseWavBWF(WAVEFILEOUT* self, WAVEOUT_LOUDNESSINFO bextData); -#endif - -/***** Implementation *********************************************************/ - -#if defined (__i386__) || defined (_M_IX86) || defined (_M_X64) || defined (__x86_64__) || defined (__arm__) || defined (__xtensa__) || defined (__aarch64__) || defined (__EMSCRIPTEN__) -#define __TWO_LE /* _T_iny _W_ave _O_ut _L_ittle _E_ndian */ -#endif - -#if defined (__POWERPC__) -#define __TWO_BE /* _T_iny _W_ave _O_ut _B_ig _E_ndian */ -#endif - -#if defined (__sparc__) -#define __TWO_BE /* _T_iny _W_ave _O_ut _B_ig _E_ndian */ -#endif - -#if ! defined (__TWO_LE) && ! defined (__TWO_BE) -#error unknown processor -#endif - -/*--- local types/structs ----------------------------------*/ - -#if defined(_MSC_VER) - #pragma pack(push, 1) -#else - #pragma pack(1) -#endif - - -#ifdef TWO_SUPPORT_BWF -struct WAVEOUT_LOUDNESSINFO { - float loudnessVal; - float loudnessRange; - float maxTruePeakLevel; - float maxMomentaryLoudnes; - float maxShortTermLoudness; -}; -#endif - - -typedef struct __tinyWaveOutHeader -{ - unsigned int riffType; /* 'RIFF/RF64' */ - unsigned int riffSize; /* file size/-1 */ - unsigned int waveType; /* 'WAVE' */ -} __tinyWaveOutHeader; - -typedef struct __tinyWaveOutDs64Chunk -{ - unsigned int formatType; /* = 'JUNK/ds64' */ - unsigned int formatSize; /* size info */ - TWO_UINT64 riffSize64; - TWO_UINT64 dataSize64; - TWO_UINT64 sampleCount64; - unsigned int tableLength; /* optional tables, always 0 for tinywaveout */ - /* here: optional tables */ -} __tinyWaveOutDs64Chunk; - -#ifdef TWO_SUPPORT_BWF -typedef struct __tinyWaveOutBextChunk -{ - unsigned int formatType; /* = 'bext' */ - unsigned int formatSize; /* size info */ - - unsigned char description[256]; - unsigned char originator[32]; - unsigned char originatorReference[32]; - unsigned char originatorDate[10]; /* ASCII: <> */ - unsigned char originationTime[8]; /* ASCII: <> */ - unsigned int timeReferenceLow; - unsigned int timeReferenceHigh; - unsigned short version; - unsigned char UMID[64]; /* Binary Bytes of SMPTE UMID */ - - signed short loudnessVal; - signed short loudnessRange; - signed short maxTruePeakLevel; - signed short maxMomentaryLoudnes; - signed short maxShortTermLoudness; - - unsigned char Reserved[180]; - - unsigned char codingHistory; /* ASCII: <> - undefined length! */ - /* for variable length, mve this out of this struct */ -} __tinyWaveOutBextChunk; -#endif - -typedef struct __tinyWaveOutFmtChunk -{ - unsigned int formatType; - unsigned int formatSize; - - unsigned short formatTag; - unsigned short numChannels; - unsigned int sampleRate; - unsigned int bytesPerSecond; - unsigned short blockAlignment; - unsigned short bitsPerSample; - - /* wav fmt ext hdr here */ -} __tinyWaveOutFmtChunk; - -typedef struct __tinyWaveOutDataChunk -{ - unsigned int dataType; - unsigned int dataSize; - -} __tinyWaveOutDataChunk; - - -struct WAVEFILEOUT { - /* for reasons of memory alignment, have 64 bit data types first */ - TWO_UINT64 dataSize; - TWO_UINT64 dataSizeLimit; /* maximum size for data chunk for 4 GB files */ - TWO_UINT64 dataSizeLimit64; /* maximum size for data chunk for 2^64 B addressable files */ - TWO_UINT64 clipCount; - FILE* theFile; - unsigned int junkChunkOffset; - unsigned int fmtChunkOffset; -#ifdef TWO_SUPPORT_BWF - unsigned int bextChunkOffset; -#endif - unsigned int dataChunkOffset; - unsigned int bps; - - /* only needed for RF64: */ - unsigned int blockAlign; /* only needed for close() of ds64 chunk */ -}; - - -/*--- local protos --------------------------------------------------*/ -static __inline unsigned int BigEndian32(char, char, char, char); -static __inline unsigned int LittleEndian32(unsigned int); -static __inline unsigned int LittleEndian32s(int); -static __inline short LittleEndian16(short); -static __inline TWO_UINT64 LittleEndian64(TWO_UINT64); -#ifdef TWO_SUPPORT_BWF -static unsigned int EncodeLoudness(float); -#endif -static __inline int __dataSizeChk( WAVEFILEOUT* self, int newbytes ); - -#if defined(_MSC_VER) - #pragma pack(pop) -#else - #pragma pack() -#endif - - -#ifdef TWO_SUPPORT_BWF -static void setDefaultLoudness(WAVEOUT_LOUDNESSINFO *x) -{ - x->loudnessVal = 1.0f; - x->loudnessRange = 2.0f; - x->maxTruePeakLevel = 3.0f; - x->maxMomentaryLoudnes = 4.0f; - x->maxShortTermLoudness = 5.0f; -} -#endif - -static WAVEFILEOUT* __CreateWavInternal( - const char *fileName, - const unsigned int sampleRate, - const unsigned int numChannels, - const unsigned int bps -#ifdef TWO_SUPPORT_BWF - , - const WAVEOUT_LOUDNESSINFO *hBwfData -#endif - ) -{ - WAVEFILEOUT* self = NULL; - __tinyWaveOutHeader whdr; - __tinyWaveOutDs64Chunk ds64ch; -#ifdef TWO_SUPPORT_BWF - __tinyWaveOutBextChunk wbextch; -#endif - __tinyWaveOutFmtChunk wfch; - __tinyWaveOutDataChunk wdch; - unsigned int blockAlignment = 0; - unsigned int ByteCnt = 0; /* Byte counter for fwrite */ - - /* pseudo use to avoid unused symbols */ - (void)WriteWavShort; - (void)WriteWavLong; - (void)WriteWavFloat; -#ifdef TWI_SUPPORT_BWF - (void)CreateWavBWF; - (void)CloseWavBWF; - (void)setDefaultLoudness; -#endif - - /* param check */ - if (!fileName) goto bail; - if (sampleRate == 0) goto bail; - if (sampleRate > 768000) goto bail; - if (numChannels == 0) goto bail; - if (numChannels > 64) goto bail; - if (bps != 16 && bps != 24 && bps != 32) goto bail; - - self = (WAVEFILEOUT*)calloc(1, sizeof(WAVEFILEOUT)); - if (!self) goto bail; /* return NULL; */ - - self->theFile = fopen(fileName, "wb+"); - if (!self->theFile) goto bail; - - /* WAV-Header */ - whdr.riffType = BigEndian32('R','I','F','F'); - whdr.riffSize = LittleEndian32(0xffffffff); /* set to maximum, if fseek() doesn't work later */ - whdr.waveType = BigEndian32('W','A','V','E'); - /* write to file */ - ByteCnt = 0; - ByteCnt += fwrite(&whdr, 1, sizeof(whdr), self->theFile); - - /* ds64/JUNK-Chunk */ - ds64ch.formatType = BigEndian32('J','U','N','K'); - ds64ch.formatSize = LittleEndian32(sizeof(__tinyWaveOutDs64Chunk) - 8); - ds64ch.riffSize64 = (TWO_UINT64) -1; - ds64ch.dataSize64 = (TWO_UINT64) -1; - ds64ch.sampleCount64 = (TWO_UINT64) -1; - ds64ch.tableLength = 0; - self->junkChunkOffset = ByteCnt; - ByteCnt += fwrite(&ds64ch, 1, sizeof(ds64ch), self->theFile); - -#ifdef TWO_SUPPORT_BWF - /* BEXT-Chunk */ - if (hBwfData) { - memset(&wbextch, 0, sizeof(__tinyWaveOutBextChunk)); - wbextch.formatType = BigEndian32('b','e','x','t'); - wbextch.formatSize = LittleEndian32(sizeof(__tinyWaveOutBextChunk) - 8); - wbextch.version = 0x0002; - wbextch.loudnessVal = EncodeLoudness(hBwfData->loudnessVal); - wbextch.loudnessRange = EncodeLoudness(hBwfData->loudnessRange); - wbextch.maxTruePeakLevel = EncodeLoudness(hBwfData->maxTruePeakLevel); - wbextch.maxMomentaryLoudnes = EncodeLoudness(hBwfData->maxMomentaryLoudnes); - wbextch.maxShortTermLoudness = EncodeLoudness(hBwfData->maxShortTermLoudness); - /* t.b.d.: more values */ - - /* write to file */ - self->bextChunkOffset = ByteCnt; - ByteCnt += fwrite(&wbextch, 1, sizeof(wbextch), self->theFile); - } -#endif - - /* FMT-Chunk */ - wfch.formatType = BigEndian32('f','m','t',' '); - wfch.formatSize = LittleEndian32(16); - switch (bps) { - case 16: - case 24: - wfch.formatTag = LittleEndian16(0x0001); /* WAVE_FORMAT_PCM */ - break; - case 32: - wfch.formatTag = LittleEndian16(0x0003); /* WAVE_FORMAT_IEEE_FLOAT */ - break; - default: - goto bail; - } - self->bps = bps; - wfch.bitsPerSample = LittleEndian16(bps); - wfch.numChannels = LittleEndian16(numChannels); - blockAlignment = numChannels * (bps >> 3); - wfch.blockAlignment = LittleEndian16(blockAlignment); - wfch.sampleRate = LittleEndian32(sampleRate); - wfch.bytesPerSecond = LittleEndian32(sampleRate * blockAlignment); - /* tbd: wavfmt ext hdr here */ - /* write to file */ - self->fmtChunkOffset = ByteCnt; - ByteCnt += fwrite(&wfch, 1, sizeof(wfch), self->theFile); - - /* DATA-Chunk */ - self->dataChunkOffset = ByteCnt; - wdch.dataType = BigEndian32('d','a','t','a'); - wdch.dataSize = LittleEndian32(0xffffffff - ByteCnt); /* yet unknown. set to maximum of 4 GB file */ - /* write to file */ - ByteCnt += fwrite(&wdch, 1, sizeof(wdch), self->theFile); - - self->dataSize = 0; - - /* self->dataSizeLimit = 0x7fffffff - ByteCnt; */ /* maximum size for data chunk for 2 GB files */ - self->dataSizeLimit = 0xffffffff - ByteCnt; /* maximum size for data chunk for 4 GB files */ - self->dataSizeLimit64 = 0xffffffffffffffff - ByteCnt; /* maximum size for data chunk for 64 bit addressable files */ - - self->clipCount = 0; - self->blockAlign = blockAlignment; - - return self; - - bail: - if ( NULL != self) { - free(self); - } - - return NULL; -} - -static WAVEFILEOUT* CreateWav( - const char* fileName, - const unsigned int sampleRate, - const unsigned int numChannels, - const unsigned int bps - ) -{ -#ifdef TWO_SUPPORT_BWF - return __CreateWavInternal(fileName, sampleRate, numChannels, bps, NULL); -#else - return __CreateWavInternal(fileName, sampleRate, numChannels, bps); -#endif -} - -#ifdef TWO_SUPPORT_BWF -static WAVEFILEOUT* CreateWavBWF( - const char *fileName, - const unsigned int sampleRate, - const unsigned int numChannels, - const unsigned int bps, - const WAVEOUT_LOUDNESSINFO *hBwfData - ) -{ - return __CreateWavInternal(fileName, sampleRate, numChannels, bps, hBwfData); -} -#endif - -#define MAX_PCM16 (+32767) -#define MIN_PCM16 (-32768) -static __inline int CLIP_PCM16(int sample, TWO_UINT64* clipcount) -{ - int tmp = sample; - - if (sample >= MAX_PCM16) { - tmp = MAX_PCM16; - (*clipcount)++; - } else { - if (sample <= MIN_PCM16) { - tmp = MIN_PCM16; - (*clipcount)++; - } - } - - return tmp; -} - -#define MAX_PCM24 (+8388607) -#define MIN_PCM24 (-8388608) -static __inline int CLIP_PCM24(int sample, TWO_UINT64* clipcount) -{ - int tmp = sample; - - if (sample >= MAX_PCM24) { - tmp = MAX_PCM24; - (*clipcount)++; - } else { - if (sample <= MIN_PCM24) { - tmp = MIN_PCM24; - (*clipcount)++; - } - } - - return tmp; -} - -#define MAX_FLOAT32 (+1.0f) -#define MIN_FLOAT32 (-1.0f) -static __inline float CLIP_FLOAT32(float sample, TWO_UINT64* clipcount) -{ - float tmp = sample; - - if (sample >= MAX_FLOAT32) { - tmp = MAX_FLOAT32; - (*clipcount)++; - } else { - if (sample <= MIN_FLOAT32) { - tmp = MIN_FLOAT32; - (*clipcount)++; - } - } - - return tmp; -} - - - -static int __WriteSample16( - WAVEFILEOUT* self, - int sample, - int scale - ) -{ - size_t cnt; - short v; - - if ((scale - 16) > 0) - sample = sample >> (scale - 16); - else - sample = (int) ((uint32_t) sample << (16 - scale)); - - v = (short)CLIP_PCM16(sample, &(self->clipCount)); -#ifdef __TWO_BE - v = LittleEndian16(v); -#endif - - cnt = fwrite(&v, sizeof(short), 1, self->theFile); - - if (cnt == 1) { - self->dataSize += 2; - return __TWO_SUCCESS; - } - - return __TWO_ERROR; -} - - -static int __WriteSample24( - WAVEFILEOUT* self, - int sample, - int scale - ) -{ - size_t cnt; - int v; - - if ((scale - 24) > 0) - sample = sample >> (scale - 24); - else - sample = (int) (((unsigned int)sample) << (24 - scale)); - - v = (int)CLIP_PCM24(sample, &(self->clipCount)); -#ifdef __TWO_BE - v = LittleEndian32s(v); -#endif - cnt = fwrite(&v, 3, 1, self->theFile); - - if (cnt == 1) { - self->dataSize += 3; - return __TWO_SUCCESS; - } - - return __TWO_ERROR; -} - - -static int __WriteSample32( - WAVEFILEOUT* self, - float sample - ) -{ - size_t cnt; - union fl_int { - float v_float; - int v_int; - }; - union fl_int v; - -#if CLIP_FLOAT - v.v_float = CLIP_FLOAT32(sample, &(self->clipCount)); -#else - v.v_float = sample; - if((sample > 1.0f) || (sample <-1.0f)) - self->clipCount++; -#endif - -#ifdef __TWO_BE - v.v_int = LittleEndian32s(v.v_int); -#endif - cnt = fwrite(&v, 4, 1, self->theFile); - - if (cnt == 1) { - self->dataSize += 4; - return __TWO_SUCCESS; - } - - return __TWO_ERROR; -} - - -static int __WriteSampleInt( - WAVEFILEOUT* self, - int sample, - int scale - ) -{ - int err; - - if (!self) return __TWO_ERROR; - - - switch (self->bps) { - - case 16: - err = __WriteSample16(self, sample, scale); - break; - - case 24: - err = __WriteSample24(self, sample, scale); - break; - - default: - err = __TWO_ERROR; - break; - } - - return err; -} - - -/* this function expects values in the 16 bit range +-32767/8 */ -static int WriteWavShort( - WAVEFILEOUT* self, - short sampleBuffer[], - unsigned int nSamples - ) -{ - unsigned long i; - int err = __TWO_SUCCESS; - - if (!self) return __TWO_ERROR; - if (!sampleBuffer) return __TWO_ERROR; - if (__dataSizeChk(self, nSamples * sizeof(short))) return __TWO_ERROR; - - for (i=0; i< nSamples; i++) { - if (self->bps == 32) - { - err = __WriteSample32(self, sampleBuffer[i] / 32768.0f); - } - else - { - err = __WriteSampleInt(self, (int)sampleBuffer[i], 16); - } - if (err != __TWO_SUCCESS) return err; - } - - return __TWO_SUCCESS; -} - - -/* this function expects values in the 24 bit range +-8388607/8 */ -static int WriteWavLong( - WAVEFILEOUT* self, - int sampleBuffer[], - unsigned int nSamples - ) -{ - unsigned long i; - int err = __TWO_SUCCESS; - - if (!self) return __TWO_ERROR; - if (!sampleBuffer) return __TWO_ERROR; - if (__dataSizeChk(self, nSamples * sizeof(int))) return __TWO_ERROR; - - for (i = 0; i < nSamples; i++) { - if (self->bps == 32) - { - err = __WriteSample32(self, sampleBuffer[i] / 8388608.0f); - } - else - { - err = __WriteSampleInt(self, sampleBuffer[i], 24); - } - if (err != __TWO_SUCCESS) return err; - } - - return __TWO_SUCCESS; -} - - -/* this function expects normalized values in the range +-1.0 */ -#define MAX_FL (+2.0f * 8388608.0f ) -#define MIN_FL (-2.0f * 8388608.0f ) -#define CLIP_FL(x) ( ((x) >= MAX_FL) ? MAX_FL : (((x) <= MIN_FL) ? MIN_FL : (x)) ) -static int WriteWavFloat( - WAVEFILEOUT* self, - float sampleBuffer[], - unsigned int nSamples - ) -{ - unsigned int i; - int err = __TWO_SUCCESS; - - if (!self) return __TWO_ERROR; - if (!sampleBuffer) return __TWO_ERROR; - if (__dataSizeChk(self, nSamples * sizeof(float))) return __TWO_ERROR; - - for (i=0; ibps == 32) - { - err = __WriteSample32(self, sampleBuffer[i]); - } - else - { - float tmp = CLIP_FL(sampleBuffer[i] * 8388608.0f); /* CLIP_FL is just to avoid an INT overrun before the actual cast to int, real clipping and counting is done below */ - err = __WriteSampleInt(self, (int) tmp, 24); - } - if (err != __TWO_SUCCESS) return err; - } - - return __TWO_SUCCESS; -} - - -static int CloseWav(WAVEFILEOUT* self) -{ - unsigned int riffSize_le = 0; - unsigned int dataSize_le = 0; - TWO_UINT64 riffSize64 = 0; - TWO_UINT64 dataSize64 = 0; - TWO_UINT64 sampleCount64 = 0; /* nr of samples in the WAVE sense: 1 sample are all pcm samples of all channels of one time slice */ - int mustWriteRF64 = 0; - - if (!self) return __TWO_ERROR; - - /* check for 4 GB (switch to RF64) */ - if ( self->dataSize > self->dataSizeLimit ) { - /* when we exceed 4 GB: switch from std wave header to RF64 header */ - mustWriteRF64 = 1; - } - - /* calc header values */ - if (mustWriteRF64 == 0) { - /* write padding byte if dataSize is uneven */ - int pad = 0; - if (self->dataSize % 2 > 0) { - char tmp= 0x00; - fwrite(&tmp, sizeof(char), 1, self->theFile); - pad = 1; - } - riffSize_le = LittleEndian32(self->dataChunkOffset - 8 + 8 + (unsigned int)self->dataSize + pad); /* sizeof(hdr) - (8 bytes of riff chunk header) + (8 bytes data chunk header) + sizeof(raw-pcm-data) + padding Byte */ - dataSize_le = LittleEndian32((unsigned int)self->dataSize); - } else { - riffSize_le = 0xffffffff; - dataSize_le = 0xffffffff; - riffSize64 = LittleEndian64( self->dataSize + (TWO_UINT64)self->dataChunkOffset ); - dataSize64 = LittleEndian64( self->dataSize ); - sampleCount64 = LittleEndian64( self->dataSize / (TWO_UINT64)self->blockAlign ); - } - - /* now overwrite length/size values in header with the actual/real ones */ - if (mustWriteRF64 == 0) { - /* riffsize32 */ - fseek(self->theFile, 4, SEEK_SET); - fwrite(&riffSize_le, sizeof(riffSize_le), 1, self->theFile); - /* datasize32 */ - fseek(self->theFile, self->dataChunkOffset + 4, SEEK_SET); - fwrite(&dataSize_le, sizeof(dataSize_le), 1, self->theFile); - } else { - unsigned int rf64sig = BigEndian32('R','F','6','4'); - unsigned int ds64sig = BigEndian32('d','s','6','4'); - - /* replace RIFF->RF64 */ - fseek(self->theFile, 0, SEEK_SET); - fwrite(&rf64sig, sizeof(rf64sig), 1, self->theFile); - - /* riffsize32 */ - fseek(self->theFile, 4, SEEK_SET); - fwrite(&riffSize_le, sizeof(riffSize_le), 1, self->theFile); - - /* replace JUNK->ds64 */ - fseek(self->theFile, self->junkChunkOffset, SEEK_SET); - fwrite(&ds64sig, sizeof(ds64sig), 1, self->theFile); - - /* riffSize64, dataSize64, sampleCount64 */ - fseek(self->theFile, self->junkChunkOffset + 8, SEEK_SET); - fwrite(&riffSize64, sizeof(riffSize64), 1, self->theFile); - fwrite(&dataSize64, sizeof(dataSize64), 1, self->theFile); - fwrite(&sampleCount64, sizeof(sampleCount64), 1, self->theFile); - - /* datasize32 */ - fseek(self->theFile, self->dataChunkOffset + 4, SEEK_SET); - fwrite(&dataSize_le, sizeof(dataSize_le), 1, self->theFile); - } - - fclose(self->theFile); - free(self); - - return __TWO_SUCCESS; -} - -#ifdef TWO_SUPPORT_BWF -static int CloseWavBWF( - WAVEFILEOUT* self, - WAVEOUT_LOUDNESSINFO bextData - ) -{ - int wordData; - - if (!self) return __TWO_ERROR; - - if (self->bextChunkOffset) { - /* Offset for Loudness Data in bext-chunk: 8: Chunk-Header, 412:prev.Data */ - fseek(self->theFile, self->bextChunkOffset+8+412, SEEK_SET); - - wordData = LittleEndian32(EncodeLoudness(bextData.loudnessVal)); - fwrite(&wordData, 2, 1, self->theFile); - - wordData = LittleEndian32(EncodeLoudness(bextData.loudnessRange)); - fwrite(&wordData, 2, 1, self->theFile); - - wordData = LittleEndian32(EncodeLoudness(bextData.maxTruePeakLevel)); - fwrite(&wordData, 2, 1, self->theFile); - - wordData = LittleEndian32(EncodeLoudness(bextData.maxMomentaryLoudnes)); - fwrite(&wordData, 2, 1, self->theFile); - - wordData = LittleEndian32(EncodeLoudness(bextData.maxShortTermLoudness)); - fwrite(&wordData, 2, 1, self->theFile); - } - - return CloseWav(self); -} -#endif - -/*------------- local subs ----------------*/ - -static __inline unsigned int BigEndian32(char a, char b, char c, char d) -{ -#ifdef __TWO_LE - return - (unsigned int) d << 24 | - (unsigned int) c << 16 | - (unsigned int) b << 8 | - (unsigned int) a ; -#else - return - (unsigned int) a << 24 | - (unsigned int) b << 16 | - (unsigned int) c << 8 | - (unsigned int) d ; -#endif -} - - -static __inline unsigned int LittleEndian32(unsigned int v) -{ -#ifdef __TWO_LE - return v; -#else - return - (v & 0x000000FF) << 24 | - (v & 0x0000FF00) << 8 | - (v & 0x00FF0000) >> 8 | - (v & 0xFF000000) >> 24 ; -#endif -} - - -/* signed version of the above */ -static __inline unsigned int LittleEndian32s(int v) -{ -#ifdef __TWO_LE - return v; -#else - return - (v & 0x000000FF) << 24 | - (v & 0x0000FF00) << 8 | - (v & 0x00FF0000) >> 8 | - (v & 0xFF000000) >> 24 ; -#endif -} - - -static __inline short LittleEndian16(short v) -{ -#ifdef __TWO_LE - return v; -#else - return ((v << 8) & 0xFF00) | ((v >> 8) & 0x00FF); -#endif -} - -static __inline TWO_UINT64 LittleEndian64(TWO_UINT64 v) -{ -#ifdef __TWO_LE - return v; -#else - return - (v & 0x00000000000000FF) << 56 | - (v & 0x000000000000FF00) << 40 | - (v & 0x0000000000FF0000) << 24 | - (v & 0x00000000FF000000) << 8 | - (v & 0x000000FF00000000) >> 8 | - (v & 0x0000FF0000000000) >> 24 | - (v & 0x00FF000000000000) >> 40 | - (v & 0xFF00000000000000) >> 56 ; -#endif -} - -#ifdef TWO_SUPPORT_BWF -static unsigned int EncodeLoudness(float x) -{ - int s = (x>0)-(x<0); - return (int)( x*100.0f + s*0.5f ); -} -#endif - -static __inline int __dataSizeChk( WAVEFILEOUT* self, int newbytes ) -{ - if (!self) return __TWO_ERROR; - - if ( (self->dataSize + ((TWO_UINT64)newbytes) ) > self->dataSizeLimit64 ) { - return __TWO_ERROR; - } - - return __TWO_SUCCESS; -} - -#endif /* __TINYWAVEOUT_C_H__ */ - - - diff --git a/lib_lc3plus/tns_coder_fx.c b/lib_lc3plus/tns_coder_fx.c index 738f4e95b..e012abd0f 100644 --- a/lib_lc3plus/tns_coder_fx.c +++ b/lib_lc3plus/tns_coder_fx.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,6 +7,8 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "functions.h" static void Parcor2Index(const Word16 parCoeff[] /*Q15*/, Word16 index[], Word16 order); @@ -16,7 +18,7 @@ static Word32 FIRLattice(Word16 order, const Word16 *parCoeff /*Q15*/, Word32 *s /*************************************************************************/ void processTnsCoder_fx(Word16 *bits, Word16 indexes[], Word32 x[], Word16 BW_cutoff_idx, Word16 order[], - Word16 *numfilters, Word16 enable_lpc_weighting, Word16 nSubdivisions, Word16 frame_dms, + Word16 *numfilters, Word16 enable_lpc_weighting, Word16 nSubdivisions, LC3PLUS_FrameDuration frame_dms, Word16 maxLen, Word8 *scratchBuffer #ifdef ENABLE_HR_MODE , Word16 hrmode @@ -49,6 +51,10 @@ void processTnsCoder_fx(Word16 *bits, Word16 indexes[], Word32 x[], Word16 BW_cu move16(); *numfilters = 1; move16(); + subdiv_startfreq = 0; + move16(); + subdiv_stopfreq = 0; + move16(); #ifdef ENABLE_HR_MODE if (hrmode) @@ -64,7 +70,15 @@ void processTnsCoder_fx(Word16 *bits, Word16 indexes[], Word32 x[], Word16 BW_cu SWITCH (frame_dms) { - case 25: +#ifdef CR9_C_ADD_1p25MS + case LC3PLUS_FRAME_DURATION_1p25MS: + *bits = 0; + order[0] = 0; + order[1] = 0; + *numfilters = 0; + goto tns_exit; +#endif + case LC3PLUS_FRAME_DURATION_2p5MS: startfreq[0] = 3; move16(); @@ -88,7 +102,7 @@ void processTnsCoder_fx(Word16 *bits, Word16 indexes[], Word32 x[], Word16 BW_cu maxOrder = 4; move16(); BREAK; - case 50: + case LC3PLUS_FRAME_DURATION_5MS: startfreq[0] = 6; move16(); @@ -111,7 +125,7 @@ void processTnsCoder_fx(Word16 *bits, Word16 indexes[], Word32 x[], Word16 BW_cu xLen = shr_pos(xLen, 1); maxOrder = 4; BREAK; - case 75: + case LC3PLUS_FRAME_DURATION_7p5MS: startfreq[0] = 9; move16(); subdiv_startfreq = tns_subdiv_startfreq_7_5ms[BW_cutoff_idx]; @@ -122,7 +136,7 @@ void processTnsCoder_fx(Word16 *bits, Word16 indexes[], Word32 x[], Word16 BW_cu xLen = add(tmp, add(tmp, tmp)); maxOrder = 8; BREAK; - default: /* 100 */ + case LC3PLUS_FRAME_DURATION_10MS: startfreq[0] = 12; move16(); @@ -143,9 +157,10 @@ void processTnsCoder_fx(Word16 *bits, Word16 indexes[], Word32 x[], Word16 BW_cu move16(); } BREAK; + case LC3PLUS_FRAME_DURATION_UNDEFINED: assert(0); } - IF (sub(BW_cutoff_idx, 3) >= 0 && frame_dms >= 50) + IF (sub(BW_cutoff_idx, 3) >= 0 && frame_dms >= LC3PLUS_FRAME_DURATION_5MS) { *numfilters = 2; startfreq[1] = shr_pos(xLen, 1); @@ -163,7 +178,7 @@ void processTnsCoder_fx(Word16 *bits, Word16 indexes[], Word32 x[], Word16 BW_cu subdiv_startfreq[nSubdivisions * j + iSubdivisions]); /*norms[iFilter][iSubdivisions] = norm2FLOAT(pSpectrum+iStartLine, iEndLine-iStartLine);*/ - headroom = getScaleFactor32_lc3plus(x + subdiv_startfreq[nSubdivisions * j + iSubdivisions], n); + headroom = getScaleFactor32(x + subdiv_startfreq[nSubdivisions * j + iSubdivisions], n); /* Calculate norm of spectrum band */ L_tmp = Norm32Norm(x + subdiv_startfreq[nSubdivisions * j + iSubdivisions], headroom, n, &shift); @@ -193,10 +208,14 @@ void processTnsCoder_fx(Word16 *bits, Word16 indexes[], Word32 x[], Word16 BW_cu SWITCH (frame_dms) { - case 25: facs_e = add(facs_e, 1); BREAK; - case 50: facs_e = add(facs_e, 1); BREAK; - case 75: BREAK; - case 100: BREAK; +#ifdef CR9_C_ADD_1p25MS + case LC3PLUS_FRAME_DURATION_1p25MS: assert(0); +#endif + case LC3PLUS_FRAME_DURATION_2p5MS: facs_e = add(facs_e, 1); BREAK; + case LC3PLUS_FRAME_DURATION_5MS: facs_e = add(facs_e, 1); BREAK; + case LC3PLUS_FRAME_DURATION_7p5MS: BREAK; + case LC3PLUS_FRAME_DURATION_10MS: BREAK; + case LC3PLUS_FRAME_DURATION_UNDEFINED: assert(0); } tmp = sub(1, shl_pos(tmp, 1)); /* exponent of autocorrelation */ @@ -219,7 +238,7 @@ void processTnsCoder_fx(Word16 *bits, Word16 indexes[], Word32 x[], Word16 BW_cu L_tmp = L_mac0(L_tmp, tmpbuf[i], tmpbuf[i + lag]); } if (lag != 0) - L_tmp = Mpy_32_32_lc3plus(L_tmp, tnsAcfWindow_lc3plus[lag - 1]); + L_tmp = Mpy_32_32_lc3plus(L_tmp, tnsAcfWindow[lag - 1]); L_tmp = Mpy_32_16_lc3plus(L_tmp, facs); L_tmp = L_shl(L_tmp, facs_e); @@ -311,6 +330,10 @@ tns_disabled: order[j] = 0; } } + +#ifdef CR9_C_ADD_1p25MS +tns_exit: +#endif Dyn_Mem_Deluxe_Out(); } diff --git a/lib_lc3plus/tns_decoder_fx.c b/lib_lc3plus/tns_decoder_fx.c index aad24424c..7b9575f2d 100644 --- a/lib_lc3plus/tns_decoder_fx.c +++ b/lib_lc3plus/tns_decoder_fx.c @@ -1,5 +1,5 @@ /****************************************************************************** -* ETSI TS 103 634 V1.5.1 * +* ETSI TS 103 634 V1.6.1 * * Low Complexity Communication Codec Plus (LC3plus) * * * * Copyright licence is solely granted through ETSI Intellectual Property * @@ -7,6 +7,8 @@ * estoppel or otherwise. * ******************************************************************************/ +#include "options.h" +#include "wmc_auto.h" #include "functions.h" static Word32 IIRLattice(Word16 order, const Word16 *parCoeff, Word32 *state, Word32 x); @@ -14,7 +16,7 @@ static Word32 IIRLattice(Word16 order, const Word16 *parCoeff, Word32 *state, Wo /*************************************************************************/ void processTnsDecoder_fx(Word16 rc_idx[], Word32 x[], Word16 xLen, Word16 order[], Word16 *x_e, Word16 BW_stopband_idx, - Word16 frame_dms, Word8 *scratchBuffer + LC3PLUS_FrameDuration frame_dms, Word8 *scratchBuffer #ifdef ENABLE_HR_MODE , Word16 hrmode #endif @@ -45,26 +47,40 @@ void processTnsDecoder_fx(Word16 rc_idx[], Word32 x[], Word16 xLen, Word16 order SWITCH (frame_dms) { - case 25: +#ifdef CR9_C_ADD_1p25MS + case LC3PLUS_FRAME_DURATION_1p25MS: + startfreq[0] = 3; move16(); + BW_stopband = shr_pos(BW_stopband, 3); + BREAK; +#endif + case LC3PLUS_FRAME_DURATION_2p5MS: startfreq[0] = 3; move16(); BW_stopband = shr_pos(BW_stopband, 2); BREAK; - case 50: + case LC3PLUS_FRAME_DURATION_5MS: startfreq[0] = 6; move16(); BW_stopband = shr_pos(BW_stopband, 1); BREAK; - case 75: + case LC3PLUS_FRAME_DURATION_7p5MS: startfreq[0] = 9; move16(); BW_stopband = add(shr_pos(BW_stopband, 2), add(shr_pos(BW_stopband, 2), shr_pos(BW_stopband, 2))); BREAK; - case 100: startfreq[0] = 12; BREAK; + case LC3PLUS_FRAME_DURATION_10MS: startfreq[0] = 12; BREAK; + case LC3PLUS_FRAME_DURATION_UNDEFINED: assert(0); } - IF (sub(BW_stopband_idx, 3) >= 0 && frame_dms >= 50) + IF (sub(BW_stopband_idx, 3) >= 0 && frame_dms >= LC3PLUS_FRAME_DURATION_5MS) { numfilters = 2; startfreq[1] = shr_pos(BW_stopband, 1); } + +#ifdef CR9_C_ADD_1p25MS + IF (frame_dms <= LC3PLUS_FRAME_DURATION_1p25MS) { + numfilters = 0; + } +#endif + stopfreq = 0; test(); test(); @@ -77,8 +93,8 @@ void processTnsDecoder_fx(Word16 rc_idx[], Word32 x[], Word16 xLen, Word16 order { f = startfreq[1]; move16(); } - s1 = getScaleFactor32_lc3plus(x, f); - s2 = getScaleFactor32_lc3plus(x + f, sub(xLen, f)); + s1 = getScaleFactor32(x, f); + s2 = getScaleFactor32(x + f, sub(xLen, f)); s = s_min(s1, sub(s2, 7)); /* 7 bits of headroom for IIR filtering */ *x_e = sub(*x_e, s); -- GitLab From 411c2f3627dc51c08b1458f74dfff148a8b21ac7 Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Tue, 28 Oct 2025 18:51:40 +0100 Subject: [PATCH 02/11] add new file com_entropy.c and setup_com_lc3plus.c to MSVC solution --- Workspace_msvc/lib_lc3plus.vcxproj | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Workspace_msvc/lib_lc3plus.vcxproj b/Workspace_msvc/lib_lc3plus.vcxproj index 4d937cf64..64a966e29 100644 --- a/Workspace_msvc/lib_lc3plus.vcxproj +++ b/Workspace_msvc/lib_lc3plus.vcxproj @@ -109,6 +109,7 @@ + @@ -166,6 +167,7 @@ + @@ -192,4 +194,4 @@ - \ No newline at end of file + -- GitLab From 13fa1b7cf7a74acc24d8183c49096f8df58bb434 Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Wed, 29 Oct 2025 11:28:30 +0100 Subject: [PATCH 03/11] [fix] IVAS LC3plus unit test; add new helper function to translate integer framesize to newly introduced enum --- lib_isar/isar_lc3plus_common.c | 36 ++++++++++++++++++++++++++++++++++ lib_isar/isar_lc3plus_common.h | 3 +++ lib_isar/isar_lc3plus_dec.c | 2 +- lib_isar/isar_lc3plus_enc.c | 2 +- 4 files changed, 41 insertions(+), 2 deletions(-) diff --git a/lib_isar/isar_lc3plus_common.c b/lib_isar/isar_lc3plus_common.c index 28435cea9..d7d5bf025 100644 --- a/lib_isar/isar_lc3plus_common.c +++ b/lib_isar/isar_lc3plus_common.c @@ -58,6 +58,12 @@ ivas_error ISAR_LC3PLUS_LC3plusErrToIvasErr( } +/*-----------------------------------------------------------------------------------------* + * Function IVAS_LC3PLUS_LC3plusRtpErrToIvasErr() + * + * + *-----------------------------------------------------------------------------------------*/ + ivas_error IVAS_LC3PLUS_LC3plusRtpErrToIvasErr( const LC3PLUS_RTP_ERR lc3PlusRtpError ) { @@ -86,3 +92,33 @@ ivas_error IVAS_LC3PLUS_LC3plusRtpErrToIvasErr( return IVAS_ERR_UNKNOWN; } + +/*-----------------------------------------------------------------------------------------* + * Function IVAS_LC3PLUS_UsToLC3plusFrameDuration() + * + * + *-----------------------------------------------------------------------------------------*/ + +LC3PLUS_FrameDuration IVAS_LC3PLUS_UsToLC3plusFrameDuration( + const int16_t lc3PlusFrameDurationUs ) +{ + switch ( lc3PlusFrameDurationUs ) + { +#ifdef CR9_C_ADD_1p25MS /* TODO LC3plus: verify switch stripping on update */ + case 1250: + return LC3PLUS_FRAME_DURATION_1p25MS; +#endif + case 2500: + return LC3PLUS_FRAME_DURATION_2p5MS; + case 5000: + return LC3PLUS_FRAME_DURATION_5MS; + case 7500: + return LC3PLUS_FRAME_DURATION_7p5MS; + case 10000: + return LC3PLUS_FRAME_DURATION_10MS; + default: + break; + } + + return LC3PLUS_FRAME_DURATION_UNDEFINED; +} diff --git a/lib_isar/isar_lc3plus_common.h b/lib_isar/isar_lc3plus_common.h index eb3e7b0ad..3b52e5b3f 100644 --- a/lib_isar/isar_lc3plus_common.h +++ b/lib_isar/isar_lc3plus_common.h @@ -61,4 +61,7 @@ ivas_error ISAR_LC3PLUS_LC3plusErrToIvasErr( const LC3PLUS_Error lc3PlusError ); /*! utility function to convert LC3PLUS_Errors to the suitable ivas_error */ ivas_error IVAS_LC3PLUS_LC3plusRtpErrToIvasErr( const LC3PLUS_RTP_ERR lc3PlusRtpError ); +/*! utility function to convert a value in microseconds to an LC3PLUS_FrameDuration */ +LC3PLUS_FrameDuration IVAS_LC3PLUS_UsToLC3plusFrameDuration( const int16_t lc3PlusFrameDuration ); + #endif /* ISAR_LC3PLUS_COM_H */ diff --git a/lib_isar/isar_lc3plus_dec.c b/lib_isar/isar_lc3plus_dec.c index f8cbe9582..2ac21e4d3 100644 --- a/lib_isar/isar_lc3plus_dec.c +++ b/lib_isar/isar_lc3plus_dec.c @@ -137,7 +137,7 @@ ivas_error ISAR_LC3PLUS_DEC_Open( return IVAS_ERROR( ISAR_LC3PLUS_LC3plusErrToIvasErr( err ), "lc3plus_dec_init failed\n" ); } - err = lc3plus_dec_set_frame_dms( ( *handle )->handles[iCh], config.lc3plus_frame_duration_us / 100 ); + err = lc3plus_dec_set_frame_dms( ( *handle )->handles[iCh], IVAS_LC3PLUS_UsToLC3plusFrameDuration( config.lc3plus_frame_duration_us ) ); if ( LC3PLUS_OK != err ) { ISAR_LC3PLUS_DEC_Close( handle ); diff --git a/lib_isar/isar_lc3plus_enc.c b/lib_isar/isar_lc3plus_enc.c index af89213e6..60121a11f 100644 --- a/lib_isar/isar_lc3plus_enc.c +++ b/lib_isar/isar_lc3plus_enc.c @@ -163,7 +163,7 @@ ivas_error ISAR_LC3PLUS_ENC_Open( return IVAS_ERROR( ISAR_LC3PLUS_LC3plusErrToIvasErr( err ), "lc3plus_enc_init failed\n" ); } - err = lc3plus_enc_set_frame_dms( ( *handle )->handles[iCh], config.lc3plus_frame_duration_us / 100 ); + err = lc3plus_enc_set_frame_dms( ( *handle )->handles[iCh], IVAS_LC3PLUS_UsToLC3plusFrameDuration( config.lc3plus_frame_duration_us ) ); if ( err != LC3PLUS_OK ) { ISAR_LC3PLUS_ENC_Close( handle ); -- GitLab From c0e93b0b20924ad491c1e44f9cdf2e363f54da25 Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Wed, 29 Oct 2025 14:05:43 +0100 Subject: [PATCH 04/11] remove unsupported frame durations from helper func --- lib_isar/isar_lc3plus_common.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/lib_isar/isar_lc3plus_common.c b/lib_isar/isar_lc3plus_common.c index d7d5bf025..03f31cf8e 100644 --- a/lib_isar/isar_lc3plus_common.c +++ b/lib_isar/isar_lc3plus_common.c @@ -104,16 +104,8 @@ LC3PLUS_FrameDuration IVAS_LC3PLUS_UsToLC3plusFrameDuration( { switch ( lc3PlusFrameDurationUs ) { -#ifdef CR9_C_ADD_1p25MS /* TODO LC3plus: verify switch stripping on update */ - case 1250: - return LC3PLUS_FRAME_DURATION_1p25MS; -#endif - case 2500: - return LC3PLUS_FRAME_DURATION_2p5MS; case 5000: return LC3PLUS_FRAME_DURATION_5MS; - case 7500: - return LC3PLUS_FRAME_DURATION_7p5MS; case 10000: return LC3PLUS_FRAME_DURATION_10MS; default: -- GitLab From 57ec6a477cb63b55cd97df66cf810647270730b1 Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Wed, 29 Oct 2025 16:14:01 +0100 Subject: [PATCH 05/11] update LC3plus code resulting from modifications to integration script --- lib_lc3plus/basop_util_lc3plus.c | 4 +- lib_lc3plus/constants.c | 6 +-- lib_lc3plus/dct2_fx.c | 14 +++--- lib_lc3plus/dec_entropy.c | 14 +++--- lib_lc3plus/dec_lc3plus.c | 8 +-- lib_lc3plus/defines.h | 30 +++++------ lib_lc3plus/enc_lc3plus.c | 6 +-- lib_lc3plus/estimate_global_gain_fx.c | 70 +++++++++++++------------- lib_lc3plus/fft_lc3plus.c | 2 +- lib_lc3plus/functions.h | 4 +- lib_lc3plus/near_nyquist_detector_fx.c | 6 +-- lib_lc3plus/plc_phecu_fec_hq_fx.c | 4 +- lib_lc3plus/pvq_dec_fx.c | 2 +- lib_lc3plus/pvq_enc_fx.c | 2 +- lib_lc3plus/rom_basop_util_lc3plus.h | 2 +- lib_lc3plus/setup_com_lc3plus.c | 2 +- lib_lc3plus/setup_enc_lc3plus.c | 4 +- lib_lc3plus/sns_compute_scf_fx.c | 8 +-- lib_lc3plus/sns_quantize_scf_fx.c | 14 +++--- 19 files changed, 101 insertions(+), 101 deletions(-) diff --git a/lib_lc3plus/basop_util_lc3plus.c b/lib_lc3plus/basop_util_lc3plus.c index bb7f572d3..348e11b24 100644 --- a/lib_lc3plus/basop_util_lc3plus.c +++ b/lib_lc3plus/basop_util_lc3plus.c @@ -88,7 +88,7 @@ Word32 BASOP_Util_Log2(Word32 x) -#ifdef LOG2_LC_APPROX +#ifdef LOG2_LC_APPROX /* LC log2 with 16 segment piecewise 2nd order minmax optimized approximation */ Word32 BASOP_Util_Log2_LC(Word32 L_x) @@ -318,7 +318,7 @@ Word32 BASOP_Util_InvLog2_pos(Word32 x, Word16 *exp) } ELSE IF(x == 0) { -#ifdef LRSNS_ALLZERO_FIX +#ifdef LRSNS_ALLZERO_FIX *exp = 2; move16(); return (1L << 29); /* 2^29/(2^(31-(+2)) = 1.0 exactly */ #else diff --git a/lib_lc3plus/constants.c b/lib_lc3plus/constants.c index 1d00d56e0..c8aa477ef 100644 --- a/lib_lc3plus/constants.c +++ b/lib_lc3plus/constants.c @@ -544,7 +544,7 @@ const Word16 bands_offset_with_one_max_lin_1_25ms[NUM_SAMP_FREQ] = {-1, 20, 30, const Word16 bands_offset_with_two_max_lin_1_25ms[NUM_SAMP_FREQ] = {0, 0, 0, 0, 0 #ifdef ENABLE_HR_MODE , 0 -#endif +#endif }; #endif #endif /* CR9_C_ADD_1p25MS */ @@ -1798,7 +1798,7 @@ RAM_ALIGN const Word16 POW_ATT_TABLE1[OFF_FRAMES_LIMIT + 1] = { #ifdef PLC2_FADEOUT_IN_MS #if PLC2_FADEOUT_IN_MS == 0 -#else /* PLC2_FADEOUT_IN_MS == 0 */ +#else /* PLC2_FADEOUT_IN_MS == 0 */ RAM_ALIGN const Word16 POW_ATT_TABLE_p3x9_14_7[OFF_FRAMES_LIMIT + 1] = { 32767, @@ -1880,7 +1880,7 @@ RAM_ALIGN const Word16 fade_scheme_tab_fx[24 / 2][3] = { #endif /* PLC2_FADEOUT_IN_MS == 0 */ -#else /* PLC2_FADEOUT_IN_MS */ +#else /* PLC2_FADEOUT_IN_MS */ RAM_ALIGN const Word16 *const POW_ATT_TABLES[1 + 2] = { NULL, POW_ATT_TABLE1 /*1 .3dB steps */, diff --git a/lib_lc3plus/dct2_fx.c b/lib_lc3plus/dct2_fx.c index 6d428cdc5..63d513219 100644 --- a/lib_lc3plus/dct2_fx.c +++ b/lib_lc3plus/dct2_fx.c @@ -478,8 +478,8 @@ void dct16_W32int_fx(const Word16 *in, { -#define Mpy_32_16op(Lx,y) Mpy_32_16_lc3plus(Lx, y ) /* two-three cycle count as in existing STL */ -#define Mpy_32_16_0op(Lx,y) Mpy_32_16_0_0(Lx,y ) /* no rounding , STL shift cost still there */ +#define Mpy_32_16op(Lx,y) Mpy_32_16_lc3plus(Lx, y ) /* two-three cycle count as in existing STL */ +#define Mpy_32_16_0op(Lx,y) Mpy_32_16_0_0(Lx,y ) /* no rounding , STL shift cost still there */ Dyn_Mem_Deluxe_In( @@ -496,7 +496,7 @@ void dct16_W32int_fx(const Word16 *in, #define INSCALE (1<<(15-INMARGIN) ) #endif -#if INMARGIN == 0 +#if INMARGIN == 0 L_a0 = L_deposit_h(add(in[15], in[0])); /* Word16 Q11 deposited 16 levels up, becomes Q27, NB add can still potentially saturate ! */ L_a1 = L_deposit_h(add(in[14], in[1])); L_a2 = L_deposit_h(add(in[13], in[2])); @@ -537,7 +537,7 @@ void dct16_W32int_fx(const Word16 *in, L_b6 = L_sub(L_a1, L_a6); L_b7 = L_sub(L_a0, L_a7); -#if INMARGIN == 0 +#if INMARGIN == 0 L_b8 = L_deposit_h(sub(in[7], in[8])); L_b9 = L_deposit_h(sub(in[6], in[9])); #else @@ -556,7 +556,7 @@ void dct16_W32int_fx(const Word16 *in, L_b13 = L_add(Mpy_32_16op(L_a13, 23170), Mpy_32_16op(L_a10, 23170)); /* Cπ/4 Cπ/4 */ //L_b13 = L_add(L_b13, L_b13);/* scale up due to previous use of L_Mpy_32_16_0op() */ -#if INMARGIN == 0 +#if INMARGIN == 0 L_b14 = L_deposit_h(sub(in[1], in[14])); L_b15 = L_deposit_h(sub(in[0], in[15])); #else @@ -640,11 +640,11 @@ void dct16_W32int_fx(const Word16 *in, #ifdef Mpy_32_16op -#undef Mpy_32_16op +#undef Mpy_32_16op #endif #ifdef Mpy_32_16_0op -#undef Mpy_32_16_0op +#undef Mpy_32_16_0op #endif #ifdef WMOPS pop_wmops(); diff --git a/lib_lc3plus/dec_entropy.c b/lib_lc3plus/dec_entropy.c index a1773f92b..20582f47b 100644 --- a/lib_lc3plus/dec_entropy.c +++ b/lib_lc3plus/dec_entropy.c @@ -347,7 +347,7 @@ void processDecoderEntropy_fx(UWord8 *bytes, Word16 *bp_side, Word16 *mask_side, rx_status[1] = read_indice( ptr, bp_side, mask_side, 5 ); #else rx_status[1] = 0; -#endif +#endif } } ELSE { L = read_indice(ptr, bp_side, mask_side, 1+9); move16(); @@ -383,7 +383,7 @@ void processDecoderEntropy_fx(UWord8 *bytes, Word16 *bp_side, Word16 *mask_side, ltpf_idx[1] = 0; move16(); ltpf_idx[2] = 0; move16(); } -#endif /* new signalling */ +#endif /* new signalling */ /* Decode noise-fac */ *fac_ns_idx = read_indice( ptr, bp_side, mask_side, 3 ); move16(); @@ -586,7 +586,7 @@ void readSNSData_fx(UWord8* ptr, BER_detect = 0; move16(); plc_trigger_SNS1 = 1; move16(); -#ifdef LRSNS_10MS_BFISIGNAL_FIX +#ifdef LRSNS_10MS_BFISIGNAL_FIX plc_trigger_SNS2 = 1; move16(); #else plc_trigger_SNS2 = 2; move16(); @@ -675,7 +675,7 @@ void readSNSData_fx(UWord8* ptr, L_add(L_scf_idx[2], L_deposit_l(submodeLSB)); /* decoder internal signal shape_j = submode 0..3 to VQ */ -#ifdef LRSNS_10MS_BFISIGNAL_FIX +#ifdef LRSNS_10MS_BFISIGNAL_FIX IF( BER_detect > 0) { *bfiPtr = 1; move16(); @@ -762,7 +762,7 @@ void readSNSData_fx(UWord8* ptr, *bfiPtr = plc_trigger_SNS1; move16(); IF(*bfiPtr != 0) { -#ifdef LRSNS_10MS_BFISIGNAL_FIX +#ifdef LRSNS_10MS_BFISIGNAL_FIX ASSERT(*bfiPtr == 1); #endif Dyn_Mem_Deluxe_Out(); @@ -791,7 +791,7 @@ void readSNSData_fx(UWord8* ptr, *bfiPtr = plc_trigger_SNS2; move16(); IF( *bfiPtr != 0 ) { -#ifdef LRSNS_10MS_BFISIGNAL_FIX +#ifdef LRSNS_10MS_BFISIGNAL_FIX ASSERT(*bfiPtr == 1); #endif Dyn_Mem_Deluxe_Out(); @@ -856,7 +856,7 @@ void readSNSData_fx(UWord8* ptr, } /*stage1B* + stage2 */ } /*10+ bits*/ } -#ifdef LRSNS_PC_SIGNAL_FIX +#ifdef LRSNS_PC_SIGNAL_FIX assert(*bfiPtr == 0 || *bfiPtr == 1); /* local SNS BFI-flag output check */ #endif Dyn_Mem_Deluxe_Out(); diff --git a/lib_lc3plus/dec_lc3plus.c b/lib_lc3plus/dec_lc3plus.c index 525edc74f..ba9a2b39a 100644 --- a/lib_lc3plus/dec_lc3plus.c +++ b/lib_lc3plus/dec_lc3plus.c @@ -314,13 +314,13 @@ static int Dec_LC3PLUS_Channel(LC3PLUS_Dec *decoder, int channel, int bits_per_s #endif IF (sub(bfi, 1) != 0) -#ifdef CR9_C_ADD_1p25MS_LRSNS +#ifdef CR9_C_ADD_1p25MS_LRSNS { IF(sub(decoder->frame_dms, LC3PLUS_FRAME_DURATION_1p25MS) == 0) { pitch_rx_fx = ltpf_idx[0]; move16(); -#ifdef LRSNS_CBC_NO_LTPF_DEPENDENCY +#ifdef LRSNS_CBC_NO_LTPF_DEPENDENCY ltpf_rx_fx = 0; move16(); /* CB_C with binary means , not dependent on LTPF activation */ #else ltpf_rx_fx = ltpf_idx[1]; move16();/* CB_C, with ternary means dependent on LTPF activation */ @@ -331,7 +331,7 @@ static int Dec_LC3PLUS_Channel(LC3PLUS_Dec *decoder, int channel, int bits_per_s #endif } ELSE -#endif /* CR9_C_ADD_1p25MS_LRSNS */ +#endif /* CR9_C_ADD_1p25MS_LRSNS */ { /* currentScratch Size = 96 bytes */ #ifdef ENABLE_HR_MODE @@ -341,7 +341,7 @@ static int Dec_LC3PLUS_Channel(LC3PLUS_Dec *decoder, int channel, int bits_per_s processSnsQuantizeScfDecoder_fx(L_scf_idx, scf_q, currentScratch); #endif } -#ifdef CR9_C_ADD_1p25MS_LRSNS +#ifdef CR9_C_ADD_1p25MS_LRSNS } #endif #ifdef WMOPS diff --git a/lib_lc3plus/defines.h b/lib_lc3plus/defines.h index 24da69b87..746521471 100644 --- a/lib_lc3plus/defines.h +++ b/lib_lc3plus/defines.h @@ -128,30 +128,30 @@ #define FIX_BOTH_1p25_WB_GLOBGAINOFFSET_NONBE /* 1p25 curve tilt calulation corrected and made into BASOP, WB had a loss of of HF in the range 211-260 kbps */ #define FIX_BOTH_1p25_WB_GLOBGAINOFFSET_LOWLIM_NONBE -135 /* 1p25 curve tilt calulation limited to value -135 kbps */ -#define FIX_BOTH_1p25_TEST_NEW_GG_EST2 /* GG_EST2_will use bands with two coeffs in each instead of four, for 1p25 WB and 1p25 SSWB , note only active for regular, hrmode==0 */ +#define FIX_BOTH_1p25_TEST_NEW_GG_EST2 /* GG_EST2_will use bands with two coeffs in each instead of four, for 1p25 WB and 1p25 SSWB , note only active for regular, hrmode==0 */ #ifdef FIX_BOTH_1p25_TEST_NEW_GG_EST2 -#define FIX_BASOP_1p25_NEW_GG_EST3 /* GG_EST3 , GG_EST2 with optimized code for better BASOP code reuse , less changes to non 1p25ms */ -#define FIX_BOTH_1p25_GG_EST_SWB_FB /* 1.25ms GG_EST update for SWB/FB, better RD curve float and BASOP , active for hrmode==0 */ +#define FIX_BASOP_1p25_NEW_GG_EST3 /* GG_EST3 , GG_EST2 with optimized code for better BASOP code reuse , less changes to non 1p25ms */ +#define FIX_BOTH_1p25_GG_EST_SWB_FB /* 1.25ms GG_EST update for SWB/FB, better RD curve float and BASOP , active for hrmode==0 */ #endif /* defines to activate 2 or 3 tuple 1.25ms loops for WB,SSWB,SWB,FB */ #define FIX_1p25_GG_EST_TUPLES /* 1.25 ms GG_EST2_will use 2,3 or 4 , note only active for regular, hrmode==0 */ #ifdef FIX_1p25_GG_EST_TUPLES -#define GG_1p25_WB_TUPLES 2 -#define GG_1p25_SSWB_TUPLES 2 -#define GG_1p25_SWB_TUPLES 2 -#define GG_1p25_FB_TUPLES 3 -#define GG_1p25_MAX_TUPLES MAX(MAX(GG_1p25_WB_TUPLES ,GG_1p25_SSWB_TUPLES ), MAX(GG_1p25_SWB_TUPLES ,GG_1p25_FB_TUPLES)) /* used to control common energy loop */ +#define GG_1p25_WB_TUPLES 2 +#define GG_1p25_SSWB_TUPLES 2 +#define GG_1p25_SWB_TUPLES 2 +#define GG_1p25_FB_TUPLES 3 +#define GG_1p25_MAX_TUPLES MAX(MAX(GG_1p25_WB_TUPLES ,GG_1p25_SSWB_TUPLES ), MAX(GG_1p25_SWB_TUPLES ,GG_1p25_FB_TUPLES)) /* used to control common energy loop */ #define FIX_1p25_32kHz_CLANG_WARNING_EST_GAIN -#ifndef FIX_BOTH_1p25_ALLOC_SPECTRUM -#define FIX_BOTH_1p25_ALLOC_SPECTRUM +#ifndef FIX_BOTH_1p25_ALLOC_SPECTRUM +#define FIX_BOTH_1p25_ALLOC_SPECTRUM #endif -#define FIX_1p25_FLEX_ITER_TUPLE_LOOP /* energy loop part optimized BASOP only */ -#define LOG2_LC_APPROX /* log2_LC(energy) call BASOP only */ /* only applied to 1p25 ms global gain estimation loop */ -#define FIX_1p25_FLEX_BISECT_LOOP /* bisect optimization BASOP only !! */ +#define FIX_1p25_FLEX_ITER_TUPLE_LOOP /* energy loop part optimized BASOP only */ +#define LOG2_LC_APPROX /* log2_LC(energy) call BASOP only */ /* only applied to 1p25 ms global gain estimation loop */ +#define FIX_1p25_FLEX_BISECT_LOOP /* bisect optimization BASOP only !! */ #endif @@ -251,7 +251,7 @@ #ifdef DEBUG #ifdef READ_G192FER -#define READ_G192_FER_BYTE /* Allow C executable to also read G192 byte formatted FER files 0x20=BAD , 0x21=Good */ +#define READ_G192_FER_BYTE /* Allow C executable to also read G192 byte formatted FER files 0x20=BAD , 0x21=Good */ #endif #endif @@ -453,7 +453,7 @@ do not change __forceinline for mex compilation using gcc6.3.0 or larger #define SNSLR_A_CNST_WEIGHT 28672 /* 0.875 */ -#define SNS_VQ_MAX_IDX 8 +#define SNS_VQ_MAX_IDX 8 #endif /* CR9_C_ADD_LRSNS */ diff --git a/lib_lc3plus/enc_lc3plus.c b/lib_lc3plus/enc_lc3plus.c index 2658ac6bb..0c34a8d48 100644 --- a/lib_lc3plus/enc_lc3plus.c +++ b/lib_lc3plus/enc_lc3plus.c @@ -91,7 +91,7 @@ static void Enc_LC3PLUS_Channel(LC3PLUS_Enc *encoder, int channel, int bits_per_ ASSERT(encoder->frame_dms == LC3PLUS_FRAME_DURATION_1p25MS); ASSERT(MAX_LEN >= lg_4 * 4 ); /* "en" size in estimate_global_gain_fx() */ } -#ifdef FIX_BASOP_1p25_NEW_GG_EST3 +#ifdef FIX_BASOP_1p25_NEW_GG_EST3 if(encoder->frame_dms == LC3PLUS_FRAME_DURATION_1p25MS && (sub(encoder->frame_length, 30) <= 0)) /* WB and SSWB */ { ASSERT(MAX_LEN >= 2 + lg_4 * 4); /*make sure that there are 2 extra tail coeffs in d_fx*/ @@ -345,7 +345,7 @@ static void Enc_LC3PLUS_Channel(LC3PLUS_Enc *encoder, int channel, int bits_per_ /* No BW Cutoff for 8 kHz and 96 kHz */ IF (encoder->fs_idx > 0 && encoder->hrmode == 0 && encoder->bw_ctrl_active == 0) { -#else /* ENABLE_HR_MODE */ +#else /* ENABLE_HR_MODE */ IF (encoder->fs_idx > 0 && encoder->bw_ctrl_active == 0) { #endif /* ENABLE_HR_MODE */ @@ -509,7 +509,7 @@ static void Enc_LC3PLUS_Channel(LC3PLUS_Enc *encoder, int channel, int bits_per_ #endif test(); -#ifdef CR9_C_ADD_1p25MS_LRSNS +#ifdef CR9_C_ADD_1p25MS_LRSNS /* incoming (state based) ltpf_bits for tranmission set in function ltpf_coder_fx() */ test(); test(); lrsns_st1C_in_use = 0; move16(); diff --git a/lib_lc3plus/estimate_global_gain_fx.c b/lib_lc3plus/estimate_global_gain_fx.c index ec4e8cd1a..21b0d7d16 100644 --- a/lib_lc3plus/estimate_global_gain_fx.c +++ b/lib_lc3plus/estimate_global_gain_fx.c @@ -41,13 +41,13 @@ void processEstimateGlobalGain_fx(Word32 x[], Word16 x_e, Word16 lg, Word16 nbit Word16 *en_exp = NULL; Word32 M0, M1; #endif -#ifdef FIX_1p25_GG_EST_TUPLES +#ifdef FIX_1p25_GG_EST_TUPLES /* NB (-1) WB(20), SSWB(30), SWB(40), FB(50) */ Word16 nCoeffTab1p25[5] = { -1/*NB*/, GG_1p25_WB_TUPLES, GG_1p25_SSWB_TUPLES, GG_1p25_SWB_TUPLES, GG_1p25_FB_TUPLES }; Word16 bwIdx; Word16 divTabQ15[5] = { 0, -32768, 16384, 10923, 8192 }; #endif -#ifdef FIX_BOTH_1p25_TEST_NEW_GG_EST2 +#ifdef FIX_BOTH_1p25_TEST_NEW_GG_EST2 Word16 nCoeffPerBand = 4; /* 4 coeff per band */ Word16 twoCoeffFlag = 0; /* boolean */ #endif @@ -89,15 +89,15 @@ void processEstimateGlobalGain_fx(Word32 x[], Word16 x_e, Word16 lg, Word16 nbit UNUSED(L_twoCoeffSuppressMaskB); #endif -#ifdef FIX_1p25_FLEX_ITER_TUPLE_LOOP +#ifdef FIX_1p25_FLEX_ITER_TUPLE_LOOP UNUSED(twoCoeffOutShiftA); UNUSED(L_twoCoeffSuppressMaskA); UNUSED(twoCoeffOutShiftB); UNUSED(L_twoCoeffSuppressMaskB); #endif -#ifndef FIX_1p25_GG_EST_TUPLES -#ifdef FIX_BOTH_1p25_TEST_NEW_GG_EST2 +#ifndef FIX_1p25_GG_EST_TUPLES +#ifdef FIX_BOTH_1p25_TEST_NEW_GG_EST2 IF(frame_dms == LC3PLUS_FRAME_DURATION_1p25MS && (sub(lg, 30) <= 0)) /* WB and SSWB */ { nCoeffPerBand = 2; move16(); /* 2 coeff per band */ @@ -107,7 +107,7 @@ void processEstimateGlobalGain_fx(Word32 x[], Word16 x_e, Word16 lg, Word16 nbit #endif -#ifdef FIX_1p25_GG_EST_TUPLES +#ifdef FIX_1p25_GG_EST_TUPLES twoCoeffFlag = 0; move16(); nCoeffPerBand = 4; move16(); /* default assume 4 coeff per band(4-tuples block) */ lg_4 = shr_pos_pos(lg, 2); @@ -141,7 +141,7 @@ void processEstimateGlobalGain_fx(Word32 x[], Word16 x_e, Word16 lg, Word16 nbit lg_4 = s; /* lg_4 also used for 3_tuples, 2 tuples*/ } -#elif defined( FIX_BASOP_ENC_QUANTIZE_1P25MS_512KBPS) +#elif defined( FIX_BASOP_ENC_QUANTIZE_1P25MS_512KBPS) /* handle non-eaxactly quadruple lengths, in case frame_length is (e.g 1p25ms 24kHz --> 30 = 7*4 + 2 ) */ /* e.g 1p25ms 48kHz --> 50 = 12*4 + 2 ) */ /* quadruple extension is needed provide a correct x_max analysis as req. for scaling analysis */ @@ -190,7 +190,7 @@ void processEstimateGlobalGain_fx(Word32 x[], Word16 x_e, Word16 lg, Word16 nbit *old_targetBits = nbitsSQ; move16(); nbitsSQ = add(nbitsSQ, round_fx(*targetBitsOff)); -#ifndef FIX_BASOP_ENC_QUANTIZE_1P25MS_512KBPS +#ifndef FIX_BASOP_ENC_QUANTIZE_1P25MS_512KBPS lg_4 = shr_pos(lg, 2); #endif @@ -302,7 +302,7 @@ void processEstimateGlobalGain_fx(Word32 x[], Word16 x_e, Word16 lg, Word16 nbit L_twoCoeffSuppressMaskB = 0; move32(); /* suppress value*/ -#if GG_1p25_MAX_TUPLES>=3 +#if GG_1p25_MAX_TUPLES>=3 IF(sub(nCoeffPerBand, 3) == 0) { L_dB_scale_offset = L_add(Mpy_32_16_lc3plus(0x9CCCD, 24576), 1L); /* S15Q16/ round(7.5 * 3/4), 481689.75 -> 481690 */ @@ -316,7 +316,7 @@ void processEstimateGlobalGain_fx(Word32 x[], Word16 x_e, Word16 lg, Word16 nbit } #endif -#if GG_1p25_MAX_TUPLES>=4 +#if GG_1p25_MAX_TUPLES>=4 IF(sub(nCoeffPerBand, 4) == 0) { twoCoeffOutShiftA = 0; move16(); /* do not shift out */ @@ -327,7 +327,7 @@ void processEstimateGlobalGain_fx(Word32 x[], Word16 x_e, Word16 lg, Word16 nbit #endif #endif -#ifdef FIX_1p25_FLEX_ITER_TUPLE_LOOP +#ifdef FIX_1p25_FLEX_ITER_TUPLE_LOOP FOR(i = 0; i < lg_4; i++) /* 1.25 ms energy loop used for all N/4 , (N)/3 and N/2 */ { @@ -338,10 +338,10 @@ void processEstimateGlobalGain_fx(Word32 x[], Word16 x_e, Word16 lg, Word16 nbit tmp32 = L_max(tmp32, L_abs(x[1])); /* 0 or 31 shift, 0 for blocks of 4, 31 to accumulate a 0 value (for block #2,#3) for blocks of 2 or blocks of 3 */ -#if GG_1p25_MAX_TUPLES>=3 +#if GG_1p25_MAX_TUPLES>=3 tmp32 = L_max(tmp32, L_shr_pos_pos(L_abs(x[2]), twoCoeffOutShiftA)); #endif -#if GG_1p25_MAX_TUPLES>=4 +#if GG_1p25_MAX_TUPLES>=4 tmp32 = L_max(tmp32, L_shr_pos_pos(L_abs(x[3]), twoCoeffOutShiftB)); #endif x_max = L_max(x_max, tmp32); /* global x_max */ @@ -365,13 +365,13 @@ void processEstimateGlobalGain_fx(Word32 x[], Word16 x_e, Word16 lg, Word16 nbit tmp16 = round_fx(L_shl(x[1], s)); ener = L_mac(ener, tmp16, tmp16); -#if GG_1p25_MAX_TUPLES >= 3 +#if GG_1p25_MAX_TUPLES >= 3 tmp32 = L_and(x[2], L_twoCoeffSuppressMaskA); /* mask is 0 for 2blocks, all ones for 3 or 4 blocks */ tmp16 = round_fx(L_shl(tmp32, s)); ener = L_mac(ener, tmp16, tmp16); #endif -#if GG_1p25_MAX_TUPLES >= 4 +#if GG_1p25_MAX_TUPLES >= 4 tmp32 = L_and(x[3], L_twoCoeffSuppressMaskB); /* 0 for 2 or 3 blocks, all ones for 4 blocks */ tmp16 = round_fx(L_shl(tmp32, s)); ener = L_mac(ener, tmp16, tmp16); @@ -386,7 +386,7 @@ void processEstimateGlobalGain_fx(Word32 x[], Word16 x_e, Word16 lg, Word16 nbit } #endif -#ifndef LOG2_LC_APPROX +#ifndef LOG2_LC_APPROX /* log2 */ tmp32 = L_add_sat(BASOP_Util_Log2(ener), L_shl_sat(L_deposit_l(s), 25)); /* log2, 6Q25 */ #endif @@ -405,7 +405,7 @@ void processEstimateGlobalGain_fx(Word32 x[], Word16 x_e, Word16 lg, Word16 nbit { /* 4 or 2 merged loop for non-1p25ms */ #endif -#ifndef FIX_1p25_GG_EST_TUPLES +#ifndef FIX_1p25_GG_EST_TUPLES # ifdef FIX_BOTH_1p25_TEST_NEW_GG_EST2 test(); if (twoCoeffFlag != 0) @@ -418,7 +418,7 @@ void processEstimateGlobalGain_fx(Word32 x[], Word16 x_e, Word16 lg, Word16 nbit #ifdef FIX_BASOP_1p25_NEW_GG_EST3 /*set up constants for blocks of two (or block of 4)*/ L_dB_scale_offset = L_shr_pos(0x9CCCD, twoCoeffFlag); /* S15Q16/ 7.5 or 3.5 offset */ -#ifdef FIX_1p25_FLEX_ITER_TUPLE_LOOP +#ifdef FIX_1p25_FLEX_ITER_TUPLE_LOOP Word16 twoCoeffOutShift; Word32 L_twoCoeffSuppressMask; #endif @@ -441,8 +441,8 @@ void processEstimateGlobalGain_fx(Word32 x[], Word16 x_e, Word16 lg, Word16 nbit tmp32 = L_abs(x[0]); tmp32 = L_max(tmp32, L_abs(x[1])); -#ifdef FIX_BOTH_1p25_TEST_NEW_GG_EST2 -#ifdef FIX_BASOP_1p25_NEW_GG_EST3 +#ifdef FIX_BOTH_1p25_TEST_NEW_GG_EST2 +#ifdef FIX_BASOP_1p25_NEW_GG_EST3 /* 0 or 31 shift, 0 for blocks of 4, 31 to accumulate a 0 value (for block #2,#3) for blocks of 2 */ tmp32 = L_max(tmp32, L_shr_pos(L_abs(x[2]), twoCoeffOutShift)); tmp32 = L_max(tmp32, L_shr_pos(L_abs(x[3]), twoCoeffOutShift)); @@ -467,8 +467,8 @@ void processEstimateGlobalGain_fx(Word32 x[], Word16 x_e, Word16 lg, Word16 nbit tmp16 = round_fx(L_shl(x[1], s)); ener = L_mac(ener, tmp16, tmp16); -#ifdef FIX_BOTH_1p25_TEST_NEW_GG_EST2 -#ifdef FIX_BASOP_1p25_NEW_GG_EST3 +#ifdef FIX_BOTH_1p25_TEST_NEW_GG_EST2 +#ifdef FIX_BASOP_1p25_NEW_GG_EST3 tmp32 = L_and(x[2], L_twoCoeffSuppressMask); /* 0 for 2blocks, all ones for 4 blocks */ tmp16 = round_fx(L_shl(tmp32, s)); ener = L_mac(ener, tmp16, tmp16); @@ -491,8 +491,8 @@ void processEstimateGlobalGain_fx(Word32 x[], Word16 x_e, Word16 lg, Word16 nbit /* log */ tmp32 = L_add_sat(BASOP_Util_Log2(ener), L_shl_sat(L_deposit_l(s), 25)); /* log2, 6Q25 */ -#ifdef FIX_BOTH_1p25_TEST_NEW_GG_EST2 -#ifdef FIX_BASOP_1p25_NEW_GG_EST3 +#ifdef FIX_BOTH_1p25_TEST_NEW_GG_EST2 +#ifdef FIX_BASOP_1p25_NEW_GG_EST3 tmp32 = L_add(L_shr_pos(Mpy_32_16_lc3plus(tmp32, 0x436E), 6), L_dB_scale_offset); /* -> (28/20)*( (7or3.5) + 10*tmp32/log2(10)), 15Q16 */ #endif #else @@ -500,13 +500,13 @@ void processEstimateGlobalGain_fx(Word32 x[], Word16 x_e, Word16 lg, Word16 nbit #endif en[i] = tmp32; move32(); -#ifdef FIX_BOTH_1p25_TEST_NEW_GG_EST2 +#ifdef FIX_BOTH_1p25_TEST_NEW_GG_EST2 x += nCoeffPerBand; #else x += 4; #endif } /* N/4 or N/2 energy loop */ -#ifdef FIX_1p25_FLEX_ITER_TUPLE_LOOP +#ifdef FIX_1p25_FLEX_ITER_TUPLE_LOOP } /* end of non-1.25ms 4 or 2 tuple energy loop */ #endif }/* hrmode==0 */ @@ -734,7 +734,7 @@ void processEstimateGlobalGain_fx(Word32 x[], Word16 x_e, Word16 lg, Word16 nbit { #ifndef FIX_1p25_FLEX_BISECT_LOOP -#ifdef FIX_BASOP_1p25_NEW_GG_EST3 +#ifdef FIX_BASOP_1p25_NEW_GG_EST3 /*these limits were constant for blocks of 4 , now we adaptively adjust them for blocks of two */ L_dB_scale_offset = L_shr_pos(0x9CCCD, twoCoeffFlag); L_dB_scale_offset2 = L_shr_pos(0x460000, twoCoeffFlag); @@ -762,7 +762,7 @@ void processEstimateGlobalGain_fx(Word32 x[], Word16 x_e, Word16 lg, Word16 nbit L_dB_scale_offset3 = L_shr_pos(0x3C7AE, twoCoeffFlag); /* set up constants for blocks of 4 (or block of 3 or 2)*/ -#if GG_1p25_MAX_TUPLES>=3 +#if GG_1p25_MAX_TUPLES>=3 IF(sub(nCoeffPerBand, 3) == 0) { L_dB_scale_offset = L_add(Mpy_32_16_lc3plus(0x9CCCD, 24576), 1L); /* S15Q16/ round(7.5 * 3/4), 481689.75 -> 481690 */ @@ -842,7 +842,7 @@ void processEstimateGlobalGain_fx(Word32 x[], Word16 x_e, Word16 lg, Word16 nbit { #endif /* FLEX BISECT*/ /* find offset (0 to 127) */ -#ifdef FIX_BASOP_1p25_NEW_GG_EST3 +#ifdef FIX_BASOP_1p25_NEW_GG_EST3 /* 4 ,or 2 tuples */ L_dB_scale_offset = L_shr_pos(0x9CCCD, twoCoeffFlag); /* S15Q16 7.5(4 tuples) or 3.75(2_tuples) offset */ @@ -861,8 +861,8 @@ void processEstimateGlobalGain_fx(Word32 x[], Word16 x_e, Word16 lg, Word16 nbit FOR(i = lg_4 - 1; i >= 0; i--) { tmp32 = L_sub(en[i], offset); -#ifdef FIX_BOTH_1p25_TEST_NEW_GG_EST2 -#ifdef FIX_BASOP_1p25_NEW_GG_EST3 +#ifdef FIX_BOTH_1p25_TEST_NEW_GG_EST2 +#ifdef FIX_BASOP_1p25_NEW_GG_EST3 diff = L_sub(tmp32, L_dB_scale_offset); /* 0x9CCCD -> (28/20)*( 7or3.5) in Q16 */ #endif #else @@ -872,8 +872,8 @@ void processEstimateGlobalGain_fx(Word32 x[], Word16 x_e, Word16 lg, Word16 nbit { if (iszero == 0) { -#ifdef FIX_BOTH_1p25_TEST_NEW_GG_EST2 -#ifdef FIX_BASOP_1p25_NEW_GG_EST3 +#ifdef FIX_BOTH_1p25_TEST_NEW_GG_EST2 +#ifdef FIX_BASOP_1p25_NEW_GG_EST3 ener = L_add_sat(ener, L_dB_scale_offset3); /* 0x3C7AE -> (28/20)*(2.7or 3.5) in Q16 */ #endif #else @@ -885,8 +885,8 @@ void processEstimateGlobalGain_fx(Word32 x[], Word16 x_e, Word16 lg, Word16 nbit { ener = L_add_sat(ener, tmp32); iszero = 0; move16(); -#ifdef FIX_BOTH_1p25_TEST_NEW_GG_EST2 -#ifdef FIX_BASOP_1p25_NEW_GG_EST3 +#ifdef FIX_BOTH_1p25_TEST_NEW_GG_EST2 +#ifdef FIX_BASOP_1p25_NEW_GG_EST3 diff2 = L_sub(tmp32, L_dB_scale_offset2); /* 0x460000 -> (28/20)*(50or25) in Q16 */ #endif #else diff --git a/lib_lc3plus/fft_lc3plus.c b/lib_lc3plus/fft_lc3plus.c index e7a71d5b1..1f727bcd4 100644 --- a/lib_lc3plus/fft_lc3plus.c +++ b/lib_lc3plus/fft_lc3plus.c @@ -68,7 +68,7 @@ #endif #ifdef ENABLE_HR_MODE -#undef L_shr_pos +#undef L_shr_pos #define L_shr_pos(x, y) (L_shr(L_add(L_shr((x), ((y)-1)),1),1)) #endif diff --git a/lib_lc3plus/functions.h b/lib_lc3plus/functions.h index 5146ca05c..38b32769d 100644 --- a/lib_lc3plus/functions.h +++ b/lib_lc3plus/functions.h @@ -346,7 +346,7 @@ void dct16_W32int_fx(const Word16 *in, Word16 *out); void writeSNSData_fx(UWord8 *bytes, Word16 *bp_side, Word16 *mask_side, LC3PLUS_FrameDuration frame_dms, Word32* L_scf_idx); -#endif /* CR9_C_ADD_1p25MS_LRSNS */ +#endif /* CR9_C_ADD_1p25MS_LRSNS */ #ifdef NEW_SIGNALLING_SCHEME_1p25 @@ -758,7 +758,7 @@ void processEstimateGlobalGain_fx(Word32 x[], Word16 x_e, Word16 lg, Word16 sqTa #ifdef ENABLE_HR_MODE , Word16 hrmode, Word16 regBits, LC3PLUS_FrameDuration frame_dms #else -#ifdef FIX_BOTH_1p25_TEST_NEW_GG_EST2 +#ifdef FIX_BOTH_1p25_TEST_NEW_GG_EST2 , LC3PLUS_FrameDuration frame_dms #endif #endif diff --git a/lib_lc3plus/near_nyquist_detector_fx.c b/lib_lc3plus/near_nyquist_detector_fx.c index c88a7fc9f..5e83af0b1 100644 --- a/lib_lc3plus/near_nyquist_detector_fx.c +++ b/lib_lc3plus/near_nyquist_detector_fx.c @@ -15,13 +15,13 @@ void processNearNyquistdetector_fx(Word16 *near_nyquist_flag, const Word16 fs_id const Word16 bands_number, const Word32 *ener_fx, const Word16 ener_fx_exp #ifdef ENABLE_HR_MODE ,LC3PLUS_FrameDuration frame_dms, Word16 hrmode -#endif +#endif ) { *near_nyquist_flag = 0; #ifdef ENABLE_HR_MODE IF (hrmode == 0){ -#endif +#endif IF (sub(fs_idx, 4) < 0) { Dyn_Mem_Deluxe_In( @@ -74,7 +74,7 @@ void processNearNyquistdetector_fx(Word16 *near_nyquist_flag, const Word16 fs_id case LC3PLUS_FRAME_DURATION_1p25MS: assert(0); BREAK; -#endif +#endif case LC3PLUS_FRAME_DURATION_2p5MS: td_thresh = TD_HR_thresh_2_5ms; BREAK; diff --git a/lib_lc3plus/plc_phecu_fec_hq_fx.c b/lib_lc3plus/plc_phecu_fec_hq_fx.c index 37711a6bc..0d94b3718 100644 --- a/lib_lc3plus/plc_phecu_fec_hq_fx.c +++ b/lib_lc3plus/plc_phecu_fec_hq_fx.c @@ -289,7 +289,7 @@ void trans_burst_ana_fx( /* band gain muting can take place earlier due to a band transient */ beta_mute_thr = fade_scheme_tab_fx[fade_ms_ind][2]; /* faster muting of added noise starts when slow main signal fadeout is over */ -#ifdef PLC_FADEOUT_IN_MS +#ifdef PLC_FADEOUT_IN_MS ASSERT(att_per_frame >= 1 && att_per_frame <= 12); /* table based lookup restriction */ #else ASSERT(att_per_frame == 1 || att_per_frame == 2); /* table based lookup restriction */ @@ -1239,7 +1239,7 @@ static Word16 imax_fx( /* o: The location, relative to the /* in the first lost frame analyze spectra and spectral bands to possibly reverse an initial pure sine assumption */ *nonpure_tone_flag_ptr = plc_phEcu_nonpure_tone_ana_fx(plocs, *num_plocs, X, L_Xavg, Lprot, fs_idx); -#ifdef LOCAL_PLC2_TON_ANA_DEACTIVATE +#ifdef LOCAL_PLC2_TON_ANA_DEACTIVATE *nonpure_tone_flag_ptr = 0; /* dbg of inactive tone analysis */ #endif } diff --git a/lib_lc3plus/pvq_dec_fx.c b/lib_lc3plus/pvq_dec_fx.c index 2eb1a76a4..25ec3e539 100644 --- a/lib_lc3plus/pvq_dec_fx.c +++ b/lib_lc3plus/pvq_dec_fx.c @@ -117,7 +117,7 @@ void lrsns_pvq_dec_scale_W32vec_fx( } Dyn_Mem_Deluxe_Out(); } -#endif /* ENABLE_HR_MODE */ +#endif /* ENABLE_HR_MODE */ void pvq_fess_dec_en1_normQ30andQ14_fx( const Word16 *y /*Q0*/, diff --git a/lib_lc3plus/pvq_enc_fx.c b/lib_lc3plus/pvq_enc_fx.c index 9351cbcc2..9933419bb 100644 --- a/lib_lc3plus/pvq_enc_fx.c +++ b/lib_lc3plus/pvq_enc_fx.c @@ -12,7 +12,7 @@ #include "defines.h" #include "functions.h" -#ifdef CR9_C_ADD_1p25MS_LRSNS +#ifdef CR9_C_ADD_1p25MS_LRSNS static void pvq_pyr_project_lrsns_adv(const Word16 dim_proj, /* vector dimension */ const Word16 *xabs, /* absolute vector values */ Word32 L_xsum, /* absolute vector sum over dim_proj */ diff --git a/lib_lc3plus/rom_basop_util_lc3plus.h b/lib_lc3plus/rom_basop_util_lc3plus.h index bde04fad3..ac088fa1d 100644 --- a/lib_lc3plus/rom_basop_util_lc3plus.h +++ b/lib_lc3plus/rom_basop_util_lc3plus.h @@ -71,7 +71,7 @@ void BASOP_getTables( #else const PWord16 **ptwiddle, const PWord16 **sin_twiddle, -#endif +#endif Word16 *sin_step, Word16 length); diff --git a/lib_lc3plus/setup_com_lc3plus.c b/lib_lc3plus/setup_com_lc3plus.c index ce8a9ac66..1121d1905 100644 --- a/lib_lc3plus/setup_com_lc3plus.c +++ b/lib_lc3plus/setup_com_lc3plus.c @@ -24,7 +24,7 @@ Word16 calc_GGainOffset_1p25_fx(Word16 total_bits, Word16 fs_idx) tmp2 = negate(add(s_min(115, tmp1), tmp2)); move16(); -#ifdef FIX_BOTH_1p25_WB_GLOBGAINOFFSET_LOWLIM_NONBE +#ifdef FIX_BOTH_1p25_WB_GLOBGAINOFFSET_LOWLIM_NONBE if (sub(fs_idx, 1) <= 0) { /* only NB and WB additionally limited to -135 */ tmp2 = s_max(tmp2, FIX_BOTH_1p25_WB_GLOBGAINOFFSET_LOWLIM_NONBE); diff --git a/lib_lc3plus/setup_enc_lc3plus.c b/lib_lc3plus/setup_enc_lc3plus.c index 92c668912..6005f1521 100644 --- a/lib_lc3plus/setup_enc_lc3plus.c +++ b/lib_lc3plus/setup_enc_lc3plus.c @@ -586,7 +586,7 @@ LC3PLUS_Error update_enc_bitrate(LC3PLUS_Enc *encoder, int bitrate) } } else -#endif +#endif { fec_slot_bytes_min = FEC_SLOT_BYTES_MIN; } @@ -594,7 +594,7 @@ LC3PLUS_Error update_enc_bitrate(LC3PLUS_Enc *encoder, int bitrate) check_bytes = bitrate * encoder->frame_length / ( 8 * encoder->fs_in * encoder->channels ); maxBR = FEC_SLOT_BYTES_MAX * ( 8 * encoder->fs_in * encoder->channels ) / encoder->frame_length; if ( check_bytes < fec_slot_bytes_min || bitrate > maxBR ) -#else +#else max_bytes = bitrate * encoder->frame_length / (8 * encoder->fs_in * encoder->channels); if (max_bytes < FEC_SLOT_BYTES_MIN || max_bytes > FEC_SLOT_BYTES_MAX) #endif /* CR12_D_FIX_BITRATE_LIMITS */ diff --git a/lib_lc3plus/sns_compute_scf_fx.c b/lib_lc3plus/sns_compute_scf_fx.c index 8acfe52bb..a95e3e772 100644 --- a/lib_lc3plus/sns_compute_scf_fx.c +++ b/lib_lc3plus/sns_compute_scf_fx.c @@ -185,12 +185,12 @@ void processSnsComputeScf_fx(Word32 *d2_fx, Word16 d2_fx_exp, Word16 fs_idx, Wor Word16 ncorr_fac_orig = i_mult(s_max(sub(LT_normcorr_mem, 26214), 0), 5); UNUSED(ncorr_fac_orig); #endif -#else +#else /* LT_normcorr * (1-0.125) + normcorr * 0.125 */ *LT_normcorr = add(mult(*LT_normcorr,28672), mult(norm_corr,4096)); /* ncorr_fac = max(LT_normcorr - 0.8, 0) * 5 */ ncorr_fac = i_mult(s_max(sub(*LT_normcorr, 26214), 0), 5); -#endif +#endif if (ncorr_fac == 0) { @@ -459,7 +459,7 @@ void processSnsComputeScf_fx(Word32 *d2_fx, Word16 d2_fx_exp, Word16 fs_idx, Wor L_mean = L_add(L_mean, L_shr_pos(d3_fx[i], 4)); } -#ifdef FIX_SNS_BASOP_MEAN16_APPLY +#ifdef FIX_SNS_BASOP_MEAN16_APPLY Word16 limGainDamping = 0; Word16 up_shift = 0, dn_shift = 0; @@ -484,7 +484,7 @@ void processSnsComputeScf_fx(Word32 *d2_fx, Word16 d2_fx_exp, Word16 fs_idx, Wor #if defined (CR9_C_ADD_1p25MS) if (frame_dms == LC3PLUS_FRAME_DURATION_1p25MS) { -#ifdef FIX_SNS_BASOP_MEAN16_APPLY +#ifdef FIX_SNS_BASOP_MEAN16_APPLY /* maximize precision */ L_tmp = Mpy_32_16_lc3plus(L_shl_pos(d3_fx[i + M], up_shift), limGainDamping ); scf[i] = round_fx(L_shr_pos(L_tmp, dn_shift)); diff --git a/lib_lc3plus/sns_quantize_scf_fx.c b/lib_lc3plus/sns_quantize_scf_fx.c index d16a90b34..d4d3d3aa2 100644 --- a/lib_lc3plus/sns_quantize_scf_fx.c +++ b/lib_lc3plus/sns_quantize_scf_fx.c @@ -389,7 +389,7 @@ static void pvq_enc_find_best_submode_pre_post_fx( tmp = mult_r(search_gainTab[L_section][idx], search_en1shape[L_section][i]); /* Q15+14+1-16= Q14 */ err = sub(target_w[i], tmp); /* both in Q14 */ L_mse = L_mac0(L_mse, err, err); /* Q14+14 = Q28 */ -#endif /* Q14+14 = Q28 */ +#endif /* Q14+14 = Q28 */ } IF (L_sub(L_mse, L_mse_min) < 0) /* OPT: always update L_mse_min) */ @@ -873,7 +873,7 @@ Word16 snsQuantScfDecLR_fx(Word32* L_sns_vq_idx_fx, Xq_shape_j_fx = (Word16*)scratchAlign(L_Xq_shape_j_fx, sizeof(*L_Xq_shape_j_fx) * M); /*1*16*/ /*1*16*/ -#ifdef LRSNS_CBC_NO_LTPF_DEPENDENCY +#ifdef LRSNS_CBC_NO_LTPF_DEPENDENCY UNUSED(ltpf_rx_fx); #endif BER_dec = 0; /* no BER detected in PVQ indeces */ @@ -918,13 +918,13 @@ Word16 snsQuantScfDecLR_fx(Word32* L_sns_vq_idx_fx, /* add harmonic mean , based on pitch_info availability */ pitch_rx_fx = extract_l(L_sns_vq_idx_fx[3]); /* LTP active flag directly from dec_entropy */ -#ifdef LRSNS_CBC_NO_LTPF_DEPENDENCY +#ifdef LRSNS_CBC_NO_LTPF_DEPENDENCY ltpf_rx_fx = 0; /* CB_C has no dependency on LTPF active flag */ #else ltpf_rx_fx = extract_l(L_sns_vq_idx_fx[4]); /* LTPF active flag directly from dec_entropy */ #endif CBCmeanp_ind_fx = pitch_rx_fx; move16(); /* 0 or 1 */ -#ifndef LRSNS_CBC_NO_LTPF_DEPENDENCY +#ifndef LRSNS_CBC_NO_LTPF_DEPENDENCY test(); test(); test(); if (pitch_rx_fx != 0 && ltpf_rx_fx != 0) { @@ -1116,7 +1116,7 @@ Word32 snsQuantScfEncLRSt1ABC_fx(Word16* env, Word32* L_index, Word32 *L_min_mse st1_vectorB_idx_fx = scratchAlign(scratch, 0); target_fx = scratchAlign(scratch, sizeof(*st1_vectorB_idx_fx) * M); -#ifdef LRSNS_CBC_NO_LTPF_DEPENDENCY +#ifdef LRSNS_CBC_NO_LTPF_DEPENDENCY UNUSED(ltpf_rx); #endif st1_vectorA_fx = &(st1_vectors[0]); @@ -1203,7 +1203,7 @@ Word32 snsQuantScfEncLRSt1ABC_fx(Word16* env, Word32* L_index, Word32 *L_min_mse push_wmops("MSEsearchCbC_fx"); #endif meanC_ind = pitch_rx; move16(); -#ifndef LRSNS_CBC_NO_LTPF_DEPENDENCY +#ifndef LRSNS_CBC_NO_LTPF_DEPENDENCY if (ltpf_rx != 0) { meanC_ind = add(meanC_ind, 1); @@ -1359,7 +1359,7 @@ Word16 snsQuantScfEncLR_fx( /* o: bits spent on LRSNS-VQ envelope */ ); -#ifdef ENABLE_HR_MODE +#ifdef ENABLE_HR_MODE Word16 scf_q_fx[M]; /* W16Q11 always in use also for HR_MODE */ UNUSED(scf_q_fx); #endif -- GitLab From ccebcd94942d06058035df4ba0f901d2ded0e712 Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Wed, 29 Oct 2025 16:35:21 +0100 Subject: [PATCH 06/11] update BASOP_CI_BRANCH_PC_REPO to update-basop-ci-branch-lc3plus-v161 --- .gitlab-ci/variables.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.gitlab-ci/variables.yml b/.gitlab-ci/variables.yml index 817be6f79..d8db25d33 100644 --- a/.gitlab-ci/variables.yml +++ b/.gitlab-ci/variables.yml @@ -1,4 +1,5 @@ variables: + BASOP_CI_BRANCH_PC_REPO: "update-basop-ci-branch-lc3plus-v161" TESTV_DIR: "/usr/local/testv" LTV_DIR: "/usr/local/ltv" EVS_BE_TEST_DIR_BASOP: "/usr/local/be_2_evs_basop" @@ -81,8 +82,6 @@ variables: RUNNER_TAG: "ivas-basop-linux" LOGS_BACKUP_SOURCE_DIR: "" LOGS_BACKUP_TARGET_DIR: "" - # set this to true to skip the external HRTF testcases in pytest calls - DISABLE_HRTF: "false" MANUAL_PIPELINE_TYPE: description: "Type for the manual pipeline run. Use 'pytest-compare' to run comparison test against reference float codec." value: 'default' @@ -104,4 +103,3 @@ variables: - 'peaq-enc-passthrough' - 'long-term-logs' - 'backup-long-term-logs' - - 'test-long-self-test' -- GitLab From 574e8b0857314e21c418f652be1fb12113bc859d Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Thu, 30 Oct 2025 08:22:50 +0100 Subject: [PATCH 07/11] try to fix linker error --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 45cda9e37..e975df2b9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -184,7 +184,7 @@ target_include_directories(lib_util PRIVATE lib_lc3plus lib_isar) if(NOT WMOPS) add_executable(ivas_lc3plus_unit_test ${CMAKE_SOURCE_DIR}/scripts/split_rendering/lc3plus_basop/ivas_lc3plus_unit_test.c) - target_link_libraries(ivas_lc3plus_unit_test lib_rend lib_dec lib_util lib_basop lib_com lib_debug lib_isar) + target_link_libraries(ivas_lc3plus_unit_test lib_rend lib_dec lib_util lib_com lib_basop lib_debug lib_isar) endif() file(GLOB libISARSrcs "lib_isar/*.c") -- GitLab From 38c93851925f6faf0bac35f6c4ac602546beb3f5 Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Thu, 30 Oct 2025 08:51:21 +0100 Subject: [PATCH 08/11] fix LC3plus unit test - add missing case in switch --- lib_isar/isar_lc3plus_common.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib_isar/isar_lc3plus_common.c b/lib_isar/isar_lc3plus_common.c index 03f31cf8e..f7fe0db32 100644 --- a/lib_isar/isar_lc3plus_common.c +++ b/lib_isar/isar_lc3plus_common.c @@ -104,6 +104,8 @@ LC3PLUS_FrameDuration IVAS_LC3PLUS_UsToLC3plusFrameDuration( { switch ( lc3PlusFrameDurationUs ) { + case 2500: + return LC3PLUS_FRAME_DURATION_2p5MS; case 5000: return LC3PLUS_FRAME_DURATION_5MS; case 10000: -- GitLab From 600419c345ca4647d19a4c456f6dcc6f800475c4 Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Fri, 31 Oct 2025 12:10:15 +0100 Subject: [PATCH 09/11] [ci] revert override of BASOP_CI_BRANCH_PC_REPO --- .gitlab-ci/variables.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitlab-ci/variables.yml b/.gitlab-ci/variables.yml index d8db25d33..31d69a643 100644 --- a/.gitlab-ci/variables.yml +++ b/.gitlab-ci/variables.yml @@ -1,5 +1,4 @@ variables: - BASOP_CI_BRANCH_PC_REPO: "update-basop-ci-branch-lc3plus-v161" TESTV_DIR: "/usr/local/testv" LTV_DIR: "/usr/local/ltv" EVS_BE_TEST_DIR_BASOP: "/usr/local/be_2_evs_basop" -- GitLab From 625952bcef418e38b194975f8b416c5d8adb3f3b Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Fri, 31 Oct 2025 12:47:09 +0100 Subject: [PATCH 10/11] remove deleted files from MSVC solution --- Workspace_msvc/lib_lc3plus.vcxproj | 2 -- 1 file changed, 2 deletions(-) diff --git a/Workspace_msvc/lib_lc3plus.vcxproj b/Workspace_msvc/lib_lc3plus.vcxproj index 64a966e29..ad5139c35 100644 --- a/Workspace_msvc/lib_lc3plus.vcxproj +++ b/Workspace_msvc/lib_lc3plus.vcxproj @@ -188,8 +188,6 @@ - - -- GitLab From 7fa270c5e2c339b0ea94bd82e88474aefcbc252a Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Fri, 31 Oct 2025 12:47:30 +0100 Subject: [PATCH 11/11] [ci] revert changes in variables.yml --- .gitlab-ci/variables.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitlab-ci/variables.yml b/.gitlab-ci/variables.yml index 31d69a643..817be6f79 100644 --- a/.gitlab-ci/variables.yml +++ b/.gitlab-ci/variables.yml @@ -81,6 +81,8 @@ variables: RUNNER_TAG: "ivas-basop-linux" LOGS_BACKUP_SOURCE_DIR: "" LOGS_BACKUP_TARGET_DIR: "" + # set this to true to skip the external HRTF testcases in pytest calls + DISABLE_HRTF: "false" MANUAL_PIPELINE_TYPE: description: "Type for the manual pipeline run. Use 'pytest-compare' to run comparison test against reference float codec." value: 'default' @@ -102,3 +104,4 @@ variables: - 'peaq-enc-passthrough' - 'long-term-logs' - 'backup-long-term-logs' + - 'test-long-self-test' -- GitLab